Merge "msm: sps: Fix BAM ISR race with pipe disconnect"
diff --git a/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt b/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt
new file mode 100644
index 0000000..7a15f6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt
@@ -0,0 +1,22 @@
+* Qualcomm Application CPU clock device
+
+acpuclock-a7 selects the clock source used by the cpus and l2 cache. It
+can be configured to divide the clock source by any value in [1, 16] in
+half-integer increments.
+
+Required properties:
+- compatible: "qcom,acpuclk-a7"
+- reg: offset and length of the register sets for the acpuclock controller
+- reg-names: name of the bases for the above registers. "rcg_base"
+	     is expected.
+- a7_cpu-supply: regulator to supply a7 cpu
+- a7_mem-supply: regulator to supply a7 l2 cache
+
+Example:
+	qcom,acpuclk@f9011050 {
+		compatible = "qcom,acpuclk-a7";
+		reg = <0xf9011050 0x8>;
+		reg-names = "rcg_base";
+		a7_cpu-supply = <&pm8026_s2>;
+		a7_mem-supply = <&pm8026_l3>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index b359c49..6d22003 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -35,6 +35,13 @@
 	in mWatts.uSec
 - qcom,time-overhead: The time spent in entering and exiting this level in uS
 
+Optional properties
+- qcom,irqs-detectable: The field indicates whether the IRQs are detectable by
+			the GIC controller when entering a low power mode.
+- qcom,gpio-detectable: The field indicates whether the GPIOs can be detected
+			by the GPIO interrupt controller during a given low
+			power mode.
+
 Example:
 
 qcom,lpm-levels {
@@ -48,6 +55,8 @@
 		qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 		qcom,vdd-dig-upper-bound = <5>; /* MAX */
 		qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
+		qcom,irqs-detectable;
+		qcom,gpio-detectable;
 		qcom,latency-us = <100>;
 		qcom,ss-power = <650>;
 		qcom,energy-overhead = <801>;
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
index 5f534a2..4d441ba 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
@@ -1,9 +1,139 @@
-MSM Bus Scaling Driver
+MSM Bus Devices
 
-The bus scaling driver builds the topology of chipsets by adding
-bus devices (fabrics/NoCs) to the kernel tree. The device-tree
-data for bus devices contains the register addresses for QoS
-related registers on each NoC/Fabric.
+The bus devices (fabrics/NoCs) are the interconnects between various
+components on chipsets. These devices form the backbone of the chip
+topology. Entire topology of the chipset is built using the
+device-tree data of these bus devices.
+
+To add the bus devices following properties are required:
+
+compatible:		The bus devices need to be compatible with
+			msm-bus-fabric
+cell-id:		A 32 bit integer unique per bus per chipset. The IDs
+			for buses are in multiples of 1024.
+label:			Bus name
+qcom,fabclk-dual:	Dual set (active/sleep) bus clock name
+qcom,fabclk-active:	Active set bus clock name
+
+
+The following properties are optional as a bus might not support
+these features:
+
+qcom,ntieredslaves:	Number of tiered slaves on the bus.
+qcom,qos-freq:		QoS frequency (In Hz)
+qcom,hw-sel:		A string which decides whether QoS data
+			should be sent to RPM, set using BIMC or NoCs.
+			It can be set to "RPM", "NoC" or "BIMC".
+qcom,rpm-en:		A boolean flag indicating whether RPM transactions are
+			supported for nodes of the bus.
+qcom,ahb:		A boolean flag indicating whether the bus is ahb type.
+qcom,virt:		A boolean property indicating this is a virtual bus.
+reg:			Register space of the bus device. Not required in case
+			the bus is virtual.
+
+The following properties are optional as collecting data via coresight might
+not be supported for every bus. The documentation for coresight properties
+can be found in:
+Documentation/devicetree/bindings/coresight/coresight.txt
+
+coreisght-id		Unique integer identifier for the bus.
+coresight-name		Unique descriptive name of the bus.
+coresight-nr-inports	Number of input ports on the bus.
+coresight-outports	List of output port numbers on the bus.
+coresight-child-list	List of phandles pointing to the children of this
+			component.
+coresight-child-ports	List of input port numbers of the children.
+
+
+Any interconnect on the bus is represented as a child node.
+A child node can be of type: master, slave or a gateway.
+A gateway is an interconnect between buses and can be of both
+master and slave type.
+
+The following properties are available to characterize a child node.
+The properties can be chosen depending on the type of child node.
+
+cell-id:		For a master the ID is between 0 - 512
+			For a slave the ID is between 512 - 1024
+label:			Name of the master/slave/gateway
+qcom,masterp:		Hardware master port number(s)
+qcom,tier:		The tier to which a master/slave belongs.
+			Note that tiering might not be supported on
+			all architectures.
+qcom,hw-sel:		A string which decides whether QoS data should be sent
+			to RPM, set using BIMC or NoCs.
+			It can be set to "RPM", "NoC" or "BIMC".
+qcom,mode:		Used for masters on NoC/BIMC. Indicates which of the
+			four modes (Fixed/Limiter/Bypass/Regulator) the master
+			belongs to.
+qcom,perm-mode:		Permissible mode switches. Indicates which of the four
+			modes are supported of the master node. Generally,
+			modes are set at boot-up and not switched at run-time.
+qcom,qport:		QoS port number. This can be different from the
+			master-port number.
+qcom,ws:		Window size (in Hz), used for NoC/BIMC masters to
+			calculate saturation values.
+qcom,mas-hw-id:		A unique hardware ID agreed upon by processors across
+			the system. This ID is assigned to every master. It can
+			be used to send master specific data from
+			Apps/Modem/LPASS to RPM.
+qcom,slv-hw-id:		A unique hardware ID agreed upon by processors across
+			the system. This ID is assigned to every slave. It can
+			be used to send slave specific data from
+			Apps/Modem/LPASS to RPM.
+qcom,gateway:		Flag indicating whether a particular node is a gateway.
+qcom,slavep:		Hardware slave port number(s).
+qcom,buswidth:		Width of the interconnect between a node and the bus.
+			(In Bytes).
+qcom,prio-rd:		Read priority for a BIMC bus master (Can be 0/1/2)
+qcom,prio-wr:		Write priority for a BIMC bus master (Can be 0/1/2)
+
+
+Example:
+
+
+	msm-mmss-noc@fc478000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc478000 0x00004000>;
+		cell-id = <2048>;
+		label = "msm_mmss_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,qos-freq = <4800>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		mas-gfx3d {
+			cell-id = <26>;
+			label = "mas-gfx3d";
+			qcom,masterp = <2 3>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,ws = <10000>;
+			qcom,qport = <2 3>;
+			qcom,mas-hw-id = <6>;
+		};
+
+		mas-jpeg {
+			cell-id = <62>;
+			label = "mas-jpeg";
+			qcom,masterp = <4>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,qport = <0>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <7>;
+		};
+	};
+
+
+
+
 
 The bus scaling driver also provides the ability to configure
 bus performance parameters across the entire chip-set.
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_memory_hole.txt b/Documentation/devicetree/bindings/arm/msm/msm_memory_hole.txt
new file mode 100644
index 0000000..3cce02c
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_memory_hole.txt
@@ -0,0 +1,20 @@
+Memory Hole
+
+The msm_mem_hole module exists for the express purpose of removing
+memory via the msm memory-remove mechanism (see
+memory-reserve.txt). Compiling this module into a kernel is
+essentially the means by which any nodes in the device tree with
+compatible = "qcom,msm-mem-hole" will be "activated", thus providing a
+convenient mechanism for enabling/disabling memory removal
+(qcom,memory-*).
+
+
+Required properties
+
+- compatible: "qcom,msm-mem-hole"
+
+	qcom,msm-mem-hole {
+		compatible = "qcom,msm-mem-hole";
+		qcom,memblock-remove = <0x8100000 0x7e00000>; /* Address and Size of Hole */
+	};
+
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-log.txt b/Documentation/devicetree/bindings/arm/msm/rpm-log.txt
new file mode 100644
index 0000000..552955b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-log.txt
@@ -0,0 +1,43 @@
+* RPM Log
+
+RPM maintains Ulog in the RPM RAM. A device tree node is added
+that will hold the address of the RPM RAM region from where
+Ulog is read. The physical address from the RPM RAM region
+contains a header where various parameters to read the log are
+defined. These parameter's offsets in the header are also stored
+as a part of the device tree node.
+
+The required properties for rpm-log are:
+
+- compatible: "qcom,rpm-log"
+- reg: Specifies the base physical address and the size of the RPM
+	registers from where ulog is read.
+- qcom,rpm-addr-phys: RPM reads physical address of the RPM RAM region
+		differently when compared to Apps. Physical address of
+		the RPM RAM region is at an offset when seen from Apps.
+		This property specifies the offset which will get added
+		to the physical address of RPM RAM to make it
+		accessible to the Apps.
+- qcom,offset-version: Offset from the start of the phys_addr_base where version
+			information is stored.
+- qcom,offset-page-buffer-addr: Offset from the start of the phys_addr_base
+				where raw log start address is stored. Raw log
+				start address is the start of raw log in the
+				RPM address space as it should be seen from rpm.
+- qcom,offset-log-len: Offset from the start of the phy_addr_base where log
+			length is stored.
+- qcom,offset-log-len-mask: Offset from the start of the phy_addr_base where
+				log length mask is stored.
+- qcom,offset-page-indices: Offset from the start of the phy_addr_base where
+				index to the writer is stored.
+Example:
+qcom,rpm-log@fc19dc00 {
+	compatible = "qcom,rpm-log";
+	reg = <0xfc19dc00 0x2000>,
+	qcom,offset-rpm-addr = <0xfc000000>;
+	qcom,offset-version = <4>;
+	qcom,offset-page-buffer-addr = <36>;
+	qcom,offset-log-len = <40>;
+	qcom,offset-log-len-mask = <44>;
+	qcom,offset-page-indices = <56>;
+};
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
new file mode 100644
index 0000000..7d19c03
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -0,0 +1,29 @@
+Qualcomm mdss-dsi-ctrl
+
+mdss-dsi-ctrl is a dsi controller device which supports host controllers that
+are compatable with MIPI display serial interface specification.
+
+Required properties:
+- compatible:				Must be "qcom,mdss-dsi-ctrl"
+- cell-index:				Specifies the controller used among the two controllers.
+- reg:					offset and length of the register set for the device.
+- vdd-supply:				Phandle for vdd regulator device node.
+- vdd-io-supply:			Phandle for vdd-io regulator device node.
+- vreg-supply:				Phandle for vreg regulator device node.
+- qcom,mdss-fb-map:			pHandle that specifies the framebuffer to which the
+					interface is mapped.
+
+Optional properties:
+- label:		        	A string used to describe the controller used.
+
+Example:
+        mdss_dsi0: qcom,mdss_dsi@fd922800 {
+                compatible = "qcom,mdss-dsi-ctrl";
+                label = "MDSS DSI CTRL->0";
+                cell-index = <0>;
+                reg = <0xfd922800 0x600>;
+                vdd-supply = <&pm8941_l22>;
+                vdd_io-supply = <&pm8941_l12>;
+                vreg-supply = <&pm8941_l2>;
+		qcom,mdss-fb-map = <&mdss_fb0>;
+        };
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 26bddd9..94746b8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -1,6 +1,6 @@
 Qualcomm mdss-dsi-panel
 
-mdss-dsi-panel is a dsi panel driver which supports panels that
+mdss-dsi-panel is a dsi panel device which supports panels that
 are compatable with MIPI display serial interface specification.
 
 Required properties:
@@ -9,11 +9,17 @@
 					the panel driver. By default this property will be
 					set to "disable". Will be set to "ok/okay" status
 					for specific platforms.
+- qcom,dsi-ctrl-phandle:		Specifies the phandle for the DSI controller that
+					this panel will be mapped to.
 - qcom,mdss-pan-res:			A two dimensional array that specifies the panel
 					resolution.
 - qcom,mdss-pan-bpp:			Specifies the panel bits per pixel. Default value is 24(rgb888).
 					18 = for rgb666
 					16 = for rgb565
+- qcom,mdss-pan-dest:			A string that specifies the destination display for the panel.
+					Default is "display_1".
+					"display_1" = DISPLAY_1
+					"display_2" = DISPLAY_2
 - qcom,panel-phy-regulatorSettings:	An array of length 7 that specifies the PHY
 					regulator settings for the panel.
 - qcom,panel-phy-timingSettings:	An array of length 12 that specifies the PHY
@@ -45,15 +51,11 @@
 					--> size of payload
 					--> payload.
 
-Required structure:
-- A qcom,mdss-dsi-panel node must be a child of an mdss-dsi controller node that links to
-    one of the two DSI controllers.
-
-
 Optional properties:
 - label:		        	A string used as a descriptive name of the panel
 - qcom,enable-gpio:			Specifies the panel lcd/display enable gpio.
 - qcom,rst-gpio:			Specifies the panel reset gpio.
+- qcom,mdss-pan-broadcast-mode:		Boolean used to enable broadcast mode.
 - qcom,mdss-pan-porch-values:		An array of size 6 that specifies the panel blanking values.
 - qcom,mdss-pan-underflow-clr:		Specifies the controller settings for the panel underflow clear
 					settings. Default value is 0xff.
@@ -102,6 +104,15 @@
 					5 = DSI_RGB_SWAP_GBR
 - qcom,mdss-pan-dsi-data-lanes:		An array that specifies the data lanes enabled.
 					<1 1 0 0> = data lanes 1 and 2 are enabled.(default).
+- qcom,mdss-pan-dsi-dlane-swap:		Specifies the data lane swap configuration.
+					0 = <0 1 2 3> (default value)
+					1 = <3 0 1 2>
+					2 = <2 3 0 1>
+					3 = <1 2 3 0>
+					4 = <0 3 2 1>
+					5 = <1 0 3 2>
+					6 = <2 1 0 3>
+					7 = <3 2 1 0>
 - qcom,mdss-pan-dsi-t-clk:		An array that specifies the byte clock cycles
 					before and after each mode switch.
 - qcom,mdss-pan-dsi-stream:		Specifies the packet stream to be used.
@@ -120,38 +131,44 @@
 					6 = Software trigger and TE
 - qcom,mdss-pan-dsi-frame-rate:		Specifies the frame rate for the panel.
 					60 = 60 frames per second (default)
+- qcom,on-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,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".
 
 Note, if a given optional qcom,* binding is not present, then the driver will configure
 the default values specified.
 
 Example:
-	qcom,mdss_dsi@fd922800 {
-
-		qcom,mdss_dsi_sim_video {
-			compatible = "qcom,mdss-dsi-panel";
-			label = "simulator video mode dsi panel";
-			status = "disable";
-			qcom,mdss-pan-res = <640 480>;
-			qcom,mdss-pan-bpp = <24>;
-			qcom,mdss-pan-porch-values = <6 2 6 6 2 6>;
-			qcom,mdss-pan-underflow-clr = <0xff>;
-			qcom,mdss-pan-bl-levels = <1 15>;
-			qcom,mdss-pan-dsi-mode = <0>;
-			qcom,mdss-pan-dsi-h-pulse-mode = <1>;
-			qcom,mdss-pan-dsi-h-power-stop = <1 1 1>;
-			qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
-			qcom,mdss-pan-dsi-traffic-mode = <0>;
-			qcom,mdss-pan-dsi-dst-format = <3>;
-			qcom,mdss-pan-dsi-vc = <0>;
-			qcom,mdss-pan-dsi-rgb-swap = <0>;
-			qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
-			qcom,mdss-pan-dsi-t-clk = <0x24 0x03>;
-			qcom,mdss-pan-dsi-stream = <0>;
-			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-off-cmds = [22 01 00 00 00 00 00];
-		};
-
+/ {
+	qcom,mdss_dsi_sim_video {
+		compatible = "qcom,mdss-dsi-panel";
+		label = "simulator video mode dsi panel";
+		status = "disable";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,mdss-pan-res = <640 480>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <6 2 6 6 2 6>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-levels = <1 15>;
+		qcom,mdss-pan-dsi-mode = <0>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+		qcom,mdss-pan-dsi-h-power-stop = <1 1 1>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <0>;
+		qcom,mdss-pan-dsi-dst-format = <3>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+		qcom,mdss-pan-dsi-t-clk = <0x24 0x03>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		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,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/fb/mdss-edp.txt b/Documentation/devicetree/bindings/fb/mdss-edp.txt
index 3c4e1d3..578b07c 100644
--- a/Documentation/devicetree/bindings/fb/mdss-edp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-edp.txt
@@ -12,12 +12,14 @@
 - vdda-supply :				Phandle for vdd regulator device node.
 - gpio-panel-en	:			GPIO for supplying power to panel and backlight
 							driver.
-- qcom,panel-lpg-channel :	LPG channel for backlight.
-- qcom,panel-pwm-period :	PWM period in microseconds.
-- status :					A string that has to be set to "okay/ok" to enable
-							the driver. By default this property will be set to
-							"disable". Will be set to "ok/okay" status for
-							specific platforms.
+- qcom,panel-lpg-channel :		LPG channel for backlight.
+- qcom,panel-pwm-period :		PWM period in microseconds.
+- status :				A string that has to be set to "okay/ok" to enable
+						the driver. By default this property will be set to
+						"disable". Will be set to "ok/okay" status for
+						specific platforms.
+- qcom,mdss-fb-map:			pHandle that specifies the framebuffer to which the
+					interface is mapped.
 
 Example:
 	mdss_edp: qcom,mdss_edp@fd923400 {
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 478e335..0f31a38 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -10,6 +10,97 @@
 - reg-names :		names to refer to register sets related to this device
 - interrupts :		Interrupt associated with MDSS.
 - vdd-supply :		Phandle for vdd regulator device node.
+- qcom,mdss-pipe-vig-off:	Array of offset for MDP source surface pipes of
+				type VIG, the offsets are calculated from
+				register "mdp_phys" defined in reg property.
+				The number of offsets defined here should
+				reflect the amount of VIG pipes that can be
+				active in MDP for this configuration.
+- qcom,mdss-pipe-vig-fetch-id:	Array of shared memory pool fetch ids
+				corresponding to the VIG pipe offsets defined in
+				previous property, the amount of fetch ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-vig-off
+- qcom,mdss-pipe-rgb-off:	Array of offsets for MDP source surface pipes of
+				type RGB, the offsets are calculated from
+				register "mdp_phys" defined in reg property.
+				The number of offsets defined here should
+				reflect the amount of RGB pipes that can be
+				active in MDP for this configuration.
+- qcom,mdss-pipe-rgb-fetch-id:	Array of shared memory pool fetch ids
+				corresponding to the RGB pipe offsets defined in
+				previous property, the amount of fetch ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-rgb-off
+- qcom,mdss-pipe-dma-off:	Array of offsets for MDP source surface pipes of
+				type DMA, the offsets are calculated from
+				register "mdp_phys" defined in reg property.
+				The number of offsets defined here should
+				reflect the amount of DMA pipes that can be
+				active in MDP for this configuration.
+- qcom,mdss-pipe-dma-fetch-id:	Array of shared memory pool fetch ids
+				corresponding to the DMA pipe offsets defined in
+				previous property, the amount of fetch ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-dma-off
+- qcom,mdss-ctl-off:		Array of offset addresses for the available ctl
+				hw blocks within MDP, these offsets are
+				calculated from register "mdp_phys" defined in
+				reg property.  The number of ctl offsets defined
+				here should reflect the number of control paths
+				that can be configured concurrently on MDP for
+				this configuration.
+- qcom,mdss-wb-off:		Array of offset addresses for the progammable
+				writeback blocks within MDP. The number of
+				offsets defined should match the number of ctl
+				blocks defined in property: qcom,mdss-ctl-off
+- qcom,mdss-mixer-intf-off: 	Array of offset addresses for the available
+				mixer blocks that can drive data to panel
+				interfaces.
+				These offsets are be calculated from register
+				"mdp_phys" defined in reg property.
+				The number of offsets defined should reflect the
+				amount of mixers that can drive data to a panel
+				interface.
+- qcom,mdss-dspp-off: 		Array of offset addresses for the available dspp
+				blocks. These offsets are calculated from
+				regsiter "mdp_phys" defined in reg property.
+				The number of dspp blocks should match the
+				number of mixers driving data to interface
+				defined in property: qcom,mdss-mixer-intf-off
+- qcom,mdss-mixer-wb-off: 	Array of offset addresses for the available
+				mixer blocks that can be drive data to writeback
+				block.  These offsets will be calculated from
+				register "mdp_phys" defined in reg property.
+				The number of writeback mixer offsets defined
+				should reflect the number of mixers that can
+				drive data to a writeback block.
+- qcom,mdss-intf-off:		Array of offset addresses for the available MDP
+				video interface blocks that can drive data to a
+				panel controller through timing engine.
+				The offsets are calculated from "mdp_phys"
+				defined in reg property. The number of offsets
+				defiend should reflect the number of progammable
+				interface blocks avaialble in hardware.
+
+Optional properties:
+- qcom,vbif-settings :	Array with key-value pairs of constant VBIF register
+			settings used to setup MDSS QoS for optimum performance.
+			The key used should be offset from "vbif_phys" register
+			defined in reg property.
+- qcom,mdp-settings :	Array with key-value pairs of constant MDP register
+			settings used to setup MDSS QoS for best performance.
+			The key used should be offset from "mdp_phys" register
+			defined in reg property.
+
+Optional subnodes:
+Child nodes representing the frame buffer virtual devices.
+
+Subnode properties:
+- compatible :		Must be "qcom,mdss-fb"
+- cell-index :		Index representing frame buffer
+
+
 
 Example:
 	qcom,mdss_mdp@fd900000 {
@@ -19,5 +110,34 @@
 		reg-names = "mdp_phys", "vbif_phys";
 		interrupts = <0 72 0>;
 		vdd-supply = <&gdsc_mdss>;
+
+		qcom,vbif-settings = <0x0004 0x00000001>,
+				     <0x00D8 0x00000707>;
+		qcom,mdp-settings = <0x02E0 0x000000AA>,
+				    <0x02E4 0x00000055>;
+		qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
+					  0x00001A00>;
+		qcom,mdss-pipe-rgb-off = <0x00001E00 0x00002200
+					  0x00002600>;
+		qcom,mdss-pipe-dma-off = <0x00002A00 0x00002E00>;
+		qcom,mdss-pipe-vig-fetch-id = <1 4 7>;
+		qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
+		qcom,mdss-pipe-dma-fetch-id = <10 13>;
+
+		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
+				     0x00000900 0x0000A00>;
+		qcom,mdss-mixer-intf-off = <0x00003200 0x00003600
+					    0x00003A00>;
+		qcom,mdss-mixer-wb-off = <0x00003E00 0x00004200>;
+		qcom,mdss-dspp-off = <0x00004600 0x00004A00 0x00004E00>;
+		qcom,mdss-wb-off = <0x00011100 0x00013100 0x00015100
+				    0x00017100 0x00019100>;
+		qcom,mdss-intf-off = <0x00021100 0x00021300
+					   0x00021500 0x00021700>;
+
+		mdss_fb0: qcom,mdss_fb_primary {
+			cell-index = <0>;
+			compatible = "qcom,mdss-fb";
+		};
 	};
 
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index dde1a16..bcea355 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -22,8 +22,6 @@
  - atmel,fw-name	: firmware name to used for flashing firmware
 
 Optional property:
- - atmel,bl-addr		: bootloader address, by default is looked up
-					in mxt_slave_addresses structure
  - atmel,config			: configuration parameter for the controller
  - atmel,i2c-pull-up		: specify to indicate pull up is needed
  - vcc_i2c-supply		: Power source required to pull up i2c bus
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu.txt b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
deleted file mode 100644
index 2a631ed..0000000
--- a/Documentation/devicetree/bindings/iommu/msm_iommu.txt
+++ /dev/null
@@ -1,70 +0,0 @@
-* Qualcomm MSM IOMMU
-
-Required properties:
-- compatible : one of:
-	- "qcom,msm-smmu-v2"
-- reg : offset and length of the register set for the device. Optional
-	offset and length for clock register for additional clock that
-	needs to be turned on for access to this IOMMU.
-- reg-names: "iommu_base", "clk_base" (optional)
-- label: name of this IOMMU instance.
-
-Optional properties:
-- qcom,iommu-secure-id : Secure identifier for the IOMMU block
-- qcom,secure-context : boolean indicating that a context is secure and
-  programmed by the secure environment.
-- qcom,alt-vdd-supply : Alternative regulator needed to access IOMMU
-  configuration registers.
-- interrupts : should contain the performance monitor overflow interrupt number.
-
-- List of sub nodes, one for each of the translation context banks supported.
-  Each sub node has the following required properties:
-
-  - reg : offset and length of the register set for the context bank.
-  - interrupts : should contain the context bank interrupt.
-  - qcom,iommu-ctx-sids : List of stream identifiers associated with this
-    translation context.
-  - label : Name of the context bank
-  - vdd-supply : vdd-supply: phandle to GDSC regulator controlling this IOMMU.
-
-Optional properties:
-- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
-  access to the IOMMU configuration registers
-- qcom,iommu-bfb-regs : An array of unsigned 32-bit integers corresponding to
-  BFB register addresses that need to be configured for performance tuning
-  purposes. If this property is present, the qcom,iommu-bfb-data must also be
-  present. Register addresses are specified as an offset from the base of the
-  IOMMU hardware block. This property may be omitted if no BFB register
-  configuration needs to be done for a particular IOMMU hardware instance. The
-  registers specified by this property shall fall within the IOMMU
-  implementation-defined register region.
-- qcom,iommu-bfb-data : An array of unsigned 32-bit integers representing the
-  values to be programmed into the corresponding registers given by the
-  qcom,iommu-bfb-regs property. If this property is present, the
-  qcom,iommu-bfb-regs property shall also be present, and the lengths of both
-  properties shall be the same.
-
-Example:
-
-	qcom,iommu@fda64000 {
-		compatible = "qcom,msm-smmu-v2";
-		reg = <0xfda64000 0x10000>;
-		reg-names = "iommu_base";
-		vdd-supply = <&gdsc_iommu>;
-		qcom,iommu-bfb-regs = <0x204c 0x2050>;
-		qcom,iommu-bfb-data = <0xffff 0xffce>;
-		label = "iommu_0";
-
-		qcom,iommu-ctx@fda6c000 {
-			reg = <0xfda6c000 0x1000>;
-			interrupts = <0 70 0>;
-			qcom,iommu-ctx-sids = <0 2>;
-			label = "ctx_0";
-		};
-		qcom,iommu-ctx@fda6d000 {
-			reg = <0xfda6d000 0x1000>;
-			interrupts = <0 71 0>;
-			qcom,iommu-ctx-sids = <1>;
-			label = "ctx_1";
-		};
-	};
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
new file mode 100644
index 0000000..ea2d43a
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
@@ -0,0 +1,37 @@
+* Qualcomm MSM IOMMU v0
+
+Required properties:
+- compatible : one of:
+	- "qcom,msm-smmu-v0"
+- reg : offset and length of the register set for the device.
+- qcom,glb-offset : Offset for the global register base.
+
+Optional properties:
+- List of sub nodes, one for each of the translation context banks supported.
+  Each sub node has the following required properties:
+
+  - reg : offset and length of the register set for the context bank.
+  - interrupts : should contain the context bank interrupt.
+  - qcom,iommu-ctx-mids : List of machine identifiers associated with this
+    translation context.
+  - label : Name of the context bank
+
+Optional properties:
+  - none
+
+Example:
+
+	qcom,iommu@fd000000 {
+		compatible = "qcom,msm-smmu-v0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfd890000 0x10000>;
+		qcom,glb-offset = <0xF000>;
+
+		qcom,iommu-ctx@fd000000 {
+			reg = <0xfd000000 0x1000>;
+			interrupts = <0 250 0>;
+			qcom,iommu-ctx-mids = <0 3>;
+			label = "a_label";
+		};
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
index d8e7791..2c47f74 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
@@ -3,35 +3,77 @@
 Required properties:
 - compatible : one of:
 	- "qcom,msm-smmu-v1"
-- reg : offset and length of the register set for the device.
-- qcom,glb-offset : Offset for the global register base.
+- reg : offset and length of the register set for the device. Optional
+	offset and length for clock register for additional clock that
+	needs to be turned on for access to this IOMMU.
+- reg-names: "iommu_base", "clk_base" (optional)
+- label: name of this IOMMU instance.
 
 Optional properties:
+- qcom,iommu-secure-id : Secure identifier for the IOMMU block
+- qcom,secure-context : boolean indicating that a context is secure and
+  programmed by the secure environment.
+- qcom,alt-vdd-supply : Alternative regulator needed to access IOMMU
+  configuration registers.
+- interrupts : should contain the performance monitor overflow interrupt number.
+- qcom,iommu-enable-halt : Enable halt of the IOMMU before programming certain	19
+  registers
+- qcom,iommu-pmu-ngroups: Number of Performance Monitor Unit (PMU) groups.
+- qcom,iommu-pmu-ncounters: Number of PMU counters per group.
+- qcom,iommu-pmu-event-classes: List of event classes supported.
+
 - List of sub nodes, one for each of the translation context banks supported.
   Each sub node has the following required properties:
 
   - reg : offset and length of the register set for the context bank.
   - interrupts : should contain the context bank interrupt.
-  - qcom,iommu-ctx-mids : List of machine identifiers associated with this
+  - qcom,iommu-ctx-sids : List of stream identifiers associated with this
     translation context.
   - label : Name of the context bank
+  - vdd-supply : vdd-supply: phandle to GDSC regulator controlling this IOMMU.
 
 Optional properties:
-  - none
+- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
+  access to the IOMMU configuration registers
+- qcom,iommu-bfb-regs : An array of unsigned 32-bit integers corresponding to
+  BFB register addresses that need to be configured for performance tuning
+  purposes. If this property is present, the qcom,iommu-bfb-data must also be
+  present. Register addresses are specified as an offset from the base of the
+  IOMMU hardware block. This property may be omitted if no BFB register
+  configuration needs to be done for a particular IOMMU hardware instance. The
+  registers specified by this property shall fall within the IOMMU
+  implementation-defined register region.
+- qcom,iommu-bfb-data : An array of unsigned 32-bit integers representing the
+  values to be programmed into the corresponding registers given by the
+  qcom,iommu-bfb-regs property. If this property is present, the
+  qcom,iommu-bfb-regs property shall also be present, and the lengths of both
+  properties shall be the same.
 
 Example:
 
-	qcom,iommu@fd000000 {
+	qcom,iommu@fda64000 {
 		compatible = "qcom,msm-smmu-v1";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		reg = <0xfd890000 0x10000>;
-		qcom,glb-offset = <0xF000>;
+		reg = <0xfda64000 0x10000>;
+		reg-names = "iommu_base";
+		vdd-supply = <&gdsc_iommu>;
+		qcom,iommu-bfb-regs = <0x204c 0x2050>;
+		qcom,iommu-bfb-data = <0xffff 0xffce>;
+		label = "iommu_0";
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00,
+						0x01>;
 
-		qcom,iommu-ctx@fd000000 {
-			reg = <0xfd000000 0x1000>;
-			interrupts = <0 250 0>;
-			qcom,iommu-ctx-mids = <0 3>;
-			label = "a_label";
+		qcom,iommu-ctx@fda6c000 {
+			reg = <0xfda6c000 0x1000>;
+			interrupts = <0 70 0>;
+			qcom,iommu-ctx-sids = <0 2>;
+			label = "ctx_0";
 		};
+		qcom,iommu-ctx@fda6d000 {
+			reg = <0xfda6d000 0x1000>;
+			interrupts = <0 71 0>;
+			qcom,iommu-ctx-sids = <1>;
+			label = "ctx_1";
+		};
+	};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index cf33f50..6309068 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -125,6 +125,27 @@
 - qcom,sensor-position : should contain the mount angle of the camera sensor
     - 0 -> back camera
     - 1 -> front camera
+- qcom,cci-master : should contain i2c master id to be used for this camera
+    sensor
+    - 0 -> MASTER 0
+    - 1 -> MASTER 1
+- qcom,actuator-src : if auto focus is supported by this sensor, this
+   property should contain phandle of respective actuator node
+
+* Qualcomm MSM ACTUATOR
+
+Required properties:
+- cell-index : should contain unique identifier to differentiate
+    between multiple actuators
+- reg : should contain i2c slave address of the actuator and length of
+    data field which is 0x0
+- compatible :
+    - "qcom,actuator"
+- qcom,cci-master : should contain i2c master id to be used for this camera
+    sensor
+    - 0 -> MASTER 0
+    - 1 -> MASTER 1
+
 Example:
 
    qcom,cci@0xfda0c000 {
@@ -154,6 +175,14 @@
        qcom,hw-scl-stretch-en = <0>;
        qcom,hw-trdhld = <6>;
        qcom,hw-tsp = <1>;
+
+        actuator0: qcom,actuator@18 {
+                cell-index = <0>;
+                reg = <0x18 0x0>;
+                compatible = "qcom,actuator";
+                qcom,cci-master = <0>;
+        };
+
        qcom,s5k3l1yx@6e {
                compatible = "qcom,s5k3l1yx";
                reg = <0x6e 0x0>;
@@ -161,6 +190,7 @@
                qcom,led-flash-sd-index = <0>;
                qcom,csiphy-sd-index = <2>;
                qcom,csid-sd-index = <0>;
+               qcom,actuator-src = <&actuator0>;
                qcom,mount-angle = <90>;
                qcom,sensor-name = "s5k3l1yx";
                cam_vdig-supply = <&pm8941_l3>;
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 6af445b..cd14056 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -3,21 +3,34 @@
 Required properties:
 - compatible : one of:
 	- "qcom,msm-vidc"
-- hfi : supported Host-Firmware Interface, one of:
-        - "venus"
-        - "q6"
+- qcom,hfi : supported Host-Firmware Interface, one of:
+	- "venus"
+	- "q6"
 
 Optional properties:
 - reg : offset and length of the register set for the device.
 - interrupts : should contain the vidc interrupt.
-- vidc-cp-map : start and size of device virtual address range for secure buffers.
-  Video hardware uses this address range to identify if the buffers are secure
-  or non-secure.
-- vidc-ns-map : start and size of device virtual address range for non-secure buffers.
-  Video hardware uses this address range to identify if the buffers are secure
-  or non-secure.
-- load-freq-tbl : load (in macroblocks/sec) and corresponding vcodec clock
-  required for optimal performance in descending order.
+- qcom,vidc-cp-map : start and size of device virtual address range for
+  secure buffers. Video hardware uses this address range to identify if
+  the buffers are secure or non-secure.
+- qcom,vidc-ns-map : start and size of device virtual address range for
+  non-secure buffers. Video hardware uses this address range to identify
+  if the buffers are secure or non-secure.
+- qcom,load-freq-tbl : load (in macroblocks/sec) and corresponding vcodec
+  clock required for optimal performance in descending order.
+- qcom,reg-presets : list of offset-value pairs for registers to be written.
+  The offsets are from the base offset specified in 'reg'. This is mainly
+  used for QoS, vbif, etc. presets for video.
+- qcom,bus-ports : number of bus ports supported by venus to access
+  ddr/ocmem.
+- qcom,enc-ocmem-ab-ib : list of bus vectors (ab, ib pair) for ocmem
+  bandwidth request by different video encoder usecases.
+- qcom,dec-ocmem-ab-ib : list of bus vectors(ab, ib pair) for ocmem
+  bandwidth request by different video decoder usecases.
+- qcom,enc-ddr-ab-ib : list of bus vectors(ab,ib pair) for ddr bandwidth
+  request by different video encoder usecases.
+- qcom,dec-ddr-ab-ib : list of bus vectors(ab, ib pair) for ddr bandwidth
+  request by different video decoder usecases.
 
 Example:
 
@@ -26,13 +39,24 @@
 		compatible = "qcom,msm-vidc";
 		reg = <0xfdc00000 0xff000>;
 		interrupts = <0 44 0>;
-		vidc-cp-map = <0x1000000 0x40000000>;
-		vidc-ns-map = <0x40000000 0x40000000>;
-		load-freq-tbl = <979200 410000000>,
+		qcom,vidc-cp-map = <0x1000000 0x40000000>;
+		qcom,vidc-ns-map = <0x40000000 0x40000000>;
+		qcom,load-freq-tbl = <979200 410000000>,
 				<560145 266670000>,
 				<421161 200000000>,
 				<243000 133330000>,
 				<108000 100000000>,
 				<36000 50000000>;
-		hfi = "venus";
+		qcom,hfi = "venus";
+		qcom,reg-presets = <0x80004 0x1>,
+			<0x80178 0x00001FFF>;
+		qcom,bus-ports = <1>;
+		qcom,enc-ocmem-ab-ib = <0 0>,
+			<138200 1222000>;
+		qcom,dec-ocmem-ab-ib = <0 0>,
+			<176900 1556640>;
+		qcom,enc-ddr-ab-ib = <0 0>,
+			<60000 664950>;
+		qcom,dec-ddr-ab-ib = <0 0>,
+			<110000 909000>;
 	};
diff --git a/Documentation/devicetree/bindings/ocmem/msm-ocmem.txt b/Documentation/devicetree/bindings/ocmem/msm-ocmem.txt
index e212aca..0a0ed75 100644
--- a/Documentation/devicetree/bindings/ocmem/msm-ocmem.txt
+++ b/Documentation/devicetree/bindings/ocmem/msm-ocmem.txt
@@ -18,6 +18,7 @@
 		    "ocmem_irq" corresponds to OCMEM Error Interrupt.
 		    "dm_irq" corresponds to DM Interrupt.
 - qcom,ocmem-num-regions: The number of OCMEM hardware memory regions.
+- qcom,ocmem-num-macros: The number of OCMEM hardware memory macros.
 - qcom,resource-type: The hardware resource type of the OCMEM core.
 
 In addition to the information on the OCMEM core, the
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
index ac9600d..2764657 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -12,8 +12,13 @@
 - reg-names:	      Names of the bases for the above registers. "qdsp6_base"
 		      and "halt_base" are expected.
 - interrupts:         The lpass watchdog interrupt
+- vdd_cx-supply:      Reference to the regulator that supplies the vdd_cx domain.
 - qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
 
+Optional properties:
+- vdd_pll-supply:     Reference to the regulator that supplies the PLL's rail.
+- qcom,vdd_pll:       Voltage to be set for the PLL's rail.
+
 Example:
 	qcom,lpass@fe200000 {
 	        compatible = "qcom,pil-q6v5-lpass";
@@ -21,6 +26,6 @@
 	              <0xfd485100 0x00010>;
 		reg-names = "qdsp6_base", "halt_base";
 		interrupts = <0 194 1>;
-
+		vdd_cx-supply = <&pm8841_s2>;
 	        qcom,firmware-name = "lpass";
 	};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 22e43ab..b1f6717 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -14,6 +14,7 @@
 		      "metadata_base" are expected.
 - interrupts:         The modem watchdog interrupt
 - vdd_mss-supply:     Reference to the regulator that supplies the processor.
+- vdd_cx-supply:      Reference to the regulator that supplies the vdd_cx domain.
 - vdd_mx-supply:      Reference to the regulator that supplies the memory rail.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
 - qcom,pil-self-auth: <0> if the hardware does not require self-authenticating
@@ -23,6 +24,10 @@
 - qcom,gpio-err-fatal: GPIO used by the modem to indicate error fatal to the apps.
 - qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
 
+Optional properties:
+- vdd_pll-supply:     Reference to the regulator that supplies the PLL's rail.
+- qcom,vdd_pll:       Voltage to be set for the PLL's rail.
+
 Example:
 	qcom,mss@fc880000 {
 		compatible = "qcom,pil-q6v5-mss";
@@ -35,6 +40,7 @@
 			    "restart_reg", metadata_base";
 		interrupts = <0 24 1>;
 		vdd_mss-supply = <&pm8841_s3>;
+		vdd_cx-supply = <&pm8841_s2>;
 		vdd_mx-supply = <&pm8841_s1>;
 
 		qcom,is-loadable;
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index d91086f..708ada1 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -15,51 +15,61 @@
 
 Parent node required properties:
 - compatible : should be "qcom,qpnp-bms" for the BM driver.
-- qcom,bms-r-sense-mohm : sensor resistance in in milli-ohms.
-- qcom,bms-v-cutoff-uv : cutoff voltage where the battery is considered dead in
+- qcom,r-sense-uohm : sensor resistance in in micro-ohms.
+- qcom,v-cutoff-uv : cutoff voltage where the battery is considered dead in
 			micro-volts.
-- qcom,bms-max-voltage-uv : maximum voltage for the battery in micro-volts.
-- qcom,bms-r-conn-mohm : connector resistance in milli-ohms.
-- qcom,bms-shutdown-soc-valid-limit : If the ocv upon restart is within this
+- qcom,max-voltage-uv : maximum voltage for the battery in micro-volts.
+- qcom,r-conn-mohm : connector resistance in milli-ohms.
+- qcom,shutdown-soc-valid-limit : If the ocv upon restart is within this
 			distance of the shutdown ocv, the BMS will try to force
 			the new SoC to the old one to provide charge continuity.
 			That is to say,
 				if (abs(shutdown-soc - current-soc) < limit)
 				then use old SoC.
-- qcom,bms-adjust-soc-low-threshold : The low threshold for the "flat portion"
+- qcom,adjust-soc-low-threshold : The low threshold for the "flat portion"
 			of the charging curve. The BMS will not adjust SoC
 			based on voltage during this time.
-- qcom,bms-adjust-soc-high-threshold : The high threshold for the "flat
+- qcom,adjust-soc-high-threshold : The high threshold for the "flat
 			portion" of the charging curve. The BMS will not
 			adjust SoC based on voltage during this time.
-- qcom,bms-low-soc-calculate-soc-threshold : The SoC threshold for when
+- qcom,ocv-voltage-low-threshold-uv : The low voltage threshold for the
+			"flat portion" of the discharge curve. The bms will not
+			accept new ocvs between these thresholds.
+- qcom,ocv-voltage-high-threshold-uv : The high voltage threshold for
+			the "flat portion" of the discharge curve.
+			The bms will not accept new ocvs between these
+			thresholds.
+- qcom,low-soc-calculate-soc-threshold : The SoC threshold for when
 			the period calculate_soc work speeds up. This ensures
 			SoC is updated in userspace constantly when we are near
 			shutdown.
-- qcom,bms-low-soc-calculate-soc-ms : The time period between subsequent
+- qcom,low-soc-calculate-soc-ms : The time period between subsequent
+
 			SoC recalculations when the current SoC is below
-			qcom,bms-low-soc-calculate-soc-threshold.
-- qcom,bms-soc-calculate-soc-ms : The time period between subsequent SoC
+			qcom,low-soc-calculate-soc-threshold.
+- qcom,soc-calculate-soc-ms : The time period between subsequent SoC
 			recalculations when the current SoC is above or equal
-			qcom,bms-low-soc-calculate-soc-threshold.
-- qcom,bms-chg-term-ua : current in micro-amps when charging is considered done.
+			qcom,low-soc-calculate-soc-threshold.
+- qcom,chg-term-ua : current in micro-amps when charging is considered done.
 			As soon as current passes this point, charging is
 			stopped.
-- qcom,bms-batt-type: Type of battery used. This is an integer that corresponds
+- qcom,batt-type: Type of battery used. This is an integer that corresponds
 			to the enum defined in
 			include/linux/mfd/pm8xxx/batterydata-lib.h
 
 Parent node optional properties:
-- qcom,bms-ignore-shutdown-soc: A boolean that controls whether BMS will
+- qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
 			try to force the startup SoC to be the same as the
 			shutdown SoC. Defining it will make BMS ignore the
 			shutdown SoC.
-- qcom,bms-use-voltage-soc : A boolean that controls whether BMS will use
+- qcom,use-voltage-soc : A boolean that controls whether BMS will use
 			voltage-based SoC instead of a coulomb counter based
 			one. Voltage-based SoC will not guarantee linearity.
-- qcom,bms-use-external-rsense : A boolean that controls whether BMS will use
+- qcom,use-external-rsense : A boolean that controls whether BMS will use
 			an external sensor resistor instead of the default
 			RDS of the batfet.
+- qcom,use-ocv-thresholds : A boolean that controls whether BMS will take
+			new OCVs only between the defined thresholds.
 
 All sub node required properties:
 - reg : offset and length of the PMIC peripheral register map.
@@ -87,18 +97,20 @@
 	#size-cells = <1>;
 	status = "disabled";
 
-	qcom,bms-r-sense-mohm = <2>;
-	qcom,bms-v-cutoff-uv = <3400000>;
-	qcom,bms-max-voltage-uv = <4200000>;
-	qcom,bms-r-conn-mohm = <18>;
-	qcom,bms-shutdown-soc-valid-limit = <20>;
-	qcom,bms-adjust-soc-low-threshold = <25>;
-	qcom,bms-adjust-soc-high-threshold = <45>;
-	qcom,bms-low-soc-calculate-soc-threshold = <15>;
-	qcom,bms-low-soc-calculate-soc-ms = <5000>;
-	qcom,bms-calculate-soc-ms = <20000>;
-	qcom,bms-chg-term-ua = <100000>;
-	qcom,bms-batt-type = <0>;
+	qcom,r-sense-uohm = <10000>;
+	qcom,v-cutoff-uv = <3400000>;
+	qcom,max-voltage-uv = <4200000>;
+	qcom,r-conn-mohm = <18>;
+	qcom,shutdown-soc-valid-limit = <20>;
+	qcom,ocv-voltage-low-threshold-uv = <3650000>;
+	qcom,ocv-voltage-high-threshold-uv = <3750000>;
+	qcom,adjust-soc-low-threshold = <25>;
+	qcom,adjust-soc-high-threshold = <45>;
+	qcom,low-soc-calculate-soc-threshold = <15>;
+	qcom,low-soc-calculate-soc-ms = <5000>;
+	qcom,calculate-soc-ms = <20000>;
+	qcom,chg-term-ua = <100000>;
+	qcom,batt-type = <0>;
 
 	qcom,bms-iadc@3800 {
 		reg = <0x3800 0x100>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 59a9fd9..03b01ee 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -23,13 +23,15 @@
 			settings, comparator override features etc.
 
 Parent node required properties:
-- qcom,chg-vddmax-mv:	Target voltage of battery in mV
-- qcom,chg-vddsafe-mv:	Maximum Vdd voltage in mV
-- qcom,chg-vinmin-mv:	Minimum input voltage in mV
-- qcom,chg-vbatdet-mv:	Battery voltage at which charging resumes
-- qcom,chg-ibatmax-ma:	Maximum battery charge current in mA
-- qcom,chg-ibatterm-ma:	Current at which charging is terminated in mA.
-- qcom,chg-ibatsafe-ma:	Safety battery current setting
+- qcom,chg-vddmax-mv:			Target voltage of battery in mV.
+- qcom,chg-vddsafe-mv:			Maximum Vdd voltage in mV.
+- qcom,chg-vinmin-mv:			Minimum input voltage in mV.
+- qcom,chg-vbatdet-mv:			Battery charging resume voltage in mV.
+- qcom,chg-ibatmax-ma:			Maximum battery charge current in mA
+- qcom,chg-ibatterm-ma:			Current at which charging is terminated.
+- qcom,chg-ibatsafe-ma:			Safety battery current setting
+- qcom,chg-thermal-mitigation:		Array of ibatmax values for different
+					system thermal mitigation level.
 
 Parent node optional properties:
 - qcom,chg-charging-disabled:		Set this property to disable charging
@@ -128,8 +130,11 @@
 		qcom,chg-vddmax-mv = <4200>;
 		qcom,chg-vddsafe-mv = <4200>;
 		qcom,chg-vinmin-mv = <4200>;
-		qcom,chg-ibatmax-mv = <1500>;
-		qcom,chg-ibatterm-mv = <200>;
+		qcom,chg-vbatdet-mv = <4200>;
+		qcom,chg-ibatmax-ma = <1500>;
+		qcom,chg-ibatterm-ma = <200>;
+		qcom,chg-ibatsafe-ma = <1500>;
+		qcom,chg-thermal-mitigation = <1500 700 600 325>;
 
 		qcom,chg-chgr@1000 {
 			reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/regulator/krait-regulator.txt b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
index 149445d..f057834 100644
--- a/Documentation/devicetree/bindings/regulator/krait-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
@@ -21,6 +21,7 @@
 - qcom,ldo-delta-voltage:	The delta used to reduce the requested voltage in order
 				to derive the LDO output voltage while switching
 				to LDO mode. Acceptable values are from 1000uV to 100000uV
+- qcom,cpu-num:			Indicates what cpu this regulator controls
 
 Any property defined as part of the core regulator
 binding, defined in regulator.txt, can also be used.
@@ -39,5 +40,6 @@
 		qcom,ldo-default-voltage = <745000>;
 		qcom,ldo-threshold-voltage = <750000>;
 		qcom,ldo-delta-voltage = <50000>;
+		qcom,cpu-num = 0;
 	};
 
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 975d51c..232ddec 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -105,8 +105,8 @@
                             RT Proxy port ID values from 224 to 225 and 240 to
 			    241
                             FM Rx and TX port ID values from 12292 to 12293
-                            incall record Rx and TX port ID values from 32771 to
-			    32772
+                            incall record Rx and TX port ID values from 32771 to 32772
+                            inCall Music Delivery port ID is 32773
 
 * msm-auxpcm
 
@@ -343,6 +343,11 @@
 			compatible = "qcom,msm-dai-q6-dev";
 			qcom,msm-dai-q6-dev-id = <32772>;
 		};
+
+		qcom,msm-dai-q6-incall-music-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32773>;
+		};
 	};
 
         qcom,msm-auxpcm {
diff --git a/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt b/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
index 63c1e87..dc0e00b 100644
--- a/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
+++ b/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
@@ -3,43 +3,30 @@
 Required properties:
 - cell-index : the bus identifier.
 - compatible : should be "qcom,spmi-pmic-arb".
+- reg-names  : should be "core", "intr", "cnfg"
 - reg : offset and length of the PMIC Arbiter Core register map.
 - reg : offset and length of the PMIC Arbiter Interrupt controller register map.
+- reg : offset and length of the PMIC Arbiter Configuration register map.
 - interrupts : the PMIC Arbiter interrupt.
 - qcom,pmic-arb-ee : the execution environment (EE) identifier.
 - qcom,pmic-arb-channel : the assigned channel number for channel registers.
-- qcom,pmic-arb-ppid-map : an array used to map a 12-bit PPID to 8-bit APID.
 
 Optional properties:
 - qcom,not-wakeup : boolean property which indicates that SPMI PMIC interrupts
 	should not be treated as wakeup sources
 
-Peripherals on the SPMI bus are identified with a 12-bit identifier (PPID)
-which is composed of a 4-bit slave address and an 8-bit peripheral identifier.
-The PMIC Arbiter hardware uses an 8-bit APID (Arbiter Peripheral Identifier)
-internally.  Software needs the mapping between the APID and the PPID.
-Up to a maximum of 256 peripherals are supported and the mapping is target
-specific.
-
-Data format of pmic-arb-ppid-map:
-<0x13100001>
-value is 32 bit.
-MSB 12 bits are the PPID
-12 bits padding
-LSB 8 bit are the APID
-
 Example:
 
 	qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
 		reg = <0xfc4cf000 0x1000>,
-		      <0Xfc4cb000 0x1000>;
+		      <0Xfc4cb000 0x1000>,
+		      <0Xfc4ca000 0x1000>;
 		interrupts = <0>;
 		qcom,pmic-arb-ee = <0>;
 		qcom,pmic-arb-channel = <0>;
-		qcom,pmic-arb-ppid-map = <0x13000000>, /* PPID 0x130, APID 0 */
-					 <0x13100001>, /* PPID 0x131, APID 1 */
 	};
 
 
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
index 82faa7e..5861eea 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
@@ -44,6 +44,12 @@
 need to configured.
 qcom,use-pm : If present, this property will cause the device to prevent system
 suspend as long as the port remains open.
+- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for below properties:
+    - qcom,msm_bus,name
+    - qcom,msm_bus,num_cases
+    - qcom,msm_bus,active_only
+    - qcom,msm_bus,num_paths
+    - qcom,msm_bus,vectors
 
 Aliases:
 An alias may optionally be used to bind the serial device to a tty device
@@ -68,4 +74,12 @@
 		qcom,cts-gpio = <&msmgpio 43 0x00>;
 		qcom,rfr-gpio = <&msmgpio 44 0x00>;
 		qcom,use-pm;
+
+		qcom,msm-bus,name = "serial_uart0";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<84 512 0 0>,
+				<84 512 500 800>;
 	};
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
index e00584f..c597536 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
@@ -54,7 +54,13 @@
 receiving interrupt with UART RX GPIO IRQ line (i.e. above wakeup_irq property),
 HSUART driver injects provided character with property rx_to_inject.
 - qcom, rx_to_inject : The character to be inserted on wakeup.
-
+- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
+below optional properties:
+    - qcom,msm_bus,name
+    - qcom,msm_bus,num_cases
+    - qcom,msm_bus,active_only
+    - qcom,msm_bus,num_paths
+    - qcom,msm_bus,vectors
 
 Aliases :
 An alias may be optionally used to bind the UART device to a TTY device
@@ -84,4 +90,12 @@
 
 		qcom,bam-tx-ep-pipe-index = <0>;
 		qcom,bam-rx-ep-pipe-index = <1>;
+
+		qcom,msm-bus,name = "uart7";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<84 512 0 0>,
+				<84 512 500 800>;
 	};
diff --git a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
new file mode 100644
index 0000000..7bd95e7
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
@@ -0,0 +1,60 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	qcom,mdss_dsi_orise_720p_video {
+		compatible = "qcom,mdss-dsi-panel";
+		label = "orise 720p video mode dsi panel";
+		status = "disable";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi1>;
+		qcom,mdss-pan-res = <720 1280>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_2";
+		qcom,mdss-pan-porch-values = <32 12 144 3 4 9>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-levels = <1 255>;
+		qcom,mdss-pan-dsi-mode = <0>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <1>;
+		qcom,mdss-pan-dsi-dst-format = <3>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>;
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings = [03 01 01 00  /* Regualotor settings */
+						    20 00 01];
+		qcom,panel-phy-timingSettings = [69 29 1f 00 55 55
+						    19 2a 2a 03 04 00];
+		qcom,panel-phy-strengthCtrl = [77 06];
+		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
+					   00 00];
+		qcom,panel-phy-laneConfig = [00 c2 45 00 00 00 00 01 75 /* lane0 config */
+					     00 c2 45 00 00 00 00 01 75 /* lane1 config */
+					     00 c2 45 00 00 00 00 01 75 /* lane2 config */
+					     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,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,off-cmds-dsi-state = "DSI_LP_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
index a484372..98074c8 100644
--- a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,14 +10,16 @@
  * GNU General Public License for more details.
  */
 
-&mdss_dsi {
+/ {
 
 	qcom,mdss_dsi_sim_video {
 		compatible = "qcom,mdss-dsi-panel";
 		label = "simulator video mode dsi panel";
 		status = "disable";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
 		qcom,mdss-pan-res = <640 480>;
 		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
 		qcom,mdss-pan-porch-values = <6 2 6 6 2 6>;
 		qcom,mdss-pan-underflow-clr = <0xff>;
 		qcom,mdss-pan-bl-levels = <1 15>;
@@ -30,12 +32,15 @@
 		qcom,mdss-pan-dsi-vc = <0>;
 		qcom,mdss-pan-dsi-rgb-swap = <0>;
 		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
 		qcom,mdss-pan-dsi-t-clk = <0x24 0x03>;
 		qcom,mdss-pan-dsi-stream = <0>;
 		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,on-cmds-dsi-state = "DSI_LP_MODE";
 		qcom,panel-off-cmds = [22 01 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 9e1d909..6ebab2b 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,16 +10,18 @@
  * GNU General Public License for more details.
  */
 
-&mdss_dsi {
+/ {
 
 	qcom,mdss_dsi_toshiba_720p_video {
 		compatible = "qcom,mdss-dsi-panel";
 		label = "toshiba 720p video mode dsi panel";
 		status = "disable";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
 		qcom,enable-gpio = <&msmgpio 58 0>;
 		qcom,rst-gpio = <&pm8941_gpios 19 0>;
 		qcom,mdss-pan-res = <720 1280>;
 		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
 		qcom,mdss-pan-porch-values = <32 12 144 3 4 9>;
 		qcom,mdss-pan-underflow-clr = <0xff>;
 		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
@@ -33,6 +35,7 @@
 		qcom,mdss-pan-dsi-vc = <0>;
 		qcom,mdss-pan-dsi-rgb-swap = <0>;
 		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>;
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
 		qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
 		qcom,mdss-pan-dsi-stream = <0>;
 		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
@@ -113,7 +116,9 @@
 					23 01 00 00 0a 02 e2 00
 					05 01 00 00 78 02 11 00
 					05 01 00 00 32 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,off-cmds-dsi-state = "DSI_HS_MODE";
 	};
 };
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
index 6a88992..c6693e1 100644
--- a/arch/arm/boot/dts/mpq8092-iommu.dtsi
+++ b/arch/arm/boot/dts/mpq8092-iommu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/include/ "msm-iommu.dtsi"
+/include/ "msm-iommu-v1.dtsi"
 
 &jpeg_iommu {
 	status = "ok";
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 339faa9..75f168d 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -63,174 +63,16 @@
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
 		reg = <0xfc4cf000 0x1000>,
-		      <0Xfc4cb000 0x1000>;
+		      <0Xfc4cb000 0x1000>,
+		      <0Xfc4ca000 0x1000>;
 		/* 190,ee0_krait_hlos_spmi_periph_irq */
 		/* 187,channel_0_krait_hlos_trans_done_irq */
 		interrupts = <0 190 0 0 187 0>;
 		qcom,not-wakeup;
 		qcom,pmic-arb-ee = <0>;
 		qcom,pmic-arb-channel = <0>;
-		qcom,pmic-arb-ppid-map = <0x00100000>, /* PM8644_0 */
-				 <0x10100001>, /* PM8644_1 */
-				 <0x00500002>, /* INTERRUPT */
-				 <0x00800003>, /* PON0 */
-				 <0x03000004>, /* ADC_1 */
-				 <0x03100005>, /* ADC_2 */
-				 <0x03200006>, /* ADC_3 */
-				 <0x03300007>, /* ADC_4 */
-				 <0x03400008>, /* ADC_5 */
-				 <0x03500009>, /* ADC_6 */
-				 <0x0360000a>, /* ADC_7 */
-				 <0x0370000b>, /* ADC_8 */
-				 <0x0500000c>, /* SHARED_XO */
-				 <0x0510000d>, /* BB_CLK1 */
-				 <0x0520000e>, /* BB_CLK2 */
-				 <0x05a0000f>, /* SLEEP_CLK */
-				 <0x06000010>, /* RTC_RW */
-				 <0x06100011>, /* RTC_ALARM */
-				 <0x07000012>, /* PBS_CORE */
-				 <0x07100013>, /* PBS_CLIENT_1 */
-				 <0x07200014>, /* PBS_CLIENT_2 */
-				 <0x07300015>, /* PBS_CLIENT_3 */
-				 <0x07400016>, /* PBS_CLIENT_4 */
-				 <0x07500017>, /* PBS_CLIENT_5 */
-				 <0x07600018>, /* PBS_CLIENT_6 */
-				 <0x07700019>, /* PBS_CLIENT_7 */
-				 <0x0780001a>, /* PBS_CLIENT_8 */
-				 <0x0790001b>, /* PBS_CLIENT_9 */
-				 <0x07a0001c>, /* PBS_CLIENT_10 */
-				 <0x07b0001d>, /* PBS_CLIENT_11 */
-				 <0x07c0001e>, /* PBS_CLIENT_12 */
-				 <0x07d0001f>, /* PBS_CLIENT_13 */
-				 <0x07e00020>, /* PBS_CLIENT_14 */
-				 <0x07f00021>, /* PBS_CLIENT_15 */
-				 <0x08000022>, /* PBS_CLIENT_16 */
-				 <0x0a000023>, /* MPP_1 */
-				 <0x0a100024>, /* MPP_2 */
-				 <0x0a200025>, /* MPP_3 */
-				 <0x0a300026>, /* MPP_4 */
-				 <0x0a400027>, /* MPP_5 */
-				 <0x0a500028>, /* MPP_6 */
-				 <0x0c000029>, /* PM8644_GPIO_1 */
-				 <0x0c10002a>, /* PM8644_GPIO_2 */
-				 <0x0c20002b>, /* PM8644_GPIO_3 */
-				 <0x0c30002c>, /* PM8644_GPIO_4 */
-				 <0x0c40002d>, /* PM8644_GPIO_5 */
-				 <0x0c50002e>, /* PM8644_GPIO_6 */
-				 <0x0c60002f>, /* PM8644_GPIO_7 */
-				 <0x0c700030>, /* PM8644_GPIO_8 */
-				 <0x0c800031>, /* PM8644_GPIO_9 */
-				 <0x0c900032>, /* PM8644_GPIO_10 */
-				 <0x0ca00033>, /* PM8644_GPIO_11 */
-				 <0x0cb00034>, /* PM8644_GPIO_12 */
-				 <0x0cc00035>, /* PM8644_GPIO_13 */
-				 <0x0cd00036>, /* PM8644_GPIO_14 */
-				 <0x0ce00037>, /* PM8644_GPIO_15 */
-				 <0x0cf00038>, /* PM8644_GPIO_16 */
-				 <0x0d000039>, /* PM8644_GPIO_17 */
-				 <0x0d10003a>, /* PM8644_GPIO_18 */
-				 <0x0d20003b>, /* PM8644_GPIO_19 */
-				 <0x0d30003c>, /* PM8644_GPIO_20 */
-				 <0x0d40003d>, /* PM8644_GPIO_21 */
-				 <0x0d50003e>, /* PM8644_GPIO_22 */
-				 <0x0d60003f>, /* PM8644_GPIO_23 */
-				 <0x0d700040>, /* PM8644_GPIO_24 */
-				 <0x0d800041>, /* PM8644_GPIO_25 */
-				 <0x0d900042>, /* PM8644_GPIO_26 */
-				 <0x0da00043>, /* PM8644_GPIO_27 */
-				 <0x0db00044>, /* PM8644_GPIO_28 */
-				 <0x0dc00045>, /* PM8644_GPIO_29 */
-				 <0x0dd00046>, /* PM8644_GPIO_30 */
-				 <0x0de00047>, /* PM8644_GPIO_31 */
-				 <0x0df00048>, /* PM8644_GPIO_32 */
-				 <0x0e000049>, /* PM8644_GPIO_33 */
-				 <0x0e10004a>, /* PM8644_GPIO_34 */
-				 <0x0e20004b>, /* PM8644_GPIO_35 */
-				 <0x0e30004c>, /* PM8644_GPIO_36 */
-				 <0x0e40004d>, /* PM8644_GPIO_37 */
-				 <0x0e50004e>, /* PM8644_GPIO_38 */
-				 <0x0e60004f>, /* PM8644_GPIO_39 */
-				 <0x0e700050>, /* PM8644_GPIO_40 */
-				 <0x0e800051>, /* PM8644_GPIO_41 */
-				 <0x0e900052>, /* PM8644_GPIO_42 */
-				 <0x0ea00053>, /* PM8644_GPIO_43 */
-				 <0x11000054>, /* BUCK_CMN_1 */
-				 <0x11100055>, /* BUCK_CMN_2 */
-				 <0x11200056>, /* BUCK_CMN_3 */
-				 <0x11400057>, /* PM8644_SMPS1 */
-				 <0x11500058>, /* SMPS_1_PS1 */
-				 <0x11600059>, /* BUCK_FREQ_1 */
-				 <0x1170005a>, /* PM8644_SMPS2 */
-				 <0x1180005b>, /* SMPS_2_PS1 */
-				 <0x1190005c>, /* BUCK_FREQ_2 */
-				 <0x11a0005d>, /* PM8644_SMPS3 */
-				 <0x11b0005e>, /* SMPS_3_PS1 */
-				 <0x11c0005f>, /* BUCK_FREQ_3 */
-				 <0x11d00060>, /* PM8644_SMPS4 */
-				 <0x11e00061>, /* SMPS_4_PS1 */
-				 <0x11f00062>, /* PM8644_BUCK_FREQ_4 */
-				 <0x12000063>, /* PM8644_SMPS5 */
-				 <0x12100064>, /* FTPS1_5 */
-				 <0x12200065>, /* PM8644_BUCK_FREQ_5 */
-				 <0x12300066>, /* PM8644_SMPS6 */
-				 <0x12400067>, /* FTPS1_6 */
-				 <0x12500068>, /* PM8644_BUCK_FREQ_6 */
-				 <0x12600069>, /* PM8644_SMPS7 */
-				 <0x1270006a>, /* FTPS1_7 */
-				 <0x1280006b>, /* PM8644_BUCK_FREQ_7 */
-				 <0x1290006c>, /* PM8644_SMPS8 */
-				 <0x12a0006d>, /* FTPS1_8 */
-				 <0x12b0006e>, /* PM8644_BUCK_FREQ_8 */
-				 <0x12c0006f>, /* PM8644_SMPS9 */
-				 <0x12d00070>, /* FTPS1_9 */
-				 <0x12e00071>, /* PM8644_BUCK_FREQ_9 */
-				 <0x12f00072>, /* PM8644_SMPS10 */
-				 <0x13000073>, /* FTPS1_10 */
-				 <0x13100074>, /* PM8644_BUCK_FREQ_10 */
-				 <0x13200075>, /* PM8644_SMPS11 */
-				 <0x13300076>, /* FTPS1_11 */
-				 <0x13400077>, /* BUCK_FREQ_11 */
-				 <0x14000078>, /* PM8644_LDO_1 */
-				 <0x14100079>, /* PM8644_LDO_2 */
-				 <0x1420007a>, /* PM8644_LDO_3 */
-				 <0x1430007b>, /* PM8644_LDO_4 */
-				 <0x1440007c>, /* PM8644_LDO_5 */
-				 <0x1450007d>, /* PM8644_LDO_6 */
-				 <0x1460007e>, /* PM8644_LDO_7 */
-				 <0x1470007f>, /* PM8644_LDO_8 */
-				 <0x14800080>, /* PM8644_LDO_9 */
-				 <0x14900081>, /* PM8644_LDO_10 */
-				 <0x14a00082>, /* PM8644_LDO_11 */
-				 <0x14b00083>, /* PM8644_LDO_12 */
-				 <0x14c00084>, /* PM8644_LDO_13 */
-				 <0x14d00085>, /* PM8644_LDO_14 */
-				 <0x14e00086>, /* PM8644_LDO_15 */
-				 <0x14f00087>, /* PM8644_LDO_16 */
-				 <0x15000088>, /* PM8644_LDO_17 */
-				 <0x15100089>, /* PM8644_LDO_18 */
-				 <0x1520008a>, /* PM8644_LDO_19 */
-				 <0x1530008b>, /* PM8644_LDO_20 */
-				 <0x1540008c>, /* PM8644_LDO_21 */
-				 <0x1550008d>, /* PM8644_LDO_22 */
-				 <0x1560008e>, /* PM8644_LDO_23 */
-				 <0x1570008f>, /* PM8644_LDO_24 */
-				 <0x15800090>, /* PM8644_LDO_25 */
-				 <0x18000091>, /* PM8644_LVS_1 */
-				 <0x18100092>, /* PM8644_LVS_2 */
-				 <0x18200093>, /* PM8644_OTG */
-				 <0x18300094>, /* PM8644_HDMI */
-				 <0x1a800095>, /* KEYPAD */
-				 <0x1b000096>, /* LPG_LUT */
-				 <0x1b100097>, /* LPG_CHAN_1 */
-				 <0x1b200098>, /* LPG_CHAN_2 */
-				 <0x1b300099>, /* LPG_CHAN_3 */
-				 <0x1b40009a>, /* LPG_CHAN_4 */
-				 <0x1b50009b>, /* LPG_CHAN_5 */
-				 <0x1b60009c>, /* LPG_CHAN_6 */
-				 <0x1b70009d>, /* LPG_CHAN_7 */
-				 <0x1b80009e>, /* LPG_CHAN_8 */
-				 <0x1bc0009f>; /* LPG_PWM */
 	};
 
 	sdcc1: qcom,sdcc@f9824000 {
diff --git a/arch/arm/boot/dts/msm-iommu-v0.dtsi b/arch/arm/boot/dts/msm-iommu-v0.dtsi
new file mode 100644
index 0000000..c6eb1b9
--- /dev/null
+++ b/arch/arm/boot/dts/msm-iommu-v0.dtsi
@@ -0,0 +1,228 @@
+/* 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.
+ */
+
+/ {
+	lpass_iommu: qcom,iommu@fd000000 {
+		compatible = "qcom,msm-smmu-v0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfd000000 0x10000>;
+		qcom,glb-offset = <0xF000>;
+		label = "lpass_iommu";
+		status = "disabled";
+
+		lpass_q6_fw: qcom,iommu-ctx@fd000000 {
+			reg = <0xfd000000 0x1000>;
+			interrupts = <0 250 0>;
+			qcom,iommu-ctx-mids = <0 15>;
+			label = "q6_fw";
+		};
+
+		lpass_audio_shared: qcom,iommu-ctx@fd001000 {
+			reg = <0xfd001000 0x1000>;
+			interrupts = <0 250 0>;
+			qcom,iommu-ctx-mids = <1>;
+			label = "audio_shared";
+		};
+
+		lpass_video_shared: qcom,iommu-ctx@fd002000 {
+			reg = <0xfd002000 0x1000>;
+			interrupts = <0 250 0>;
+			qcom,iommu-ctx-mids = <2>;
+			label = "video_shared";
+		};
+
+		lpass_q6_spare: qcom,iommu-ctx@fd003000 {
+			reg = <0xfd003000 0x1000>;
+			interrupts = <0 250 0>;
+			qcom,iommu-ctx-mids = <3 4 5 6 7 8 9 10 11 12 13 14>;
+			label = "q6_spare";
+		};
+	};
+
+	copss_iommu: qcom,iommu@fd010000 {
+		compatible = "qcom,msm-smmu-v0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfd010000 0x10000>;
+		qcom,glb-offset = <0xF000>;
+		label = "copss_iommu";
+		status = "disabled";
+
+		qcom,iommu-ctx@fd010000 {
+			reg = <0xfd010000 0x1000>;
+			interrupts = <0 254 0>;
+			qcom,iommu-ctx-mids = <0>;
+			label = "copss_0";
+		};
+
+		qcom,iommu-ctx@fd011000 {
+			reg = <0xfd011000 0x1000>;
+			interrupts = <0 254 0>;
+			qcom,iommu-ctx-mids = <1>;
+			label = "copss_1";
+		};
+
+		qcom,iommu-ctx@fd012000 {
+			reg = <0xfd012000 0x1000>;
+			interrupts = <0 254 0>;
+			qcom,iommu-ctx-mids = <2>;
+			label = "copss_2";
+		};
+
+		qcom,iommu-ctx@fd013000 {
+			reg = <0xfd013000 0x1000>;
+			interrupts = <0 254 0>;
+			qcom,iommu-ctx-mids = <3>;
+			label = "copss_3";
+		};
+
+		qcom,iommu-ctx@fd014000 {
+			reg = <0xfd014000 0x1000>;
+			interrupts = <0 254 0>;
+			qcom,iommu-ctx-mids = <4>;
+			label = "copss_4";
+		};
+
+		qcom,iommu-ctx@fd015000 {
+			reg = <0xfd015000 0x1000>;
+			interrupts = <0 254 0>;
+			qcom,iommu-ctx-mids = <5>;
+			label = "copss_5";
+		};
+
+		qcom,iommu-ctx@fd016000 {
+			reg = <0xfd016000 0x1000>;
+			interrupts = <0 254 0>;
+			qcom,iommu-ctx-mids = <6>;
+			label = "copss_6";
+		};
+
+		qcom,iommu-ctx@fd017000 {
+			reg = <0xfd017000 0x1000>;
+			interrupts = <0 254 0>;
+			qcom,iommu-ctx-mids = <7>;
+			label = "copss_7";
+		};
+	};
+
+	mdpe_iommu: qcom,iommu@fd860000 {
+		compatible = "qcom,msm-smmu-v0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfd860000 0x10000>;
+		qcom,glb-offset = <0xF000>;
+		label = "mdpe_iommu";
+		status = "disabled";
+
+		qcom,iommu-ctx@fd860000 {
+			reg = <0xfd860000 0x1000>;
+			interrupts = <0 247 0>;
+			qcom,iommu-ctx-mids = <>;
+			label = "mdpe_0";
+		};
+
+		qcom,iommu-ctx@fd861000 {
+			reg = <0xfd861000 0x1000>;
+			interrupts = <0 247 0>;
+			qcom,iommu-ctx-mids = <>;
+			label = "mdpe_1";
+		};
+	};
+
+	mdps_iommu: qcom,iommu@fd870000 {
+		compatible = "qcom,msm-smmu-v0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfd870000 0x10000>;
+		qcom,glb-offset = <0xF000>;
+		label = "mdps_iommu";
+		status = "disabled";
+
+		qcom,iommu-ctx@fd870000 {
+			reg = <0xfd870000 0x1000>;
+			interrupts = <0 247 0>;
+			qcom,iommu-ctx-mids = <>;
+			label = "mdps_0";
+		};
+
+		qcom,iommu-ctx@fd871000 {
+			reg = <0xfd871000 0x1000>;
+			interrupts = <0 247 0>;
+			qcom,iommu-ctx-mids = <>;
+			label = "mdps_1";
+		};
+	};
+
+	gfx_iommu: qcom,iommu@fd880000 {
+		compatible = "qcom,msm-smmu-v0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfd880000 0x10000>;
+		qcom,glb-offset = <0xF000>;
+		label = "gfx_iommu";
+		status = "disabled";
+
+		qcom,iommu-ctx@fd880000 {
+			reg = <0xfd880000 0x1000>;
+			interrupts = <0 241 0>;
+			qcom,iommu-ctx-mids = <0 1 2 3 4 5 6 7 8 9 10 11 12 13
+					       14 15>;
+			label = "gfx3d_user";
+		};
+
+		qcom,iommu-ctx@fd881000 {
+			reg = <0xfd881000 0x1000>;
+			interrupts = <0 241 0>;
+			qcom,iommu-ctx-mids = <16 17 18 19 20 21 22 23 24 25
+					       26 27 28 29 30 31>;
+			label = "gfx3d_priv";
+		};
+
+		qcom,iommu-ctx@fd882000 {
+			reg = <0xfd882000 0x1000>;
+			interrupts = <0 241 0>;
+			qcom,iommu-ctx-mids = <>;
+			label = "gfx3d_spare";
+		};
+	};
+
+	vfe_iommu: qcom,iommu@fd890000 {
+		compatible = "qcom,msm-smmu-v0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfd890000 0x10000>;
+		qcom,glb-offset = <0xF000>;
+		label = "vfe_iommu";
+		status = "disabled";
+
+		qcom,iommu-ctx@fd890000 {
+			reg = <0xfd890000 0x1000>;
+			interrupts = <0 65 0>;
+			qcom,iommu-ctx-mids = <0>;
+			label = "vfe0";
+		};
+
+		qcom,iommu-ctx@fd891000 {
+			reg = <0xfd891000 0x1000>;
+			interrupts = <0 65 0>;
+			qcom,iommu-ctx-mids = <1>;
+			label = "vfe1";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm-iommu-v1.dtsi b/arch/arm/boot/dts/msm-iommu-v1.dtsi
index ea4fa75..71dcc6a 100644
--- a/arch/arm/boot/dts/msm-iommu-v1.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v1.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,218 +11,462 @@
  */
 
 / {
-	lpass_iommu: qcom,iommu@fd000000 {
+	jpeg_iommu: qcom,iommu@fda64000 {
 		compatible = "qcom,msm-smmu-v1";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
-		reg = <0xfd000000 0x10000>;
-		qcom,glb-offset = <0xF000>;
-		label = "lpass_iommu";
+		reg = <0xfda64000 0x10000>;
+		reg-names = "iommu_base";
+		interrupts = <0 67 0>;
+		vdd-supply = <&gdsc_jpeg>;
+		qcom,needs-alt-core-clk;
+		label = "jpeg_iommu";
 		status = "disabled";
 
-		lpass_q6_fw: qcom,iommu-ctx@fd000000 {
-			reg = <0xfd000000 0x1000>;
-			interrupts = <0 250 0>;
-			qcom,iommu-ctx-mids = <0 15>;
-			label = "q6_fw";
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0A
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
+
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2050
+					0x2514
+					0x2540
+					0x256c
+					0x2314
+					0x2394
+					0x2414
+					0x20ac
+					0x215c
+					0x220c
+					0x2008
+					0x200c
+					0x2010
+					0x2014>;
+
+		qcom,iommu-bfb-data =  <0x0000ffff
+					0x0
+					0x4
+					0x4
+					0x0
+					0x0
+					0x10
+					0x50
+					0x0
+					0x10
+					0x20
+					0x0
+					0x0
+					0x0
+					0x0>;
+
+		qcom,iommu-ctx@fda6c000 {
+			reg = <0xfda6c000 0x1000>;
+			interrupts = <0 70 0>;
+			qcom,iommu-ctx-sids = <0>;
+			label = "jpeg_enc0";
 		};
 
-		lpass_audio_shared: qcom,iommu-ctx@fd001000 {
-			reg = <0xfd001000 0x1000>;
-			interrupts = <0 250 0>;
-			qcom,iommu-ctx-mids = <1>;
-			label = "audio_shared";
+		qcom,iommu-ctx@fda6d000 {
+			reg = <0xfda6d000 0x1000>;
+			interrupts = <0 70 0>;
+			qcom,iommu-ctx-sids = <1>;
+			label = "jpeg_enc1";
 		};
 
-		lpass_video_shared: qcom,iommu-ctx@fd002000 {
-			reg = <0xfd002000 0x1000>;
-			interrupts = <0 250 0>;
-			qcom,iommu-ctx-mids = <2>;
-			label = "video_shared";
-		};
-
-		lpass_q6_spare: qcom,iommu-ctx@fd003000 {
-			reg = <0xfd003000 0x1000>;
-			interrupts = <0 250 0>;
-			qcom,iommu-ctx-mids = <3 4 5 6 7 8 9 10 11 12 13 14>;
-			label = "q6_spare";
+		qcom,iommu-ctx@fda6e000 {
+			reg = <0xfda6e000 0x1000>;
+			interrupts = <0 70 0>;
+			qcom,iommu-ctx-sids = <2>;
+			label = "jpeg_dec";
 		};
 	};
 
-	copss_iommu: qcom,iommu@fd010000 {
+	mdp_iommu: qcom,iommu@fd928000 {
 		compatible = "qcom,msm-smmu-v1";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
-		reg = <0xfd010000 0x10000>;
-		qcom,glb-offset = <0xF000>;
-		label = "copss_iommu";
+		reg = <0xfd928000 0x10000>;
+		reg-names = "iommu_base";
+		interrupts = <0 73 0>;
+		vdd-supply = <&gdsc_mdss>;
+		qcom,iommu-secure-id = <1>;
+		label = "mdp_iommu";
 		status = "disabled";
 
-		qcom,iommu-ctx@fd010000 {
-			reg = <0xfd010000 0x1000>;
-			interrupts = <0 254 0>;
-			qcom,iommu-ctx-mids = <0>;
-			label = "copss_0";
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0A
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
+
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2050
+					0x2514
+					0x2540
+					0x256c
+					0x20ac
+					0x215c
+					0x220c
+					0x2314
+					0x2394
+					0x2414
+					0x2008
+					0x200c
+					0x2010
+					0x2014
+					0x2018
+					0x201c
+					0x2020>;
+
+		qcom,iommu-bfb-data =  <0xffffffff
+					0x0
+					0x00000004
+					0x00000010
+					0x00000000
+					0x00000000
+					0x00000034
+					0x00000044
+					0x0
+					0x34
+					0x74
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0>;
+
+		qcom,iommu-ctx@fd930000 {
+			reg = <0xfd930000 0x1000>;
+			interrupts = <0 47 0>;
+			qcom,iommu-ctx-sids = <0>;
+			label = "mdp_0";
 		};
 
-		qcom,iommu-ctx@fd011000 {
-			reg = <0xfd011000 0x1000>;
-			interrupts = <0 254 0>;
-			qcom,iommu-ctx-mids = <1>;
-			label = "copss_1";
+		qcom,iommu-ctx@fd931000 {
+			reg = <0xfd931000 0x1000>;
+			interrupts = <0 47 0>;
+			qcom,iommu-ctx-sids = <1>;
+			label = "mdp_1";
+			qcom,secure-context;
 		};
 
-		qcom,iommu-ctx@fd012000 {
-			reg = <0xfd012000 0x1000>;
-			interrupts = <0 254 0>;
-			qcom,iommu-ctx-mids = <2>;
-			label = "copss_2";
-		};
-
-		qcom,iommu-ctx@fd013000 {
-			reg = <0xfd013000 0x1000>;
-			interrupts = <0 254 0>;
-			qcom,iommu-ctx-mids = <3>;
-			label = "copss_3";
-		};
-
-		qcom,iommu-ctx@fd014000 {
-			reg = <0xfd014000 0x1000>;
-			interrupts = <0 254 0>;
-			qcom,iommu-ctx-mids = <4>;
-			label = "copss_4";
-		};
-
-		qcom,iommu-ctx@fd015000 {
-			reg = <0xfd015000 0x1000>;
-			interrupts = <0 254 0>;
-			qcom,iommu-ctx-mids = <5>;
-			label = "copss_5";
-		};
-
-		qcom,iommu-ctx@fd016000 {
-			reg = <0xfd016000 0x1000>;
-			interrupts = <0 254 0>;
-			qcom,iommu-ctx-mids = <6>;
-			label = "copss_6";
-		};
-
-		qcom,iommu-ctx@fd017000 {
-			reg = <0xfd017000 0x1000>;
-			interrupts = <0 254 0>;
-			qcom,iommu-ctx-mids = <7>;
-			label = "copss_7";
+		qcom,iommu-ctx@fd932000 {
+			reg = <0xfd932000 0x1000>;
+			interrupts = <0 47 0>;
+			qcom,iommu-ctx-sids = <>;
+			label = "mdp_2";
+			qcom,secure-context;
 		};
 	};
 
-	mdpe_iommu: qcom,iommu@fd860000 {
+	venus_iommu: qcom,iommu@fdc84000 {
 		compatible = "qcom,msm-smmu-v1";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
-		reg = <0xfd860000 0x10000>;
-		qcom,glb-offset = <0xF000>;
-		label = "mdpe_iommu";
+		reg = <0xfdc84000 0x10000
+		       0xfdce0004 0x4>;
+		reg-names = "iommu_base", "clk_base";
+		interrupts = <0 45 0>;
+		vdd-supply = <&gdsc_venus>;
+		qcom,iommu-secure-id = <0>;
+		qcom,needs-alt-core-clk;
+		label = "venus_iommu";
 		status = "disabled";
 
-		qcom,iommu-ctx@fd860000 {
-			reg = <0xfd860000 0x1000>;
-			interrupts = <0 247 0>;
-			qcom,iommu-ctx-mids = <>;
-			label = "mdpe_0";
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0A
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
+
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2050
+					0x2514
+					0x2540
+					0x256c
+					0x20ac
+					0x215c
+					0x220c
+					0x2314
+					0x2394
+					0x2414
+					0x2008
+					0x200c
+					0x2010
+					0x2014
+					0x2018
+					0x201c
+					0x2020
+					0x2024
+					0x2028
+					0x202c
+					0x2030
+					0x2034
+					0x2038>;
+
+		qcom,iommu-bfb-data =  <0xffffffff
+					0xffffffff
+					0x00000004
+					0x00000008
+					0x00000000
+					0x00000000
+					0x00000094
+					0x000000b4
+					0x0
+					0x94
+					0x114
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0>;
+
+		venus_ns: qcom,iommu-ctx@fdc8c000 {
+			reg = <0xfdc8c000 0x1000>;
+			interrupts = <0 42 0>;
+			qcom,iommu-ctx-sids = <0 1 2 3 4 5>;
+			label = "venus_ns";
 		};
 
-		qcom,iommu-ctx@fd861000 {
-			reg = <0xfd861000 0x1000>;
-			interrupts = <0 247 0>;
-			qcom,iommu-ctx-mids = <>;
-			label = "mdpe_1";
+		venus_cp: qcom,iommu-ctx@fdc8d000 {
+			reg = <0xfdc8d000 0x1000>;
+			interrupts = <0 42 0>;
+			qcom,iommu-ctx-sids = <0x80 0x81 0x82 0x83 0x84 0x85>;
+			label = "venus_cp";
+			qcom,secure-context;
+		};
+
+		venus_fw: qcom,iommu-ctx@fdc8e000 {
+			reg = <0xfdc8e000 0x1000>;
+			interrupts = <0 42 0>;
+			qcom,iommu-ctx-sids = <0xc0 0xc6>;
+			label = "venus_fw";
+			qcom,secure-context;
 		};
 	};
 
-	mdps_iommu: qcom,iommu@fd870000 {
+	kgsl_iommu: qcom,iommu@fdb10000 {
 		compatible = "qcom,msm-smmu-v1";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
-		reg = <0xfd870000 0x10000>;
-		qcom,glb-offset = <0xF000>;
-		label = "mdps_iommu";
+		reg = <0xfdb10000 0x10000>;
+		reg-names = "iommu_base";
+		interrupts = <0 38 0>;
+		vdd-supply = <&gdsc_oxili_cx>;
+		qcom,alt-vdd-supply = <&gdsc_oxili_gx>;
+		qcom,needs-alt-core-clk;
+		label = "kgsl_iommu";
 		status = "disabled";
 
-		qcom,iommu-ctx@fd870000 {
-			reg = <0xfd870000 0x1000>;
-			interrupts = <0 247 0>;
-			qcom,iommu-ctx-mids = <>;
-			label = "mdps_0";
-		};
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0A
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
 
-		qcom,iommu-ctx@fd871000 {
-			reg = <0xfd871000 0x1000>;
-			interrupts = <0 247 0>;
-			qcom,iommu-ctx-mids = <>;
-			label = "mdps_1";
-		};
-	};
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2050
+					0x2514
+					0x2540
+					0x256c
+					0x20ac
+					0x215c
+					0x220c
+					0x2314
+					0x2394
+					0x2414
+					0x2008>;
 
-	gfx_iommu: qcom,iommu@fd880000 {
-		compatible = "qcom,msm-smmu-v1";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		reg = <0xfd880000 0x10000>;
-		qcom,glb-offset = <0xF000>;
-		label = "gfx_iommu";
-		status = "disabled";
+		qcom,iommu-bfb-data =  <0x00000003
+					0x0
+					0x00000004
+					0x00000010
+					0x00000000
+					0x00000000
+					0x00000001
+					0x00000021
+					0x0
+					0x1
+					0x81
+					0x0>;
 
-		qcom,iommu-ctx@fd880000 {
-			reg = <0xfd880000 0x1000>;
+		qcom,iommu-ctx@fdb18000 {
+			reg = <0xfdb18000 0x1000>;
 			interrupts = <0 241 0>;
-			qcom,iommu-ctx-mids = <0 1 2 3 4 5 6 7 8 9 10 11 12 13
-					       14 15>;
+			qcom,iommu-ctx-sids = <0>;
 			label = "gfx3d_user";
 		};
 
-		qcom,iommu-ctx@fd881000 {
-			reg = <0xfd881000 0x1000>;
+		qcom,iommu-ctx@fdb19000 {
+			reg = <0xfdb19000 0x1000>;
 			interrupts = <0 241 0>;
-			qcom,iommu-ctx-mids = <16 17 18 19 20 21 22 23 24 25
-					       26 27 28 29 30 31>;
+			qcom,iommu-ctx-sids = <1>;
 			label = "gfx3d_priv";
 		};
-
-		qcom,iommu-ctx@fd882000 {
-			reg = <0xfd882000 0x1000>;
-			interrupts = <0 241 0>;
-			qcom,iommu-ctx-mids = <>;
-			label = "gfx3d_spare";
-		};
 	};
 
-	vfe_iommu: qcom,iommu@fd890000 {
+	vfe_iommu: qcom,iommu@fda44000 {
 		compatible = "qcom,msm-smmu-v1";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
-		reg = <0xfd890000 0x10000>;
-		qcom,glb-offset = <0xF000>;
+		reg = <0xfda44000 0x10000>;
+		reg-names = "iommu_base";
+		interrupts = <0 62 0>;
+		vdd-supply = <&gdsc_vfe>;
+		qcom,needs-alt-core-clk;
 		label = "vfe_iommu";
 		status = "disabled";
 
-		qcom,iommu-ctx@fd890000 {
-			reg = <0xfd890000 0x1000>;
+		qcom,iommu-pmu-ngroups = <1>;
+		qcom,iommu-pmu-ncounters = <8>;
+		qcom,iommu-pmu-event-classes = <0x00
+						0x01
+						0x08
+						0x09
+						0x0A
+						0x10
+						0x11
+						0x12
+						0x80
+						0x81
+						0x82
+						0x83
+						0x90
+						0x91
+						0x92
+						0xb0
+						0xb1>;
+
+		qcom,iommu-bfb-regs =  <0x204c
+					0x2050
+					0x2514
+					0x2540
+					0x256c
+					0x2314
+					0x2394
+					0x2414
+					0x20ac
+					0x215c
+					0x220c
+					0x2008
+					0x200c
+					0x2010
+					0x2014
+					0x2018
+					0x201c
+					0x2020>;
+
+		qcom,iommu-bfb-data =  <0xffffffff
+					0x00000000
+					0x4
+					0x8
+					0x0
+					0x0
+					0x20
+					0x78
+					0x0
+					0x20
+					0x36
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0
+					0x0>;
+
+		qcom,iommu-ctx@fda4c000 {
+			reg = <0xfda4c000 0x1000>;
 			interrupts = <0 65 0>;
-			qcom,iommu-ctx-mids = <0>;
+			qcom,iommu-ctx-sids = <0>;
 			label = "vfe0";
 		};
 
-		qcom,iommu-ctx@fd891000 {
-			reg = <0xfd891000 0x1000>;
+		qcom,iommu-ctx@fda4d000 {
+			reg = <0xfda4d000 0x1000>;
 			interrupts = <0 65 0>;
-			qcom,iommu-ctx-mids = <1>;
+			qcom,iommu-ctx-sids = <1>;
 			label = "vfe1";
 		};
+
+		qcom,iommu-ctx@fda4e000 {
+			reg = <0xfda4e000 0x1000>;
+			interrupts = <0 65 0>;
+			qcom,iommu-ctx-sids = <2>;
+			label = "cpp";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm-iommu.dtsi b/arch/arm/boot/dts/msm-iommu.dtsi
deleted file mode 100755
index 9bb642d..0000000
--- a/arch/arm/boot/dts/msm-iommu.dtsi
+++ /dev/null
@@ -1,364 +0,0 @@
-/* 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.
- */
-
-/ {
-	jpeg_iommu: qcom,iommu@fda64000 {
-		compatible = "qcom,msm-smmu-v2";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		reg = <0xfda64000 0x10000>;
-		reg-names = "iommu_base";
-		interrupts = <0 67 0>;
-		vdd-supply = <&gdsc_jpeg>;
-		qcom,needs-alt-core-clk;
-		label = "jpeg_iommu";
-		status = "disabled";
-
-		qcom,iommu-bfb-regs =  <0x204c
-					0x2050
-					0x2514
-					0x2540
-					0x256c
-					0x2314
-					0x2394
-					0x2414
-					0x20ac
-					0x215c
-					0x220c
-					0x2008
-					0x200c
-					0x2010
-					0x2014>;
-
-		qcom,iommu-bfb-data =  <0x0000ffff
-					0x0
-					0x4
-					0x4
-					0x0
-					0x0
-					0x10
-					0x50
-					0x0
-					0x10
-					0x20
-					0x0
-					0x0
-					0x0
-					0x0>;
-
-		qcom,iommu-ctx@fda6c000 {
-			reg = <0xfda6c000 0x1000>;
-			interrupts = <0 70 0>;
-			qcom,iommu-ctx-sids = <0>;
-			label = "jpeg_enc0";
-		};
-
-		qcom,iommu-ctx@fda6d000 {
-			reg = <0xfda6d000 0x1000>;
-			interrupts = <0 70 0>;
-			qcom,iommu-ctx-sids = <1>;
-			label = "jpeg_enc1";
-		};
-
-		qcom,iommu-ctx@fda6e000 {
-			reg = <0xfda6e000 0x1000>;
-			interrupts = <0 70 0>;
-			qcom,iommu-ctx-sids = <2>;
-			label = "jpeg_dec";
-		};
-	};
-
-	mdp_iommu: qcom,iommu@fd928000 {
-		compatible = "qcom,msm-smmu-v2";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		reg = <0xfd928000 0x10000>;
-		reg-names = "iommu_base";
-		interrupts = <0 73 0>;
-		vdd-supply = <&gdsc_mdss>;
-		qcom,iommu-secure-id = <1>;
-		label = "mdp_iommu";
-		status = "disabled";
-
-		qcom,iommu-bfb-regs =  <0x204c
-					0x2050
-					0x2514
-					0x2540
-					0x256c
-					0x20ac
-					0x215c
-					0x220c
-					0x2314
-					0x2394
-					0x2414
-					0x2008
-					0x200c
-					0x2010
-					0x2014
-					0x2018
-					0x201c
-					0x2020>;
-
-		qcom,iommu-bfb-data =  <0xffffffff
-					0x0
-					0x00000004
-					0x00000010
-					0x00000000
-					0x00000000
-					0x00000034
-					0x00000044
-					0x0
-					0x34
-					0x74
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0>;
-
-		qcom,iommu-ctx@fd930000 {
-			reg = <0xfd930000 0x1000>;
-			interrupts = <0 47 0>;
-			qcom,iommu-ctx-sids = <0>;
-			label = "mdp_0";
-		};
-
-		qcom,iommu-ctx@fd931000 {
-			reg = <0xfd931000 0x1000>;
-			interrupts = <0 47 0>;
-			qcom,iommu-ctx-sids = <1>;
-			label = "mdp_1";
-			qcom,secure-context;
-		};
-	};
-
-	venus_iommu: qcom,iommu@fdc84000 {
-		compatible = "qcom,msm-smmu-v2";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		reg = <0xfdc84000 0x10000
-		       0xfdce0004 0x4>;
-		reg-names = "iommu_base", "clk_base";
-		interrupts = <0 45 0>;
-		vdd-supply = <&gdsc_venus>;
-		qcom,iommu-secure-id = <0>;
-		qcom,needs-alt-core-clk;
-		label = "venus_iommu";
-		status = "disabled";
-
-		qcom,iommu-bfb-regs =  <0x204c
-					0x2050
-					0x2514
-					0x2540
-					0x256c
-					0x20ac
-					0x215c
-					0x220c
-					0x2314
-					0x2394
-					0x2414
-					0x2008
-					0x200c
-					0x2010
-					0x2014
-					0x2018
-					0x201c
-					0x2020
-					0x2024
-					0x2028
-					0x202c
-					0x2030
-					0x2034
-					0x2038>;
-
-		qcom,iommu-bfb-data =  <0xffffffff
-					0xffffffff
-					0x00000004
-					0x00000008
-					0x00000000
-					0x00000000
-					0x00000094
-					0x000000b4
-					0x0
-					0x94
-					0x114
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0>;
-
-		qcom,iommu-ctx@fdc8c000 {
-			reg = <0xfdc8c000 0x1000>;
-			interrupts = <0 42 0>;
-			qcom,iommu-ctx-sids = <0 1 2 3 4 5>;
-			label = "venus_ns";
-		};
-
-		qcom,iommu-ctx@fdc8d000 {
-			reg = <0xfdc8d000 0x1000>;
-			interrupts = <0 42 0>;
-			qcom,iommu-ctx-sids = <0x80 0x81 0x82 0x83 0x84 0x85>;
-			label = "venus_cp";
-			qcom,secure-context;
-		};
-
-		qcom,iommu-ctx@fdc8e000 {
-			reg = <0xfdc8e000 0x1000>;
-			interrupts = <0 42 0>;
-			qcom,iommu-ctx-sids = <0xc0 0xc6>;
-			label = "venus_fw";
-			qcom,secure-context;
-		};
-	};
-
-	kgsl_iommu: qcom,iommu@fdb10000 {
-		compatible = "qcom,msm-smmu-v2";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		reg = <0xfdb10000 0x10000>;
-		reg-names = "iommu_base";
-		interrupts = <0 38 0>;
-		vdd-supply = <&gdsc_oxili_cx>;
-		qcom,alt-vdd-supply = <&gdsc_oxili_gx>;
-		qcom,needs-alt-core-clk;
-		label = "kgsl_iommu";
-		status = "disabled";
-
-		qcom,iommu-bfb-regs =  <0x204c
-					0x2050
-					0x2514
-					0x2540
-					0x256c
-					0x20ac
-					0x215c
-					0x220c
-					0x2314
-					0x2394
-					0x2414
-					0x2008>;
-
-		qcom,iommu-bfb-data =  <0x00000003
-					0x0
-					0x00000004
-					0x00000010
-					0x00000000
-					0x00000000
-					0x00000001
-					0x00000021
-					0x0
-					0x1
-					0x81
-					0x0>;
-
-		qcom,iommu-ctx@fdb18000 {
-			reg = <0xfdb18000 0x1000>;
-			interrupts = <0 241 0>;
-			qcom,iommu-ctx-sids = <0>;
-			label = "gfx3d_user";
-		};
-
-		qcom,iommu-ctx@fdb19000 {
-			reg = <0xfdb19000 0x1000>;
-			interrupts = <0 241 0>;
-			qcom,iommu-ctx-sids = <1>;
-			label = "gfx3d_priv";
-		};
-	};
-
-	vfe_iommu: qcom,iommu@fda44000 {
-		compatible = "qcom,msm-smmu-v2";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		reg = <0xfda44000 0x10000>;
-		reg-names = "iommu_base";
-		interrupts = <0 62 0>;
-		vdd-supply = <&gdsc_vfe>;
-		qcom,needs-alt-core-clk;
-		label = "vfe_iommu";
-		status = "disabled";
-
-		qcom,iommu-bfb-regs =  <0x204c
-					0x2050
-					0x2514
-					0x2540
-					0x256c
-					0x2314
-					0x2394
-					0x2414
-					0x20ac
-					0x215c
-					0x220c
-					0x2008
-					0x200c
-					0x2010
-					0x2014
-					0x2018
-					0x201c
-					0x2020>;
-
-		qcom,iommu-bfb-data =  <0xffffffff
-					0x00000000
-					0x4
-					0x8
-					0x0
-					0x0
-					0x20
-					0x78
-					0x0
-					0x20
-					0x36
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0
-					0x0>;
-
-		qcom,iommu-ctx@fda4c000 {
-			reg = <0xfda4c000 0x1000>;
-			interrupts = <0 65 0>;
-			qcom,iommu-ctx-sids = <0>;
-			label = "vfe0";
-		};
-
-		qcom,iommu-ctx@fda4d000 {
-			reg = <0xfda4d000 0x1000>;
-			interrupts = <0 65 0>;
-			qcom,iommu-ctx-sids = <1>;
-			label = "vfe1";
-		};
-
-		qcom,iommu-ctx@fda4e000 {
-			reg = <0xfda4e000 0x1000>;
-			interrupts = <0 65 0>;
-			qcom,iommu-ctx-sids = <2>;
-			label = "cpp";
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/msm-pm8026.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
similarity index 100%
rename from arch/arm/boot/dts/msm-pm8026.dtsi
rename to arch/arm/boot/dts/msm-pm8226.dtsi
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 74a95e6..2886038 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -65,18 +65,20 @@
 			#size-cells = <1>;
 			status = "disabled";
 
-			qcom,bms-r-sense-mohm = <2>;
-			qcom,bms-v-cutoff-uv = <3400000>;
-			qcom,bms-max-voltage-uv = <4200000>;
-			qcom,bms-r-conn-mohm = <18>;
-			qcom,bms-shutdown-soc-valid-limit = <20>;
-			qcom,bms-adjust-soc-low-threshold = <25>;
-			qcom,bms-adjust-soc-high-threshold = <45>;
-			qcom,bms-low-soc-calculate-soc-threshold = <15>;
-			qcom,bms-low-soc-calculate-soc-ms = <5000>;
-			qcom,bms-calculate-soc-ms = <20000>;
-			qcom,bms-chg-term-ua = <100000>;
-			qcom,bms-batt-type = <0>;
+			qcom,r-sense-uohm = <10000>;
+			qcom,v-cutoff-uv = <3400000>;
+			qcom,max-voltage-uv = <4200000>;
+			qcom,r-conn-mohm = <18>;
+			qcom,shutdown-soc-valid-limit = <20>;
+			qcom,adjust-soc-low-threshold = <25>;
+			qcom,adjust-soc-high-threshold = <45>;
+			qcom,ocv-voltage-high-threshold-uv = <3750000>;
+			qcom,ocv-voltage-low-threshold-uv = <3650000>;
+			qcom,low-soc-calculate-soc-threshold = <15>;
+			qcom,low-soc-calculate-soc-ms = <5000>;
+			qcom,calculate-soc-ms = <20000>;
+			qcom,chg-term-ua = <100000>;
+			qcom,batt-type = <0>;
 
 			qcom,bms-iadc@3800 {
 				reg = <0x3800 0x100>;
@@ -136,6 +138,7 @@
 			qcom,chg-ibatmax-ma = <1500>;
 			qcom,chg-ibatterm-ma = <200>;
 			qcom,chg-ibatsafe-ma = <1500>;
+			qcom,chg-thermal-mitigation = <1500 700 600 325>;
 
 			qcom,chg-chgr@1000 {
 				status = "disabled";
diff --git a/arch/arm/boot/dts/msm8226-gpu.dtsi b/arch/arm/boot/dts/msm8226-gpu.dtsi
new file mode 100644
index 0000000..76e934e
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-gpu.dtsi
@@ -0,0 +1,62 @@
+/* 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/ "msm8974-gpu.dtsi"
+
+&msm_gpu {
+	qcom,chipid = <0x03000510>;
+
+	qcom,msm-bus,vectors-KBps =
+			<26 512 0 0>, <89 604 0 0>,
+			<26 512 0 1600000>, <89 604 0 6400000>,
+			<26 512 0 3200000>, <89 604 0 12800000>,
+			<26 512 0 4264000>, <89 604 0 12800000>;
+
+	/* GDSC oxili regulators */
+	vddcx-supply = "\0";
+	vdd-supply = <&gdsc_oxili_cx>;
+
+	qcom,gpu-pwrlevels {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "qcom,gpu-pwrlevels";
+
+		qcom,gpu-pwrlevel@0 {
+			reg = <0>;
+			qcom,gpu-freq = <450000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <0>;
+		};
+
+		qcom,gpu-pwrlevel@1 {
+			reg = <1>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <2>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@2 {
+			reg = <2>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <1>;
+			qcom,io-fraction = <100>;
+		};
+
+		qcom,gpu-pwrlevel@3 {
+			reg = <3>;
+			qcom,gpu-freq = <19000000>;
+			qcom,bus-freq = <0>;
+			qcom,io-fraction = <0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226-iommu.dtsi b/arch/arm/boot/dts/msm8226-iommu.dtsi
index 66a7848..d23d324 100644
--- a/arch/arm/boot/dts/msm8226-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8226-iommu.dtsi
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/include/ "msm-iommu.dtsi"
+/include/ "msm-iommu-v1.dtsi"
 
 &jpeg_iommu {
 	status = "ok";
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 8fe94a5..f2269d5 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,15 @@
 		regulator-max-microvolt = <1150000>;
 	};
 
+	pm8026_s1_corner: regulator-s1-corner {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_s1_corner";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <7>;
+		qcom,consumer-supplies = "vdd_dig", "";
+	};
+
 	pm8026_s2: regulator-s2 {
 		compatible = "qcom,stub-regulator";
 		regulator-name = "8026_s2";
@@ -123,6 +132,7 @@
 		qcom,hpm-min-load = <5000>;
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
+		qcom,consumer-supplies = "vdd_sr2_pll", "";
 	};
 
 	pm8026_l9: regulator-l9 {
diff --git a/arch/arm/boot/dts/msm8226-smp2p.dtsi b/arch/arm/boot/dts/msm8226-smp2p.dtsi
new file mode 100644
index 0000000..60f63a8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-smp2p.dtsi
@@ -0,0 +1,194 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+/ {
+	qcom,smp2p-modem {
+		compatible = "qcom,smp2p";
+		reg = <0xfa006000 0x1000>, <0x8 0x0>;
+		reg-names = "irq-reg-base", "irq-reg-offset";
+		qcom,remote-pid = <1>;
+		qcom,irq-bitmask = <0x4000>;
+		interrupts = <0 27 1>;
+	};
+
+	qcom,smp2p-adsp {
+		compatible = "qcom,smp2p";
+		reg = <0xfa006000 0x1000>, <0x8 0x0>;
+		reg-names = "irq-reg-base", "irq-reg-offset";
+		qcom,remote-pid = <2>;
+		qcom,irq-bitmask = <0x400>;
+		interrupts = <0 158 1>;
+	};
+
+	qcom,smp2p-wcnss {
+		compatible = "qcom,smp2p";
+		reg = <0xfa006000 0x1000>, <0x8 0x0>;
+		reg-names = "irq-reg-base", "irq-reg-offset";
+		qcom,remote-pid = <4>;
+		qcom,irq-bitmask = <0x40000>;
+		interrupts = <0 143 1>;
+	};
+
+	/* SMP2P Test Driver for inbound entries */
+	smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <7>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_7_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_7_in";
+		gpios = <&smp2pgpio_smp2p_7_in 0 0>;
+	};
+
+	/* SMP2P Test Driver for outbound entries */
+	smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <7>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_7_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_7_out";
+		gpios = <&smp2pgpio_smp2p_7_out 0 0>;
+	};
+
+	/* SMP2P Test Driver for modem inbound */
+	smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+		gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+	};
+
+	/* SMP2P Test Driver for modem output */
+	smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+		gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+	};
+
+	/* SMP2P SSR Driver for inbound entry from modem. */
+	smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "slave-kernel";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	/* SMP2P SSR Driver for outbound entry to modem */
+	smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "master-kernel";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	/* SMP2P Test Driver for adsp inbound */
+	smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <2>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_2_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+		gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+	};
+
+	/* SMP2P Test Driver for adsp output */
+	smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_2_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+		gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+	};
+
+	/* SMP2P Test Driver for wcnss inbound */
+	smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <4>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_4_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+		gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+	};
+
+	/* SMP2P Test Driver for wcnss output */
+	smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_4_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+		gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index e8c25a8..cb33a40 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -15,6 +15,8 @@
 /include/ "msm-gdsc.dtsi"
 /include/ "msm8226-iommu.dtsi"
 /include/ "msm8226-pm.dtsi"
+/include/ "msm8226-smp2p.dtsi"
+/include/ "msm8226-gpu.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226";
@@ -88,8 +90,9 @@
 		qcom,hsusb-otg-disable-reset;
 	};
 
-	android_usb {
+	android_usb@fe8050c8 {
 		compatible = "qcom,android-usb";
+		reg = <0xfe8050c8 0xc8>;
 	};
 
 	wcd9xxx_intc: wcd9xxx-irq {
@@ -434,130 +437,16 @@
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
 		reg = <0xfc4cf000 0x1000>,
-		      <0Xfc4cb000 0x1000>;
+		      <0Xfc4cb000 0x1000>,
+		      <0Xfc4ca000 0x1000>;
 		/* 190,ee0_krait_hlos_spmi_periph_irq */
 		/* 187,channel_0_krait_hlos_trans_done_irq */
 		interrupts = <0 190 0>, <0 187 0>;
 		qcom,not-wakeup;
 		qcom,pmic-arb-ee = <0>;
 		qcom,pmic-arb-channel = <0>;
-		qcom,pmic-arb-ppid-map = <0x001000a0>, /* PM8026_0 */
-					 <0x005000a2>, /* INTERRUPT */
-					 <0x006000a3>, /* SPMI_0 */
-					 <0x00800000>, /* PON0 */
-					 <0x00a000a5>, /* VREF_LPDDR3 */
-					 <0x01000001>, /* SMBB_CHG */
-					 <0x01100002>, /* SMBB_BUCK */
-					 <0x01200003>, /* SMBB_BIF */
-					 <0x01300004>, /* SMBB_USB */
-					 <0x01500005>, /* SMBB_BOOST */
-					 <0x01600006>, /* SMBB_MISC */
-					 <0x02800009>, /* COINCELL */
-					 <0x02c000a6>, /* MBG */
-					 <0x0310000a>, /* VADC1_USR */
-					 <0x03200041>, /* VADC1_MDM */
-					 <0x0330000b>, /* VADC1_BMS */
-					 <0x0340000c>, /* VADC2_BTM */
-					 <0x0360000d>, /* IADC1_USR */
-					 <0x03700042>, /* IADC1_MDM */
-					 <0x0380000e>, /* IADC1_BMS */
-					 <0x0400000f>, /* BMS_1 */
-					 <0x050000a7>, /* SHARED_XO */
-					 <0x051000a8>, /* BB_CLK1 */
-					 <0x05200010>, /* BB_CLK2 */
-					 <0x05a000ac>, /* SLEEP_CLK */
-					 <0x06000045>, /* RTC_RW */
-					 <0x06100012>, /* RTC_ALARM */
-					 <0x070000ae>, /* PBS_CORE */
-					 <0x071000af>, /* PBS_CLIENT_1 */
-					 <0x072000b0>, /* PBS_CLIENT_2 */
-					 <0x073000b1>, /* PBS_CLIENT_3 */
-					 <0x074000b2>, /* PBS_CLIENT_4 */
-					 <0x075000b3>, /* PBS_CLIENT_5 */
-					 <0x076000b4>, /* PBS_CLIENT_6 */
-					 <0x07700046>, /* PBS_CLIENT_7 */
-					 <0x07800047>, /* PBS_CLIENT_8 */
-					 <0x079000b5>, /* PBS_CLIENT_9 */
-					 <0x07a000b6>, /* PBS_CLIENT_10 */
-					 <0x07b000b7>, /* PBS_CLIENT_11 */
-					 <0x07c000b8>, /* PBS_CLIENT_12 */
-					 <0x07d000b9>, /* PBS_CLIENT_13 */
-					 <0x07e000ba>, /* PBS_CLIENT_14 */
-					 <0x07f000bb>, /* PBS_CLIENT_15 */
-					 <0x0a0000bd>, /* MPP_1 */
-					 <0x0a100014>, /* MPP_2 */
-					 <0x0a200015>, /* MPP_3 */
-					 <0x0a300016>, /* MPP_4 */
-					 <0x0a400048>, /* MPP_5 */
-					 <0x0a500017>, /* MPP_6 */
-					 <0x0a600018>, /* MPP_7 */
-					 <0x0a700049>, /* MPP_8 */
-					 <0x0c000019>, /* GPIO_1 */
-					 <0x0c10001a>, /* GPIO_2 */
-					 <0x0c20004a>, /* GPIO_3 */
-					 <0x0c30004b>, /* GPIO_4 */
-					 <0x0c40001b>, /* GPIO_5 */
-					 <0x0c50001c>, /* GPIO_6 */
-					 <0x0c60001d>, /* GPIO_7 */
-					 <0x0c70004c>, /* GPIO_8 */
-					 <0x0fe000be>, /* TRIM_0 */
-					 <0x110000bf>, /* BUCK_CMN_1 */
-					 <0x114000c0>, /* SMPS1 */
-					 <0x115000c1>, /* FTPS1_1 */
-					 <0x116000c2>, /* BUCK_FREQ_1 */
-					 <0x1170001e>, /* SMPS2 */
-					 <0x1180001f>, /* FTPS1_2 */
-					 <0x11900020>, /* BUCK_FREQ_2 */
-					 <0x11a000c3>, /* SMPS3 */
-					 <0x11b000c4>, /* SMPS_3_PS1 */
-					 <0x11c000c5>, /* BUCK_FREQ_3 */
-					 <0x11d000c6>, /* SMPS4 */
-					 <0x11e000c7>, /* SMPS_4_PS1 */
-					 <0x11f000c8>, /* BUCK_FREQ_4 */
-					 <0x120000c9>, /* SMPS5 */
-					 <0x121000ca>, /* SMPS_5_PS1 */
-					 <0x122000cb>, /* BUCK_FREQ_5 */
-					 <0x140000cc>, /* LDO_1 */
-					 <0x141000cd>, /* LDO_2 */
-					 <0x142000ce>, /* LDO_3 */
-					 <0x143000cf>, /* LDO_4 */
-					 <0x144000d0>, /* LDO_5 */
-					 <0x145000d1>, /* LDO_6 */
-					 <0x146000d2>, /* LDO_7 */
-					 <0x147000d3>, /* LDO_8 */
-					 <0x148000d4>, /* LDO_9 */
-					 <0x149000d5>, /* LDO_10 */
-					 <0x14a000d6>, /* LDO_11 */
-					 <0x14b000d7>, /* LDO_12 */
-					 <0x14c000d8>, /* LDO_13 */
-					 <0x14d000d9>, /* LDO_14 */
-					 <0x14e000da>, /* LDO_15 */
-					 <0x14f000db>, /* LDO_16 */
-					 <0x150000dc>, /* LDO_17 */
-					 <0x151000dd>, /* LDO_18 */
-					 <0x152000de>, /* LDO_19 */
-					 <0x153000df>, /* LDO_20 */
-					 <0x154000e0>, /* LDO_21 */
-					 <0x155000e1>, /* LDO_22 */
-					 <0x156000e2>, /* LDO_23 */
-					 <0x157000e3>, /* LDO_24 */
-					 <0x158000e4>, /* LDO_25 */
-					 <0x159000e5>, /* LDO_26 */
-					 <0x15a000e6>, /* LDO_27 */
-					 <0x15b000e7>, /* LDO_28 */
-					 <0x180000e8>, /* LVS_1 */
-					 <0x1b0000e9>, /* LPG_LUT */
-					 <0x1b1000ea>, /* LPG_CHAN_1 */
-					 <0x1b200023>, /* LPG_CHAN_2 */
-					 <0x1b300024>, /* LPG_CHAN_3 */
-					 <0x1b400025>, /* LPG_CHAN_4 */
-					 <0x1b500026>, /* LPG_CHAN_5 */
-					 <0x1b600027>, /* LPG_CHAN_6 */
-					 <0x1bc00028>, /* PWM_3D */
-					 <0x1c000029>, /* VIB1 */
-					 <0x1d30002a>, /* FLASH_DRV */
-					 <0x1d80002b>; /* WLED */
 	};
 
 	i2c@f9926000 { /* BLSP-1 QUP-4 */
@@ -571,6 +460,74 @@
 		interrupt-names = "qup_err_intr";
 		qcom,i2c-bus-freq = <100000>;
 	};
+
+	qcom,acpuclk@f9011050 {
+		compatible = "qcom,acpuclk-a7";
+		reg = <0xf9011050 0x8>;
+		reg-names = "rcg_base";
+		a7_cpu-supply = <&pm8026_s2>;
+		a7_mem-supply = <&pm8026_l3>;
+	};
+
+	qcom,ocmem@fdd00000 {
+		compatible = "qcom,msm-ocmem";
+		reg = <0xfdd00000 0x2000>,
+		      <0xfdd02000 0x2000>,
+		      <0xfe039000 0x400>,
+		      <0xfec00000 0x180000>;
+		reg-names = "ocmem_ctrl_physical", "dm_ctrl_physical", "br_ctrl_physical", "ocmem_physical";
+		interrupts = <0 76 0 0 77 0>;
+		interrupt-names = "ocmem_irq", "dm_irq";
+		qcom,ocmem-num-regions = <0x1>;
+		qcom,ocmem-num-macros = <0x2>;
+		qcom,resource-type = <0x706d636f>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0xfec00000 0x180000>;
+
+		partition@0 {
+			reg = <0x0 0x100000>;
+			qcom,ocmem-part-name = "graphics";
+			qcom,ocmem-part-min = <0x80000>;
+		};
+	};
+
+	qcom,venus@fdce0000 {
+		compatible = "qcom,pil-venus";
+		reg = <0xfdce0000 0x4000>,
+		      <0xfdc80000 0x400>;
+		reg-names = "wrapper_base", "vbif_base";
+		vdd-supply = <&gdsc_venus>;
+
+		qcom,firmware-name = "venus";
+	};
+
+	qcom,pronto@fb21b000 {
+		compatible = "qcom,pil-pronto";
+		reg = <0xfb21b000 0x3000>,
+		      <0xfc401700 0x4>,
+		      <0xfd485300 0xc>;
+		reg-names = "pmu_base", "clk_base", "halt_base";
+		interrupts = <0 149 1>;
+		vdd_pronto_pll-supply = <&pm8026_l8>;
+
+		qcom,firmware-name = "wcnss";
+	};
+
+	qcom,lpass@fe200000 {
+		compatible = "qcom,pil-q6v5-lpass";
+		reg = <0xfe200000 0x00100>,
+		      <0xfd485100 0x00010>;
+		reg-names = "qdsp6_base", "halt_base";
+		interrupts = <0 162 1>;
+
+		qcom,firmware-name = "adsp";
+	};
+
+	qcom,msm-mem-hole {
+		compatible = "qcom,msm-mem-hole";
+		qcom,memblock-remove = <0x8100000 0x7e00000>; /* Address and Size of Hole */
+	};
 };
 
 &gdsc_venus {
@@ -598,4 +555,4 @@
 };
 
 /include/ "msm8226-regulator.dtsi"
-/include/ "msm-pm8026.dtsi"
+/include/ "msm-pm8226.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index a81c082..362d126 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -21,6 +21,14 @@
 		regulator-max-microvolt = <1150000>;
 	};
 
+	pm8110_s1_corner: regulator-s1-corner {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_s1_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <7>;
+		qcom,consumer-supplies = "vdd_dig", "";
+	};
+
 	pm8110_s2: regulator-s2 {
 		compatible = "qcom,stub-regulator";
 		regulator-name = "8110_s2";
@@ -133,6 +141,7 @@
 		qcom,hpm-min-load = <10000>;
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
+		qcom,consumer-supplies = "vdd_sr2_pll", "";
 	};
 
 	pm8110_l12: regulator-l12 {
diff --git a/arch/arm/boot/dts/msm8610-rumi.dts b/arch/arm/boot/dts/msm8610-rumi.dts
index d889268..af8ce2e 100644
--- a/arch/arm/boot/dts/msm8610-rumi.dts
+++ b/arch/arm/boot/dts/msm8610-rumi.dts
@@ -23,3 +23,7 @@
 		status = "ok";
 	};
 };
+
+&gfx_iommu {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index d013cba..9ff383f 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -11,7 +11,7 @@
  */
 
 /include/ "skeleton.dtsi"
-/include/ "msm-iommu-v1.dtsi"
+/include/ "msm-iommu-v0.dtsi"
 /include/ "msm8610-ion.dtsi"
 /include/ "msm-gdsc.dtsi"
 /include/ "msm8610-pm.dtsi"
@@ -72,8 +72,8 @@
 	usb@f9a55000 {
 		compatible = "qcom,hsusb-otg";
 		reg = <0xf9a55000 0x400>;
-		interrupts = <0 134 0>;
-		interrupt-names = "core_irq";
+		interrupts = <0 134 0>, <0 140 0>;
+		interrupt-names = "core_irq", "async_irq";
 		HSUSB_VDDCX-supply = <&pm8110_s1>;
 		HSUSB_1p8-supply = <&pm8110_l10>;
 		HSUSB_3p3-supply = <&pm8110_l20>;
@@ -84,8 +84,9 @@
 		qcom,hsusb-otg-disable-reset;
 	};
 
-	android_usb {
+	android_usb@fe8050c8 {
 		compatible = "qcom,android-usb";
+		reg = <0xfe8050c8 0xc8>;
 	};
 
 	sdcc1: qcom,sdcc@f9824000 {
@@ -233,6 +234,11 @@
 		rpm-standalone;
 	};
 
+	qcom,msm-mem-hole {
+		compatible = "qcom,msm-mem-hole";
+		qcom,memblock-remove = <0x07C00000 0x6000000>; /* Address and Size of Hole */
+	};
+
 	qcom,wdt@f9017000 {
 		compatible = "qcom,msm-watchdog";
 		reg = <0xf9017000 0x1000>;
@@ -242,93 +248,156 @@
 		qcom,ipi-ping;
 	};
 
+	qcom,acpuclk@f9011050 {
+		compatible = "qcom,acpuclk-a7";
+		reg = <0xf9011050 0x8>;
+		reg-names = "rcg_base";
+		a7_cpu-supply = <&pm8110_s2>;
+		a7_mem-supply = <&pm8110_l3>;
+	};
+
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
 		reg = <0xfc4cf000 0x1000>,
-		      <0Xfc4cb000 0x1000>;
+		      <0Xfc4cb000 0x1000>,
+		      <0Xfc4ca000 0x1000>;
 		/* 190,ee0_krait_hlos_spmi_periph_irq */
 		/* 187,channel_0_krait_hlos_trans_done_irq */
 		interrupts = <0 190 0>, <0 187 0>;
 		qcom,not-wakeup;
 		qcom,pmic-arb-ee = <0>;
 		qcom,pmic-arb-channel = <0>;
-		qcom,pmic-arb-ppid-map = <0x001000a0>, /* PM8110 */
-					 <0x005000a2>, /* INTERRUPT */
-					 <0x006000a3>, /* SPMI_0 */
-					 <0x00800000>, /* PON0 */
-					 <0x01000002>, /* SMBB_CHG */
-					 <0x01100003>, /* SMBB_BUCK */
-					 <0x01200004>, /* SMBB_BIF */
-					 <0x01300005>, /* SMBB_USB */
-					 <0x01500006>, /* SMBB_BOOST */
-					 <0x01600007>, /* SMBB_MISC */
-					 <0x0280000a>, /* COINCELL */
-					 <0x02c000a5>, /* MBG */
-					 <0x0310000b>, /* VADC1_LC_USR */
-					 <0x03200041>, /* VADC3_LC_MDM */
-					 <0x0330000c>, /* VADC3_LC_BMS */
-					 <0x0340000d>, /* VADC2_LC_BTM */
-					 <0x0360000e>, /* IADC1_USR */
-					 <0x03700042>, /* IADC2_MDM */
-					 <0x0380000f>, /* IADC2_BMS */
-					 <0x04000010>, /* BMS_1 */
-					 <0x050000a6>, /* SHARED_XO */
-					 <0x051000a7>, /* BB_CLK1 */
-					 <0x054000a8>, /* RF_CLK1 */
-					 <0x055000a9>, /* RF_CLK1 */
-					 <0x05a000ab>, /* SLEEP_CLK */
-					 <0x06000043>, /* RTC_RW */
-					 <0x06100011>, /* RTC_ALARM */
-					 <0x070000ac>, /* PBS_CORE */
-					 <0x071000ad>, /* PBS_CLIENT_1 */
-					 <0x072000ae>, /* PBS_CLIENT_2 */
-					 <0x07300013>, /* PBS_CLIENT_3 */
-					 <0x07400044>, /* PBS_CLIENT_4 */
-					 <0x0a000014>, /* MPP_1 */
-					 <0x0a100015>, /* MPP_2 */
-					 <0x0a200016>, /* MPP_3 */
-					 <0x0a300045>, /* MPP_4 */
-					 <0x0c000046>, /* GPIO_1 */
-					 <0x0c1000f0>, /* GPIO_2 */
-					 <0x0c2000af>, /* GPIO_3 */
-					 <0x0c300047>, /* GPIO_4 */
-					 <0x0fe000b0>, /* TRIM_0 */
-					 <0x110000b1>, /* BUCK_CMN_1 */
-					 <0x11400048>, /* SMPS1 */
-					 <0x115000b2>, /* SMPS_1_PS1 */
-					 <0x116000b3>, /* BUCK_FREQ_1 */
-					 <0x11700017>, /* SMPS2 */
-					 <0x11800018>, /* FTPS1_2 */
-					 <0x11900019>, /* BUCK_FREQ_2 */
-					 <0x11a000b4>, /* SMPS3 */
-					 <0x11b000b5>, /* SMPS_3_PS1 */
-					 <0x11c000b6>, /* BUCK_FREQ_3 */
-					 <0x11d000b7>, /* SMPS4 */
-					 <0x11e000b8>, /* SMPS_4_PS1 */
-					 <0x11f000b9>, /* BUCK_FREQ_4 */
-					 <0x140000ba>, /* LDO_1 */
-					 <0x141000bb>, /* LDO_2 */
-					 <0x142000bc>, /* LDO_3 */
-					 <0x143000bd>, /* LDO_4 */
-					 <0x144000be>, /* LDO_5 */
-					 <0x145000bf>, /* LDO_6 */
-					 <0x146000c0>, /* LDO_7 */
-					 <0x147000c1>, /* LDO_8 */
-					 <0x148000c2>, /* LDO_9 */
-					 <0x149000c3>, /* LDO_10 */
-					 <0x14a000c4>, /* LDO_11 */
-					 <0x14b000c5>, /* LDO_12 */
-					 <0x14c000c6>, /* LDO_13 */
-					 <0x14d000c7>, /* LDO_14 */
-					 <0x14e000c8>, /* LDO_15 */
-					 <0x14f000c9>, /* LDO_16 */
-					 <0x150000ca>, /* LDO_17 */
-					 <0x151000cb>, /* LDO_18 */
-					 <0x152000cc>, /* LDO_19 */
-					 <0x153000cd>, /* LDO_20 */
-					 <0x154000ce>, /* LDO_21 */
-					 <0x155000cf>; /* LDO_22 */
+	};
+
+	i2c@f9925000 { /* BLSP-1 QUP-3 */
+		cell-index = <0>;
+		compatible = "qcom,i2c-qup";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0xf9925000 0x1000>;
+		interrupt-names = "qup_err_intr";
+		interrupts = <0 97 0>;
+		qcom,i2c-bus-freq = <100000>;
+	};
+
+	qcom,pronto@fb21b000 {
+		compatible = "qcom,pil-pronto";
+		reg = <0xfb21b000 0x3000>,
+		      <0xfc401700 0x4>,
+		      <0xfd485300 0xc>;
+		reg-names = "pmu_base", "clk_base", "halt_base";
+		interrupts = <0 149 1>;
+		vdd_pronto_pll-supply = <&pm8110_l10>;
+
+		qcom,firmware-name = "wcnss";
+	};
+
+	sound {
+		compatible = "qcom,msm8x10-audio-codec";
+		qcom,model = "msm8x10-snd-card";
+	};
+
+	qcom,msm-pcm {
+		compatible = "qcom,msm-pcm-dsp";
+	};
+
+	qcom,msm-pcm-routing {
+		compatible = "qcom,msm-pcm-routing";
+	};
+
+	qcom,msm-pcm-lpa {
+		compatible = "qcom,msm-pcm-lpa";
+	};
+
+	qcom,msm-compr-dsp {
+		compatible = "qcom,msm-compr-dsp";
+	};
+
+	qcom,msm-voip-dsp {
+		compatible = "qcom,msm-voip-dsp";
+	};
+
+	qcom,msm-pcm-voice {
+		compatible = "qcom,msm-pcm-voice";
+	};
+
+	qcom,msm-stub-codec {
+		compatible = "qcom,msm-stub-codec";
+	};
+
+	qcom,msm-dai-fe {
+		compatible = "qcom,msm-dai-fe";
+	};
+
+	qcom,msm-pcm-afe {
+		compatible = "qcom,msm-pcm-afe";
+	};
+
+	qcom,msm-dai-mi2s {
+		compatible = "qcom,msm-dai-mi2s";
+		qcom,msm-dai-q6-mi2s-prim {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <0>;
+			qcom,msm-mi2s-rx-lines = <1>;
+			qcom,msm-mi2s-tx-lines = <0>;
+		};
+
+		qcom,msm-dai-q6-mi2s-sec {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <1>;
+			qcom,msm-mi2s-rx-lines = <0>;
+			qcom,msm-mi2s-tx-lines = <3>;
+		};
+	};
+
+	qcom,msm-dai-q6 {
+		compatible = "qcom,msm-dai-q6";
+		qcom,msm-dai-q6-bt-sco-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12288>;
+		};
+
+		qcom,msm-dai-q6-bt-sco-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12289>;
+		};
+
+		qcom,msm-dai-q6-int-fm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12292>;
+		};
+
+		qcom,msm-dai-q6-int-fm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12293>;
+		};
+
+		qcom,msm-dai-q6-be-afe-pcm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <224>;
+		};
+
+		qcom,msm-dai-q6-be-afe-pcm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <225>;
+		};
+
+		qcom,msm-dai-q6-afe-proxy-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <241>;
+		};
+
+		qcom,msm-dai-q6-afe-proxy-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <240>;
+		};
+	};
+
+	qcom,msm-pcm-hostless {
+		compatible = "qcom,msm-pcm-hostless";
 	};
 
 	qcom,lpass@fe200000 {
@@ -337,7 +406,7 @@
 		      <0xfd485100 0x00010>;
 		reg-names = "qdsp6_base", "halt_base";
 		interrupts = <0 162 1>;
-
+		vdd_cx-supply = <&pm8110_s1_corner>;
 		qcom,firmware-name = "adsp";
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
new file mode 100644
index 0000000..ba4a14e8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -0,0 +1,1403 @@
+/* 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.
+ */
+
+/ {
+	msm-mmss-noc@fc478000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc478000 0x00004000>;
+		cell-id = <2048>;
+		label = "msm_mmss_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,qos-freq = <4800>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		coresight-id = <52>;
+		coresight-name = "coresight-mnoc";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <5>;
+
+		mas-gfx3d {
+			cell-id = <26>;
+			label = "mas-gfx3d";
+			qcom,masterp = <2 3>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,ws = <10000>;
+			qcom,qport = <2 3>;
+			qcom,mas-hw-id = <6>;
+		};
+
+		mas-jpeg {
+			cell-id = <62>;
+			label = "mas-jpeg";
+			qcom,masterp = <4>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,qport = <0>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <7>;
+		};
+
+		mas-mdp-port0 {
+			cell-id = <22>;
+			label = "mas-mdp-port0";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,qport = <1>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <8>;
+		};
+
+		mas-video-p0 {
+			cell-id = <63>;
+			label = "mas-video-p0";
+			qcom,masterp = <6 7>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,ws = <10000>;
+			qcom,qport = <4 5>;
+			qcom,mas-hw-id = <9>;
+		};
+
+		mas-vfe {
+			cell-id = <29>;
+			label = "mas-vfe";
+			qcom,masterp = <16>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,ws = <10000>;
+			qcom,qport = <6>;
+			qcom,mas-hw-id = <11>;
+		};
+
+		fab-cnoc {
+			cell-id = <5120>;
+			label = "fab-cnoc";
+			qcom,gateway;
+			qcom,masterp = <0 1>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "RPM";
+			qcom,mas-hw-id = <4>;
+		};
+
+		fab-bimc {
+			cell-id = <0>;
+			label = "fab-bimc";
+			qcom,gateway;
+			qcom,slavep = <16 17>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <16>;
+		};
+
+		slv-camera-cfg {
+			cell-id = <589>;
+			label = "slv-camera-cfg";
+			qcom,slavep = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <3>;
+		};
+
+		slv-display-cfg {
+			cell-id = <590>;
+			label = "slv-display-cfg";
+			qcom,slavep = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <4>;
+		};
+
+		slv-ocmem-cfg {
+			cell-id = <591>;
+			label = "slv-ocmem-cfg";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <5>;
+		};
+
+		slv-cpr-cfg {
+			cell-id = <592>;
+			label = "slv-cpr-cfg";
+			qcom,slavep = <3>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <6>;
+		};
+
+		slv-cpr-xpu-cfg {
+			cell-id = <593>;
+			label = "slv-cpr-xpu-cfg";
+			qcom,slavep = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <7>;
+		};
+
+		slv-misc-cfg {
+			cell-id = <594>;
+			label = "slv-misc-cfg";
+			qcom,slavep = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <8>;
+		};
+
+		slv-misc-xpu-cfg {
+			cell-id = <595>;
+			label = "slv-misc-xpu-cfg";
+			qcom,slavep = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <9>;
+		};
+
+		slv-venus-cfg {
+			cell-id = <596>;
+			label = "slv-venus-cfg";
+			qcom,slavep = <8>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <10>;
+		};
+
+		slv-gfx3d-cfg {
+			cell-id = <598>;
+			label = "slv-gfx3d-cfg";
+			qcom,slavep = <9>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <11>;
+		};
+
+		slv-mmss-clk-cfg {
+			cell-id = <599>;
+			label = "slv-mmss-clk-cfg";
+			qcom,slavep = <11>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <12>;
+		};
+
+		slv-mmss-clk-xpu-cfg {
+			cell-id = <600>;
+			label = "slv-mmss-clk-xpu-cfg";
+			qcom,slavep = <12>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <13>;
+		};
+
+		slv-mnoc-mpu-cfg {
+			cell-id = <601>;
+			label = "slv-mnoc-mpu-cfg";
+			qcom,slavep = <13>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <14>;
+		};
+
+		slv-onoc-mpu-cfg {
+			cell-id = <602>;
+			label = "slv-onoc-mpu-cfg";
+			qcom,slavep = <14>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <15>;
+		};
+
+		slv-service-mnoc {
+			cell-id = <603>;
+			label = "slv-service-mnoc";
+			qcom,slavep = <18>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <17>;
+		};
+
+	};
+
+	msm-sys-noc@fc460000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc460000 0x00004000>;
+		cell-id = <1024>;
+		label = "msm_sys_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,qos-freq = <4800>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		coresight-id = <50>;
+		coresight-name = "coresight-snoc";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <3>;
+
+		msm-lpass-ahb {
+			cell-id = <52>;
+			label = "mas-lpass-ahb";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,qport = <0>;
+			qcom,mas-hw-id = <18>;
+			qcom,mode = "Fixed";
+			qcom,prio-rd = <2>;
+			qcom,prio-wr = <2>;
+		};
+
+		mas-qdss-bam {
+			cell-id = <53>;
+			label = "mas-qdss-bam";
+			qcom,masterp = <1>;
+			qcom,tier = <2>;
+			qcom,mode = "Fixed";
+			qcom,qport = <1>;
+			qcom,mas-hw-id = <19>;
+		};
+
+		mas-snoc-cfg {
+			cell-id = <54>;
+			label = "mas-snoc-cfg";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <20>;
+		};
+
+		fab-bimc {
+			cell-id = <0>;
+			label= "fab-bimc";
+			qcom,gateway;
+			qcom,slavep = <7 8>;
+			qcom,masterp = <3>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <21>;
+			qcom,slv-hw-id = <24>;
+		};
+
+		fab-cnoc {
+			cell-id = <5120>;
+			label = "fab-cnoc";
+			qcom,gateway;
+			qcom,slavep = <9>;
+			qcom,masterp = <4>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <22>;
+			qcom,slv-hw-id = <25>;
+		};
+
+		fab-pnoc {
+			cell-id = <4096>;
+			label = "fab-pnoc";
+			qcom,gateway;
+			qcom,slavep = <12>;
+			qcom,masterp = <11>;
+			qcom,buswidth = <8>;
+			qcom,qport = <8>;
+			qcom,mas-hw-id = <29>;
+			qcom,slv-hw-id = <28>;
+			qcom,mode = "Fixed";
+			qcom,prio-rd = <2>;
+			qcom,prio-wr = <2>;
+		};
+
+		fab-ovnoc {
+			cell-id = <6144>;
+			label = "fab-ovnoc";
+			qcom,gateway;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <53>;
+			qcom,slv-hw-id = <77>;
+		};
+
+		mas-crypto-core0 {
+			cell-id = <55>;
+			label = "mas-crypto-core0";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,mode = "Fixed";
+			qcom,qport = <2>;
+			qcom,mas-hw-id = <23>;
+			qcom,hw-sel = "NoC";
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+		};
+
+		mas-crypto-core1 {
+			cell-id = <56>;
+			label = "mas-crypto-core1";
+			qcom,masterp = <6>;
+			qcom,tier = <2>;
+			qcom,mode = "Fixed";
+			qcom,qport = <3>;
+			qcom,mas-hw-id = <24>;
+			qcom,hw-sel = "NoC";
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+		};
+
+		mas-lpass-proc {
+			cell-id = <11>;
+			label = "mas-lpass-proc";
+			qcom,masterp = <7>;
+			qcom,tier = <2>;
+			qcom,qport = <4>;
+			qcom,mas-hw-id = <25>;
+			qcom,mode = "Fixed";
+			qcom,prio-rd = <2>;
+			qcom,prio-wr = <2>;
+		};
+
+		mas-mss {
+			cell-id = <38>;
+			label = "mas-mss";
+			qcom,masterp = <8>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <26>;
+		};
+
+		mas-mss-nav {
+			cell-id = <57>;
+			label = "mas-mss-nav";
+			qcom,masterp = <9>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <27>;
+		};
+
+		mas-ocmem-dma {
+			cell-id = <58>;
+			label = "mas-ocmem-dma";
+			qcom,masterp = <10>;
+			qcom,tier = <2>;
+			qcom,mode = "Fixed";
+			qcom,qport = <7>;
+			qcom,mas-hw-id = <28>;
+		};
+
+		mas-wcss {
+			cell-id = <59>;
+			label = "mas-wcss";
+			qcom,masterp = <12>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <30>;
+		};
+
+		mas-qdss-etr {
+			cell-id = <60>;
+			label = "mas-qdss-etr";
+			qcom,masterp = <13>;
+			qcom,tier = <2>;
+			qcom,qport = <10>;
+			qcom,mode = "Fixed";
+			qcom,mas-hw-id = <31>;
+		};
+
+		mas-usb3 {
+			cell-id = <61>;
+			label = "mas-usb3";
+			qcom,masterp = <14>;
+			qcom,tier = <2>;
+			qcom,mode = "Fixed";
+			qcom,qport = <11>;
+			qcom,mas-hw-id = <32>;
+			qcom,prio-rd = <2>;
+			qcom,prio-wr = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,iface-clk-node = "msm_usb3";
+		};
+
+		slv-ampss {
+			cell-id = <520>;
+			label = "slv-ampss";
+			qcom,slavep = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <20>;
+		};
+
+		slv-lpass {
+			cell-id = <522>;
+			label = "slv-lpass";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <21>;
+		};
+
+		slv-usb3 {
+			cell-id = <583>;
+			label = "slv-usb3";
+			qcom,slavep = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <22>;
+		};
+
+		slv-wcss {
+			cell-id = <584>;
+			label = "slv-wcss";
+			qcom,slavep = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <23>;
+		};
+
+		slv-ocimem {
+			cell-id = <585>;
+			label = "slv-ocimem";
+			qcom,slavep = <10>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <26>;
+		};
+
+		slv-snoc-ocmem {
+			cell-id = <586>;
+			label = "slv-snoc-ocmem";
+			qcom,slavep = <11>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <27>;
+		};
+
+		slv-service-snoc {
+			cell-id = <587>;
+			label = "slv-service-snoc";
+			qcom,slavep = <13>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <29>;
+		};
+
+		slv-qdss-stm {
+			cell-id = <588>;
+			label = "slv-qdss-stm";
+			qcom,slavep = <14>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <30>;
+		};
+
+	};
+
+	msm-periph-noc@fc468000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc468000 0x00004000>;
+		cell-id = <4096>;
+		label = "msm_periph_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		coresight-id = <54>;
+		coresight-name = "coresight-pnoc";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <6>;
+
+		mas-pnoc-cfg {
+			cell-id = <88>;
+			label = "mas-pnoc-cfg";
+			qcom,masterp = <10>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <43>;
+		};
+
+		mas-sdcc-1 {
+			cell-id = <78>;
+			label = "mas-sdcc-1";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <33>;
+		};
+
+		mas-sdcc-3 {
+			cell-id = <79>;
+			label = "mas-sdcc-3";
+			qcom,masterp = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <34>;
+		};
+
+		mas-sdcc-4 {
+			cell-id = <80>;
+			label = "mas-sdcc-4";
+			qcom,masterp = <3>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <36>;
+		};
+
+		mas-sdcc-2 {
+			cell-id = <81>;
+			label = "mas-sdcc-2";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <35>;
+		};
+
+		mas-tsif {
+			cell-id = <82>;
+			label = "mas-tsif";
+			qcom,masterp = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <37>;
+		};
+
+		mas-bam-dma {
+			cell-id = <83>;
+			label = "mas-bam-dma";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <38>;
+		};
+
+		mas-blsp-2 {
+			cell-id = <84>;
+			label = "mas-blsp-2";
+			qcom,masterp = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <39>;
+		};
+
+		mas-usb-hsic {
+			cell-id = <85>;
+			label = "mas-usb-hsic";
+			qcom,masterp = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <40>;
+		};
+
+		mas-blsp-1 {
+			cell-id = <86>;
+			label = "mas-blsp-1";
+			qcom,masterp = <8>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <41>;
+		};
+
+		mas-usb-hs {
+			cell-id = <87>;
+			label = "mas-usb-hs";
+			qcom,masterp = <9>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <42>;
+		};
+
+		fab-snoc {
+			cell-id = <1024>;
+			label = "fab-snoc";
+			qcom,gateway;
+			qcom,slavep = <14>;
+			qcom,masterp = <11>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <45>;
+			qcom,mas-hw-id = <44>;
+		};
+
+		slv-sdcc-1 {
+			cell-id = <606>;
+			label = "slv-sdcc-1";
+			qcom,slavep = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <31>;
+		};
+
+		slv-sdcc-3 {
+			cell-id = <607>;
+			label = "slv-sdcc-3";
+			qcom,slavep = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <32>;
+		};
+
+		slv-sdcc-2 {
+			cell-id = <608>;
+			label = "slv-sdcc-2";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <33>;
+		};
+
+		slv-sdcc-4 {
+			cell-id = <609>;
+			label = "slv-sdcc-4";
+			qcom,slavep = <3>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <34>;
+		};
+
+		slv-tsif {
+			cell-id = <575>;
+			label = "slv-tsif";
+			qcom,slavep = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <35>;
+		};
+
+		slv-bam-dma {
+			cell-id = <610>;
+			label = "slv-bam-dma";
+			qcom,slavep = <5>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <36>;
+		};
+
+		slv-blsp-2 {
+			cell-id = <611>;
+			label = "slv-blsp-2";
+			qcom,slavep = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <37>;
+		};
+
+		slv-usb-hsic {
+			cell-id = <612>;
+			label = "slv-usb-hsic";
+			qcom,slavep = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <38>;
+		};
+
+		slv-blsp-1 {
+			cell-id = <613>;
+			label = "slv-blsp-1";
+			qcom,slavep = <8>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <39>;
+		};
+
+		slv-usb-hs {
+			cell-id = <614>;
+			label = "slv-usb-hs";
+			qcom,slavep = <9>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <40>;
+		};
+
+		slv-pdm	{
+			cell-id = <615>;
+			label = "slv-pdm";
+			qcom,slavep = <10>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <41>;
+		};
+
+		slv-periph-apu-cfg {
+			cell-id = <616>;
+			label = "slv-periph-apu-cfg";
+			qcom,slavep = <11>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <42>;
+		};
+
+		slv-pnoc-mpu-cfg {
+			cell-id = <617>;
+			label = "slv-pnoc-mpu-cfg";
+			qcom,slavep = <12>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <43>;
+		};
+
+		slv-prng {
+			cell-id = <618>;
+			label = "slv-prng";
+			qcom,slavep = <13>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <44>;
+		};
+
+		slv-service-pnoc {
+			cell-id = <619>;
+			label = "slv-service-pnoc";
+			qcom,slavep = <15>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <46>;
+		};
+
+	};
+
+	msm-config-noc@fc480000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc480000 0x00004000>;
+		cell-id = <5120>;
+		label = "msm_config_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		mas-rpm-inst {
+			cell-id = <72>;
+			label = "mas-rpm-inst";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <45>;
+		};
+
+		mas-rpm-data {
+			cell-id = <73>;
+			label = "mas-rpm-data";
+			qcom,masterp = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <46>;
+		};
+
+		mas-rpm-sys {
+			cell-id = <74>;
+			label = "mas-rpm-sys";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <47>;
+		};
+
+		mas-dehr {
+			cell-id = <75>;
+			label = "mas-dehr";
+			qcom,masterp = <3>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <48>;
+		};
+
+		mas-qdss-dsp {
+			cell-id = <76>;
+			label = "mas-qdss-dap";
+			qcom,masterp = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <49>;
+		};
+
+		mas-spdm {
+			cell-id = <36>;
+			label = "mas-spdm";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <50>;
+		};
+
+		mas-tic	{
+			cell-id = <77>;
+			label = "mas-tic";
+			qcom,masterp = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <51>;
+		};
+
+		slv-clk-ctl {
+			cell-id = <620>;
+			label = "slv-clk-ctl";
+			qcom,slavep = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <47>;
+		};
+
+		slv-cnoc-mss {
+			cell-id = <621>;
+			label = "slv-cnoc-mss";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <48>;
+		};
+
+		slv-security {
+			cell-id = <622>;
+			label = "slv-security";
+			qcom,slavep = <3>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <49>;
+		};
+
+		slv-tcsr {
+			cell-id = <623>;
+			label = "slv-tcsr";
+			qcom,slavep = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <50>;
+		};
+
+		slv-tlmm {
+			cell-id = <624>;
+			label = "slv-tlmm";
+			qcom,slavep = <5>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <51>;
+		};
+
+		slv-crypto-0-cfg {
+			cell-id = <625>;
+			label = "slv-crypto-0-cfg";
+			qcom,slavep = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <52>;
+		};
+
+		slv-crypto-1-cfg {
+			cell-id = <626>;
+			label = "slv-crypto-1-cfg";
+			qcom,slavep = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <53>;
+		};
+
+		slv-imem-cfg {
+			cell-id = <627>;
+			label = "slv-imem-cfg";
+			qcom,slavep = <8>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <54>;
+		};
+
+		slv-message-ram	{
+			cell-id = <628>;
+			label = "slv-message-ram";
+			qcom,slavep = <9>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <55>;
+		};
+
+		slv-bimc-cfg {
+			cell-id = <629>;
+			label = "slv-bimc-cfg";
+			qcom,slavep = <10>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <56>;
+		};
+
+		slv-boot-rom {
+			cell-id = <630>;
+			label = "slv-boot-rom";
+			qcom,slavep = <11>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <57>;
+		};
+
+		slv-pmic-arb {
+			cell-id = <632>;
+			label = "slv-pmic-arb";
+			qcom,slavep = <13>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <59>;
+		};
+
+		slv-spdm-wrapper {
+			cell-id = <633>;
+			label = "slv-spdm-wrapper";
+			qcom,slavep = <14>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <60>;
+		};
+
+		slv-dehr-cfg {
+			cell-id = <634>;
+			label = "slv-dehr-cfg";
+			qcom,slavep = <15>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <61>;
+		};
+
+		slv-mpm	{
+			cell-id = <536>;
+			label = "slv-mpm";
+			qcom,slavep = <16>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <62>;
+		};
+
+		slv-qdss-cfg {
+			cell-id = <635>;
+			label = "slv-qdss-cfg";
+			qcom,slavep = <17>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <63>;
+		};
+
+		slv-rbcpr-cfg {
+			cell-id = <636>;
+			label = "slv-rbcpr-cfg";
+			qcom,slavep = <18>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <64>;
+		};
+
+		slv-rbcpr-qdss-apu-cfg {
+			cell-id = <637>;
+			label = "slv-rbcpr-qdss-apu-cfg";
+			qcom,slavep = <19>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <65>;
+		};
+
+		fab-snoc {
+			cell-id = <1024>;
+			label = "fab-snoc";
+			qcom,gateway;
+			qcom,slavep = <29>;
+			qcom,masterp = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <52>;
+			qcom,slv-hw-id = <75>;
+		};
+
+		slv-cnoc-onoc-cfg {
+			cell-id = <639>;
+			label = "slv-cnoc-onoc-cfg";
+			qcom,slavep = <22>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <68>;
+		};
+
+		slv-cnoc-mnoc-mmss-cfg {
+			cell-id = <631>;
+			label = "slv-cnoc-mnoc-mmss-cfg";
+			qcom,slavep = <12>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <58>;
+		};
+
+		slv-cnoc-mnoc-cfg {
+			cell-id = <640>;
+			label = "slv-cnoc-mnoc-cfg";
+			qcom,slavep = <20>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <66>;
+		};
+
+		slv-pnoc-cfg {
+			cell-id = <641>;
+			label = "slv-pnoc-cfg";
+			qcom,slavep = <23>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <69>;
+		};
+
+		slv-snoc-mpu-cfg {
+			cell-id = <638>;
+			label = "slv-snoc-mpu-cfg";
+			qcom,slavep = <21>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <67>;
+		};
+
+		slv-snoc-cfg {
+			cell-id = <642>;
+			label = "slv-snoc-cfg";
+			qcom,slavep = <24>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <70>;
+		};
+
+		slv-ebi1-dll-cfg {
+			cell-id = <643>;
+			label = "slv-ebi1-dll-cfg";
+			qcom,slavep = <25>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <71>;
+		};
+
+		slv-phy-apu-cfg {
+			cell-id = <644>;
+			label = "slv-phy-apu-cfg";
+			qcom,slavep = <26>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <72>;
+		};
+
+		slv-ebi1-phy-cfg {
+			cell-id = <645>;
+			label = "slv-ebi1-phy-cfg";
+			qcom,slavep = <27>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <73>;
+		};
+
+		slv-rpm {
+			cell-id = <534>;
+			label = "slv-rpm";
+			qcom,slavep = <28>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <74>;
+		};
+
+		slv-service-cnoc {
+			cell-id = <646>;
+			label = "slv-service-cnoc";
+			qcom,slavep = <30>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <76>;
+		};
+
+	};
+
+	msm-bimc@0xfc380000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc380000 0x0006A000>;
+		cell-id = <0>;
+		label = "msm_bimc";
+		qcom,fabclk-dual = "mem_clk";
+		qcom,fabclk-active = "mem_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,qos-freq = <4800>;
+		qcom,hw-sel = "BIMC";
+		qcom,rpm-en;
+
+		coresight-id = <55>;
+		coresight-name = "coresight-bimc";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <3>;
+
+		mas-ampss-m0 {
+			cell-id = <1>;
+			label = "mas-ampss-m0";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "BIMC";
+			qcom,mode = "Fixed";
+			qcom,qport = <0>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <0>;
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+		};
+
+		mas-ampss-m1 {
+			cell-id = <2>;
+			label = "mas-ampss-m1";
+			qcom,masterp = <1>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "BIMC";
+			qcom,mode = "Fixed";
+			qcom,qport = <1>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <0>;
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+		};
+
+		mas-mss-proc {
+			cell-id = <65>;
+			label = "mas-mss-proc";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "RPM";
+			qcom,mas-hw-id = <1>;
+		};
+
+		fab-mmss-noc {
+			cell-id = <2048>;
+			label = "fab_mmss_noc";
+			qcom,gateway;
+			qcom,masterp = <3 4>;
+			qcom,qport = <3 4>;
+			qcom,buswidth = <8>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <2>;
+			qcom,hw-sel = "BIMC";
+			qcom,mode = "Bypass";
+		};
+
+		fab-snoc {
+			cell-id = <1024>;
+			label = "fab-snoc";
+			qcom,gateway;
+			qcom,slavep = <3>;
+			qcom,masterp = <5 6>;
+			qcom,qport = <5 6>;
+			qcom,buswidth = <8>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <3>;
+			qcom,slv-hw-id = <2>;
+		};
+
+		slv-ebi-ch0 {
+			cell-id = <512>;
+			label = "slv-ebi-ch0";
+			qcom,slavep = <0 1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <0>;
+			qcom,mode = "Bypass";
+		};
+
+		slv-ampss-l2 {
+			cell-id = <514>;
+			label = "slv-ampss-l2";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <1>;
+		};
+	};
+
+	msm-ocmem-vnoc@6144 {
+		compatible = "msm-bus-fabric";
+		reg = <0x6144 0x2>;
+		cell-id = <6144>;
+		label = "msm-ocmem-vnoc";
+		qcom,ntieredslaves = <0>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+		qcom,virt;
+
+		mas-v-ocmem-gfx3d {
+			cell-id = <89>;
+			label = "mas-v-ocmem-gfx3d";
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <55>;
+		};
+
+		slv-ocmem {
+			cell-id = <604>;
+			label = "slv-ocmem";
+			qcom,slavep = <0 1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,slv-hw-id = <18>;
+			qcom,slaveclk-dual = "ocmem_clk";
+			qcom,slaveclk-active = "ocmem_a_clk";
+		};
+
+		fab-snoc {
+			cell-id = <1024>;
+			label = "fab-snoc";
+			qcom,gateway;
+			qcom,buswidth = <8>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <57>;
+			qcom,slv-hw-id = <80>;
+		};
+
+		fab-onoc {
+			cell-id = <3072>;
+			label = "fab-onoc";
+			qcom,gateway;
+			qcom,buswidth = <16>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <56>;
+			qcom,slv-hw-id = <79>;
+		};
+
+	};
+
+	msm-ocmem-noc@fc470000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc470000 0x00004000>;
+		cell-id = <3072>;
+		label = "msm_ocmem_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,qos-freq = <4800>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		coresight-id = <51>;
+		coresight-name = "coresight-onoc";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <4>;
+
+		fab-ocmem-vnoc	{
+			cell-id = <6144>;
+			label = "fab-ocmem-vnoc";
+			qcom,gateway;
+			qcom,buswidth = <16>;
+			qcom,mas-hw-id = <54>;
+			qcom,slv-hw-id = <78>;
+		};
+
+		mas-jpeg-ocmem	{
+			cell-id = <66>;
+			label = "mas-jpeg-ocmem";
+			qcom,masterp = <1>;
+			qcom,tier = <2>;
+			qcom,perm-mode = "Fixed";
+			qcom,mode = "Fixed";
+			qcom,qport = <0>;
+			qcom,mas-hw-id = <13>;
+			qcom,hw-sel = "NoC";
+		};
+
+		mas-mdp-ocmem {
+			cell-id = <67>;
+			label = "mas-mdp-ocmem";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,perm-mode = "Fixed";
+			qcom,mode = "Fixed";
+			qcom,mas-hw-id = <14>;
+			qcom,hw-sel = "NoC";
+		};
+
+		mas-video-p0-ocmem {
+			cell-id = <68>;
+			label = "mas-video-p0-ocmem";
+			qcom,masterp = <3>;
+			qcom,tier = <2>;
+			qcom,perm-mode = "Fixed";
+			qcom,mode = "Fixed";
+			qcom,qport = <2>;
+			qcom,mas-hw-id = <15>;
+			qcom,hw-sel = "NoC";
+		};
+
+		mas-video-p1-ocmem {
+			cell-id = <69>;
+			label = "mas-video-p1-ocmem";
+			qcom,masterp = <4>;
+			qcom,tier = <2>;
+			qcom,perm-mode = "Fixed";
+			qcom,mode = "Fixed";
+			qcom,qport = <3>;
+			qcom,mas-hw-id = <16>;
+			qcom,hw-sel = "NoC";
+		};
+
+		mas-vfe-ocmem {
+			cell-id = <70>;
+			label = "mas-vfe-ocmem";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,perm-mode = "Fixed";
+			qcom,mode = "Fixed";
+			qcom,qport = <4>;
+			qcom,mas-hw-id = <17>;
+			qcom,hw-sel = "NoC";
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+		};
+
+		mas-cnoc-onoc-cfg {
+			cell-id = <71>;
+			label = "mas-cnoc-onoc-cfg";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,mas-hw-id = <12>;
+			qcom,hw-sel = "NoC";
+		};
+
+		slv-service-onoc {
+			cell-id = <605>;
+			label = "slv-service-onoc";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,slv-hw-id = <19>;
+		};
+	};
+};
+
+
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
new file mode 100644
index 0000000..51c6712
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+&cci {
+
+	qcom,camera@6e {
+		compatible = "qcom,s5k3l1yx";
+		reg = <0x6e>;
+		qcom,slave-id = <0x6e 0x0 0x3121>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,flash-src-index = <&led_flash0>;
+		qcom,actuator-src = <&actuator0>;
+		qcom,mount-angle = <270>;
+		qcom,sensor-name = "s5k3l1yx";
+		cam_vdig-supply = <&pm8941_l3>;
+		cam_vana-supply = <&pm8941_l17>;
+		cam_vio-supply = <&pm8941_lvs3>;
+		cam_vaf-supply = <&pm8941_l23>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+				     "cam_vaf";
+		qcom,cam-vreg-type = <0 1 0 0>;
+		qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 15 0>,
+			<&msmgpio 90 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-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 30000>;
+		qcom,csi-lane-assign = <0x4320>;
+		qcom,csi-lane-mask = <0x1F>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
+
+	qcom,camera@6c {
+		compatible = "qcom,ov2720";
+		reg = <0x6c>;
+		qcom,slave-id = <0x6c 0x300A 0x2720>;
+		qcom,led-flash-sd-index = <0>;
+		qcom,csiphy-sd-index = <2>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "ov2720";
+		cam_vdig-supply = <&pm8941_l3>;
+		cam_vana-supply = <&pm8941_l17>;
+		cam_vio-supply = <&pm8941_lvs3>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio";
+		qcom,cam-vreg-type = <0 0 1>;
+		qcom,cam-vreg-min-voltage = <1225000 2850000 0>;
+		qcom,cam-vreg-max-voltage = <1225000 2850000 0>;
+		qcom,cam-vreg-op-mode = <105000 80000 0>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 17 0>,
+			<&msmgpio 18 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-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 4000>;
+		qcom,csi-lane-assign = <0x4320>;
+		qcom,csi-lane-mask = <0x7>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <1>;
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index 7035bb4..dd85b3c 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -48,6 +48,7 @@
 		qcom,csi-lane-mask = <0x1F>;
 		qcom,sensor-position = <0>;
 		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
 		status = "ok";
 	};
 
@@ -83,6 +84,7 @@
 		qcom,csi-lane-mask = <0x7>;
 		qcom,sensor-position = <1>;
 		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
 		status = "ok";
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor.dtsi
index 948cdf5..85b90c2 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor.dtsi
@@ -20,6 +20,7 @@
 		qcom,csiphy-sd-index = <0>;
 		qcom,csid-sd-index = <0>;
 		qcom,flash-src-index = <&led_flash0>;
+		qcom,actuator-src = <&actuator0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "s5k3l1yx";
 		cam_vdig-supply = <&pm8941_l3>;
@@ -47,6 +48,7 @@
 		qcom,csi-lane-mask = <0x1F>;
 		qcom,sensor-position = <0>;
 		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
 		status = "ok";
 	};
 
@@ -57,7 +59,7 @@
 		qcom,led-flash-sd-index = <0>;
 		qcom,csiphy-sd-index = <2>;
 		qcom,csid-sd-index = <0>;
-		qcom,mount-angle = <180>;
+		qcom,mount-angle = <90>;
 		qcom,sensor-name = "ov2720";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
@@ -82,6 +84,7 @@
 		qcom,csi-lane-mask = <0x7>;
 		qcom,sensor-position = <1>;
 		qcom,sensor-mode = <1>;
+		qcom,cci-master = <1>;
 		status = "ok";
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 6002f85..a550c0b 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -203,6 +203,13 @@
 		qcom,hw-trdhld = <6>;
 		qcom,hw-tsp = <1>;
 
+		actuator0: qcom,actuator@18 {
+			cell-index = <0>;
+			reg = <0x18 0x0>;
+			compatible = "qcom,actuator";
+			qcom,cci-master = <0>;
+		};
+
 		qcom,camera@6e {
 			status = "disable";
 		};
@@ -242,6 +249,7 @@
 			qcom,csi-lane-mask = <0x3>;
 			qcom,sensor-position = <1>;
 			qcom,sensor-mode = <1>;
+			qcom,cci-master = <0>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 06bab30..6b902d7 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -11,6 +11,7 @@
  */
 
 /include/ "dsi-panel-toshiba-720p-video.dtsi"
+/include/ "dsi-panel-orise-720p-video.dtsi"
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor.dtsi"
 
@@ -19,10 +20,12 @@
 		status = "ok";
 	};
 
-	qcom,mdss_dsi@fd922800 {
-		qcom,mdss_dsi_toshiba_720p_video {
-			status = "ok";
-		};
+	qcom,mdss_dsi_toshiba_720p_video {
+		status = "ok";
+	};
+
+	qcom,mdss_dsi_orise_720p_video {
+		status = "disable";
 	};
 
 	qcom,hdmi_tx@fd922100 {
@@ -107,6 +110,16 @@
 		};
 	};
 
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "atmel_mxt_ts";
+		qcom,disp-maxx = <720>;
+		qcom,disp-maxy = <1280>;
+		qcom,panel-maxx = <760>;
+		qcom,panel-maxy = <1424>;
+		qcom,key-codes = <158 139 102 217>;
+	};
+
 	i2c@f9967000 {
 		isa1200@48 {
 			status = "okay";
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index 6bb7b28..427ef0b 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -141,7 +141,9 @@
 		coresight-outports = <0>;
 		coresight-child-list = <&funnel_kpss>;
 		coresight-child-ports = <0>;
+
 		qcom,pc-save;
+		qcom,round-robin;
 	};
 
 	etm1: etm@fc33d000 {
@@ -154,7 +156,9 @@
 		coresight-outports = <0>;
 		coresight-child-list = <&funnel_kpss>;
 		coresight-child-ports = <1>;
+
 		qcom,pc-save;
+		qcom,round-robin;
 	};
 
 	etm2: etm@fc33e000 {
@@ -167,7 +171,9 @@
 		coresight-outports = <0>;
 		coresight-child-list = <&funnel_kpss>;
 		coresight-child-ports = <2>;
+
 		qcom,pc-save;
+		qcom,round-robin;
 	};
 
 	etm3: etm@fc33f000 {
@@ -180,7 +186,9 @@
 		coresight-outports = <0>;
 		coresight-child-list = <&funnel_kpss>;
 		coresight-child-ports = <3>;
+
 		qcom,pc-save;
+		qcom,round-robin;
 	};
 
 	csr: csr@fc302000 {
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 2e18dfa..a6086f0 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -11,7 +11,7 @@
  */
 
 /include/ "dsi-panel-toshiba-720p-video.dtsi"
-/include/ "msm8974-camera-sensor.dtsi"
+/include/ "msm8974-camera-sensor-fluid.dtsi"
 /include/ "msm8974-leds.dtsi"
 
 / {
@@ -19,10 +19,8 @@
 		status = "ok";
 	};
 
-	qcom,mdss_dsi@fd922800 {
-		qcom,mdss_dsi_toshiba_720p_video {
-			status = "ok";
-		};
+	qcom,mdss_dsi_toshiba_720p_video {
+		status = "ok";
 	};
 
 	qcom,hdmi_tx@fd922100 {
@@ -120,6 +118,7 @@
 			avcc_12-supply = <&pm8941_l2>;
 			smps3a-supply = <&pm8941_s3>;
 			vdda-supply = <&pm8941_l12>;
+			qcom,hdmi-tx-map = <&mdss_hdmi_tx>;
 		};
 
 		isa1200@48 {
@@ -144,6 +143,16 @@
 		};
 	};
 
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "atmel_mxt_ts";
+		qcom,disp-maxx = <720>;
+		qcom,disp-maxy = <1280>;
+		qcom,panel-maxx = <760>;
+		qcom,panel-maxy = <1424>;
+		qcom,key-codes = <158 139 102 217>;
+	};
+
 	gpio_keys {
 		compatible = "gpio-keys";
 		input-name = "gpio-keys";
@@ -282,6 +291,10 @@
 	qcom,otg-capability;
 };
 
+&pm8941_bms {
+	status = "ok";
+};
+
 &pm8941_chg {
 	status = "ok";
 
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index 480a034..2751d76 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 / {
-	qcom,kgsl-3d0@fdb00000 {
+	msm_gpu: qcom,kgsl-3d0@fdb00000 {
 		label = "kgsl-3d0";
 		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
 		reg = <0xfdb00000 0x10000
@@ -24,7 +24,7 @@
 
 		qcom,initial-pwrlevel = <1>;
 
-		qcom,idle-timeout = <83>; //<HZ/12>
+		qcom,idle-timeout = <8>; //<HZ/12>
 		qcom,nap-allowed = <1>;
 		qcom,strtstp-sleepwake;
 		qcom,clk-map = <0x0000006>; //KGSL_CLK_CORE | KGSL_CLK_IFACE
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index be561b4..7bb2837 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,24 +28,10 @@
 			qcom,memory-reservation-size = <0x7800000>;
 		};
 
-		qcom,ion-heap@23 { /* PIL1 HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <23>;
-			qcom,heap-align = <0x10000>;
-			qcom,memory-fixed = <0xd200000 0x2800000>;
-		};
-
 		qcom,ion-heap@25 { /* IOMMU HEAP */
 			reg = <25>;
 		};
 
-		qcom,ion-heap@26 { /* PIL2 HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <26>;
-			qcom,heap-align = <0x10000>;
-			qcom,memory-fixed = <0x8400000 0x4e00000>;
-		};
-
 		qcom,ion-heap@27 { /* QSECOM HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <27>;
diff --git a/arch/arm/boot/dts/msm8974-leds.dtsi b/arch/arm/boot/dts/msm8974-leds.dtsi
index 8ba3470..befd206 100644
--- a/arch/arm/boot/dts/msm8974-leds.dtsi
+++ b/arch/arm/boot/dts/msm8974-leds.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,17 @@
 				qcom,id = <4>;
 				linux,default-trigger = "battery-full";
 			};
+
+			qcom,rgb_2 {
+				label = "rgb";
+				linux,name = "led:rgb_blue";
+				qcom,mode = <0>;
+				qcom,pwm-channel = <4>;
+				qcom,pwm-us = <1000>;
+				qcom,max-current = <12>;
+				qcom,id = <5>;
+				status = "disabled";
+			};
 		};
 
 		qcom,leds@d100 {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index f0f79b0..fb17449 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -73,10 +73,6 @@
 		};
 	};
 
-	qcom,mdss_mdp@fd900000 {
-		qcom,memory-reservation-size = <0x1000000>; /* size 16MB */
-	};
-
 	qcom,hdmi_tx@fd922100 {
 		status = "ok";
 
@@ -224,30 +220,34 @@
 			"Lineout_3 amp", "LINEOUT3",
 			"Lineout_2 amp", "LINEOUT2",
 			"Lineout_4 amp", "LINEOUT4",
-			"AMIC1", "MIC BIAS1 Internal1",
-			"MIC BIAS1 Internal1", "Handset Mic",
+			"AMIC1", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Analog Mic4",
 			"AMIC2", "MIC BIAS2 External",
 			"MIC BIAS2 External", "Headset Mic",
 			"AMIC3", "MIC BIAS2 External",
 			"MIC BIAS2 External", "ANCRight Headset Mic",
 			"AMIC4", "MIC BIAS2 External",
 			"MIC BIAS2 External", "ANCLeft Headset Mic",
+			"AMIC5", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Analog Mic6",
+			"AMIC6", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Analog Mic7",
 			"DMIC1", "MIC BIAS3 External",
-			"MIC BIAS1 External", "Digital Mic1",
+			"MIC BIAS3 External", "Digital Mic1",
 			"DMIC2", "MIC BIAS3 External",
-			"MIC BIAS1 External", "Digital Mic2",
+			"MIC BIAS3 External", "Digital Mic2",
 			"DMIC3", "MIC BIAS2 External",
-			"MIC BIAS3 External", "Digital Mic3",
+			"MIC BIAS2 External", "Digital Mic3",
 			"DMIC4", "MIC BIAS3 External",
 			"MIC BIAS3 External", "Digital Mic4",
 			"DMIC5", "MIC BIAS2 External",
-			"MIC BIAS4 External", "Digital Mic5",
+			"MIC BIAS2 External", "Digital Mic5",
 			"DMIC6", "MIC BIAS2 External",
-			"MIC BIAS4 External", "Digital Mic6";
+			"MIC BIAS2 External", "Digital Mic6";
 
 		qcom,ext-spk-amp-supply = <&ext_5v>;
 		qcom,ext-spk-amp-gpio = <&pm8841_mpps 1 0>;
-
+		qcom,dock-plug-det-irq = <&pm8841_mpps 2 0>;
 		qcom,hdmi-audio-rx;
 	};
 
@@ -278,6 +278,10 @@
 	};
 };
 
+&mdss_fb0 {
+	qcom,memory-reservation-size = <0x1000000>; /* size 16MB */
+};
+
 &usb3 {
 	qcom,charging-disabled;
 };
@@ -544,6 +548,11 @@
 	};
 
 	mpp@a100 { /* MPP 2 */
+		/* DOCK_PLUG_DET speakers+docking detect irq*/
+		qcom,mode = <0>; /* DIG_IN */
+		qcom,vin-sel = <2>; /* S3A 1.8v */
+		qcom,src-sel = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
 	mpp@a200 { /* HDMI_MUX_SEL MPP 3*/
@@ -589,3 +598,15 @@
 		qcom,channel-type = <0xf0000000>;
 	};
 };
+
+&spmi_bus {
+	qcom,pm8941@1 {
+		qcom,leds@d000 {
+			qcom,rgb_2 {
+				status = "ok";
+				qcom,default-state = "on";
+				qcom,turn-off-delay-ms = <1000>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index d17f909..0b95419 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,27 +11,86 @@
  */
 
 / {
-	qcom,mdss_mdp@fd900000 {
+	mdss_mdp: qcom,mdss_mdp@fd900000 {
 		compatible = "qcom,mdss_mdp";
 		reg = <0xfd900000 0x22100>,
 			<0xfd924000 0x1000>;
 		reg-names = "mdp_phys", "vbif_phys";
 		interrupts = <0 72 0>;
 		vdd-supply = <&gdsc_mdss>;
-		qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-		qcom,memory-reservation-size = <0x800000>; /* size 8MB */
+
+		qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
+					       0x00001A00>;
+		qcom,mdss-pipe-rgb-off = <0x00001E00 0x00002200
+					       0x00002600>;
+		qcom,mdss-pipe-dma-off = <0x00002A00 0x00002E00>;
+		qcom,mdss-pipe-vig-fetch-id = <1 4 7>;
+		qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
+		qcom,mdss-pipe-dma-fetch-id = <10 13>;
+
+		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
+				     0x00000900 0x0000A00>;
+		qcom,mdss-mixer-intf-off = <0x00003200 0x00003600
+					    0x00003A00>;
+		qcom,mdss-mixer-wb-off = <0x00003E00 0x00004200>;
+		qcom,mdss-dspp-off = <0x00004600 0x00004A00 0x00004E00>;
+		qcom,mdss-wb-off = <0x00011100 0x00013100 0x00015100
+				    0x00017100 0x00019100>;
+		qcom,mdss-intf-off = <0x00021100 0x00021300
+					   0x00021500 0x00021700>;
+
+		qcom,vbif-settings = <0x0004 0x00000001>,
+				     <0x00D8 0x00000707>,
+				     <0x00F0 0x00000030>,
+				     <0x0124 0x00000001>,
+				     <0x0178 0x00000FFF>,
+				     <0x017C 0x0FFF0FFF>,
+				     <0x0160 0x22222222>,
+				     <0x0164 0x00002222>;
+		qcom,mdp-settings = <0x02E0 0x000000AA>,
+				    <0x02E4 0x00000055>;
+
+		mdss_fb0: qcom,mdss_fb_primary {
+			cell-index = <0>;
+			compatible = "qcom,mdss-fb";
+			qcom,memory-reservation-type = "EBI1";
+			qcom,memory-reservation-size = <0x800000>;
+		};
+
+		mdss_fb1: qcom,mdss_fb_external {
+			cell-index = <1>;
+			compatible = "qcom,mdss-fb";
+		};
+
+		mdss_fb2: qcom,mdss_fb_wfd {
+			cell-index = <2>;
+			compatible = "qcom,mdss-fb";
+		};
 	};
 
-	mdss_dsi: qcom,mdss_dsi@fd922800 {
-		compatible = "qcom,msm-mdss-dsi";
-		reg = <0xfd922800 0x600>,
-			<0xfd8c2000 0x01000>;
+	mdss_dsi0: qcom,mdss_dsi@fd922800 {
+		compatible = "qcom,mdss-dsi-ctrl";
+		label = "MDSS DSI CTRL->0";
+		cell-index = <0>;
+		reg = <0xfd922800 0x600>;
 		vdd-supply = <&pm8941_l22>;
 		vdd_io-supply = <&pm8941_l12>;
 		vreg-supply = <&pm8941_l2>;
+		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 
-	qcom,hdmi_tx@fd922100 {
+	mdss_dsi1: qcom,mdss_dsi@fd922e00 {
+		compatible = "qcom,mdss-dsi-ctrl";
+		label = "MDSS DSI CTRL->1";
+		cell-index = <1>;
+		reg = <0xfd922e00 0x600>;
+		vdd-supply = <&pm8941_l22>;
+		vdd_io-supply = <&pm8941_l12>;
+		vreg-supply = <&pm8941_l2>;
+		qcom,mdss-fb-map = <&mdss_fb0>;
+	};
+
+	mdss_hdmi_tx: qcom,hdmi_tx@fd922100 {
 		cell-index = <0>;
 		compatible = "qcom,hdmi-tx";
 		reg =	<0xfd922100 0x35C>,
@@ -53,7 +112,7 @@
 		qcom,hdmi-tx-ddc-clk = <&msmgpio 32 0>;
 		qcom,hdmi-tx-ddc-data = <&msmgpio 33 0>;
 		qcom,hdmi-tx-hpd = <&msmgpio 34 0>;
-
+		qcom,mdss-fb-map = <&mdss_fb1>;
 		qcom,msm-hdmi-audio-rx {
 			compatible = "qcom,msm-hdmi-audio-codec-rx";
 		};
@@ -63,6 +122,7 @@
 		compatible = "qcom,mdss_wb";
 		qcom,mdss_pan_res = <1920 1080>;
 		qcom,mdss_pan_bpp = <24>;
+		qcom,mdss-fb-map = <&mdss_fb2>;
 	};
 
 	mdss_edp: qcom,mdss_edp@fd923400 {
@@ -76,5 +136,6 @@
 		qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
 		qcom,panel-pwm-period = <53>;
 		status = "disable";
+		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 40eaf2d..b2d320c 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -19,10 +19,8 @@
 		status = "ok";
 	};
 
-	qcom,mdss_dsi@fd922800 {
-		qcom,mdss_dsi_toshiba_720p_video {
-			status = "ok";
-		};
+	qcom,mdss_dsi_toshiba_720p_video {
+		status = "ok";
 	};
 
 	qcom,hdmi_tx@fd922100 {
@@ -107,6 +105,16 @@
 		};
 	};
 
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "atmel_mxt_ts";
+		qcom,disp-maxx = <720>;
+		qcom,disp-maxy = <1280>;
+		qcom,panel-maxx = <760>;
+		qcom,panel-maxy = <1424>;
+		qcom,key-codes = <158 139 102 217>;
+	};
+
 	i2c@f9967000 {
 		isa1200@48 {
 			status = "okay";
diff --git a/arch/arm/boot/dts/msm8974-pm.dtsi b/arch/arm/boot/dts/msm8974-pm.dtsi
index ab105a9..f9b9e33 100644
--- a/arch/arm/boot/dts/msm8974-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-pm.dtsi
@@ -185,11 +185,13 @@
 			reg = <0x0>;
 			qcom,mode = <0>;        /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
 			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <2>;          /* Retention */
+			qcom,l2 = <3>;          /* ACTIVE */
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -200,26 +202,31 @@
 			reg = <0x1>;
 			qcom,mode = <4>;        /* MSM_PM_SLEEP_MODE_RETENTION*/
 			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <2>;          /* Retention */
+			qcom,l2 = <3>;          /* ACTIVE */
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <75>;
 			qcom,ss-power = <735>;
 			qcom,energy-overhead = <77341>;
 			qcom,time-overhead = <105>;
 		};
 
+
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = <2>;        /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
 			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <2>;          /* Retention */
+			qcom,l2 = <3>;          /* ACTIVE */
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <95>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
@@ -235,6 +242,8 @@
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <2000>;
 			qcom,ss-power = <138>;
 			qcom,energy-overhead = <1208400>;
@@ -245,11 +254,13 @@
 			reg = <0x4>;
 			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
 			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,l2 = <0>;          /* OFF */
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO  */
 			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <3000>;
 			qcom,ss-power = <110>;
 			qcom,energy-overhead = <1250300>;
@@ -273,9 +284,24 @@
 
 		qcom,lpm-level@6 {
 			reg = <0x6>;
+			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+			qcom,xo = <0>;          /* OFF */
+			qcom,l2 = <0>;          /* OFF */
+			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,latency-us = <10300>;
+			qcom,ss-power = <63>;
+			qcom,energy-overhead = <2128000>;
+			qcom,time-overhead = <18200>;
+		};
+
+		qcom,lpm-level@7 {
+			reg = <0x7>;
 			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
 			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,l2 = <0>;          /* OFF */
 			qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
 			qcom,vdd-mem-lower-bound = <950000>;  /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
@@ -286,8 +312,8 @@
 			qcom,time-overhead = <27000>;
 		};
 
-		qcom,lpm-level@7 {
-			reg = <0x7>;
+		qcom,lpm-level@8 {
+			reg = <0x8>;
 			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
 			qcom,xo = <0>;          /* OFF */
 			qcom,l2 = <0>;          /* OFF */
@@ -404,6 +430,17 @@
 		qcom,use-sync-timer;
 	};
 
+	qcom,rpm-log@fc19dc00 {
+		compatible = "qcom,rpm-log";
+		reg = <0xfc19dc00 0x4000>;
+		qcom,rpm-addr-phys = <0xfc000000>;
+		qcom,offset-version = <4>;
+		qcom,offset-page-buffer-addr = <36>;
+		qcom,offset-log-len = <40>;
+		qcom,offset-log-len-mask = <44>;
+		qcom,offset-page-indices = <56>;
+	};
+
 	qcom,rpm-stats@0xfc19dbd0{
 		compatible = "qcom,rpm-stats";
 		reg = <0xfc19dbd0 0x1000>;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index c6c5452..1a6d9ba 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -436,6 +436,7 @@
 		qcom,ldo-default-voltage = <750000>;
 		qcom,ldo-threshold-voltage = <850000>;
 		qcom,ldo-delta-voltage = <50000>;
+		qcom,cpu-num = <0>;
 	};
 
 	krait1_vreg: regulator@f9098000 {
@@ -451,6 +452,7 @@
 		qcom,ldo-default-voltage = <750000>;
 		qcom,ldo-threshold-voltage = <850000>;
 		qcom,ldo-delta-voltage = <50000>;
+		qcom,cpu-num = <1>;
 	};
 
 	krait2_vreg: regulator@f90a8000 {
@@ -466,6 +468,7 @@
 		qcom,ldo-default-voltage = <750000>;
 		qcom,ldo-threshold-voltage = <850000>;
 		qcom,ldo-delta-voltage = <50000>;
+		qcom,cpu-num = <2>;
 	};
 
 	krait3_vreg: regulator@f90b8000 {
@@ -481,6 +484,7 @@
 		qcom,ldo-default-voltage = <750000>;
 		qcom,ldo-threshold-voltage = <850000>;
 		qcom,ldo-delta-voltage = <50000>;
+		qcom,cpu-num = <3>;
 	};
 
 	spi_eth_vreg: spi_eth_phy_vreg {
diff --git a/arch/arm/boot/dts/msm8974-rumi.dtsi b/arch/arm/boot/dts/msm8974-rumi.dtsi
index 38e552e..932c11c 100644
--- a/arch/arm/boot/dts/msm8974-rumi.dtsi
+++ b/arch/arm/boot/dts/msm8974-rumi.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -140,3 +140,7 @@
 &gdsc_usb_hsic {
         status = "disabled";
 };
+
+&rpm_bus {
+	rpm-standalone;
+};
diff --git a/arch/arm/boot/dts/msm8974-iommu.dtsi b/arch/arm/boot/dts/msm8974-v1-iommu.dtsi
old mode 100755
new mode 100644
similarity index 86%
rename from arch/arm/boot/dts/msm8974-iommu.dtsi
rename to arch/arm/boot/dts/msm8974-v1-iommu.dtsi
index 6a88992..c6693e1
--- a/arch/arm/boot/dts/msm8974-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-iommu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-/include/ "msm-iommu.dtsi"
+/include/ "msm-iommu-v1.dtsi"
 
 &jpeg_iommu {
 	status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index e60ab28..eb69c51 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -17,10 +17,21 @@
  */
 
 /include/ "msm8974.dtsi"
+/include/ "msm8974-v1-iommu.dtsi"
 
 / {
+	android_usb@fc42b0c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfc42b0c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
+	};
+
 	qcom,msm-imem@fc42b000 {
 		compatible = "qcom,msm-imem";
 		reg = <0xfc42b000 0x1000>; /* Address and size of IMEM */
 	};
 };
+
+&tsens {
+	qcom,calibration-less-mode;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-iommu.dtsi b/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
new file mode 100644
index 0000000..500f1de
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
@@ -0,0 +1,246 @@
+/* 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/ "msm-iommu-v1.dtsi"
+
+&venus_iommu {
+	status = "ok";
+	qcom,iommu-enable-halt;
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2050
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x2314
+				0x2394
+				0x2414
+				0x2008
+				0x200c
+				0x2010
+				0x2014
+				0x2018
+				0x201c
+				0x2020
+				0x2024
+				0x2028
+				0x202c
+				0x2030
+				0x2034
+				0x2038>;
+
+	qcom,iommu-bfb-data =  <0x1FFFFFF
+				0x0
+				0x00000004
+				0x00000008
+				0x00000000
+				0x00013205
+				0x00004000
+				0x00014020
+				0x0
+				0x94
+				0x114
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0>;
+
+	venus_ns: qcom,iommu-ctx@fdc8c000 {
+		qcom,iommu-ctx-sids = <0 1 2 3 4 5 7>;
+	};
+
+	venus_sec_bitstream: qcom,iommu-ctx@fdc8d000 {
+		label = "venus_sec_bitstream";
+	};
+
+	venus_sec_pixel: qcom,iommu-ctx@fdc8f000 {
+		reg = <0xfdc8f000 0x1000>;
+		interrupts = <0 42 0>;
+		qcom,iommu-ctx-sids = <0x85>;
+		label = "venus_sec_pixel";
+		qcom,secure-context;
+	};
+
+	venus_sec_non_pixel: qcom,iommu-ctx@fdc90000 {
+		reg = <0xfdc90000 0x1000>;
+		interrupts = <0 42 0>;
+		qcom,iommu-ctx-sids = <0x87 0xA0>;
+		label = "venus_sec_non_pixel";
+		qcom,secure-context;
+	};
+};
+
+&jpeg_iommu {
+	status = "ok";
+	qcom,iommu-enable-halt;
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2050
+				0x2514
+				0x2540
+				0x256c
+				0x2314
+				0x2394
+				0x2414
+				0x20ac
+				0x215c
+				0x220c
+				0x2008
+				0x200c
+				0x2010
+				0x2014>;
+
+	qcom,iommu-bfb-data =  <0x3FFF
+				0x00000000
+				0x4
+				0x4
+				0x0
+				0x0
+				0x10
+				0x50
+				0x00002000
+				0x00002804
+				0x00009614
+				0x0
+				0x0
+				0x0
+				0x0>;
+};
+
+&mdp_iommu {
+	status = "ok";
+	qcom,iommu-enable-halt;
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2050
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x2314
+				0x2394
+				0x2414
+				0x2008
+				0x200c
+				0x2010
+				0x2014
+				0x2018
+				0x201c
+				0x2020>;
+
+	qcom,iommu-bfb-data =  <0xFFFFF
+				0x00000000
+				0x00000004
+				0x00000010
+				0x00000000
+				0x00006800
+				0x00006221
+				0x00016231
+				0x0
+				0x34
+				0x74
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0>;
+};
+
+&kgsl_iommu {
+	status = "ok";
+	qcom,iommu-enable-halt;
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2050
+				0x2514
+				0x2540
+				0x256c
+				0x20ac
+				0x215c
+				0x220c
+				0x2314
+				0x2394
+				0x2414
+				0x2008>;
+
+	qcom,iommu-bfb-data =  <0x00000003
+				0x0
+				0x00000004
+				0x00000010
+				0x00000000
+				0x00000000
+				0x00000000
+				0x00000020
+				0x0
+				0x1
+				0x81
+				0x0>;
+};
+
+&vfe_iommu {
+	status = "ok";
+	qcom,iommu-enable-halt;
+
+	qcom,iommu-bfb-regs =  <0x204c
+				0x2050
+				0x2514
+				0x2540
+				0x256c
+				0x2314
+				0x2394
+				0x2414
+				0x20ac
+				0x215c
+				0x220c
+				0x2008
+				0x200c
+				0x2010
+				0x2014
+				0x2018
+				0x201c
+				0x2020>;
+
+	qcom,iommu-bfb-data =  <0xffffffff
+				0x00000000
+				0x4
+				0x8
+				0x0
+				0x0
+				0x20
+				0x78
+				0x00004000
+				0x00003c08
+				0x0000b41e
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0
+				0x0>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 3ddf4da9..09f559d 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -17,10 +17,45 @@
  */
 
 /include/ "msm8974.dtsi"
+/include/ "msm8974-v2-iommu.dtsi"
 
 / {
+	android_usb@fe8050c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
+	};
+
 	qcom,msm-imem@fe805000 {
 		compatible = "qcom,msm-imem";
 		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
 	};
 };
+
+/* GPU overrides */
+&msm_gpu {
+	/* Updated chip ID */
+	qcom,chipid = <0x03030001>;
+
+	/* Updated bus bandwidth requirements */
+	qcom,msm-bus,vectors-KBps =
+		/* Off */
+		<26 512 0 0>, <89 604 0 0>,
+		/* SVS */
+		<26 512 0 2504000>, <89 604 0 2400000>,
+		/* Nominal */
+		<26 512 0 5016000>, <89 604 0 5334880>,
+		/* Turbo */
+		<26 512 0 7464000>, <89 604 0 6400000>;
+};
+
+&mdss_mdp {
+	qcom,vbif-settings = <0x0004 0x00000001>;
+	qcom,mdp-settings = <0x02E0 0x000000A9>,
+			    <0x02E4 0x00000055>;
+
+	qcom,mdss-wb-off = <0x00011100 0x00011500
+			    0x00011900 0x00011D00 0x00012100>;
+	qcom,mdss-intf-off = <0x00012500 0x00012700
+			      0x00012900 0x00012b00>;
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 7960e41..b63b50f 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -12,7 +12,6 @@
 
 /include/ "skeleton.dtsi"
 /include/ "msm8974-pm.dtsi"
-/include/ "msm8974-iommu.dtsi"
 /include/ "msm8974-camera.dtsi"
 /include/ "msm8974-coresight.dtsi"
 /include/ "msm-gdsc.dtsi"
@@ -20,6 +19,7 @@
 /include/ "msm8974-gpu.dtsi"
 /include/ "msm8974-mdss.dtsi"
 /include/ "msm8974-smp2p.dtsi"
+/include/ "msm8974-bus.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974";
@@ -65,13 +65,61 @@
 		compatible = "qcom,msm-vidc";
 		reg = <0xfdc00000 0xff000>;
 		interrupts = <0 44 0>;
-		vidc-cp-map = <0x1000000 0x3f000000>;
-		vidc-ns-map = <0x40000000 0x40000000>;
-		load-freq-tbl = <979200 410000000>,
+		qcom,vidc-cp-map = <0x1000000 0x3f000000>;
+		qcom,vidc-ns-map = <0x40000000 0x40000000>;
+		qcom,load-freq-tbl = <979200 410000000>,
 			<783360 410000000>,
 			<489600 266670000>,
 			<244800 133330000>;
-		hfi = "venus";
+		qcom,hfi = "venus";
+		qcom,reg-presets = <0x80004 0x1>,
+			<0x80178 0x00001FFF>,
+			<0x8017c 0x1FFF1FFF>,
+			<0x800b0 0x10101001>,
+			<0x800b4 0x10101010>,
+			<0x800b8 0x10101010>,
+			<0x800bc 0x00000010>,
+			<0x800c0 0x1010100f>,
+			<0x800c4 0x10101010>,
+			<0x800c8 0x10101010>,
+			<0x800cc 0x00000010>,
+			<0x800d0 0x00001010>,
+			<0x800d4 0x00001010>,
+			<0x800f0 0x00000030>,
+			<0x800d8 0x00000707>,
+			<0x800dc 0x00000707>,
+			<0x80124 0x00000001>,
+			<0xE0020 0x5555556>,
+			<0xE0024 0x0>;
+		qcom,bus-ports = <1>;
+		qcom,enc-ocmem-ab-ib = <0 0>,
+			<138200 1222000>,
+			<414700 1222000>,
+			<940000 2444000>,
+			<1880000 2444000>,
+			<3008000 3910400>,
+			<3760000 4888000>;
+		qcom,dec-ocmem-ab-ib = <0 0>,
+			<176900 1556640>,
+			<456200 1556640>,
+			<864800 1556640>,
+			<1729600 3113280>,
+			<2767360 4981248>,
+			<3459200 6226560>;
+		qcom,enc-ddr-ab-ib = <0 0>,
+			<60000 664950>,
+			<181000 664950>,
+			<403000 664950>,
+			<806000 1329900>,
+			<1289600 2127840>,
+			<161200 6400000>;
+		qcom,dec-ddr-ab-ib = <0 0>,
+			<110000 909000>,
+			<268000 909000>,
+			<505000 909000>,
+			<1010000 1818000>,
+			<1616000 2908800>,
+			<2020000 6400000>;
 	};
 
 	qcom,wfd {
@@ -97,6 +145,14 @@
 		reg = <0xf991e000 0x1000>;
 		interrupts = <0 108 0>;
 		status = "disabled";
+
+		qcom,msm-bus,name = "serial_uart2";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<84 512 0 0>,
+				<84 512 500 800>;
 	};
 
 	usb_otg: usb@f9a55000 {
@@ -126,12 +182,6 @@
 				<87 512 60000 960000>;
 	};
 
-	android_usb@fc42b0c8 {
-		compatible = "qcom,android-usb";
-		reg = <0xfc42b0c8 0xc8>;
-		qcom,android-usb-swfi-latency = <1>;
-	};
-
 	sdcc1: qcom,sdcc@f9824000 {
 		cell-index = <1>; /* SDC1 eMMC slot */
 		compatible = "qcom,msm-sdcc";
@@ -481,149 +531,15 @@
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
 		reg = <0xfc4cf000 0x1000>,
-		      <0Xfc4cb000 0x1000>;
+		      <0Xfc4cb000 0x1000>,
+		      <0Xfc4ca000 0x1000>;
 		/* 190,ee0_krait_hlos_spmi_periph_irq */
 		/* 187,channel_0_krait_hlos_trans_done_irq */
 		interrupts = <0 190 0 0 187 0>;
 		qcom,pmic-arb-ee = <0>;
 		qcom,pmic-arb-channel = <0>;
-		qcom,pmic-arb-ppid-map = <0x40400000>, /* BUS */
-					 <0x40500001>, /* INT */
-					 <0x40600002>, /* SPMI */
-					 <0x40800003>, /* PON */
-					 <0x42400004>, /* TEMP_ALARM */
-					 <0x47000005>, /* PBS_CORE */
-					 <0x47100006>, /* PBS_CLIENT0 */
-					 <0x47200007>, /* PBS_CLIENT1 */
-					 <0x47300008>, /* PBS_CLIENT2 */
-					 <0x47400009>, /* PBS_CLIENT3 */
-					 <0x4750000a>, /* PBS_CLIENT4 */
-					 <0x4760000b>, /* PBS_CLIENT5 */
-					 <0x4770000c>, /* PBS_CLIENT6 */
-					 <0x4780000d>, /* PBS_CLIENT7 */
-					 <0x4a00000e>, /* MPP1 */
-					 <0x4a100021>, /* MPP2 */
-					 <0x4a20000f>, /* MPP3 */
-					 <0x4a300010>, /* MPP4 */
-					 <0x51000011>, /* BCLK_GEN_MAIN */
-					 <0x51d00012>, /* S4_CTRL */
-					 <0x51e00013>, /* S4_PS */
-					 <0x51f00014>, /* S4_FREQ */
-					 <0x52000015>, /* S5_CTRL */
-					 <0x52100016>, /* S5_PS */
-					 <0x52200017>, /* S5_FREQ */
-					 <0x52300018>, /* S6_CTRL */
-					 <0x52400019>, /* S6_PS */
-					 <0x5250001a>, /* S6_FREQ */
-					 <0x5260001b>, /* S7_CTRL */
-					 <0x5270001c>, /* S7_PS */
-					 <0x5280001d>, /* S7_FREQ */
-					 <0x5290001e>, /* S8_CTRL */
-					 <0x52a0001f>, /* S8_PS */
-					 <0x52b00020>, /* S8_FREQ */
-					 <0x00400022>, /* BUS */
-					 <0x00500023>, /* INT */
-					 <0x00600024>, /* SPMI */
-					 <0x00800025>, /* PON */
-					 <0x00b00027>, /* VREG_TFT */
-					 <0x01000028>, /* SMBB_CHGR */
-					 <0x01100029>, /* SMBB_BUCK */
-					 <0x0120002a>, /* SMBB_BAT_IF */
-					 <0x0130002b>, /* SMBB_USB_CHGPTH */
-					 <0x0140002c>, /* SMBB_DC_CHGPTH */
-					 <0x0150002d>, /* SMBB_BOOST */
-					 <0x0160002e>, /* SMBB_MISC */
-					 <0x0170002f>, /* SMBB_FREQ */
-					 <0x02400030>, /* TEMP_ALARM */
-					 <0x02800031>, /* COIN */
-					 <0x03100032>, /* VADC1_USR */
-					 <0x03300033>, /* VADC1_BMS */
-					 <0x03400034>, /* VADC2_BTM */
-					 <0x03600035>, /* IADC1_USR */
-					 <0x03800036>, /* IADC1_BMS */
-					 <0x04000037>, /* BMS1 */
-					 <0x05700039>, /* DIFF_CLK1 */
-					 <0x05c0003b>, /* DIV_CLK2 */
-					 <0x0610003d>, /* RTC_ALARM */
-					 <0x0620003e>, /* RTC_TIMER */
-					 <0x07100040>, /* PBS_CLIENT0 */
-					 <0x07200041>, /* PBS_CLIENT1 */
-					 <0x07300042>, /* PBS_CLIENT2 */
-					 <0x07400043>, /* PBS_CLIENT3 */
-					 <0x07500044>, /* PBS_CLIENT4 */
-					 <0x07600045>, /* PBS_CLIENT5 */
-					 <0x07700046>, /* PBS_CLIENT6 */
-					 <0x07800047>, /* PBS_CLIENT7 */
-					 <0x07900048>, /* PBS_CLIENT8 */
-					 <0x07a00049>, /* PBS_CLIENT9 */
-					 <0x07b0004a>, /* PBS_CLIENT10 */
-					 <0x07c0004b>, /* PBS_CLIENT11 */
-					 <0x07d0004c>, /* PBS_CLIENT12 */
-					 <0x07e0004d>, /* PBS_CLIENT13 */
-					 <0x07f0004e>, /* PBS_CLIENT14 */
-					 <0x0800004f>, /* PBS_CLIENT15 */
-					 <0x0a100050>, /* MPP2 */
-					 <0x0a300051>, /* MPP4 */
-					 <0x0a400052>, /* MPP5 */
-					 <0x0a500053>, /* MPP6 */
-					 <0x0a600054>, /* MPP7 */
-					 <0x0a700055>, /* MPP8 */
-					 <0x0c000056>, /* GPIO1 */
-					 <0x0c100057>, /* GPIO2 */
-					 <0x0c200058>, /* GPIO3 */
-					 <0x0c300059>, /* GPIO4 */
-					 <0x0c40005a>, /* GPIO5 */
-					 <0x0c50005b>, /* GPIO6 */
-					 <0x0c60005c>, /* GPIO7 */
-					 <0x0c70005d>, /* GPIO8 */
-					 <0x0c80005e>, /* GPIO9 */
-					 <0x0c90005f>, /* GPIO10 */
-					 <0x0ca00060>, /* GPIO11 */
-					 <0x0cb00061>, /* GPIO12 */
-					 <0x0cc00062>, /* GPIO13 */
-					 <0x0cd00063>, /* GPIO14 */
-					 <0x0ce00064>, /* GPIO15 */
-					 <0x0cf00065>, /* GPIO16 */
-					 <0x0d200066>, /* GPIO19 */
-					 <0x0d300067>, /* GPIO20 */
-					 <0x0d500068>, /* GPIO22 */
-					 <0x0d600069>, /* GPIO23 */
-					 <0x0d70006a>, /* GPIO24 */
-					 <0x0d80006b>, /* GPIO25 */
-					 <0x0d90006c>, /* GPIO26 */
-					 <0x0da0006d>, /* GPIO27 */
-					 <0x0dc0006e>, /* GPIO29 */
-					 <0x0dd0006f>, /* GPIO30 */
-					 <0x0df00070>, /* GPIO32 */
-					 <0x0e000071>, /* GPIO33 */
-					 <0x0e100072>, /* GPIO34 */
-					 <0x0e200073>, /* GPIO35 */
-					 <0x0e300074>, /* GPIO36 */
-					 <0x11000075>, /* BUCK_CMN */
-					 <0x1a000076>, /* BOOST */
-					 <0x1a100077>, /* BOOST_FREQ */
-					 <0x1a800078>, /* KEYPAD1 */
-					 <0x1b000079>, /* LPG_LUT */
-					 <0x1b10007a>, /* LPG_CHAN1 */
-					 <0x1b20007b>, /* LPG_CHAN2 */
-					 <0x1b30007c>, /* LPG_CHAN3 */
-					 <0x1b40007d>, /* LPG_CHAN4 */
-					 <0x1b50007e>, /* LPG_CHAN5 */
-					 <0x1b60007f>, /* LPG_CHAN6 */
-					 <0x1b700080>, /* LPG_CHAN7 */
-					 <0x1b800081>, /* LPG_CHAN8 */
-					 <0x1bc00082>, /* PWM_3D */
-					 <0x1c000083>, /* VIB1 */
-					 <0x1d000084>, /* TRI_LED */
-					 <0x1d300085>, /* FLASH1 */
-					 <0x1d800086>, /* WLED1 */
-					 <0x1e200087>, /* KPDBL_MAIN */
-					 <0x1e300088>, /* KPDBL_LUT */
-					 <0x1e400089>, /* LPG_CHAN9 */
-					 <0x1e50008a>, /* LPG_CHAN10 */
-					 <0x1e60008b>, /* LPG_CHAN11 */
-					 <0x1e70008c>; /* LPG_CHAN12 */
 	};
 
 	i2c@f9967000 { /* BLSP#11 */
@@ -734,6 +650,7 @@
 		reg = <0xfe200000 0x00100>,
 		      <0xfd485100 0x00010>;
 		reg-names = "qdsp6_base", "halt_base";
+		vdd_cx-supply = <&pm8841_s2_corner>;
 		interrupts = <0 162 1>;
 
 		qcom,firmware-name = "adsp";
@@ -807,6 +724,16 @@
 			qcom,msm-dai-q6-dev-id = <16387>;
 		};
 
+		qcom,msm-dai-q6-sb-2-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16388>;
+		};
+
+		qcom,msm-dai-q6-sb-2-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16389>;
+		};
+
 		qcom,msm-dai-q6-sb-3-rx {
 			compatible = "qcom,msm-dai-q6-dev";
 			qcom,msm-dai-q6-dev-id = <16390>;
@@ -876,6 +803,11 @@
 			compatible = "qcom,msm-dai-q6-dev";
 			qcom,msm-dai-q6-dev-id = <32772>;
 		};
+
+		qcom,msm-dai-q6-incall-music-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32773>;
+		};
 	};
 
 	qcom,msm-auxpcm {
@@ -945,8 +877,10 @@
 
 		interrupts = <0 24 1>;
 		vdd_mss-supply = <&pm8841_s3>;
+		vdd_cx-supply = <&pm8841_s2_corner>;
 		vdd_mx-supply = <&pm8841_s1>;
-
+		vdd_pll-supply = <&pm8941_l12>;
+		qcom,vdd_pll = <1800000>;
 		qcom,is-loadable;
 		qcom,firmware-name = "mba";
 		qcom,pil-self-auth = <1>;
@@ -1000,6 +934,7 @@
 		interrupts = <0 76 0 0 77 0>;
 		interrupt-names = "ocmem_irq", "dm_irq";
 		qcom,ocmem-num-regions = <0x3>;
+		qcom,ocmem-num-macros = <0x8>;
 		qcom,resource-type = <0x706d636f>;
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1079,7 +1014,7 @@
 	qcom,venus@fdce0000 {
 		compatible = "qcom,pil-venus";
 		reg = <0xfdce0000 0x4000>,
-		      <0xfdc80208 0x8>;
+		      <0xfdc80000 0x400>;
 		reg-names = "wrapper_base", "vbif_base";
 		vdd-supply = <&gdsc_venus>;
 
@@ -1100,13 +1035,12 @@
 		qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
 	};
 
-	tsens@fc4a8000 {
+	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
 		      <0xfc4b8000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
-		qcom,calibration-less-mode;
 		qcom,sensors = <11>;
 		qcom,slope = <3200 3200 3200 3200 3200 3200 3200 3200 3200
 				3200 3200>;
@@ -1217,7 +1151,7 @@
 
 	qcom,msm-thermal {
 		compatible = "qcom,msm-thermal";
-		qcom,sensor-id = <0>;
+		qcom,sensor-id = <5>;
 		qcom,poll-ms = <250>;
 		qcom,limit-temp = <60>;
 		qcom,temp-hysteresis = <10>;
@@ -1251,6 +1185,13 @@
 
 		qcom,bam-tx-ep-pipe-index = <0>;
 		qcom,bam-rx-ep-pipe-index = <1>;
+		qcom,msm-bus,name = "uart7";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<84 512 0 0>,
+				<84 512 500 800>;
 	};
 
 	qcom,smem@fa00000 {
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 5a925cb..793d27b 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -82,6 +82,8 @@
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <100>;
 			qcom,ss-power = <8000>;
 			qcom,energy-overhead = <100000>;
@@ -97,6 +99,8 @@
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <2000>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60100000>;
@@ -112,6 +116,8 @@
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <3500>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60350000>;
@@ -127,6 +133,8 @@
 			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
 			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
+			qcom,irqs-detectable;
+			qcom.gpios-detectable;
 			qcom,latency-us = <4500>;
 			qcom,ss-power = <5000>;
 			qcom,energy-overhead = <60350000>;
@@ -142,6 +150,7 @@
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
+			qcom,irqs-detectable;
 			qcom,latency-us = <6800>;
 			qcom,ss-power = <2000>;
 			qcom,energy-overhead = <71850000>;
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index 6295062..3e88158 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -19,9 +19,15 @@
 /include/ "msm9625.dtsi"
 
 / {
-	qcom,msm-imem@fc42b000 {
+	qcom,msm-imem@fc42a800 {
 		compatible = "qcom,msm-imem";
-		reg = <0xfc42b000 0x1000>; /* Address and size of IMEM */
+		reg = <0xfc42a800 0x1000>; /* Address and size of IMEM */
+	};
+
+	android_usb@fc42a8c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfc42a8c8 0xc8>;
+		qcom,android-usb-swfi-latency = <100>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm9625-v2.dtsi b/arch/arm/boot/dts/msm9625-v2.dtsi
index a0249cc..c3c2c49 100644
--- a/arch/arm/boot/dts/msm9625-v2.dtsi
+++ b/arch/arm/boot/dts/msm9625-v2.dtsi
@@ -19,11 +19,16 @@
 /include/ "msm9625.dtsi"
 
 / {
-	qcom,msm-imem@fe805000 {
+	qcom,msm-imem@fe807800 {
 		compatible = "qcom,msm-imem";
-		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
+		reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
 	};
 
+	android_usb@fe8078c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfe8078c8 0xc8>;
+		qcom,android-usb-swfi-latency = <100>;
+	};
 };
 
 &ipa_hw {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index e95d108..2bdd9fd 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -97,12 +97,6 @@
 				<87 512 40000 640000>;
 	};
 
-	android_usb@fc42b0c8 {
-		compatible = "qcom,android-usb";
-		reg = <0xfc42b0c8 0xc8>;
-		qcom,android-usb-swfi-latency = <100>;
-	};
-
 	hsic@f9a15000 {
 		compatible = "qcom,hsic-host";
 		reg = <0xf9a15000 0x400>;
@@ -232,27 +226,15 @@
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
 		reg = <0xfc4cf000 0x1000>,
-		      <0Xfc4cb000 0x1000>;
+		      <0Xfc4cb000 0x1000>,
+		      <0Xfc4ca000 0x1000>;
 		/* 190,ee0_krait_hlos_spmi_periph_irq */
 		/* 187,channel_0_krait_hlos_trans_done_irq */
 		interrupts = <0 190 0 0 187 0>;
 		qcom,pmic-arb-ee = <0>;
 		qcom,pmic-arb-channel = <0>;
-		qcom,pmic-arb-ppid-map = <0x02400000>, /* TEMP_ALARM */
-					 <0x03100001>, /* VADC1_USR */
-					 <0x06100002>, /* RTC_ALARM */
-					 <0x06200003>, /* RTC_TIMER */
-					 <0x0a000004>, /* MPP1 */
-					 <0x0a100005>, /* MPP2 */
-					 <0x0a200006>, /* MPP3 */
-					 <0x0a300007>, /* MPP4 */
-					 <0x0a400008>, /* MPP5 */
-					 <0x0a500009>, /* MPP6 */
-					 <0x0c20000a>, /* GPIO3 */
-					 <0x0c30000b>, /* GPIO4 */
-					 <0x0c50000c>, /* GPIO6 */
-					 <0x0080000d>; /* PON */
 	};
 
 	i2c@f9925000 {
@@ -707,6 +689,12 @@
 		qcom,memory-reservation-type = "EBI1";
 		qcom,memory-reservation-size = <0x1000>; /* 4K EBI1 buffer */
 	};
+
+        qcom,msm-mem-hole {
+                compatible = "qcom,msm-mem-hole";
+                qcom,memblock-remove = <0x1f00000 0x5700000>; /* Address and Size of Hole */
+        };
+
 };
 
 /include/ "msm-pm8019-rpm-regulator.dtsi"
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 6793a65..ac92e9d 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -37,19 +37,28 @@
 CONFIG_ARCH_MSM8610=y
 CONFIG_ARCH_MSM8226=y
 CONFIG_SND_SOC_MSM8226=y
+CONFIG_SND_SOC_MSM8X10=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_IPC_LOGGING=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
-CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_LPASS_QDSP6V5=y
+CONFIG_MSM_PIL_PRONTO=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_MSM_PIL_VENUS=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_ADSP_LOADER=m
@@ -64,10 +73,11 @@
 CONFIG_HIGHMEM=y
 CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_USE_OF=y
+CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-# CONFIG_SUSPEND is not set
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -93,6 +103,9 @@
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_BRIDGE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_MD=y
@@ -100,6 +113,9 @@
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_INPUT_MISC=y
@@ -116,7 +132,12 @@
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
 CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
 CONFIG_WCD9306_CODEC=y
 # CONFIG_HWMON is not set
 CONFIG_REGULATOR=y
@@ -183,8 +204,14 @@
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
 CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MSM_CAMERA is not set
+CONFIG_MSM_VIDC_V4L2=y
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_VIDEOBUF2_MSM_MEM=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_NONSECURE=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 7ab8522..053e1ca 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -484,8 +484,12 @@
 CONFIG_MSM_IOMMU=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
-CONFIG_MSM_QDSS=y
-CONFIG_CONTROL_TRACE=m
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_ETB=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_EVENT=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 809ed77..7b54eb4 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -486,9 +486,13 @@
 CONFIG_MSM_IOMMU=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
-CONFIG_MSM_QDSS=y
-CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE=y
-CONFIG_CONTROL_TRACE=m
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_ETB=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_ETM_DEFAULT_ENABLE=y
+CONFIG_CORESIGHT_EVENT=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 1148dc5..bd7c1a0 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -224,6 +224,8 @@
 CONFIG_BT_HCISMD=y
 CONFIG_MSM_BT_POWER=y
 CONFIG_CFG80211=y
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_NL80211_TESTMODE=y
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
@@ -257,6 +259,7 @@
 CONFIG_USB_USBNET=y
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -264,6 +267,7 @@
 CONFIG_JOYSTICK_XPAD=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_SERIAL_MSM_HS=y
@@ -312,7 +316,11 @@
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MSM_CAMERA=n
+CONFIG_MT9M114=y
 CONFIG_MSMB_CAMERA=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_OV2720=y
+CONFIG_MSMB_JPEG=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_JPEG=y
 CONFIG_MSM_CCI=y
@@ -348,6 +356,7 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_EHSET=y
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_USB_ACM=y
@@ -364,6 +373,7 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_DWC3_MSM=y
@@ -405,8 +415,15 @@
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
 CONFIG_MSM_IOMMU=y
-CONFIG_MSM_QDSS=y
-CONFIG_MSM_QDSS_ETM_PCSAVE_DEFAULT_ENABLE=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE=y
+CONFIG_CORESIGHT_EVENT=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
@@ -441,3 +458,4 @@
 CONFIG_SW_SYNC=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
+CONFIG_DEFAULT_ROW=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 029dec2..2f2e0b3 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -34,6 +34,7 @@
 CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_EFI_PARTITION=y
+CONFIG_IOSCHED_TEST=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8974=y
 CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
@@ -228,9 +229,12 @@
 CONFIG_BT_HCISMD=y
 CONFIG_MSM_BT_POWER=y
 CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_TSPP=m
@@ -262,6 +266,7 @@
 CONFIG_USB_USBNET=y
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -269,6 +274,7 @@
 CONFIG_JOYSTICK_XPAD=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_SERIAL_MSM_HS=y
@@ -313,25 +319,27 @@
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_DVB_CORE=m
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_MSM_CAMERA=n
-CONFIG_MSMB_CAMERA=y
+# CONFIG_MSM_CAMERA is not set
+CONFIG_MT9M114=y
+CONFIG_OV2720=y
 CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_JPEG=y
 CONFIG_MSM_CCI=y
 CONFIG_MSM_CSI30_HEADER=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
-CONFIG_MSM_CSI2_REGISTER=y
 CONFIG_MSM_ISPIF=y
 CONFIG_S5K3L1YX=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
-CONFIG_RADIO_IRIS=y
-CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_DVB_MPQ=m
 CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
@@ -354,7 +362,7 @@
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_EHSET=y
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_USB_ACM=y
@@ -371,6 +379,7 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_DWC3_MSM=y
@@ -383,12 +392,11 @@
 CONFIG_MMC_BLOCK_MINORS=32
 # CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_TEST=m
+CONFIG_MMC_BLOCK_TEST=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_IOSCHED_TEST=y
-CONFIG_MMC_BLOCK_TEST=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_BACKLIGHT=y
@@ -412,8 +420,18 @@
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
 CONFIG_MSM_IOMMU=y
-CONFIG_MSM_QDSS=y
-CONFIG_MSM_QDSS_ETM_PCSAVE_DEFAULT_ENABLE=y
+CONFIG_MSM_IOMMU_PMON=y
+CONFIG_MOBICORE_SUPPORT=m
+CONFIG_MOBICORE_API=m
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE=y
+CONFIG_CORESIGHT_EVENT=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
@@ -457,7 +475,4 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
-CONFIG_MOBICORE_SUPPORT=m
-CONFIG_MOBICORE_API=m
+CONFIG_DEFAULT_ROW=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 19301fe..540fdf6 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -246,7 +246,14 @@
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_IPA=y
-CONFIG_MSM_QDSS=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_EVENT=m
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_YAFFS_FS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 5cf6bd2..5694a2e 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -290,6 +290,7 @@
 	select SENSORS_ADSP
 	select MSM_ULTRASOUND_B
 	select MSM_LPM_TEST
+	select MSM_RPM_LOG
 
 config ARCH_MPQ8092
 	bool "MPQ8092"
@@ -377,7 +378,8 @@
 	select MSM_QDSP6V2_CODECS
 	select MSM_AUDIO_QDSP6V2 if SND_SOC
 	select CPU_HAS_L2_PMU
-	select MSM_JTAG_MM if MSM_QDSS
+	select MSM_JTAG_MM if CORESIGHT_ETM
+	select MEMORY_HOLE_CARVEOUT
 
 config ARCH_MSM8610
 	bool "MSM8610"
@@ -393,6 +395,8 @@
 	select MSM_GPIOMUX
 	select MSM_NATIVE_RESTART
 	select MSM_RESTART_V2
+	select MEMORY_HOLE_CARVEOUT
+	select DONT_MAP_HOLE_AFTER_MEMBANK
 	select QMI_ENCDEC
 	select MSM_QDSP6_APRV2
 	select MSM_QDSP6V2_CODECS
@@ -401,6 +405,11 @@
 	select MSM_SPM_V2
 	select MSM_L2_SPM
 	select MSM_PM8X60 if PM
+	select CPU_FREQ_MSM
+	select CPU_FREQ
+	select CPU_FREQ_GOV_USERSPACE
+	select CPU_FREQ_GOV_ONDEMAND
+	select MSM_PIL
 
 config ARCH_MSM8226
 	bool "MSM8226"
@@ -424,6 +433,8 @@
 	select MSM_SPM_V2
 	select MSM_L2_SPM
 	select MSM_PM8X60 if PM
+	select MEMORY_HOLE_CARVEOUT
+	select DONT_MAP_HOLE_AFTER_MEMBANK0
 endmenu
 
 choice
@@ -468,14 +479,14 @@
 	select ARCH_MSM_SCORPION
 	select MSM_SMP
 	select HAVE_ARCH_HAS_CURRENT_TIMER
-	select MSM_JTAG if MSM_QDSS
+	select MSM_JTAG if CORESIGHT_ETM
 	bool
 
 config  ARCH_MSM_KRAITMP
 	select ARCH_MSM_KRAIT
 	select MSM_SMP
 	select HAVE_ARCH_HAS_CURRENT_TIMER
-	select MSM_JTAG if MSM_QDSS
+	select MSM_JTAG if CORESIGHT_ETM
 	bool
 
 config  ARCH_MSM_CORTEXMP
@@ -2196,7 +2207,7 @@
 config MSM_RPM_LOG
 	tristate "MSM Resource Power Manager Log Driver"
 	depends on DEBUG_FS
-	depends on MSM_RPM
+	depends on MSM_RPM || MSM_RPM_SMD
 	default n
 	help
 	  This option enables a driver which can read from a circular buffer
@@ -2308,28 +2319,29 @@
 		enabled via another mechanism.
 
 config MSM_JTAG
-	bool "JTAG and kernel debug and trace support across power collapse"
+	bool "Debug and ETM trace support across power collapse"
 	help
-	  Enables support for kernel debugging (specifically breakpoints) and
+	  Enables support for debugging (specifically breakpoints) and ETM
 	  processor tracing across power collapse both for JTag and OS hosted
 	  software running on the target. Enabling this will ensure debug
 	  and ETM registers are saved and restored across power collapse.
 
-	  For production builds, you should probably say 'N' here to avoid
-	  potential power, performance and memory penalty.
+	  If unsure, say 'N' here to avoid potential power, performance and
+	  memory penalty.
 
 config MSM_JTAG_MM
-	bool "ETM trace and debug support across power collapse using memory mapped access"
+	bool "Debug and ETM trace support across power collapse using memory mapped access"
 	help
-	   Enables support for kernel debugging (specifically breakpoints) and
-	   processor tracing using ETM across power collapse both for JTag and
-	   OS hosted software running on the target. Enabling this will ensure
-	   debug and ETM registers are saved and restored across power collapse.
-	   Needed on targets on which cp14 access to debug and ETM registers is
-	   not permitted and so memory mapped access is necessary.
+	  Enables support for debugging (specifically breakpoints) and ETM
+	  processor tracing across power collapse both for JTag and OS hosted
+	  software running on the target. Enabling this will ensure debug
+	  and ETM registers are saved and restored across power collapse.
 
-	   For production builds, you should probably say 'N' here to avoid
-	   potential power, performance and memory penalty.
+	  Required on targets on which cp14 access to debug and ETM registers is
+	  not permitted and so memory mapped access is necessary.
+
+	  If unsure, say 'N' here to avoid potential power, performance and
+	  memory penalty.
 
 config MSM_ETM
 	tristate "Enable MSM ETM and ETB"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index c4d9048..ecea32b 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -279,6 +279,7 @@
 obj-$(CONFIG_MACH_MSM8930_FLUID) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
 obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o batterydata-lib.o
 obj-$(CONFIG_QPNP_BMS) += bms-batterydata.o bms-batterydata-desay.o batterydata-lib.o
+obj-$(CONFIG_QPNP_BMS) += bms-batterydata-oem.o
 obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_LIQUID) += board-8064-all.o board-8064-regulator.o
@@ -295,10 +296,12 @@
 obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
-obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o
+obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
 obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
+obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8974.o
+obj-$(CONFIG_ARCH_MSM8226) += acpuclock-8226.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += clock-local2.o clock-pll.o clock-8610.o clock-rpm.o clock-voter.o
 
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
new file mode 100644
index 0000000..7dc3a0e
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/clk-provider.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/rpm-regulator-smd.h>
+
+#include "acpuclock-cortex.h"
+
+#define RCG_CONFIG_UPDATE_BIT		BIT(0)
+
+static struct msm_bus_paths bw_level_tbl[] = {
+	[0] =  BW_MBPS(152), /* At least 19 MHz on bus. */
+	[1] =  BW_MBPS(300), /* At least 37.5 MHz on bus. */
+	[2] =  BW_MBPS(400), /* At least 50 MHz on bus. */
+	[3] =  BW_MBPS(800), /* At least 100 MHz on bus. */
+	[4] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+	[5] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+	[6] = BW_MBPS(3200), /* At least 400 MHz on bus. */
+	[7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_client_pdata = {
+	.usecase = bw_level_tbl,
+	.num_usecases = ARRAY_SIZE(bw_level_tbl),
+	.active_only = 1,
+	.name = "acpuclock",
+};
+
+/* TODO:
+ * 1) Update MX voltage when data is avaiable
+ * 2) Update bus bandwidth
+ * 3) Depending on Frodo version, may need minimum of LVL_NOM
+ */
+static struct clkctl_acpu_speed acpu_freq_tbl[] = {
+	{ 0,   19200, CXO,     0, 0,   LVL_LOW,    950000, 0 },
+	{ 1,  300000, PLL0,    4, 2,   LVL_LOW,    950000, 4 },
+	{ 1,  384000, ACPUPLL, 5, 0,   LVL_LOW,    950000, 4 },
+	{ 1,  600000, PLL0,    4, 0,   LVL_NOM,    950000, 6 },
+	{ 1,  787200, ACPUPLL, 5, 0,   LVL_NOM,   1050000, 6 },
+	{ 1,  998400, ACPUPLL, 5, 0,   LVL_HIGH,  1050000, 7 },
+	{ 1, 1190400, ACPUPLL, 5, 0,   LVL_HIGH,  1050000, 7 },
+	{ 0 }
+};
+
+static struct acpuclk_drv_data drv_data = {
+	.freq_tbl = acpu_freq_tbl,
+	.current_speed = &(struct clkctl_acpu_speed){ 0 },
+	.bus_scale = &bus_client_pdata,
+	/* FIXME regulator doesn't support corners yet */
+	.vdd_max_cpu = 1050000,
+	.vdd_max_mem = 1150000,
+	.src_clocks = {
+		[PLL0].name = "gpll0",
+		[ACPUPLL].name = "a7sspll",
+	},
+	.reg_data = {
+		.cfg_src_mask = BM(10, 8),
+		.cfg_src_shift = 8,
+		.cfg_div_mask = BM(4, 0),
+		.cfg_div_shift = 0,
+		.update_mask = RCG_CONFIG_UPDATE_BIT,
+		.poll_mask = RCG_CONFIG_UPDATE_BIT,
+	},
+};
+
+static int __init acpuclk_a7_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
+	if (!res)
+		return -EINVAL;
+
+	drv_data.apcs_rcg_cmd = ioremap(res->start, resource_size(res));
+	if (!drv_data.apcs_rcg_cmd)
+		return -ENOMEM;
+
+	drv_data.apcs_rcg_config = drv_data.apcs_rcg_cmd + 4;
+
+	drv_data.vdd_cpu = regulator_get(&pdev->dev, "a7_cpu");
+	if (IS_ERR(drv_data.vdd_cpu)) {
+		dev_err(&pdev->dev, "regulator for %s get failed\n", "a7_cpu");
+		return PTR_ERR(drv_data.vdd_cpu);
+	}
+
+	drv_data.vdd_mem = regulator_get(&pdev->dev, "a7_mem");
+	if (IS_ERR(drv_data.vdd_mem)) {
+		dev_err(&pdev->dev, "regulator for %s get failed\n", "a7_mem");
+		return PTR_ERR(drv_data.vdd_mem);
+	}
+
+	return acpuclk_cortex_init(pdev, &drv_data);
+}
+
+static struct of_device_id acpuclk_a7_match_table[] = {
+	{.compatible = "qcom,acpuclk-a7"},
+	{}
+};
+
+static struct platform_driver acpuclk_a7_driver = {
+	.driver = {
+		.name = "acpuclk-a7",
+		.of_match_table = acpuclk_a7_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init acpuclk_a7_init(void)
+{
+	return platform_driver_probe(&acpuclk_a7_driver, acpuclk_a7_probe);
+}
+device_initcall(acpuclk_a7_init);
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 8eb4b28..41cc1e5 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -116,17 +116,17 @@
 	[1]  = { {  345600, HFPLL, 2,  36 }, LVL_NOM,   950000, 1 },
 	[2]  = { {  422400, HFPLL, 2,  44 }, LVL_NOM,   950000, 1 },
 	[3]  = { {  499200, HFPLL, 2,  52 }, LVL_NOM,   950000, 2 },
-	[4]  = { {  576000, HFPLL, 1,  30 }, LVL_NOM,   950000, 2 },
+	[4]  = { {  576000, HFPLL, 1,  30 }, LVL_NOM,   950000, 3 },
 	[5]  = { {  652800, HFPLL, 1,  34 }, LVL_NOM,   950000, 3 },
 	[6]  = { {  729600, HFPLL, 1,  38 }, LVL_NOM,   950000, 3 },
-	[7]  = { {  806400, HFPLL, 1,  42 }, LVL_HIGH, 1050000, 3 },
+	[7]  = { {  806400, HFPLL, 1,  42 }, LVL_HIGH, 1050000, 4 },
 	[8]  = { {  883200, HFPLL, 1,  46 }, LVL_HIGH, 1050000, 4 },
 	[9]  = { {  960000, HFPLL, 1,  50 }, LVL_HIGH, 1050000, 4 },
-	[10] = { { 1036800, HFPLL, 1,  54 }, LVL_HIGH, 1050000, 4 },
+	[10] = { { 1036800, HFPLL, 1,  54 }, LVL_HIGH, 1050000, 5 },
 	[11] = { { 1113600, HFPLL, 1,  58 }, LVL_HIGH, 1050000, 5 },
-	[12] = { { 1190400, HFPLL, 1,  62 }, LVL_HIGH, 1050000, 5 },
+	[12] = { { 1190400, HFPLL, 1,  62 }, LVL_HIGH, 1050000, 6 },
 	[13] = { { 1267200, HFPLL, 1,  66 }, LVL_HIGH, 1050000, 6 },
-	[14] = { { 1344000, HFPLL, 1,  70 }, LVL_HIGH, 1050000, 6 },
+	[14] = { { 1344000, HFPLL, 1,  70 }, LVL_HIGH, 1050000, 7 },
 	[15] = { { 1420800, HFPLL, 1,  74 }, LVL_HIGH, 1050000, 7 },
 	[16] = { { 1497600, HFPLL, 1,  78 }, LVL_HIGH, 1050000, 7 },
 	{ }
@@ -138,20 +138,20 @@
 	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
 	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
 	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(6),   825000, 3200000 },
-	{ 0, {  729600, HFPLL, 1,  38 }, L2(6),   825000, 3200000 },
-	{ 1, {  806400, HFPLL, 1,  42 }, L2(8),   835000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(8),   845000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 }, L2(8),   860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(8),   880000, 3200000 },
-	{ 1, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
 	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 1, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
-	{ 1, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
 	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 3200000 },
 	{ 0, { 0 } }
 };
@@ -162,20 +162,20 @@
 	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
 	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
 	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(6),   825000, 3200000 },
-	{ 0, {  729600, HFPLL, 1,  38 }, L2(6),   825000, 3200000 },
-	{ 1, {  806400, HFPLL, 1,  42 }, L2(8),   835000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(8),   845000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 }, L2(8),   860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(8),   880000, 3200000 },
-	{ 1, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
 	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 1, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
-	{ 1, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
 	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 3200000 },
 	{ 0, { 0 } }
 };
@@ -186,20 +186,20 @@
 	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
 	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
 	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(6),   825000, 3200000 },
-	{ 0, {  729600, HFPLL, 1,  38 }, L2(6),   825000, 3200000 },
-	{ 1, {  806400, HFPLL, 1,  42 }, L2(8),   825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(8),   825000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 }, L2(8),   835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(8),   855000, 3200000 },
-	{ 1, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
 	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 3200000 },
-	{ 1, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
-	{ 1, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
 	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 3200000 },
 	{ 0, { 0 } }
 };
@@ -210,20 +210,20 @@
 	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
 	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
 	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(6),   825000, 3200000 },
-	{ 0, {  729600, HFPLL, 1,  38 }, L2(6),   825000, 3200000 },
-	{ 1, {  806400, HFPLL, 1,  42 }, L2(8),   825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(8),   825000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 }, L2(8),   835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(8),   855000, 3200000 },
-	{ 1, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
 	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 3200000 },
-	{ 1, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
-	{ 1, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
 	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 3200000 },
 	{ 0, { 0 } }
 };
@@ -234,20 +234,20 @@
 	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),  825000, 3200000 },
 	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),  825000, 3200000 },
 	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(6),  825000, 3200000 },
-	{ 0, {  729600, HFPLL, 1,  38 }, L2(6),  825000, 3200000 },
-	{ 1, {  806400, HFPLL, 1,  42 }, L2(8),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(8),  825000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 }, L2(8),  825000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(8),  825000, 3200000 },
-	{ 1, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),  825000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),  825000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10), 825000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10), 825000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10), 825000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10), 825000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 3200000 },
 	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12), 885000, 3200000 },
-	{ 1, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 3200000 },
-	{ 1, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 3200000 },
 	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 950000, 3200000 },
 	{ 0, { 0 } }
 };
diff --git a/arch/arm/mach-msm/acpuclock-9625.c b/arch/arm/mach-msm/acpuclock-9625.c
index b0556c3..b439088 100644
--- a/arch/arm/mach-msm/acpuclock-9625.c
+++ b/arch/arm/mach-msm/acpuclock-9625.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,96 +15,22 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
 #include <linux/errno.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
 #include <linux/platform_device.h>
-#include <linux/iopoll.h>
+#include <linux/regulator/consumer.h>
 
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
-#include <mach/rpm-regulator.h>
 #include <mach/clk-provider.h>
 #include <mach/rpm-regulator-smd.h>
 
-#include "acpuclock.h"
+#include "acpuclock-cortex.h"
 
-#define RCG_SRC_DIV_MASK		BM(7, 0)
 #define RCG_CONFIG_PGM_DATA_BIT		BIT(11)
 #define RCG_CONFIG_PGM_ENA_BIT		BIT(10)
-#define POLL_INTERVAL_US		1
-#define APCS_RCG_UPDATE_TIMEOUT_US	20
 #define GPLL0_TO_A5_ALWAYS_ENABLE	BIT(18)
 
-#define MAX_VDD_MEM			1050000
-#define MAX_VDD_CPU			1050000
-
-/* Corner type vreg VDD values */
-#define LVL_NONE        RPM_REGULATOR_CORNER_NONE
-#define LVL_LOW         RPM_REGULATOR_CORNER_SVS_SOC
-#define LVL_NOM         RPM_REGULATOR_CORNER_NORMAL
-#define LVL_HIGH        RPM_REGULATOR_CORNER_SUPER_TURBO
-
-enum clk_src {
-	CXO,
-	PLL0,
-	ACPUPLL,
-	NUM_SRC,
-};
-
-struct src_clock {
-	struct clk *clk;
-	const char *name;
-};
-
-static struct src_clock src_clocks[NUM_SRC] = {
-	[PLL0].name = "pll0",
-	[ACPUPLL].name = "pll14",
-};
-
-struct clkctl_acpu_speed {
-	bool use_for_scaling;
-	unsigned int khz;
-	int src;
-	unsigned int src_sel;
-	unsigned int src_div;
-	unsigned int vdd_cpu;
-	unsigned int vdd_mem;
-	unsigned int bw_level;
-};
-
-struct acpuclk_drv_data {
-	struct mutex			lock;
-	struct clkctl_acpu_speed	*current_speed;
-	void __iomem			*apcs_rcg_config;
-	void __iomem			*apcs_cpu_pwr_ctl;
-	struct regulator		*vdd_cpu;
-	struct regulator		*vdd_mem;
-};
-
-static struct acpuclk_drv_data drv_data = {
-	.current_speed = &(struct clkctl_acpu_speed){ 0 },
-};
-
-/* Instantaneous bandwidth requests in MB/s. */
-#define BW_MBPS(_bw) \
-	{ \
-		.vectors = &(struct msm_bus_vectors){ \
-			.src = MSM_BUS_MASTER_AMPSS_M0, \
-			.dst = MSM_BUS_SLAVE_EBI_CH0, \
-			.ib = (_bw) * 1000000UL, \
-			.ab = 0, \
-		}, \
-		.num_paths = 1, \
-	}
-
 static struct msm_bus_paths bw_level_tbl[] = {
 	[0] =  BW_MBPS(152), /* At least 19 MHz on bus. */
 	[1] =  BW_MBPS(264), /* At least 33 MHz on bus. */
@@ -123,8 +49,6 @@
 	.name = "acpuclock",
 };
 
-static uint32_t bus_perf_client;
-
 /* TODO:
  * 1) Update MX voltage when they are avaiable
  * 2) Update bus bandwidth
@@ -138,265 +62,31 @@
 	{ 0 }
 };
 
-/* Update the bus bandwidth request. */
-static void set_bus_bw(unsigned int bw)
-{
-	int ret;
-
-	if (bw >= ARRAY_SIZE(bw_level_tbl)) {
-		pr_err("invalid bandwidth request (%d)\n", bw);
-		return;
-	}
-
-	/* Update bandwidth if request has changed. This may sleep. */
-	ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
-	if (ret)
-		pr_err("bandwidth request failed (%d)\n", ret);
-
-	return;
-}
-
-/* Apply any per-cpu voltage increases. */
-static int increase_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
-{
-	int rc = 0;
-
-	/* Increase vdd_mem before vdd_cpu. vdd_mem should be >= vdd_cpu. */
-	rc = regulator_set_voltage(drv_data.vdd_mem, vdd_mem, MAX_VDD_MEM);
-	if (rc) {
-		pr_err("vdd_mem increase failed (%d)\n", rc);
-		return rc;
-	}
-
-	rc = regulator_set_voltage(drv_data.vdd_cpu, vdd_cpu, MAX_VDD_CPU);
-	if (rc)
-		pr_err("vdd_cpu increase failed (%d)\n", rc);
-
-	return rc;
-}
-
-/* Apply any per-cpu voltage decreases. */
-static void decrease_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
-{
-	int ret;
-
-	/* Update CPU voltage. */
-	ret = regulator_set_voltage(drv_data.vdd_cpu, vdd_cpu, MAX_VDD_CPU);
-	if (ret) {
-		pr_err("vdd_cpu decrease failed (%d)\n", ret);
-		return;
-	}
-
-	/* Decrease vdd_mem after vdd_cpu. vdd_mem should be >= vdd_cpu. */
-	ret = regulator_set_voltage(drv_data.vdd_mem, vdd_mem, MAX_VDD_MEM);
-	if (ret)
-		pr_err("vdd_mem decrease failed (%d)\n", ret);
-}
-
-static void select_clk_source_div(struct clkctl_acpu_speed *s)
-{
-	u32 regval, rc, src_div;
-	void __iomem *apcs_rcg_config = drv_data.apcs_rcg_config;
-
-	src_div = s->src_div ? ((2 * s->src_div) - 1) : s->src_div;
-
-	regval = readl_relaxed(apcs_rcg_config);
-	regval &= ~RCG_SRC_DIV_MASK;
-	regval |= BVAL(2, 0, s->src_sel) | BVAL(7, 3, src_div);
-	writel_relaxed(regval, apcs_rcg_config);
-
-	/*
-	 * Make sure writing of src and div finishes before update
-	 * the configuration
-	 */
-	mb();
-
-	/* Update the configruation */
-	regval = readl_relaxed(apcs_rcg_config);
-	regval |= RCG_CONFIG_PGM_DATA_BIT | RCG_CONFIG_PGM_ENA_BIT;
-	writel_relaxed(regval, apcs_rcg_config);
-
-	/* Wait for update to take effect */
-	rc = readl_poll_timeout(apcs_rcg_config, regval,
-		   !(regval & RCG_CONFIG_PGM_DATA_BIT),
-		   POLL_INTERVAL_US,
-		   APCS_RCG_UPDATE_TIMEOUT_US);
-	if (rc)
-		pr_warn("acpu rcg didn't update its configuration\n");
-}
-
-static int set_speed(struct clkctl_acpu_speed *tgt_s)
-{
-	int rc = 0;
-	unsigned int tgt_freq_hz = tgt_s->khz * 1000;
-	struct clkctl_acpu_speed *strt_s = drv_data.current_speed;
-	struct clkctl_acpu_speed *cxo_s = &acpu_freq_tbl[0];
-	struct clk *strt = src_clocks[strt_s->src].clk;
-	struct clk *tgt = src_clocks[tgt_s->src].clk;
-
-	if (strt_s->src == ACPUPLL && tgt_s->src == ACPUPLL) {
-		/* Switch to another always on src */
-		select_clk_source_div(cxo_s);
-
-		/* Re-program acpu pll */
-		clk_disable(tgt);
-		rc = clk_set_rate(tgt, tgt_freq_hz);
-		if (rc)
-			pr_err("Failed to set ACPU PLL to %u\n", tgt_freq_hz);
-		BUG_ON(clk_enable(tgt));
-
-		/* Switch back to acpu pll */
-		select_clk_source_div(tgt_s);
-	} else if (strt_s->src != ACPUPLL && tgt_s->src == ACPUPLL) {
-		rc = clk_set_rate(tgt, tgt_freq_hz);
-		if (rc) {
-			pr_err("Failed to set ACPU PLL to %u\n", tgt_freq_hz);
-			return rc;
-		}
-
-		rc = clk_enable(tgt);
-		if (rc) {
-			pr_err("ACPU PLL enable failed\n");
-			return rc;
-		}
-
-		select_clk_source_div(tgt_s);
-
-		clk_disable(strt);
-	} else {
-		rc = clk_enable(tgt);
-		if (rc) {
-			pr_err("%s enable failed\n",
-					src_clocks[tgt_s->src].name);
-			return rc;
-		}
-
-		select_clk_source_div(tgt_s);
-
-		clk_disable(strt);
-	}
-
-	return rc;
-}
-
-static int acpuclk_9625_set_rate(int cpu, unsigned long rate,
-				 enum setrate_reason reason)
-{
-	struct clkctl_acpu_speed *tgt_s, *strt_s;
-	int rc = 0;
-
-	if (reason == SETRATE_CPUFREQ)
-		mutex_lock(&drv_data.lock);
-
-	strt_s = drv_data.current_speed;
-
-	/* Return early if rate didn't change */
-	if (rate == strt_s->khz)
-		goto out;
-
-	/* Find target frequency */
-	for (tgt_s = acpu_freq_tbl; tgt_s->khz != 0; tgt_s++)
-		if (tgt_s->khz == rate)
-			break;
-	if (tgt_s->khz == 0) {
-		rc = -EINVAL;
-		goto out;
-	}
-
-	/* Increase VDD levels if needed */
-	if ((reason == SETRATE_CPUFREQ || reason == SETRATE_INIT)
-			&& (tgt_s->khz > strt_s->khz)) {
-		rc = increase_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
-		if (rc)
-			goto out;
-	}
-
-	pr_debug("Switching from CPU rate %u KHz -> %u KHz\n",
-		strt_s->khz, tgt_s->khz);
-
-	/* Switch CPU speed. */
-	rc = set_speed(tgt_s);
-	if (rc)
-		goto out;
-
-	drv_data.current_speed = tgt_s;
-	pr_debug("CPU speed change complete\n");
-
-	/* Nothing else to do for SWFI or power-collapse. */
-	if (reason == SETRATE_SWFI || reason == SETRATE_PC)
-		goto out;
-
-	/* Update bus bandwith request */
-	set_bus_bw(tgt_s->bw_level);
-
-	/* Drop VDD levels if we can. */
-	if (tgt_s->khz < strt_s->khz)
-		decrease_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
-
-out:
-	if (reason == SETRATE_CPUFREQ)
-		mutex_unlock(&drv_data.lock);
-	return rc;
-}
-
-static unsigned long acpuclk_9625_get_rate(int cpu)
-{
-	return drv_data.current_speed->khz;
-}
-
-#ifdef CONFIG_CPU_FREQ_MSM
-static struct cpufreq_frequency_table freq_table[30];
-
-static void __init cpufreq_table_init(void)
-{
-	int i, freq_cnt = 0;
-
-	/* Construct the freq_table tables from acpu_freq_tbl. */
-	for (i = 0; acpu_freq_tbl[i].khz != 0
-			&& freq_cnt < ARRAY_SIZE(freq_table); i++) {
-		if (!acpu_freq_tbl[i].use_for_scaling)
-			continue;
-		freq_table[freq_cnt].index = freq_cnt;
-		freq_table[freq_cnt].frequency = acpu_freq_tbl[i].khz;
-		freq_cnt++;
-	}
-	/* freq_table not big enough to store all usable freqs. */
-	BUG_ON(acpu_freq_tbl[i].khz != 0);
-
-	freq_table[freq_cnt].index = freq_cnt;
-	freq_table[freq_cnt].frequency = CPUFREQ_TABLE_END;
-
-	pr_info("CPU: %d scaling frequencies supported.\n", freq_cnt);
-
-	/* Register table with CPUFreq. */
-	cpufreq_frequency_table_get_attr(freq_table, smp_processor_id());
-}
-#else
-static void __init cpufreq_table_init(void) {}
-#endif
-
-static struct acpuclk_data acpuclk_9625_data = {
-	.set_rate = acpuclk_9625_set_rate,
-	.get_rate = acpuclk_9625_get_rate,
-	.power_collapse_khz = 19200,
-	.wait_for_irq_khz = 19200,
+static struct acpuclk_drv_data drv_data = {
+	.freq_tbl = acpu_freq_tbl,
+	.current_speed = &(struct clkctl_acpu_speed){ 0 },
+	.bus_scale = &bus_client_pdata,
+	.vdd_max_cpu = LVL_HIGH,
+	.vdd_max_mem = 1050000,
+	.src_clocks = {
+		[PLL0].name = "pll0",
+		[ACPUPLL].name = "pll14",
+	},
+	.reg_data = {
+		.cfg_src_mask = BM(2, 0),
+		.cfg_src_shift = 0,
+		.cfg_div_mask = BM(7, 3),
+		.cfg_div_shift = 3,
+		.update_mask = RCG_CONFIG_PGM_DATA_BIT | RCG_CONFIG_PGM_ENA_BIT,
+		.poll_mask = RCG_CONFIG_PGM_DATA_BIT,
+	},
 };
 
 static int __init acpuclk_9625_probe(struct platform_device *pdev)
 {
-	unsigned long max_cpu_khz = 0;
 	struct resource *res;
-	int i, rc;
 	u32 regval;
 
-	mutex_init(&drv_data.lock);
-
-	bus_perf_client = msm_bus_scale_register_client(&bus_client_pdata);
-	if (!bus_perf_client) {
-		pr_err("Unable to register bus client\n");
-		BUG();
-	}
-
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
 	if (!res)
 		return -EINVAL;
@@ -405,6 +95,8 @@
 	if (!drv_data.apcs_rcg_config)
 		return -ENOMEM;
 
+	drv_data.apcs_rcg_cmd = drv_data.apcs_rcg_config;
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwr_base");
 	if (!res)
 		return -EINVAL;
@@ -430,60 +122,7 @@
 	regval |= GPLL0_TO_A5_ALWAYS_ENABLE;
 	writel_relaxed(regval, drv_data.apcs_cpu_pwr_ctl);
 
-	for (i = 0; i < NUM_SRC; i++) {
-		if (!src_clocks[i].name)
-			continue;
-		src_clocks[i].clk = clk_get(&pdev->dev, src_clocks[i].name);
-		BUG_ON(IS_ERR(src_clocks[i].clk));
-		/*
-		 * Prepare the PLLs because we enable/disable them
-		 * in atomic context during power collapse/restore.
-		 */
-		BUG_ON(clk_prepare(src_clocks[i].clk));
-	}
-
-	/* Improve boot time by ramping up CPU immediately */
-	for (i = 0; acpu_freq_tbl[i].khz != 0 &&
-				acpu_freq_tbl[i].use_for_scaling; i++)
-		max_cpu_khz = acpu_freq_tbl[i].khz;
-
-	/* Initialize regulators */
-	rc = increase_vdd(acpu_freq_tbl[i].vdd_cpu, acpu_freq_tbl[i].vdd_mem);
-	if (rc)
-		goto err_vdd;
-
-	rc = regulator_enable(drv_data.vdd_mem);
-	if (rc) {
-		dev_err(&pdev->dev, "regulator_enable for a5_mem failed\n");
-		goto err_vdd;
-	}
-
-	rc = regulator_enable(drv_data.vdd_cpu);
-	if (rc) {
-		dev_err(&pdev->dev, "regulator_enable for a5_cpu failed\n");
-		goto err_vdd_cpu;
-	}
-
-	acpuclk_9625_set_rate(smp_processor_id(), max_cpu_khz, SETRATE_INIT);
-
-	acpuclk_register(&acpuclk_9625_data);
-	cpufreq_table_init();
-
-	return 0;
-
-err_vdd_cpu:
-	regulator_disable(drv_data.vdd_mem);
-err_vdd:
-	regulator_put(drv_data.vdd_mem);
-	regulator_put(drv_data.vdd_cpu);
-
-	for (i = 0; i < NUM_SRC; i++) {
-		if (!src_clocks[i].name)
-			continue;
-		clk_unprepare(src_clocks[i].clk);
-		clk_put(src_clocks[i].clk);
-	}
-	return rc;
+	return acpuclk_cortex_init(pdev, &drv_data);
 }
 
 static struct of_device_id acpuclk_9625_match_table[] = {
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
new file mode 100644
index 0000000..64e31ba
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/iopoll.h>
+
+#include <mach/board.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/rpm-regulator.h>
+#include <mach/clk-provider.h>
+#include <mach/rpm-regulator-smd.h>
+
+#include "acpuclock.h"
+#include "acpuclock-cortex.h"
+
+#define POLL_INTERVAL_US		1
+#define APCS_RCG_UPDATE_TIMEOUT_US	20
+
+static struct acpuclk_drv_data *acpuclk_init_data;
+static uint32_t bus_perf_client;
+
+/* Update the bus bandwidth request. */
+static void set_bus_bw(unsigned int bw)
+{
+	int ret;
+
+	if (bw >= acpuclk_init_data->bus_scale->num_usecases) {
+		pr_err("invalid bandwidth request (%d)\n", bw);
+		return;
+	}
+
+	/* Update bandwidth if request has changed. This may sleep. */
+	ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
+	if (ret)
+		pr_err("bandwidth request failed (%d)\n", ret);
+
+	return;
+}
+
+/* Apply any voltage increases. */
+static int increase_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
+{
+	int rc = 0;
+
+	/* Increase vdd_mem before vdd_cpu. vdd_mem should be >= vdd_cpu. */
+	rc = regulator_set_voltage(acpuclk_init_data->vdd_mem, vdd_mem,
+		acpuclk_init_data->vdd_max_mem);
+	if (rc) {
+		pr_err("vdd_mem increase failed (%d)\n", rc);
+		return rc;
+	}
+
+	rc = regulator_set_voltage(acpuclk_init_data->vdd_cpu, vdd_cpu,
+		acpuclk_init_data->vdd_max_cpu);
+	if (rc)
+		pr_err("vdd_cpu increase failed (%d)\n", rc);
+
+	return rc;
+}
+
+/* Apply any per-cpu voltage decreases. */
+static void decrease_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
+{
+	int ret;
+
+	/* Update CPU voltage. */
+	ret = regulator_set_voltage(acpuclk_init_data->vdd_cpu, vdd_cpu,
+		acpuclk_init_data->vdd_max_cpu);
+	if (ret) {
+		pr_err("vdd_cpu decrease failed (%d)\n", ret);
+		return;
+	}
+
+	/* Decrease vdd_mem after vdd_cpu. vdd_mem should be >= vdd_cpu. */
+	ret = regulator_set_voltage(acpuclk_init_data->vdd_mem, vdd_mem,
+		acpuclk_init_data->vdd_max_mem);
+	if (ret)
+		pr_err("vdd_mem decrease failed (%d)\n", ret);
+}
+
+static void select_clk_source_div(struct acpuclk_drv_data *drv_data,
+	struct clkctl_acpu_speed *s)
+{
+	u32 regval, rc, src_div;
+	void __iomem *apcs_rcg_config = drv_data->apcs_rcg_config;
+	void __iomem *apcs_rcg_cmd = drv_data->apcs_rcg_cmd;
+	struct acpuclk_reg_data *r = &drv_data->reg_data;
+
+	src_div = s->src_div ? ((2 * s->src_div) - 1) : s->src_div;
+
+	regval = readl_relaxed(apcs_rcg_config);
+	regval &= ~r->cfg_src_mask;
+	regval |= s->src_sel << r->cfg_src_shift;
+	regval &= ~r->cfg_div_mask;
+	regval |= src_div << r->cfg_div_shift;
+	writel_relaxed(regval, apcs_rcg_config);
+
+	/* Update the configuration */
+	regval = readl_relaxed(apcs_rcg_cmd);
+	regval |= r->update_mask;
+	writel_relaxed(regval, apcs_rcg_cmd);
+
+	/* Wait for the update to take effect */
+	rc = readl_poll_timeout(apcs_rcg_cmd, regval,
+		   !(regval & r->poll_mask),
+		   POLL_INTERVAL_US,
+		   APCS_RCG_UPDATE_TIMEOUT_US);
+	if (rc)
+		pr_warn("acpu rcg didn't update its configuration\n");
+}
+
+static int set_speed(struct clkctl_acpu_speed *tgt_s)
+{
+	int rc = 0;
+	unsigned int tgt_freq_hz = tgt_s->khz * 1000;
+	struct clkctl_acpu_speed *strt_s = acpuclk_init_data->current_speed;
+	struct clkctl_acpu_speed *cxo_s = &acpuclk_init_data->freq_tbl[0];
+	struct clk *strt = acpuclk_init_data->src_clocks[strt_s->src].clk;
+	struct clk *tgt = acpuclk_init_data->src_clocks[tgt_s->src].clk;
+
+	if (strt_s->src == ACPUPLL && tgt_s->src == ACPUPLL) {
+		/* Switch to another always on src */
+		select_clk_source_div(acpuclk_init_data, cxo_s);
+
+		/* Re-program acpu pll */
+		clk_disable(tgt);
+		rc = clk_set_rate(tgt, tgt_freq_hz);
+		if (rc)
+			pr_err("Failed to set ACPU PLL to %u\n", tgt_freq_hz);
+		BUG_ON(clk_enable(tgt));
+
+		/* Switch back to acpu pll */
+		select_clk_source_div(acpuclk_init_data, tgt_s);
+
+	} else if (strt_s->src != ACPUPLL && tgt_s->src == ACPUPLL) {
+		rc = clk_set_rate(tgt, tgt_freq_hz);
+		if (rc) {
+			pr_err("Failed to set ACPU PLL to %u\n", tgt_freq_hz);
+			return rc;
+		}
+
+		rc = clk_enable(tgt);
+		if (rc) {
+			pr_err("ACPU PLL enable failed\n");
+			return rc;
+		}
+
+		select_clk_source_div(acpuclk_init_data, tgt_s);
+
+		clk_disable(strt);
+	} else {
+		rc = clk_enable(tgt);
+		if (rc) {
+			pr_err("%s enable failed\n",
+				acpuclk_init_data->src_clocks[tgt_s->src].name);
+			return rc;
+		}
+
+		select_clk_source_div(acpuclk_init_data, tgt_s);
+
+		clk_disable(strt);
+	}
+
+	return rc;
+}
+
+static int acpuclk_cortex_set_rate(int cpu, unsigned long rate,
+				 enum setrate_reason reason)
+{
+	struct clkctl_acpu_speed *tgt_s, *strt_s;
+	int rc = 0;
+
+	if (reason == SETRATE_CPUFREQ)
+		mutex_lock(&acpuclk_init_data->lock);
+
+	strt_s = acpuclk_init_data->current_speed;
+
+	/* Return early if rate didn't change */
+	if (rate == strt_s->khz)
+		goto out;
+
+	/* Find target frequency */
+	for (tgt_s = acpuclk_init_data->freq_tbl; tgt_s->khz != 0; tgt_s++)
+		if (tgt_s->khz == rate)
+			break;
+	if (tgt_s->khz == 0) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* Increase VDD levels if needed */
+	if ((reason == SETRATE_CPUFREQ || reason == SETRATE_INIT)
+			&& (tgt_s->khz > strt_s->khz)) {
+		rc = increase_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
+		if (rc)
+			goto out;
+	}
+
+	pr_debug("Switching from CPU rate %u KHz -> %u KHz\n",
+		strt_s->khz, tgt_s->khz);
+
+	/* Switch CPU speed. */
+	rc = set_speed(tgt_s);
+	if (rc)
+		goto out;
+
+	acpuclk_init_data->current_speed = tgt_s;
+	pr_debug("CPU speed change complete\n");
+
+	/* Nothing else to do for SWFI or power-collapse. */
+	if (reason == SETRATE_SWFI || reason == SETRATE_PC)
+		goto out;
+
+	/* Update bus bandwith request */
+	set_bus_bw(tgt_s->bw_level);
+
+	/* Drop VDD levels if we can. */
+	if (tgt_s->khz < strt_s->khz)
+		decrease_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
+
+out:
+	if (reason == SETRATE_CPUFREQ)
+		mutex_unlock(&acpuclk_init_data->lock);
+	return rc;
+}
+
+static unsigned long acpuclk_cortex_get_rate(int cpu)
+{
+	return acpuclk_init_data->current_speed->khz;
+}
+
+#ifdef CONFIG_CPU_FREQ_MSM
+static struct cpufreq_frequency_table freq_table[30];
+
+static void __init cpufreq_table_init(void)
+{
+	int i, freq_cnt = 0;
+
+	/* Construct the freq_table tables from acpuclk_init_data->freq_tbl. */
+	for (i = 0; acpuclk_init_data->freq_tbl[i].khz != 0
+			&& freq_cnt < ARRAY_SIZE(freq_table); i++) {
+		if (!acpuclk_init_data->freq_tbl[i].use_for_scaling)
+			continue;
+		freq_table[freq_cnt].index = freq_cnt;
+		freq_table[freq_cnt].frequency =
+			acpuclk_init_data->freq_tbl[i].khz;
+		freq_cnt++;
+	}
+	/* freq_table not big enough to store all usable freqs. */
+	BUG_ON(acpuclk_init_data->freq_tbl[i].khz != 0);
+
+	freq_table[freq_cnt].index = freq_cnt;
+	freq_table[freq_cnt].frequency = CPUFREQ_TABLE_END;
+
+	pr_info("CPU: %d scaling frequencies supported.\n", freq_cnt);
+
+	/* Register table with CPUFreq. */
+	for_each_possible_cpu(i)
+		cpufreq_frequency_table_get_attr(freq_table, i);
+}
+#else
+static void __init cpufreq_table_init(void) {}
+#endif
+
+static struct acpuclk_data acpuclk_cortex_data = {
+	.set_rate = acpuclk_cortex_set_rate,
+	.get_rate = acpuclk_cortex_get_rate,
+	.power_collapse_khz = 19200,
+	.wait_for_irq_khz = 19200,
+};
+
+int __init acpuclk_cortex_init(struct platform_device *pdev,
+	struct acpuclk_drv_data *data)
+{
+	unsigned long max_cpu_khz = 0;
+	int i, rc;
+
+	acpuclk_init_data = data;
+	mutex_init(&acpuclk_init_data->lock);
+
+	bus_perf_client = msm_bus_scale_register_client(
+		acpuclk_init_data->bus_scale);
+	if (!bus_perf_client) {
+		pr_err("Unable to register bus client\n");
+		BUG();
+	}
+
+	for (i = 0; i < NUM_SRC; i++) {
+		if (!acpuclk_init_data->src_clocks[i].name)
+			continue;
+		acpuclk_init_data->src_clocks[i].clk =
+			clk_get(&pdev->dev,
+				acpuclk_init_data->src_clocks[i].name);
+		BUG_ON(IS_ERR(acpuclk_init_data->src_clocks[i].clk));
+		/*
+		 * Prepare the PLLs because we enable/disable them
+		 * in atomic context during power collapse/restore.
+		 */
+		BUG_ON(clk_prepare(acpuclk_init_data->src_clocks[i].clk));
+	}
+
+	/* Improve boot time by ramping up CPU immediately */
+	for (i = 0; acpuclk_init_data->freq_tbl[i].khz != 0 &&
+			acpuclk_init_data->freq_tbl[i].use_for_scaling; i++)
+		max_cpu_khz = acpuclk_init_data->freq_tbl[i].khz;
+
+	/* Initialize regulators */
+	rc = increase_vdd(acpuclk_init_data->freq_tbl[i].vdd_cpu,
+		acpuclk_init_data->freq_tbl[i].vdd_mem);
+	if (rc)
+		goto err_vdd;
+
+	rc = regulator_enable(acpuclk_init_data->vdd_mem);
+	if (rc) {
+		dev_err(&pdev->dev, "regulator_enable for mem failed\n");
+		goto err_vdd;
+	}
+
+	rc = regulator_enable(acpuclk_init_data->vdd_cpu);
+	if (rc) {
+		dev_err(&pdev->dev, "regulator_enable for cpu failed\n");
+		goto err_vdd_cpu;
+	}
+
+	acpuclk_cortex_set_rate(0, max_cpu_khz, SETRATE_INIT);
+
+	acpuclk_register(&acpuclk_cortex_data);
+	cpufreq_table_init();
+
+	return 0;
+
+err_vdd_cpu:
+	regulator_disable(acpuclk_init_data->vdd_mem);
+err_vdd:
+	regulator_put(acpuclk_init_data->vdd_mem);
+	regulator_put(acpuclk_init_data->vdd_cpu);
+
+	for (i = 0; i < NUM_SRC; i++) {
+		if (!acpuclk_init_data->src_clocks[i].name)
+			continue;
+		clk_unprepare(acpuclk_init_data->src_clocks[i].clk);
+		clk_put(acpuclk_init_data->src_clocks[i].clk);
+	}
+	return rc;
+}
diff --git a/arch/arm/mach-msm/acpuclock-cortex.h b/arch/arm/mach-msm/acpuclock-cortex.h
new file mode 100644
index 0000000..2db3987
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-cortex.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+/* Corner type vreg VDD values */
+#define LVL_NONE        RPM_REGULATOR_CORNER_NONE
+#define LVL_LOW         RPM_REGULATOR_CORNER_SVS_SOC
+#define LVL_NOM         RPM_REGULATOR_CORNER_NORMAL
+#define LVL_HIGH        RPM_REGULATOR_CORNER_SUPER_TURBO
+
+enum clk_src {
+	CXO,
+	PLL0,
+	ACPUPLL,
+	NUM_SRC,
+};
+
+struct src_clock {
+	struct clk *clk;
+	const char *name;
+};
+
+struct clkctl_acpu_speed {
+	bool use_for_scaling;
+	unsigned int khz;
+	int src;
+	unsigned int src_sel;
+	unsigned int src_div;
+	unsigned int vdd_cpu;
+	unsigned int vdd_mem;
+	unsigned int bw_level;
+};
+
+struct acpuclk_reg_data {
+	u32 cfg_src_mask;
+	u32 cfg_src_shift;
+	u32 cfg_div_mask;
+	u32 cfg_div_shift;
+	u32 update_mask;
+	u32 poll_mask;
+};
+
+struct acpuclk_drv_data {
+	struct mutex			lock;
+	struct clkctl_acpu_speed	*freq_tbl;
+	struct clkctl_acpu_speed	*current_speed;
+	struct msm_bus_scale_pdata	*bus_scale;
+	void __iomem			*apcs_rcg_config;
+	void __iomem			*apcs_rcg_cmd;
+	void __iomem			*apcs_cpu_pwr_ctl;
+	struct regulator		*vdd_cpu;
+	unsigned long			vdd_max_cpu;
+	struct regulator		*vdd_mem;
+	unsigned long			vdd_max_mem;
+	struct src_clock		src_clocks[NUM_SRC];
+	struct acpuclk_reg_data		reg_data;
+};
+
+/* Instantaneous bandwidth requests in MB/s. */
+#define BW_MBPS(_bw) \
+	{ \
+		.vectors = &(struct msm_bus_vectors){ \
+			.src = MSM_BUS_MASTER_AMPSS_M0, \
+			.dst = MSM_BUS_SLAVE_EBI_CH0, \
+			.ib = (_bw) * 1000000ULL, \
+			.ab = 0, \
+		}, \
+		.num_paths = 1, \
+	}
+
+int __init acpuclk_cortex_init(struct platform_device *pdev,
+	struct acpuclk_drv_data *data);
+
diff --git a/arch/arm/mach-msm/bms-batterydata-oem.c b/arch/arm/mach-msm/bms-batterydata-oem.c
new file mode 100644
index 0000000..036bf88
--- /dev/null
+++ b/arch/arm/mach-msm/bms-batterydata-oem.c
@@ -0,0 +1,108 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
+
+static struct single_row_lut fcc_temp = {
+	.x		= {-20, 0, 25, 40, 65},
+	.y		= {1492, 1492, 1493, 1483, 1502},
+	.cols	= 5
+};
+
+static struct pc_temp_ocv_lut pc_temp_ocv = {
+	.rows		= 29,
+	.cols		= 5,
+	.temp		= {-20, 0, 25, 40, 65},
+	.percent	= {100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40,
+					35, 30, 25, 20, 15, 10, 9, 8, 7, 6, 5,
+					4, 3, 2, 1, 0},
+	.ocv		= {
+				{4173, 4167, 4163, 4156, 4154},
+				{4104, 4107, 4108, 4102, 4104},
+				{4057, 4072, 4069, 4061, 4060},
+				{3973, 4009, 4019, 4016, 4020},
+				{3932, 3959, 3981, 3982, 3983},
+				{3899, 3928, 3954, 3950, 3950},
+				{3868, 3895, 3925, 3921, 3920},
+				{3837, 3866, 3898, 3894, 3892},
+				{3812, 3841, 3853, 3856, 3862},
+				{3794, 3818, 3825, 3823, 3822},
+				{3780, 3799, 3804, 3804, 3803},
+				{3768, 3787, 3790, 3788, 3788},
+				{3757, 3779, 3778, 3775, 3776},
+				{3747, 3772, 3771, 3766, 3765},
+				{3736, 3763, 3766, 3760, 3746},
+				{3725, 3749, 3756, 3747, 3729},
+				{3714, 3718, 3734, 3724, 3706},
+				{3701, 3703, 3696, 3689, 3668},
+				{3675, 3695, 3682, 3675, 3662},
+				{3670, 3691, 3680, 3673, 3661},
+				{3661, 3686, 3679, 3672, 3656},
+				{3649, 3680, 3676, 3669, 3641},
+				{3633, 3669, 3667, 3655, 3606},
+				{3610, 3647, 3640, 3620, 3560},
+				{3580, 3607, 3596, 3572, 3501},
+				{3533, 3548, 3537, 3512, 3425},
+				{3457, 3468, 3459, 3429, 3324},
+				{3328, 3348, 3340, 3297, 3172},
+				{3000, 3000, 3000, 3000, 3000}
+	}
+};
+
+static struct sf_lut rbatt_sf = {
+	.rows		= 29,
+	.cols		= 5,
+	/* row_entries are temperature */
+	.row_entries	= {-20, 0, 20, 40, 65},
+	.percent	= {100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40,
+					35, 30, 25, 20, 15, 10, 9, 8, 7, 6, 5,
+					4, 3, 2, 1, 0},
+	.sf		= {
+				{357, 187, 100, 91, 91},
+				{400, 208, 105, 94, 94},
+				{390, 204, 106, 95, 96},
+				{391, 201, 108, 98, 98},
+				{391, 202, 110, 98, 100},
+				{390, 200, 110, 99, 102},
+				{389, 200, 110, 99, 102},
+				{393, 202, 101, 93, 100},
+				{407, 205, 99, 89, 94},
+				{428, 208, 100, 91, 96},
+				{455, 212, 102, 92, 98},
+				{495, 220, 104, 93, 101},
+				{561, 232, 107, 95, 102},
+				{634, 245, 112, 98, 98},
+				{714, 258, 114, 98, 98},
+				{791, 266, 114, 97, 100},
+				{871, 289, 108, 95, 97},
+				{973, 340, 124, 108, 105},
+				{489, 241, 109, 96, 99},
+				{511, 246, 110, 96, 99},
+				{534, 252, 111, 95, 98},
+				{579, 263, 112, 96, 96},
+				{636, 276, 111, 95, 97},
+				{730, 294, 109, 96, 99},
+				{868, 328, 112, 98, 104},
+				{1089, 374, 119, 101, 115},
+				{1559, 457, 128, 105, 213},
+				{12886, 1026, 637, 422, 3269},
+				{170899, 127211, 98968, 88907, 77102},
+	}
+};
+
+struct bms_battery_data oem_batt_data = {
+	.fcc			= 1500,
+	.fcc_temp_lut		= &fcc_temp,
+	.pc_temp_ocv_lut	= &pc_temp_ocv,
+	.rbatt_sf_lut		= &rbatt_sf,
+	.default_rbatt_mohm	= 236,
+};
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 3a6eb7f..ea943f9 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -66,41 +66,6 @@
 {
 	return MEMTYPE_EBI1;
 }
-static struct clk_lookup msm_clocks_dummy[] = {
-	CLK_DUMMY("core_clk",   NULL,           "f9926000.i2c", OFF),
-	CLK_DUMMY("iface_clk",  NULL,           "f9926000.i2c", OFF),
-	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
-	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
-	CLK_DUMMY("iface_clk",  HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
-	CLK_DUMMY("core_clk",	HSUSB_CORE_CLK, "f9a55000.usb", OFF),
-	CLK_DUMMY("dfab_clk",	DFAB_CLK, "msm_sps", OFF),
-	CLK_DUMMY("dma_bam_pclk",	DMA_BAM_P_CLK, "msm_sps", OFF),
-	CLK_DUMMY("iface_clk",	NULL,		"msm_sdcc.1", OFF),
-	CLK_DUMMY("core_clk",	NULL,		"msm_sdcc.1", OFF),
-	CLK_DUMMY("bus_clk",	NULL,		"msm_sdcc.1", OFF),
-	CLK_DUMMY("iface_clk",	NULL,		"msm_sdcc.2", OFF),
-	CLK_DUMMY("core_clk",	NULL,		"msm_sdcc.2", OFF),
-	CLK_DUMMY("bus_clk",	NULL,		"msm_sdcc.2", OFF),
-	CLK_DUMMY("core_clk",	NULL,		"f9928000.spi", OFF),
-	CLK_DUMMY("iface_clk",	NULL,		"f9928000.spi", OFF),
-	CLK_DUMMY("iface_clk",		NULL, "fda64000.qcom,iommu", OFF),
-	CLK_DUMMY("core_clk",		NULL, "fda64000.qcom,iommu", OFF),
-	CLK_DUMMY("iface_clk",		NULL, "fda44000.qcom,iommu", OFF),
-	CLK_DUMMY("core_clk",		NULL, "fda44000.qcom,iommu", OFF),
-	CLK_DUMMY("iface_clk",		NULL, "fd928000.qcom,iommu", OFF),
-	CLK_DUMMY("core_clk",		NULL, "fd928000.qcom,iommu", OFF),
-	CLK_DUMMY("core_clk",		NULL, "fdb10000.qcom,iommu", OFF),
-	CLK_DUMMY("iface_clk",		NULL, "fdb10000.qcom,iommu", OFF),
-	CLK_DUMMY("alt_core_clk",	NULL, "fdb10000.qcom,iommu", OFF),
-	CLK_DUMMY("iface_clk",		NULL, "fdc84000.qcom,iommu", OFF),
-	CLK_DUMMY("alt_core_clk",	NULL, "fdc84000.qcom,iommu", OFF),
-	CLK_DUMMY("core_clk",		NULL, "fdc84000.qcom,iommu", OFF),
-};
-
-static struct clock_init_data msm_dummy_clock_init_data __initdata = {
-	.table = msm_clocks_dummy,
-	.size = ARRAY_SIZE(msm_clocks_dummy),
-};
 
 static struct of_dev_auxdata msm8226_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9824000, \
@@ -118,20 +83,32 @@
 static void __init msm8226_early_memory(void)
 {
 	reserve_info = &msm8226_reserve_info;
-	of_scan_flat_dt(dt_scan_for_memory_reserve, msm8226_reserve_table);
+	of_scan_flat_dt(dt_scan_for_memory_hole, msm8226_reserve_table);
 }
 
 static void __init msm8226_reserve(void)
 {
+	reserve_info = &msm8226_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msm8226_reserve_table);
 	msm_reserve();
 }
 
-
+/*
+ * 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 msm8226_add_drivers(void)
 {
 	msm_rpm_driver_init();
 	msm_lpmrs_module_init();
 	msm_spm_device_init();
+	if (machine_is_msm8226_rumi())
+		msm_clock_init(&msm8226_rumi_clock_init_data);
+	else
+		msm_clock_init(&msm8226_clock_init_data);
+
 	msm_thermal_device_init();
 }
 
@@ -143,10 +120,8 @@
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm8226_init_gpiomux();
-	msm8226_add_drivers();
-	msm_clock_init(&msm_dummy_clock_init_data);
 	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
-
+	msm8226_add_drivers();
 }
 
 static const char *msm8226_dt_match[] __initconst = {
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 49d8236..5b3d30c 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -17,6 +17,27 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 
+static struct gpiomux_setting gpio_i2c_config = {
+	.func = GPIOMUX_FUNC_3,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
+	{
+		.gpio      = 10,		/* BLSP-1 QUP-3 I2C_SDA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+		},
+	},
+	{
+		.gpio      = 11,		/* BLSP-1 QUP-3 I2C_SCL */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+		},
+	},
+};
+
 void __init msm8610_init_gpiomux(void)
 {
 	int rc;
@@ -26,4 +47,6 @@
 		pr_err("%s failed %d\n", __func__, rc);
 		return;
 	}
+
+	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
 }
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 322d696..b4f202d 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -81,11 +81,13 @@
 static void __init msm8610_early_memory(void)
 {
 	reserve_info = &msm8610_reserve_info;
-	of_scan_flat_dt(dt_scan_for_memory_reserve, msm8610_reserve_table);
+	of_scan_flat_dt(dt_scan_for_memory_hole, msm8610_reserve_table);
 }
 
 static void __init msm8610_reserve(void)
 {
+	reserve_info = &msm8610_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msm8610_reserve_table);
 	msm_reserve();
 }
 
@@ -95,6 +97,11 @@
 	msm_lpmrs_module_init();
 	msm_spm_device_init();
 	msm_thermal_device_init();
+
+	if (machine_is_msm8610_rumi())
+		msm_clock_init(&msm8610_rumi_clock_init_data);
+	else
+		msm_clock_init(&msm8610_clock_init_data);
 }
 
 void __init msm8610_init(void)
@@ -105,14 +112,8 @@
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm8610_init_gpiomux();
-	msm8610_add_drivers();
-
-	if (machine_is_msm8610_rumi())
-		msm_clock_init(&msm8610_rumi_clock_init_data);
-	else
-		msm_clock_init(&msm8610_clock_init_data);
-
 	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+	msm8610_add_drivers();
 }
 
 static const char *msm8610_dt_match[] __initconst = {
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index ac93b00..eb99073 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -68,6 +68,20 @@
 };
 #endif
 
+static struct gpiomux_setting gpio_suspend_config[] = {
+	{
+		.func = GPIOMUX_FUNC_GPIO,  /* IN-NP */
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+	{
+		.func = GPIOMUX_FUNC_GPIO,  /* O-LOW */
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+		.dir = GPIOMUX_OUT_LOW,
+	},
+};
+
 static struct gpiomux_setting gpio_epm_config = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv  = GPIOMUX_DRV_2MA,
@@ -327,6 +341,49 @@
 	},
 };
 
+static struct gpiomux_setting gpio_uart7_active_cfg = {
+	.func = GPIOMUX_FUNC_3,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gpio_uart7_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config msm_blsp2_uart7_configs[] __initdata = {
+	{
+		.gpio	= 41,	/* BLSP2 UART7 TX */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &gpio_uart7_active_cfg,
+			[GPIOMUX_SUSPENDED] = &gpio_uart7_suspend_cfg,
+		},
+	},
+	{
+		.gpio	= 42,	/* BLSP2 UART7 RX */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &gpio_uart7_active_cfg,
+			[GPIOMUX_SUSPENDED] = &gpio_uart7_suspend_cfg,
+		},
+	},
+	{
+		.gpio	= 43,	/* BLSP2 UART7 CTS */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &gpio_uart7_active_cfg,
+			[GPIOMUX_SUSPENDED] = &gpio_uart7_suspend_cfg,
+		},
+	},
+	{
+		.gpio	= 44,	/* BLSP2 UART7 RFR */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &gpio_uart7_active_cfg,
+			[GPIOMUX_SUSPENDED] = &gpio_uart7_suspend_cfg,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm_rumi_blsp_configs[] __initdata = {
 	{
 		.gpio      = 45,	/* BLSP2 UART8 TX */
@@ -421,25 +478,29 @@
 	{
 		.gpio      = 53,		/* BLSP2 QUP4 SPI_DATA_MOSI */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+			[GPIOMUX_ACTIVE] = &gpio_spi_config,
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio      = 54,		/* BLSP2 QUP4 SPI_DATA_MISO */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+			[GPIOMUX_ACTIVE] = &gpio_spi_config,
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio      = 56,		/* BLSP2 QUP4 SPI_CLK */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+			[GPIOMUX_ACTIVE] = &gpio_spi_config,
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
 		},
 	},
 	{
 		.gpio      = 55,		/* BLSP2 QUP4 SPI_CS0_N */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+			[GPIOMUX_ACTIVE] = &gpio_spi_config,
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
 		},
 	},
 	{
@@ -497,18 +558,25 @@
 	},
 };
 
-static struct gpiomux_setting sd_card_det_config = {
+static struct gpiomux_setting sd_card_det_active_config = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_NONE,
 	.dir = GPIOMUX_IN,
 };
 
+static struct gpiomux_setting sd_card_det_sleep_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+	.dir = GPIOMUX_IN,
+};
+
 static struct msm_gpiomux_config sd_card_det __initdata = {
 	.gpio = 62,
 	.settings = {
-		[GPIOMUX_ACTIVE]    = &sd_card_det_config,
-		[GPIOMUX_SUSPENDED] = &sd_card_det_config,
+		[GPIOMUX_ACTIVE]    = &sd_card_det_active_config,
+		[GPIOMUX_SUSPENDED] = &sd_card_det_sleep_config,
 	},
 };
 
@@ -545,49 +613,49 @@
 		.gpio = 19, /* CCI_I2C_SDA0 */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[2],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
 		},
 	},
 	{
 		.gpio = 20, /* CCI_I2C_SCL0 */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[2],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
 		},
 	},
 	{
 		.gpio = 21, /* CCI_I2C_SDA1 */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[2],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
 		},
 	},
 	{
 		.gpio = 22, /* CCI_I2C_SCL1 */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[2],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
 		},
 	},
 	{
 		.gpio = 23, /* FLASH_LED_EN */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio = 24, /* FLASH_LED_NOW */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio = 25, /* WEBCAM2_RESET_N */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
@@ -601,14 +669,14 @@
 		.gpio = 27, /* OIS_SYNC */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
 		.gpio = 28, /* WEBCAM1_STANDBY */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[0],
-			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
 	{
@@ -922,6 +990,8 @@
 	msm_gpiomux_install(msm_eth_configs, ARRAY_SIZE(msm_eth_configs));
 #endif
 	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+	msm_gpiomux_install(msm_blsp2_uart7_configs,
+			 ARRAY_SIZE(msm_blsp2_uart7_configs));
 	msm_gpiomux_install(wcnss_5wire_interface,
 				ARRAY_SIZE(wcnss_5wire_interface));
 
@@ -945,7 +1015,9 @@
 				ARRAY_SIZE(msm_hsic_hub_configs));
 
 	msm_gpiomux_install(msm_hdmi_configs, ARRAY_SIZE(msm_hdmi_configs));
-	msm_gpiomux_install(msm_mhl_configs, ARRAY_SIZE(msm_mhl_configs));
+	if (machine_is_msm8974_fluid())
+		msm_gpiomux_install(msm_mhl_configs,
+				    ARRAY_SIZE(msm_mhl_configs));
 
 	msm_gpiomux_install(msm8974_pri_auxpcm_configs,
 				 ARRAY_SIZE(msm8974_pri_auxpcm_configs));
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 2fdceae..cc73330 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -42,7 +42,6 @@
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
 #include <mach/socinfo.h>
-#include <mach/msm_bus_board.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
@@ -86,189 +85,17 @@
 	of_scan_flat_dt(dt_scan_for_memory_hole, msm8974_reserve_table);
 }
 
-#define BIMC_BASE	0xfc380000
-#define BIMC_SIZE	0x0006A000
-#define SYS_NOC_BASE	0xfc460000
-#define PERIPH_NOC_BASE 0xFC468000
-#define OCMEM_NOC_BASE	0xfc470000
-#define	MMSS_NOC_BASE	0xfc478000
-#define CONFIG_NOC_BASE	0xfc480000
-#define NOC_SIZE	0x00004000
-
-static struct resource bimc_res[] = {
-	{
-		.start = BIMC_BASE,
-		.end = BIMC_BASE + BIMC_SIZE,
-		.flags = IORESOURCE_MEM,
-		.name = "bimc_mem",
-	},
-};
-
-static struct resource ocmem_noc_res[] = {
-	{
-		.start = OCMEM_NOC_BASE,
-		.end = OCMEM_NOC_BASE + NOC_SIZE,
-		.flags = IORESOURCE_MEM,
-		.name = "ocmem_noc_mem",
-	},
-};
-
-static struct resource mmss_noc_res[] = {
-	{
-		.start = MMSS_NOC_BASE,
-		.end = MMSS_NOC_BASE + NOC_SIZE,
-		.flags = IORESOURCE_MEM,
-		.name = "mmss_noc_mem",
-	},
-};
-
-static struct resource sys_noc_res[] = {
-	{
-		.start = SYS_NOC_BASE,
-		.end = SYS_NOC_BASE + NOC_SIZE,
-		.flags = IORESOURCE_MEM,
-		.name = "sys_noc_mem",
-	},
-};
-
-static struct resource config_noc_res[] = {
-	{
-		.start = CONFIG_NOC_BASE,
-		.end = CONFIG_NOC_BASE + NOC_SIZE,
-		.flags = IORESOURCE_MEM,
-		.name = "config_noc_mem",
-	},
-};
-
-static struct resource periph_noc_res[] = {
-	{
-		.start = PERIPH_NOC_BASE,
-		.end = PERIPH_NOC_BASE + NOC_SIZE,
-		.flags = IORESOURCE_MEM,
-		.name = "periph_noc_mem",
-	},
-};
-
-static struct platform_device msm_bus_sys_noc = {
-	.name  = "msm_bus_fabric",
-	.id    =  MSM_BUS_FAB_SYS_NOC,
-	.num_resources = ARRAY_SIZE(sys_noc_res),
-	.resource = sys_noc_res,
-};
-
-static struct platform_device msm_bus_bimc = {
-	.name  = "msm_bus_fabric",
-	.id    = MSM_BUS_FAB_BIMC,
-	.num_resources = ARRAY_SIZE(bimc_res),
-	.resource = bimc_res,
-};
-
-static struct platform_device msm_bus_mmss_noc = {
-	.name  = "msm_bus_fabric",
-	.id    = MSM_BUS_FAB_MMSS_NOC,
-	.num_resources = ARRAY_SIZE(mmss_noc_res),
-	.resource = mmss_noc_res,
-};
-
-static struct platform_device msm_bus_ocmem_noc = {
-	.name  = "msm_bus_fabric",
-	.id    = MSM_BUS_FAB_OCMEM_NOC,
-	.num_resources = ARRAY_SIZE(ocmem_noc_res),
-	.resource = ocmem_noc_res,
-};
-
-static struct platform_device msm_bus_periph_noc = {
-	.name  = "msm_bus_fabric",
-	.id    = MSM_BUS_FAB_PERIPH_NOC,
-	.num_resources = ARRAY_SIZE(periph_noc_res),
-	.resource = periph_noc_res,
-};
-
-static struct platform_device msm_bus_config_noc = {
-	.name  = "msm_bus_fabric",
-	.id    = MSM_BUS_FAB_CONFIG_NOC,
-	.num_resources = ARRAY_SIZE(config_noc_res),
-	.resource = config_noc_res,
-};
-
-static struct platform_device msm_bus_ocmem_vnoc = {
-	.name  = "msm_bus_fabric",
-	.id    = MSM_BUS_FAB_OCMEM_VNOC,
-};
-
 static struct platform_device msm_fm_platform_init = {
 	.name  = "iris_fm",
 	.id    = -1,
 };
 
 static struct platform_device *msm_bus_8974_devices[] = {
-	&msm_bus_sys_noc,
-	&msm_bus_bimc,
-	&msm_bus_mmss_noc,
-	&msm_bus_ocmem_noc,
-	&msm_bus_periph_noc,
-	&msm_bus_config_noc,
-	&msm_bus_ocmem_vnoc,
 	&msm_fm_platform_init,
 };
 
-static ssize_t mxt336s_vkeys_show(struct kobject *kobj,
-			struct kobj_attribute *attr, char *buf)
-{
-	return snprintf(buf, 200,
-	__stringify(EV_KEY) ":" __stringify(KEY_BACK) ":62:1345:90:90" \
-	":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":240:1345:90:90" \
-	":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":470:1345:90:90" \
-	":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":658:1345:90:90" \
-	"\n");
-}
-
-static struct kobj_attribute mxt336s_vkeys_attr = {
-	.attr = {
-		.mode = S_IRUGO,
-	},
-	.show = &mxt336s_vkeys_show,
-};
-
-static struct attribute *mxt336s_properties_attrs[] = {
-	&mxt336s_vkeys_attr.attr,
-	NULL
-};
-
-static struct attribute_group mxt336s_properties_attr_group = {
-	.attrs = mxt336s_properties_attrs,
-};
-
-static void mxt_init_vkeys_8974(void)
-{
-	int rc = 0;
-	static struct kobject *mxt336s_properties_kobj;
-
-	mxt336s_vkeys_attr.attr.name = "virtualkeys.atmel_mxt_ts";
-	mxt336s_properties_kobj = kobject_create_and_add("board_properties",
-								NULL);
-	if (mxt336s_properties_kobj)
-		rc = sysfs_create_group(mxt336s_properties_kobj,
-					&mxt336s_properties_attr_group);
-	if (!mxt336s_properties_kobj || rc)
-		pr_err("%s: failed to create board_properties\n",
-				__func__);
-
-	return;
-}
-
 static void __init msm8974_init_buses(void)
 {
-#ifdef CONFIG_MSM_BUS_SCALING
-	msm_bus_sys_noc.dev.platform_data =
-		&msm_bus_8974_sys_noc_pdata;
-	msm_bus_bimc.dev.platform_data = &msm_bus_8974_bimc_pdata;
-	msm_bus_mmss_noc.dev.platform_data = &msm_bus_8974_mmss_noc_pdata;
-	msm_bus_ocmem_noc.dev.platform_data = &msm_bus_8974_ocmem_noc_pdata;
-	msm_bus_periph_noc.dev.platform_data = &msm_bus_8974_periph_noc_pdata;
-	msm_bus_config_noc.dev.platform_data = &msm_bus_8974_config_noc_pdata;
-	msm_bus_ocmem_vnoc.dev.platform_data = &msm_bus_8974_ocmem_vnoc_pdata;
-#endif
 	platform_add_devices(msm_bus_8974_devices,
 				ARRAY_SIZE(msm_bus_8974_devices));
 };
@@ -294,7 +121,6 @@
 		msm_clock_init(&msm8974_clock_init_data);
 	msm8974_init_buses();
 	msm_thermal_device_init();
-	mxt_init_vkeys_8974();
 }
 
 static struct of_dev_auxdata msm8974_auxdata_lookup[] __initdata = {
@@ -355,6 +181,8 @@
 			"qcedev.0", NULL),
 	OF_DEV_AUXDATA("qcom,qcrypto", 0xFD440000, \
 			"qcrypto.0", NULL),
+	OF_DEV_AUXDATA("qcom,hsic-host", 0xF9A00000, \
+			"msm_hsic_host", NULL),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 9b02a5d..923dc2a 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -120,11 +120,13 @@
 static void __init msm9625_early_memory(void)
 {
 	reserve_info = &msm9625_reserve_info;
-	of_scan_flat_dt(dt_scan_for_memory_reserve, msm9625_reserve_table);
+	of_scan_flat_dt(dt_scan_for_memory_hole, msm9625_reserve_table);
 }
 
 static void __init msm9625_reserve(void)
 {
+	reserve_info = &msm9625_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msm9625_reserve_table);
 	msm_reserve();
 }
 
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
new file mode 100644
index 0000000..f65b595
--- /dev/null
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -0,0 +1,4335 @@
+/* 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/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/rpm-regulator-smd.h>
+#include <mach/socinfo.h>
+#include <mach/rpm-smd.h>
+
+#include "clock-local2.h"
+#include "clock-pll.h"
+#include "clock-rpm.h"
+#include "clock-voter.h"
+#include "clock-mdss-8974.h"
+#include "clock.h"
+
+enum {
+	GCC_BASE,
+	MMSS_BASE,
+	LPASS_BASE,
+	APCS_BASE,
+	APCS_PLL_BASE,
+	N_BASES,
+};
+
+static void __iomem *virt_bases[N_BASES];
+
+#define GCC_REG_BASE(x) (void __iomem *)(virt_bases[GCC_BASE] + (x))
+#define MMSS_REG_BASE(x) (void __iomem *)(virt_bases[MMSS_BASE] + (x))
+#define LPASS_REG_BASE(x) (void __iomem *)(virt_bases[LPASS_BASE] + (x))
+#define APCS_REG_BASE(x) (void __iomem *)(virt_bases[APCS_BASE] + (x))
+
+/* Mux source select values */
+#define xo_source_val  0
+#define gpll0_source_val 1
+#define gpll1_source_val 2
+
+#define xo_mm_source_val 0
+#define mmpll0_pll_mm_source_val 1
+#define mmpll1_pll_mm_source_val 2
+#define mmpll2_pll_mm_source_val 3
+#define gpll0_mm_source_val 5
+#define dsipll_750_mm_source_val 1
+#define dsipll_667_mm_source_val 1
+
+#define gpll1_hsic_source_val 4
+
+#define xo_lpass_source_val 0
+#define lpaaudio_pll_lpass_source_val 1
+#define gpll0_lpass_source_val 5
+
+/* Prevent a divider of -1 */
+#define FIXDIV(div) (div ? (2 * (div) - 1) : (0))
+
+#define F_GCC(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(FIXDIV(div))) \
+			| BVAL(10, 8, s##_source_val), \
+	}
+
+#define F_MMSS(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(FIXDIV(div))) \
+			| BVAL(10, 8, s##_mm_source_val), \
+	}
+
+#define F_MDSS(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(FIXDIV(div))) \
+			| BVAL(10, 8, s##_mm_source_val), \
+	}
+
+#define F_HSIC(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(FIXDIV(div))) \
+			| BVAL(10, 8, s##_hsic_source_val), \
+	}
+
+#define F_LPASS(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(FIXDIV(div))) \
+			| BVAL(10, 8, s##_lpass_source_val), \
+	}
+
+#define F_APCS_PLL(f, l, m, n, pre_div, post_div, vco) \
+	{ \
+		.freq_hz = (f), \
+		.l_val = (l), \
+		.m_val = (m), \
+		.n_val = (n), \
+		.pre_div_val = BVAL(12, 12, (pre_div)), \
+		.post_div_val = BVAL(9, 8, (post_div)), \
+		.vco_val = BVAL(29, 28, (vco)), \
+	}
+
+#define VDD_DIG_FMAX_MAP1(l1, f1) \
+	.vdd_class = &vdd_dig, \
+	.fmax = (unsigned long[VDD_DIG_NUM]) {  \
+		[VDD_DIG_##l1] = (f1),          \
+	},                                      \
+	.num_fmax = VDD_DIG_NUM
+
+#define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \
+	.vdd_class = &vdd_dig, \
+	.fmax = (unsigned long[VDD_DIG_NUM]) {  \
+		[VDD_DIG_##l1] = (f1),          \
+		[VDD_DIG_##l2] = (f2),          \
+	},                                      \
+	.num_fmax = VDD_DIG_NUM
+
+#define VDD_DIG_FMAX_MAP3(l1, f1, l2, f2, l3, f3) \
+	.vdd_class = &vdd_dig, \
+	.fmax = (unsigned long[VDD_DIG_NUM]) {  \
+		[VDD_DIG_##l1] = (f1),          \
+		[VDD_DIG_##l2] = (f2),          \
+		[VDD_DIG_##l3] = (f3),          \
+	},                                      \
+	.num_fmax = VDD_DIG_NUM
+
+enum vdd_dig_levels {
+	VDD_DIG_NONE,
+	VDD_DIG_LOW,
+	VDD_DIG_NOMINAL,
+	VDD_DIG_HIGH,
+	VDD_DIG_NUM
+};
+
+static const int vdd_corner[] = {
+	[VDD_DIG_NONE]	  = RPM_REGULATOR_CORNER_NONE,
+	[VDD_DIG_LOW]	  = RPM_REGULATOR_CORNER_SVS_SOC,
+	[VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
+	[VDD_DIG_HIGH]	  = RPM_REGULATOR_CORNER_SUPER_TURBO,
+};
+
+static struct regulator *vdd_dig_reg;
+
+static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
+{
+	return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
+					RPM_REGULATOR_CORNER_SUPER_TURBO);
+}
+
+static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+
+#define RPM_MISC_CLK_TYPE	0x306b6c63
+#define RPM_BUS_CLK_TYPE	0x316b6c63
+#define RPM_MEM_CLK_TYPE	0x326b6c63
+
+#define RPM_SMD_KEY_ENABLE	0x62616E45
+
+#define CXO_ID			0x0
+#define QDSS_ID			0x1
+
+#define PNOC_ID		0x0
+#define SNOC_ID		0x1
+#define CNOC_ID		0x2
+#define MMSSNOC_AHB_ID  0x3
+
+#define BIMC_ID		0x0
+#define OXILI_ID	0x1
+#define OCMEM_ID	0x2
+
+#define D0_ID		 1
+#define D1_ID		 2
+#define A0_ID		 4
+#define A1_ID		 5
+#define A2_ID		 6
+#define DIFF_CLK_ID	 7
+#define DIV_CLK1_ID	11
+#define DIV_CLK2_ID	12
+
+DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(cnoc_clk, cnoc_a_clk, RPM_BUS_CLK_TYPE, CNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, RPM_BUS_CLK_TYPE,
+			MMSSNOC_AHB_ID, NULL);
+
+DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
+DEFINE_CLK_RPM_SMD(ocmemgx_clk, ocmemgx_a_clk, RPM_MEM_CLK_TYPE, OCMEM_ID,
+			NULL);
+DEFINE_CLK_RPM_SMD(gfx3d_clk_src, gfx3d_a_clk_src, RPM_MEM_CLK_TYPE, OXILI_ID,
+			NULL);
+
+DEFINE_CLK_RPM_SMD_BRANCH(xo, xo_a_clk,
+				RPM_MISC_CLK_TYPE, CXO_ID, 19200000);
+DEFINE_CLK_RPM_SMD_QDSS(qdss_clk, qdss_a_clk, RPM_MISC_CLK_TYPE, QDSS_ID);
+
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_d0, cxo_d0_a, D0_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_d1, cxo_d1_a, D1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a0, cxo_a0_a, A0_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a1, cxo_a1_a, A1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a2, cxo_a2_a, A2_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(div_clk1, div_a_clk1, DIV_CLK1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(div_clk2, div_a_clk2, DIV_CLK2_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(diff_clk, diff_a_clk, DIFF_CLK_ID);
+
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d0_pin, cxo_d0_a_pin, D0_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d1_pin, cxo_d1_a_pin, D1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a0_pin, cxo_a0_a_pin, A0_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a1_pin, cxo_a1_a_pin, A1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a2_pin, cxo_a2_a_pin, A2_ID);
+
+struct measure_mux_entry {
+	struct clk *c;
+	int base;
+	u32 debug_mux;
+};
+
+static struct branch_clk oxilicx_axi_clk;
+
+#define MSS_DEBUG_CLOCK_CTL  0x0078
+#define LPASS_DEBUG_CLK_CTL  0x29000
+#define GLB_CLK_DIAG    0x01C
+#define GLB_TEST_BUS_SEL    0x020
+
+#define MMPLL0_PLL_MODE                                    (0x0000)
+#define MMPLL0_PLL_L_VAL                                   (0x0004)
+#define MMPLL0_PLL_M_VAL                                   (0x0008)
+#define MMPLL0_PLL_N_VAL                                   (0x000C)
+#define MMPLL0_PLL_USER_CTL                                (0x0010)
+#define MMPLL0_PLL_STATUS                                  (0x001C)
+#define MMPLL1_PLL_MODE                                    (0x0040)
+#define MMPLL1_PLL_L_VAL                                   (0x0044)
+#define MMPLL1_PLL_M_VAL                                   (0x0048)
+#define MMPLL1_PLL_N_VAL                                   (0x004C)
+#define MMPLL1_PLL_USER_CTL                                (0x0050)
+#define MMPLL1_PLL_STATUS                                  (0x005C)
+#define MMSS_PLL_VOTE_APCS                                 (0x0100)
+#define VCODEC0_CMD_RCGR                                   (0x1000)
+#define VENUS0_VCODEC0_CBCR                                (0x1028)
+#define VENUS0_AHB_CBCR                                    (0x1030)
+#define VENUS0_AXI_CBCR                                    (0x1034)
+#define PCLK0_CMD_RCGR                                     (0x2000)
+#define MDP_CMD_RCGR                                       (0x2040)
+#define VSYNC_CMD_RCGR                                     (0x2080)
+#define BYTE0_CMD_RCGR                                     (0x2120)
+#define ESC0_CMD_RCGR                                      (0x2160)
+#define MDSS_AHB_CBCR                                      (0x2308)
+#define MDSS_AXI_CBCR                                      (0x2310)
+#define MDSS_PCLK0_CBCR                                    (0x2314)
+#define MDSS_MDP_CBCR                                      (0x231C)
+#define MDSS_MDP_LUT_CBCR                                  (0x2320)
+#define MDSS_VSYNC_CBCR                                    (0x2328)
+#define MDSS_BYTE0_CBCR                                    (0x233C)
+#define MDSS_ESC0_CBCR                                     (0x2344)
+#define CSI0PHYTIMER_CMD_RCGR                              (0x3000)
+#define CAMSS_PHY0_CSI0PHYTIMER_CBCR                       (0x3024)
+#define CSI1PHYTIMER_CMD_RCGR                              (0x3030)
+#define CAMSS_PHY1_CSI1PHYTIMER_CBCR                       (0x3054)
+#define CSI0_CMD_RCGR                                      (0x3090)
+#define CAMSS_CSI0_CBCR                                    (0x30B4)
+#define CAMSS_CSI0_AHB_CBCR                                (0x30BC)
+#define CAMSS_CSI0PHY_CBCR                                 (0x30C4)
+#define CAMSS_CSI0RDI_CBCR                                 (0x30D4)
+#define CAMSS_CSI0PIX_CBCR                                 (0x30E4)
+#define CSI1_CMD_RCGR                                      (0x3100)
+#define CAMSS_CSI1_CBCR                                    (0x3124)
+#define CAMSS_CSI1_AHB_CBCR                                (0x3128)
+#define CAMSS_CSI1PHY_CBCR                                 (0x3134)
+#define CAMSS_CSI1RDI_CBCR                                 (0x3144)
+#define CAMSS_CSI1PIX_CBCR                                 (0x3154)
+#define CAMSS_ISPIF_AHB_CBCR                               (0x3224)
+#define CCI_CMD_RCGR                                       (0x3300)
+#define CAMSS_CCI_CCI_CBCR                                 (0x3344)
+#define CAMSS_CCI_CCI_AHB_CBCR                             (0x3348)
+#define MCLK0_CMD_RCGR                                     (0x3360)
+#define CAMSS_MCLK0_CBCR                                   (0x3384)
+#define MCLK1_CMD_RCGR                                     (0x3390)
+#define CAMSS_MCLK1_CBCR                                   (0x33B4)
+#define MMSS_GP0_CMD_RCGR                                  (0x3420)
+#define CAMSS_GP0_CBCR                                     (0x3444)
+#define MMSS_GP1_CMD_RCGR                                  (0x3450)
+#define CAMSS_GP1_CBCR                                     (0x3474)
+#define CAMSS_TOP_AHB_CBCR                                 (0x3484)
+#define CAMSS_MICRO_AHB_CBCR                               (0x3494)
+#define JPEG0_CMD_RCGR                                     (0x3500)
+#define CAMSS_JPEG_JPEG0_CBCR                              (0x35A8)
+#define CAMSS_JPEG_JPEG_AHB_CBCR                           (0x35B4)
+#define CAMSS_JPEG_JPEG_AXI_CBCR                           (0x35B8)
+#define VFE0_CMD_RCGR                                      (0x3600)
+#define CPP_CMD_RCGR                                       (0x3640)
+#define CAMSS_VFE_VFE0_CBCR                                (0x36A8)
+#define CAMSS_VFE_CPP_CBCR                                 (0x36B0)
+#define CAMSS_VFE_CPP_AHB_CBCR                             (0x36B4)
+#define CAMSS_VFE_VFE_AHB_CBCR                             (0x36B8)
+#define CAMSS_VFE_VFE_AXI_CBCR                             (0x36BC)
+#define CAMSS_CSI_VFE0_CBCR                                (0x3704)
+#define OXILI_GFX3D_CBCR                                   (0x4028)
+#define OXILICX_AXI_CBCR                                   (0x4038)
+#define OXILICX_AHB_CBCR                                   (0x403C)
+#define OCMEMCX_AHB_CBCR                                   (0x405C)
+#define MMPLL2_PLL_MODE                                    (0x4100)
+#define MMPLL2_PLL_STATUS                                  (0x411C)
+#define MMSS_MMSSNOC_AHB_CBCR                              (0x5024)
+#define MMSS_MMSSNOC_BTO_AHB_CBCR                          (0x5028)
+#define MMSS_MISC_AHB_CBCR                                 (0x502C)
+#define AXI_CMD_RCGR                                       (0x5040)
+#define MMSS_S0_AXI_CBCR                                   (0x5064)
+#define MMSS_MMSSNOC_AXI_CBCR                              (0x506C)
+#define MMSS_DEBUG_CLK_CTL                                 (0x0900)
+#define GPLL0_MODE                                         (0x0000)
+#define GPLL0_L_VAL                                        (0x0004)
+#define GPLL0_M_VAL                                        (0x0008)
+#define GPLL0_N_VAL                                        (0x000C)
+#define GPLL0_USER_CTL                                     (0x0010)
+#define GPLL0_STATUS                                       (0x001C)
+#define GPLL1_MODE                                         (0x0040)
+#define GPLL1_L_VAL                                        (0x0044)
+#define GPLL1_M_VAL                                        (0x0048)
+#define GPLL1_N_VAL                                        (0x004C)
+#define GPLL1_USER_CTL                                     (0x0050)
+#define GPLL1_STATUS                                       (0x005C)
+#define PERIPH_NOC_AHB_CBCR                                (0x0184)
+#define NOC_CONF_XPU_AHB_CBCR                              (0x01C0)
+#define MMSS_NOC_CFG_AHB_CBCR                              (0x024C)
+#define MSS_CFG_AHB_CBCR                                   (0x0280)
+#define MSS_Q6_BIMC_AXI_CBCR                               (0x0284)
+#define USB_HS_HSIC_BCR                                    (0x0400)
+#define USB_HSIC_AHB_CBCR                                  (0x0408)
+#define USB_HSIC_SYSTEM_CMD_RCGR                           (0x041C)
+#define USB_HSIC_SYSTEM_CBCR                               (0x040C)
+#define USB_HSIC_CMD_RCGR                                  (0x0440)
+#define USB_HSIC_CBCR                                      (0x0410)
+#define USB_HSIC_IO_CAL_CMD_RCGR                           (0x0458)
+#define USB_HSIC_IO_CAL_CBCR                               (0x0414)
+#define USB_HS_BCR                                         (0x0480)
+#define USB_HS_SYSTEM_CBCR                                 (0x0484)
+#define USB_HS_AHB_CBCR                                    (0x0488)
+#define USB_HS_SYSTEM_CMD_RCGR                             (0x0490)
+#define USB2A_PHY_SLEEP_CBCR                               (0x04AC)
+#define SDCC1_APPS_CMD_RCGR                                (0x04D0)
+#define SDCC1_APPS_CBCR                                    (0x04C4)
+#define SDCC1_AHB_CBCR                                     (0x04C8)
+#define SDCC2_APPS_CMD_RCGR                                (0x0510)
+#define SDCC2_APPS_CBCR                                    (0x0504)
+#define SDCC2_AHB_CBCR                                     (0x0508)
+#define SDCC3_APPS_CMD_RCGR                                (0x0550)
+#define SDCC3_APPS_CBCR                                    (0x0544)
+#define SDCC3_AHB_CBCR                                     (0x0548)
+#define BLSP1_AHB_CBCR                                     (0x05C4)
+#define BLSP1_QUP1_SPI_APPS_CBCR                           (0x0644)
+#define BLSP1_QUP1_I2C_APPS_CBCR                           (0x0648)
+#define BLSP1_QUP1_I2C_APPS_CMD_RCGR                       (0x0660)
+#define BLSP1_QUP2_I2C_APPS_CMD_RCGR                       (0x06E0)
+#define BLSP1_QUP3_I2C_APPS_CMD_RCGR                       (0x0760)
+#define BLSP1_QUP4_I2C_APPS_CMD_RCGR                       (0x07E0)
+#define BLSP1_QUP5_I2C_APPS_CMD_RCGR                       (0x0860)
+#define BLSP1_QUP6_I2C_APPS_CMD_RCGR                       (0x08E0)
+#define BLSP1_QUP1_SPI_APPS_CMD_RCGR                       (0x064C)
+#define BLSP1_UART1_APPS_CBCR                              (0x0684)
+#define BLSP1_UART1_APPS_CMD_RCGR                          (0x068C)
+#define BLSP1_QUP2_SPI_APPS_CBCR                           (0x06C4)
+#define BLSP1_QUP2_I2C_APPS_CBCR                           (0x06C8)
+#define BLSP1_QUP2_SPI_APPS_CMD_RCGR                       (0x06CC)
+#define BLSP1_UART2_APPS_CBCR                              (0x0704)
+#define BLSP1_UART2_APPS_CMD_RCGR                          (0x070C)
+#define BLSP1_QUP3_SPI_APPS_CBCR                           (0x0744)
+#define BLSP1_QUP3_I2C_APPS_CBCR                           (0x0748)
+#define BLSP1_QUP3_SPI_APPS_CMD_RCGR                       (0x074C)
+#define BLSP1_UART3_APPS_CBCR                              (0x0784)
+#define BLSP1_UART3_APPS_CMD_RCGR                          (0x078C)
+#define BLSP1_QUP4_SPI_APPS_CBCR                           (0x07C4)
+#define BLSP1_QUP4_I2C_APPS_CBCR                           (0x07C8)
+#define BLSP1_QUP4_SPI_APPS_CMD_RCGR                       (0x07CC)
+#define BLSP1_UART4_APPS_CBCR                              (0x0804)
+#define BLSP1_UART4_APPS_CMD_RCGR                          (0x080C)
+#define BLSP1_QUP5_SPI_APPS_CBCR                           (0x0844)
+#define BLSP1_QUP5_I2C_APPS_CBCR                           (0x0848)
+#define BLSP1_QUP5_SPI_APPS_CMD_RCGR                       (0x084C)
+#define BLSP1_UART5_APPS_CBCR                              (0x0884)
+#define BLSP1_UART5_APPS_CMD_RCGR                          (0x088C)
+#define BLSP1_QUP6_SPI_APPS_CBCR                           (0x08C4)
+#define BLSP1_QUP6_I2C_APPS_CBCR                           (0x08C8)
+#define BLSP1_QUP6_SPI_APPS_CMD_RCGR                       (0x08CC)
+#define BLSP1_UART6_APPS_CBCR                              (0x0904)
+#define BLSP1_UART6_APPS_CMD_RCGR                          (0x090C)
+#define PDM_AHB_CBCR                                       (0x0CC4)
+#define PDM_XO4_CBCR                                       (0x0CC8)
+#define PDM2_CBCR                                          (0x0CCC)
+#define PDM2_CMD_RCGR                                      (0x0CD0)
+#define PRNG_AHB_CBCR                                      (0x0D04)
+#define BAM_DMA_AHB_CBCR                                   (0x0D44)
+#define BOOT_ROM_AHB_CBCR                                  (0x0E04)
+#define CE1_CMD_RCGR                                       (0x1050)
+#define CE1_CBCR                                           (0x1044)
+#define CE1_AXI_CBCR                                       (0x1048)
+#define CE1_AHB_CBCR                                       (0x104C)
+#define GCC_XO_DIV4_CBCR                                   (0x10C8)
+#define LPASS_Q6_AXI_CBCR                                  (0x11C0)
+#define APCS_GPLL_ENA_VOTE                                 (0x1480)
+#define APCS_CLOCK_BRANCH_ENA_VOTE                         (0x1484)
+#define APCS_CLOCK_SLEEP_ENA_VOTE                          (0x1488)
+#define GCC_DEBUG_CLK_CTL                                  (0x1880)
+#define CLOCK_FRQ_MEASURE_CTL                              (0x1884)
+#define CLOCK_FRQ_MEASURE_STATUS                           (0x1888)
+#define PLLTEST_PAD_CFG                                    (0x188C)
+#define GP1_CBCR                                           (0x1900)
+#define GP1_CMD_RCGR                                       (0x1904)
+#define GP2_CBCR                                           (0x1940)
+#define GP2_CMD_RCGR                                       (0x1944)
+#define GP3_CBCR                                           (0x1980)
+#define GP3_CMD_RCGR                                       (0x1984)
+#define LPAAUDIO_PLL_MODE                                  (0x0000)
+#define LPAAUDIO_PLL_L                                     (0x0004)
+#define LPAAUDIO_PLL_M                                     (0x0008)
+#define LPAAUDIO_PLL_N                                     (0x000C)
+#define LPAAUDIO_PLL_USER_CTL                              (0x0010)
+#define LPAAUDIO_PLL_STATUS                                (0x001C)
+#define LPA_PLL_VOTE_APPS                                  (0x2000)
+#define Q6SS_BCR                                           (0x6000)
+#define AUDIO_CORE_GDSCR                                   (0x7000)
+#define LPAIF_SPKR_CMD_RCGR                                (0xA000)
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR               (0xA014)
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR              (0xA018)
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR              (0xA01C)
+#define LPAIF_PRI_CMD_RCGR                                 (0xB000)
+#define AUDIO_CORE_LPAIF_PRI_OSR_CBCR                      (0xB014)
+#define AUDIO_CORE_LPAIF_PRI_IBIT_CBCR                     (0xB018)
+#define AUDIO_CORE_LPAIF_PRI_EBIT_CBCR                     (0xB01C)
+#define LPAIF_SEC_CMD_RCGR                                 (0xC000)
+#define AUDIO_CORE_LPAIF_SEC_OSR_CBCR                      (0xC014)
+#define AUDIO_CORE_LPAIF_SEC_IBIT_CBCR                     (0xC018)
+#define AUDIO_CORE_LPAIF_SEC_EBIT_CBCR                     (0xC01C)
+#define LPAIF_TER_CMD_RCGR                                 (0xD000)
+#define AUDIO_CORE_LPAIF_TER_OSR_CBCR                      (0xD014)
+#define AUDIO_CORE_LPAIF_TER_IBIT_CBCR                     (0xD018)
+#define AUDIO_CORE_LPAIF_TER_EBIT_CBCR                     (0xD01C)
+#define LPAIF_QUAD_CMD_RCGR                                (0xE000)
+#define AUDIO_CORE_LPAIF_QUAD_OSR_CBCR                     (0xE014)
+#define AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR                    (0xE018)
+#define AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR                    (0xE01C)
+#define LPAIF_PCM0_CMD_RCGR                                (0xF000)
+#define AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR                    (0xF014)
+#define AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR                    (0xF018)
+#define LPAIF_PCM1_CMD_RCGR                                (0x10000)
+#define AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR                    (0x10014)
+#define AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR                    (0x10018)
+#define SLIMBUS_CMD_RCGR                                   (0x12000)
+#define AUDIO_CORE_SLIMBUS_CORE_CBCR                       (0x12014)
+#define AUDIO_CORE_SLIMBUS_LFABIF_CBCR                     (0x12018)
+#define LPAIF_PCMOE_CMD_RCGR                               (0x13000)
+#define AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR                  (0x13014)
+#define AUDIO_CORE_IXFABRIC_CBCR                           (0x1B000)
+#define Q6SS_AHB_LFABIF_CBCR                               (0x22000)
+#define Q6SS_AHBM_CBCR                                     (0x22004)
+#define AUDIO_WRAPPER_BR_CBCR                              (0x24000)
+#define Q6SS_XO_CBCR                                       (0x26000)
+
+static unsigned int soft_vote_gpll0;
+
+static struct pll_vote_clk gpll0 = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)GPLL0_STATUS,
+	.status_mask = BIT(17),
+	.soft_vote = &soft_vote_gpll0,
+	.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.rate = 600000000,
+		.parent = &xo.c,
+		.dbg_name = "gpll0",
+		.ops = &clk_ops_pll_acpu_vote,
+		CLK_INIT(gpll0.c),
+	},
+};
+
+/*Don't vote for xo if using this clock to allow xo shutdown*/
+static struct pll_vote_clk gpll0_ao = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)GPLL0_STATUS,
+	.status_mask = BIT(17),
+	.soft_vote = &soft_vote_gpll0,
+	.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.rate = 600000000,
+		.dbg_name = "gpll0_ao",
+		.ops = &clk_ops_pll_acpu_vote,
+		CLK_INIT(gpll0_ao.c),
+	},
+};
+
+static struct pll_vote_clk gpll1 = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(1),
+	.status_reg = (void __iomem *)GPLL1_STATUS,
+	.status_mask = BIT(17),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.rate = 480000000,
+		.parent = &xo.c,
+		.dbg_name = "gpll1",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(gpll1.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_blsp1_qup1_6_i2c_apps_clk[] = {
+	F_GCC(  19200000,         xo,   0,    0,    0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP1_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup1_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup1_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = {
+	F_GCC(    960000,         xo,  10,    1,    2),
+	F_GCC(   4800000,         xo,   4,    0,    0),
+	F_GCC(   9600000,         xo,   2,    0,    0),
+	F_GCC(  15000000,      gpll0,  10,    1,    4),
+	F_GCC(  19200000,         xo,   1,    0,    0),
+	F_GCC(  25000000,      gpll0,  12,    1,    2),
+	F_GCC(  50000000,      gpll0,  12,    0,    0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup1_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP1_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup1_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup1_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP2_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup2_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup2_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup2_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP2_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup2_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup2_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP3_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup3_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup3_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup3_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP3_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup3_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup3_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP4_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup4_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup4_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup4_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP4_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup4_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup4_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP5_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup5_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup5_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup5_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP5_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup5_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup5_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP6_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup6_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup6_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup6_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP6_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup6_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup6_spi_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_blsp1_uart1_6_apps_clk[] = {
+	F_GCC(   3686400,      gpll0,   1,   96, 15625),
+	F_GCC(   7372800,      gpll0,   1,  192, 15625),
+	F_GCC(  14745600,      gpll0,   1,  384, 15625),
+	F_GCC(  16000000,      gpll0,   5,    2,   15),
+	F_GCC(  19200000,         xo,   1,    0,    0),
+	F_GCC(  24000000,      gpll0,   5,    1,    5),
+	F_GCC(  32000000,      gpll0,   1,    4,   75),
+	F_GCC(  40000000,      gpll0,  15,    0,    0),
+	F_GCC(  46400000,      gpll0,   1,   29,  375),
+	F_GCC(  48000000,      gpll0, 12.5,    0,    0),
+	F_GCC(  51200000,      gpll0,   1,   32,  375),
+	F_GCC(  56000000,      gpll0,   1,    7,   75),
+	F_GCC(  58982400,      gpll0,   1, 1536, 15625),
+	F_GCC(  60000000,      gpll0,  10,    0,    0),
+	F_END
+};
+
+static struct rcg_clk blsp1_uart1_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart1_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart1_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart2_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART2_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart2_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart2_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart3_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART3_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart3_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart3_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart4_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART4_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart4_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart4_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart5_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART5_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart5_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart5_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart6_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART6_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart6_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart6_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = {
+	F_GCC(  50000000,      gpll0,  12,    0,    0),
+	F_GCC( 100000000,      gpll0,   6,    0,    0),
+	F_END
+};
+
+static struct rcg_clk ce1_clk_src = {
+	.cmd_rcgr_reg = CE1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_ce1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "ce1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
+		CLK_INIT(ce1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_gp1_3_clk[] = {
+	F_GCC(  19200000,         xo,   1,    0,    0),
+	F_END
+};
+
+static struct rcg_clk gp1_clk_src = {
+	.cmd_rcgr_reg = GP1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_gp1_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp1_clk_src.c),
+	},
+};
+
+static struct rcg_clk gp2_clk_src = {
+	.cmd_rcgr_reg = GP2_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_gp1_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp2_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp2_clk_src.c),
+	},
+};
+
+static struct rcg_clk gp3_clk_src = {
+	.cmd_rcgr_reg = GP3_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_gp1_3_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp3_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp3_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_pdm2_clk[] = {
+	F_GCC(  60000000,      gpll0,  10,    0,    0),
+	F_END
+};
+
+static struct rcg_clk pdm2_clk_src = {
+	.cmd_rcgr_reg = PDM2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_pdm2_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "pdm2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 60000000),
+		CLK_INIT(pdm2_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_sdcc1_3_apps_clk[] = {
+	F_GCC(    144000,         xo,  16,    3,   25),
+	F_GCC(    400000,         xo,  12,    1,    4),
+	F_GCC(  20000000,      gpll0,  15,    1,    2),
+	F_GCC(  25000000,      gpll0,  12,    1,    2),
+	F_GCC(  50000000,      gpll0,  12,    0,    0),
+	F_GCC( 100000000,      gpll0,   6,    0,    0),
+	F_GCC( 200000000,      gpll0,   3,    0,    0),
+	F_END
+};
+
+static struct rcg_clk sdcc1_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_sdcc1_3_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc1_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(sdcc1_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk sdcc2_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC2_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_sdcc1_3_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc2_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(sdcc2_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk sdcc3_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC3_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gcc_sdcc1_3_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc3_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
+		CLK_INIT(sdcc3_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
+	F_GCC(  75000000,      gpll0,   8,    0,    0),
+	F_END
+};
+
+static struct rcg_clk usb_hs_system_clk_src = {
+	.cmd_rcgr_reg = USB_HS_SYSTEM_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb_hs_system_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hs_system_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 37500000, NOMINAL, 75000000),
+		CLK_INIT(usb_hs_system_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hsic_clk[] = {
+	F_HSIC( 480000000,      gpll1,   0,    0,    0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb_hsic_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 480000000),
+		CLK_INIT(usb_hsic_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hsic_io_cal_clk[] = {
+	F_GCC(   9600000,         xo,   2,    0,    0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_io_cal_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_IO_CAL_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb_hsic_io_cal_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_io_cal_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 9600000),
+		CLK_INIT(usb_hsic_io_cal_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hsic_system_clk[] = {
+	F_GCC(  75000000,      gpll0,   8,    0,    0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_system_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_SYSTEM_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_usb_hsic_system_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_system_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 37500000, NOMINAL, 75000000),
+		CLK_INIT(usb_hsic_system_clk_src.c),
+	},
+};
+
+static struct local_vote_clk gcc_bam_dma_ahb_clk = {
+	.cbcr_reg = BAM_DMA_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(12),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_bam_dma_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_bam_dma_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_blsp1_ahb_clk = {
+	.cbcr_reg = BLSP1_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(17),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_blsp1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP1_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup1_i2c_apps_clk",
+		.parent = &blsp1_qup1_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup1_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup1_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP1_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup1_spi_apps_clk",
+		.parent = &blsp1_qup1_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup1_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP2_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup2_i2c_apps_clk",
+		.parent = &blsp1_qup2_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup2_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup2_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP2_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup2_spi_apps_clk",
+		.parent = &blsp1_qup2_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup2_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",
+		.parent = &blsp1_qup3_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup3_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup3_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP3_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup3_spi_apps_clk",
+		.parent = &blsp1_qup3_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup3_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup4_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP4_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup4_i2c_apps_clk",
+		.parent = &blsp1_qup4_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup4_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup4_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP4_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup4_spi_apps_clk",
+		.parent = &blsp1_qup4_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup4_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup5_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP5_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup5_i2c_apps_clk",
+		.parent = &blsp1_qup5_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup5_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup5_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP5_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup5_spi_apps_clk",
+		.parent = &blsp1_qup5_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup5_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup6_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP6_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup6_i2c_apps_clk",
+		.parent = &blsp1_qup6_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup6_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup6_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP6_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup6_spi_apps_clk",
+		.parent = &blsp1_qup6_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup6_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart1_apps_clk = {
+	.cbcr_reg = BLSP1_UART1_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart1_apps_clk",
+		.parent = &blsp1_uart1_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart1_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart2_apps_clk = {
+	.cbcr_reg = BLSP1_UART2_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart2_apps_clk",
+		.parent = &blsp1_uart2_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart2_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart3_apps_clk = {
+	.cbcr_reg = BLSP1_UART3_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart3_apps_clk",
+		.parent = &blsp1_uart3_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart3_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart4_apps_clk = {
+	.cbcr_reg = BLSP1_UART4_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart4_apps_clk",
+		.parent = &blsp1_uart4_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart4_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart5_apps_clk = {
+	.cbcr_reg = BLSP1_UART5_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart5_apps_clk",
+		.parent = &blsp1_uart5_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart5_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart6_apps_clk = {
+	.cbcr_reg = BLSP1_UART6_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart6_apps_clk",
+		.parent = &blsp1_uart6_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart6_apps_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_boot_rom_ahb_clk = {
+	.cbcr_reg = BOOT_ROM_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(10),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_boot_rom_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_boot_rom_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce1_ahb_clk = {
+	.cbcr_reg = CE1_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(3),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce1_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce1_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce1_axi_clk = {
+	.cbcr_reg = CE1_AXI_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(4),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce1_axi_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce1_axi_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_ce1_clk = {
+	.cbcr_reg = CE1_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(5),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_ce1_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_ce1_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp1_clk = {
+	.cbcr_reg = GP1_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp1_clk",
+		.parent = &gp1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp1_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp2_clk = {
+	.cbcr_reg = GP2_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp2_clk",
+		.parent = &gp2_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp2_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp3_clk = {
+	.cbcr_reg = GP3_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp3_clk",
+		.parent = &gp3_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp3_clk.c),
+	},
+};
+
+static struct branch_clk gcc_lpass_q6_axi_clk = {
+	.cbcr_reg = LPASS_Q6_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_lpass_q6_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_lpass_q6_axi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_mmss_noc_cfg_ahb_clk = {
+	.cbcr_reg = MMSS_NOC_CFG_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_mmss_noc_cfg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_mmss_noc_cfg_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_mss_cfg_ahb_clk = {
+	.cbcr_reg = MSS_CFG_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_mss_cfg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_mss_cfg_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_mss_q6_bimc_axi_clk = {
+	.cbcr_reg = MSS_Q6_BIMC_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_mss_q6_bimc_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_mss_q6_bimc_axi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_noc_conf_xpu_ahb_clk = {
+	.cbcr_reg = NOC_CONF_XPU_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_noc_conf_xpu_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_noc_conf_xpu_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm2_clk = {
+	.cbcr_reg = PDM2_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_pdm2_clk",
+		.parent = &pdm2_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm2_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm_ahb_clk = {
+	.cbcr_reg = PDM_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_pdm_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm_xo4_clk = {
+	.cbcr_reg = PDM_XO4_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_pdm_xo4_clk",
+		.parent = &xo.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm_xo4_clk.c),
+	},
+};
+
+static struct branch_clk gcc_periph_noc_ahb_clk = {
+	.cbcr_reg = PERIPH_NOC_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_periph_noc_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_periph_noc_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_prng_ahb_clk = {
+	.cbcr_reg = PRNG_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(13),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_prng_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_prng_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_ahb_clk = {
+	.cbcr_reg = SDCC1_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc1_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_apps_clk = {
+	.cbcr_reg = SDCC1_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc1_apps_clk",
+		.parent = &sdcc1_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc2_ahb_clk = {
+	.cbcr_reg = SDCC2_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc2_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc2_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc2_apps_clk = {
+	.cbcr_reg = SDCC2_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc2_apps_clk",
+		.parent = &sdcc2_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc2_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc3_ahb_clk = {
+	.cbcr_reg = SDCC3_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc3_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc3_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc3_apps_clk = {
+	.cbcr_reg = SDCC3_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc3_apps_clk",
+		.parent = &sdcc3_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc3_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb2a_phy_sleep_clk = {
+	.cbcr_reg = USB2A_PHY_SLEEP_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb2a_phy_sleep_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb2a_phy_sleep_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hs_ahb_clk = {
+	.cbcr_reg = USB_HS_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hs_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hs_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hs_system_clk = {
+	.cbcr_reg = USB_HS_SYSTEM_CBCR,
+	.has_sibling = 0,
+	.bcr_reg = USB_HS_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hs_system_clk",
+		.parent = &usb_hs_system_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hs_system_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_ahb_clk = {
+	.cbcr_reg = USB_HSIC_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_clk = {
+	.cbcr_reg = USB_HSIC_CBCR,
+	.has_sibling = 0,
+	.bcr_reg = USB_HS_HSIC_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_clk",
+		.parent = &usb_hsic_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_io_cal_clk = {
+	.cbcr_reg = USB_HSIC_IO_CAL_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_io_cal_clk",
+		.parent = &usb_hsic_io_cal_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_io_cal_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_system_clk = {
+	.cbcr_reg = USB_HSIC_SYSTEM_CBCR,
+	.has_sibling = 0,
+	.bcr_reg = USB_HS_HSIC_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_system_clk",
+		.parent = &usb_hsic_system_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_system_clk.c),
+	},
+};
+
+static struct measure_mux_entry measure_mux_GCC[] = {
+	{ &gcc_periph_noc_ahb_clk.c,  GCC_BASE, 0x0010 },
+	{ &gcc_noc_conf_xpu_ahb_clk.c,  GCC_BASE, 0x0018 },
+	{ &gcc_mmss_noc_cfg_ahb_clk.c,  GCC_BASE, 0x002a },
+	{ &gcc_mss_cfg_ahb_clk.c,  GCC_BASE, 0x0030 },
+	{ &gcc_mss_q6_bimc_axi_clk.c,  GCC_BASE, 0x0031 },
+	{ &gcc_usb_hsic_ahb_clk.c,  GCC_BASE, 0x0058 },
+	{ &gcc_usb_hsic_system_clk.c,  GCC_BASE, 0x0059 },
+	{ &gcc_usb_hsic_clk.c,  GCC_BASE, 0x005a },
+	{ &gcc_usb_hsic_io_cal_clk.c,  GCC_BASE, 0x005b },
+	{ &gcc_usb_hs_system_clk.c,  GCC_BASE, 0x0060 },
+	{ &gcc_usb_hs_ahb_clk.c,  GCC_BASE, 0x0061 },
+	{ &gcc_usb2a_phy_sleep_clk.c,  GCC_BASE, 0x0063 },
+	{ &gcc_sdcc1_apps_clk.c,  GCC_BASE, 0x0068 },
+	{ &gcc_sdcc1_ahb_clk.c,  GCC_BASE, 0x0069 },
+	{ &gcc_sdcc2_apps_clk.c,  GCC_BASE, 0x0070 },
+	{ &gcc_sdcc2_ahb_clk.c,  GCC_BASE, 0x0071 },
+	{ &gcc_sdcc3_apps_clk.c,  GCC_BASE, 0x0078 },
+	{ &gcc_sdcc3_ahb_clk.c,  GCC_BASE, 0x0079 },
+	{ &gcc_blsp1_ahb_clk.c,  GCC_BASE, 0x0088 },
+	{ &gcc_blsp1_qup1_spi_apps_clk.c,  GCC_BASE, 0x008a },
+	{ &gcc_blsp1_qup1_i2c_apps_clk.c,  GCC_BASE, 0x008b },
+	{ &gcc_blsp1_uart1_apps_clk.c,  GCC_BASE, 0x008c },
+	{ &gcc_blsp1_qup2_spi_apps_clk.c,  GCC_BASE, 0x008e },
+	{ &gcc_blsp1_qup2_i2c_apps_clk.c,  GCC_BASE, 0x0090 },
+	{ &gcc_blsp1_uart2_apps_clk.c,  GCC_BASE, 0x0091 },
+	{ &gcc_blsp1_qup3_spi_apps_clk.c,  GCC_BASE, 0x0093 },
+	{ &gcc_blsp1_qup3_i2c_apps_clk.c,  GCC_BASE, 0x0094 },
+	{ &gcc_blsp1_uart3_apps_clk.c,  GCC_BASE, 0x0095 },
+	{ &gcc_blsp1_qup4_spi_apps_clk.c,  GCC_BASE, 0x0098 },
+	{ &gcc_blsp1_qup4_i2c_apps_clk.c,  GCC_BASE, 0x0099 },
+	{ &gcc_blsp1_uart4_apps_clk.c,  GCC_BASE, 0x009a },
+	{ &gcc_blsp1_qup5_spi_apps_clk.c,  GCC_BASE, 0x009c },
+	{ &gcc_blsp1_qup5_i2c_apps_clk.c,  GCC_BASE, 0x009d },
+	{ &gcc_blsp1_uart5_apps_clk.c,  GCC_BASE, 0x009e },
+	{ &gcc_blsp1_qup6_spi_apps_clk.c,  GCC_BASE, 0x00a1 },
+	{ &gcc_blsp1_qup6_i2c_apps_clk.c,  GCC_BASE, 0x00a2 },
+	{ &gcc_blsp1_uart6_apps_clk.c,  GCC_BASE, 0x00a3 },
+	{ &gcc_pdm_ahb_clk.c,  GCC_BASE, 0x00d0 },
+	{ &gcc_pdm_xo4_clk.c,  GCC_BASE, 0x00d1 },
+	{ &gcc_pdm2_clk.c,  GCC_BASE, 0x00d2 },
+	{ &gcc_prng_ahb_clk.c,  GCC_BASE, 0x00d8 },
+	{ &gcc_bam_dma_ahb_clk.c,  GCC_BASE, 0x00e0 },
+	{ &gcc_boot_rom_ahb_clk.c,  GCC_BASE, 0x00f8 },
+	{ &gcc_ce1_clk.c,  GCC_BASE, 0x0138 },
+	{ &gcc_ce1_axi_clk.c,  GCC_BASE, 0x0139 },
+	{ &gcc_ce1_ahb_clk.c,  GCC_BASE, 0x013a },
+	{ &gcc_lpass_q6_axi_clk.c,  GCC_BASE, 0x0160 },
+	{&dummy_clk, N_BASES, 0x0000},
+};
+
+static struct pll_vote_clk mmpll0_pll = {
+	.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)MMPLL0_PLL_STATUS,
+	.status_mask = BIT(17),
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.rate = 800000000,
+		.parent = &xo.c,
+		.dbg_name = "mmpll0_pll",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(mmpll0_pll.c),
+	},
+};
+
+static struct pll_vote_clk mmpll1_pll = {
+	.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS,
+	.en_mask = BIT(1),
+	.status_reg = (void __iomem *)MMPLL1_PLL_STATUS,
+	.status_mask = BIT(17),
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.rate = 1000000000,
+		.parent = &xo.c,
+		.dbg_name = "mmpll1_pll",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(mmpll1_pll.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mmss_mmssnoc_axi_clk[] = {
+	F_MMSS(  19200000,         xo,   1,    0,    0),
+	F_MMSS(  37500000,      gpll0,  16,    0,    0),
+	F_MMSS(  50000000,      gpll0,  12,    0,    0),
+	F_MMSS(  75000000,      gpll0,   8,    0,    0),
+	F_MMSS( 100000000,      gpll0,   6,    0,    0),
+	F_MMSS( 150000000,      gpll0,   4,    0,    0),
+	F_MMSS( 200000000, mmpll0_pll,   4,    0,    0),
+	F_MMSS( 266000000, mmpll0_pll,   3,    0,    0),
+	F_END
+};
+
+static struct rcg_clk axi_clk_src = {
+	.cmd_rcgr_reg = AXI_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mmss_mmssnoc_axi_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "axi_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000, HIGH,
+		266670000),
+		CLK_INIT(axi_clk_src.c),
+	},
+};
+
+static struct pll_clk mmpll2_pll = {
+	.mode_reg = (void __iomem *)MMPLL2_PLL_MODE,
+	.status_reg = (void __iomem *)MMPLL2_PLL_STATUS,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmpll2_pll",
+		.parent = &xo.c,
+		.rate = 900000000,
+		.ops = &clk_ops_local_pll,
+		CLK_INIT(mmpll2_pll.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_csi0_1_clk[] = {
+	F_MMSS( 100000000,      gpll0,   6,    0,    0),
+	F_MMSS( 200000000, mmpll0_pll,   4,    0,    0),
+	F_END
+};
+
+static struct rcg_clk csi0_clk_src = {
+	.cmd_rcgr_reg = CSI0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_csi0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi0_clk_src.c),
+	},
+};
+
+static struct rcg_clk csi1_clk_src = {
+	.cmd_rcgr_reg = CSI1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_csi0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_vfe_vfe0_clk[] = {
+	F_MMSS(  37500000,      gpll0,  16,    0,    0),
+	F_MMSS(  50000000,      gpll0,  12,    0,    0),
+	F_MMSS(  60000000,      gpll0,  10,    0,    0),
+	F_MMSS(  80000000,      gpll0, 7.5,    0,    0),
+	F_MMSS( 100000000,      gpll0,   6,    0,    0),
+	F_MMSS( 109090000,      gpll0, 5.5,    0,    0),
+	F_MMSS( 133330000,      gpll0, 4.5,    0,    0),
+	F_MMSS( 200000000,      gpll0,   3,    0,    0),
+	F_MMSS( 228570000, mmpll0_pll, 3.5,    0,    0),
+	F_MMSS( 266670000, mmpll0_pll,   3,    0,    0),
+	F_MMSS( 320000000, mmpll0_pll, 2.5,    0,    0),
+	F_END
+};
+
+static struct rcg_clk vfe0_clk_src = {
+	.cmd_rcgr_reg = VFE0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_vfe_vfe0_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "vfe0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000, HIGH,
+		320000000),
+		CLK_INIT(vfe0_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_mdp_clk[] = {
+	F_MMSS(  37500000,      gpll0,  16,    0,    0),
+	F_MMSS(  60000000,      gpll0,  10,    0,    0),
+	F_MMSS(  75000000,      gpll0,   8,    0,    0),
+	F_MMSS(  92310000,      gpll0, 6.5,    0,    0),
+	F_MMSS( 100000000,      gpll0,   6,    0,    0),
+	F_MMSS( 133330000, mmpll0_pll,   6,    0,    0),
+	F_MMSS( 177780000, mmpll0_pll, 4.5,    0,    0),
+	F_MMSS( 200000000, mmpll0_pll,   4,    0,    0),
+	F_END
+};
+
+static struct rcg_clk mdp_clk_src = {
+	.cmd_rcgr_reg = MDP_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_mdp_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdp_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 92310000, NOMINAL, 177780000, HIGH,
+		200000000),
+		CLK_INIT(mdp_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_jpeg_jpeg0_clk[] = {
+	F_MMSS(  75000000,      gpll0,   8,    0,    0),
+	F_MMSS( 133330000,      gpll0, 4.5,    0,    0),
+	F_MMSS( 200000000,      gpll0,   3,    0,    0),
+	F_MMSS( 228570000, mmpll0_pll, 3.5,    0,    0),
+	F_MMSS( 266670000, mmpll0_pll,   3,    0,    0),
+	F_MMSS( 320000000, mmpll0_pll, 2.5,    0,    0),
+	F_END
+};
+
+static struct rcg_clk jpeg0_clk_src = {
+	.cmd_rcgr_reg = JPEG0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "jpeg0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000, HIGH,
+		320000000),
+		CLK_INIT(jpeg0_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_pclk0_clk[] = {
+	F_MDSS(  83000000, dsipll_667,   8,    0,    0),
+	F_MDSS( 166000000, dsipll_667,   4,    0,    0),
+	F_END
+};
+
+static struct rcg_clk pclk0_clk_src = {
+	.cmd_rcgr_reg = PCLK0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_mdss_pclk0_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "pclk0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 83330000, NOMINAL, 166670000),
+		CLK_INIT(pclk0_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_venus0_vcodec0_clk[] = {
+	F_MMSS(  66700000,      gpll0,   9,    0,    0),
+	F_MMSS( 100000000,      gpll0,   6,    0,    0),
+	F_MMSS( 133330000, mmpll0_pll,   6,    0,    0),
+	F_END
+};
+
+static struct rcg_clk vcodec0_clk_src = {
+	.cmd_rcgr_reg = VCODEC0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_venus0_vcodec0_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "vcodec0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOW, 66670000, NOMINAL, 133330000, HIGH,
+		160000000),
+		CLK_INIT(vcodec0_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_cci_cci_clk[] = {
+	F_MMSS(  19200000,         xo,   1,    0,    0),
+	F_END
+};
+
+static struct rcg_clk cci_clk_src = {
+	.cmd_rcgr_reg = CCI_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_camss_cci_cci_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "cci_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(cci_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_gp0_1_clk[] = {
+	F_MMSS(     10000,         xo,  16,    1,  120),
+	F_MMSS(     24000,         xo,  16,    1,   50),
+	F_MMSS(   6000000,      gpll0,  10,    1,   10),
+	F_MMSS(  12000000,      gpll0,  10,    1,    5),
+	F_MMSS(  13000000,      gpll0,   4,   13,  150),
+	F_MMSS(  24000000,      gpll0,   5,    1,    5),
+	F_END
+};
+
+static struct rcg_clk mmss_gp0_clk_src = {
+	.cmd_rcgr_reg = MMSS_GP0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_camss_gp0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_gp0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(mmss_gp0_clk_src.c),
+	},
+};
+
+static struct rcg_clk mmss_gp1_clk_src = {
+	.cmd_rcgr_reg = MMSS_GP1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_camss_gp0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_gp1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(mmss_gp1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_mclk0_1_clk[] = {
+	F_MMSS(  66670000,      gpll0,   9,    0,    0),
+	F_END
+};
+
+static struct rcg_clk mclk0_clk_src = {
+	.cmd_rcgr_reg = MCLK0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_camss_mclk0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mclk0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP1(LOW, 66670000),
+		CLK_INIT(mclk0_clk_src.c),
+	},
+};
+
+static struct rcg_clk mclk1_clk_src = {
+	.cmd_rcgr_reg = MCLK1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_camss_mclk0_1_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mclk1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP1(LOW, 66670000),
+		CLK_INIT(mclk1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_phy0_1_csi0_1phytimer_clk[] = {
+	F_MMSS( 100000000,      gpll0,   6,    0,    0),
+	F_MMSS( 200000000, mmpll0_pll,   4,    0,    0),
+	F_END
+};
+
+static struct rcg_clk csi0phytimer_clk_src = {
+	.cmd_rcgr_reg = CSI0PHYTIMER_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_phy0_1_csi0_1phytimer_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi0phytimer_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi0phytimer_clk_src.c),
+	},
+};
+
+static struct rcg_clk csi1phytimer_clk_src = {
+	.cmd_rcgr_reg = CSI1PHYTIMER_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_phy0_1_csi0_1phytimer_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi1phytimer_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+		CLK_INIT(csi1phytimer_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_camss_vfe_cpp_clk[] = {
+	F_MMSS( 133330000,      gpll0, 4.5,    0,    0),
+	F_MMSS( 266670000, mmpll0_pll,   3,    0,    0),
+	F_MMSS( 320000000, mmpll0_pll, 2.5,    0,    0),
+	F_END
+};
+
+static struct rcg_clk cpp_clk_src = {
+	.cmd_rcgr_reg = CPP_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_camss_vfe_cpp_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "cpp_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000, HIGH,
+		320000000),
+		CLK_INIT(cpp_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_byte0_clk[] = {
+	F_MDSS(  62500000, dsipll_750,  12,    0,    0),
+	F_MDSS( 125000000, dsipll_750,   6,    0,    0),
+	F_END
+};
+
+static struct rcg_clk byte0_clk_src = {
+	.cmd_rcgr_reg = BYTE0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_byte0_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "byte0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 62500000, NOMINAL, 125000000),
+		CLK_INIT(byte0_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_esc0_clk[] = {
+	F_MDSS(  19200000,         xo,   1,    0,    0),
+	F_END
+};
+
+static struct rcg_clk esc0_clk_src = {
+	.cmd_rcgr_reg = ESC0_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_esc0_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "esc0_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(esc0_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_vsync_clk[] = {
+	F_MDSS(  19200000,         xo,   1,    0,    0),
+	F_END
+};
+
+static struct rcg_clk vsync_clk_src = {
+	.cmd_rcgr_reg = VSYNC_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_mdss_vsync_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "vsync_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOW, 20000000, NOMINAL, 40000000),
+		CLK_INIT(vsync_clk_src.c),
+	},
+};
+
+static struct branch_clk camss_cci_cci_ahb_clk = {
+	.cbcr_reg = CAMSS_CCI_CCI_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_cci_cci_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_cci_cci_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_cci_cci_clk = {
+	.cbcr_reg = CAMSS_CCI_CCI_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_cci_cci_clk",
+		.parent = &cci_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_cci_cci_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0_ahb_clk = {
+	.cbcr_reg = CAMSS_CSI0_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0_clk = {
+	.cbcr_reg = CAMSS_CSI0_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0_clk",
+		.parent = &csi0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0phy_clk = {
+	.cbcr_reg = CAMSS_CSI0PHY_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0phy_clk",
+		.parent = &csi0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0phy_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0pix_clk = {
+	.cbcr_reg = CAMSS_CSI0PIX_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0pix_clk",
+		.parent = &csi0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0pix_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi0rdi_clk = {
+	.cbcr_reg = CAMSS_CSI0RDI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi0rdi_clk",
+		.parent = &csi0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi0rdi_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1_ahb_clk = {
+	.cbcr_reg = CAMSS_CSI1_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1_clk = {
+	.cbcr_reg = CAMSS_CSI1_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1_clk",
+		.parent = &csi1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1phy_clk = {
+	.cbcr_reg = CAMSS_CSI1PHY_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1phy_clk",
+		.parent = &csi1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1phy_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1pix_clk = {
+	.cbcr_reg = CAMSS_CSI1PIX_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1pix_clk",
+		.parent = &csi1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1pix_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi1rdi_clk = {
+	.cbcr_reg = CAMSS_CSI1RDI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi1rdi_clk",
+		.parent = &csi1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi1rdi_clk.c),
+	},
+};
+
+static struct branch_clk camss_csi_vfe0_clk = {
+	.cbcr_reg = CAMSS_CSI_VFE0_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_csi_vfe0_clk",
+		.parent = &vfe0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_csi_vfe0_clk.c),
+	},
+};
+
+static struct branch_clk camss_gp0_clk = {
+	.cbcr_reg = CAMSS_GP0_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_gp0_clk",
+		.parent = &mmss_gp0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_gp0_clk.c),
+	},
+};
+
+static struct branch_clk camss_gp1_clk = {
+	.cbcr_reg = CAMSS_GP1_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_gp1_clk",
+		.parent = &mmss_gp1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_gp1_clk.c),
+	},
+};
+
+static struct branch_clk camss_ispif_ahb_clk = {
+	.cbcr_reg = CAMSS_ISPIF_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_ispif_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_ispif_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg0_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG0_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg0_clk",
+		.parent = &jpeg0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg0_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg_ahb_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_jpeg_jpeg_axi_clk = {
+	.cbcr_reg = CAMSS_JPEG_JPEG_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_jpeg_jpeg_axi_clk",
+		.parent = &axi_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_jpeg_jpeg_axi_clk.c),
+	},
+};
+
+static struct branch_clk camss_mclk0_clk = {
+	.cbcr_reg = CAMSS_MCLK0_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_mclk0_clk",
+		.parent = &mclk0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_mclk0_clk.c),
+	},
+};
+
+static struct branch_clk camss_mclk1_clk = {
+	.cbcr_reg = CAMSS_MCLK1_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_mclk1_clk",
+		.parent = &mclk1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_mclk1_clk.c),
+	},
+};
+
+static struct branch_clk camss_micro_ahb_clk = {
+	.cbcr_reg = CAMSS_MICRO_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_micro_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_micro_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_phy0_csi0phytimer_clk = {
+	.cbcr_reg = CAMSS_PHY0_CSI0PHYTIMER_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_phy0_csi0phytimer_clk",
+		.parent = &csi0phytimer_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_phy0_csi0phytimer_clk.c),
+	},
+};
+
+static struct branch_clk camss_phy1_csi1phytimer_clk = {
+	.cbcr_reg = CAMSS_PHY1_CSI1PHYTIMER_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_phy1_csi1phytimer_clk",
+		.parent = &csi1phytimer_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_phy1_csi1phytimer_clk.c),
+	},
+};
+
+static struct branch_clk camss_top_ahb_clk = {
+	.cbcr_reg = CAMSS_TOP_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_top_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_top_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_cpp_ahb_clk = {
+	.cbcr_reg = CAMSS_VFE_CPP_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_cpp_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_cpp_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_cpp_clk = {
+	.cbcr_reg = CAMSS_VFE_CPP_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_cpp_clk",
+		.parent = &cpp_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_cpp_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_vfe0_clk = {
+	.cbcr_reg = CAMSS_VFE_VFE0_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_vfe0_clk",
+		.parent = &vfe0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_vfe0_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_vfe_ahb_clk = {
+	.cbcr_reg = CAMSS_VFE_VFE_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_vfe_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_vfe_ahb_clk.c),
+	},
+};
+
+static struct branch_clk camss_vfe_vfe_axi_clk = {
+	.cbcr_reg = CAMSS_VFE_VFE_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "camss_vfe_vfe_axi_clk",
+		.parent = &axi_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(camss_vfe_vfe_axi_clk.c),
+	},
+};
+
+static struct branch_clk mdss_ahb_clk = {
+	.cbcr_reg = MDSS_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mdss_axi_clk = {
+	.cbcr_reg = MDSS_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_axi_clk",
+		.parent = &axi_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_axi_clk.c),
+	},
+};
+
+static struct branch_clk mdss_byte0_clk = {
+	.cbcr_reg = MDSS_BYTE0_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_byte0_clk",
+		.parent = &byte0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_byte0_clk.c),
+	},
+};
+
+static struct branch_clk mdss_esc0_clk = {
+	.cbcr_reg = MDSS_ESC0_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_esc0_clk",
+		.parent = &esc0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_esc0_clk.c),
+	},
+};
+
+static struct branch_clk mdss_mdp_clk = {
+	.cbcr_reg = MDSS_MDP_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_mdp_clk",
+		.parent = &mdp_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_mdp_clk.c),
+	},
+};
+
+static struct branch_clk mdss_mdp_lut_clk = {
+	.cbcr_reg = MDSS_MDP_LUT_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_mdp_lut_clk",
+		.parent = &mdp_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_mdp_lut_clk.c),
+	},
+};
+
+static struct branch_clk mdss_pclk0_clk = {
+	.cbcr_reg = MDSS_PCLK0_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_pclk0_clk",
+		.parent = &pclk0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_pclk0_clk.c),
+	},
+};
+
+static struct branch_clk mdss_vsync_clk = {
+	.cbcr_reg = MDSS_VSYNC_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mdss_vsync_clk",
+		.parent = &vsync_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mdss_vsync_clk.c),
+	},
+};
+
+static struct branch_clk mmss_misc_ahb_clk = {
+	.cbcr_reg = MMSS_MISC_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_misc_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_misc_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mmss_mmssnoc_ahb_clk = {
+	.cbcr_reg = MMSS_MMSSNOC_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_mmssnoc_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_mmssnoc_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mmss_mmssnoc_bto_ahb_clk = {
+	.cbcr_reg = MMSS_MMSSNOC_BTO_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_mmssnoc_bto_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_mmssnoc_bto_ahb_clk.c),
+	},
+};
+
+static struct branch_clk mmss_mmssnoc_axi_clk = {
+	.cbcr_reg = MMSS_MMSSNOC_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_mmssnoc_axi_clk",
+		.parent = &axi_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_mmssnoc_axi_clk.c),
+	},
+};
+
+static struct branch_clk mmss_s0_axi_clk = {
+	.cbcr_reg = MMSS_S0_AXI_CBCR,
+	.has_sibling = 0,
+	.max_div = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "mmss_s0_axi_clk",
+		.parent = &axi_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(mmss_s0_axi_clk.c),
+		.depends = &mmss_mmssnoc_axi_clk.c,
+	},
+};
+
+static struct branch_clk ocmemcx_ahb_clk = {
+	.cbcr_reg = OCMEMCX_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "ocmemcx_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(ocmemcx_ahb_clk.c),
+	},
+};
+
+static struct branch_clk oxili_gfx3d_clk = {
+	.cbcr_reg = OXILI_GFX3D_CBCR,
+	.has_sibling = 1,
+	.max_div = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "oxili_gfx3d_clk",
+		.parent = &gfx3d_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(oxili_gfx3d_clk.c),
+		.depends = &oxilicx_axi_clk.c,
+	},
+};
+
+static struct branch_clk oxilicx_ahb_clk = {
+	.cbcr_reg = OXILICX_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "oxilicx_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(oxilicx_ahb_clk.c),
+	},
+};
+
+static struct branch_clk oxilicx_axi_clk = {
+	.cbcr_reg = OXILICX_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "oxilicx_axi_clk",
+		.parent = &axi_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(oxilicx_axi_clk.c),
+	},
+};
+
+static struct branch_clk venus0_ahb_clk = {
+	.cbcr_reg = VENUS0_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "venus0_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(venus0_ahb_clk.c),
+	},
+};
+
+static struct branch_clk venus0_axi_clk = {
+	.cbcr_reg = VENUS0_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "venus0_axi_clk",
+		.parent = &axi_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(venus0_axi_clk.c),
+	},
+};
+
+static struct branch_clk venus0_vcodec0_clk = {
+	.cbcr_reg = VENUS0_VCODEC0_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "venus0_vcodec0_clk",
+		.parent = &vcodec0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(venus0_vcodec0_clk.c),
+	},
+};
+
+static struct measure_mux_entry measure_mux_MMSS[] = {
+	{ &mmss_mmssnoc_ahb_clk.c,  MMSS_BASE, 0x0001 },
+	{ &mmss_mmssnoc_bto_ahb_clk.c,  MMSS_BASE, 0x0002 },
+	{ &mmss_misc_ahb_clk.c,  MMSS_BASE, 0x0003 },
+	{ &mmss_mmssnoc_axi_clk.c,  MMSS_BASE, 0x0004 },
+	{ &mmss_s0_axi_clk.c,  MMSS_BASE, 0x0005 },
+	{ &ocmemcx_ahb_clk.c,  MMSS_BASE, 0x000a },
+	{ &oxilicx_axi_clk.c,  MMSS_BASE, 0x000b },
+	{ &oxilicx_ahb_clk.c,  MMSS_BASE, 0x000c },
+	{ &oxili_gfx3d_clk.c,  MMSS_BASE, 0x000d },
+	{ &venus0_vcodec0_clk.c,  MMSS_BASE, 0x000e },
+	{ &venus0_axi_clk.c,  MMSS_BASE, 0x000f },
+	{ &venus0_ahb_clk.c,  MMSS_BASE, 0x0011 },
+	{ &mdss_mdp_clk.c,  MMSS_BASE, 0x0014 },
+	{ &mdss_mdp_lut_clk.c,  MMSS_BASE, 0x0015 },
+	{ &mdss_pclk0_clk.c,  MMSS_BASE, 0x0016 },
+	{ &mdss_vsync_clk.c,  MMSS_BASE, 0x001c },
+	{ &mdss_byte0_clk.c,  MMSS_BASE, 0x001e },
+	{ &mdss_esc0_clk.c,  MMSS_BASE, 0x0020 },
+	{ &mdss_ahb_clk.c,  MMSS_BASE, 0x0022 },
+	{ &mdss_axi_clk.c,  MMSS_BASE, 0x0024 },
+	{ &camss_top_ahb_clk.c,  MMSS_BASE, 0x0025 },
+	{ &camss_micro_ahb_clk.c,  MMSS_BASE, 0x0026 },
+	{ &camss_gp0_clk.c,  MMSS_BASE, 0x0027 },
+	{ &camss_gp1_clk.c,  MMSS_BASE, 0x0028 },
+	{ &camss_mclk0_clk.c,  MMSS_BASE, 0x0029 },
+	{ &camss_mclk1_clk.c,  MMSS_BASE, 0x002a },
+	{ &camss_cci_cci_clk.c,  MMSS_BASE, 0x002d },
+	{ &camss_cci_cci_ahb_clk.c,  MMSS_BASE, 0x002e },
+	{ &camss_phy0_csi0phytimer_clk.c,  MMSS_BASE, 0x002f },
+	{ &camss_phy1_csi1phytimer_clk.c,  MMSS_BASE, 0x0030 },
+	{ &camss_jpeg_jpeg0_clk.c,  MMSS_BASE, 0x0032 },
+	{ &camss_jpeg_jpeg_ahb_clk.c,  MMSS_BASE, 0x0035 },
+	{ &camss_jpeg_jpeg_axi_clk.c,  MMSS_BASE, 0x0036 },
+	{ &camss_vfe_vfe0_clk.c,  MMSS_BASE, 0x0038 },
+	{ &camss_vfe_cpp_clk.c,  MMSS_BASE, 0x003a },
+	{ &camss_vfe_cpp_ahb_clk.c,  MMSS_BASE, 0x003b },
+	{ &camss_vfe_vfe_ahb_clk.c,  MMSS_BASE, 0x003c },
+	{ &camss_vfe_vfe_axi_clk.c,  MMSS_BASE, 0x003d },
+	{ &camss_csi_vfe0_clk.c,  MMSS_BASE, 0x003f },
+	{ &camss_csi0_clk.c,  MMSS_BASE, 0x0041 },
+	{ &camss_csi0_ahb_clk.c,  MMSS_BASE, 0x0042 },
+	{ &camss_csi0phy_clk.c,  MMSS_BASE, 0x0043 },
+	{ &camss_csi0rdi_clk.c,  MMSS_BASE, 0x0044 },
+	{ &camss_csi0pix_clk.c,  MMSS_BASE, 0x0045 },
+	{ &camss_csi1_clk.c,  MMSS_BASE, 0x0046 },
+	{ &camss_csi1_ahb_clk.c,  MMSS_BASE, 0x0047 },
+	{ &camss_csi1phy_clk.c,  MMSS_BASE, 0x0048 },
+	{ &camss_csi1rdi_clk.c,  MMSS_BASE, 0x0049 },
+	{ &camss_csi1pix_clk.c,  MMSS_BASE, 0x004a },
+	{ &camss_ispif_ahb_clk.c,  MMSS_BASE, 0x0055 },
+	{&dummy_clk, N_BASES, 0x0000},
+};
+
+static struct pll_vote_clk lpaaudio_pll = {
+	.en_reg = (void __iomem *)LPA_PLL_VOTE_APPS,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)LPAAUDIO_PLL_STATUS,
+	.status_mask = BIT(17),
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.rate = 491520000,
+		.parent = &xo.c,
+		.dbg_name = "lpaaudio_pll",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(lpaaudio_pll.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_audio_core_lpaif__osr_clk[] = {
+	F_LPASS(    512000, lpaaudio_pll,  16,    1,   60),
+	F_LPASS(    768000, lpaaudio_pll,  16,    1,   40),
+	F_LPASS(   1024000, lpaaudio_pll,  16,    1,   30),
+	F_LPASS(   1536000, lpaaudio_pll,  16,    1,   20),
+	F_LPASS(   2048000, lpaaudio_pll,  16,    1,   15),
+	F_LPASS(   3072000, lpaaudio_pll,  16,    1,   10),
+	F_LPASS(   4096000, lpaaudio_pll,  15,    1,    8),
+	F_LPASS(   6144000, lpaaudio_pll,  10,    1,    8),
+	F_LPASS(   8192000, lpaaudio_pll,  15,    1,    4),
+	F_LPASS(  12288000, lpaaudio_pll,  10,    1,    4),
+	F_END
+};
+
+static struct rcg_clk lpaif_pri_clk_src = {
+	.cmd_rcgr_reg = LPAIF_PRI_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif__osr_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "lpaif_pri_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+		CLK_INIT(lpaif_pri_clk_src.c),
+	},
+};
+
+static struct rcg_clk lpaif_quad_clk_src = {
+	.cmd_rcgr_reg = LPAIF_QUAD_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif__osr_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "lpaif_quad_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+		CLK_INIT(lpaif_quad_clk_src.c),
+	},
+};
+
+static struct rcg_clk lpaif_sec_clk_src = {
+	.cmd_rcgr_reg = LPAIF_SEC_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif__osr_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "lpaif_sec_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+		CLK_INIT(lpaif_sec_clk_src.c),
+	},
+};
+
+static struct rcg_clk lpaif_spkr_clk_src = {
+	.cmd_rcgr_reg = LPAIF_SPKR_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif__osr_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "lpaif_spkr_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+		CLK_INIT(lpaif_spkr_clk_src.c),
+	},
+};
+
+static struct rcg_clk lpaif_ter_clk_src = {
+	.cmd_rcgr_reg = LPAIF_TER_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif__osr_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "lpaif_ter_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+		CLK_INIT(lpaif_ter_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_audio_core_lpaif_pcmoe_clk[] = {
+	F_LPASS(    512000, lpaaudio_pll,  16,    1,   60),
+	F_LPASS(    768000, lpaaudio_pll,  16,    1,   40),
+	F_LPASS(   1024000, lpaaudio_pll,  16,    1,   30),
+	F_LPASS(   1536000, lpaaudio_pll,  16,    1,   20),
+	F_LPASS(   2048000, lpaaudio_pll,  16,    1,   15),
+	F_LPASS(   3072000, lpaaudio_pll,  16,    1,   10),
+	F_LPASS(   4096000, lpaaudio_pll,  15,    1,    8),
+	F_LPASS(   6144000, lpaaudio_pll,  10,    1,    8),
+	F_LPASS(   8192000, lpaaudio_pll,  15,    1,    4),
+	F_LPASS(  12288000, lpaaudio_pll,  10,    1,    4),
+	F_END
+};
+
+static struct rcg_clk lpaif_pcmoe_clk_src = {
+	.cmd_rcgr_reg = LPAIF_PCMOE_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_pcmoe_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "lpaif_pcmoe_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+		CLK_INIT(lpaif_pcmoe_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_audio_core_lpaif_pcm0_1_ibit_clk[] = {
+	F_LPASS(    512000, lpaaudio_pll,  16,    1,   60),
+	F_LPASS(    768000, lpaaudio_pll,  16,    1,   40),
+	F_LPASS(   1024000, lpaaudio_pll,  16,    1,   30),
+	F_LPASS(   1536000, lpaaudio_pll,  16,    1,   20),
+	F_LPASS(   2048000, lpaaudio_pll,  16,    1,   15),
+	F_LPASS(   3072000, lpaaudio_pll,  16,    1,   10),
+	F_LPASS(   4096000, lpaaudio_pll,  15,    1,    8),
+	F_LPASS(   6144000, lpaaudio_pll,  10,    1,    8),
+	F_LPASS(   8192000, lpaaudio_pll,  15,    1,    4),
+	F_END
+};
+
+static struct rcg_clk lpaif_pcm0_clk_src = {
+	.cmd_rcgr_reg = LPAIF_PCM0_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_pcm0_1_ibit_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "lpaif_pcm0_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8190000),
+		CLK_INIT(lpaif_pcm0_clk_src.c),
+	},
+};
+
+static struct rcg_clk lpaif_pcm1_clk_src = {
+	.cmd_rcgr_reg = LPAIF_PCM1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_lpaif_pcm0_1_ibit_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "lpaif_pcm1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8190000),
+		CLK_INIT(lpaif_pcm1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clk[] = {
+	F_LPASS(  24576000, lpaaudio_pll,  10,    1,    2),
+	F_END
+};
+
+static struct rcg_clk slimbus_clk_src = {
+	.cmd_rcgr_reg = SLIMBUS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_audio_core_slimbus_core_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "slimbus_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOW, 13000000, NOMINAL, 26010000),
+		CLK_INIT(slimbus_clk_src.c),
+	},
+};
+
+static struct branch_clk audio_core_ixfabric_clk = {
+	.cbcr_reg = AUDIO_CORE_IXFABRIC_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_ixfabric_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_ixfabric_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_slimbus_lfabif_clk = {
+	.cbcr_reg = AUDIO_CORE_SLIMBUS_LFABIF_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_slimbus_lfabif_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_slimbus_lfabif_clk.c),
+	},
+};
+
+static struct branch_clk audio_wrapper_br_clk = {
+	.cbcr_reg = AUDIO_WRAPPER_BR_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_wrapper_br_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_wrapper_br_clk.c),
+	},
+};
+
+static struct branch_clk q6ss_ahb_lfabif_clk = {
+	.cbcr_reg = Q6SS_AHB_LFABIF_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "q6ss_ahb_lfabif_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(q6ss_ahb_lfabif_clk.c),
+	},
+};
+
+static struct branch_clk q6ss_ahbm_clk = {
+	.cbcr_reg = Q6SS_AHBM_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "q6ss_ahbm_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(q6ss_ahbm_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcmoe_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcmoe_clk",
+		.parent = &lpaif_pcmoe_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcmoe_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pri_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_EBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pri_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pri_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pri_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_IBIT_CBCR,
+	.has_sibling = 1,
+	.max_div = 15,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pri_ibit_clk",
+		.parent = &lpaif_pri_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pri_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pri_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_OSR_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pri_osr_clk",
+		.parent = &lpaif_pri_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pri_osr_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcm0_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm0_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcm0_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcm0_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm0_ibit_clk",
+		.parent = &lpaif_pcm0_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcm0_ibit_clk.c),
+	},
+};
+
+static struct branch_clk q6ss_xo_clk = {
+	.cbcr_reg = Q6SS_XO_CBCR,
+	.has_sibling = 1,
+	.bcr_reg = Q6SS_BCR,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "q6ss_xo_clk",
+		.parent = &xo.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(q6ss_xo_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_quad_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_quad_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_quad_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_quad_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR,
+	.has_sibling = 1,
+	.max_div = 15,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_quad_ibit_clk",
+		.parent = &lpaif_quad_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_quad_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_quad_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_QUAD_OSR_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_quad_osr_clk",
+		.parent = &lpaif_quad_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_quad_osr_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_sec_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_EBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_sec_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_sec_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_sec_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_IBIT_CBCR,
+	.has_sibling = 1,
+	.max_div = 15,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_sec_ibit_clk",
+		.parent = &lpaif_sec_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_sec_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_sec_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_OSR_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_sec_osr_clk",
+		.parent = &lpaif_sec_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_sec_osr_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcm1_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm1_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcm1_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_pcm1_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_pcm1_ibit_clk",
+		.parent = &lpaif_pcm1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_pcm1_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_slimbus_core_clk = {
+	.cbcr_reg = AUDIO_CORE_SLIMBUS_CORE_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_slimbus_core_clk",
+		.parent = &slimbus_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_slimbus_core_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_codec_spkr_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_codec_spkr_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR,
+	.has_sibling = 1,
+	.max_div = 15,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_codec_spkr_ibit_clk",
+		.parent = &lpaif_spkr_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_codec_spkr_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_codec_spkr_osr_clk",
+		.parent = &lpaif_spkr_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_codec_spkr_osr_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_ter_ebit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_TER_EBIT_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_ter_ebit_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_ter_ebit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_ter_ibit_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_TER_IBIT_CBCR,
+	.has_sibling = 1,
+	.max_div = 15,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_ter_ibit_clk",
+		.parent = &lpaif_ter_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_ter_ibit_clk.c),
+	},
+};
+
+static struct branch_clk audio_core_lpaif_ter_osr_clk = {
+	.cbcr_reg = AUDIO_CORE_LPAIF_TER_OSR_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_lpaif_ter_osr_clk",
+		.parent = &lpaif_ter_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_lpaif_ter_osr_clk.c),
+	},
+};
+
+static struct measure_mux_entry measure_mux_LPASS[] = {
+	{ &lpaif_pcmoe_clk_src.c,  LPASS_BASE, 0x000f },
+	{ &slimbus_clk_src.c,  LPASS_BASE, 0x0011 },
+	{ &lpaif_pcm1_clk_src.c,  LPASS_BASE, 0x0012 },
+	{ &lpaif_pcm0_clk_src.c,  LPASS_BASE, 0x0013 },
+	{ &lpaif_quad_clk_src.c,  LPASS_BASE, 0x0014 },
+	{ &lpaif_ter_clk_src.c,  LPASS_BASE, 0x0015 },
+	{ &lpaif_sec_clk_src.c,  LPASS_BASE, 0x0016 },
+	{ &lpaif_pri_clk_src.c,  LPASS_BASE, 0x0017 },
+	{ &lpaif_spkr_clk_src.c,  LPASS_BASE, 0x0018 },
+	{ &q6ss_ahbm_clk.c,  LPASS_BASE, 0x001d },
+	{ &q6ss_ahb_lfabif_clk.c,  LPASS_BASE, 0x001e },
+	{ &audio_wrapper_br_clk.c,  LPASS_BASE, 0x0022 },
+	{ &q6ss_xo_clk.c,  LPASS_BASE, 0x002b },
+	{ &audio_core_lpaif_pcmoe_clk.c,  LPASS_BASE, 0x0030 },
+	{ &audio_core_slimbus_core_clk.c,  LPASS_BASE, 0x003d },
+	{ &audio_core_slimbus_lfabif_clk.c,  LPASS_BASE, 0x003e },
+	{ &audio_core_ixfabric_clk.c,  LPASS_BASE, 0x0059 },
+	{&dummy_clk, N_BASES, 0x0000},
+};
+
+
+static DEFINE_CLK_MEASURE(apc0_m_clk);
+static DEFINE_CLK_MEASURE(apc1_m_clk);
+static DEFINE_CLK_MEASURE(apc2_m_clk);
+static DEFINE_CLK_MEASURE(apc3_m_clk);
+static DEFINE_CLK_MEASURE(l2_m_clk);
+
+static struct  measure_mux_entry measure_mux_APSS[] = {
+	{&apc0_m_clk,                    APCS_BASE, 0x00010},
+	{&apc1_m_clk,                    APCS_BASE, 0x00114},
+	{&apc2_m_clk,                    APCS_BASE, 0x00220},
+	{&apc3_m_clk,                    APCS_BASE, 0x00324},
+	{&l2_m_clk,                      APCS_BASE, 0x01000},
+	{&dummy_clk, N_BASES, 0x0000}
+};
+
+#define APCS_SH_PLL_MODE        (0x000)
+#define APCS_SH_PLL_L_VAL       (0x004)
+#define APCS_SH_PLL_M_VAL       (0x008)
+#define APCS_SH_PLL_N_VAL       (0x00C)
+#define APCS_SH_PLL_USER_CTL    (0x010)
+#define APCS_SH_PLL_CONFIG_CTL  (0x014)
+#define APCS_SH_PLL_STATUS      (0x01C)
+
+enum vdd_sr2_pll_levels {
+	VDD_SR2_PLL_OFF,
+	VDD_SR2_PLL_ON,
+	VDD_SR2_PLL_NUM
+};
+
+static struct regulator *vdd_sr2_reg;
+static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
+{
+	if (level == VDD_SR2_PLL_ON) {
+		return regulator_set_voltage(vdd_sr2_reg, 1800000,
+		1800000);
+	} else {
+		return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
+	}
+}
+
+static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
+			VDD_SR2_PLL_NUM);
+
+static struct pll_freq_tbl apcs_pll_freq[] = {
+	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL( 787200000, 41, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL( 998400000, 52, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1190400000, 62, 0x0, 0x1, 0x0, 0x0, 0x0),
+	PLL_F_END
+};
+
+static struct pll_clk a7sspll = {
+	.mode_reg = (void __iomem *)APCS_SH_PLL_MODE,
+	.l_reg = (void __iomem *)APCS_SH_PLL_L_VAL,
+	.m_reg = (void __iomem *)APCS_SH_PLL_M_VAL,
+	.n_reg = (void __iomem *)APCS_SH_PLL_N_VAL,
+	.config_reg = (void __iomem *)APCS_SH_PLL_USER_CTL,
+	.status_reg = (void __iomem *)APCS_SH_PLL_STATUS,
+	.freq_tbl = apcs_pll_freq,
+	.masks = {
+		.vco_mask = BM(29, 28),
+		.pre_div_mask = BIT(12),
+		.post_div_mask = BM(9, 8),
+		.mn_en_mask = BIT(24),
+		.main_output_mask = BIT(0),
+	},
+	.base = &virt_bases[APCS_PLL_BASE],
+	.c = {
+		.dbg_name = "a7sspll",
+		.ops = &clk_ops_sr2_pll,
+		.vdd_class = &vdd_sr2_pll,
+		.fmax = (unsigned long [VDD_SR2_PLL_NUM]) {
+			[VDD_SR2_PLL_ON] = ULONG_MAX,
+		},
+		.num_fmax = VDD_SR2_PLL_NUM,
+		CLK_INIT(a7sspll.c),
+		/*
+		 * Need to skip handoff of the acpu pll to avoid
+		 * turning off the pll when the cpu is using it
+		 */
+		.flags = CLKFLAG_SKIP_HANDOFF,
+	},
+};
+
+static DEFINE_CLK_VOTER(pnoc_msmbus_clk, &pnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_clk, &cnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, &pnoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, &cnoc_a_clk.c, LONG_MAX);
+
+static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_acpu_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(oxili_gfx3d_clk_src, &gfx3d_clk_src.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_msmbus_clk, &ocmemgx_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_core_clk, &ocmemgx_clk.c, LONG_MAX);
+
+static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, LONG_MAX);
+
+#ifdef CONFIG_DEBUG_FS
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
+{
+	struct measure_clk *clk = to_measure_clk(c);
+	unsigned long flags;
+	u32 regval, clk_sel;
+	int i;
+	struct measure_mux_entry *array[] = {
+		measure_mux_GCC,
+		measure_mux_MMSS,
+		measure_mux_LPASS,
+		measure_mux_APSS,
+		NULL
+	};
+	struct measure_mux_entry *mux = array[0];
+
+	if (!parent)
+		return -EINVAL;
+
+	for (i = 0; array[i]; i++) {
+		for (mux = array[i]; mux->c != &dummy_clk; mux++)
+			if (mux->c == parent)
+				break;
+	}
+
+	if (mux->c == &dummy_clk)
+		return -EINVAL;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	/*
+	 * Program the test vector, measurement period (sample_ticks)
+	 * and scaling multiplier.
+	 */
+	clk->sample_ticks = 0x10000;
+	clk->multiplier = 1;
+
+	switch (mux->base) {
+
+	case GCC_BASE:
+		writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL));
+		clk_sel = mux->debug_mux;
+		break;
+
+	case MMSS_BASE:
+		writel_relaxed(0, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL));
+		clk_sel = 0x02C;
+		regval = BVAL(11, 0, mux->debug_mux);
+		writel_relaxed(regval, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL));
+
+		/* Activate debug clock output */
+		regval |= BIT(16);
+		writel_relaxed(regval, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL));
+		break;
+
+	case LPASS_BASE:
+		writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL));
+		clk_sel = 0x161;
+		regval = BVAL(11, 0, mux->debug_mux);
+		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL));
+
+		/* Activate debug clock output */
+		regval |= BIT(20);
+		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL));
+		break;
+
+	case APCS_BASE:
+		clk->multiplier = 4;
+		clk_sel = 362;
+		regval = readl_relaxed(APCS_REG_BASE(GLB_CLK_DIAG));
+		regval &= ~0xC0037335;
+		/* configure a divider of 4 */
+		regval = BVAL(31, 30, 0x3) | mux->debug_mux;
+		writel_relaxed(regval, APCS_REG_BASE(GLB_CLK_DIAG));
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* Set debug mux clock index */
+	regval = BVAL(8, 0, clk_sel);
+	writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL));
+
+	/* Activate debug clock output */
+	regval |= BIT(16);
+	writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL));
+
+	/* Make sure test vector is set before starting measurements. */
+	mb();
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	return 0;
+}
+
+/* Sample clock for 'ticks' reference clock ticks. */
+static u32 run_measurement(unsigned ticks)
+{
+	/* Stop counters and set the XO4 counter start value. */
+	writel_relaxed(ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL));
+
+	/* Wait for timer to become ready. */
+	while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS)) &
+			BIT(25)) != 0)
+		cpu_relax();
+
+	/* Run measurement and wait for completion. */
+	writel_relaxed(BIT(20)|ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL));
+	while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS)) &
+			BIT(25)) == 0)
+		cpu_relax();
+
+	/* Return measured ticks. */
+	return readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS)) &
+				BM(24, 0);
+}
+
+/*
+ * Perform a hardware rate measurement for a given clock.
+ * FOR DEBUG USE ONLY: Measurements take ~15 ms!
+ */
+static unsigned long measure_clk_get_rate(struct clk *c)
+{
+	unsigned long flags;
+	u32 gcc_xo4_reg_backup;
+	u64 raw_count_short, raw_count_full;
+	struct measure_clk *clk = to_measure_clk(c);
+	unsigned ret;
+
+	ret = clk_prepare_enable(&xo.c);
+	if (ret) {
+		pr_warn("CXO clock failed to enable. Can't measure\n");
+		return 0;
+	}
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+	/* Enable CXO/4 and RINGOSC branch. */
+	gcc_xo4_reg_backup = readl_relaxed(GCC_REG_BASE(GCC_XO_DIV4_CBCR));
+	writel_relaxed(0x1, GCC_REG_BASE(GCC_XO_DIV4_CBCR));
+
+	/*
+	 * The ring oscillator counter will not reset if the measured clock
+	 * is not running.  To detect this, run a short measurement before
+	 * the full measurement.  If the raw results of the two are the same
+	 * then the clock must be off.
+	 */
+
+	/* Run a short measurement. (~1 ms) */
+	raw_count_short = run_measurement(0x1000);
+	/* Run a full measurement. (~14 ms) */
+	raw_count_full = run_measurement(clk->sample_ticks);
+
+	writel_relaxed(gcc_xo4_reg_backup, GCC_REG_BASE(GCC_XO_DIV4_CBCR));
+
+	/* Return 0 if the clock is off. */
+	if (raw_count_full == raw_count_short) {
+		ret = 0;
+	} else {
+		/* Compute rate in Hz. */
+		raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
+		do_div(raw_count_full, ((clk->sample_ticks * 10) + 35));
+		ret = (raw_count_full * clk->multiplier);
+	}
+
+	writel_relaxed(0x51A00, GCC_REG_BASE(PLLTEST_PAD_CFG));
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	clk_disable_unprepare(&xo.c);
+
+	return ret;
+}
+
+#else /* !CONFIG_DEBUG_FS */
+static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	return -EINVAL;
+}
+
+static unsigned long measure_clk_get_rate(struct clk *clk)
+{
+	return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static struct clk_ops clk_ops_measure = {
+	.set_parent = measure_clk_set_parent,
+	.get_rate = measure_clk_get_rate,
+};
+
+static struct measure_clk measure_clk = {
+	.c = {
+		.dbg_name = "measure_clk",
+		.ops = &clk_ops_measure,
+		CLK_INIT(measure_clk.c),
+	},
+	.multiplier = 1,
+};
+
+static struct clk_lookup msm_clocks_8226[] = {
+	/* Debug Clocks */
+	CLK_LOOKUP("measure", measure_clk.c, "debug"),
+	CLK_LOOKUP("apc0_m_clk", apc0_m_clk, ""),
+	CLK_LOOKUP("apc1_m_clk", apc1_m_clk, ""),
+	CLK_LOOKUP("apc2_m_clk", apc2_m_clk, ""),
+	CLK_LOOKUP("apc3_m_clk", apc3_m_clk, ""),
+	CLK_LOOKUP("l2_m_clk", l2_m_clk, ""),
+
+	/* PIL-LPASS */
+	CLK_LOOKUP("xo",                         xo.c, "fe200000.qcom,lpass"),
+	CLK_LOOKUP("core_clk",          q6ss_xo_clk.c, "fe200000.qcom,lpass"),
+	CLK_LOOKUP("bus_clk",  gcc_lpass_q6_axi_clk.c, "fe200000.qcom,lpass"),
+	CLK_LOOKUP("iface_clk", q6ss_ahb_lfabif_clk.c, "fe200000.qcom,lpass"),
+	CLK_LOOKUP("reg_clk",         q6ss_ahbm_clk.c, "fe200000.qcom,lpass"),
+
+	/* PIL-MODEM */
+	CLK_LOOKUP("xo",                           xo.c, "fc880000.qcom,mss"),
+	CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "fc880000.qcom,mss"),
+	CLK_LOOKUP("iface_clk",   gcc_mss_cfg_ahb_clk.c, "fc880000.qcom,mss"),
+	CLK_LOOKUP("mem_clk",    gcc_boot_rom_ahb_clk.c, "fc880000.qcom,mss"),
+
+	/* PIL-PRONTO */
+	CLK_LOOKUP("xo", xo.c, "fb21b000.qcom,pronto"),
+
+	/* PIL-VENUS */
+	CLK_LOOKUP("src_clk",     vcodec0_clk_src.c, "fdce0000.qcom,venus"),
+	CLK_LOOKUP("core_clk", venus0_vcodec0_clk.c, "fdce0000.qcom,venus"),
+	CLK_LOOKUP("iface_clk",    venus0_ahb_clk.c, "fdce0000.qcom,venus"),
+	CLK_LOOKUP("bus_clk",      venus0_axi_clk.c, "fdce0000.qcom,venus"),
+	CLK_LOOKUP("mem_clk",      venus0_ahb_clk.c, "fdce0000.qcom,venus"),
+
+	/* ACPUCLOCK */
+	CLK_LOOKUP("xo",     xo_a_clk.c, "f9011050.qcom,acpuclk"),
+	CLK_LOOKUP("gpll0",  gpll0_ao.c, "f9011050.qcom,acpuclk"),
+	CLK_LOOKUP("a7sspll", a7sspll.c, "f9011050.qcom,acpuclk"),
+
+	/* WCNSS CLOCKS */
+	CLK_LOOKUP("xo", xo.c, "fb000000.qcom,wcnss-wlan"),
+
+	/* BUS DRIVER */
+	CLK_LOOKUP("bus_clk", cnoc_msmbus_clk.c, "msm_config_noc"),
+	CLK_LOOKUP("bus_a_clk", cnoc_msmbus_a_clk.c, "msm_config_noc"),
+	CLK_LOOKUP("bus_clk", snoc_msmbus_clk.c, "msm_sys_noc"),
+	CLK_LOOKUP("bus_a_clk", snoc_msmbus_a_clk.c, "msm_sys_noc"),
+	CLK_LOOKUP("bus_clk", pnoc_msmbus_clk.c, "msm_periph_noc"),
+	CLK_LOOKUP("bus_a_clk", pnoc_msmbus_a_clk.c, "msm_periph_noc"),
+	CLK_LOOKUP("mem_clk", bimc_msmbus_clk.c, "msm_bimc"),
+	CLK_LOOKUP("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc"),
+	CLK_LOOKUP("mem_clk", bimc_acpu_a_clk.c, ""),
+	CLK_LOOKUP("ocmem_clk",	ocmemgx_msmbus_clk.c,	  "msm_bus"),
+	CLK_LOOKUP("ocmem_a_clk", ocmemgx_msmbus_a_clk.c, "msm_bus"),
+	CLK_LOOKUP("bus_clk",	mmss_s0_axi_clk.c,	"msm_mmss_noc"),
+	CLK_LOOKUP("bus_a_clk",	mmss_s0_axi_clk.c,	"msm_mmss_noc"),
+	CLK_LOOKUP("iface_clk", gcc_mmss_noc_cfg_ahb_clk.c, ""),
+
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etr"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-replicator"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etf"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-merg"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in0"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in1"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-kpss"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-mmss"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-stm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm0"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm1"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm2"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm3"),
+
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etr"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tpiu"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-replicator"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etf"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-merg"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in0"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in1"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-kpss"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-mmss"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-stm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm0"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm1"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm2"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm3"),
+
+	/* HSUSB-OTG Clocks */
+	CLK_LOOKUP("xo",                          xo.c, "f9a55000.usb"),
+	CLK_LOOKUP("iface_clk",   gcc_usb_hs_ahb_clk.c, "f9a55000.usb"),
+	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, "f9a55000.usb"),
+
+	/* SPS CLOCKS */
+	CLK_LOOKUP("dfab_clk",            pnoc_sps_clk.c, "f9984000.qcom,sps"),
+	CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "f9884000.qcom,sps"),
+	CLK_LOOKUP("dfab_clk",            pnoc_sps_clk.c, "msm_sps"),
+	CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
+
+	/* I2C Clocks */
+	CLK_LOOKUP("iface_clk",          gcc_blsp1_ahb_clk.c, "f9926000.i2c"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup4_i2c_apps_clk.c, "f9926000.i2c"),
+
+	/* lsuart-v14 Clocks */
+	CLK_LOOKUP("iface_clk",       gcc_blsp1_ahb_clk.c, "f991f000.serial"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, "f991f000.serial"),
+
+	CLK_LOOKUP("iface_clk",       gcc_blsp1_ahb_clk.c, "f995e000.serial"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart2_apps_clk.c, "f995e000.serial"),
+
+	CLK_LOOKUP("iface_clk",          gcc_blsp1_ahb_clk.c, "f9928000.spi"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, "f9928000.spi"),
+
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,         "qseecom"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,     "qseecom"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,     "qseecom"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,         "qseecom"),
+
+	/* SDCC */
+	CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "f9824000.qcom,sdcc"),
+	CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "f9824000.qcom,sdcc"),
+	CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "msm_sdcc.1"),
+	CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "msm_sdcc.1"),
+
+	CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "f98a4000.qcom,sdcc"),
+	CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "f98a4000.qcom,sdcc"),
+	CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "msm_sdcc.2"),
+	CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "msm_sdcc.2"),
+
+	CLK_LOOKUP("iface_clk", gcc_sdcc3_ahb_clk.c, "msm_sdcc.3"),
+	CLK_LOOKUP("core_clk", gcc_sdcc3_apps_clk.c, "msm_sdcc.3"),
+
+	CLK_LOOKUP("sleep_a_clk", gcc_usb2a_phy_sleep_clk.c, "msm_dwc3"),
+	CLK_LOOKUP("ref_clk", diff_clk.c, "msm_dwc3"),
+
+
+	CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
+	CLK_LOOKUP("bus_clk", pnoc_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
+	CLK_LOOKUP("bus_clk", snoc_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk", cnoc_clk.c, ""),
+	CLK_LOOKUP("bus_clk", cnoc_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk", mmssnoc_ahb_clk.c, ""),
+	CLK_LOOKUP("bus_clk", mmssnoc_ahb_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk", bimc_clk.c, ""),
+	CLK_LOOKUP("bus_clk", bimc_a_clk.c, ""),
+	CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
+
+	CLK_LOOKUP("gpll0", gpll0.c, ""),
+	CLK_LOOKUP("gpll1", gpll1.c, ""),
+	CLK_LOOKUP("mmpll0", mmpll0_pll.c, ""),
+	CLK_LOOKUP("mmpll1", mmpll1_pll.c, ""),
+	CLK_LOOKUP("mmpll2", mmpll2_pll.c, ""),
+	CLK_LOOKUP("lpaaudio_pll", lpaaudio_pll.c, ""),
+
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup2_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup3_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup3_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup4_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup4_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup5_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup5_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup6_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup6_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart1_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart4_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart5_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_pdm2_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_pdm_ahb_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
+
+	CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c,	  "msm_hsic_host"),
+	CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c,	  "msm_hsic_host"),
+	CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c,  "msm_hsic_host"),
+	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
+	CLK_LOOKUP("ref_clk", div_clk2.c, "msm_smsc_hub"),
+	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c,     "msm_ehci_host"),
+	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c,   "msm_ehci_host"),
+	CLK_LOOKUP("pwm_clk", div_clk2.c, "0-0048"),
+
+	/* Multimedia clocks */
+	CLK_LOOKUP("byte_clk", mdss_byte0_clk.c, "fd922800.qcom,mdss_dsi"),
+	CLK_LOOKUP("core_clk", mdss_esc0_clk.c, "fd922800.qcom,mdss_dsi"),
+	CLK_LOOKUP("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi"),
+	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdss_dsi_clk_ctrl"),
+
+	CLK_LOOKUP("core_clk", mdss_mdp_clk.c, "mdp.0"),
+	CLK_LOOKUP("lut_clk", mdss_mdp_lut_clk.c, "mdp.0"),
+	CLK_LOOKUP("core_clk_src", mdp_clk_src.c, "mdp.0"),
+	CLK_LOOKUP("vsync_clk", mdss_vsync_clk.c, "mdp.0"),
+	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdp.0"),
+	CLK_LOOKUP("bus_clk", mdss_axi_clk.c, "mdp.0"),
+
+	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "fd928000.qcom,iommu"),
+	CLK_LOOKUP("core_clk", mdss_axi_clk.c, "fd928000.qcom,iommu"),
+
+	/* MM sensor clocks */
+	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6e.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "90.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6e.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "90.qcom,camera"),
+
+	/* CCI clocks */
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda0c000.qcom,cci"),
+	CLK_LOOKUP("cci_ahb_clk", camss_cci_cci_ahb_clk.c,
+		"fda0c000.qcom,cci"),
+	CLK_LOOKUP("cci_src_clk", cci_clk_src.c, "fda0c000.qcom,cci"),
+	CLK_LOOKUP("cci_clk", camss_cci_cci_clk.c, "fda0c000.qcom,cci"),
+
+	/* CSIPHY clocks */
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda0ac00.qcom,csiphy"),
+	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+		"fda0ac00.qcom,csiphy"),
+	CLK_LOOKUP("csiphy_timer_src_clk", csi0phytimer_clk_src.c,
+		"fda0ac00.qcom,csiphy"),
+	CLK_LOOKUP("csiphy_timer_clk", camss_phy0_csi0phytimer_clk.c,
+		"fda0ac00.qcom,csiphy"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda0b000.qcom,csiphy"),
+	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+		"fda0b000.qcom,csiphy"),
+	CLK_LOOKUP("csiphy_timer_src_clk", csi1phytimer_clk_src.c,
+		"fda0b000.qcom,csiphy"),
+	CLK_LOOKUP("csiphy_timer_clk", camss_phy1_csi1phytimer_clk.c,
+		"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"),
+
+	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"),
+
+	/* ISPIF clocks */
+	CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
+		"fda0a000.qcom,ispif"),
+	CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe0_clk.c,
+		"fda0a000.qcom,ispif"),
+
+	/* VFE clocks */
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+					"fda10000.qcom,vfe"),
+	CLK_LOOKUP("vfe_clk_src", vfe0_clk_src.c,	 "fda10000.qcom,vfe"),
+	CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
+					"fda10000.qcom,vfe"),
+	CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe0_clk.c,
+					"fda10000.qcom,vfe"),
+	CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c, "fda10000.qcom,vfe"),
+	CLK_LOOKUP("bus_clk", camss_vfe_vfe_axi_clk.c,	 "fda10000.qcom,vfe"),
+
+	CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c,
+	"fda44000.qcom,iommu"),
+	CLK_LOOKUP("core_clk", camss_vfe_vfe_axi_clk.c, "fda44000.qcom,iommu"),
+	CLK_LOOKUP("alt_core_clk", camss_top_ahb_clk.c, "fda44000.qcom,iommu"),
+
+	/* Jpeg Clocks */
+	CLK_LOOKUP("core_clk", camss_jpeg_jpeg0_clk.c, "fda1c000.qcom,jpeg"),
+	CLK_LOOKUP("iface_clk", camss_jpeg_jpeg_ahb_clk.c,
+						"fda1c000.qcom,jpeg"),
+	CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c,
+	"fda1c000.qcom,jpeg"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+						"fda1c000.qcom,jpeg"),
+
+	CLK_LOOKUP("alt_core_clk", camss_top_ahb_clk.c, "fda64000.qcom,iommu"),
+	CLK_LOOKUP("iface_clk", camss_jpeg_jpeg_ahb_clk.c,
+						"fda64000.qcom,iommu"),
+	CLK_LOOKUP("core_clk", camss_jpeg_jpeg_axi_clk.c,
+						"fda64000.qcom,iommu"),
+
+	/* KGSL Clocks */
+	CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, "fdb00000.qcom,kgsl-3d0"),
+	CLK_LOOKUP("iface_clk", oxilicx_ahb_clk.c, "fdb00000.qcom,kgsl-3d0"),
+
+	CLK_LOOKUP("alt_core_clk", oxili_gfx3d_clk.c, "fdb10000.qcom,iommu"),
+	CLK_LOOKUP("iface_clk", oxilicx_ahb_clk.c, "fdb10000.qcom,iommu"),
+	CLK_LOOKUP("core_clk", oxilicx_axi_clk.c, "fdb10000.qcom,iommu"),
+
+	CLK_LOOKUP("core_clk", ocmemgx_core_clk.c, "fdd00000.qcom,ocmem"),
+	CLK_LOOKUP("br_clk", audio_wrapper_br_clk.c, "fdd00000.qcom,ocmem"),
+
+	/* Venus Clocks */
+	CLK_LOOKUP("core_clk", venus0_vcodec0_clk.c, "fdc00000.qcom,vidc"),
+	CLK_LOOKUP("iface_clk",  venus0_ahb_clk.c, "fdc00000.qcom,vidc"),
+	CLK_LOOKUP("bus_clk",  venus0_axi_clk.c, "fdc00000.qcom,vidc"),
+
+	CLK_LOOKUP("alt_core_clk", venus0_vcodec0_clk.c,
+	"fdc84000.qcom,iommu"),
+	CLK_LOOKUP("iface_clk", venus0_ahb_clk.c, "fdc84000.qcom,iommu"),
+	CLK_LOOKUP("core_clk", venus0_axi_clk.c, "fdc84000.qcom,iommu"),
+
+	CLK_LOOKUP("cam_gp0_clk", camss_gp0_clk.c, ""),
+	CLK_LOOKUP("cam_gp1_clk", camss_gp1_clk.c, ""),
+	CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
+
+	CLK_LOOKUP("", mmss_mmssnoc_ahb_clk.c, ""),
+	CLK_LOOKUP("", mmss_mmssnoc_bto_ahb_clk.c, ""),
+	CLK_LOOKUP("", mmss_mmssnoc_axi_clk.c, ""),
+	CLK_LOOKUP("", mmss_s0_axi_clk.c, ""),
+	CLK_LOOKUP("", ocmemcx_ahb_clk.c, ""),
+
+	/* LPASS CLOCKS */
+	CLK_LOOKUP("core_clk", audio_core_slimbus_core_clk.c, "fe12f000.slim"),
+	CLK_LOOKUP("iface_clk", audio_core_slimbus_lfabif_clk.c,
+			"fe12f000.slim"),
+
+	CLK_LOOKUP("core_clk", lpaif_quad_clk_src.c,
+			"msm-dai-q6-mi2s.3"),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_quad_osr_clk.c,
+			"msm-dai-q6-mi2s.3"),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_quad_ebit_clk.c,
+			"msm-dai-q6-mi2s.3"),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_quad_ibit_clk.c,
+			"msm-dai-q6-mi2s.3"),
+
+	CLK_LOOKUP("pcm_clk", lpaif_pcm0_clk_src.c,
+						"msm-dai-q6.4106"),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c,
+						"msm-dai-q6.4106"),
+	CLK_LOOKUP("core_oe_src_clk", lpaif_pcmoe_clk_src.c,
+						"msm-dai-q6.4106"),
+	CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
+						"msm-dai-q6.4106"),
+
+	CLK_LOOKUP("pcm_clk", lpaif_pcm0_clk_src.c,
+						"msm-dai-q6.4107"),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c,
+						"msm-dai-q6.4107"),
+	CLK_LOOKUP("core_oe_src_clk", lpaif_pcmoe_clk_src.c,
+						"msm-dai-q6.4107"),
+	CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
+						"msm-dai-q6.4107"),
+
+
+	CLK_LOOKUP("bus_clk", audio_core_ixfabric_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
+	CLK_LOOKUP("core_clk", lpaif_pcm1_clk_src.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", lpaif_spkr_clk_src.c, ""),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_codec_spkr_osr_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_codec_spkr_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_codec_spkr_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", lpaif_pri_clk_src.c, ""),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_pri_osr_clk.c, ""),
+
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pri_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pri_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", lpaif_sec_clk_src.c, ""),
+
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_sec_osr_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_sec_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_sec_ibit_clk.c, ""),
+
+	CLK_LOOKUP("core_clk", lpaif_ter_clk_src.c, ""),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_ter_osr_clk.c, ""),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_ter_ebit_clk.c, ""),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_ter_ibit_clk.c, ""),
+};
+
+static struct clk_lookup msm_clocks_8226_rumi[] = {
+	CLK_DUMMY("core_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("iface_clk", HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
+	CLK_DUMMY("core_clk", HSUSB_CORE_CLK, "f9a55000.usb", OFF),
+	CLK_DUMMY("iface_clk", NULL, "msm_sdcc.1", OFF),
+	CLK_DUMMY("core_clk",  NULL, "msm_sdcc.1", OFF),
+	CLK_DUMMY("bus_clk",   NULL, "msm_sdcc.1", OFF),
+	CLK_DUMMY("iface_clk", NULL, "msm_sdcc.2", OFF),
+	CLK_DUMMY("core_clk",  NULL, "msm_sdcc.2", OFF),
+	CLK_DUMMY("bus_clk",   NULL, "msm_sdcc.2", OFF),
+};
+
+struct clock_init_data msm8226_rumi_clock_init_data __initdata = {
+	.table = msm_clocks_8226_rumi,
+	.size = ARRAY_SIZE(msm_clocks_8226_rumi),
+};
+
+static struct pll_config_regs gpll0_regs __initdata = {
+	.l_reg = (void __iomem *)GPLL0_L_VAL,
+	.m_reg = (void __iomem *)GPLL0_M_VAL,
+	.n_reg = (void __iomem *)GPLL0_N_VAL,
+	.config_reg = (void __iomem *)GPLL0_USER_CTL,
+	.mode_reg = (void __iomem *)GPLL0_MODE,
+	.base = &virt_bases[GCC_BASE],
+};
+
+/* GPLL0 at 600 MHz, main output enabled. */
+static struct pll_config gpll0_config __initdata = {
+	.l = 0x1f,
+	.m = 0x1,
+	.n = 0x4,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs gpll1_regs __initdata = {
+	.l_reg = (void __iomem *)GPLL1_L_VAL,
+	.m_reg = (void __iomem *)GPLL1_M_VAL,
+	.n_reg = (void __iomem *)GPLL1_N_VAL,
+	.config_reg = (void __iomem *)GPLL1_USER_CTL,
+	.mode_reg = (void __iomem *)GPLL1_MODE,
+	.base = &virt_bases[GCC_BASE],
+};
+
+/* GPLL1 at 480 MHz, main output enabled. */
+static struct pll_config gpll1_config __initdata = {
+	.l = 0x19,
+	.m = 0x0,
+	.n = 0x1,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs mmpll0_regs __initdata = {
+	.l_reg = (void __iomem *)MMPLL0_PLL_L_VAL,
+	.m_reg = (void __iomem *)MMPLL0_PLL_M_VAL,
+	.n_reg = (void __iomem *)MMPLL0_PLL_N_VAL,
+	.config_reg = (void __iomem *)MMPLL0_PLL_USER_CTL,
+	.mode_reg = (void __iomem *)MMPLL0_PLL_MODE,
+	.base = &virt_bases[MMSS_BASE],
+};
+
+/* MMPLL0 at 800 MHz, main output enabled. */
+static struct pll_config mmpll0_config __initdata = {
+	.l = 0x29,
+	.m = 0x2,
+	.n = 0x3,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs mmpll1_regs __initdata = {
+	.l_reg = (void __iomem *)MMPLL1_PLL_L_VAL,
+	.m_reg = (void __iomem *)MMPLL1_PLL_M_VAL,
+	.n_reg = (void __iomem *)MMPLL1_PLL_N_VAL,
+	.config_reg = (void __iomem *)MMPLL1_PLL_USER_CTL,
+	.mode_reg = (void __iomem *)MMPLL1_PLL_MODE,
+	.base = &virt_bases[MMSS_BASE],
+};
+
+/* MMPLL1 at 1000 MHz, main output enabled. */
+static struct pll_config mmpll1_config __initdata = {
+	.l = 0x2C,
+	.m = 0x1,
+	.n = 0x10,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs lpapll0_regs __initdata = {
+	.l_reg = (void __iomem *)LPAAUDIO_PLL_L,
+	.m_reg = (void __iomem *)LPAAUDIO_PLL_M,
+	.n_reg = (void __iomem *)LPAAUDIO_PLL_N,
+	.config_reg = (void __iomem *)LPAAUDIO_PLL_USER_CTL,
+	.mode_reg = (void __iomem *)LPAAUDIO_PLL_MODE,
+	.base = &virt_bases[LPASS_BASE],
+};
+
+/* LPAPLL0 at 491.52 MHz, main output enabled. */
+static struct pll_config lpapll0_config __initdata = {
+	.l = 0x33,
+	.m = 0x1,
+	.n = 0x5,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = BVAL(14, 12, 0x1),
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
+#define PLL_AUX_OUTPUT_BIT 1
+#define PLL_AUX2_OUTPUT_BIT 2
+
+#define PWR_ON_MASK		BIT(31)
+#define EN_REST_WAIT_MASK	(0xF << 20)
+#define EN_FEW_WAIT_MASK	(0xF << 16)
+#define CLK_DIS_WAIT_MASK	(0xF << 12)
+#define SW_OVERRIDE_MASK	BIT(2)
+#define HW_CONTROL_MASK		BIT(1)
+#define SW_COLLAPSE_MASK	BIT(0)
+
+/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
+#define EN_REST_WAIT_VAL	(0x2 << 20)
+#define EN_FEW_WAIT_VAL		(0x2 << 16)
+#define CLK_DIS_WAIT_VAL	(0x2 << 12)
+#define GDSC_TIMEOUT_US		50000
+
+#define PLL_OUTCTRL BIT(0)
+#define PLL_BYPASSNL BIT(1)
+#define PLL_RESET_N BIT(2)
+#define PLL_LOCKED_BIT BIT(16)
+#define ENABLE_WAIT_MAX_LOOPS 200
+
+static void __init reg_init(void)
+{
+	u32 regval, status;
+	int ret;
+
+	if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS))
+			& gpll0.status_mask))
+		configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
+
+	if (!(readl_relaxed(GCC_REG_BASE(GPLL1_STATUS))
+			& gpll1.status_mask))
+		configure_sr_hpm_lp_pll(&gpll1_config, &gpll1_regs, 1);
+
+	configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
+	configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
+	configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
+
+	/* Enable GPLL0's aux outputs. */
+	regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL));
+	regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
+	writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL));
+
+	/* Vote for GPLL0 to turn on. Needed by acpuclock. */
+	regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE));
+	regval |= BIT(0);
+	writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE));
+
+	/*
+	 * TODO: Confirm that no clocks need to be voted on in this sleep vote
+	 * register.
+	 */
+	writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
+
+	/*
+	 * TODO: The following sequence enables the LPASS audio core GDSC.
+	 * Remove when this becomes unnecessary.
+	 */
+
+	/*
+	 * Disable HW trigger: collapse/restore occur based on registers writes
+	 * Disable SW override: Use hardware state-machine for sequencing.
+	 */
+	regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+	regval &= ~(HW_CONTROL_MASK | SW_OVERRIDE_MASK);
+
+	/* Configure wait time between states. */
+	regval &= ~(EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK);
+	regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
+	writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+
+	regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+	regval &= ~BIT(0);
+	writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+
+	ret = readl_poll_timeout(LPASS_REG_BASE(AUDIO_CORE_GDSCR), status,
+				status & PWR_ON_MASK, 50, GDSC_TIMEOUT_US);
+	WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
+}
+static void __init msm8226_clock_post_init(void)
+{
+
+	/* Set rates for single-rate clocks. */
+	clk_set_rate(&usb_hs_system_clk_src.c,
+			usb_hs_system_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&usb_hsic_clk_src.c,
+			usb_hsic_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&usb_hsic_io_cal_clk_src.c,
+			usb_hsic_io_cal_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&usb_hsic_system_clk_src.c,
+			usb_hsic_system_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&pdm2_clk_src.c, pdm2_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&cci_clk_src.c, cci_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&mclk0_clk_src.c, mclk0_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&mclk1_clk_src.c, mclk1_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&esc0_clk_src.c, esc0_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&vsync_clk_src.c, vsync_clk_src.freq_tbl[0].freq_hz);
+	clk_set_rate(&slimbus_clk_src.c,
+			slimbus_clk_src.freq_tbl[0].freq_hz);
+}
+
+#define GCC_CC_PHYS		0xFC400000
+#define GCC_CC_SIZE		SZ_16K
+
+#define MMSS_CC_PHYS		0xFD8C0000
+#define MMSS_CC_SIZE		SZ_256K
+
+#define LPASS_CC_PHYS		0xFE000000
+#define LPASS_CC_SIZE		SZ_256K
+
+#define APCS_KPSS_SH_PLL_PHYS	0xF9016000
+#define APCS_KPSS_SH_PLL_SIZE	SZ_64
+
+#define APCS_KPSS_GLB_PHYS	0xF9011000
+#define APCS_KPSS_GLB_SIZE	SZ_4K
+
+
+static void __init msm8226_clock_pre_init(void)
+{
+	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
+	if (!virt_bases[GCC_BASE])
+		panic("clock-8226: Unable to ioremap GCC memory!");
+
+	virt_bases[MMSS_BASE] = ioremap(MMSS_CC_PHYS, MMSS_CC_SIZE);
+	if (!virt_bases[MMSS_BASE])
+		panic("clock-8226: Unable to ioremap MMSS_CC memory!");
+
+	virt_bases[LPASS_BASE] = ioremap(LPASS_CC_PHYS, LPASS_CC_SIZE);
+	if (!virt_bases[LPASS_BASE])
+		panic("clock-8226: Unable to ioremap LPASS_CC memory!");
+
+	virt_bases[APCS_BASE] = ioremap(APCS_KPSS_GLB_PHYS,
+		APCS_KPSS_GLB_SIZE);
+	if (!virt_bases[APCS_BASE])
+		panic("clock-8226: Unable to ioremap APCS_GCC_CC memory!");
+
+	virt_bases[APCS_PLL_BASE] = ioremap(APCS_KPSS_SH_PLL_PHYS,
+		APCS_KPSS_SH_PLL_SIZE);
+	if (!virt_bases[APCS_PLL_BASE])
+		panic("clock-8226: Unable to ioremap APCS_GCC_CC memory!");
+
+	clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
+
+	vdd_dig_reg = regulator_get(NULL, "vdd_dig");
+	if (IS_ERR(vdd_dig_reg))
+		panic("clock-8226: Unable to get the vdd_dig regulator!");
+
+	vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
+	if (IS_ERR(vdd_dig_reg))
+		panic("clock-8226: Unable to get the sr2_pll regulator!");
+
+	/*
+	 * The SR2 PLL is used at boot. Vote to prevent its regulator from
+	 * being turned off while the PLL is still in use.
+	 */
+	regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
+	regulator_enable(vdd_sr2_reg);
+
+	/*
+	 * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
+	 * until late_init. This may not be necessary with clock handoff;
+	 * Investigate this code on a real non-simulator target to determine
+	 * its necessity.
+	 */
+	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+	regulator_enable(vdd_dig_reg);
+
+	/*
+	 * Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
+	 * source. Sleep set vote is 0.
+	 * RPM will also turn on gcc_mmss_noc_cfg_ahb_clk, which is needed to
+	 * access mmss clock controller registers.
+	 */
+	clk_set_rate(&mmssnoc_ahb_a_clk.c, 40000000);
+	clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
+
+	/*
+	 * Hold an active set vote for CXO; this is because CXO is expected
+	 * to remain on whenever CPUs aren't power collapsed.
+	 */
+	clk_prepare_enable(&xo_a_clk.c);
+
+	enable_rpm_scaling();
+
+	reg_init();
+	/*
+	 * FIXME remove after bus driver is in place
+	 * Requires gpll0 to be configured
+	 */
+	clk_set_rate(&axi_clk_src.c, 200000000);
+	clk_prepare_enable(&mmss_s0_axi_clk.c);
+
+
+	/* TODO: Delete this code once bootloaders enable this clk
+	 * Temporarily enable a clock to allow access to LPASS core
+	 * registers. Possibly requires gdsc to be enabled.
+	 */
+	clk_prepare_enable(&audio_core_ixfabric_clk.c);
+
+	/*
+	 * TODO: Enable the gcc_bimc_clk smcbc, which is the parent of thhe
+	 * mss_gcc_q6_bimc_axi_clk
+	 */
+	writel_relaxed(0x1, GCC_REG_BASE(0x1118));
+}
+
+static int __init msm8226_clock_late_init(void)
+{
+	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+}
+
+struct clock_init_data msm8226_clock_init_data __initdata = {
+	.table = msm_clocks_8226,
+	.size = ARRAY_SIZE(msm_clocks_8226),
+	.pre_init = msm8226_clock_pre_init,
+	.post_init = msm8226_clock_post_init,
+	.late_init = msm8226_clock_late_init,
+};
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 159f151..55427b5 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/iopoll.h>
+#include <linux/regulator/consumer.h>
 
 #include <mach/rpm-regulator-smd.h>
 #include <mach/socinfo.h>
@@ -35,6 +36,7 @@
 	MMSS_BASE,
 	LPASS_BASE,
 	APCS_BASE,
+	APCS_PLL_BASE,
 	N_BASES,
 };
 
@@ -359,6 +361,17 @@
 			| BVAL(10, 8, s##_source_val), \
 	}
 
+#define F_APCS_PLL(f, l, m, n, pre_div, post_div, vco) \
+	{ \
+		.freq_hz = (f), \
+		.l_val = (l), \
+		.m_val = (m), \
+		.n_val = (n), \
+		.pre_div_val = BVAL(12, 12, (pre_div)), \
+		.post_div_val = BVAL(9, 8, (post_div)), \
+		.vco_val = BVAL(29, 28, (vco)), \
+	}
+
 #define F_MM(f, s, div, m, n) \
 	{ \
 		.freq_hz = (f), \
@@ -439,11 +452,11 @@
 	[VDD_DIG_HIGH]	  = RPM_REGULATOR_CORNER_SUPER_TURBO,
 };
 
-static struct rpm_regulator *vdd_dig_reg;
+static struct regulator *vdd_dig_reg;
 
 static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
 {
-	return rpm_regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
+	return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
 					RPM_REGULATOR_CORNER_SUPER_TURBO);
 }
 
@@ -517,21 +530,117 @@
 static DEFINE_CLK_VOTER(pnoc_iommu_clk, &pnoc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(pnoc_qseecom_clk, &pnoc_clk.c, LONG_MAX);
 
+static DEFINE_CLK_MEASURE(apc0_m_clk);
+static DEFINE_CLK_MEASURE(apc1_m_clk);
+static DEFINE_CLK_MEASURE(apc2_m_clk);
+static DEFINE_CLK_MEASURE(apc3_m_clk);
+static DEFINE_CLK_MEASURE(l2_m_clk);
+
+#define APCS_SH_PLL_MODE        0x000
+#define APCS_SH_PLL_L_VAL       0x004
+#define APCS_SH_PLL_M_VAL       0x008
+#define APCS_SH_PLL_N_VAL       0x00C
+#define APCS_SH_PLL_USER_CTL    0x010
+#define APCS_SH_PLL_CONFIG_CTL  0x014
+#define APCS_SH_PLL_STATUS      0x01C
+
+enum vdd_sr2_pll_levels {
+	VDD_SR2_PLL_OFF,
+	VDD_SR2_PLL_ON,
+	VDD_SR2_PLL_NUM
+};
+
+static struct regulator *vdd_sr2_reg;
+
+static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
+{
+	if (level == VDD_SR2_PLL_ON) {
+		return regulator_set_voltage(vdd_sr2_reg, 1800000,
+		1800000);
+	} else {
+		return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
+	}
+}
+
+static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
+			VDD_SR2_PLL_NUM);
+
+static struct pll_freq_tbl apcs_pll_freq[] = {
+	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL( 787200000, 41, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL( 998400000, 52, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1190400000, 62, 0x0, 0x1, 0x0, 0x0, 0x0),
+	PLL_F_END
+};
+
+static struct pll_clk a7sspll = {
+	.mode_reg = (void __iomem *)APCS_SH_PLL_MODE,
+	.l_reg = (void __iomem *)APCS_SH_PLL_L_VAL,
+	.m_reg = (void __iomem *)APCS_SH_PLL_M_VAL,
+	.n_reg = (void __iomem *)APCS_SH_PLL_N_VAL,
+	.config_reg = (void __iomem *)APCS_SH_PLL_USER_CTL,
+	.status_reg = (void __iomem *)APCS_SH_PLL_STATUS,
+	.freq_tbl = apcs_pll_freq,
+	.masks = {
+		.vco_mask = BM(29, 28),
+		.pre_div_mask = BIT(12),
+		.post_div_mask = BM(9, 8),
+		.mn_en_mask = BIT(24),
+		.main_output_mask = BIT(0),
+	},
+	.base = &virt_bases[APCS_PLL_BASE],
+	.c = {
+		.dbg_name = "a7sspll",
+		.ops = &clk_ops_sr2_pll,
+		.vdd_class = &vdd_sr2_pll,
+		.fmax = (unsigned long [VDD_SR2_PLL_NUM]) {
+			[VDD_SR2_PLL_ON] = ULONG_MAX,
+		},
+		.num_fmax = VDD_SR2_PLL_NUM,
+		CLK_INIT(a7sspll.c),
+		/*
+		 * Need to skip handoff of the acpu pll to avoid
+		 * turning off the pll when the cpu is using it
+		 */
+		.flags = CLKFLAG_SKIP_HANDOFF,
+	},
+};
+
+static unsigned int soft_vote_gpll0;
+
 static struct pll_vote_clk gpll0_clk_src = {
 	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
 	.en_mask = BIT(0),
 	.status_reg = (void __iomem *)GPLL0_STATUS,
 	.status_mask = BIT(17),
+	.soft_vote = &soft_vote_gpll0,
+	.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &gcc_xo_clk_src.c,
 		.rate = 600000000,
 		.dbg_name = "gpll0_clk_src",
-		.ops = &clk_ops_pll_vote,
+		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(gpll0_clk_src.c),
 	},
 };
 
+static struct pll_vote_clk gpll0_ao_clk_src = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)GPLL0_STATUS,
+	.status_mask = BIT(17),
+	.soft_vote = &soft_vote_gpll0,
+	.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.rate = 600000000,
+		.dbg_name = "gpll0_ao_clk_src",
+		.ops = &clk_ops_pll_acpu_vote,
+		CLK_INIT(gpll0_ao_clk_src.c),
+	},
+};
+
 static struct pll_vote_clk mmpll0_clk_src = {
 	.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS_REG,
 	.en_mask = BIT(0),
@@ -1450,27 +1559,6 @@
 	},
 };
 
-static struct clk_freq_tbl ftbl_mmss_mmssnoc_ahb_clk[] = {
-	F_MM(19200000, gcc_xo,  1, 0, 0),
-	F_MM(40000000,  gpll0, 15, 0, 0),
-	F_MM(80000000, mmpll0, 10, 0, 0),
-	F_END,
-};
-
-static struct rcg_clk ahb_clk_src = {
-	.cmd_rcgr_reg = AHB_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_mmss_mmssnoc_ahb_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[MMSS_BASE],
-	.c = {
-		.dbg_name = "ahb_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 40000000, NOMINAL, 80000000),
-		CLK_INIT(ahb_clk_src.c),
-	},
-};
-
 static struct clk_freq_tbl ftbl_mmss_mmssnoc_axi_clk[] = {
 	F_MM( 19200000, gcc_xo,  1, 0, 0),
 	F_MM( 37500000,  gpll0, 16, 0, 0),
@@ -1496,6 +1584,9 @@
 	},
 };
 
+static DEFINE_CLK_VOTER(mdp_axi_clk_src, &axi_clk_src.c, 200000000);
+static DEFINE_CLK_VOTER(mmssnoc_axi_clk_src, &axi_clk_src.c, 200000000);
+
 static struct clk_freq_tbl ftbl_dsi_pclk_clk[] = {
 	F_MDSS( 50000000, dsipll, 10, 0, 0),
 	F_MDSS(103330000, dsipll,  9, 0, 0),
@@ -1997,12 +2088,11 @@
 
 static struct branch_clk mdp_axi_clk = {
 	.cbcr_reg = MDP_AXI_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	 /* FIXME: Remove this once simulation is fixed. */
 	.halt_check = DELAY,
 	.c = {
-		.parent = &axi_clk_src.c,
+		.parent = &mdp_axi_clk_src.c,
 		.dbg_name = "mdp_axi_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(mdp_axi_clk.c),
@@ -2073,7 +2163,7 @@
 	.has_sibling = 0,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
-		.parent = &axi_clk_src.c,
+		.parent = &mmssnoc_axi_clk_src.c,
 		.dbg_name = "mmss_s0_axi_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(mmss_s0_axi_clk.c),
@@ -2081,18 +2171,6 @@
 	},
 };
 
-static struct branch_clk mmss_mmssnoc_ahb_clk = {
-	.cbcr_reg = MMSS_MMSSNOC_AHB_CBCR,
-	.has_sibling = 0,
-	.base = &virt_bases[MMSS_BASE],
-	.c = {
-		.parent = &ahb_clk_src.c,
-		.dbg_name = "mmss_mmssnoc_ahb_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(mmss_mmssnoc_ahb_clk.c),
-	},
-};
-
 static struct branch_clk mmss_mmssnoc_bto_ahb_clk = {
 	.cbcr_reg = MMSS_MMSSNOC_BTO_AHB_CBCR,
 	.has_sibling = 1,
@@ -2682,7 +2760,7 @@
 	{                   &bimc_clk.c, GCC_BASE, 0x0154},
 	{       &gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160},
 
-	{&mmss_mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001},
+	{     &mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001},
 	{   &mmss_misc_ahb_clk.c, MMSS_BASE, 0x0003},
 	{&mmss_mmssnoc_axi_clk.c, MMSS_BASE, 0x0004},
 	{     &mmss_s0_axi_clk.c, MMSS_BASE, 0x0005},
@@ -2733,6 +2811,12 @@
 	{&audio_core_lpaif_pcm_data_oe_clk.c, LPASS_BASE, 0x0030},
 	{         &audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
 
+	{&apc0_m_clk,                    APCS_BASE, 0x10},
+	{&apc1_m_clk,                    APCS_BASE, 0x11},
+	{&apc2_m_clk,                    APCS_BASE, 0x12},
+	{&apc3_m_clk,                    APCS_BASE, 0x13},
+	{&l2_m_clk,                      APCS_BASE, 0x15},
+
 	{&dummy_clk, N_BASES, 0x0000},
 };
 
@@ -2935,7 +3019,7 @@
 	CLK_LOOKUP("xo",	gcc_xo_clk_src.c, "pil-q6v5-mss"),
 	CLK_LOOKUP("xo",	gcc_xo_clk_src.c, "pil-mba"),
 	CLK_LOOKUP("xo",	gcc_xo_clk_src.c, "fb000000.qcom,wcnss-wlan"),
-	CLK_LOOKUP("xo",	gcc_xo_clk_src.c, "pil_pronto"),
+	CLK_LOOKUP("xo",	gcc_xo_clk_src.c, "fb21b000.qcom,pronto"),
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
 
 	CLK_LOOKUP("iface_clk",  gcc_blsp1_ahb_clk.c, "f991f000.serial"),
@@ -3014,12 +3098,12 @@
 	CLK_LOOKUP("core_clk_src",          sdcc2_apps_clk_src.c, ""),
 	CLK_LOOKUP("core_clk_src",       usb_hs_system_clk_src.c, ""),
 
-	CLK_LOOKUP("iface_clk",            gcc_blsp1_ahb_clk.c, ""),
+	CLK_LOOKUP("iface_clk",           gcc_blsp1_ahb_clk.c, "f9925000.i2c"),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup1_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup1_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup2_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup2_spi_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk",  gcc_blsp1_qup3_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk",  gcc_blsp1_qup3_i2c_apps_clk.c, "f9925000.i2c"),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup3_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup4_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup4_spi_apps_clk.c, ""),
@@ -3058,6 +3142,8 @@
 
 	CLK_LOOKUP("core_clk_src",                csi0_clk_src.c, ""),
 	CLK_LOOKUP("core_clk_src",                 axi_clk_src.c, ""),
+	CLK_LOOKUP("",                         mdp_axi_clk_src.c, ""),
+	CLK_LOOKUP("",                     mmssnoc_axi_clk_src.c, ""),
 	CLK_LOOKUP("core_clk_src",            dsi_pclk_clk_src.c, ""),
 	CLK_LOOKUP("core_clk_src",               gfx3d_clk_src.c, ""),
 	CLK_LOOKUP("core_clk_src",                 vfe_clk_src.c, ""),
@@ -3099,7 +3185,6 @@
 	CLK_LOOKUP("core_clk",                mdp_vsync_clk.c, ""),
 	CLK_LOOKUP("core_clk",            mmss_misc_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk",              mmss_s0_axi_clk.c, ""),
-	CLK_LOOKUP("core_clk",         mmss_mmssnoc_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk",     mmss_mmssnoc_bto_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk",         mmss_mmssnoc_axi_clk.c, ""),
 	CLK_LOOKUP("core_clk",                      vfe_clk.c, ""),
@@ -3163,6 +3248,16 @@
 	CLK_LOOKUP("bus_clk", gcc_lpass_q6_axi_clk.c,  "fe200000.qcom,lpass"),
 	CLK_LOOKUP("iface_clk", q6ss_ahb_lfabif_clk.c, "fe200000.qcom,lpass"),
 	CLK_LOOKUP("reg_clk",        q6ss_ahbm_clk.c,  "fe200000.qcom,lpass"),
+
+	CLK_LOOKUP("xo",      gcc_xo_a_clk_src.c, "f9011050.qcom,acpuclk"),
+	CLK_LOOKUP("gpll0", gpll0_ao_clk_src.c, "f9011050.qcom,acpuclk"),
+	CLK_LOOKUP("a7sspll",        a7sspll.c, "f9011050.qcom,acpuclk"),
+
+	CLK_LOOKUP("measure_clk", apc0_m_clk, ""),
+	CLK_LOOKUP("measure_clk", apc1_m_clk, ""),
+	CLK_LOOKUP("measure_clk", apc2_m_clk, ""),
+	CLK_LOOKUP("measure_clk", apc3_m_clk, ""),
+	CLK_LOOKUP("measure_clk",   l2_m_clk, ""),
 };
 
 static struct clk_lookup msm_clocks_8610_rumi[] = {
@@ -3189,6 +3284,9 @@
 	CLK_DUMMY("core_clk",   NULL, "fd000000.qcom,iommu", OFF),
 	CLK_DUMMY("iface_clk",  NULL, "fd010000.qcom,iommu", OFF),
 	CLK_DUMMY("core_clk",   NULL, "fd010000.qcom,iommu", OFF),
+	CLK_DUMMY("xo",      NULL, "f9011050.qcom,acpuclk", OFF),
+	CLK_DUMMY("gpll0",      NULL, "f9011050.qcom,acpuclk", OFF),
+	CLK_DUMMY("a7sspll",    NULL, "f9011050.qcom,acpuclk", OFF),
 };
 
 struct clock_init_data msm8610_rumi_clock_init_data __initdata = {
@@ -3385,6 +3483,9 @@
 #define APCS_GCC_CC_PHYS	0xF9011000
 #define APCS_GCC_CC_SIZE	SZ_4K
 
+#define APCS_KPSS_SH_PLL_PHYS	0xF9016000
+#define APCS_KPSS_SH_PLL_SIZE	SZ_64
+
 static void __init msm8610_clock_pre_init(void)
 {
 	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
@@ -3403,12 +3504,24 @@
 	if (!virt_bases[APCS_BASE])
 		panic("clock-8610: Unable to ioremap APCS_GCC_CC memory!");
 
+	virt_bases[APCS_PLL_BASE] = ioremap(APCS_KPSS_SH_PLL_PHYS,
+		APCS_KPSS_SH_PLL_SIZE);
+	if (!virt_bases[APCS_PLL_BASE])
+		panic("clock-8610: Unable to ioremap APCS_GCC_CC memory!");
+
 	clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
 
-	vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
+	vdd_dig_reg = regulator_get(NULL, "vdd_dig");
 	if (IS_ERR(vdd_dig_reg))
 		panic("clock-8610: Unable to get the vdd_dig regulator!");
 
+	vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
+	if (IS_ERR(vdd_sr2_reg))
+		panic("clock-8610: Unable to get the vdd_sr2_pll regulator!");
+
+	regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
+	regulator_enable(vdd_sr2_reg);
+
 	/*
 	 * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
 	 * until late_init. This may not be necessary with clock handoff;
@@ -3416,7 +3529,7 @@
 	 * its necessity.
 	 */
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	rpm_regulator_enable(vdd_dig_reg);
+	regulator_enable(vdd_dig_reg);
 
 	enable_rpm_scaling();
 
@@ -3425,10 +3538,12 @@
 
 	reg_init();
 
+	/* Maintain the max nominal frequency on the MMSSNOC AHB bus. */
+	clk_set_rate(&mmssnoc_ahb_a_clk.c,  40000000);
+	clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
+
 	/* TODO: Remove this once the bus driver is in place */
-	clk_set_rate(&ahb_clk_src.c,  40000000);
 	clk_set_rate(&axi_clk_src.c, 200000000);
-	clk_prepare_enable(&mmss_mmssnoc_ahb_clk.c);
 	clk_prepare_enable(&mmss_s0_axi_clk.c);
 
 	/* TODO: Temporarily enable a clock to allow access to LPASS core
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 01ccb5e..aefaa5c 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4137,6 +4137,7 @@
 	F_TV( 27000000, hdmi_pll,  27000000, 1, 0, 0),
 	F_TV( 27030000, hdmi_pll,  27030000, 1, 0, 0),
 	F_TV( 74250000, hdmi_pll,  74250000, 1, 0, 0),
+	F_TV(108000000, hdmi_pll, 108000000, 1, 0, 0),
 	F_TV(148500000, hdmi_pll, 148500000, 1, 0, 0),
 	F_END
 };
@@ -5505,18 +5506,18 @@
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,		"mdp.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,	"footswitch-8x60.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.0"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.1"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.2"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.3"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.5"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.6"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.7"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.8"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.9"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.10"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.11"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.0"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.1"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.2"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.3"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.4"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.5"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.6"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.7"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.8"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.9"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.10"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.11"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"footswitch-8x60.6"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,		"msm_vidc.0"),
@@ -5583,19 +5584,19 @@
 	CLK_LOOKUP("core_clk",	      usb_hsic_system_clk.c,   "msm_hsic_host"),
 	CLK_LOOKUP("iface_clk",	      usb_hsic_p_clk.c,        "msm_hsic_host"),
 
-	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	"msm_iommu.0"),
-	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		"msm_iommu.1"),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.2"),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.3"),
-	CLK_LOOKUP("core_clk",		rot_axi_clk.c,		"msm_iommu.4"),
-	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,	"msm_iommu.5"),
-	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,		"msm_iommu.6"),
-	CLK_LOOKUP("core_clk",		vcodec_axi_a_clk.c,	"msm_iommu.7"),
-	CLK_LOOKUP("core_clk",		vcodec_axi_b_clk.c,	"msm_iommu.8"),
-	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,	"msm_iommu.9"),
-	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,	"msm_iommu.10"),
+	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,    "msm_iommu-v0.0"),
+	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,	    "msm_iommu-v0.1"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,	    "msm_iommu-v0.2"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,	    "msm_iommu-v0.3"),
+	CLK_LOOKUP("core_clk",		rot_axi_clk.c,	    "msm_iommu-v0.4"),
+	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,    "msm_iommu-v0.5"),
+	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,	    "msm_iommu-v0.6"),
+	CLK_LOOKUP("core_clk",		vcodec_axi_a_clk.c, "msm_iommu-v0.7"),
+	CLK_LOOKUP("core_clk",		vcodec_axi_b_clk.c, "msm_iommu-v0.8"),
+	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,    "msm_iommu-v0.9"),
+	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,    "msm_iommu-v0.10"),
 
-	CLK_LOOKUP("core_clk",		vcap_axi_clk.c,		"msm_iommu.11"),
+	CLK_LOOKUP("core_clk",		vcap_axi_clk.c,	    "msm_iommu-v0.11"),
 
 	CLK_LOOKUP("mdp_iommu_clk", mdp_axi_clk.c,	"msm_vidc.0"),
 	CLK_LOOKUP("rot_iommu_clk",	rot_axi_clk.c,	"msm_vidc.0"),
@@ -5864,16 +5865,16 @@
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,		"mdp.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,	"footswitch-8x60.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.0"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.1"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.2"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.3"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.5"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.6"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.7"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.8"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.9"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.0"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.1"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.2"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.3"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.4"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.5"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.6"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.7"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.8"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.9"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"footswitch-8x60.6"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"msm_vidc.0"),
@@ -5910,16 +5911,16 @@
 	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		"msm-dai-q6.3"),
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
-	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	"msm_iommu.0"),
-	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		"msm_iommu.1"),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.2"),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.3"),
-	CLK_LOOKUP("core_clk",		rot_axi_clk.c,		"msm_iommu.4"),
-	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,	"msm_iommu.5"),
-	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,		"msm_iommu.6"),
-	CLK_LOOKUP("core_clk",		vcodec_axi_a_clk.c,	"msm_iommu.7"),
-	CLK_LOOKUP("core_clk",		vcodec_axi_b_clk.c,	"msm_iommu.8"),
-	CLK_LOOKUP("core_clk",		gfx3d_clk.c,		"msm_iommu.9"),
+	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,    "msm_iommu-v0.0"),
+	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,	    "msm_iommu-v0.1"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,	    "msm_iommu-v0.2"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,	    "msm_iommu-v0.3"),
+	CLK_LOOKUP("core_clk",		rot_axi_clk.c,	    "msm_iommu-v0.4"),
+	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,    "msm_iommu-v0.5"),
+	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,	    "msm_iommu-v0.6"),
+	CLK_LOOKUP("core_clk",		vcodec_axi_a_clk.c, "msm_iommu-v0.7"),
+	CLK_LOOKUP("core_clk",		vcodec_axi_b_clk.c, "msm_iommu-v0.8"),
+	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	    "msm_iommu-v0.9"),
 
 	CLK_LOOKUP("mdp_iommu_clk", mdp_axi_clk.c,	"msm_vidc.0"),
 	CLK_LOOKUP("rot_iommu_clk",	rot_axi_clk.c,	"msm_vidc.0"),
@@ -5968,16 +5969,16 @@
 	CLK_LOOKUP("iface_clk",		gfx2d0_p_clk.c,	"footswitch-8x60.0"),
 	CLK_LOOKUP("iface_clk",		gfx2d1_p_clk.c,	"kgsl-2d1.1"),
 	CLK_LOOKUP("iface_clk",		gfx2d1_p_clk.c,	"footswitch-8x60.1"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,		"msm_iommu.10"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,		"msm_iommu.11"),
-	CLK_LOOKUP("core_clk",		gfx2d0_clk.c,		"msm_iommu.10"),
-	CLK_LOOKUP("core_clk",		gfx2d1_clk.c,		"msm_iommu.11"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.10"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.11"),
+	CLK_LOOKUP("core_clk",		gfx2d0_clk.c,	"msm_iommu-v0.10"),
+	CLK_LOOKUP("core_clk",		gfx2d1_clk.c,	"msm_iommu-v0.11"),
 };
 
 static struct clk_lookup msm_clocks_8960ab_only[] __initdata = {
 	CLK_LOOKUP("bus_clk", gfx3d_axi_clk.c, "footswitch-8x60.2"),
-	CLK_LOOKUP("iface_clk",	smmu_p_clk.c,	"msm_iommu.10"),
-	CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, "msm_iommu.10"),
+	CLK_LOOKUP("iface_clk",	smmu_p_clk.c,	"msm_iommu-v0.10"),
+	CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, "msm_iommu-v0.10"),
 	CLK_LOOKUP("div_clk",	tv_src_div_clk.c,	""),
 };
 
@@ -6213,17 +6214,17 @@
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,		"mdp.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,	"footswitch-8x60.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.0"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.1"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.2"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.3"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.5"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.6"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.7"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.8"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.9"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.10"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.0"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.1"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.2"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.3"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.4"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.5"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.6"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.7"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.8"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.9"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.10"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"footswitch-8x60.6"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"msm_vidc.0"),
@@ -6257,16 +6258,16 @@
 	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		"msm-dai-q6.2"),
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
-	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		"msm_iommu.1"),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.2"),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.3"),
-	CLK_LOOKUP("core_clk",		rot_axi_clk.c,		"msm_iommu.4"),
-	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,	"msm_iommu.5"),
-	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,		"msm_iommu.6"),
-	CLK_LOOKUP("core_clk",		vcodec_axi_a_clk.c,	"msm_iommu.7"),
-	CLK_LOOKUP("core_clk",		vcodec_axi_b_clk.c,	"msm_iommu.8"),
-	CLK_LOOKUP("core_clk",		gfx3d_axi_clk_8930.c,	"msm_iommu.9"),
-	CLK_LOOKUP("core_clk",		gfx3d_axi_clk_8930.c,	"msm_iommu.10"),
+	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,	  "msm_iommu-v0.1"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,	  "msm_iommu-v0.2"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,	  "msm_iommu-v0.3"),
+	CLK_LOOKUP("core_clk",		rot_axi_clk.c,	  "msm_iommu-v0.4"),
+	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,  "msm_iommu-v0.5"),
+	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,	  "msm_iommu-v0.6"),
+	CLK_LOOKUP("core_clk",	   vcodec_axi_a_clk.c,    "msm_iommu-v0.7"),
+	CLK_LOOKUP("core_clk",	   vcodec_axi_b_clk.c,    "msm_iommu-v0.8"),
+	CLK_LOOKUP("core_clk",	   gfx3d_axi_clk_8930.c,  "msm_iommu-v0.9"),
+	CLK_LOOKUP("core_clk",	   gfx3d_axi_clk_8930.c,  "msm_iommu-v0.10"),
 
 	CLK_LOOKUP("mdp_iommu_clk", mdp_axi_clk.c,	"msm_vidc.0"),
 	CLK_LOOKUP("rot_iommu_clk",	rot_axi_clk.c,	"msm_vidc.0"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index a48bf94..887f7cc 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -112,6 +112,7 @@
 #define LPASS_LPA_PLL_VOTE_APPS_REG    0x2000
 
 #define GLB_CLK_DIAG_REG               0x001C
+#define L2_CBCR_REG                    0x004C
 
 #define USB30_MASTER_CMD_RCGR          0x03D4
 #define USB30_MOCK_UTMI_CMD_RCGR       0x03E8
@@ -128,28 +129,40 @@
 #define SDCC3_APPS_CMD_RCGR            0x0550
 #define SDCC4_APPS_CMD_RCGR            0x0590
 #define BLSP1_QUP1_SPI_APPS_CMD_RCGR   0x064C
+#define BLSP1_QUP1_I2C_APPS_CMD_RCGR   0x0660
 #define BLSP1_UART1_APPS_CMD_RCGR      0x068C
 #define BLSP1_QUP2_SPI_APPS_CMD_RCGR   0x06CC
+#define BLSP1_QUP2_I2C_APPS_CMD_RCGR   0x06E0
 #define BLSP1_UART2_APPS_CMD_RCGR      0x070C
 #define BLSP1_QUP3_SPI_APPS_CMD_RCGR   0x074C
+#define BLSP1_QUP3_I2C_APPS_CMD_RCGR   0x0760
 #define BLSP1_UART3_APPS_CMD_RCGR      0x078C
 #define BLSP1_QUP4_SPI_APPS_CMD_RCGR   0x07CC
+#define BLSP1_QUP4_I2C_APPS_CMD_RCGR   0x07E0
 #define BLSP1_UART4_APPS_CMD_RCGR      0x080C
 #define BLSP1_QUP5_SPI_APPS_CMD_RCGR   0x084C
+#define BLSP1_QUP5_I2C_APPS_CMD_RCGR   0x0860
 #define BLSP1_UART5_APPS_CMD_RCGR      0x088C
 #define BLSP1_QUP6_SPI_APPS_CMD_RCGR   0x08CC
+#define BLSP1_QUP6_I2C_APPS_CMD_RCGR   0x08E0
 #define BLSP1_UART6_APPS_CMD_RCGR      0x090C
 #define BLSP2_QUP1_SPI_APPS_CMD_RCGR   0x098C
+#define BLSP2_QUP1_I2C_APPS_CMD_RCGR   0x09A0
 #define BLSP2_UART1_APPS_CMD_RCGR      0x09CC
 #define BLSP2_QUP2_SPI_APPS_CMD_RCGR   0x0A0C
+#define BLSP2_QUP2_I2C_APPS_CMD_RCGR   0x0A20
 #define BLSP2_UART2_APPS_CMD_RCGR      0x0A4C
 #define BLSP2_QUP3_SPI_APPS_CMD_RCGR   0x0A8C
+#define BLSP2_QUP3_I2C_APPS_CMD_RCGR   0x0AA0
 #define BLSP2_UART3_APPS_CMD_RCGR      0x0ACC
 #define BLSP2_QUP4_SPI_APPS_CMD_RCGR   0x0B0C
+#define BLSP2_QUP4_I2C_APPS_CMD_RCGR   0x0B20
 #define BLSP2_UART4_APPS_CMD_RCGR      0x0B4C
 #define BLSP2_QUP5_SPI_APPS_CMD_RCGR   0x0B8C
+#define BLSP2_QUP5_I2C_APPS_CMD_RCGR   0x0BA0
 #define BLSP2_UART5_APPS_CMD_RCGR      0x0BCC
 #define BLSP2_QUP6_SPI_APPS_CMD_RCGR   0x0C0C
+#define BLSP2_QUP6_I2C_APPS_CMD_RCGR   0x0C20
 #define BLSP2_UART6_APPS_CMD_RCGR      0x0C4C
 #define PDM2_CMD_RCGR                  0x0CD0
 #define TSIF_REF_CMD_RCGR              0x0D90
@@ -806,6 +819,13 @@
 
 static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, 0);
 
+static DEFINE_CLK_BRANCH_VOTER(cxo_otg_clk, &cxo_clk_src.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_pil_lpass_clk, &cxo_clk_src.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_pil_mss_clk, &cxo_clk_src.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_wlan_clk, &cxo_clk_src.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_pil_pronto_clk, &cxo_clk_src.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_dwc3_clk, &cxo_clk_src.c);
+
 static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
 	F(125000000,  gpll0,   1,   5,  24),
 	F_END
@@ -920,6 +940,95 @@
 	},
 };
 
+static struct clk_freq_tbl ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk[] = {
+	F(50000000,  gpll0,  12,   0,   0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP1_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup1_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup1_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP2_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup2_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup2_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP3_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup3_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup3_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP4_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup4_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup4_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP5_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup5_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup5_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP6_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup6_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp1_qup6_i2c_apps_clk_src.c),
+	},
+};
+
 static struct clk_freq_tbl ftbl_gcc_blsp1_2_uart1_6_apps_clk[] = {
 	F_GCC_GND,
 	F( 3686400,  gpll0,    1,  96,  15625),
@@ -1108,6 +1217,90 @@
 	},
 };
 
+static struct rcg_clk blsp2_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP1_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup1_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp2_qup1_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP2_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup2_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp2_qup2_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP3_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup3_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp2_qup3_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP4_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup4_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp2_qup4_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP5_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup5_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp2_qup5_i2c_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp2_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP2_QUP6_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp2_qup6_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOW, 50000000),
+		CLK_INIT(blsp2_qup6_i2c_apps_clk_src.c),
+	},
+};
+
 static struct rcg_clk blsp2_uart1_apps_clk_src = {
 	.cmd_rcgr_reg = BLSP2_UART1_APPS_CMD_RCGR,
 	.set_rate = set_rate_mnd,
@@ -1521,7 +1714,6 @@
 
 static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
 	.cbcr_reg = BLSP1_QUP1_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1544,7 +1736,6 @@
 
 static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {
 	.cbcr_reg = BLSP1_QUP2_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1567,7 +1758,6 @@
 
 static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {
 	.cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1590,7 +1780,6 @@
 
 static struct branch_clk gcc_blsp1_qup4_i2c_apps_clk = {
 	.cbcr_reg = BLSP1_QUP4_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1613,7 +1802,6 @@
 
 static struct branch_clk gcc_blsp1_qup5_i2c_apps_clk = {
 	.cbcr_reg = BLSP1_QUP5_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1636,7 +1824,6 @@
 
 static struct branch_clk gcc_blsp1_qup6_i2c_apps_clk = {
 	.cbcr_reg = BLSP1_QUP6_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1749,7 +1936,6 @@
 
 static struct branch_clk gcc_blsp2_qup1_i2c_apps_clk = {
 	.cbcr_reg = BLSP2_QUP1_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1772,7 +1958,6 @@
 
 static struct branch_clk gcc_blsp2_qup2_i2c_apps_clk = {
 	.cbcr_reg = BLSP2_QUP2_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1795,7 +1980,6 @@
 
 static struct branch_clk gcc_blsp2_qup3_i2c_apps_clk = {
 	.cbcr_reg = BLSP2_QUP3_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1818,7 +2002,6 @@
 
 static struct branch_clk gcc_blsp2_qup4_i2c_apps_clk = {
 	.cbcr_reg = BLSP2_QUP4_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1841,7 +2024,6 @@
 
 static struct branch_clk gcc_blsp2_qup5_i2c_apps_clk = {
 	.cbcr_reg = BLSP2_QUP5_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -1864,7 +2046,6 @@
 
 static struct branch_clk gcc_blsp2_qup6_i2c_apps_clk = {
 	.cbcr_reg = BLSP2_QUP6_I2C_APPS_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
 		.parent = &cxo_clk_src.c,
@@ -4655,6 +4836,14 @@
 	u32 debug_mux;
 };
 
+enum {
+	M_ACPU0 = 0,
+	M_ACPU1,
+	M_ACPU2,
+	M_ACPU3,
+	M_L2,
+};
+
 struct measure_mux_entry measure_mux[] = {
 	{&gcc_pdm_ahb_clk.c,			GCC_BASE, 0x00d0},
 	{&gcc_blsp2_qup1_i2c_apps_clk.c,	GCC_BASE, 0x00ab},
@@ -4830,11 +5019,11 @@
 	{&audio_core_ixfabric_clk.c,		LPASS_BASE, 0x0059},
 	{&audio_wrapper_br_clk.c,		LPASS_BASE, 0x0022},
 
-	{&l2_m_clk,				APCS_BASE, 0x0081},
-	{&krait0_m_clk,				APCS_BASE, 0x0080},
-	{&krait1_m_clk,				APCS_BASE, 0x0088},
-	{&krait2_m_clk,				APCS_BASE, 0x0090},
-	{&krait3_m_clk,				APCS_BASE, 0x0098},
+	{&krait0_m_clk,				APCS_BASE, M_ACPU0},
+	{&krait1_m_clk,				APCS_BASE, M_ACPU1},
+	{&krait2_m_clk,				APCS_BASE, M_ACPU2},
+	{&krait3_m_clk,				APCS_BASE, M_ACPU3},
+	{&l2_m_clk,				APCS_BASE, M_L2},
 
 	{&dummy_clk,				N_BASES,   0x0000},
 };
@@ -4895,7 +5084,19 @@
 	case APCS_BASE:
 		clk->multiplier = 4;
 		clk_sel = 0x16A;
-		regval = measure_mux[i].debug_mux;
+
+		if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) {
+			if (measure_mux[i].debug_mux == M_L2)
+				regval = BIT(7)|BIT(0);
+			else
+				regval = BIT(7)|(measure_mux[i].debug_mux << 3);
+		} else {
+			if (measure_mux[i].debug_mux == M_L2)
+				regval = BIT(12);
+			else
+				regval = measure_mux[i].debug_mux << 8;
+			writel_relaxed(BIT(0), APCS_REG_BASE(L2_CBCR_REG));
+		}
 		writel_relaxed(regval, APCS_REG_BASE(GLB_CLK_DIAG_REG));
 		break;
 
@@ -5057,14 +5258,30 @@
 	CLK_DUMMY("vsync_clk", "mdp.0", NULL, 0),
 	CLK_DUMMY("iface_clk", "mdp.0", NULL, 0),
 	CLK_DUMMY("bus_clk", "mdp.0", NULL, 0),
+	CLK_DUMMY("iface_clk", NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk", NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk", NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fda44000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk", NULL, "fda44000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk", NULL, "fda44000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fd928000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk", NULL, "fd928000.qcom,iommu", oFF),
+	CLK_DUMMY("core_clk", NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk", NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk", NULL, "fdc84000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk", NULL, "fdc84000.qcom,iommu", oFF),
+	CLK_DUMMY("core_clk", NULL, "fdc84000.qcom,iommu", oFF),
 };
 
 static struct clk_lookup msm_clocks_8974[] = {
-	CLK_LOOKUP("xo",	cxo_clk_src.c,	"msm_otg"),
-	CLK_LOOKUP("xo",	cxo_clk_src.c,	"fe200000.qcom,lpass"),
-	CLK_LOOKUP("xo",	cxo_clk_src.c,	"fc880000.qcom,mss"),
-	CLK_LOOKUP("xo",	cxo_clk_src.c,	"fb000000.qcom,wcnss-wlan"),
-	CLK_LOOKUP("xo",	cxo_clk_src.c,	"fb21b000.qcom,pronto"),
+	CLK_LOOKUP("xo",        cxo_otg_clk.c,                  "msm_otg"),
+	CLK_LOOKUP("xo",  cxo_pil_lpass_clk.c,      "fe200000.qcom,lpass"),
+	CLK_LOOKUP("xo",    cxo_pil_mss_clk.c,        "fc880000.qcom,mss"),
+	CLK_LOOKUP("xo",       cxo_wlan_clk.c, "fb000000.qcom,wcnss-wlan"),
+	CLK_LOOKUP("xo", cxo_pil_pronto_clk.c,     "fb21b000.qcom,pronto"),
+	CLK_LOOKUP("xo",       cxo_dwc3_clk.c,                 "msm_dwc3"),
+
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
 
 	CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
@@ -5711,6 +5928,17 @@
 	writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
 
 	/*
+	 * V2 requires additional votes to allow the LPASS and MMSS
+	 * controllers to use GPLL0.
+	 */
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+		regval = readl_relaxed(
+				GCC_REG_BASE(APCS_CLOCK_BRANCH_ENA_VOTE));
+		writel_relaxed(regval | BIT(26) | BIT(25),
+				GCC_REG_BASE(APCS_CLOCK_BRANCH_ENA_VOTE));
+	}
+
+	/*
 	 * TODO: Confirm that no clocks need to be voted on in this sleep vote
 	 * register.
 	 */
@@ -5834,6 +6062,21 @@
 #define APCS_GCC_CC_PHYS	0xF9011000
 #define APCS_GCC_CC_SIZE	SZ_4K
 
+static struct clk *qup_i2c_clks[][2] __initdata = {
+	{&gcc_blsp1_qup1_i2c_apps_clk.c, &blsp1_qup1_i2c_apps_clk_src.c,},
+	{&gcc_blsp1_qup2_i2c_apps_clk.c, &blsp1_qup2_i2c_apps_clk_src.c,},
+	{&gcc_blsp1_qup3_i2c_apps_clk.c, &blsp1_qup3_i2c_apps_clk_src.c,},
+	{&gcc_blsp1_qup4_i2c_apps_clk.c, &blsp1_qup4_i2c_apps_clk_src.c,},
+	{&gcc_blsp1_qup5_i2c_apps_clk.c, &blsp1_qup5_i2c_apps_clk_src.c,},
+	{&gcc_blsp1_qup6_i2c_apps_clk.c, &blsp1_qup6_i2c_apps_clk_src.c,},
+	{&gcc_blsp2_qup1_i2c_apps_clk.c, &blsp2_qup1_i2c_apps_clk_src.c,},
+	{&gcc_blsp2_qup2_i2c_apps_clk.c, &blsp2_qup2_i2c_apps_clk_src.c,},
+	{&gcc_blsp2_qup3_i2c_apps_clk.c, &blsp2_qup3_i2c_apps_clk_src.c,},
+	{&gcc_blsp2_qup4_i2c_apps_clk.c, &blsp2_qup4_i2c_apps_clk_src.c,},
+	{&gcc_blsp2_qup5_i2c_apps_clk.c, &blsp2_qup5_i2c_apps_clk_src.c,},
+	{&gcc_blsp2_qup6_i2c_apps_clk.c, &blsp2_qup6_i2c_apps_clk_src.c,},
+};
+
 static void __init msm8974_clock_pre_init(void)
 {
 	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
@@ -5873,6 +6116,8 @@
 
 	/* v2 specific changes */
 	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+		int i;
+
 		mmpll3_clk_src.c.rate =  930000000;
 		mmpll1_clk_src.c.rate = 1167000000;
 		mmpll1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 1167000000;
@@ -5888,6 +6133,10 @@
 		vcodec0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
 
 		mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 240000000;
+
+		/* The parent of each of the QUP I2C clocks is an RCG on V2 */
+		for (i = 0; i < ARRAY_SIZE(qup_i2c_clks); i++)
+			qup_i2c_clks[i][0]->parent =  qup_i2c_clks[i][1];
 	}
 }
 
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 439b538..d0b4a32 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-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
@@ -3689,18 +3689,18 @@
 	CLK_LOOKUP("mem_iface_clk",	imem_p_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,		"mdp.0"),
 	CLK_LOOKUP("iface_clk",		mdp_p_clk.c,	"footswitch-8x60.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.0"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.1"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.2"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.3"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.4"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.5"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.6"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.7"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.8"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.9"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.10"),
-	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu.11"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.0"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.1"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.2"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.3"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.4"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.5"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.6"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.7"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.8"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.9"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.10"),
+	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,	"msm_iommu-v0.11"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"footswitch-8x60.6"),
 	CLK_LOOKUP("tv_enc_pclk",	tv_enc_p_clk.c,		NULL),
@@ -3721,18 +3721,18 @@
 	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c,	NULL),
 	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c,	NULL),
 	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		NULL),
-	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	"msm_iommu.0"),
-	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		"msm_iommu.1"),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.2"),
-	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.3"),
-	CLK_LOOKUP("core_clk",		rot_axi_clk.c,		"msm_iommu.4"),
-	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,	"msm_iommu.5"),
-	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,		"msm_iommu.6"),
-	CLK_LOOKUP("core_clk",		vcodec_axi_clk.c,	"msm_iommu.7"),
-	CLK_LOOKUP("core_clk",		vcodec_axi_clk.c,	"msm_iommu.8"),
-	CLK_LOOKUP("core_clk",		gfx3d_clk.c,		"msm_iommu.9"),
-	CLK_LOOKUP("core_clk",		gfx2d0_clk.c,		"msm_iommu.10"),
-	CLK_LOOKUP("core_clk",		gfx2d1_clk.c,		"msm_iommu.11"),
+	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,  "msm_iommu-v0.0"),
+	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,	  "msm_iommu-v0.1"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,	  "msm_iommu-v0.2"),
+	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,	  "msm_iommu-v0.3"),
+	CLK_LOOKUP("core_clk",		rot_axi_clk.c,	  "msm_iommu-v0.4"),
+	CLK_LOOKUP("core_clk",		ijpeg_axi_clk.c,  "msm_iommu-v0.5"),
+	CLK_LOOKUP("core_clk",		vfe_axi_clk.c,	  "msm_iommu-v0.6"),
+	CLK_LOOKUP("core_clk",		vcodec_axi_clk.c, "msm_iommu-v0.7"),
+	CLK_LOOKUP("core_clk",		vcodec_axi_clk.c, "msm_iommu-v0.8"),
+	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	  "msm_iommu-v0.9"),
+	CLK_LOOKUP("core_clk",		gfx2d0_clk.c,	  "msm_iommu-v0.10"),
+	CLK_LOOKUP("core_clk",		gfx2d1_clk.c,	  "msm_iommu-v0.11"),
 
 	CLK_LOOKUP("mdp_iommu_clk", mdp_axi_clk.c,	"msm_vidc.0"),
 	CLK_LOOKUP("rot_iommu_clk",	rot_axi_clk.c,	"msm_vidc.0"),
diff --git a/arch/arm/mach-msm/clock-dss-8960.c b/arch/arm/mach-msm/clock-dss-8960.c
index e6a71d3..c147a33 100644
--- a/arch/arm/mach-msm/clock-dss-8960.c
+++ b/arch/arm/mach-msm/clock-dss-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-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
@@ -334,6 +334,22 @@
 		writel_relaxed(0x3B, HDMI_PHY_PLL_VCOCAL_CFG2);
 	break;
 
+	case 108000000:
+		writel_relaxed(0x08, HDMI_PHY_PLL_REFCLK_CFG);
+		writel_relaxed(0x21, HDMI_PHY_PLL_LOOP_FLT_CFG0);
+		writel_relaxed(0xF9, HDMI_PHY_PLL_LOOP_FLT_CFG1);
+		writel_relaxed(0x1C, HDMI_PHY_PLL_VCOCAL_CFG0);
+		writel_relaxed(0x02, HDMI_PHY_PLL_VCOCAL_CFG1);
+		writel_relaxed(0x3B, HDMI_PHY_PLL_VCOCAL_CFG2);
+		writel_relaxed(0x86, HDMI_PHY_PLL_VCOCAL_CFG4);
+		writel_relaxed(0x00, HDMI_PHY_PLL_VCOCAL_CFG5);
+		writel_relaxed(0x49, HDMI_PHY_PLL_SDM_CFG0);
+		writel_relaxed(0x49, HDMI_PHY_PLL_SDM_CFG1);
+		writel_relaxed(0x00, HDMI_PHY_PLL_SDM_CFG2);
+		writel_relaxed(0x00, HDMI_PHY_PLL_SDM_CFG3);
+		writel_relaxed(0x00, HDMI_PHY_PLL_SDM_CFG4);
+	break;
+
 	case 148500000:
 		/* 1080p60/1080p50 case */
 		writel_relaxed(0x2, HDMI_PHY_PLL_REFCLK_CFG);
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index c3145ef..51d895a 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -39,6 +39,9 @@
 	struct clk_voter *clkh, *v = to_clk_voter(clk);
 	unsigned long cur_rate, new_rate, other_rate = 0;
 
+	if (v->is_branch)
+		return 0;
+
 	mutex_lock(&voter_clk_lock);
 
 	if (v->enabled) {
@@ -77,6 +80,9 @@
 	struct clk *parent;
 	struct clk_voter *v = to_clk_voter(clk);
 
+	if (v->is_branch)
+		return 0;
+
 	mutex_lock(&voter_clk_lock);
 	parent = clk->parent;
 
@@ -103,6 +109,9 @@
 	struct clk *parent;
 	struct clk_voter *v = to_clk_voter(clk);
 
+	if (v->is_branch)
+		return;
+
 	mutex_lock(&voter_clk_lock);
 	parent = clk->parent;
 
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
index c743959..6d58b3c 100644
--- a/arch/arm/mach-msm/clock-voter.h
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -20,6 +20,7 @@
 extern struct clk_ops clk_ops_voter;
 
 struct clk_voter {
+	int is_branch;
 	bool enabled;
 	struct clk c;
 };
@@ -29,8 +30,9 @@
 	return container_of(clk, struct clk_voter, c);
 }
 
-#define DEFINE_CLK_VOTER(clk_name, _parent, _default_rate) \
+#define __DEFINE_CLK_VOTER(clk_name, _parent, _default_rate, _is_branch) \
 	struct clk_voter clk_name = { \
+		.is_branch = (_is_branch), \
 		.c = { \
 			.parent = _parent, \
 			.dbg_name = #clk_name, \
@@ -40,4 +42,10 @@
 		}, \
 	}
 
+#define DEFINE_CLK_VOTER(clk_name, _parent, _default_rate) \
+	 __DEFINE_CLK_VOTER(clk_name, _parent, _default_rate, 0)
+
+#define DEFINE_CLK_BRANCH_VOTER(clk_name, _parent) \
+	 __DEFINE_CLK_VOTER(clk_name, _parent, 1000, 1)
+
 #endif
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 002ee96..9ca1965 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -51,6 +51,8 @@
 extern struct clock_init_data msm8974_rumi_clock_init_data;
 extern struct clock_init_data msm8610_clock_init_data;
 extern struct clock_init_data msm8610_rumi_clock_init_data;
+extern struct clock_init_data msm8226_clock_init_data;
+extern struct clock_init_data msm8226_rumi_clock_init_data;
 
 int msm_clock_init(struct clock_init_data *data);
 int find_vdd_level(struct clk *clk, unsigned long rate);
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index a9d4eaa..46af77d 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -223,11 +223,12 @@
 	if (table == NULL)
 		return -ENODEV;
 	/*
-	 * In 8625 both cpu core's frequency can not
+	 * In 8625, 8610, and 8226 both cpu core's frequency can not
 	 * be changed independently. Each cpu is bound to
 	 * same frequency. Hence set the cpumask to all cpu.
 	 */
-	if (cpu_is_msm8625() || cpu_is_msm8625q())
+	if (cpu_is_msm8625() || cpu_is_msm8625q() || cpu_is_msm8226()
+		|| cpu_is_msm8610())
 		cpumask_setall(policy->cpus);
 
 	if (cpufreq_frequency_table_cpuinfo(policy, table)) {
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index 056f19e..1e3f8a0 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -76,10 +76,7 @@
 	enum msm_pm_sleep_mode pm_mode;
 	struct cpuidle_state_usage *st_usage = NULL;
 
-#ifdef CONFIG_CPU_PM
 	cpu_pm_enter();
-#endif
-
 	pm_mode = msm_pm_idle_enter(dev, drv, index);
 	for (i = 0; i < dev->state_count; i++) {
 		st_usage = &dev->states_usage[i];
@@ -90,10 +87,7 @@
 		}
 	}
 
-#ifdef CONFIG_CPU_PM
 	cpu_pm_exit();
-#endif
-
 	local_irq_enable();
 
 	return ret;
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 446f3f2..c3748fa 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1067,6 +1067,36 @@
 	},
 };
 
+int64_t vidc_v4l2_ns_iommu_mapping[] = {-1, -1};
+int64_t vidc_v4l2_cp_iommu_mapping[] = {-1, -1};
+int64_t *vidc_v4l2_iommu_mappings[] = {
+	[MSM_VIDC_V4L2_IOMMU_MAP_NS] = vidc_v4l2_ns_iommu_mapping,
+	[MSM_VIDC_V4L2_IOMMU_MAP_CP] = vidc_v4l2_cp_iommu_mapping,
+};
+
+int64_t vidc_v4l2_load_1[] = {-1, -1};
+int64_t vidc_v4l2_load_2[] = {-1, -1};
+int64_t *vidc_v4l2_load_table[] = {
+	vidc_v4l2_load_1,
+	vidc_v4l2_load_2,
+};
+
+static struct msm_vidc_v4l2_platform_data vidc_v4l2_plaform_data = {
+	.iommu_table = vidc_v4l2_iommu_mappings,
+	.num_iommu_table = 2,
+	.load_table = vidc_v4l2_load_table,
+	.num_load_table = 2,
+};
+
+struct platform_device msm_device_vidc_v4l2 = {
+	.name = "msm_vidc_v4l2",
+	.id = 0,
+	.num_resources = 0,
+	.dev = {
+		.platform_data = &vidc_v4l2_plaform_data,
+	},
+};
+
 struct msm_vidc_platform_data vidc_platform_data = {
 #ifdef CONFIG_MSM_BUS_SCALING
 	.vidc_bus_client_pdata = &vidc_bus_client_data,
@@ -4564,7 +4594,8 @@
 };
 
 struct platform_device *msm8960_vidc_device[] __initdata = {
-	&msm_device_vidc
+	&msm_device_vidc,
+	&msm_device_vidc_v4l2,
 };
 
 void __init msm8960_add_vidc_device(void)
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 983b13e..b91e7fe 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -387,7 +387,7 @@
 };
 
 static struct platform_device msm_device_iommu_jpegd = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 0,
 	.dev = {
 		.platform_data = &jpegd_iommu,
@@ -397,7 +397,7 @@
 };
 
 static struct platform_device msm_device_iommu_vpe = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 1,
 	.dev = {
 		.platform_data = &vpe_iommu,
@@ -407,7 +407,7 @@
 };
 
 static struct platform_device msm_device_iommu_mdp0 = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 2,
 	.dev = {
 		.platform_data = &mdp0_iommu,
@@ -417,7 +417,7 @@
 };
 
 static struct platform_device msm_device_iommu_mdp1 = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 3,
 	.dev = {
 		.platform_data = &mdp1_iommu,
@@ -427,7 +427,7 @@
 };
 
 static struct platform_device msm_device_iommu_rot = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 4,
 	.dev = {
 		.platform_data = &rot_iommu,
@@ -437,7 +437,7 @@
 };
 
 static struct platform_device msm_device_iommu_ijpeg = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 5,
 	.dev = {
 		.platform_data = &ijpeg_iommu,
@@ -447,7 +447,7 @@
 };
 
 static struct platform_device msm_device_iommu_vfe = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 6,
 	.dev = {
 		.platform_data = &vfe_iommu,
@@ -457,7 +457,7 @@
 };
 
 static struct platform_device msm_device_iommu_vcodec_a = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 7,
 	.dev = {
 		.platform_data = &vcodec_a_iommu,
@@ -467,7 +467,7 @@
 };
 
 static struct platform_device msm_device_iommu_vcodec_b = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 8,
 	.dev = {
 		.platform_data = &vcodec_b_iommu,
@@ -477,7 +477,7 @@
 };
 
 static struct platform_device msm_device_iommu_gfx3d = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 9,
 	.dev = {
 		.platform_data = &gfx3d_iommu,
@@ -487,7 +487,7 @@
 };
 
 static struct platform_device msm_device_iommu_gfx3d1 = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 10,
 	.dev = {
 		.platform_data = &gfx3d1_iommu,
@@ -497,7 +497,7 @@
 };
 
 static struct platform_device msm_device_iommu_gfx2d0 = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 10,
 	.dev = {
 		.platform_data = &gfx2d0_iommu,
@@ -507,7 +507,7 @@
 };
 
 static struct platform_device msm_device_iommu_gfx2d1 = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 11,
 	.dev = {
 		.platform_data = &gfx2d1_iommu,
@@ -517,7 +517,7 @@
 };
 
 static struct platform_device msm_device_iommu_vcap = {
-	.name = "msm_iommu",
+	.name = "msm_iommu-v0",
 	.id = 11,
 	.dev = {
 		.platform_data = &vcap_iommu,
@@ -975,8 +975,8 @@
 static int __init iommu_init(void)
 {
 	int ret;
-	if (!msm_soc_version_supports_iommu_v1()) {
-		pr_err("IOMMU v1 is not supported on this SoC version.\n");
+	if (!msm_soc_version_supports_iommu_v0()) {
+		pr_err("IOMMU v0 is not supported on this SoC version.\n");
 		return -ENODEV;
 	}
 
diff --git a/arch/arm/mach-msm/event_timer.c b/arch/arm/mach-msm/event_timer.c
index 9f46f68..df79e42 100644
--- a/arch/arm/mach-msm/event_timer.c
+++ b/arch/arm/mach-msm/event_timer.c
@@ -37,9 +37,9 @@
 	void *data;
 };
 
-
 static DEFINE_TIME_HEAD(timer_head);
 static DEFINE_SPINLOCK(event_timer_lock);
+static DEFINE_SPINLOCK(event_setup_lock);
 static struct hrtimer event_hrtimer;
 static enum hrtimer_restart event_hrtimer_cb(struct hrtimer *hrtimer);
 
@@ -73,6 +73,9 @@
 	event_info->data = data;
 	/* Init rb node and hr timer */
 	timerqueue_init(&event_info->node);
+	pr_debug("%s: New Event Added. Event 0x%x.",
+	__func__,
+	(unsigned int)event_info);
 
 	return event_info;
 }
@@ -140,10 +143,6 @@
 
 	event_hrtimer.function = event_hrtimer_cb;
 	hrtimer_start(&event_hrtimer, expires, HRTIMER_MODE_ABS);
-
-	if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
-		pr_info("%s: Setting timer for %lu", __func__,
-			(unsigned long)ktime_to_ns(expires));
 }
 
 /**
@@ -155,7 +154,9 @@
 {
 	struct event_timer_info *event;
 	struct timerqueue_node *next;
+	unsigned long flags;
 
+	spin_lock_irqsave(&event_timer_lock, flags);
 	next = timerqueue_getnext(&timer_head);
 
 	while (next && (ktime_to_ns(next->expires)
@@ -168,7 +169,8 @@
 			goto hrtimer_cb_exit;
 
 		if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
-			pr_info("%s: Deleting event @ %lu", __func__,
+			pr_info("%s: Deleting event 0x%x @ %lu", __func__,
+			(unsigned int)event,
 			(unsigned long)ktime_to_ns(next->expires));
 
 		timerqueue_del(&timer_head, &event->node);
@@ -181,6 +183,7 @@
 	if (next)
 		create_hrtimer(next->expires);
 
+	spin_unlock_irqrestore(&event_timer_lock, flags);
 hrtimer_cb_exit:
 	return HRTIMER_NORESTART;
 }
@@ -201,7 +204,10 @@
 
 	next = timerqueue_getnext(&timer_head);
 	timerqueue_add(&timer_head, &event->node);
-	spin_unlock_irqrestore(&event_timer_lock, flags);
+	if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
+		pr_info("%s: Adding Event 0x%x for %lu", __func__,
+		(unsigned int)event,
+		(unsigned long)ktime_to_ns(event->node.expires));
 
 	if (!next ||
 		(next && (ktime_to_ns(event->node.expires) <
@@ -211,6 +217,7 @@
 			(unsigned long)ktime_to_ns(event->node.expires));
 		create_hrtimer(event->node.expires);
 	}
+	spin_unlock_irqrestore(&event_timer_lock, flags);
 }
 
 /**
@@ -239,9 +246,11 @@
 		pr_info("%s: Adding event timer @ %lu", __func__,
 				(unsigned long)ktime_to_us(event_time));
 
+	spin_lock(&event_setup_lock);
 	event->node.expires = event_time;
 	/* Start hr timer and add event to rb tree */
 	setup_event_hrtimer(event);
+	spin_unlock(&event_setup_lock);
 }
 
 
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 56c78c6..327212e 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -545,6 +545,30 @@
 	unsigned long fw_addr;
 };
 
+enum msm_vidc_v4l2_iommu_map {
+	MSM_VIDC_V4L2_IOMMU_MAP_NS = 0,
+	MSM_VIDC_V4L2_IOMMU_MAP_CP,
+	MSM_VIDC_V4L2_IOMMU_MAP_MAX,
+};
+
+struct msm_vidc_v4l2_platform_data {
+	/*
+	 * Should be a <num_iommu_table x 2> array where
+	 * iommu_table[n][0] is the start address and
+	 * iommu_table[n][1] is the size.
+	 */
+	int64_t **iommu_table;
+	int num_iommu_table;
+
+	/*
+	 * Should be a <num_load_table x 2> array where
+	 * load_table[n][0] is the load and load_table[n][1]
+	 * is the desired clock rate.
+	 */
+	int64_t **load_table;
+	int num_load_table;
+};
+
 struct vcap_platform_data {
 	unsigned *gpios;
 	int num_gpios;
diff --git a/arch/arm/mach-msm/include/mach/camera2.h b/arch/arm/mach-msm/include/mach/camera2.h
index e624131..b518e56 100644
--- a/arch/arm/mach-msm/include/mach/camera2.h
+++ b/arch/arm/mach-msm/include/mach/camera2.h
@@ -17,9 +17,9 @@
 #include <media/msm_cam_sensor.h>
 #include <mach/board.h>
 
-enum msm_sensor_device_type_t {
-	MSM_SENSOR_I2C_DEVICE,
-	MSM_SENSOR_PLATFORM_DEVICE,
+enum msm_camera_device_type_t {
+	MSM_CAMERA_I2C_DEVICE,
+	MSM_CAMERA_PLATFORM_DEVICE,
 };
 
 enum msm_bus_perf_setting {
@@ -36,6 +36,11 @@
 	S_EXIT
 };
 
+enum cci_i2c_master_t {
+	MASTER_0,
+	MASTER_1,
+};
+
 struct msm_camera_slave_info {
 	uint16_t sensor_slave_addr;
 	uint16_t sensor_id_reg_addr;
@@ -88,4 +93,11 @@
 	int16_t mask;
 };
 
+struct msm_camera_i2c_conf_array {
+	struct msm_camera_i2c_reg_conf *conf;
+	uint16_t size;
+	uint16_t delay;
+	enum msm_camera_i2c_data_type data_type;
+};
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/diag_bridge.h b/arch/arm/mach-msm/include/mach/diag_bridge.h
index 5647256..d67d664 100644
--- a/arch/arm/mach-msm/include/mach/diag_bridge.h
+++ b/arch/arm/mach-msm/include/mach/diag_bridge.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011, 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -23,32 +23,31 @@
 	void (*resume)(void *ctxt);
 };
 
-#if defined(CONFIG_USB_QCOM_DIAG_BRIDGE) \
-	|| defined(CONFIG_USB_QCOM_DIAG_BRIDGE_MODULE)
+#if IS_ENABLED(CONFIG_USB_QCOM_DIAG_BRIDGE)
 
-extern int diag_bridge_read(char *data, int size);
-extern int diag_bridge_write(char *data, int size);
-extern int diag_bridge_open(struct diag_bridge_ops *ops);
-extern void diag_bridge_close(void);
+extern int diag_bridge_read(int id, char *data, int size);
+extern int diag_bridge_write(int id, char *data, int size);
+extern int diag_bridge_open(int id, struct diag_bridge_ops *ops);
+extern void diag_bridge_close(int id);
 
 #else
 
-static int __maybe_unused diag_bridge_read(char *data, int size)
+static int __maybe_unused diag_bridge_read(int id, char *data, int size)
 {
 	return -ENODEV;
 }
 
-static int __maybe_unused diag_bridge_write(char *data, int size)
+static int __maybe_unused diag_bridge_write(int id, char *data, int size)
 {
 	return -ENODEV;
 }
 
-static int __maybe_unused diag_bridge_open(struct diag_bridge_ops *ops)
+static int __maybe_unused diag_bridge_open(int id, struct diag_bridge_ops *ops)
 {
 	return -ENODEV;
 }
 
-static void __maybe_unused diag_bridge_close(void) { }
+static void __maybe_unused diag_bridge_close(int id) { }
 
 #endif
 
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index bbf3153..c6e93de 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -95,6 +95,7 @@
  * @dev:	Struct device this hardware instance is tied to
  * @list:	List head to link all iommus together
  * @clk_reg_virt: Optional clock register virtual address.
+ * @halt_enabled: Set to 1 if IOMMU halt is supported in the IOMMU, 0 otherwise.
  *
  * A msm_iommu_drvdata holds the global driver data about a single piece
  * of an IOMMU hardware instance.
@@ -115,12 +116,15 @@
 	struct device *dev;
 	struct list_head list;
 	void __iomem *clk_reg_virt;
+	int halt_enabled;
 };
 
 void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
 void msm_iommu_remove_drv(struct msm_iommu_drvdata *drv);
 void program_iommu_bfb_settings(void __iomem *base,
 			const struct msm_iommu_bfb_settings *bfb_settings);
+void iommu_halt(const struct msm_iommu_drvdata *iommu_drvdata);
+void iommu_resume(const struct msm_iommu_drvdata *iommu_drvdata);
 
 /**
  * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
@@ -235,18 +239,18 @@
  */
 int msm_iommu_sec_program_iommu(int sec_id);
 
-static inline int msm_soc_version_supports_iommu_v1(void)
+static inline int msm_soc_version_supports_iommu_v0(void)
 {
 #ifdef CONFIG_OF
 	struct device_node *node;
 
-	node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v2");
+	node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v1");
 	if (node) {
 		of_node_put(node);
 		return 0;
 	}
 
-	node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v1");
+	node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v0");
 	if (node) {
 		of_node_put(node);
 		return 1;
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 07f82ec..a104a42 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -94,6 +94,7 @@
 
 extern int msm_iommu_map_extra(struct iommu_domain *domain,
 						unsigned long start_iova,
+						unsigned long phys_addr,
 						unsigned long size,
 						unsigned long page_size,
 						int cached);
@@ -147,6 +148,7 @@
 
 static inline int msm_iommu_map_extra(struct iommu_domain *domain,
 						unsigned long start_iova,
+						unsigned long phys_addr,
 						unsigned long size,
 						unsigned long page_size,
 						int cached)
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-v0.h
similarity index 99%
rename from arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
rename to arch/arm/mach-msm/include/mach/iommu_hw-v0.h
index 31b2b4f..198f72f 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v0.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h b/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
similarity index 98%
rename from arch/arm/mach-msm/include/mach/iommu_hw-v2.h
rename to arch/arm/mach-msm/include/mach/iommu_hw-v1.h
index cf9e973..4f08187 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -144,6 +144,10 @@
 #define GET_CBFRSYNRA_N(b, N)    GET_GLOBAL_REG_N(CBFRSYNRA, N, (b))
 
 /* Implementation defined register setters/getters */
+#define SET_MICRO_MMU_CTRL_HALT_REQ(b, v) \
+				SET_GLOBAL_FIELD(b, MICRO_MMU_CTRL, HALT_REQ, v)
+#define GET_MICRO_MMU_CTRL_IDLE(b) \
+				GET_GLOBAL_FIELD(b, MICRO_MMU_CTRL, IDLE)
 #define SET_PREDICTIONDIS0(b, v) SET_GLOBAL_REG(PREDICTIONDIS0, (b), (v))
 #define SET_PREDICTIONDIS1(b, v) SET_GLOBAL_REG(PREDICTIONDIS1, (b), (v))
 #define SET_S1L1BFBLP0(b, v)     SET_GLOBAL_REG(S1L1BFBLP0, (b), (v))
@@ -955,6 +959,7 @@
 #define CBFRSYNRA	(0x1400)
 
 /* Implementation defined Register Space */
+#define MICRO_MMU_CTRL	(0x2000)
 #define PREDICTIONDIS0	(0x204C)
 #define PREDICTIONDIS1	(0x2050)
 #define S1L1BFBLP0	(0x215C)
@@ -1571,6 +1576,10 @@
 /* Context Bank Fault Restricted Syndrome Register A: CBFRSYNRA */
 #define CBFRSYNRA_SID_MASK      0x7FFF
 
+/* Implementation defined register space masks */
+#define MICRO_MMU_CTRL_HALT_REQ_MASK          0x01
+#define MICRO_MMU_CTRL_IDLE_MASK              0x01
+
 /* Stage 1 Context Bank Format Masks */
 /* Auxiliary Control Register: CB_ACTLR */
 #define CB_ACTLR_REQPRIORITY_MASK    0x3
@@ -1929,6 +1938,10 @@
 /* Context Bank Fault Restricted Syndrome Register A: CBFRSYNRA */
 #define CBFRSYNRA_SID_SHIFT        0
 
+/* Implementation defined register space shift */
+#define MICRO_MMU_CTRL_HALT_REQ_SHIFT         0x02
+#define MICRO_MMU_CTRL_IDLE_SHIFT             0x03
+
 /* Stage 1 Context Bank Format Shifts */
 /* Auxiliary Control Register: CB_ACTLR */
 #define CB_ACTLR_REQPRIORITY_SHIFT     0
diff --git a/arch/arm/mach-msm/include/mach/iommu_perfmon.h b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
index b44523f..59f58c1 100644
--- a/arch/arm/mach-msm/include/mach/iommu_perfmon.h
+++ b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
@@ -16,7 +16,6 @@
 #ifndef MSM_IOMMU_PERFMON_H
 #define MSM_IOMMU_PERFMON_H
 
-
 /**
  * struct iommu_access_ops - Callbacks for accessing IOMMU
  * @iommu_power_on:     Turn on clocks/power to unit
@@ -92,7 +91,9 @@
  * @iommu_list:           iommu_list head
  * @cnt_grp:              list of counter groups
  * @num_groups:           number of counter groups
- * @event_cls_supp_value: event classes supported for this PMU
+ * @num_counters:         number of counters per group
+ * @event_cls_supported:  an array of event classes supported for this PMU
+ * @nevent_cls_supported: number of event classes supported.
  * @enabled:              Indicates whether perf. mon is enabled or not
  * @iommu_attached        Indicates whether iommu is attached or not.
  * @lock:                 mutex used to synchronize access to shared data
@@ -102,8 +103,10 @@
 	struct iommu_info iommu;
 	struct list_head iommu_list;
 	struct iommu_pmon_cnt_group *cnt_grp;
-	unsigned int num_groups;
-	unsigned int event_cls_supp_value;
+	u32 num_groups;
+	u32 num_counters;
+	u32 *event_cls_supported;
+	u32 nevent_cls_supported;
 	unsigned int enabled;
 	unsigned int iommu_attach_count;
 	struct mutex lock;
@@ -114,9 +117,9 @@
 #ifdef CONFIG_MSM_IOMMU_PMON
 /**
  * Allocate memory for performance monitor structure. Must
- * be called befre iommu_pm_iommu_register
+ * be called before iommu_pm_iommu_register
  */
-struct iommu_info *msm_iommu_pm_alloc(struct device *iommu_dev);
+struct iommu_pmon *msm_iommu_pm_alloc(struct device *iommu_dev);
 
 /**
  * Free memory previously allocated with iommu_pm_alloc
@@ -126,7 +129,7 @@
 /**
  * Register iommu with the performance monitor module.
  */
-int msm_iommu_pm_iommu_register(struct iommu_info *info);
+int msm_iommu_pm_iommu_register(struct iommu_pmon *info);
 
 /**
  * Unregister iommu with the performance monitor module.
@@ -147,7 +150,7 @@
   */
 void msm_iommu_detached(struct device *dev);
 #else
-static inline struct iommu_info *msm_iommu_pm_alloc(struct device *iommu_dev)
+static inline struct iommu_pmon *msm_iommu_pm_alloc(struct device *iommu_dev)
 {
 	return NULL;
 }
@@ -157,7 +160,7 @@
 	return;
 }
 
-static inline int msm_iommu_pm_iommu_register(struct iommu_info *info)
+static inline int msm_iommu_pm_iommu_register(struct iommu_pmon *info)
 {
 	return -EIO;
 }
diff --git a/arch/arm/mach-msm/include/mach/msm_bus.h b/arch/arm/mach-msm/include/mach/msm_bus.h
index 41b46a9..049cf02 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus.h
@@ -78,24 +78,11 @@
 uint32_t msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata);
 int msm_bus_scale_client_update_request(uint32_t cl, unsigned int index);
 void msm_bus_scale_unregister_client(uint32_t cl);
-struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev);
-void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata);
 /* AXI Port configuration APIs */
 int msm_bus_axi_porthalt(int master_port);
 int msm_bus_axi_portunhalt(int master_port);
 
 #else
-static inline struct msm_bus_scale_pdata
-*msm_bus_cl_get_pdata(struct platform_device *pdev)
-{
-	return NULL;
-}
-
-static inline void
-msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata)
-{
-}
-
 static inline uint32_t
 msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata)
 {
@@ -124,4 +111,18 @@
 }
 #endif
 
+#if defined(CONFIG_OF) && defined(CONFIG_MSM_BUS_SCALING)
+struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev);
+void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata);
+#else
+static inline struct msm_bus_scale_pdata
+*msm_bus_cl_get_pdata(struct platform_device *pdev)
+{
+	return NULL;
+}
+
+static inline void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata)
+{
+}
+#endif
 #endif /*_ARCH_ARM_MACH_MSM_BUS_H*/
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h
index e7f9cec..390160d 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,7 +24,7 @@
 
 struct msm_bus_fabric_registration {
 	unsigned int id;
-	char *name;
+	const char *name;
 	struct msm_bus_node_info *info;
 	unsigned int len;
 	int ahb;
@@ -33,9 +33,9 @@
 	unsigned int offset;
 	unsigned int haltid;
 	unsigned int rpm_enabled;
-	const unsigned int nmasters;
-	const unsigned int nslaves;
-	const unsigned int ntieredslaves;
+	unsigned int nmasters;
+	unsigned int nslaves;
+	unsigned int ntieredslaves;
 	bool il_flag;
 	const struct msm_bus_board_algorithm *board_algo;
 	int hw_sel;
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 6213334..4f475fe 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -67,7 +67,11 @@
 #define MSM_SAW_L2_BASE		IOMEM(0xFA007000)	/*  4K	*/
 #define MSM_SAW0_BASE		IOMEM(0xFA008000)	/*  4K	*/
 #define MSM_SAW1_BASE		IOMEM(0xFA009000)	/*  4K	*/
+
+#ifndef CONFIG_ARCH_MSM9625
 #define MSM_IMEM_BASE		IOMEM(0xFA00A000)	/*  4K	*/
+#endif
+
 #define MSM_ACC0_BASE		IOMEM(0xFA00B000)	/*  4K	*/
 #define MSM_ACC1_BASE		IOMEM(0xFA00C000)	/*  4K	*/
 #define MSM_ACC2_BASE		IOMEM(0xFA00D000)	/*  4K	*/
@@ -98,6 +102,13 @@
 #define MSM_MDC_BASE		IOMEM(0xFA400000)	/*  1M */
 #define MSM_AD5_BASE		IOMEM(0xFA900000)	/*  13M (D00000)
 							  0xFB600000 */
+/* MSM9625 has unaligned imem so we need to map excess 2K virtually
+ * to get the correct mapping. This should not be done for any
+ * other chipset under normal circumstances.
+ */
+#ifdef CONFIG_ARCH_MSM9625
+#define MSM_IMEM_BASE		IOMEM(0xFB601800)	/* 6K -> 8K */
+#endif
 
 #define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
 #define MSM8625_CPU_PHYS		0x0FE00000
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
index 4c06af4..59908e6 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
@@ -82,7 +82,8 @@
 #define APR_SVC_ADSP_CVS	0x0A
 #define APR_SVC_ADSP_CVP	0x0B
 #define APR_SVC_USM		0x0C
-#define APR_SVC_MAX		0x0D
+#define APR_SVC_VIDC		0x16
+#define APR_SVC_MAX		0x17
 
 /* Modem Service IDs */
 #define APR_SVC_MVS		0x3
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
new file mode 100644
index 0000000..3a13af8
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -0,0 +1,130 @@
+/*
+ * 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 __QSEECOMI_H_
+#define __QSEECOMI_H_
+
+#include <linux/qseecom.h>
+
+enum qseecom_command_scm_resp_type {
+	QSEOS_APP_ID = 0xEE01,
+	QSEOS_LISTENER_ID
+};
+
+enum qseecom_qceos_cmd_id {
+	QSEOS_APP_START_COMMAND      = 0x01,
+	QSEOS_APP_SHUTDOWN_COMMAND,
+	QSEOS_APP_LOOKUP_COMMAND,
+	QSEOS_REGISTER_LISTENER,
+	QSEOS_DEREGISTER_LISTENER,
+	QSEOS_CLIENT_SEND_DATA_COMMAND,
+	QSEOS_LISTENER_DATA_RSP_COMMAND,
+	QSEOS_LOAD_EXTERNAL_ELF_COMMAND,
+	QSEOS_UNLOAD_EXTERNAL_ELF_COMMAND,
+	QSEOS_GET_APP_STATE_COMMAND,
+	QSEOS_LOAD_SERV_IMAGE_COMMAND,
+	QSEOS_UNLOAD_SERV_IMAGE_COMMAND,
+	QSEOS_APP_REGION_NOTIFICATION,
+	QSEOS_REGISTER_LOG_BUF_COMMAND,
+	QSEOS_CMD_MAX     = 0xEFFFFFFF
+};
+
+enum qseecom_qceos_cmd_status {
+	QSEOS_RESULT_SUCCESS = 0,
+	QSEOS_RESULT_INCOMPLETE,
+	QSEOS_RESULT_FAILURE  = 0xFFFFFFFF
+};
+
+__packed  struct qsee_apps_region_info_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t addr;
+	uint32_t size;
+};
+
+__packed struct qseecom_check_app_ireq {
+	uint32_t qsee_cmd_id;
+	char     app_name[MAX_APP_NAME_SIZE];
+};
+
+__packed struct qseecom_load_app_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t mdt_len;		/* Length of the mdt file */
+	uint32_t img_len;		/* Length of .bxx and .mdt files */
+	uint32_t phy_addr;		/* phy addr of the start of image */
+	char     app_name[MAX_APP_NAME_SIZE];	/* application name*/
+};
+
+__packed struct qseecom_unload_app_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t  app_id;
+};
+
+__packed struct qseecom_load_lib_image_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t mdt_len;
+	uint32_t img_len;
+	uint32_t phy_addr;
+};
+
+__packed struct qseecom_unload_lib_image_ireq {
+	uint32_t qsee_cmd_id;
+};
+
+__packed struct qseecom_register_listener_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t listener_id;
+	void *sb_ptr;
+	uint32_t sb_len;
+};
+
+__packed struct qseecom_unregister_listener_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t  listener_id;
+};
+
+__packed struct qseecom_client_send_data_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t app_id;
+	void *req_ptr;
+	uint32_t req_len;
+	void *rsp_ptr;   /* First 4 bytes should always be the return status */
+	uint32_t rsp_len;
+};
+
+__packed struct qseecom_reg_log_buf_ireq {
+	uint32_t qsee_cmd_id;
+	unsigned long phy_addr;
+	uint32_t len;
+};
+
+/* send_data resp */
+__packed struct qseecom_client_listener_data_irsp {
+	uint32_t qsee_cmd_id;
+	uint32_t listener_id;
+	uint32_t status;
+};
+
+/*
+ * struct qseecom_command_scm_resp - qseecom response buffer
+ * @cmd_status: value from enum tz_sched_cmd_status
+ * @sb_in_rsp_addr: points to physical location of response
+ *                buffer
+ * @sb_in_rsp_len: length of command response
+ */
+__packed struct qseecom_command_scm_resp {
+	uint32_t result;
+	enum qseecom_command_scm_resp_type resp_type;
+	unsigned int data;
+};
+
+#endif /* __QSEECOMI_H_ */
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 5b4f00e..d9b0336 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -40,6 +40,8 @@
 	of_machine_is_compatible("qcom,msm8974-sim")
 #define machine_is_msm8974_rumi()	\
 	of_machine_is_compatible("qcom,msm8974-rumi")
+#define machine_is_msm8974_fluid()	\
+	of_machine_is_compatible("qcom,msm8974-fluid")
 #define early_machine_is_msm9625()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm9625")
 #define machine_is_msm9625()		\
@@ -69,6 +71,7 @@
 #define machine_is_msm8974()		0
 #define machine_is_msm8974_sim()	0
 #define machine_is_msm8974_rumi()	0
+#define machine_is_msm8974_fluid()	0
 #define early_machine_is_msm9625()	0
 #define machine_is_msm9625()		0
 #define early_machine_is_mpq8092()	0
diff --git a/arch/arm/mach-msm/include/mach/subsystem_notif.h b/arch/arm/mach-msm/include/mach/subsystem_notif.h
index 3d8ae55..5865eff 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_notif.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_notif.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011, 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,6 +24,7 @@
 	SUBSYS_AFTER_SHUTDOWN,
 	SUBSYS_BEFORE_POWERUP,
 	SUBSYS_AFTER_POWERUP,
+	SUBSYS_RAMDUMP_NOTIFICATION,
 	SUBSYS_NOTIF_TYPE_COUNT
 };
 
@@ -50,7 +51,8 @@
  */
 void *subsys_notif_add_subsys(const char *);
 int subsys_notif_queue_notification(void *subsys_handle,
-					enum subsys_notif_type notif_type);
+					enum subsys_notif_type notif_type,
+					void *data);
 #else
 
 static inline void *subsys_notif_register_notifier(
@@ -71,7 +73,8 @@
 }
 
 static inline int subsys_notif_queue_notification(void *subsys_handle,
-					enum subsys_notif_type notif_type)
+					enum subsys_notif_type notif_type,
+					void *data)
 {
 	return 0;
 }
diff --git a/arch/arm/mach-msm/include/mach/usbdiag.h b/arch/arm/mach-msm/include/mach/usbdiag.h
index d9320c3..15f4783 100644
--- a/arch/arm/mach-msm/include/mach/usbdiag.h
+++ b/arch/arm/mach-msm/include/mach/usbdiag.h
@@ -26,6 +26,7 @@
 #define DIAG_LEGACY		"diag"
 #define DIAG_MDM		"diag_mdm"
 #define DIAG_QSC		"diag_qsc"
+#define DIAG_MDM2		"diag_mdm2"
 
 #define USB_DIAG_CONNECT	0
 #define USB_DIAG_DISCONNECT	1
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index dc67403..02272bc 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -29,9 +29,6 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 
-/* dummy 64K for overmapping */
-char iommu_dummy[2*SZ_64K-4];
-
 struct msm_iova_data {
 	struct rb_node node;
 	struct mem_pool *pools;
@@ -49,17 +46,29 @@
 	return iommu_present(&platform_bus_type);
 }
 
+bool msm_iommu_page_size_is_supported(unsigned long page_size)
+{
+	return page_size == SZ_4K
+		|| page_size == SZ_64K
+		|| page_size == SZ_1M
+		|| page_size == SZ_16M;
+}
+
 int msm_iommu_map_extra(struct iommu_domain *domain,
 				unsigned long start_iova,
+				unsigned long phy_addr,
 				unsigned long size,
 				unsigned long page_size,
-				int cached)
+				int prot)
 {
 	int ret = 0;
 	int i = 0;
-	unsigned long phy_addr = ALIGN(virt_to_phys(iommu_dummy), page_size);
 	unsigned long temp_iova = start_iova;
-	if (page_size == SZ_4K) {
+	/* the extra "padding" should never be written to. map it
+	 * read-only. */
+	prot &= ~IOMMU_WRITE;
+
+	if (msm_iommu_page_size_is_supported(page_size)) {
 		struct scatterlist *sglist;
 		unsigned int nrpages = PFN_ALIGN(size) >> PAGE_SHIFT;
 		struct page *dummy_page = phys_to_page(phy_addr);
@@ -75,7 +84,7 @@
 		for (i = 0; i < nrpages; i++)
 			sg_set_page(&sglist[i], dummy_page, PAGE_SIZE, 0);
 
-		ret = iommu_map_range(domain, temp_iova, sglist, size, cached);
+		ret = iommu_map_range(domain, temp_iova, sglist, size, prot);
 		if (ret) {
 			pr_err("%s: could not map extra %lx in domain %p\n",
 				__func__, start_iova, domain);
@@ -89,7 +98,7 @@
 
 		for (i = 0; i < nrpages; i++) {
 			ret = iommu_map(domain, temp_iova, phy_addr, page_size,
-						cached);
+						prot);
 			if (ret) {
 				pr_err("%s: could not map %lx in domain %p, error: %d\n",
 					__func__, start_iova, domain, ret);
@@ -474,7 +483,7 @@
 				 const struct device_node *node)
 {
 	unsigned int ret_val = 0;
-	unsigned int i;
+	unsigned int i, j;
 	struct msm_iova_layout l;
 	struct msm_iova_partition *part = 0;
 	struct iommu_domain *domain = 0;
@@ -512,9 +521,9 @@
 			goto free_mem;
 		}
 
-		for (i = 0; i < l.npartitions * 2; i += 2) {
-			part[i].start = addr_array[i];
-			part[i].size = addr_array[i+1];
+		for (i = 0, j = 0; j < l.npartitions * 2; i++, j += 2) {
+			part[i].start = addr_array[j];
+			part[i].size = addr_array[j+1];
 		}
 	} else {
 		l.npartitions = 1;
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index cdacd87..265435a 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -198,12 +198,6 @@
 static struct workqueue_struct *msm_ipc_router_workqueue;
 
 enum {
-	CLIENT_PORT,
-	SERVER_PORT,
-	CONTROL_PORT,
-};
-
-enum {
 	DOWN,
 	UP,
 };
@@ -1465,8 +1459,9 @@
 	for (i = 0; i < RT_HASH_SIZE; i++) {
 		list_for_each_entry(rt_entry, &routing_table[i], list) {
 			if ((rt_entry->node_id != IPC_ROUTER_NID_LOCAL) &&
-			    (rt_entry->xprt_info->xprt->link_id ==
-			     xprt_info->xprt->link_id))
+			    (!rt_entry->xprt_info ||
+			     (rt_entry->xprt_info->xprt->link_id ==
+			      xprt_info->xprt->link_id)))
 				continue;
 			rc = msm_ipc_router_send_server_list(rt_entry->node_id,
 							     xprt_info);
@@ -1872,6 +1867,7 @@
 	struct rr_header *hdr;
 	struct msm_ipc_port *port_ptr;
 	struct rr_packet *pkt;
+	int ret_len;
 
 	if (!data) {
 		pr_err("%s: Invalid pkt pointer\n", __func__);
@@ -1917,11 +1913,12 @@
 	mutex_lock(&port_ptr->port_rx_q_lock);
 	wake_lock(&port_ptr->port_rx_wake_lock);
 	list_add_tail(&pkt->list, &port_ptr->port_rx_q);
+	ret_len = pkt->length;
 	wake_up(&port_ptr->port_rx_wait_q);
 	mutex_unlock(&port_ptr->port_rx_q_lock);
 	mutex_unlock(&local_ports_lock);
 
-	return pkt->length;
+	return ret_len;
 }
 
 static int msm_ipc_router_write_pkt(struct msm_ipc_port *src,
@@ -2307,6 +2304,11 @@
 		mutex_lock(&control_ports_lock);
 		list_del(&port_ptr->list);
 		mutex_unlock(&control_ports_lock);
+	} else if (port_ptr->type == IRSC_PORT) {
+		mutex_lock(&local_ports_lock);
+		list_del(&port_ptr->list);
+		mutex_unlock(&local_ports_lock);
+		signal_irsc_completion();
 	}
 
 	mutex_lock(&port_ptr->port_rx_q_lock);
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index d05c430..a50a37d 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -55,6 +55,13 @@
 #define ALL_SERVICE 0xFFFFFFFF
 #define ALL_INSTANCE 0xFFFFFFFF
 
+enum {
+	CLIENT_PORT,
+	SERVER_PORT,
+	CONTROL_PORT,
+	IRSC_PORT,
+};
+
 union rr_control_msg {
 	uint32_t cmd;
 	struct {
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 88ab3dd..d31af84 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -174,12 +174,6 @@
 	struct msm_ipc_port *port_ptr;
 	void *pil;
 
-	if (!check_permissions()) {
-		pr_err("%s: %s Do not have permissions\n",
-			__func__, current->comm);
-		return -EPERM;
-	}
-
 	if (unlikely(protocol != 0)) {
 		pr_err("%s: Protocol not supported\n", __func__);
 		return -EPROTONOSUPPORT;
@@ -229,6 +223,12 @@
 	if (!sk)
 		return -EINVAL;
 
+	if (!check_permissions()) {
+		pr_err("%s: %s Do not have permissions\n",
+			__func__, current->comm);
+		return -EPERM;
+	}
+
 	if (!uaddr_len) {
 		pr_err("%s: Invalid address length\n", __func__);
 		return -EINVAL;
@@ -282,6 +282,9 @@
 		goto out_sendmsg;
 	}
 
+	if (port_ptr->type == CLIENT_PORT)
+		wait_for_irsc_completion();
+
 	ret = msm_ipc_router_send_to(port_ptr, msg, &dest->address);
 	if (ret == (IPC_ROUTER_HDR_SIZE + total_len))
 		ret = total_len;
@@ -431,6 +434,8 @@
 
 	case IPC_ROUTER_IOCTL_CONFIG_SEC_RULES:
 		ret = msm_ipc_config_sec_rules((void *)arg);
+		if (ret != -EPERM)
+			port_ptr->type = IRSC_PORT;
 		break;
 
 	default:
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index aa03a6a..01be641 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -70,6 +70,7 @@
 
 #define BHS_SETTLING_DELAY_US		1
 #define LDO_SETTLING_DELAY_US		1
+#define MDD_SETTLING_DELAY_US		5
 
 #define _KRAIT_MASK(BITS, POS)  (((u32)(1 << (BITS)) - 1) << POS)
 #define KRAIT_MASK(LEFT_BIT_POS, RIGHT_BIT_POS) \
@@ -179,9 +180,12 @@
 	int				headroom_uV;
 	int				ldo_threshold_uV;
 	int				ldo_delta_uV;
+	int				cpu_num;
 	bool				online;
 };
 
+DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
+
 static u32 version;
 
 static int is_between(int left, int right, int value)
@@ -267,6 +271,40 @@
 	return 0;
 }
 
+static int __krait_power_mdd_enable(struct krait_power_vreg *kvreg, bool on)
+{
+	if (on) {
+		writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
+		/* complete the above write before the delay */
+		mb();
+		udelay(MDD_SETTLING_DELAY_US);
+	} else {
+		writel_relaxed(0x00000000, kvreg->mdd_base + MDD_MODE);
+		/*
+		 * complete the above write before other accesses
+		 * to krait regulator
+		 */
+		mb();
+	}
+	return 0;
+}
+
+int krait_power_mdd_enable(int cpu_num, bool on)
+{
+	struct krait_power_vreg *kvreg = per_cpu(krait_vregs, cpu_num);
+
+	if (!on && kvreg->mode == LDO_MODE) {
+		pr_debug("%s using LDO - cannot turn off MDD\n", kvreg->name);
+		return -EINVAL;
+	}
+
+	if ((on && kvreg->mode == LDO_MODE) || (!on && kvreg->mode == HS_MODE))
+		return 0;
+
+	__krait_power_mdd_enable(kvreg, on);
+	return 0;
+}
+
 static int switch_to_using_hs(struct krait_power_vreg *kvreg)
 {
 	if (kvreg->mode == HS_MODE)
@@ -296,6 +334,8 @@
 	krait_masked_write(kvreg, APC_PWR_GATE_CTL,
 				LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
 
+	/* turn off MDD since LDO is not used */
+	__krait_power_mdd_enable(kvreg, false);
 	kvreg->mode = HS_MODE;
 	pr_debug("%s using BHS\n", kvreg->name);
 	return 0;
@@ -314,6 +354,9 @@
 	if (kvreg->mode == LDO_MODE)
 		switch_to_using_hs(kvreg);
 
+	/* turn on MDD since LDO is being turned on */
+	__krait_power_mdd_enable(kvreg, true);
+
 	set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
 
 	/*
@@ -873,6 +916,7 @@
 	int rc = 0;
 	int headroom_uV, retention_uV, ldo_default_uV, ldo_threshold_uV;
 	int ldo_delta_uV;
+	int cpu_num;
 
 	/* Initialize the pmic gang if it hasn't been initialized already */
 	if (the_gang == NULL) {
@@ -967,6 +1011,13 @@
 					ldo_delta_uV);
 			return -EINVAL;
 		}
+		rc = of_property_read_u32(pdev->dev.of_node,
+					"qcom,cpu-num",
+					&cpu_num);
+		if (cpu_num > num_possible_cpus()) {
+			pr_err("bad cpu-num= %d specified\n", cpu_num);
+			return -EINVAL;
+		}
 	}
 
 	if (!init_data) {
@@ -1019,6 +1070,7 @@
 	kvreg->ldo_default_uV	= ldo_default_uV;
 	kvreg->ldo_threshold_uV = ldo_threshold_uV;
 	kvreg->ldo_delta_uV	= ldo_delta_uV;
+	kvreg->cpu_num		= cpu_num;
 
 	platform_set_drvdata(pdev, kvreg);
 
@@ -1038,6 +1090,7 @@
 	}
 
 	kvreg_hw_init(kvreg);
+	per_cpu(krait_vregs, cpu_num) = kvreg;
 	dev_dbg(&pdev->dev, "id=%d, name=%s\n", pdev->id, kvreg->name);
 
 	return 0;
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index fcb4299..8571bda 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -176,6 +176,18 @@
 	}
 	return best->latency_us - 1;
 }
+static bool msm_lpm_irqs_detectable(struct msm_rpmrs_limits *limits,
+		bool irqs_detectable, bool gpio_detectable)
+{
+	if (!limits->irqs_detectable)
+		return irqs_detectable;
+
+	if (!limits->gpio_detectable)
+		return gpio_detectable;
+
+	return true;
+
+}
 
 static void *msm_lpm_lowest_limits(bool from_idle,
 		enum msm_pm_sleep_mode sleep_mode,
@@ -186,11 +198,19 @@
 	uint32_t pwr;
 	int i;
 	int best_level_iter = msm_lpm_level_count + 1;
+	bool irqs_detect = false;
+	bool gpio_detect = false;
+
 	if (!msm_lpm_levels)
 		return NULL;
 
 	msm_lpm_level_update();
 
+	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
+		irqs_detect = msm_mpm_irqs_detectable(from_idle);
+		gpio_detect = msm_mpm_gpio_irqs_detectable(from_idle);
+	}
+
 	for (i = 0; i < msm_lpm_level_count; i++) {
 		struct msm_rpmrs_level *level = &msm_lpm_levels[i];
 
@@ -203,6 +223,11 @@
 		if (time_param->latency_us < level->latency_us)
 			continue;
 
+		if ((sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) &&
+			!msm_lpm_irqs_detectable(&level->rs_limits,
+				irqs_detect, gpio_detect))
+				continue;
+
 		if ((MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE == sleep_mode)
 			|| (MSM_PM_SLEEP_MODE_POWER_COLLAPSE == sleep_mode))
 			if (!cpu && msm_rpm_waiting_for_ack())
@@ -325,6 +350,14 @@
 			goto fail;
 		level->rs_limits.vdd_mem_lower_bound = val;
 
+		key = "qcom,gpio-detectable";
+		level->rs_limits.gpio_detectable =
+				of_property_read_bool(node, key);
+
+		key = "qcom,irqs-detectable";
+		level->rs_limits.irqs_detectable =
+				of_property_read_bool(node, key);
+
 		key = "qcom,latency-us";
 		ret = of_property_read_u32(node, key, &val);
 		if (ret)
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
index 42e43c2..1a2d72d 100644
--- a/arch/arm/mach-msm/lpm_resources.h
+++ b/arch/arm/mach-msm/lpm_resources.h
@@ -8,7 +8,6 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
  */
 
 #ifndef __ARCH_ARM_MACH_MSM_LPM_RESOURCES_H
@@ -36,6 +35,8 @@
 	uint32_t vdd_mem_lower_bound;
 	uint32_t vdd_dig_upper_bound;
 	uint32_t vdd_dig_lower_bound;
+	bool irqs_detectable;
+	bool gpio_detectable;
 
 	uint32_t latency_us[NR_CPUS];
 	uint32_t power[NR_CPUS];
diff --git a/arch/arm/mach-msm/mpm-of.c b/arch/arm/mach-msm/mpm-of.c
index 8f78735..09f784d 100644
--- a/arch/arm/mach-msm/mpm-of.c
+++ b/arch/arm/mach-msm/mpm-of.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -51,11 +51,14 @@
 	unsigned long pin;
 	struct hlist_node node;
 };
+#define MAX_DOMAIN_NAME 5
 
 struct mpm_irqs {
 	struct irq_domain *domain;
 	unsigned long *enabled_irqs;
 	unsigned long *wakeup_irqs;
+	unsigned long size;
+	char domain_name[MAX_DOMAIN_NAME];
 };
 
 static struct mpm_irqs unlisted_irqs[MSM_MPM_NR_IRQ_DOMAINS];
@@ -437,28 +440,53 @@
 	return 0;
 }
 
-bool msm_mpm_irqs_detectable(bool from_idle)
+static bool msm_mpm_interrupts_detectable(int d, bool from_idle)
 {
-	/* TODO:
-	 * Return true if unlisted irqs is empty
-	 */
+	unsigned long *irq_bitmap;
+	bool debug_mask, ret = false;
+	struct mpm_irqs *unlisted = &unlisted_irqs[d];
 
 	if (!msm_mpm_is_initialized())
 		return false;
 
-	return true;
+	if (from_idle) {
+		irq_bitmap = unlisted->enabled_irqs;
+		debug_mask = msm_mpm_debug_mask &
+				MSM_MPM_DEBUG_NON_DETECTABLE_IRQ_IDLE;
+	} else {
+		irq_bitmap = unlisted->wakeup_irqs;
+		debug_mask = msm_mpm_debug_mask &
+				MSM_MPM_DEBUG_NON_DETECTABLE_IRQ;
+	}
+
+	ret = (bool) __bitmap_empty(irq_bitmap, unlisted->size);
+
+	if (debug_mask && !ret) {
+		int i = 0;
+		i = find_first_bit(irq_bitmap, unlisted->size);
+		pr_info("%s(): %s preventing system sleep modes during %s\n",
+				__func__, unlisted->domain_name,
+				from_idle ? "idle" : "suspend");
+
+		while (i < unlisted->size) {
+			pr_info("\thwirq: %d\n", i);
+			i = find_next_bit(irq_bitmap, unlisted->size, i + 1);
+		}
+	}
+
+	return ret;
 }
 
 bool msm_mpm_gpio_irqs_detectable(bool from_idle)
 {
-	/* TODO:
-	 * Return true if unlisted irqs is empty
-	 */
-	if (!msm_mpm_is_initialized())
-		return false;
-	return true;
+	return msm_mpm_interrupts_detectable(MSM_MPM_GPIO_IRQ_DOMAIN,
+			from_idle);
 }
-
+bool msm_mpm_irqs_detectable(bool from_idle)
+{
+	return msm_mpm_interrupts_detectable(MSM_MPM_GIC_IRQ_DOMAIN,
+			from_idle);
+}
 void msm_mpm_enter_sleep(uint32_t sclk_count, bool from_idle)
 {
 	cycle_t wakeup = (u64)sclk_count * ARCH_TIMER_HZ;
@@ -614,6 +642,7 @@
 	struct mpm_of {
 		char *pkey;
 		char *map;
+		char name[MAX_DOMAIN_NAME];
 		struct irq_chip *chip;
 		int (*get_max_irqs)(struct irq_domain *d);
 	};
@@ -623,12 +652,14 @@
 		{
 			"qcom,gic-parent",
 			"qcom,gic-map",
+			"gic",
 			&gic_arch_extn,
 			mpm_irq_domain_linear_size,
 		},
 		{
 			"qcom,gpio-parent",
 			"qcom,gpio-map",
+			"gpio",
 			&msm_gpio_irq_extn,
 			mpm_irq_domain_legacy_size,
 		},
@@ -665,6 +696,9 @@
 		}
 
 		size = mpm_of_map[i].get_max_irqs(domain);
+		unlisted_irqs[i].size = size;
+		memcpy(unlisted_irqs[i].domain_name, mpm_of_map[i].name,
+				MAX_DOMAIN_NAME);
 
 		unlisted_irqs[i].enabled_irqs =
 			kzalloc(BITS_TO_LONGS(size) * sizeof(unsigned long),
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index dde25ab..e785c00 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -2,7 +2,9 @@
 # Makefile for msm-bus driver specific files
 #
 obj-y += msm_bus_core.o msm_bus_fabric.o msm_bus_config.o msm_bus_arb.o
-obj-y += msm_bus_bimc.o msm_bus_noc.o msm_bus_of.o
+obj-y += msm_bus_bimc.o msm_bus_noc.o
+obj-$(CONFIG_CORESIGHT) +=  msm_buspm_coresight.o
+obj-$(CONFIG_OF) += msm_bus_of.o
 obj-$(CONFIG_MSM_RPM) += msm_bus_rpm.o
 obj-$(CONFIG_MSM_RPM_SMD) += msm_bus_rpm_smd.o
 obj-$(CONFIG_ARCH_MSM8X60) += msm_bus_board_8660.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
index b593439..d3d1ffa 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
@@ -922,3 +922,7 @@
 {
 	return -ENXIO;
 }
+
+void msm_bus_board_init(struct msm_bus_fabric_registration *pdata)
+{
+}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 056763c..158dee3 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -1114,3 +1114,7 @@
 	id[1] = MSM_RPM_STATUS_ID_EBI1_CH1_RANGE;
 	return 0;
 }
+
+void msm_bus_board_init(struct msm_bus_fabric_registration *pdata)
+{
+}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c
index 7b67157..1f6e508 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c
@@ -2007,3 +2007,8 @@
 	.virt = 1,
 	.rpm_enabled = 1,
 };
+
+void msm_bus_board_init(struct msm_bus_fabric_registration *pdata)
+{
+	pdata->board_algo = &msm_bus_board_algo;
+}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
index b3c3e7f..862bb46 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
@@ -311,3 +311,7 @@
 {
 	return -ENXIO;
 }
+
+void msm_bus_board_init(struct msm_bus_fabric_registration *pdata)
+{
+}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
index 92cd255..65834eb 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
@@ -1301,3 +1301,7 @@
 	.hw_sel = MSM_BUS_NOC,
 	.rpm_enabled = 1,
 };
+
+void msm_bus_board_init(struct msm_bus_fabric_registration *pdata)
+{
+}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.c b/arch/arm/mach-msm/msm_bus/msm_bus_core.c
index 6f65bcc..20600bf 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -58,6 +58,8 @@
 	struct msm_bus_fabric_device *fabric;
 	dev = bus_find_device(&msm_bus_type, NULL, (void *)fabid,
 		msm_bus_device_match);
+	if (!dev)
+		return NULL;
 	fabric = to_msm_bus_fabric_device(dev);
 	return fabric;
 }
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index d03f9a7..9201398 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -81,6 +81,7 @@
 	unsigned int prio_wr;
 	unsigned int prio1;
 	unsigned int prio0;
+	const char *name;
 };
 
 struct path_node {
@@ -213,6 +214,7 @@
 
 int msm_bus_hw_fab_init(struct msm_bus_fabric_registration *pdata,
 	struct msm_bus_hw_algorithm *hw_algo);
+void msm_bus_board_init(struct msm_bus_fabric_registration *pdata);
 #if defined(CONFIG_MSM_RPM) || defined(CONFIG_MSM_RPM_SMD)
 int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata,
 	struct msm_bus_hw_algorithm *hw_algo);
@@ -259,4 +261,30 @@
 }
 #endif
 
+#ifdef CONFIG_CORESIGHT
+int msmbus_coresight_init(struct platform_device *pdev);
+void msmbus_coresight_remove(struct platform_device *pdev);
+#else
+static inline int msmbus_coresight_init(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static inline void msmbus_coresight_remove(struct platform_device *pdev)
+{
+}
+#endif
+
+
+#ifdef CONFIG_OF
+struct msm_bus_fabric_registration
+	*msm_bus_of_get_fab_data(struct platform_device *pdev);
+#else
+static inline struct msm_bus_fabric_registration
+	*msm_bus_of_get_fab_data(struct platform_device *pdev)
+{
+	return NULL;
+}
+#endif
+
 #endif /*_ARCH_ARM_MACH_MSM_BUS_CORE_H*/
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 2c4b434..0d28e9d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -712,11 +712,12 @@
 
 	/* If possible, get pdata from device-tree */
 	if (pdev->dev.of_node) {
-		pdata = pdev->dev.platform_data;
+		pdata = msm_bus_of_get_fab_data(pdev);
 		if (IS_ERR(pdata) || ZERO_OR_NULL_PTR(pdata)) {
 			pr_err("Null platform data\n");
 			return PTR_ERR(pdata);
 		}
+		msm_bus_board_init(pdata);
 		fabric->fabdev.id = pdata->id;
 	} else {
 		pdata = (struct msm_bus_fabric_registration *)pdev->
@@ -788,6 +789,9 @@
 		}
 	}
 
+	if (msmbus_coresight_init(pdev))
+		pr_warn("Coresight support absent for bus: %d\n", pdata->id);
+
 	return ret;
 err:
 	kfree(fabric->info.node_info);
@@ -803,6 +807,7 @@
 	int ret = 0;
 
 	fabdev = platform_get_drvdata(pdev);
+	msmbus_coresight_remove(pdev);
 	msm_bus_fabric_device_unregister(fabdev);
 	fabric = to_msm_bus_fabric(fabdev);
 	msm_bus_dbg_commit_data(fabric->fabdev.name, NULL, 0, 0, 0,
@@ -824,7 +829,7 @@
 }
 
 static struct of_device_id fabric_match[] = {
-	{.compatible = "msm_bus_fabric"},
+	{.compatible = "msm-bus-fabric"},
 	{}
 };
 
@@ -832,7 +837,7 @@
 	.probe = msm_bus_fabric_probe,
 	.remove = msm_bus_fabric_remove,
 	.driver = {
-		.name = "msm_bus_fabric",
+		.name = "msm-bus-fabric",
 		.owner = THIS_MODULE,
 		.of_match_table = fabric_match,
 	},
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_of.c b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
index 8ae1b46..489eb5c 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_of.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,12 +14,34 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include "msm_bus_core.h"
 
 #define KBTOMB(a) (a * 1000ULL)
+static const char * const hw_sel_name[] = {"RPM", "NoC", "BIMC", NULL};
+static const char * const mode_sel_name[] = {"Fixed", "Limiter", "Bypass",
+						"Regulator", NULL};
+
+static int get_num(const char *const str[], const char *name)
+{
+	int i = 0;
+
+	do {
+		if (!strcmp(name, str[i]))
+			return i;
+
+		i++;
+	} while (str[i] != NULL);
+
+	pr_err("Error: string %s not found\n", name);
+	return -EINVAL;
+}
+
 /**
  * msm_bus_cl_get_pdata() - Generate bus client data from device tree
  * provided by clients.
@@ -72,8 +94,8 @@
 	ret = of_property_read_u32(of_node, "qcom,msm-bus,active-only",
 		&pdata->active_only);
 	if (ret) {
-		pr_info("active_only flag absent.\n");
-		pr_info("Using dual context by default\n");
+		pr_debug("active_only flag absent.\n");
+		pr_debug("Using dual context by default\n");
 	}
 
 	usecase = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_paths) *
@@ -149,3 +171,292 @@
 	kfree(pdata);
 }
 EXPORT_SYMBOL(msm_bus_cl_clear_pdata);
+
+static int *get_arr(struct platform_device *pdev,
+		const struct device_node *node, const char *prop,
+		int *nports)
+{
+	int size = 0, ret;
+	int *arr = NULL;
+
+	if (of_get_property(node, prop, &size)) {
+		*nports = size / sizeof(int);
+	} else {
+		pr_debug("Property %s not available\n", prop);
+		*nports = 0;
+		return NULL;
+	}
+
+	arr = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	if ((size > 0) && ZERO_OR_NULL_PTR(arr)) {
+		pr_err("Error: Failed to alloc mem for %s\n", prop);
+		return NULL;
+	}
+
+	ret = of_property_read_u32_array(node, prop, (u32 *)arr, *nports);
+	if (ret) {
+		pr_err("Error in reading property: %s\n", prop);
+		goto err;
+	}
+
+	return arr;
+err:
+	devm_kfree(&pdev->dev, arr);
+	return NULL;
+}
+
+static struct msm_bus_node_info *get_nodes(struct device_node *of_node,
+	struct platform_device *pdev,
+	struct msm_bus_fabric_registration *pdata)
+{
+	struct msm_bus_node_info *info;
+	struct device_node *child_node = NULL;
+	int i = 0, ret;
+
+	for_each_child_of_node(of_node, child_node) {
+		i++;
+	}
+
+	pdata->len = i;
+	info = (struct msm_bus_node_info *)
+		devm_kzalloc(&pdev->dev, sizeof(struct msm_bus_node_info) *
+			pdata->len, GFP_KERNEL);
+	if (ZERO_OR_NULL_PTR(info)) {
+		pr_err("Failed to alloc memory for nodes: %d\n", pdata->len);
+		goto err;
+	}
+
+	i = 0;
+	child_node = NULL;
+	for_each_child_of_node(of_node, child_node) {
+		const char *sel_str;
+
+		ret = of_property_read_string(child_node, "label",
+			&info[i].name);
+		if (ret)
+			pr_err("Error reading node label\n");
+
+		ret = of_property_read_u32(child_node, "cell-id", &info[i].id);
+		if (ret) {
+			pr_err("Error reading node id\n");
+			goto err;
+		}
+
+		if (of_property_read_bool(child_node, "qcom,gateway"))
+			info[i].gateway = 1;
+
+		of_property_read_u32(child_node, "qcom,mas-hw-id",
+			&info[i].mas_hw_id);
+
+		of_property_read_u32(child_node, "qcom,slv-hw-id",
+			&info[i].slv_hw_id);
+		info[i].masterp = get_arr(pdev, child_node,
+					"qcom,masterp", &info[i].num_mports);
+		/* No need to store number of qports */
+		info[i].qport = get_arr(pdev, child_node,
+					"qcom,qport", &ret);
+		pdata->nmasters += info[i].num_mports;
+
+
+		info[i].slavep = get_arr(pdev, child_node,
+					"qcom,slavep", &info[i].num_sports);
+		pdata->nslaves += info[i].num_sports;
+
+
+		info[i].tier = get_arr(pdev, child_node,
+					"qcom,tier", &info[i].num_tiers);
+
+		if (of_property_read_bool(child_node, "qcom,ahb"))
+			info[i].ahb = 1;
+
+		ret = of_property_read_string(child_node, "qcom,hw-sel",
+			&sel_str);
+		if (ret)
+			info[i].hw_sel = 0;
+		else {
+			ret =  get_num(hw_sel_name, sel_str);
+			if (ret < 0) {
+				pr_err("Invalid hw-sel\n");
+				goto err;
+			}
+
+			info[i].hw_sel = ret;
+		}
+
+		of_property_read_u32(child_node, "qcom,buswidth",
+			&info[i].buswidth);
+		of_property_read_u32(child_node, "qcom,ws", &info[i].ws);
+		ret = of_property_read_string(child_node, "qcom,mode",
+			&sel_str);
+		if (ret)
+			info[i].mode = 0;
+		else {
+			ret = get_num(mode_sel_name, sel_str);
+			if (ret < 0) {
+				pr_err("Unknown mode :%s\n", sel_str);
+				goto err;
+			}
+
+			info[i].mode = ret;
+		}
+
+		ret = of_property_read_string(child_node, "qcom,perm-mode",
+			&sel_str);
+		if (ret)
+			info[i].perm_mode = 0;
+		else {
+			ret = get_num(mode_sel_name, sel_str);
+			if (ret < 0)
+				goto err;
+
+			info[i].perm_mode = 1 << ret;
+		}
+
+		of_property_read_u32(child_node, "qcom,prio-lvl",
+			&info[i].prio_lvl);
+		of_property_read_u32(child_node, "qcom,prio-rd",
+			&info[i].prio_rd);
+		of_property_read_u32(child_node, "qcom,prio-wr",
+			&info[i].prio_wr);
+		of_property_read_u32(child_node, "qcom,prio0", &info[i].prio0);
+		of_property_read_u32(child_node, "qcom,prio1", &info[i].prio1);
+		ret = of_property_read_string(child_node, "qcom,slaveclk-dual",
+			&info[i].slaveclk[DUAL_CTX]);
+		if (!ret)
+			pr_debug("Got slaveclk_dual: %s\n",
+				info[i].slaveclk[DUAL_CTX]);
+		else
+			info[i].slaveclk[DUAL_CTX] = NULL;
+
+		ret = of_property_read_string(child_node,
+			"qcom,slaveclk-active", &info[i].slaveclk[ACTIVE_CTX]);
+		if (!ret)
+			pr_debug("Got slaveclk_active\n");
+		else
+			info[i].slaveclk[ACTIVE_CTX] = NULL;
+
+		ret = of_property_read_string(child_node, "qcom,memclk-dual",
+			&info[i].memclk[DUAL_CTX]);
+		if (!ret)
+			pr_debug("Got memclk_dual\n");
+		else
+			info[i].memclk[DUAL_CTX] = NULL;
+
+		ret = of_property_read_string(child_node, "qcom,memclk-active",
+			&info[i].memclk[ACTIVE_CTX]);
+		if (!ret)
+			pr_debug("Got memclk_active\n");
+		else
+			info[i].memclk[ACTIVE_CTX] = NULL;
+
+		ret = of_property_read_string(child_node, "qcom,iface-clk-node",
+			&info[i].iface_clk_node);
+		if (!ret)
+			pr_debug("Got iface_clk_node\n");
+		else
+			info[i].iface_clk_node = NULL;
+
+		pr_debug("Node name: %s\n", info[i].name);
+		of_node_put(child_node);
+		i++;
+	}
+
+	pr_debug("Bus %d added: %d masters\n", pdata->id, pdata->nmasters);
+	pr_debug("Bus %d added: %d slaves\n", pdata->id, pdata->nslaves);
+	return info;
+err:
+	return NULL;
+}
+
+struct msm_bus_fabric_registration
+	*msm_bus_of_get_fab_data(struct platform_device *pdev)
+{
+	struct device_node *of_node = pdev->dev.of_node;
+	struct msm_bus_fabric_registration *pdata;
+	bool mem_err = false;
+	int ret = 0;
+	const char *sel_str;
+
+	if (!pdev) {
+		pr_err("Error: Null platform device\n");
+		return NULL;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct msm_bus_fabric_registration), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("Error: Memory allocation for pdata failed\n");
+		mem_err = true;
+		goto err;
+	}
+
+	ret = of_property_read_string(of_node, "label", &pdata->name);
+	if (ret) {
+		pr_err("Error: label not found\n");
+		goto err;
+	}
+	pr_debug("Fab_of: Read name: %s\n", pdata->name);
+
+	ret = of_property_read_u32(of_node, "cell-id",
+		&pdata->id);
+	if (ret) {
+		pr_err("Error: num-usecases not found\n");
+		goto err;
+	}
+	pr_debug("Fab_of: Read id: %u\n", pdata->id);
+
+	if (of_property_read_bool(of_node, "qcom,ahb"))
+		pdata->ahb = 1;
+
+	ret = of_property_read_string(of_node, "qcom,fabclk-dual",
+		&pdata->fabclk[DUAL_CTX]);
+	if (ret) {
+		pr_debug("fabclk_dual not available\n");
+		pdata->fabclk[DUAL_CTX] = NULL;
+	} else
+		pr_debug("Fab_of: Read clk dual ctx: %s\n",
+			pdata->fabclk[DUAL_CTX]);
+	ret = of_property_read_string(of_node, "qcom,fabclk-active",
+		&pdata->fabclk[ACTIVE_CTX]);
+	if (ret) {
+		pr_debug("Error: fabclk_active not available\n");
+		pdata->fabclk[ACTIVE_CTX] = NULL;
+	} else
+		pr_debug("Fab_of: Read clk act ctx: %s\n",
+			pdata->fabclk[ACTIVE_CTX]);
+
+	ret = of_property_read_u32(of_node, "qcom,ntieredslaves",
+		&pdata->ntieredslaves);
+	if (ret) {
+		pr_err("Error: ntieredslaves not found\n");
+		goto err;
+	}
+
+	ret = of_property_read_u32(of_node, "qcom,qos-freq", &pdata->qos_freq);
+	if (ret)
+		pr_debug("qos_freq not available\n");
+
+	ret = of_property_read_string(of_node, "qcom,hw-sel", &sel_str);
+	if (ret) {
+		pr_err("Error: hw_sel not found\n");
+		goto err;
+	} else {
+		ret = get_num(hw_sel_name, sel_str);
+		if (ret < 0)
+			goto err;
+
+		pdata->hw_sel = ret;
+	}
+
+	if (of_property_read_bool(of_node, "qcom,virt"))
+		pdata->virt = true;
+
+	if (of_property_read_bool(of_node, "qcom,rpm-en"))
+		pdata->rpm_enabled = 1;
+
+	pdata->info = get_nodes(of_node, pdev, pdata);
+	return pdata;
+err:
+	return NULL;
+}
+EXPORT_SYMBOL(msm_bus_of_get_fab_data);
diff --git a/arch/arm/mach-msm/msm_bus/msm_buspm_coresight.c b/arch/arm/mach-msm/msm_bus/msm_buspm_coresight.c
new file mode 100644
index 0000000..6dbe954
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_buspm_coresight.c
@@ -0,0 +1,159 @@
+/* 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/clk.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+#include <linux/memory_alloc.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+struct msmbus_coresight_drvdata {
+	struct device			*dev;
+	struct coresight_device		*csdev;
+	struct clk			*clk;
+	const char			*clk_name;
+	const char			*clknode;
+};
+
+static int msmbus_coresight_enable(struct coresight_device *csdev)
+{
+	struct msmbus_coresight_drvdata *drvdata =
+		dev_get_drvdata(csdev->dev.parent);
+
+	return clk_prepare_enable(drvdata->clk);
+}
+
+static void msmbus_coresight_disable(struct coresight_device *csdev)
+{
+	struct msmbus_coresight_drvdata *drvdata =
+		dev_get_drvdata(csdev->dev.parent);
+
+	clk_disable_unprepare(drvdata->clk);
+}
+
+static const struct coresight_ops_source msmbus_coresight_source_ops = {
+	.enable		= msmbus_coresight_enable,
+	.disable	= msmbus_coresight_disable,
+};
+
+static const struct coresight_ops msmbus_coresight_cs_ops = {
+	.source_ops	= &msmbus_coresight_source_ops,
+};
+
+void msmbus_coresight_remove(struct platform_device *pdev)
+{
+	struct msmbus_coresight_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	msmbus_coresight_disable(drvdata->csdev);
+	coresight_unregister(drvdata->csdev);
+	devm_kfree(&pdev->dev, drvdata);
+	platform_set_drvdata(pdev, NULL);
+}
+EXPORT_SYMBOL(msmbus_coresight_remove);
+
+static int buspm_of_get_clk(struct device_node *of_node,
+	struct msmbus_coresight_drvdata *drvdata)
+{
+	if (of_property_read_string(of_node, "qcom,fabclk-dual",
+						&drvdata->clk_name)) {
+		pr_err("Error: Unable to find clock from of_node\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_string(of_node, "label", &drvdata->clknode)) {
+		pr_err("Error: Unable to find clock-node from of_node\n");
+		return -EINVAL;
+	}
+
+	drvdata->clk = clk_get_sys(drvdata->clknode, drvdata->clk_name);
+	if (IS_ERR(drvdata->clk)) {
+		pr_err("Error: clk_get_sys failed for: %s\n",
+			drvdata->clknode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int msmbus_coresight_init(struct platform_device *pdev)
+{
+	int ret;
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct msmbus_coresight_drvdata *drvdata;
+	struct coresight_desc *desc;
+
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
+	}
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata) {
+		pr_err("coresight: Alloc for drvdata failed\n");
+		return -ENOMEM;
+	}
+
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+	ret = buspm_of_get_clk(pdev->dev.of_node, drvdata);
+	if (ret) {
+		pr_err("Error getting clocks\n");
+		ret = -ENXIO;
+		goto err1;
+	}
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc) {
+		pr_err("coresight: Error allocating memory\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
+	desc->ops = &msmbus_coresight_cs_ops;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev)) {
+		pr_err("coresight: Coresight register failed\n");
+		ret = PTR_ERR(drvdata->csdev);
+		goto err0;
+	}
+
+	dev_info(dev, "msmbus_coresight initialized\n");
+
+	return 0;
+err0:
+	devm_kfree(dev, desc);
+err1:
+	devm_kfree(dev, drvdata);
+	platform_set_drvdata(pdev, NULL);
+	return ret;
+}
+EXPORT_SYMBOL(msmbus_coresight_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM BusPM CoreSight Driver");
diff --git a/arch/arm/mach-msm/msm_ipc_router_security.c b/arch/arm/mach-msm/msm_ipc_router_security.c
index 27cf524..756e24e 100644
--- a/arch/arm/mach-msm/msm_ipc_router_security.c
+++ b/arch/arm/mach-msm/msm_ipc_router_security.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -29,6 +29,7 @@
 #include "ipc_router.h"
 #include "msm_ipc_router_security.h"
 
+#define IRSC_COMPLETION_TIMEOUT_MS 30000
 #define SEC_RULES_HASH_SZ 32
 struct security_rule {
 	struct list_head list;
@@ -41,6 +42,31 @@
 
 static DEFINE_MUTEX(security_rules_lock);
 static struct list_head security_rules[SEC_RULES_HASH_SZ];
+static DECLARE_COMPLETION(irsc_completion);
+
+/**
+ * wait_for_irsc_completion() - Wait for IPC Router Security Configuration
+ *                              (IRSC) to complete
+ */
+void wait_for_irsc_completion(void)
+{
+	unsigned long rem_jiffies;
+	do {
+		rem_jiffies = wait_for_completion_timeout(&irsc_completion,
+				msecs_to_jiffies(IRSC_COMPLETION_TIMEOUT_MS));
+		if (rem_jiffies)
+			return;
+		pr_err("%s: waiting for IPC Security Conf.\n", __func__);
+	} while (1);
+}
+
+/**
+ * signal_irsc_completion() - Signal the completion of IRSC
+ */
+void signal_irsc_completion(void)
+{
+	complete_all(&irsc_completion);
+}
 
 /**
  * check_permisions() - Check whether the process has permissions to
diff --git a/arch/arm/mach-msm/msm_ipc_router_security.h b/arch/arm/mach-msm/msm_ipc_router_security.h
index 8701343..9cc61e9 100644
--- a/arch/arm/mach-msm/msm_ipc_router_security.h
+++ b/arch/arm/mach-msm/msm_ipc_router_security.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -73,6 +73,17 @@
  */
 int msm_ipc_router_security_init(void);
 
+/**
+ * wait_for_irsc_completion() - Wait for IPC Router Security Configuration
+ *                              (IRSC) to complete
+ */
+void wait_for_irsc_completion(void);
+
+/**
+ * signal_irsc_completion() - Signal the completion of IRSC
+ */
+void signal_irsc_completion(void);
+
 #else
 
 static inline int check_permissions(void)
@@ -100,5 +111,10 @@
 {
 	return 0;
 }
+
+static inline void wait_for_irsc_completion(void) { }
+
+static inline void signal_irsc_completion(void) { }
+
 #endif
 #endif
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 34fd8d2..534cdc6 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -359,9 +359,13 @@
 int ocmem_enable_iface_clock(void)
 {
 	int ret;
+
+	if (!ocmem_pdata->iface_clk)
+		return 0;
+
 	ret = clk_prepare_enable(ocmem_pdata->iface_clk);
 	if (ret) {
-		pr_err("ocmem: Failed to disable branch clock\n");
+		pr_err("ocmem: Failed to disable iface clock\n");
 		return ret;
 	}
 	pr_debug("ocmem: Enabled iface clock\n");
@@ -370,6 +374,9 @@
 
 void ocmem_disable_iface_clock(void)
 {
+	if (!ocmem_pdata->iface_clk)
+		return;
+
 	clk_disable_unprepare(ocmem_pdata->iface_clk);
 	pr_debug("ocmem: Disabled iface clock\n");
 }
@@ -411,6 +418,7 @@
 	struct resource *ocmem_mem_io;
 	unsigned nr_parts = 0;
 	unsigned nr_regions = 0;
+	unsigned nr_macros = 0;
 
 	pdata = devm_kzalloc(dev, sizeof(struct ocmem_plat_data),
 			GFP_KERNEL);
@@ -512,6 +520,16 @@
 		return NULL;
 	}
 
+	if (of_property_read_u32(node, "qcom,ocmem-num-macros",
+							 &nr_macros)) {
+		dev_err(dev, "No OCMEM macros specified\n");
+	}
+
+	if (nr_macros == 0) {
+		dev_err(dev, "No hardware macros found\n");
+		return NULL;
+	}
+
 	/* Figure out the number of partititons */
 	nr_parts = of_ocmem_parse_regions(dev, &parts);
 	if (nr_parts <= 0) {
@@ -528,6 +546,7 @@
 	pdata->nr_parts = nr_parts;
 	pdata->parts = parts;
 	pdata->nr_regions = nr_regions;
+	pdata->nr_macros = nr_macros;
 	pdata->ocmem_irq = ocmem_irq->start;
 	pdata->dm_irq = dm_irq->start;
 	return pdata;
@@ -777,10 +796,8 @@
 
 	ocmem_iface_clk = devm_clk_get(dev, "iface_clk");
 
-	if (IS_ERR(ocmem_iface_clk)) {
-		dev_err(dev, "Unable to get the memory interface clock\n");
-		return PTR_ERR(ocmem_core_clk);
-	};
+	if (IS_ERR_OR_NULL(ocmem_iface_clk))
+		ocmem_iface_clk = NULL;
 
 	ocmem_br_clk = devm_clk_get(dev, "br_clk");
 
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 865b3cc..612c9fa 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -49,7 +49,6 @@
 static struct mutex region_ctrl_lock;
 static void *ocmem_base;
 
-#define OCMEM_V1_REGIONS 3
 #define OCMEM_V1_MACROS 8
 #define OCMEM_V1_MACRO_SZ (SZ_64K)
 
@@ -964,30 +963,19 @@
 
 	hw_ver = ocmem_read(ocmem_base + OC_HW_PROFILE);
 
-	if (pdata->nr_regions != OCMEM_V1_REGIONS) {
-		pr_err("Invalid number of regions (%d)\n", pdata->nr_regions);
-		goto hw_not_supported;
-	}
-
 	num_macros = (hw_ver & NUM_MACROS_MASK) >> NUM_MACROS_SHIFT;
 	num_ports = (hw_ver & NUM_PORTS_MASK) >> NUM_PORTS_SHIFT;
 
-	if (num_macros != OCMEM_V1_MACROS) {
+	if (num_macros != pdata->nr_macros) {
 		pr_err("Invalid number of macros (%d)\n", pdata->nr_macros);
 		goto hw_not_supported;
 	}
 
 	interleaved = (hw_ver & INTERLEAVING_MASK) >> INTERLEAVING_SHIFT;
 
-	if (interleaved == false) {
-		pr_err("Interleaving is disabled\n");
-		goto hw_not_supported;
-	}
-
 	num_regions = pdata->nr_regions;
 
 	pdata->interleaved = true;
-	pdata->nr_macros = num_macros;
 	pdata->nr_ports = num_ports;
 	macro_size = OCMEM_V1_MACRO_SZ * 2;
 	num_banks = num_ports / 2;
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 819b4db..dfbda74 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/sysfs.h>
 
 #include <mach/clk.h>
 #include <mach/subsystem_restart.h>
@@ -36,6 +37,9 @@
 #define QDSP6SS_RST_EVB			0x010
 #define PROXY_TIMEOUT_MS		10000
 
+static struct kobject *lpass_status;
+static char status[32];
+
 struct lpass_data {
 	struct q6v5_data *q6;
 	struct subsys_device *subsys;
@@ -278,6 +282,34 @@
 	pr_debug("%s: Q6 NMI was sent.\n", __func__);
 }
 
+/*
+ * The "status" file where a static variable is read from and written to.
+ */
+static ssize_t adsp_state_show(struct kobject *kobj,
+			struct kobj_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, sizeof(status), "%s\n", status);
+}
+
+static struct kobj_attribute adsp_state_attribute =
+	__ATTR(status, 0444, adsp_state_show, NULL);
+
+static struct attribute *attrs[] = {
+	&adsp_state_attribute.attr,
+	NULL,   /* need to NULL terminate the list of attributes */
+};
+
+static struct attribute_group attr_group = {
+	.attrs = attrs,
+};
+
+static void adsp_set_state(char *state)
+{
+	strlcpy(status, state, sizeof(status));
+	sysfs_notify(lpass_status, NULL, "status");
+}
+
 #define subsys_to_lpass(d) container_of(d, struct lpass_data, subsys_desc)
 
 static int adsp_shutdown(const struct subsys_desc *subsys)
@@ -290,6 +322,8 @@
 	pil_shutdown(&drv->q6->desc);
 	disable_irq_nosync(drv->wdog_irq);
 
+	pr_debug("ADSP is Down\n");
+	adsp_set_state("OFFLINE");
 	return 0;
 }
 
@@ -299,6 +333,9 @@
 	int ret = 0;
 	ret = pil_boot(&drv->q6->desc);
 	enable_irq(drv->wdog_irq);
+
+	pr_debug("ADSP is back online\n");
+	adsp_set_state("ONLINE");
 	return ret;
 }
 
@@ -441,7 +478,24 @@
 		ret = PTR_ERR(drv->modem_notif_hdle);
 		goto err_notif_modem;
 	}
+	lpass_status = kobject_create_and_add("audio_voice_service",
+						kernel_kobj);
+	if (!lpass_status) {
+		pr_err("%s: kobject create failed\n", __func__);
+		ret = -ENOMEM;
+		goto err_notif_modem;
+	}
+
+	ret = sysfs_create_group(lpass_status, &attr_group);
+	if (ret) {
+		pr_err("%s: sysfs create group failed\n", __func__);
+		goto err_kobj;
+	}
+
+	adsp_set_state("ONLINE");
 	return 0;
+err_kobj:
+	kobject_put(lpass_status);
 err_notif_modem:
 	subsys_notif_unregister_notifier(drv->riva_notif_hdle, &rnb);
 err_notif_riva:
@@ -454,7 +508,7 @@
 	destroy_ramdump_device(drv->ramdump_dev);
 err_ramdump:
 	pil_desc_release(desc);
-	return 0;
+	return ret;
 }
 
 static int __devexit pil_lpass_driver_exit(struct platform_device *pdev)
@@ -467,6 +521,8 @@
 	subsys_unregister(drv->subsys);
 	destroy_ramdump_device(drv->ramdump_dev);
 	pil_desc_release(&drv->q6->desc);
+	sysfs_remove_group(lpass_status, &attr_group);
+	kobject_del(lpass_status);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 7cf61ab..e85831a 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -514,7 +514,7 @@
 	if (ret)
 		return ret;
 
-	ret = pil_do_ramdump(&drv->q6->desc, drv->ramdump_dev);
+	ret = pil_do_ramdump(&drv->desc, drv->ramdump_dev);
 	if (ret < 0) {
 		pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);
 		goto out;
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 1a9fd26..7f8d3b9 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,8 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <mach/rpm-regulator-smd.h>
 #include <mach/clk.h>
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
@@ -27,7 +29,6 @@
 #define QDSP6SS_RESET			0x014
 #define QDSP6SS_GFMUX_CTL		0x020
 #define QDSP6SS_PWR_CTL			0x030
-#define QDSP6SS_CGC_OVERRIDE		0x034
 
 /* AXI Halt Register Offsets */
 #define AXI_HALTREQ			0x0
@@ -52,10 +53,7 @@
 #define Q6SS_SLP_RET_N			BIT(19)
 #define Q6SS_CLAMP_IO			BIT(20)
 #define QDSS_BHS_ON			BIT(21)
-
-/* QDSP6SS_CGC_OVERRIDE */
-#define Q6SS_CORE_CLK_EN		BIT(0)
-#define Q6SS_CORE_RCLK_EN		BIT(1)
+#define QDSS_LDO_BYP			BIT(22)
 
 int pil_q6v5_make_proxy_votes(struct pil_desc *pil)
 {
@@ -64,16 +62,63 @@
 
 	ret = clk_prepare_enable(drv->xo);
 	if (ret) {
-		dev_err(pil->dev, "Failed to enable XO\n");
-		return ret;
+		dev_err(pil->dev, "Failed to vote for XO\n");
+		goto out;
 	}
+
+	ret = regulator_set_voltage(drv->vreg_cx,
+				    RPM_REGULATOR_CORNER_SUPER_TURBO,
+				    RPM_REGULATOR_CORNER_SUPER_TURBO);
+	if (ret) {
+		dev_err(pil->dev, "Failed to request vdd_cx voltage.\n");
+		goto err_cx_voltage;
+	}
+
+	ret = regulator_set_optimum_mode(drv->vreg_cx, 100000);
+	if (ret < 0) {
+		dev_err(pil->dev, "Failed to set vdd_cx mode.\n");
+		goto err_cx_mode;
+	}
+
+	ret = regulator_enable(drv->vreg_cx);
+	if (ret) {
+		dev_err(pil->dev, "Failed to vote for vdd_cx\n");
+		goto err_cx_enable;
+	}
+
+	if (drv->vreg_pll) {
+		ret = regulator_enable(drv->vreg_pll);
+		if (ret) {
+			dev_err(pil->dev, "Failed to vote for vdd_pll\n");
+			goto err_vreg_pll;
+		}
+	}
+
 	return 0;
+
+err_vreg_pll:
+	regulator_disable(drv->vreg_cx);
+err_cx_enable:
+	regulator_set_optimum_mode(drv->vreg_cx, 0);
+err_cx_mode:
+	regulator_set_voltage(drv->vreg_cx, RPM_REGULATOR_CORNER_NONE,
+			      RPM_REGULATOR_CORNER_SUPER_TURBO);
+err_cx_voltage:
+	clk_disable_unprepare(drv->xo);
+out:
+	return ret;
 }
 EXPORT_SYMBOL(pil_q6v5_make_proxy_votes);
 
 void pil_q6v5_remove_proxy_votes(struct pil_desc *pil)
 {
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	if (drv->vreg_pll)
+		regulator_disable(drv->vreg_pll);
+	regulator_disable(drv->vreg_cx);
+	regulator_set_optimum_mode(drv->vreg_cx, 0);
+	regulator_set_voltage(drv->vreg_cx, RPM_REGULATOR_CORNER_NONE,
+			      RPM_REGULATOR_CORNER_SUPER_TURBO);
 	clk_disable_unprepare(drv->xo);
 }
 EXPORT_SYMBOL(pil_q6v5_remove_proxy_votes);
@@ -125,7 +170,7 @@
 	val = (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENA);
 	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
 
-	/* Kill power at block headswitch (affects LPASS only) */
+	/* Kill power at block headswitch */
 	val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
 	val &= ~QDSS_BHS_ON;
 	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
@@ -142,10 +187,12 @@
 	val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENA | Q6SS_STOP_CORE);
 	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
 
-	/* Enable power block headswitch (only affects LPASS) */
+	/* Enable power block headswitch, and wait for it to stabilize */
 	val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
-	val |= QDSS_BHS_ON;
+	val |= QDSS_BHS_ON | QDSS_LDO_BYP;
 	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+	mb();
+	udelay(1);
 
 	/* Turn on memories */
 	val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
@@ -163,11 +210,6 @@
 	val &= ~Q6SS_CORE_ARES;
 	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
 
-	/* Disable clock gating for core and rclk */
-	val = readl_relaxed(drv->reg_base + QDSP6SS_CGC_OVERRIDE);
-	val |= Q6SS_CORE_RCLK_EN | Q6SS_CORE_CLK_EN;
-	writel_relaxed(val, drv->reg_base + QDSP6SS_CGC_OVERRIDE);
-
 	/* Turn on core clock */
 	val = readl_relaxed(drv->reg_base + QDSP6SS_GFMUX_CTL);
 	val |= Q6SS_CLK_ENA;
@@ -214,6 +256,35 @@
 	if (IS_ERR(drv->xo))
 		return ERR_CAST(drv->xo);
 
+	drv->vreg_cx = devm_regulator_get(&pdev->dev, "vdd_cx");
+	if (IS_ERR(drv->vreg_cx))
+		return ERR_CAST(drv->vreg_cx);
+
+	drv->vreg_pll = devm_regulator_get(&pdev->dev, "vdd_pll");
+	if (!IS_ERR(drv->vreg_pll)) {
+		int voltage;
+		ret = of_property_read_u32(pdev->dev.of_node, "qcom,vdd_pll",
+					   &voltage);
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to find vdd_pll voltage.\n");
+			return ERR_PTR(ret);
+		}
+
+		ret = regulator_set_voltage(drv->vreg_pll, voltage, voltage);
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to request vdd_pll voltage.\n");
+			return ERR_PTR(ret);
+		}
+
+		ret = regulator_set_optimum_mode(drv->vreg_pll, 10000);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to set vdd_pll mode.\n");
+			return ERR_PTR(ret);
+		}
+	} else {
+		 drv->vreg_pll = NULL;
+	}
+
 	desc->dev = &pdev->dev;
 
 	return drv;
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index d9ad6ae..0d986a6 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -31,7 +31,9 @@
 	void __iomem *axi_halt_base;
 	void __iomem *restart_reg;
 	struct regulator *vreg;
+	struct regulator *vreg_cx;
 	struct regulator *vreg_mx;
+	struct regulator *vreg_pll;
 	bool is_booted;
 	struct pil_desc desc;
 };
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index b63eb94..b0150d4 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -36,22 +36,34 @@
 #include "ramdump.h"
 
 /* VENUS WRAPPER registers */
+#define VENUS_WRAPPER_HW_VERSION			0x0
 #define VENUS_WRAPPER_CLOCK_CONFIG			0x4
-#define VENUS_WRAPPER_VBIF_SS_SEC_CPA_START_ADDR	0x1018
-#define VENUS_WRAPPER_VBIF_SS_SEC_CPA_END_ADDR		0x101C
-#define VENUS_WRAPPER_VBIF_SS_SEC_FW_START_ADDR		0x1020
-#define VENUS_WRAPPER_VBIF_SS_SEC_FW_END_ADDR		0x1024
+
+#define VENUS_WRAPPER_VBIF_SS_SEC_CPA_START_ADDR_v1	0x1018
+#define VENUS_WRAPPER_VBIF_SS_SEC_CPA_END_ADDR_v1	0x101C
+#define VENUS_WRAPPER_VBIF_SS_SEC_FW_START_ADDR_v1	0x1020
+#define VENUS_WRAPPER_VBIF_SS_SEC_FW_END_ADDR_v1	0x1024
+
+#define VENUS_WRAPPER_VBIF_SS_SEC_CPA_START_ADDR_v2	0x1020
+#define VENUS_WRAPPER_VBIF_SS_SEC_CPA_END_ADDR_v2	0x1024
+#define VENUS_WRAPPER_VBIF_SS_SEC_FW_START_ADDR_v2	0x1028
+#define VENUS_WRAPPER_VBIF_SS_SEC_FW_END_ADDR_v2	0x102C
+
 #define VENUS_WRAPPER_CPU_CLOCK_CONFIG			0x2000
 #define VENUS_WRAPPER_SW_RESET				0x3000
 
 /* VENUS VBIF registers */
-#define VENUS_VBIF_AXI_HALT_CTRL0			0x0
+#define VENUS_VBIF_CLKON				0x4
+#define VENUS_VBIF_CLKON_FORCE_ON			BIT(0)
+
+#define VENUS_VBIF_AXI_HALT_CTRL0			0x208
 #define VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ		BIT(0)
 
-#define VENUS_VBIF_AXI_HALT_CTRL1			0x4
+#define VENUS_VBIF_AXI_HALT_CTRL1			0x20C
 #define VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK		BIT(0)
 #define VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US		500000
 
+
 /* PIL proxy vote timeout */
 #define VENUS_PROXY_TIMEOUT				10000
 
@@ -77,11 +89,14 @@
 	struct iommu_domain *iommu_fw_domain;
 	int venus_domain_num;
 	bool is_booted;
+	bool hw_ver_checked;
 	void *ramdump_dev;
 	u32 fw_sz;
 	u32 fw_min_paddr;
 	u32 fw_max_paddr;
 	u32 bus_perf_client;
+	u32 hw_ver_major;
+	u32 hw_ver_minor;
 };
 
 #define subsys_to_drv(d) container_of(d, struct venus_data, subsys_desc)
@@ -271,6 +286,7 @@
 	void __iomem *wrapper_base = drv->venus_wrapper_base;
 	phys_addr_t pa = pil_get_entry_addr(pil);
 	unsigned long iova;
+	u32 ver, cpa_start_addr, cpa_end_addr, fw_start_addr, fw_end_addr;
 
 	/*
 	 * GDSC needs to remain on till Venus is shutdown. So, enable
@@ -283,17 +299,34 @@
 		return rc;
 	}
 
+	/* Get Venus version number */
+	if (!drv->hw_ver_checked) {
+		ver = readl_relaxed(wrapper_base + VENUS_WRAPPER_HW_VERSION);
+		drv->hw_ver_minor = (ver & 0x0FFF0000) >> 16;
+		drv->hw_ver_major = (ver & 0xF0000000) >> 28;
+		drv->hw_ver_checked = 1;
+	}
+
+	/* Get the cpa and fw start/end addr based on Venus version */
+	if (drv->hw_ver_major == 0x1 && drv->hw_ver_minor <= 1) {
+		cpa_start_addr = VENUS_WRAPPER_VBIF_SS_SEC_CPA_START_ADDR_v1;
+		cpa_end_addr = VENUS_WRAPPER_VBIF_SS_SEC_CPA_END_ADDR_v1;
+		fw_start_addr = VENUS_WRAPPER_VBIF_SS_SEC_FW_START_ADDR_v1;
+		fw_end_addr = VENUS_WRAPPER_VBIF_SS_SEC_FW_END_ADDR_v1;
+	} else {
+		cpa_start_addr = VENUS_WRAPPER_VBIF_SS_SEC_CPA_START_ADDR_v2;
+		cpa_end_addr = VENUS_WRAPPER_VBIF_SS_SEC_CPA_END_ADDR_v2;
+		fw_start_addr = VENUS_WRAPPER_VBIF_SS_SEC_FW_START_ADDR_v2;
+		fw_end_addr = VENUS_WRAPPER_VBIF_SS_SEC_FW_END_ADDR_v2;
+	}
+
 	/* Program CPA start and end address */
-	writel_relaxed(0, wrapper_base +
-			VENUS_WRAPPER_VBIF_SS_SEC_CPA_START_ADDR);
-	writel_relaxed(drv->fw_sz, wrapper_base +
-			VENUS_WRAPPER_VBIF_SS_SEC_CPA_END_ADDR);
+	writel_relaxed(0, wrapper_base + cpa_start_addr);
+	writel_relaxed(drv->fw_sz, wrapper_base + cpa_end_addr);
 
 	/* Program FW start and end address */
-	writel_relaxed(0, wrapper_base +
-			VENUS_WRAPPER_VBIF_SS_SEC_FW_START_ADDR);
-	writel_relaxed(drv->fw_sz, wrapper_base +
-			VENUS_WRAPPER_VBIF_SS_SEC_FW_END_ADDR);
+	writel_relaxed(0, wrapper_base + fw_start_addr);
+	writel_relaxed(drv->fw_sz, wrapper_base + fw_end_addr);
 
 	/* Enable all Venus internal clocks */
 	writel_relaxed(0, wrapper_base + VENUS_WRAPPER_CLOCK_CONFIG);
@@ -365,6 +398,17 @@
 
 	iommu_detach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
 
+	/*
+	 * Force the VBIF clk to be on to avoid AXI bridge halt ack failure
+	 * for certain Venus version.
+	 */
+	if (drv->hw_ver_major == 0x1 &&
+		(drv->hw_ver_minor == 0x2 || drv->hw_ver_minor == 0x3)) {
+		reg = readl_relaxed(vbif_base + VENUS_VBIF_CLKON);
+		reg |= VENUS_VBIF_CLKON_FORCE_ON;
+		writel_relaxed(reg, vbif_base + VENUS_VBIF_CLKON);
+	}
+
 	/* Halt AXI and AXI OCMEM VBIF Access */
 	reg = readl_relaxed(vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
 	reg |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
@@ -544,6 +588,7 @@
 	if (rc)
 		return rc;
 
+
 	desc->dev = &pdev->dev;
 	desc->owner = THIS_MODULE;
 	desc->proxy_timeout = VENUS_PROXY_TIMEOUT;
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index b034525..e7b4cea 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -35,7 +35,6 @@
 #define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
 #define SCSS_CPU1CORE_RESET 0xD80
 #define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
-#define BOOT_REMAP_ENABLE 0x01
 
 /*
  * control for which core is the next to come out of the secondary
@@ -82,7 +81,7 @@
 	spin_unlock(&boot_lock);
 }
 
-static int __cpuinit release_secondary_sim(unsigned long base, int cpu)
+static int __cpuinit release_secondary_sim(unsigned long base, unsigned int cpu)
 {
 	void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
 	if (!base_ptr)
@@ -112,7 +111,8 @@
 	return 0;
 }
 
-static int __cpuinit msm8960_release_secondary(unsigned long base, int cpu)
+static int __cpuinit msm8960_release_secondary(unsigned long base,
+						unsigned int cpu)
 {
 	void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
 	if (!base_ptr)
@@ -143,7 +143,8 @@
 	return 0;
 }
 
-static int __cpuinit msm8974_release_secondary(unsigned long base, int cpu)
+static int __cpuinit msm8974_release_secondary(unsigned long base,
+						unsigned int cpu)
 {
 	void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
 	if (!base_ptr)
@@ -168,6 +169,41 @@
 	return 0;
 }
 
+static int __cpuinit arm_release_secondary(unsigned long base, unsigned int cpu)
+{
+	void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+	if (!base_ptr)
+		return -ENODEV;
+
+	writel_relaxed(0x00000033, base_ptr+0x04);
+	mb();
+
+	writel_relaxed(0x10000001, base_ptr+0x14);
+	mb();
+	udelay(2);
+
+	writel_relaxed(0x00000031, base_ptr+0x04);
+	mb();
+
+	writel_relaxed(0x00000039, base_ptr+0x04);
+	mb();
+	udelay(2);
+
+	writel_relaxed(0x00020038, base_ptr+0x04);
+	mb();
+	udelay(2);
+
+
+	writel_relaxed(0x00020008, base_ptr+0x04);
+	mb();
+
+	writel_relaxed(0x00020088, base_ptr+0x04);
+	mb();
+
+	iounmap(base_ptr);
+	return 0;
+}
+
 static int __cpuinit release_from_pen(unsigned int cpu)
 {
 	unsigned long timeout;
@@ -248,9 +284,7 @@
 	if (per_cpu(cold_boot_done, cpu) == false) {
 		if (machine_is_msm8974_sim() || machine_is_mpq8092_sim())
 			release_secondary_sim(0xf9088000, cpu);
-		else if (machine_is_msm8974_rumi())
-			return 0;
-		else
+		else if (!machine_is_msm8974_rumi())
 			msm8974_release_secondary(0xf9088000, cpu);
 
 		per_cpu(cold_boot_done, cpu) = true;
@@ -265,6 +299,8 @@
 	if (per_cpu(cold_boot_done, cpu) == false) {
 		if (machine_is_msm8226_sim() || machine_is_msm8610_sim())
 			release_secondary_sim(0xf9088000, cpu);
+		else if (!machine_is_msm8610_rumi())
+			arm_release_secondary(0xf9088000, cpu);
 
 		per_cpu(cold_boot_done, cpu) = true;
 	}
@@ -335,27 +371,9 @@
 		pr_warn("Failed to set CPU boot address\n");
 }
 
-static void __init arm_platform_smp_prepare_cpus(unsigned int max_cpus)
-{
-	void *remap_ptr = ioremap_nocache(0xF9010000, SZ_4K);
-	if (!remap_ptr) {
-		pr_err("Failed to ioremap for secondary cores\n");
-		return;
-	}
-
-	/*
-	 * Write the address of secondary startup into boot remapper
-	 * register and enable boot remapping.
-	 */
-	__raw_writel((virt_to_phys(msm_secondary_startup)|BOOT_REMAP_ENABLE),
-			(remap_ptr + 0x4));
-	mb();
-	iounmap(remap_ptr);
-}
-
 struct smp_operations arm_smp_ops __initdata = {
 	.smp_init_cpus = arm_smp_init_cpus,
-	.smp_prepare_cpus = arm_platform_smp_prepare_cpus,
+	.smp_prepare_cpus = msm_platform_smp_prepare_cpus,
 	.smp_secondary_init = platform_secondary_init,
 	.smp_boot_secondary = arm_boot_secondary,
 	.cpu_kill = platform_cpu_kill,
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index af6f8af..f7f2fef 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -25,6 +25,7 @@
 #include <linux/suspend.h>
 #include <linux/tick.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/krait-regulator.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
 #include <mach/system.h>
@@ -361,12 +362,15 @@
 static void msm_pm_config_hw_after_retention(void)
 {
 	int ret;
+
 	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
 	WARN_ON(ret);
+	krait_power_mdd_enable(smp_processor_id(), false);
 }
 
 static void msm_pm_config_hw_before_retention(void)
 {
+	krait_power_mdd_enable(smp_processor_id(), true);
 	return;
 }
 
@@ -505,10 +509,6 @@
 	void *entry;
 	bool collapsed = 0;
 	int ret;
-	unsigned int saved_gic_cpu_ctrl;
-
-	saved_gic_cpu_ctrl = readl_relaxed(MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
-	mb();
 
 	if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: notify_rpm %d\n",
@@ -526,22 +526,12 @@
 		pr_info("CPU%u: %s: program vector to %p\n",
 			cpu, __func__, entry);
 
-#ifdef CONFIG_VFP
-	vfp_pm_suspend();
-#endif
 	collapsed = msm_pm_collapse();
 
 	msm_pm_boot_config_after_pc(cpu);
 
 	if (collapsed) {
-#ifdef CONFIG_VFP
-		vfp_pm_resume();
-#endif
 		cpu_init();
-		writel(0xF0, MSM_QGIC_CPU_BASE + GIC_CPU_PRIMASK);
-		writel_relaxed(saved_gic_cpu_ctrl,
-				MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
-		mb();
 		local_fiq_enable();
 	}
 
@@ -670,7 +660,7 @@
 	int64_t time = 0;
 
 	if (msm_pm_init_data.use_sync_timer)
-		return sched_clock();
+		return ktime_to_ns(ktime_get());
 
 	time = msm_timer_get_sclk_time(period);
 	if (!time)
@@ -682,7 +672,7 @@
 static int64_t msm_pm_timer_exit_suspend(int64_t time, int64_t period)
 {
 	if (msm_pm_init_data.use_sync_timer)
-		return sched_clock() - time;
+		return ktime_to_ns(ktime_get()) - time;
 
 	if (time != 0) {
 		int64_t end_time = msm_timer_get_sclk_time(NULL);
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 5520cc6..4c106c5 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -55,7 +55,7 @@
 	int client_id;
 };
 
-static const struct apr_svc_table svc_tbl_audio[] = {
+static const struct apr_svc_table svc_tbl_qdsp6[] = {
 	{
 		.name = "AFE",
 		.idx = 0,
@@ -110,6 +110,12 @@
 		.id = APR_SVC_USM,
 		.client_id = APR_CLIENT_AUDIO,
 	},
+	{
+		.name = "VIDC",
+		.idx = 9,
+		.id = APR_SVC_VIDC,
+		.client_id = APR_CLIENT_AUDIO,
+	},
 };
 
 static struct apr_svc_table svc_tbl_voice[] = {
@@ -387,6 +393,8 @@
 		    svc == APR_SVC_TEST_CLIENT || svc == APR_SVC_ADSP_MVM ||
 		    svc == APR_SVC_ADSP_CVS || svc == APR_SVC_ADSP_CVP)
 			clnt = APR_CLIENT_AUDIO;
+		else if (svc == APR_SVC_VIDC)
+			clnt = APR_CLIENT_AUDIO;
 		else {
 			pr_err("APR: Wrong svc :%d\n", svc);
 			return;
@@ -441,8 +449,8 @@
 	int ret = 0;
 
 	if (dest_id == APR_DEST_QDSP6) {
-		tbl = (struct apr_svc_table *)&svc_tbl_audio;
-		size = ARRAY_SIZE(svc_tbl_audio);
+		tbl = (struct apr_svc_table *)&svc_tbl_qdsp6;
+		size = ARRAY_SIZE(svc_tbl_qdsp6);
 	} else {
 		tbl = (struct apr_svc_table *)&svc_tbl_voice;
 		size = ARRAY_SIZE(svc_tbl_voice);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 176f7a6..172c7eb 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -832,11 +832,12 @@
 				1);
 	if (rc < 0) {
 		pr_err("%s[%p]: memory map failed\n", __func__, audio);
-		goto ion_error;
+		goto mmap_error;
 	} else {
 		goto end;
 	}
-
+mmap_error:
+	list_del(&region->list);
 ion_error:
 	ion_unmap_kernel(audio->client, handle);
 map_error:
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_common.h b/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
index 4093ada..06369c2 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
@@ -11,6 +11,7 @@
  *
 */
 
+
 /* For Decoders */
 #ifndef __Q6_AUDIO_COMMON_H__
 #define __Q6_AUDIO_COMMON_H__
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index 822bc07..7f09a56 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.c
@@ -104,6 +104,7 @@
 	unsigned long addr = 0;
 	size_t copy_size = 0;
 	int ret = 0;
+	loff_t orig_pos = *pos;
 
 	if ((filep->f_flags & O_NONBLOCK) && !rd_dev->data_ready)
 		return -EAGAIN;
@@ -113,9 +114,10 @@
 		return ret;
 
 	if (*pos < rd_dev->elfcore_size) {
-		copy_size = min(rd_dev->elfcore_size, count);
+		copy_size = rd_dev->elfcore_size - *pos;
+		copy_size = min(copy_size, count);
 
-		if (copy_to_user(buf, rd_dev->elfcore_buf, copy_size)) {
+		if (copy_to_user(buf, rd_dev->elfcore_buf + *pos, copy_size)) {
 			ret = -EFAULT;
 			goto ramdump_done;
 		}
@@ -165,7 +167,7 @@
 	pr_debug("Ramdump(%s): Read %d bytes from address %lx.",
 			rd_dev->name, copy_size, addr);
 
-	return copy_size;
+	return *pos - orig_pos;
 
 ramdump_done:
 	rd_dev->data_ready = 0;
diff --git a/arch/arm/mach-msm/rmt_storage_client.c b/arch/arm/mach-msm/rmt_storage_client.c
index c4530a9..a4562e9 100644
--- a/arch/arm/mach-msm/rmt_storage_client.c
+++ b/arch/arm/mach-msm/rmt_storage_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2013, 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
@@ -1357,33 +1357,63 @@
  * for encryption and sync.
  */
 #define MAX_GET_SYNC_STATUS_TRIES 200
-#define GET_SYNC_STATUS_SLEEP_INTERVAL 20
+#define RMT_SLEEP_INTERVAL_MS 20
 static int rmt_storage_reboot_call(
 	struct notifier_block *this, unsigned long code, void *cmd)
 {
 	int ret, count = 0;
 
+	/*
+	 * In recovery mode RMT daemon is not available,
+	 * so return from reboot notifier without initiating
+	 * force sync.
+	 */
+	spin_lock(&rmc->lock);
+	if (!rmc->open_excl) {
+		spin_unlock(&rmc->lock);
+		msm_rpc_unregister_client(rmt_srv->rpc_client);
+		return NOTIFY_DONE;
+	}
+
+	spin_unlock(&rmc->lock);
 	switch (code) {
 	case SYS_RESTART:
 	case SYS_HALT:
 	case SYS_POWER_OFF:
-		pr_info("%s: Force RMT storage final sync...\n", __func__);
+		pr_info("%s: Sending force-sync RPC request\n", __func__);
 		ret = rmt_storage_force_sync(rmt_srv->rpc_client);
 		if (ret)
 			break;
 
 		do {
 			count++;
-			msleep(GET_SYNC_STATUS_SLEEP_INTERVAL);
+			msleep(RMT_SLEEP_INTERVAL_MS);
 			ret = rmt_storage_get_sync_status(rmt_srv->rpc_client);
 		} while (ret != 1 && count < MAX_GET_SYNC_STATUS_TRIES);
 
 		if (ret == 1)
-			pr_info("%s: RMT storage sync successful.\n", __func__);
+			pr_info("%s: Final-sync successful\n", __func__);
 		else
-			pr_err("%s: RMT storage sync failed.\n", __func__);
+			pr_err("%s: Final-sync failed\n", __func__);
 
-		pr_info("%s: Un register RMT storage client.\n", __func__);
+		/*
+		 * Check if any ongoing efs_sync triggered just before force
+		 * sync is pending. If so, wait for 4sec for completing efs_sync
+		 * before unregistring client.
+		 */
+		count = 0;
+		while (count < MAX_GET_SYNC_STATUS_TRIES) {
+			if (atomic_read(&rmc->wcount) == 0) {
+				break;
+			} else {
+				count++;
+				msleep(RMT_SLEEP_INTERVAL_MS);
+			}
+		}
+		if (atomic_read(&rmc->wcount))
+			pr_err("%s: Efs_sync still incomplete\n", __func__);
+
+		pr_info("%s: Un-register RMT storage client\n", __func__);
 		msm_rpc_unregister_client(rmt_srv->rpc_client);
 		break;
 
diff --git a/arch/arm/mach-msm/rpm_log.c b/arch/arm/mach-msm/rpm_log.c
index 76eb1d0..a2c74a5 100644
--- a/arch/arm/mach-msm/rpm_log.c
+++ b/arch/arm/mach-msm/rpm_log.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2011, 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -43,6 +44,10 @@
 /* number of ms to wait between checking for new messages in the RPM log */
 #define RECHECK_TIME (50)
 
+#define VERSION_8974 0x1000
+#define RPM_ULOG_LENGTH_SHIFT 16
+#define RPM_ULOG_LENGTH_MASK  0xFFFF0000
+
 struct msm_rpm_log_buffer {
 	char *data;
 	u32 len;
@@ -109,11 +114,14 @@
 	while (tail_idx - head_idx > 0 && tail_idx - *read_idx > 0) {
 		head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
 					    MSM_RPM_LOG_HEAD);
+		tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+				    MSM_RPM_LOG_TAIL);
 		/* check if the message to be read is valid */
 		if (tail_idx - *read_idx > tail_idx - head_idx) {
 			*read_idx = head_idx;
 			continue;
 		}
+
 		/*
 		 * Ensure that all indices are 4 byte aligned.
 		 * This conditions is required to interact with a ULog buffer
@@ -123,7 +131,16 @@
 			break;
 
 		msg_len = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER,
-					(*read_idx >> 2) & pdata->log_len_mask);
+				((*read_idx) & pdata->log_len_mask) >> 2);
+
+		/* Message length for 8974 is first 2 bytes.
+		 * Exclude message length and format from message length.
+		 */
+		if (pdata->version == VERSION_8974) {
+			msg_len = (msg_len & RPM_ULOG_LENGTH_MASK) >>
+					RPM_ULOG_LENGTH_SHIFT;
+			msg_len -= 4;
+		}
 
 		/* handle messages that claim to be longer than the log */
 		if (PADDED_LENGTH(msg_len) > tail_idx - *read_idx - 4)
@@ -142,8 +159,8 @@
 			if (IS_ALIGNED(i, 4))
 				*((u32 *)temp) = msm_rpm_log_read(pdata,
 						MSM_RPM_LOG_PAGE_BUFFER,
-						((*read_idx + 4 + i) >> 2) &
-							pdata->log_len_mask);
+						((*read_idx + 4 + i) &
+						pdata->log_len_mask) >> 2);
 
 			pos += scnprintf(msg_buffer + pos, buf_len - pos,
 					 "0x%02X, ", temp[i & 0x03]);
@@ -153,6 +170,8 @@
 
 		head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
 					    MSM_RPM_LOG_HEAD);
+		tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+				    MSM_RPM_LOG_TAIL);
 
 		/* roll back if message that was read is not still valid */
 		if (tail_idx - *read_idx > tail_idx - head_idx)
@@ -226,7 +245,7 @@
 
 /*
  * msm_rpm_log_file_open() - Allows a new reader to open the RPM log virtual
- *                           file
+ *			      file
  *
  * One local buffer is kmalloc'ed for each reader, so no resource sharing has
  * to take place (besides the read only access to the RPM log buffer).
@@ -290,23 +309,158 @@
 {
 	struct dentry *dent;
 	struct msm_rpm_log_platform_data *pdata;
+	struct resource *res = NULL;
+	struct device_node *node = NULL;
+	phys_addr_t page_buffer_address, rpm_addr_phys;
+	int ret = 0;
+	char *key = NULL;
+	uint32_t val = 0;
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata)
-		return -EINVAL;
+	node = pdev->dev.of_node;
 
-	pdata->reg_base = ioremap(pdata->phys_addr_base, pdata->phys_size);
-	if (!pdata->reg_base) {
-		pr_err("%s: ERROR could not ioremap: start=%p, len=%u\n",
-			__func__, (void *) pdata->phys_addr_base,
-			pdata->phys_size);
-		return -EBUSY;
+	if (node) {
+		pdata = kzalloc(sizeof(struct msm_rpm_log_platform_data),
+				GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			kfree(pdata);
+			return -EINVAL;
+		}
+
+		pdata->phys_addr_base = res->start;
+		pdata->phys_size = resource_size(res);
+
+		pdata->reg_base = ioremap_nocache(pdata->phys_addr_base,
+					pdata->phys_size);
+		if (!pdata->reg_base) {
+			pr_err("%s: ERROR could not ioremap: start=%p, len=%u\n",
+				__func__, (void *) pdata->phys_addr_base,
+				pdata->phys_size);
+			kfree(pdata);
+			return -EBUSY;
+		}
+		/* Read various parameters from the header if the
+		 * version of the RPM Ulog is 0x1000. This version
+		 * corresponds to the node in the rpm header which
+		 * holds RPM log on 8974.
+		 *
+		 * offset-page-buffer-addr: At this offset header
+		 * contains address of the location where raw log
+		 * starts
+		 * offset-log-len: At this offset header contains
+		 * the length of the log buffer.
+		 * offset-log-len-mask: At this offset header contains
+		 * the log length mask for the buffer.
+		 * offset-page-indices: At this offset header contains
+		 * the index for writer. */
+
+		key = "qcom,offset-version";
+		ret = of_property_read_u32(node, key, &val);
+		if (ret) {
+			pr_err("%s: Error in name %s key %s\n",
+				__func__, node->full_name, key);
+			ret = -EFAULT;
+			goto fail;
+		}
+
+		pdata->version = readl_relaxed(pdata->reg_base + val);
+		if (pdata->version == VERSION_8974) {
+			key = "qcom,rpm-addr-phys";
+			ret = of_property_read_u32(node, key, &val);
+			if (ret) {
+				pr_err("%s: Error in name %s key %s\n",
+					__func__, node->full_name, key);
+				ret = -EFAULT;
+				goto fail;
+			}
+
+			rpm_addr_phys = val;
+
+			key = "qcom,offset-page-buffer-addr";
+			ret = of_property_read_u32(node, key, &val);
+			if (ret) {
+				pr_err("%s: Error in name %s key %s\n",
+					__func__, node->full_name, key);
+				ret = -EFAULT;
+				goto fail;
+			}
+
+			page_buffer_address = rpm_addr_phys +
+				readl_relaxed(pdata->reg_base + val);
+			pdata->reg_offsets[MSM_RPM_LOG_PAGE_BUFFER] =
+				page_buffer_address - pdata->phys_addr_base;
+
+			key = "qcom,offset-log-len";
+			ret = of_property_read_u32(node, key, &val);
+			if (ret) {
+				pr_err("%s: Error in name %s key %s\n",
+					__func__, node->full_name, key);
+				ret = -EFAULT;
+				goto fail;
+			}
+			pdata->log_len = readl_relaxed(pdata->reg_base + val);
+
+			if (pdata->log_len > pdata->phys_size) {
+				pr_err("%s: Error phy size: %d should be atleast log length: %d\n",
+					__func__, pdata->phys_size,
+					pdata->log_len);
+
+				ret = -EINVAL;
+				goto fail;
+			}
+
+			key = "qcom,offset-log-len-mask";
+			ret = of_property_read_u32(node, key, &val);
+			if (ret) {
+				pr_err("%s: Error in name %s key %s\n",
+					__func__, node->full_name, key);
+				ret = -EFAULT;
+				goto fail;
+			}
+			pdata->log_len_mask = readl_relaxed(pdata->reg_base
+					+ val);
+
+			key = "qcom,offset-page-indices";
+			ret = of_property_read_u32(node, key, &val);
+			if (ret) {
+				pr_err("%s: Error in name %s key %s\n",
+					__func__, node->full_name, key);
+				ret = -EFAULT;
+				goto fail;
+			}
+			pdata->reg_offsets[MSM_RPM_LOG_PAGE_INDICES] =
+						val;
+		} else{
+			ret = -EINVAL;
+			goto fail;
+		}
+
+	} else{
+		pdata = pdev->dev.platform_data;
+		if (!pdata)
+			return -EINVAL;
+
+		pdata->reg_base = ioremap(pdata->phys_addr_base,
+				pdata->phys_size);
+		if (!pdata->reg_base) {
+			pr_err("%s: ERROR could not ioremap: start=%p, len=%u\n",
+				__func__, (void *) pdata->phys_addr_base,
+				pdata->phys_size);
+			return -EBUSY;
+		}
 	}
 
 	dent = debugfs_create_file("rpm_log", S_IRUGO, NULL,
-			pdev->dev.platform_data, &msm_rpm_log_file_fops);
+			pdata, &msm_rpm_log_file_fops);
 	if (!dent) {
 		pr_err("%s: ERROR debugfs_create_file failed\n", __func__);
+		if (pdata->version == VERSION_8974) {
+			ret = -ENOMEM;
+			goto fail;
+		}
 		return -ENOMEM;
 	}
 
@@ -314,6 +468,11 @@
 
 	pr_notice("%s: OK\n", __func__);
 	return 0;
+
+fail:
+	iounmap(pdata->reg_base);
+	kfree(pdata);
+	return ret;
 }
 
 static int __devexit msm_rpm_log_remove(struct platform_device *pdev)
@@ -333,12 +492,18 @@
 	return 0;
 }
 
+static struct of_device_id rpm_log_table[] = {
+	       {.compatible = "qcom,rpm-log"},
+	       {},
+};
+
 static struct platform_driver msm_rpm_log_driver = {
 	.probe		= msm_rpm_log_probe,
 	.remove		= __devexit_p(msm_rpm_log_remove),
 	.driver		= {
 		.name = "msm_rpm_log",
 		.owner = THIS_MODULE,
+		.of_match_table = rpm_log_table,
 	},
 };
 
diff --git a/arch/arm/mach-msm/rpm_log.h b/arch/arm/mach-msm/rpm_log.h
index 95639cb..f75937e 100644
--- a/arch/arm/mach-msm/rpm_log.h
+++ b/arch/arm/mach-msm/rpm_log.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010, 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,6 +28,7 @@
 	u32 log_len_mask;
 	phys_addr_t phys_addr_base;
 	u32 phys_size;
+	u32 version;
 	void __iomem *reg_base;
 };
 
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index eda8950..8725544 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -44,6 +44,7 @@
 #include <mach/subsystem_notif.h>
 #include <mach/socinfo.h>
 #include <mach/proc_comm.h>
+#include <mach/msm_ipc_logging.h>
 #include <asm/cacheflush.h>
 
 #include "smd_private.h"
@@ -190,33 +191,42 @@
 	SMSM_APPS_DEM_I = 3,
 };
 
-static int msm_smd_debug_mask;
+static int msm_smd_debug_mask = MSM_SMx_POWER_INFO;
 module_param_named(debug_mask, msm_smd_debug_mask,
 		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+static void *smd_log_ctx;
+#define NUM_LOG_PAGES 4
+
+#define IPC_LOG(level, x...) do { \
+	if (smd_log_ctx) \
+		ipc_log_string(smd_log_ctx, x); \
+	else \
+		printk(level x); \
+	} while (0)
 
 #if defined(CONFIG_MSM_SMD_DEBUG)
 #define SMD_DBG(x...) do {				\
 		if (msm_smd_debug_mask & MSM_SMD_DEBUG) \
-			printk(KERN_DEBUG x);		\
+			IPC_LOG(KERN_DEBUG, x);		\
 	} while (0)
 
 #define SMSM_DBG(x...) do {					\
 		if (msm_smd_debug_mask & MSM_SMSM_DEBUG)	\
-			printk(KERN_DEBUG x);			\
+			IPC_LOG(KERN_DEBUG, x);		\
 	} while (0)
 
 #define SMD_INFO(x...) do {			 	\
 		if (msm_smd_debug_mask & MSM_SMD_INFO)	\
-			printk(KERN_INFO x);		\
+			IPC_LOG(KERN_INFO, x);		\
 	} while (0)
 
 #define SMSM_INFO(x...) do {				\
 		if (msm_smd_debug_mask & MSM_SMSM_INFO) \
-			printk(KERN_INFO x);		\
+			IPC_LOG(KERN_INFO, x);		\
 	} while (0)
 #define SMx_POWER_INFO(x...) do {				\
 		if (msm_smd_debug_mask & MSM_SMx_POWER_INFO) \
-			printk(KERN_INFO x);		\
+			IPC_LOG(KERN_INFO, x);		\
 	} while (0)
 #else
 #define SMD_DBG(x...) do { } while (0)
@@ -373,6 +383,8 @@
 static RAW_NOTIFIER_HEAD(smd_module_init_notifier_list);
 static DEFINE_MUTEX(smd_module_init_notifier_lock);
 static void smd_module_init_notify(uint32_t state, void *data);
+static int smd_stream_write_avail(struct smd_channel *ch);
+static int smd_stream_read_avail(struct smd_channel *ch);
 
 static inline void smd_write_intr(unsigned int val,
 				const void __iomem *addr)
@@ -381,10 +393,34 @@
 	__raw_writel(val, addr);
 }
 
-static inline void notify_modem_smd(void)
+static inline void log_notify(uint32_t subsystem, smd_channel_t *ch)
+{
+	const char *subsys = smd_edge_to_subsystem(subsystem);
+
+	(void) subsys;
+
+	if (!ch)
+		SMx_POWER_INFO("Apps->%s\n", subsys);
+	else
+		SMx_POWER_INFO(
+			"Apps->%s ch%d '%s': tx%d/rx%d %dr/%dw : %dr/%dw\n",
+			subsys, ch->n, ch->name,
+			ch->fifo_size -
+				(smd_stream_write_avail(ch) + 1),
+			smd_stream_read_avail(ch),
+			ch->half_ch->get_tail(ch->send),
+			ch->half_ch->get_head(ch->send),
+			ch->half_ch->get_tail(ch->recv),
+			ch->half_ch->get_head(ch->recv)
+			);
+}
+
+static inline void notify_modem_smd(smd_channel_t *ch)
 {
 	static const struct interrupt_config_item *intr
 	   = &private_intr_config[SMD_MODEM].smd;
+
+	log_notify(SMD_APPS_MODEM, ch);
 	if (intr->out_base) {
 		++interrupt_stats[SMD_MODEM].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
@@ -395,10 +431,12 @@
 	}
 }
 
-static inline void notify_dsp_smd(void)
+static inline void notify_dsp_smd(smd_channel_t *ch)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_Q6].smd;
+
+	log_notify(SMD_APPS_QDSP, ch);
 	if (intr->out_base) {
 		++interrupt_stats[SMD_Q6].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
@@ -409,10 +447,12 @@
 	}
 }
 
-static inline void notify_dsps_smd(void)
+static inline void notify_dsps_smd(smd_channel_t *ch)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_DSPS].smd;
+
+	log_notify(SMD_APPS_DSPS, ch);
 	if (intr->out_base) {
 		++interrupt_stats[SMD_DSPS].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
@@ -423,11 +463,12 @@
 	}
 }
 
-static inline void notify_wcnss_smd(void)
+static inline void notify_wcnss_smd(struct smd_channel *ch)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_WCNSS].smd;
 
+	log_notify(SMD_APPS_WCNSS, ch);
 	if (intr->out_base) {
 		++interrupt_stats[SMD_WCNSS].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
@@ -438,12 +479,13 @@
 	}
 }
 
-static inline void notify_rpm_smd(void)
+static inline void notify_rpm_smd(smd_channel_t *ch)
 {
 	static const struct interrupt_config_item *intr
 		= &private_intr_config[SMD_RPM].smd;
 
 	if (intr->out_base) {
+		log_notify(SMD_APPS_RPM, ch);
 		++interrupt_stats[SMD_RPM].smd_out_config_count;
 		smd_write_intr(intr->out_bit_pos,
 		intr->out_base + intr->out_offset);
@@ -656,47 +698,6 @@
 	struct smd_half_channel_word_access ch1;
 };
 
-struct smd_channel {
-	volatile void __iomem *send; /* some variant of smd_half_channel */
-	volatile void __iomem *recv; /* some variant of smd_half_channel */
-	unsigned char *send_data;
-	unsigned char *recv_data;
-	unsigned fifo_size;
-	unsigned fifo_mask;
-	struct list_head ch_list;
-
-	unsigned current_packet;
-	unsigned n;
-	void *priv;
-	void (*notify)(void *priv, unsigned flags);
-
-	int (*read)(smd_channel_t *ch, void *data, int len, int user_buf);
-	int (*write)(smd_channel_t *ch, const void *data, int len,
-			int user_buf);
-	int (*read_avail)(smd_channel_t *ch);
-	int (*write_avail)(smd_channel_t *ch);
-	int (*read_from_cb)(smd_channel_t *ch, void *data, int len,
-			int user_buf);
-
-	void (*update_state)(smd_channel_t *ch);
-	unsigned last_state;
-	void (*notify_other_cpu)(void);
-
-	char name[20];
-	struct platform_device pdev;
-	unsigned type;
-
-	int pending_pkt_sz;
-
-	char is_pkt_ch;
-
-	/*
-	 * private internal functions to access *send and *recv.
-	 * never to be exported outside of smd
-	 */
-	struct smd_half_channel_access *half_ch;
-};
-
 struct edge_to_pid {
 	uint32_t	local_pid;
 	uint32_t	remote_pid;
@@ -973,7 +974,7 @@
 	struct smd_alloc_elm *shared;
 	unsigned long flags;
 
-	SMD_DBG("%s: starting reset\n", __func__);
+	SMx_POWER_INFO("%s: starting reset\n", __func__);
 
 	/* release any held spinlocks */
 	remote_spin_release(&remote_spinlock, restart_pid);
@@ -1014,11 +1015,11 @@
 	/* notify SMD processors */
 	mb();
 	smd_fake_irq_handler(0);
-	notify_modem_smd();
-	notify_dsp_smd();
-	notify_dsps_smd();
-	notify_wcnss_smd();
-	notify_rpm_smd();
+	notify_modem_smd(NULL);
+	notify_dsp_smd(NULL);
+	notify_dsps_smd(NULL);
+	notify_wcnss_smd(NULL);
+	notify_rpm_smd(NULL);
 
 	/* change all remote states to CLOSED */
 	mutex_lock(&smd_probe_lock);
@@ -1030,13 +1031,13 @@
 	/* notify SMD processors */
 	mb();
 	smd_fake_irq_handler(0);
-	notify_modem_smd();
-	notify_dsp_smd();
-	notify_dsps_smd();
-	notify_wcnss_smd();
-	notify_rpm_smd();
+	notify_modem_smd(NULL);
+	notify_dsp_smd(NULL);
+	notify_dsps_smd(NULL);
+	notify_wcnss_smd(NULL);
+	notify_rpm_smd(NULL);
 
-	SMD_DBG("%s: finished reset\n", __func__);
+	SMx_POWER_INFO("%s: finished reset\n", __func__);
 }
 
 /* how many bytes are available for reading */
@@ -1214,7 +1215,7 @@
 	}
 	ch->half_ch->set_state(ch->send, n);
 	ch->half_ch->set_fSTATE(ch->send, 1);
-	ch->notify_other_cpu();
+	ch->notify_other_cpu(ch);
 }
 
 static void do_smd_probe(void)
@@ -1290,7 +1291,8 @@
 	spin_unlock_irqrestore(&smd_lock, flags);
 }
 
-static void handle_smd_irq(struct list_head *list, void (*notify)(void))
+static void handle_smd_irq(struct list_head *list,
+		void (*notify)(smd_channel_t *ch))
 {
 	unsigned long flags;
 	struct smd_channel *ch;
@@ -1325,10 +1327,18 @@
 		}
 		if (ch_flags & 0x3) {
 			ch->update_state(ch);
-			SMx_POWER_INFO("SMD ch%d '%s' Data event r%d/w%d\n",
-					ch->n, ch->name,
-					ch->read_avail(ch),
-					ch->fifo_size - ch->write_avail(ch));
+			SMx_POWER_INFO(
+				"SMD ch%d '%s' Data event 0x%x tx%d/rx%d %dr/%dw : %dr/%dw\n",
+				ch->n, ch->name,
+				ch_flags,
+				ch->fifo_size -
+					(smd_stream_write_avail(ch) + 1),
+				smd_stream_read_avail(ch),
+				ch->half_ch->get_tail(ch->send),
+				ch->half_ch->get_head(ch->send),
+				ch->half_ch->get_tail(ch->recv),
+				ch->half_ch->get_head(ch->recv)
+				);
 			ch->notify(ch->priv, SMD_EVENT_DATA);
 		}
 		if (ch_flags & 0x4 && !state_change) {
@@ -1341,9 +1351,18 @@
 	do_smd_probe();
 }
 
+static inline void log_irq(uint32_t subsystem)
+{
+	const char *subsys = smd_edge_to_subsystem(subsystem);
+
+	(void) subsys;
+
+	SMx_POWER_INFO("SMD Int %s->Apps\n", subsys);
+}
+
 static irqreturn_t smd_modem_irq_handler(int irq, void *data)
 {
-	SMx_POWER_INFO("SMD Int Modem->Apps\n");
+	log_irq(SMD_APPS_MODEM);
 	++interrupt_stats[SMD_MODEM].smd_in_count;
 	handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
 	handle_smd_irq_closing_list();
@@ -1352,7 +1371,7 @@
 
 static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
 {
-	SMx_POWER_INFO("SMD Int LPASS->Apps\n");
+	log_irq(SMD_APPS_QDSP);
 	++interrupt_stats[SMD_Q6].smd_in_count;
 	handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
 	handle_smd_irq_closing_list();
@@ -1361,7 +1380,7 @@
 
 static irqreturn_t smd_dsps_irq_handler(int irq, void *data)
 {
-	SMx_POWER_INFO("SMD Int DSPS->Apps\n");
+	log_irq(SMD_APPS_DSPS);
 	++interrupt_stats[SMD_DSPS].smd_in_count;
 	handle_smd_irq(&smd_ch_list_dsps, notify_dsps_smd);
 	handle_smd_irq_closing_list();
@@ -1370,7 +1389,7 @@
 
 static irqreturn_t smd_wcnss_irq_handler(int irq, void *data)
 {
-	SMx_POWER_INFO("SMD Int WCNSS->Apps\n");
+	log_irq(SMD_APPS_WCNSS);
 	++interrupt_stats[SMD_WCNSS].smd_in_count;
 	handle_smd_irq(&smd_ch_list_wcnss, notify_wcnss_smd);
 	handle_smd_irq_closing_list();
@@ -1379,7 +1398,7 @@
 
 static irqreturn_t smd_rpm_irq_handler(int irq, void *data)
 {
-	SMx_POWER_INFO("SMD Int RPM->Apps\n");
+	log_irq(SMD_APPS_RPM);
 	++interrupt_stats[SMD_RPM].smd_in_count;
 	handle_smd_irq(&smd_ch_list_rpm, notify_rpm_smd);
 	handle_smd_irq_closing_list();
@@ -1514,7 +1533,7 @@
 	}
 
 	if (orig_len - len)
-		ch->notify_other_cpu();
+		ch->notify_other_cpu(ch);
 
 	return orig_len - len;
 }
@@ -1566,7 +1585,7 @@
 	r = ch_read(ch, data, len, user_buf);
 	if (r > 0)
 		if (!read_intr_blocked(ch))
-			ch->notify_other_cpu();
+			ch->notify_other_cpu(ch);
 
 	return r;
 }
@@ -1585,7 +1604,7 @@
 	r = ch_read(ch, data, len, user_buf);
 	if (r > 0)
 		if (!read_intr_blocked(ch))
-			ch->notify_other_cpu();
+			ch->notify_other_cpu(ch);
 
 	spin_lock_irqsave(&smd_lock, flags);
 	ch->current_packet -= r;
@@ -1609,7 +1628,7 @@
 	r = ch_read(ch, data, len, user_buf);
 	if (r > 0)
 		if (!read_intr_blocked(ch))
-			ch->notify_other_cpu();
+			ch->notify_other_cpu(ch);
 
 	ch->current_packet -= r;
 	update_packet_state(ch);
@@ -1767,7 +1786,7 @@
 	return 0;
 }
 
-static inline void notify_loopback_smd(void)
+static inline void notify_loopback_smd(smd_channel_t *ch_notif)
 {
 	unsigned long flags;
 	struct smd_channel *ch;
@@ -2290,7 +2309,7 @@
 
 	ch->half_ch->set_fSTATE(ch->send, 1);
 	barrier();
-	ch->notify_other_cpu();
+	ch->notify_other_cpu(ch);
 
 	return 0;
 }
@@ -3933,6 +3952,12 @@
 	if (registered)
 		return 0;
 
+	smd_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smd");
+	if (!smd_log_ctx) {
+		pr_err("%s: unable to create logging context\n", __func__);
+		msm_smd_debug_mask = 0;
+	}
+
 	registered = true;
 	rc = remote_spin_lock_init(&remote_spinlock, SMEM_SPINLOCK_SMEM_ALLOC);
 	if (rc) {
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 50bfb13..4a6a509 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -20,6 +20,7 @@
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/remote_spinlock.h>
+#include <linux/platform_device.h>
 #include <mach/msm_smsm.h>
 #include <mach/msm_smd.h>
 
@@ -206,6 +207,46 @@
 	unsigned reserved2, reserved3, reserved4, reserved5;
 } __attribute__ ((__packed__));
 
+struct smd_channel {
+	volatile void __iomem *send; /* some variant of smd_half_channel */
+	volatile void __iomem *recv; /* some variant of smd_half_channel */
+	unsigned char *send_data;
+	unsigned char *recv_data;
+	unsigned fifo_size;
+	unsigned fifo_mask;
+	struct list_head ch_list;
+
+	unsigned current_packet;
+	unsigned n;
+	void *priv;
+	void (*notify)(void *priv, unsigned flags);
+
+	int (*read)(smd_channel_t *ch, void *data, int len, int user_buf);
+	int (*write)(smd_channel_t *ch, const void *data, int len,
+			int user_buf);
+	int (*read_avail)(smd_channel_t *ch);
+	int (*write_avail)(smd_channel_t *ch);
+	int (*read_from_cb)(smd_channel_t *ch, void *data, int len,
+			int user_buf);
+
+	void (*update_state)(smd_channel_t *ch);
+	unsigned last_state;
+	void (*notify_other_cpu)(smd_channel_t *ch);
+
+	char name[20];
+	struct platform_device pdev;
+	unsigned type;
+
+	int pending_pkt_sz;
+
+	char is_pkt_ch;
+
+	/*
+	 * private internal functions to access *send and *recv.
+	 * never to be exported outside of smd
+	 */
+	struct smd_half_channel_access *half_ch;
+};
 
 struct smem_ram_ptable {
 	#define _SMEM_RAM_PTABLE_MAGIC_1 0x9DA5E0A8
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index a6b3d0c..9b2e732 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/smd_tty.c
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -37,6 +37,7 @@
 
 #define MAX_SMD_TTYS 37
 #define MAX_TTY_BUF_SIZE 2048
+#define MAX_RA_WAKE_LOCK_NAME_LEN 32
 
 static DEFINE_MUTEX(smd_tty_lock);
 
@@ -59,6 +60,9 @@
 	int is_open;
 	wait_queue_head_t ch_opened_wait_queue;
 	spinlock_t reset_lock;
+	spinlock_t ra_lock;		/* Read Available Lock*/
+	char ra_wake_lock_name[MAX_RA_WAKE_LOCK_NAME_LEN];
+	struct wake_lock ra_wake_lock;	/* Read Available Wakelock */
 	struct smd_config *smd;
 };
 
@@ -122,6 +126,7 @@
 	int avail;
 	struct smd_tty_info *info = (struct smd_tty_info *)param;
 	struct tty_struct *tty = info->tty;
+	unsigned long flags;
 
 	if (!tty)
 		return;
@@ -135,9 +140,14 @@
 		}
 
 		if (test_bit(TTY_THROTTLED, &tty->flags)) break;
+		spin_lock_irqsave(&info->ra_lock, flags);
 		avail = smd_read_avail(info->ch);
-		if (avail == 0)
+		if (avail == 0) {
+			wake_unlock(&info->ra_wake_lock);
+			spin_unlock_irqrestore(&info->ra_lock, flags);
 			break;
+		}
+		spin_unlock_irqrestore(&info->ra_lock, flags);
 
 		if (avail > MAX_TTY_BUF_SIZE)
 			avail = MAX_TTY_BUF_SIZE;
@@ -188,7 +198,12 @@
 			if (info->tty)
 				wake_up_interruptible(&info->tty->write_wait);
 		}
-		tasklet_hi_schedule(&info->tty_tsklt);
+		spin_lock_irqsave(&info->ra_lock, flags);
+		if (smd_read_avail(info->ch)) {
+			wake_lock(&info->ra_wake_lock);
+			tasklet_hi_schedule(&info->tty_tsklt);
+		}
+		spin_unlock_irqrestore(&info->ra_lock, flags);
 		break;
 
 	case SMD_EVENT_OPEN:
@@ -297,6 +312,11 @@
 			     (unsigned long)info);
 		wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
 				smd_tty[n].smd->port_name);
+		scnprintf(info->ra_wake_lock_name,
+			  MAX_RA_WAKE_LOCK_NAME_LEN,
+			  "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
+		wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
+				info->ra_wake_lock_name);
 		if (!info->ch) {
 			res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
 							smd_tty[n].smd->edge,
@@ -357,6 +377,7 @@
 		if (info->ch) {
 			smd_close(info->ch);
 			info->ch = 0;
+			wake_lock_destroy(&info->ra_wake_lock);
 			subsystem_put(info->pil);
 		}
 	}
@@ -565,6 +586,7 @@
 		smd_tty[idx].driver.driver.name = smd_configs[n].dev_name;
 		smd_tty[idx].driver.driver.owner = THIS_MODULE;
 		spin_lock_init(&smd_tty[idx].reset_lock);
+		spin_lock_init(&smd_tty[idx].ra_lock);
 		smd_tty[idx].is_open = 0;
 		setup_timer(&smd_tty[idx].buf_req_timer, buf_req_retry,
 				(unsigned long)&smd_tty[idx]);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 5bc4933..19e48759 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -246,6 +246,7 @@
 	[117] = MSM_CPU_8930,
 	[118] = MSM_CPU_8930,
 	[119] = MSM_CPU_8930,
+	[179] = MSM_CPU_8930,
 
 	/* 8627 IDs */
 	[120] = MSM_CPU_8627,
@@ -301,6 +302,7 @@
 	[143] = MSM_CPU_8930AA,
 	[144] = MSM_CPU_8930AA,
 	[160] = MSM_CPU_8930AA,
+	[180] = MSM_CPU_8930AA,
 
 	/* 8226 IDs */
 	[145] = MSM_CPU_8226,
@@ -319,6 +321,7 @@
 	[155] = MSM_CPU_8930AB,
 	[156] = MSM_CPU_8930AB,
 	[157] = MSM_CPU_8930AB,
+	[181] = MSM_CPU_8930AB,
 
 	/* 8625Q IDs */
 	[168] = MSM_CPU_8625Q,
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
index d638817..3269e50 100644
--- a/arch/arm/mach-msm/subsystem_map.c
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -410,8 +410,8 @@
 
 			if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
 				msm_iommu_map_extra
-					(d, temp_va, length, SZ_4K,
-					(IOMMU_READ | IOMMU_WRITE));
+					(d, temp_va, phys, length, SZ_4K,
+					IOMMU_READ);
 		}
 
 	}
diff --git a/arch/arm/mach-msm/subsystem_notif.c b/arch/arm/mach-msm/subsystem_notif.c
index afa7b48..f0db0e9 100644
--- a/arch/arm/mach-msm/subsystem_notif.c
+++ b/arch/arm/mach-msm/subsystem_notif.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011, 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -147,7 +147,8 @@
 EXPORT_SYMBOL(subsys_notif_add_subsys);
 
 int subsys_notif_queue_notification(void *subsys_handle,
-					enum subsys_notif_type notif_type)
+					enum subsys_notif_type notif_type,
+					void *data)
 {
 	int ret = 0;
 	struct subsys_notif_info *subsys =
@@ -159,10 +160,9 @@
 	if (notif_type < 0 || notif_type >= SUBSYS_NOTIF_TYPE_COUNT)
 		return -EINVAL;
 
-	ret = srcu_notifier_call_chain(
-		&subsys->subsys_notif_rcvr_list, notif_type,
-		(void *)subsys);
-
+		ret = srcu_notifier_call_chain(
+			&subsys->subsys_notif_rcvr_list, notif_type,
+			data);
 	return ret;
 }
 EXPORT_SYMBOL(subsys_notif_queue_notification);
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index ccab76a..29481d3 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,6 +30,7 @@
 #include <linux/device.h>
 #include <linux/idr.h>
 #include <linux/debugfs.h>
+#include <linux/miscdevice.h>
 
 #include <asm/current.h>
 
@@ -144,6 +145,8 @@
 	struct dentry *dentry;
 #endif
 	bool do_ramdump_on_put;
+	struct miscdevice misc_dev;
+	char miscdevice_name[32];
 };
 
 static struct subsys_device *to_subsys(struct device *d)
@@ -398,17 +401,17 @@
 	}
 }
 
-static void __send_notification_to_order(struct subsys_device *dev, void *data)
+static void notify_each_subsys_device(struct subsys_device **list,
+		unsigned count,
+		enum subsys_notif_type notif, void *data)
 {
-	enum subsys_notif_type type = (enum subsys_notif_type)data;
-
-	subsys_notif_queue_notification(dev->notify, type);
-}
-
-static void send_notification_to_order(struct subsys_device **l, unsigned n,
-		enum subsys_notif_type t)
-{
-	for_each_subsys_device(l, n, (void *)t, __send_notification_to_order);
+	while (count--) {
+		enum subsys_notif_type type = (enum subsys_notif_type)type;
+		struct subsys_device *dev = *list++;
+		if (!dev)
+			continue;
+		subsys_notif_queue_notification(dev->notify, notif, data);
+	}
 }
 
 static void subsystem_shutdown(struct subsys_device *dev, void *data)
@@ -622,9 +625,12 @@
 
 	pr_debug("[%p]: Starting restart sequence for %s\n", current,
 			desc->name);
-	send_notification_to_order(list, count, SUBSYS_BEFORE_SHUTDOWN);
+	notify_each_subsys_device(list, count, SUBSYS_BEFORE_SHUTDOWN, NULL);
 	for_each_subsys_device(list, count, NULL, subsystem_shutdown);
-	send_notification_to_order(list, count, SUBSYS_AFTER_SHUTDOWN);
+	notify_each_subsys_device(list, count, SUBSYS_AFTER_SHUTDOWN, NULL);
+
+	notify_each_subsys_device(list, count, SUBSYS_RAMDUMP_NOTIFICATION,
+							  &enable_ramdumps);
 
 	spin_lock_irqsave(&track->s_lock, flags);
 	track->p_state = SUBSYS_RESTARTING;
@@ -633,9 +639,9 @@
 	/* Collect ram dumps for all subsystems in order here */
 	for_each_subsys_device(list, count, NULL, subsystem_ramdump);
 
-	send_notification_to_order(list, count, SUBSYS_BEFORE_POWERUP);
+	notify_each_subsys_device(list, count, SUBSYS_BEFORE_POWERUP, NULL);
 	for_each_subsys_device(list, count, NULL, subsystem_powerup);
-	send_notification_to_order(list, count, SUBSYS_AFTER_POWERUP);
+	notify_each_subsys_device(list, count, SUBSYS_AFTER_POWERUP, NULL);
 
 	pr_info("[%p]: Restart sequence for %s completed.\n",
 			current, desc->name);
@@ -847,6 +853,41 @@
 static void subsys_debugfs_remove(struct subsys_device *subsys) { }
 #endif
 
+static int subsys_device_open(struct inode *inode, struct file *file)
+{
+	void *retval;
+	struct subsys_device *subsys_dev = container_of(file->private_data,
+		struct subsys_device, misc_dev);
+
+	if (!file->private_data)
+		return -EINVAL;
+
+	retval = subsystem_get(subsys_dev->desc->name);
+	if (IS_ERR(retval))
+		return PTR_ERR(retval);
+
+	return 0;
+}
+
+static int subsys_device_close(struct inode *inode, struct file *file)
+{
+	struct subsys_device *subsys_dev = container_of(file->private_data,
+		struct subsys_device, misc_dev);
+
+	if (!file->private_data)
+		return -EINVAL;
+
+	subsystem_put(subsys_dev);
+
+	return 0;
+}
+
+static const struct file_operations subsys_device_fops = {
+		.owner = THIS_MODULE,
+		.open = subsys_device_open,
+		.release = subsys_device_close,
+};
+
 static void subsys_device_release(struct device *dev)
 {
 	struct subsys_device *subsys = to_subsys(dev);
@@ -857,6 +898,33 @@
 	kfree(subsys);
 }
 
+static int subsys_misc_device_add(struct subsys_device *subsys_dev)
+{
+	int ret;
+	memset(subsys_dev->miscdevice_name, 0,
+			ARRAY_SIZE(subsys_dev->miscdevice_name));
+	snprintf(subsys_dev->miscdevice_name,
+			 ARRAY_SIZE(subsys_dev->miscdevice_name), "subsys_%s",
+			 subsys_dev->desc->name);
+
+	subsys_dev->misc_dev.minor = MISC_DYNAMIC_MINOR;
+	subsys_dev->misc_dev.name = subsys_dev->miscdevice_name;
+	subsys_dev->misc_dev.fops = &subsys_device_fops;
+	subsys_dev->misc_dev.parent = &subsys_dev->dev;
+
+	ret = misc_register(&subsys_dev->misc_dev);
+	if (ret) {
+		pr_err("%s: misc_register() failed for %s (%d)", __func__,
+				subsys_dev->miscdevice_name, ret);
+	}
+	return ret;
+}
+
+static void subsys_misc_device_remove(struct subsys_device *subsys_dev)
+{
+	misc_deregister(&subsys_dev->misc_dev);
+}
+
 struct subsys_device *subsys_register(struct subsys_desc *desc)
 {
 	struct subsys_device *subsys;
@@ -895,6 +963,12 @@
 
 	ret = device_register(&subsys->dev);
 	if (ret) {
+		device_unregister(&subsys->dev);
+		goto err_register;
+	}
+
+	ret = subsys_misc_device_add(subsys);
+	if (ret) {
 		put_device(&subsys->dev);
 		goto err_register;
 	}
@@ -924,6 +998,7 @@
 		device_unregister(&subsys->dev);
 		mutex_unlock(&subsys->track.lock);
 		subsys_debugfs_remove(subsys);
+		subsys_misc_device_remove(subsys);
 		put_device(&subsys->dev);
 	}
 }
diff --git a/arch/arm/mach-msm/tz_log.c b/arch/arm/mach-msm/tz_log.c
index da419fb..11dc436 100644
--- a/arch/arm/mach-msm/tz_log.c
+++ b/arch/arm/mach-msm/tz_log.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,16 +12,27 @@
  */
 #include <linux/debugfs.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/msm_ion.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <mach/scm.h>
+#include <mach/qseecomi.h>
 
 #define DEBUG_MAX_RW_BUF 4096
 
+/* QSEE_LOG_BUF_SIZE = 32K */
+#define QSEE_LOG_BUF_SIZE 0x8000
+
+
+/* TZ Diagnostic Area legacy version number */
+#define TZBSP_DIAG_MAJOR_VERSION_LEGACY	2
 /*
  * Preprocessor Definitions and Constants
  */
@@ -96,6 +107,24 @@
 	uint8_t int_desc[TZBSP_MAX_INT_DESC];
 	uint64_t int_count[TZBSP_CPU_COUNT]; /* # of times seen per CPU */
 };
+
+/*
+ * Log ring buffer position
+ */
+struct tzdbg_log_pos_t {
+	uint16_t wrap;
+	uint16_t offset;
+};
+
+ /*
+ * Log ring buffer
+ */
+struct tzdbg_log_t {
+	struct tzdbg_log_pos_t	log_pos;
+	/* open ended array to the end of the 4K IMEM buffer */
+	uint8_t					log_buf[];
+};
+
 /*
  * Diagnostic Table
  */
@@ -147,7 +176,7 @@
 	/*
 	 * We need at least 2K for the ring buffer
 	 */
-	uint8_t *ring_buffer;	/* TZ Ring Buffer */
+	struct tzdbg_log_t ring_buffer;	/* TZ Ring Buffer */
 };
 
 /*
@@ -160,7 +189,8 @@
 	TZDBG_VMID,
 	TZDBG_GENERAL,
 	TZDBG_LOG,
-	TZDBG_STATS_MAX,
+	TZDBG_QSEE_LOG,
+	TZDBG_STATS_MAX
 };
 
 struct tzdbg_stat {
@@ -184,8 +214,10 @@
 	.stat[TZDBG_VMID].name = "vmid",
 	.stat[TZDBG_GENERAL].name = "general",
 	.stat[TZDBG_LOG].name = "log",
+	.stat[TZDBG_QSEE_LOG].name = "qsee_log",
 };
 
+static struct tzdbg_log_t *g_qsee_log;
 
 /*
  * Debugfs data structure and functions
@@ -346,7 +378,7 @@
 	return len;
 }
 
-static int _disp_tz_log_stats(void)
+static int _disp_tz_log_stats_legacy(void)
 {
 	int len = 0;
 	unsigned char *ptr;
@@ -360,6 +392,97 @@
 	return len;
 }
 
+static int _disp_log_stats(struct tzdbg_log_t *log,
+			struct tzdbg_log_pos_t *log_start, uint32_t log_len,
+			size_t count, uint32_t buf_idx)
+{
+	uint32_t wrap_start;
+	uint32_t wrap_end;
+	uint32_t wrap_cnt;
+	int max_len;
+	int len = 0;
+	int i = 0;
+
+	wrap_start = log_start->wrap;
+	wrap_end = log->log_pos.wrap;
+
+	/* Calculate difference in # of buffer wrap-arounds */
+	if (wrap_end >= wrap_start) {
+		wrap_cnt = wrap_end - wrap_start;
+	} else {
+		/* wrap counter has wrapped around, invalidate start position */
+		wrap_cnt = 2;
+	}
+
+	if (wrap_cnt > 1) {
+		/* end position has wrapped around more than once, */
+		/* current start no longer valid                   */
+		log_start->wrap = log->log_pos.wrap - 1;
+		log_start->offset = (log->log_pos.offset + 1) % log_len;
+	} else if ((wrap_cnt == 1) &&
+		(log->log_pos.offset > log_start->offset)) {
+		/* end position has overwritten start */
+		log_start->offset = (log->log_pos.offset + 1) % log_len;
+	}
+
+	while (log_start->offset == log->log_pos.offset) {
+		/*
+		 * No data in ring buffer,
+		 * so we'll hang around until something happens
+		 */
+		unsigned long t = msleep_interruptible(50);
+		if (t != 0) {
+			/* Some event woke us up, so let's quit */
+			return 0;
+		}
+
+		if (buf_idx == TZDBG_LOG)
+			memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase,
+						DEBUG_MAX_RW_BUF);
+
+	}
+
+	max_len = (count > DEBUG_MAX_RW_BUF) ? DEBUG_MAX_RW_BUF : count;
+
+	/*
+	 *  Read from ring buff while there is data and space in return buff
+	 */
+	while ((log_start->offset != log->log_pos.offset) && (len < max_len)) {
+		tzdbg.disp_buf[i++] = log->log_buf[log_start->offset];
+		log_start->offset = (log_start->offset + 1) % log_len;
+		if (0 == log_start->offset)
+			++log_start->wrap;
+		++len;
+	}
+
+	/*
+	 * return buffer to caller
+	 */
+	tzdbg.stat[buf_idx].data = tzdbg.disp_buf;
+	return len;
+}
+
+static int _disp_tz_log_stats(size_t count)
+{
+	static struct tzdbg_log_pos_t log_start = {0};
+	struct tzdbg_log_t *log_ptr;
+	log_ptr = (struct tzdbg_log_t *)((unsigned char *)tzdbg.diag_buf +
+				tzdbg.diag_buf->ring_off -
+				offsetof(struct tzdbg_log_t, log_buf));
+
+	return _disp_log_stats(log_ptr, &log_start,
+				tzdbg.diag_buf->ring_len, count, TZDBG_LOG);
+}
+
+static int _disp_qsee_log_stats(size_t count)
+{
+	static struct tzdbg_log_pos_t log_start = {0};
+
+	return _disp_log_stats(g_qsee_log, &log_start,
+			QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t),
+			count, TZDBG_QSEE_LOG);
+}
+
 static ssize_t tzdbgfs_read(struct file *file, char __user *buf,
 	size_t count, loff_t *offp)
 {
@@ -385,7 +508,17 @@
 		len = _disp_tz_vmid_stats();
 		break;
 	case TZDBG_LOG:
-		len = _disp_tz_log_stats();
+		if (TZBSP_DIAG_MAJOR_VERSION_LEGACY <
+				(tzdbg.diag_buf->version >> 16)) {
+			len = _disp_tz_log_stats(count);
+			*offp = 0;
+		} else {
+			len = _disp_tz_log_stats_legacy();
+		}
+		break;
+	case TZDBG_QSEE_LOG:
+		len = _disp_qsee_log_stats(count);
+		*offp = 0;
 		break;
 	default:
 		break;
@@ -410,6 +543,78 @@
 	.open    = tzdbgfs_open,
 };
 
+static struct ion_client  *g_ion_clnt;
+static struct ion_handle *g_ihandle;
+
+/*
+ * Allocates log buffer from ION, registers the buffer at TZ
+ */
+static void tzdbg_register_qsee_log_buf(void)
+{
+	/* register log buffer scm request */
+	struct qseecom_reg_log_buf_ireq req;
+
+	/* scm response */
+	struct qseecom_command_scm_resp resp;
+	ion_phys_addr_t pa = 0;
+	uint32_t len;
+	int ret = 0;
+
+	/* Create ION msm client */
+	g_ion_clnt = msm_ion_client_create(ION_HEAP_CARVEOUT_MASK, "qsee_log");
+	if (g_ion_clnt == NULL) {
+		pr_err("%s: Ion client cannot be created\n", __func__);
+		return;
+	}
+
+	g_ihandle = ion_alloc(g_ion_clnt, QSEE_LOG_BUF_SIZE,
+			4096, ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+	if (IS_ERR_OR_NULL(g_ihandle)) {
+		pr_err("%s: Ion client could not retrieve the handle\n",
+			__func__);
+		goto err1;
+	}
+
+	ret = ion_phys(g_ion_clnt, g_ihandle, &pa, &len);
+	if (ret) {
+		pr_err("%s: Ion conversion to physical address failed\n",
+			__func__);
+		goto err2;
+	}
+
+	req.qsee_cmd_id = QSEOS_REGISTER_LOG_BUF_COMMAND;
+	req.phy_addr = pa;
+	req.len = len;
+
+	/*  SCM_CALL  to register the log buffer */
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,  &req, sizeof(req),
+		&resp, sizeof(resp));
+	if (ret) {
+		pr_err("%s: scm_call to register log buffer failed\n",
+			__func__);
+		goto err2;
+	}
+
+	if (resp.result != QSEOS_RESULT_SUCCESS) {
+		pr_err(
+		"%s: scm_call to register log buf failed, resp result =%d\n",
+		__func__, resp.result);
+		goto err2;
+	}
+
+	g_qsee_log =
+		(struct tzdbg_log_t *)ion_map_kernel(g_ion_clnt, g_ihandle);
+	g_qsee_log->log_pos.wrap = g_qsee_log->log_pos.offset = 0;
+	return;
+
+err2:
+	ion_free(g_ion_clnt, g_ihandle);
+	g_ihandle = NULL;
+err1:
+	ion_client_destroy(g_ion_clnt);
+	g_ion_clnt = NULL;
+}
+
 static int  tzdbgfs_init(struct platform_device *pdev)
 {
 	int rc = 0;
@@ -456,6 +661,13 @@
 	kzfree(tzdbg.disp_buf);
 	dent_dir = platform_get_drvdata(pdev);
 	debugfs_remove_recursive(dent_dir);
+	if (g_ion_clnt != NULL) {
+		if (!IS_ERR_OR_NULL(g_ihandle)) {
+			ion_unmap_kernel(g_ion_clnt, g_ihandle);
+			ion_free(g_ion_clnt, g_ihandle);
+		}
+	ion_client_destroy(g_ion_clnt);
+}
 }
 
 /*
@@ -527,6 +739,7 @@
 	if (tzdbgfs_init(pdev))
 		goto err;
 
+	tzdbg_register_qsee_log_buf();
 	return 0;
 err:
 	kfree(tzdbg.diag_buf);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index afaa39d..f6fb3b8 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -165,16 +165,29 @@
 
 static void __dma_clear_buffer(struct page *page, size_t size)
 {
-	void *ptr;
 	/*
 	 * Ensure that the allocated pages are zeroed, and that any data
 	 * lurking in the kernel direct-mapped region is invalidated.
 	 */
-	ptr = page_address(page);
-	if (ptr) {
-		memset(ptr, 0, size);
-		dmac_flush_range(ptr, ptr + size);
-		outer_flush_range(__pa(ptr), __pa(ptr) + size);
+	if (!PageHighMem(page)) {
+		void *ptr = page_address(page);
+		if (ptr) {
+			memset(ptr, 0, size);
+			dmac_flush_range(ptr, ptr + size);
+			outer_flush_range(__pa(ptr), __pa(ptr) + size);
+		}
+	} else {
+		phys_addr_t base = __pfn_to_phys(page_to_pfn(page));
+		phys_addr_t end = base + size;
+		while (size > 0) {
+			void *ptr = kmap_atomic(page);
+			memset(ptr, 0, PAGE_SIZE);
+			dmac_flush_range(ptr, ptr + PAGE_SIZE);
+			kunmap_atomic(ptr);
+			page++;
+			size -= PAGE_SIZE;
+		}
+		outer_flush_range(base, end);
 	}
 }
 
@@ -315,7 +328,7 @@
 
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
 				     pgprot_t prot, struct page **ret_page,
-				     bool no_kernel_mapping);
+				     bool no_kernel_mapping, const void *caller);
 
 static struct arm_vmregion_head coherent_head = {
 	.vm_lock	= __SPIN_LOCK_UNLOCKED(&coherent_head.vm_lock),
@@ -344,7 +357,8 @@
 	if (!IS_ENABLED(CONFIG_CMA))
 		return 0;
 
-	ptr = __alloc_from_contiguous(NULL, size, prot, &page, false);
+	ptr = __alloc_from_contiguous(NULL, size, prot, &page, false,
+						coherent_init);
 	if (ptr) {
 		coherent_head.vm_start = (unsigned long) ptr;
 		coherent_head.vm_end = (unsigned long) ptr + size;
@@ -465,7 +479,7 @@
 	return NULL;
 }
 
-static void __dma_free_remap(void *cpu_addr, size_t size)
+static void __dma_free_remap(void *cpu_addr, size_t size, bool no_warn)
 {
 	struct arm_vmregion *c;
 	unsigned long addr;
@@ -475,9 +489,11 @@
 
 	c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr);
 	if (!c) {
-		pr_err("%s: trying to free invalid coherent area: %p\n",
-		       __func__, cpu_addr);
-		dump_stack();
+		if (!no_warn) {
+			pr_err("%s: trying to free invalid coherent area: %p\n",
+			       __func__, cpu_addr);
+			dump_stack();
+		}
 		return;
 	}
 
@@ -619,29 +635,54 @@
 	return 1;
 }
 
+#define NO_KERNEL_MAPPING_DUMMY	0x2222
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
 				     pgprot_t prot, struct page **ret_page,
-				     bool no_kernel_mapping)
+				     bool no_kernel_mapping,
+				     const void *caller)
 {
 	unsigned long order = get_order(size);
 	size_t count = size >> PAGE_SHIFT;
 	struct page *page;
+	void *ptr;
 
 	page = dma_alloc_from_contiguous(dev, count, order);
 	if (!page)
 		return NULL;
 
 	__dma_clear_buffer(page, size);
-	__dma_remap(page, size, prot, no_kernel_mapping);
 
+	if (!PageHighMem(page)) {
+		__dma_remap(page, size, prot, no_kernel_mapping);
+		ptr = page_address(page);
+	} else {
+		if (no_kernel_mapping) {
+			/*
+			 * Something non-NULL needs to be returned here. Give
+			 * back a dummy address that is unmapped to catch
+			 * clients trying to use the address incorrectly
+			 */
+			ptr = (void *)NO_KERNEL_MAPPING_DUMMY;
+		} else {
+			ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot,
+						caller);
+			if (!ptr) {
+				dma_release_from_contiguous(dev, page, count);
+				return NULL;
+			}
+		}
+	}
 	*ret_page = page;
-	return page_address(page);
+	return ptr;
 }
 
 static void __free_from_contiguous(struct device *dev, struct page *page,
-				   size_t size)
+				   void *cpu_addr, size_t size)
 {
-	__dma_remap(page, size, pgprot_kernel, false);
+	if (!PageHighMem(page))
+		__dma_remap(page, size, pgprot_kernel, false);
+	else
+		__dma_free_remap(cpu_addr, size, true);
 	dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
 }
 
@@ -731,7 +772,7 @@
 		addr = __alloc_from_pool(dev, size, &page, caller);
 	else
 		addr = __alloc_from_contiguous(dev, size, prot, &page,
-						no_kernel_mapping);
+						no_kernel_mapping, caller);
 
 	if (addr)
 		*handle = pfn_to_dma(dev, page_to_pfn(page));
@@ -798,7 +839,7 @@
 	if (arch_is_coherent() || nommu()) {
 		__dma_free_buffer(page, size);
 	} else if (!IS_ENABLED(CONFIG_CMA)) {
-		__dma_free_remap(cpu_addr, size);
+		__dma_free_remap(cpu_addr, size, false);
 		__dma_free_buffer(page, size);
 	} else {
 		if (__free_from_pool(cpu_addr, size))
@@ -807,7 +848,7 @@
 		 * Non-atomic allocations cannot be freed with IRQs disabled
 		 */
 		WARN_ON(irqs_disabled());
-		__free_from_contiguous(dev, page, size);
+		__free_from_contiguous(dev, page, cpu_addr, size);
 	}
 }
 
@@ -815,25 +856,27 @@
 	size_t size, enum dma_data_direction dir,
 	void (*op)(const void *, size_t, int))
 {
+	unsigned long pfn;
+	size_t left = size;
+
+	pfn = page_to_pfn(page) + offset / PAGE_SIZE;
+	offset %= PAGE_SIZE;
+
 	/*
 	 * A single sg entry may refer to multiple physically contiguous
 	 * pages.  But we still need to process highmem pages individually.
 	 * If highmem is not configured then the bulk of this loop gets
 	 * optimized out.
 	 */
-	size_t left = size;
 	do {
 		size_t len = left;
 		void *vaddr;
 
+		page = pfn_to_page(pfn);
+
 		if (PageHighMem(page)) {
-			if (len + offset > PAGE_SIZE) {
-				if (offset >= PAGE_SIZE) {
-					page += offset / PAGE_SIZE;
-					offset %= PAGE_SIZE;
-				}
+			if (len + offset > PAGE_SIZE)
 				len = PAGE_SIZE - offset;
-			}
 			vaddr = kmap_high_get(page);
 			if (vaddr) {
 				vaddr += offset;
@@ -850,7 +893,7 @@
 			op(vaddr, len, dir);
 		}
 		offset = 0;
-		page++;
+		pfn++;
 		left -= len;
 	} while (left);
 }
@@ -1332,7 +1375,7 @@
 	c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
 	if (c) {
 		struct page **pages = c->priv;
-		__dma_free_remap(cpu_addr, size);
+		__dma_free_remap(cpu_addr, size, false);
 		__iommu_remove_mapping(dev, handle, size);
 		__iommu_free_buffer(dev, pages, size);
 	}
diff --git a/block/row-iosched.c b/block/row-iosched.c
index b8c16e7..bdb6abd 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -25,21 +25,22 @@
 #include <linux/init.h>
 #include <linux/compiler.h>
 #include <linux/blktrace_api.h>
-#include <linux/jiffies.h>
+#include <linux/hrtimer.h>
 
 /*
  * enum row_queue_prio - Priorities of the ROW queues
  *
  * This enum defines the priorities (and the number of queues)
- * the requests will be disptributed to. The higher priority -
- * the bigger is the dispatch quantum given to that queue.
+ * the requests will be distributed to. The higher priority -
+ * the bigger is the "bus time" (or the dispatch quantum) given
+ * to that queue.
  * ROWQ_PRIO_HIGH_READ - is the higher priority queue.
  *
  */
 enum row_queue_prio {
 	ROWQ_PRIO_HIGH_READ = 0,
-	ROWQ_PRIO_REG_READ,
 	ROWQ_PRIO_HIGH_SWRITE,
+	ROWQ_PRIO_REG_READ,
 	ROWQ_PRIO_REG_SWRITE,
 	ROWQ_PRIO_REG_WRITE,
 	ROWQ_PRIO_LOW_READ,
@@ -47,6 +48,14 @@
 	ROWQ_MAX_PRIO,
 };
 
+/*
+ * The following indexes define the distribution of ROW queues according to
+ * priorities. Each index defines the first queue in that priority group.
+ */
+#define ROWQ_HIGH_PRIO_IDX	ROWQ_PRIO_HIGH_READ
+#define ROWQ_REG_PRIO_IDX	ROWQ_PRIO_REG_READ
+#define ROWQ_LOW_PRIO_IDX	ROWQ_PRIO_LOW_READ
+
 /**
  * struct row_queue_params - ROW queue parameters
  * @idling_enabled: Flag indicating whether idling is enable on
@@ -69,12 +78,17 @@
  * {idling_enabled, quantum, is_urgent}
  * Each row corresponds to a queue with the same index (according to
  * enum row_queue_prio)
+ * Note: The quantums are valid inside their priority type. For example:
+ *       For every 10 high priority read requests, 1 high priority sync
+ *       write will be dispatched.
+ *       For every 100 regular read requests 1 regular write request will
+ *       be dispatched.
  */
 static const struct row_queue_params row_queues_def[] = {
 /* idling_enabled, quantum, is_urgent */
-	{true, 100, true},	/* ROWQ_PRIO_HIGH_READ */
+	{true, 10, true},	/* ROWQ_PRIO_HIGH_READ */
+	{false, 1, true},	/* ROWQ_PRIO_HIGH_SWRITE */
 	{true, 100, true},	/* ROWQ_PRIO_REG_READ */
-	{false, 2, false},	/* ROWQ_PRIO_HIGH_SWRITE */
 	{false, 1, false},	/* ROWQ_PRIO_REG_SWRITE */
 	{false, 1, false},	/* ROWQ_PRIO_REG_WRITE */
 	{false, 1, false},	/* ROWQ_PRIO_LOW_READ */
@@ -104,7 +118,6 @@
  * @prio:		queue priority (enum row_queue_prio)
  * @nr_dispatched:	number of requests already dispatched in
  *			the current dispatch cycle
- * @slice:		number of requests to dispatch in a cycle
  * @nr_req:		number of requests in queue
  * @dispatch quantum:	number of requests this queue may
  *			dispatch in a dispatch cycle
@@ -117,7 +130,6 @@
 	enum row_queue_prio	prio;
 
 	unsigned int		nr_dispatched;
-	unsigned int		slice;
 
 	unsigned int		nr_req;
 	int			disp_quantum;
@@ -128,30 +140,33 @@
 
 /**
  * struct idling_data - data for idling on empty rqueue
- * @idle_time:		idling duration (jiffies)
- * @freq:		min time between two requests that
+ * @idle_time_ms:		idling duration (msec)
+ * @freq_ms:		min time between two requests that
  *			triger idling (msec)
- * @idle_work:		pointer to struct delayed_work
+ * @hr_timer:	idling timer
+ * @idle_work:	the work to be scheduled when idling timer expires
+ * @idling_queue_idx:	index of the queues we're idling on
  *
  */
 struct idling_data {
-	unsigned long			idle_time;
-	u32				freq;
+	s64				idle_time_ms;
+	s64				freq_ms;
 
-	struct workqueue_struct	*idle_workqueue;
-	struct delayed_work		idle_work;
+	struct hrtimer			hr_timer;
+	struct work_struct		idle_work;
+	enum row_queue_prio		idling_queue_idx;
 };
 
 /**
  * struct row_queue - Per block device rqueue structure
  * @dispatch_queue:	dispatch rqueue
  * @row_queues:		array of priority request queues
- * @curr_queue:		index in the row_queues array of the
- *			currently serviced rqueue
- * @read_idle:		data for idling after READ request
+ * @rd_idle_data:		data for idling after READ request
  * @nr_reqs: nr_reqs[0] holds the number of all READ requests in
  *			scheduler, nr_reqs[1] holds the number of all WRITE
  *			requests in scheduler
+ * @nr_urgent_in_flight: number of uncompleted urgent requests
+ *			(both reads and writes)
  * @cycle_flags:	used for marking unserved queueus
  *
  */
@@ -160,10 +175,9 @@
 
 	struct row_queue row_queues[ROWQ_MAX_PRIO];
 
-	enum row_queue_prio		curr_queue;
-
-	struct idling_data		read_idle;
+	struct idling_data		rd_idle_data;
 	unsigned int			nr_reqs[2];
+	unsigned int			nr_urgent_in_flight;
 
 	unsigned int			cycle_flags;
 };
@@ -207,60 +221,37 @@
 }
 
 /******************** Static helper functions ***********************/
-/*
- * kick_queue() - Wake up device driver queue thread
- * @work:	pointer to struct work_struct
- *
- * This is a idling delayed work function. It's purpose is to wake up the
- * device driver in order for it to start fetching requests.
- *
- */
 static void kick_queue(struct work_struct *work)
 {
-	struct delayed_work *idle_work = to_delayed_work(work);
 	struct idling_data *read_data =
-		container_of(idle_work, struct idling_data, idle_work);
+		container_of(work, struct idling_data, idle_work);
 	struct row_data *rd =
-		container_of(read_data, struct row_data, read_idle);
+		container_of(read_data, struct row_data, rd_idle_data);
 
-	row_log_rowq(rd, rd->curr_queue, "Performing delayed work");
+	blk_run_queue(rd->dispatch_queue);
+}
+
+
+static enum hrtimer_restart row_idle_hrtimer_fn(struct hrtimer *hr_timer)
+{
+	struct idling_data *read_data =
+		container_of(hr_timer, struct idling_data, hr_timer);
+	struct row_data *rd =
+		container_of(read_data, struct row_data, rd_idle_data);
+
+	row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx,
+			 "Performing delayed work");
 	/* Mark idling process as done */
-	rd->row_queues[rd->curr_queue].idle_data.begin_idling = false;
+	rd->row_queues[rd->rd_idle_data.idling_queue_idx].
+			idle_data.begin_idling = false;
+	rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
 
-	if (!(rd->nr_reqs[0] + rd->nr_reqs[1]))
+	if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE])
 		row_log(rd->dispatch_queue, "No requests in scheduler");
-	else {
-		spin_lock_irq(rd->dispatch_queue->queue_lock);
-		__blk_run_queue(rd->dispatch_queue);
-		spin_unlock_irq(rd->dispatch_queue->queue_lock);
-	}
-}
-
-/*
- * row_restart_disp_cycle() - Restart the dispatch cycle
- * @rd:	pointer to struct row_data
- *
- * This function restarts the dispatch cycle by:
- * - Setting current queue to ROWQ_PRIO_HIGH_READ
- * - For each queue: reset the number of requests dispatched in
- *   the cycle
- */
-static inline void row_restart_disp_cycle(struct row_data *rd)
-{
-	int i;
-
-	for (i = 0; i < ROWQ_MAX_PRIO; i++)
-		rd->row_queues[i].nr_dispatched = 0;
-
-	rd->curr_queue = ROWQ_PRIO_HIGH_READ;
-	row_log(rd->dispatch_queue, "Restarting cycle");
-}
-
-static inline void row_get_next_queue(struct row_data *rd)
-{
-	rd->curr_queue++;
-	if (rd->curr_queue == ROWQ_MAX_PRIO)
-		row_restart_disp_cycle(rd);
+	else
+		kblockd_schedule_work(rd->dispatch_queue,
+			&read_data->idle_work);
+	return HRTIMER_NORESTART;
 }
 
 /******************* Elevator callback functions *********************/
@@ -276,6 +267,7 @@
 {
 	struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
 	struct row_queue *rqueue = RQ_ROWQ(rq);
+	s64 diff_ms;
 
 	list_add_tail(&rq->queuelist, &rqueue->fifo);
 	rd->nr_reqs[rq_data_dir(rq)]++;
@@ -283,17 +275,28 @@
 	rq_set_fifo_time(rq, jiffies); /* for statistics*/
 
 	if (row_queues_def[rqueue->prio].idling_enabled) {
-		if (delayed_work_pending(&rd->read_idle.idle_work))
-			(void)cancel_delayed_work(
-				&rd->read_idle.idle_work);
-		if (ktime_to_ms(ktime_sub(ktime_get(),
-				rqueue->idle_data.last_insert_time)) <
-				rd->read_idle.freq) {
+		if (rd->rd_idle_data.idling_queue_idx == rqueue->prio &&
+		    hrtimer_active(&rd->rd_idle_data.hr_timer)) {
+			(void)hrtimer_cancel(&rd->rd_idle_data.hr_timer);
+			row_log_rowq(rd, rqueue->prio,
+				"Canceled delayed work on %d",
+				rd->rd_idle_data.idling_queue_idx);
+			rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
+		}
+		diff_ms = ktime_to_ms(ktime_sub(ktime_get(),
+				rqueue->idle_data.last_insert_time));
+		if (unlikely(diff_ms < 0)) {
+			pr_err("ROW BUG: %s diff_ms < 0", __func__);
+			rqueue->idle_data.begin_idling = false;
+			return;
+		}
+		if (diff_ms < rd->rd_idle_data.freq_ms) {
 			rqueue->idle_data.begin_idling = true;
 			row_log_rowq(rd, rqueue->prio, "Enable idling");
 		} else {
 			rqueue->idle_data.begin_idling = false;
-			row_log_rowq(rd, rqueue->prio, "Disable idling");
+			row_log_rowq(rd, rqueue->prio, "Disable idling (%ldms)",
+				(long)diff_ms);
 		}
 
 		rqueue->idle_data.last_insert_time = ktime_get();
@@ -303,6 +306,7 @@
 		row_log_rowq(rd, rqueue->prio,
 			"added urgent request (total on queue=%d)",
 			rqueue->nr_req);
+		rq->cmd_flags |= REQ_URGENT;
 	} else
 		row_log_rowq(rd, rqueue->prio,
 			"added request (total on queue=%d)", rqueue->nr_req);
@@ -324,10 +328,9 @@
 	struct row_data    *rd = q->elevator->elevator_data;
 	struct row_queue   *rqueue = RQ_ROWQ(rq);
 
-	/* Verify rqueue is legitimate */
 	if (rqueue->prio >= ROWQ_MAX_PRIO) {
-		pr_err("\n\nROW BUG: row_reinsert_req() rqueue->prio = %d\n",
-			   rqueue->prio);
+		pr_err("\n\n%s:ROW BUG: row_reinsert_req() rqueue->prio = %d\n",
+			   rq->rq_disk->disk_name, rqueue->prio);
 		blk_dump_rq_flags(rq, "");
 		return -EIO;
 	}
@@ -342,6 +345,20 @@
 	return 0;
 }
 
+static void row_completed_req(struct request_queue *q, struct request *rq)
+{
+	struct row_data *rd = q->elevator->elevator_data;
+
+	 if (rq->cmd_flags & REQ_URGENT) {
+		if (!rd->nr_urgent_in_flight) {
+			pr_err("ROW BUG: %s() nr_urgent_in_flight = 0",
+				__func__);
+			return;
+		}
+		rd->nr_urgent_in_flight--;
+	}
+}
+
 /**
  * row_urgent_pending() - Return TRUE if there is an urgent
  *			  request on scheduler
@@ -352,12 +369,23 @@
 	struct row_data *rd = q->elevator->elevator_data;
 	int i;
 
-	for (i = 0; i < ROWQ_MAX_PRIO; i++)
+	if (rd->nr_urgent_in_flight) {
+		row_log(rd->dispatch_queue, "%d urgent requests in flight",
+			rd->nr_urgent_in_flight);
+		return false;
+	}
+
+	for (i = ROWQ_HIGH_PRIO_IDX; i < ROWQ_REG_PRIO_IDX; i++)
+		if (!list_empty(&rd->row_queues[i].fifo)) {
+			row_log_rowq(rd, i,
+				"Urgent (high prio) request pending");
+			return true;
+		}
+
+	for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_MAX_PRIO; i++)
 		if (row_queues_def[i].is_urgent && row_rowq_unserved(rd, i) &&
 		    !list_empty(&rd->row_queues[i].fifo)) {
-			row_log_rowq(rd, i,
-				     "Urgent request pending (curr=%i)",
-				     rd->curr_queue);
+			row_log_rowq(rd, i, "Urgent request pending");
 			return true;
 		}
 
@@ -383,62 +411,172 @@
 
 /*
  * row_dispatch_insert() - move request to dispatch queue
- * @rd:	pointer to struct row_data
+ * @rd:		pointer to struct row_data
+ * @queue_idx:	index of the row_queue to dispatch from
  *
  * This function moves the next request to dispatch from
- * rd->curr_queue to the dispatch queue
+ * the given queue (row_queues[queue_idx]) to the dispatch queue
  *
  */
-static void row_dispatch_insert(struct row_data *rd)
+static void row_dispatch_insert(struct row_data *rd, int queue_idx)
 {
 	struct request *rq;
 
-	rq = rq_entry_fifo(rd->row_queues[rd->curr_queue].fifo.next);
+	rq = rq_entry_fifo(rd->row_queues[queue_idx].fifo.next);
 	row_remove_request(rd->dispatch_queue, rq);
 	elv_dispatch_add_tail(rd->dispatch_queue, rq);
-	rd->row_queues[rd->curr_queue].nr_dispatched++;
-	row_clear_rowq_unserved(rd, rd->curr_queue);
-	row_log_rowq(rd, rd->curr_queue, " Dispatched request nr_disp = %d",
-		     rd->row_queues[rd->curr_queue].nr_dispatched);
+	rd->row_queues[queue_idx].nr_dispatched++;
+	row_clear_rowq_unserved(rd, queue_idx);
+	row_log_rowq(rd, queue_idx, " Dispatched request nr_disp = %d",
+		     rd->row_queues[queue_idx].nr_dispatched);
+	if (rq->cmd_flags & REQ_URGENT)
+		rd->nr_urgent_in_flight++;
 }
 
 /*
- * row_choose_queue() -  choose the next queue to dispatch from
+ * row_get_ioprio_class_to_serve() - Return the next I/O priority
+ *				      class to dispatch requests from
  * @rd:	pointer to struct row_data
+ * @force:	flag indicating if forced dispatch
  *
- * Updates rd->curr_queue. Returns 1 if there are requests to
- * dispatch, 0 if there are no requests in scheduler
+ * This function returns the next I/O priority class to serve
+ * {IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE}.
+ * If there are no more requests in scheduler or if we're idling on some queue
+ * IOPRIO_CLASS_NONE will be returned.
+ * If idling is scheduled on a lower priority queue than the one that needs
+ * to be served, it will be canceled.
  *
  */
-static int row_choose_queue(struct row_data *rd)
+static int row_get_ioprio_class_to_serve(struct row_data *rd, int force)
 {
-	int prev_curr_queue = rd->curr_queue;
+	int i;
+	int ret = IOPRIO_CLASS_NONE;
 
-	if (!(rd->nr_reqs[0] + rd->nr_reqs[1])) {
+	if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE]) {
 		row_log(rd->dispatch_queue, "No more requests in scheduler");
-		return 0;
+		goto check_idling;
 	}
 
-	row_get_next_queue(rd);
+	/* First, go over the high priority queues */
+	for (i = 0; i < ROWQ_REG_PRIO_IDX; i++) {
+		if (!list_empty(&rd->row_queues[i].fifo)) {
+			if (hrtimer_active(&rd->rd_idle_data.hr_timer)) {
+				(void)hrtimer_cancel(
+					&rd->rd_idle_data.hr_timer);
+				row_log_rowq(rd,
+					rd->rd_idle_data.idling_queue_idx,
+					"Canceling delayed work on %d. RT pending",
+					rd->rd_idle_data.idling_queue_idx);
+				rd->rd_idle_data.idling_queue_idx =
+					ROWQ_MAX_PRIO;
+			}
+			ret = IOPRIO_CLASS_RT;
+			goto done;
+		}
+	}
 
 	/*
-	 * Loop over all queues to find the next queue that is not empty.
-	 * Stop when you get back to curr_queue
+	 * At the moment idling is implemented only for READ queues.
+	 * If enabled on WRITE, this needs updating
 	 */
-	while (list_empty(&rd->row_queues[rd->curr_queue].fifo)
-	       && rd->curr_queue != prev_curr_queue) {
-		/* Mark rqueue as unserved */
-		row_mark_rowq_unserved(rd, rd->curr_queue);
-		row_get_next_queue(rd);
+	if (hrtimer_active(&rd->rd_idle_data.hr_timer)) {
+		row_log(rd->dispatch_queue, "Delayed work pending. Exiting");
+		goto done;
+	}
+check_idling:
+	/* Check for (high priority) idling and enable if needed */
+	for (i = 0; i < ROWQ_REG_PRIO_IDX && !force; i++) {
+		if (rd->row_queues[i].idle_data.begin_idling &&
+		    row_queues_def[i].idling_enabled)
+			goto initiate_idling;
 	}
 
-	return 1;
+	/* Regular priority queues */
+	for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++) {
+		if (list_empty(&rd->row_queues[i].fifo)) {
+			/* We can idle only if this is not a forced dispatch */
+			if (rd->row_queues[i].idle_data.begin_idling &&
+			    !force && row_queues_def[i].idling_enabled)
+				goto initiate_idling;
+		} else {
+			ret = IOPRIO_CLASS_BE;
+			goto done;
+		}
+	}
+
+	if (rd->nr_reqs[READ] || rd->nr_reqs[WRITE])
+		ret = IOPRIO_CLASS_IDLE;
+	goto done;
+
+initiate_idling:
+	hrtimer_start(&rd->rd_idle_data.hr_timer,
+		ktime_set(0, rd->rd_idle_data.idle_time_ms * NSEC_PER_MSEC),
+		HRTIMER_MODE_REL);
+
+	rd->rd_idle_data.idling_queue_idx = i;
+	row_log_rowq(rd, i, "Scheduled delayed work on %d. exiting", i);
+
+done:
+	return ret;
+}
+
+static void row_restart_cycle(struct row_data *rd,
+				int start_idx, int end_idx)
+{
+	int i;
+
+	row_dump_queues_stat(rd);
+	for (i = start_idx; i < end_idx; i++) {
+		if (rd->row_queues[i].nr_dispatched <
+		    rd->row_queues[i].disp_quantum)
+			row_mark_rowq_unserved(rd, i);
+		rd->row_queues[i].nr_dispatched = 0;
+	}
+	row_log(rd->dispatch_queue, "Restarting cycle for class @ %d-%d",
+		start_idx, end_idx);
+}
+
+/*
+ * row_get_next_queue() - selects the next queue to dispatch from
+ * @q:		requests queue
+ * @rd:		pointer to struct row_data
+ * @start_idx/end_idx: indexes in the row_queues array to select a queue
+ *                 from.
+ *
+ * Return index of the queues to dispatch from. Error code if fails.
+ *
+ */
+static int row_get_next_queue(struct request_queue *q, struct row_data *rd,
+				int start_idx, int end_idx)
+{
+	int i = start_idx;
+	bool restart = true;
+	int ret = -EIO;
+
+	do {
+		if (list_empty(&rd->row_queues[i].fifo) ||
+		    rd->row_queues[i].nr_dispatched >=
+		    rd->row_queues[i].disp_quantum) {
+			i++;
+			if (i == end_idx && restart) {
+				/* Restart cycle for this priority class */
+				row_restart_cycle(rd, start_idx, end_idx);
+				i = start_idx;
+				restart = false;
+			}
+		} else {
+			ret = i;
+			break;
+		}
+	} while (i < end_idx);
+
+	return ret;
 }
 
 /*
  * row_dispatch_requests() - selects the next request to dispatch
  * @q:		requests queue
- * @force:	ignored
+ * @force:		flag indicating if forced dispatch
  *
  * Return 0 if no requests were moved to the dispatch queue.
  *	  1 otherwise
@@ -447,77 +585,47 @@
 static int row_dispatch_requests(struct request_queue *q, int force)
 {
 	struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
-	int ret = 0, currq, i;
+	int ret = 0, currq, ioprio_class_to_serve, start_idx, end_idx;
 
-	currq = rd->curr_queue;
-
-	/*
-	 * Find the first unserved queue (with higher priority then currq)
-	 * that is not empty
-	 */
-	for (i = 0; i < currq; i++) {
-		if (row_rowq_unserved(rd, i) &&
-		    !list_empty(&rd->row_queues[i].fifo)) {
-			row_log_rowq(rd, currq,
-				" Preemting for unserved rowq%d. (nr_req=%u)",
-				i, rd->row_queues[currq].nr_req);
-			rd->curr_queue = i;
-			row_dispatch_insert(rd);
-			ret = 1;
-			goto done;
-		}
+	if (force && hrtimer_active(&rd->rd_idle_data.hr_timer)) {
+		(void)hrtimer_cancel(&rd->rd_idle_data.hr_timer);
+		row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx,
+			"Canceled delayed work on %d - forced dispatch",
+			rd->rd_idle_data.idling_queue_idx);
+		rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
 	}
 
-	if (rd->row_queues[currq].nr_dispatched >=
-	    rd->row_queues[currq].disp_quantum) {
-		rd->row_queues[currq].nr_dispatched = 0;
-		row_log_rowq(rd, currq, "Expiring rqueue");
-		ret = row_choose_queue(rd);
-		if (ret)
-			row_dispatch_insert(rd);
+	ioprio_class_to_serve = row_get_ioprio_class_to_serve(rd, force);
+	row_log(rd->dispatch_queue, "Dispatching from %d priority class",
+		ioprio_class_to_serve);
+
+	switch (ioprio_class_to_serve) {
+	case IOPRIO_CLASS_NONE:
+		goto done;
+	case IOPRIO_CLASS_RT:
+		start_idx = ROWQ_HIGH_PRIO_IDX;
+		end_idx = ROWQ_REG_PRIO_IDX;
+		break;
+	case IOPRIO_CLASS_BE:
+		start_idx = ROWQ_REG_PRIO_IDX;
+		end_idx = ROWQ_LOW_PRIO_IDX;
+		break;
+	case IOPRIO_CLASS_IDLE:
+		start_idx = ROWQ_LOW_PRIO_IDX;
+		end_idx = ROWQ_MAX_PRIO;
+		break;
+	default:
+		pr_err("%s(): Invalid I/O priority class", __func__);
 		goto done;
 	}
 
-	/* Dispatch from curr_queue */
-	if (list_empty(&rd->row_queues[currq].fifo)) {
-		/* check idling */
-		if (delayed_work_pending(&rd->read_idle.idle_work)) {
-			if (force) {
-				(void)cancel_delayed_work(
-				&rd->read_idle.idle_work);
-				row_log_rowq(rd, currq,
-					"Canceled delayed work - forced dispatch");
-			} else {
-				row_log_rowq(rd, currq,
-						 "Delayed work pending. Exiting");
-				goto done;
-			}
-		}
+	currq = row_get_next_queue(q, rd, start_idx, end_idx);
 
-		if (!force && row_queues_def[currq].idling_enabled &&
-		    rd->row_queues[currq].idle_data.begin_idling) {
-			if (!queue_delayed_work(rd->read_idle.idle_workqueue,
-						&rd->read_idle.idle_work,
-						rd->read_idle.idle_time)) {
-				row_log_rowq(rd, currq,
-					     "Work already on queue!");
-				pr_err("ROW_BUG: Work already on queue!");
-			} else
-				row_log_rowq(rd, currq,
-				     "Scheduled delayed work. exiting");
-			goto done;
-		} else {
-			row_log_rowq(rd, currq,
-				     "Currq empty. Choose next queue");
-			ret = row_choose_queue(rd);
-			if (!ret)
-				goto done;
-		}
+	/* Dispatch */
+	if (currq >= 0) {
+		row_dispatch_insert(rd, currq);
+		ret = 1;
 	}
-
-	ret = 1;
-	row_dispatch_insert(rd);
-
 done:
 	return ret;
 }
@@ -541,6 +649,7 @@
 	if (!rdata)
 		return NULL;
 
+	memset(rdata, 0, sizeof(*rdata));
 	for (i = 0; i < ROWQ_MAX_PRIO; i++) {
 		INIT_LIST_HEAD(&rdata->row_queues[i].fifo);
 		rdata->row_queues[i].disp_quantum = row_queues_def[i].quantum;
@@ -556,22 +665,17 @@
 	 * enable it for write queues also, note that idling frequency will
 	 * be the same in both cases
 	 */
-	rdata->read_idle.idle_time = msecs_to_jiffies(ROW_IDLE_TIME_MSEC);
-	/* Maybe 0 on some platforms */
-	if (!rdata->read_idle.idle_time)
-		rdata->read_idle.idle_time = 1;
-	rdata->read_idle.freq = ROW_READ_FREQ_MSEC;
-	rdata->read_idle.idle_workqueue = alloc_workqueue("row_idle_work",
-					    WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
-	if (!rdata->read_idle.idle_workqueue)
-		panic("Failed to create idle workqueue\n");
-	INIT_DELAYED_WORK(&rdata->read_idle.idle_work, kick_queue);
+	rdata->rd_idle_data.idle_time_ms = ROW_IDLE_TIME_MSEC;
+	rdata->rd_idle_data.freq_ms = ROW_READ_FREQ_MSEC;
+	hrtimer_init(&rdata->rd_idle_data.hr_timer,
+		CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	rdata->rd_idle_data.hr_timer.function = &row_idle_hrtimer_fn;
 
-	rdata->curr_queue = ROWQ_PRIO_HIGH_READ;
+	INIT_WORK(&rdata->rd_idle_data.idle_work, kick_queue);
+
+	rdata->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
 	rdata->dispatch_queue = q;
 
-	rdata->nr_reqs[READ] = rdata->nr_reqs[WRITE] = 0;
-
 	return rdata;
 }
 
@@ -587,9 +691,9 @@
 
 	for (i = 0; i < ROWQ_MAX_PRIO; i++)
 		BUG_ON(!list_empty(&rd->row_queues[i].fifo));
-	(void)cancel_delayed_work_sync(&rd->read_idle.idle_work);
-	BUG_ON(delayed_work_pending(&rd->read_idle.idle_work));
-	destroy_workqueue(rd->read_idle.idle_workqueue);
+	if (hrtimer_cancel(&rd->rd_idle_data.hr_timer))
+		pr_err("ROW BUG: idle timer was active!");
+	rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
 	kfree(rd);
 }
 
@@ -611,26 +715,57 @@
 }
 
 /*
- * get_queue_type() - Get queue type for a given request
+ * row_get_queue_prio() - Get queue priority for a given request
  *
  * This is a helping function which purpose is to determine what
  * ROW queue the given request should be added to (and
- * dispatched from leter on)
+ * dispatched from later on)
  *
- * TODO: Right now only 3 queues are used REG_READ, REG_WRITE
- * and REG_SWRITE
  */
-static enum row_queue_prio get_queue_type(struct request *rq)
+static enum row_queue_prio row_get_queue_prio(struct request *rq)
 {
 	const int data_dir = rq_data_dir(rq);
 	const bool is_sync = rq_is_sync(rq);
+	enum row_queue_prio q_type = ROWQ_MAX_PRIO;
+	int ioprio_class = IOPRIO_PRIO_CLASS(rq->elv.icq->ioc->ioprio);
 
-	if (data_dir == READ)
-		return ROWQ_PRIO_REG_READ;
-	else if (is_sync)
-		return ROWQ_PRIO_REG_SWRITE;
-	else
-		return ROWQ_PRIO_REG_WRITE;
+	switch (ioprio_class) {
+	case IOPRIO_CLASS_RT:
+		if (data_dir == READ)
+			q_type = ROWQ_PRIO_HIGH_READ;
+		else if (is_sync)
+			q_type = ROWQ_PRIO_HIGH_SWRITE;
+		else {
+			pr_err("%s:%s(): got a simple write from RT_CLASS. How???",
+				rq->rq_disk->disk_name, __func__);
+			q_type = ROWQ_PRIO_REG_WRITE;
+		}
+		rq->cmd_flags |= REQ_URGENT;
+		break;
+	case IOPRIO_CLASS_IDLE:
+		if (data_dir == READ)
+			q_type = ROWQ_PRIO_LOW_READ;
+		else if (is_sync)
+			q_type = ROWQ_PRIO_LOW_SWRITE;
+		else {
+			pr_err("%s:%s(): got a simple write from IDLE_CLASS. How???",
+				rq->rq_disk->disk_name, __func__);
+			q_type = ROWQ_PRIO_REG_WRITE;
+		}
+		break;
+	case IOPRIO_CLASS_NONE:
+	case IOPRIO_CLASS_BE:
+	default:
+		if (data_dir == READ)
+			q_type = ROWQ_PRIO_REG_READ;
+		else if (is_sync)
+			q_type = ROWQ_PRIO_REG_SWRITE;
+		else
+			q_type = ROWQ_PRIO_REG_WRITE;
+		break;
+	}
+
+	return q_type;
 }
 
 /*
@@ -648,7 +783,7 @@
 
 	spin_lock_irqsave(q->queue_lock, flags);
 	rq->elv.priv[0] =
-		(void *)(&rd->row_queues[get_queue_type(rq)]);
+		(void *)(&rd->row_queues[row_get_queue_prio(rq)]);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	return 0;
@@ -691,8 +826,8 @@
 	rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum, 0);
 SHOW_FUNCTION(row_lp_swrite_quantum_show,
 	rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, 0);
-SHOW_FUNCTION(row_read_idle_show, rowd->read_idle.idle_time, 0);
-SHOW_FUNCTION(row_read_idle_freq_show, rowd->read_idle.freq, 0);
+SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms, 0);
+SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms, 0);
 #undef SHOW_FUNCTION
 
 #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)			\
@@ -730,9 +865,11 @@
 			1, INT_MAX, 0);
 STORE_FUNCTION(row_lp_swrite_quantum_store,
 			&rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum,
-			1, INT_MAX, 1);
-STORE_FUNCTION(row_read_idle_store, &rowd->read_idle.idle_time, 1, INT_MAX, 0);
-STORE_FUNCTION(row_read_idle_freq_store, &rowd->read_idle.freq, 1, INT_MAX, 0);
+			1, INT_MAX, 0);
+STORE_FUNCTION(row_rd_idle_data_store, &rowd->rd_idle_data.idle_time_ms,
+			1, INT_MAX, 0);
+STORE_FUNCTION(row_rd_idle_data_freq_store, &rowd->rd_idle_data.freq_ms,
+			1, INT_MAX, 0);
 
 #undef STORE_FUNCTION
 
@@ -748,8 +885,8 @@
 	ROW_ATTR(rp_write_quantum),
 	ROW_ATTR(lp_read_quantum),
 	ROW_ATTR(lp_swrite_quantum),
-	ROW_ATTR(read_idle),
-	ROW_ATTR(read_idle_freq),
+	ROW_ATTR(rd_idle_data),
+	ROW_ATTR(rd_idle_data_freq),
 	__ATTR_NULL
 };
 
@@ -760,13 +897,15 @@
 		.elevator_add_req_fn		= row_add_request,
 		.elevator_reinsert_req_fn	= row_reinsert_req,
 		.elevator_is_urgent_fn		= row_urgent_pending,
+		.elevator_completed_req_fn	= row_completed_req,
 		.elevator_former_req_fn		= elv_rb_former_request,
 		.elevator_latter_req_fn		= elv_rb_latter_request,
 		.elevator_set_req_fn		= row_set_request,
 		.elevator_init_fn		= row_init_queue,
 		.elevator_exit_fn		= row_exit_queue,
 	},
-
+	.icq_size = sizeof(struct io_cq),
+	.icq_align = __alignof__(struct io_cq),
 	.elevator_attrs = row_attrs,
 	.elevator_name = "row",
 	.elevator_owner = THIS_MODULE,
diff --git a/block/test-iosched.c b/block/test-iosched.c
index 23c9581..c4cfb17 100644
--- a/block/test-iosched.c
+++ b/block/test-iosched.c
@@ -576,7 +576,7 @@
 		return ret;
 	}
 
-	__blk_run_queue(td->req_q);
+	blk_run_queue(td->req_q);
 
 	return 0;
 }
@@ -800,7 +800,7 @@
 		 * Wakeup the queue thread to fetch FS requests that might got
 		 * postponded due to the test
 		 */
-		__blk_run_queue(ptd->req_q);
+		blk_run_queue(ptd->req_q);
 
 		if (ptd->ignore_round)
 			test_pr_info(
diff --git a/drivers/Makefile b/drivers/Makefile
index bd18a62..f461e83 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -141,4 +141,4 @@
 #MobiCore
 obj-$(CONFIG_MOBICORE_SUPPORT)  += gud/
 
-obj-$(CONFIG_MSM_QDSS)		+= coresight/
+obj-$(CONFIG_CORESIGHT)		+= coresight/
diff --git a/drivers/base/sw_sync.c b/drivers/base/sw_sync.c
index 935769c7..14d3f39 100644
--- a/drivers/base/sw_sync.c
+++ b/drivers/base/sw_sync.c
@@ -71,23 +71,6 @@
 	return sw_sync_cmp(pt_a->value, pt_b->value);
 }
 
-static void sw_sync_print_obj(struct seq_file *s,
-			      struct sync_timeline *sync_timeline)
-{
-	struct sw_sync_timeline *obj = (struct sw_sync_timeline *)sync_timeline;
-
-	seq_printf(s, "%d", obj->value);
-}
-
-static void sw_sync_print_pt(struct seq_file *s, struct sync_pt *sync_pt)
-{
-	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
-	struct sw_sync_timeline *obj =
-		(struct sw_sync_timeline *)sync_pt->parent;
-
-	seq_printf(s, "%d / %d", pt->value, obj->value);
-}
-
 static int sw_sync_fill_driver_data(struct sync_pt *sync_pt,
 				    void *data, int size)
 {
@@ -101,14 +84,29 @@
 	return sizeof(pt->value);
 }
 
+static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline,
+				       char *str, int size)
+{
+	struct sw_sync_timeline *timeline =
+		(struct sw_sync_timeline *)sync_timeline;
+	snprintf(str, size, "%d", timeline->value);
+}
+
+static void sw_sync_pt_value_str(struct sync_pt *sync_pt,
+				       char *str, int size)
+{
+	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+	snprintf(str, size, "%d", pt->value);
+}
+
 struct sync_timeline_ops sw_sync_timeline_ops = {
 	.driver_name = "sw_sync",
 	.dup = sw_sync_pt_dup,
 	.has_signaled = sw_sync_pt_has_signaled,
 	.compare = sw_sync_pt_compare,
-	.print_obj = sw_sync_print_obj,
-	.print_pt = sw_sync_print_pt,
 	.fill_driver_data = sw_sync_fill_driver_data,
+	.timeline_value_str = sw_sync_timeline_value_str,
+	.pt_value_str = sw_sync_pt_value_str,
 };
 
 
diff --git a/drivers/base/sync.c b/drivers/base/sync.c
index 202c40d..809d02b 100644
--- a/drivers/base/sync.c
+++ b/drivers/base/sync.c
@@ -229,10 +229,8 @@
 	spin_lock_irqsave(&obj->active_list_lock, flags);
 
 	err = _sync_pt_has_signaled(pt);
-	if (err != 0) {
-		sync_fence_signal_pt(pt);
+	if (err != 0)
 		goto out;
-	}
 
 	list_add_tail(&pt->active_list, &obj->active_list_head);
 
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 2bc0de3..23dd5a1 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -152,7 +152,8 @@
 	uint16_t event_id, event_id_packet;
 	uint8_t *event_mask_ptr, byte_mask, payload_len;
 	uint8_t event_data[MAX_EVENT_SIZE], timestamp[8];
-	int i, byte_index, bit_index, length, temp_len;
+	unsigned int byte_index;
+	int i, bit_index, length, temp_len;
 	int total_event_len, payload_len_field, timestamp_len;
 	struct diag_dci_client_tbl *entry;
 
@@ -227,7 +228,8 @@
 {
 	uint16_t log_code, item_num;
 	uint8_t equip_id, *log_mask_ptr, byte_mask;
-	int i, byte_index, found = 0;
+	unsigned int byte_index;
+	int i, found = 0;
 	struct diag_dci_client_tbl *entry;
 
 	log_code = *(uint16_t *)(buf+6);
@@ -385,6 +387,10 @@
 
 	/* remove UID from user space pkt before sending to peripheral */
 	buf = buf + 4;
+	if (len > APPS_BUF_SIZE - 10) {
+		pr_err("diag: dci: buffer overwrite possible since payload bigger than buf size\n");
+		return -EIO;
+	}
 	len = len - 4;
 	mutex_lock(&driver->dci_mutex);
 	/* prepare DCI packet */
@@ -396,7 +402,6 @@
 		driver->req_tracking_tbl[index].tag;
 	for (i = 0; i < len; i++)
 		driver->apps_dci_buf[i+9] = *(buf+i);
-
 	driver->apps_dci_buf[9+len] = CONTROL_CHAR; /* end */
 
 	for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
@@ -448,12 +453,12 @@
 {
 	unsigned char *temp = buf;
 	uint16_t subsys_cmd_code, log_code, item_num;
-	int subsys_id, cmd_code, i, ret = -1, index = -1, found = 0;
+	int subsys_id, cmd_code, ret = -1, index = -1, found = 0, read_len = 0;
 	struct diag_master_table entry;
-	int count, set_mask, num_codes, byte_index, bit_index, event_id;
+	int count, set_mask, num_codes, bit_index, event_id, offset = 0, i;
+	unsigned int byte_index;
 	uint8_t equip_id, *log_mask_ptr, *head_log_mask_ptr, byte_mask;
 	uint8_t *event_mask_ptr;
-	int offset = 0;
 
 	if (!driver->smd_dci[MODEM_DATA].ch) {
 		pr_err("diag: DCI smd channel for peripheral %d not valid for dci updates\n",
@@ -529,19 +534,30 @@
 		}
 		/* Extract each log code and put in client table */
 		temp += 4;
+		read_len += 4;
 		set_mask = *(int *)temp;
 		temp += 4;
+		read_len += 4;
 		num_codes = *(int *)temp;
 		temp += 4;
+		read_len += 4;
 
 		head_log_mask_ptr = driver->dci_client_tbl[i].dci_log_mask;
 		pr_debug("diag: head of dci log mask %p\n", head_log_mask_ptr);
 		count = 0; /* iterator for extracting log codes */
 		while (count < num_codes) {
+			if (read_len >= USER_SPACE_DATA) {
+				pr_err("diag: dci: Log type, possible buffer overflow\n");
+				return -EIO;
+			}
 			log_code = *(uint16_t *)temp;
 			equip_id = LOG_GET_EQUIP_ID(log_code);
 			item_num = LOG_GET_ITEM_NUM(log_code);
 			byte_index = item_num/8 + 2;
+			if (byte_index >= (DCI_MAX_ITEMS_PER_LOG_CODE+2)) {
+				pr_err("diag: dci: Log type, invalid byte index\n");
+				return ret;
+			}
 			byte_mask = 0x01 << (item_num % 8);
 			/*
 			 * Parse through log mask table and find
@@ -550,7 +566,7 @@
 			log_mask_ptr = head_log_mask_ptr;
 			found = 0;
 			offset = 0;
-			while (log_mask_ptr) {
+			while (log_mask_ptr && (offset < DCI_LOG_MASK_SIZE)) {
 				if (*log_mask_ptr == equip_id) {
 					found = 1;
 					pr_debug("diag: find equip id = %x at %p\n",
@@ -578,6 +594,7 @@
 				offset, byte_index,
 				byte_mask);
 			temp += 2;
+			read_len += 2;
 			count++;
 			ret = DIAG_DCI_NO_ERROR;
 		}
@@ -600,17 +617,28 @@
 		}
 		/* Extract each log code and put in client table */
 		temp += 4;
+		read_len += 4;
 		set_mask = *(int *)temp;
 		temp += 4;
+		read_len += 4;
 		num_codes = *(int *)temp;
 		temp += 4;
+		read_len += 4;
 
 		event_mask_ptr = driver->dci_client_tbl[i].dci_event_mask;
 		pr_debug("diag: head of dci event mask %p\n", event_mask_ptr);
 		count = 0; /* iterator for extracting log codes */
 		while (count < num_codes) {
+			if (read_len >= USER_SPACE_DATA) {
+				pr_err("diag: dci: Event type, possible buffer overflow\n");
+				return -EIO;
+			}
 			event_id = *(int *)temp;
 			byte_index = event_id/8;
+			if (byte_index >= DCI_EVENT_MASK_SIZE) {
+				pr_err("diag: dci: Event type, invalid byte index\n");
+				return ret;
+			}
 			bit_index = event_id % 8;
 			byte_mask = 0x1 << bit_index;
 			/*
@@ -624,6 +652,7 @@
 			/* add to cumulative mask */
 			update_dci_cumulative_event_mask(byte_index, byte_mask);
 			temp += sizeof(int);
+			read_len += sizeof(int);
 			count++;
 			ret = DIAG_DCI_NO_ERROR;
 		}
@@ -704,7 +733,7 @@
 	return ret;
 }
 
-void update_dci_cumulative_log_mask(int offset, int byte_index,
+void update_dci_cumulative_log_mask(int offset, unsigned int byte_index,
 						uint8_t byte_mask)
 {
 	int i;
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 69d393b..56d1b91 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -88,7 +88,7 @@
 void extract_dci_pkt_rsp(unsigned char *buf);
 /* DCI Log streaming functions */
 void create_dci_log_mask_tbl(unsigned char *tbl_buf);
-void update_dci_cumulative_log_mask(int offset, int byte_index,
+void update_dci_cumulative_log_mask(int offset, unsigned int byte_index,
 						uint8_t byte_mask);
 int diag_send_dci_log_mask(smd_channel_t *ch);
 void extract_dci_log(unsigned char *buf);
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index d852d75..76490c8 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,10 +17,12 @@
 #include "diagchar.h"
 #include "diagfwd.h"
 #include "diagfwd_bridge.h"
+#include "diagfwd_hsic.h"
 
 #define DEBUG_BUF_SIZE	4096
 static struct dentry *diag_dbgfs_dent;
 static int diag_dbgfs_table_index;
+static int diag_dbgfs_finished;
 
 static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf,
 				      size_t count, loff_t *ppos)
@@ -233,61 +235,115 @@
 {
 	char *buf;
 	int ret;
+	int i;
+	int bytes_remaining;
+	int bytes_in_buffer = 0;
+	int bytes_written;
+	int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+	int bytes_hsic_inited = 45;
+	int bytes_hsic_not_inited = 410;
 
-	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (diag_dbgfs_finished) {
+		diag_dbgfs_finished = 0;
+		return 0;
+	}
+
+	buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL);
 	if (!buf) {
 		pr_err("diag: %s, Error allocating memory\n", __func__);
 		return -ENOMEM;
 	}
 
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
-		"hsic ch: %d\n"
-		"hsic_inited: %d\n"
-		"hsic enabled: %d\n"
-		"hsic_opened: %d\n"
-		"hsic_suspend: %d\n"
-		"in_busy_hsic_read_on_device: %d\n"
-		"in_busy_hsic_write: %d\n"
-		"count_hsic_pool: %d\n"
-		"count_hsic_write_pool: %d\n"
-		"diag_hsic_pool: %x\n"
-		"diag_hsic_write_pool: %x\n"
-		"HSIC write_len: %d\n"
-		"num_hsic_buf_tbl_entries: %d\n"
-		"HSIC usb_connected: %d\n"
-		"HSIC diag_read_work: %d\n"
-		"diag_read_hsic_work: %d\n"
-		"diag_disconnect_work: %d\n"
-		"diag_usb_read_complete_work: %d\n"
+	bytes_remaining = buf_size;
+
+	/* Only one smux for now */
+	bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
+		"Values for SMUX instance: 0\n"
 		"smux ch: %d\n"
 		"smux enabled %d\n"
 		"smux in busy %d\n"
-		"smux connected %d\n",
-		driver->hsic_ch,
-		driver->hsic_inited,
-		driver->hsic_device_enabled,
-		driver->hsic_device_opened,
-		driver->hsic_suspend,
-		driver->in_busy_hsic_read_on_device,
-		driver->in_busy_hsic_write,
-		driver->count_hsic_pool,
-		driver->count_hsic_write_pool,
-		(unsigned int)driver->diag_hsic_pool,
-		(unsigned int)driver->diag_hsic_write_pool,
-			diag_bridge[HSIC].write_len,
-		driver->num_hsic_buf_tbl_entries,
-			diag_bridge[HSIC].usb_connected,
-			work_pending(&(diag_bridge[HSIC].diag_read_work)),
-		work_pending(&(driver->diag_read_hsic_work)),
-		work_pending(&(driver->diag_disconnect_work)),
-		work_pending(&(diag_bridge[HSIC].usb_read_complete_work)),
+		"smux connected %d\n\n",
 		driver->lcid,
 		driver->diag_smux_enabled,
 		driver->in_busy_smux,
 		driver->smux_connected);
 
-	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+	bytes_in_buffer += bytes_written;
+	bytes_remaining = buf_size - bytes_in_buffer;
 
+	bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
+		"HSIC diag_disconnect_work: %d\n",
+		work_pending(&(driver->diag_disconnect_work)));
+
+	bytes_in_buffer += bytes_written;
+	bytes_remaining = buf_size - bytes_in_buffer;
+
+	for (i = 0; i < MAX_HSIC_CH; i++) {
+		if (diag_hsic[i].hsic_inited) {
+			/* Check if there is room to add another HSIC entry */
+			if (bytes_remaining < bytes_hsic_inited)
+				break;
+			bytes_written = scnprintf(buf+bytes_in_buffer,
+							bytes_remaining,
+			"Values for HSIC Instance: %d\n"
+			"hsic ch: %d\n"
+			"hsic_inited: %d\n"
+			"hsic enabled: %d\n"
+			"hsic_opened: %d\n"
+			"hsic_suspend: %d\n"
+			"in_busy_hsic_read_on_device: %d\n"
+			"in_busy_hsic_write: %d\n"
+			"count_hsic_pool: %d\n"
+			"count_hsic_write_pool: %d\n"
+			"diag_hsic_pool: %x\n"
+			"diag_hsic_write_pool: %x\n"
+			"HSIC write_len: %d\n"
+			"num_hsic_buf_tbl_entries: %d\n"
+			"HSIC usb_connected: %d\n"
+			"HSIC diag_read_work: %d\n"
+			"diag_read_hsic_work: %d\n"
+			"diag_usb_read_complete_work: %d\n\n",
+			i,
+			diag_hsic[i].hsic_ch,
+			diag_hsic[i].hsic_inited,
+			diag_hsic[i].hsic_device_enabled,
+			diag_hsic[i].hsic_device_opened,
+			diag_hsic[i].hsic_suspend,
+			diag_hsic[i].in_busy_hsic_read_on_device,
+			diag_hsic[i].in_busy_hsic_write,
+			diag_hsic[i].count_hsic_pool,
+			diag_hsic[i].count_hsic_write_pool,
+			(unsigned int)diag_hsic[i].diag_hsic_pool,
+			(unsigned int)diag_hsic[i].diag_hsic_write_pool,
+			diag_bridge[i].write_len,
+			diag_hsic[i].num_hsic_buf_tbl_entries,
+			diag_bridge[i].usb_connected,
+			work_pending(&(diag_bridge[i].diag_read_work)),
+			work_pending(&(diag_hsic[i].diag_read_hsic_work)),
+			work_pending(&(diag_bridge[i].usb_read_complete_work)));
+			if (bytes_written > bytes_hsic_inited)
+				bytes_hsic_inited = bytes_written;
+		} else {
+			/* Check if there is room to add another HSIC entry */
+			if (bytes_remaining < bytes_hsic_not_inited)
+				break;
+			bytes_written = scnprintf(buf+bytes_in_buffer,
+				bytes_remaining,
+				"HSIC Instance: %d has not been initialized\n\n",
+				i);
+			if (bytes_written > bytes_hsic_not_inited)
+				bytes_hsic_not_inited = bytes_written;
+		}
+
+		bytes_in_buffer += bytes_written;
+
+		bytes_remaining = buf_size - bytes_in_buffer;
+	}
+
+	*ppos = 0;
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
+
+	diag_dbgfs_finished = 1;
 	kfree(buf);
 	return ret;
 }
@@ -330,6 +386,7 @@
 #endif
 
 	diag_dbgfs_table_index = 0;
+	diag_dbgfs_finished = 0;
 }
 
 void diag_debugfs_cleanup(void)
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index e8567db..0c93101 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -525,6 +525,10 @@
 			*(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
 			*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
 			payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
+			if (payload_length > APPS_BUF_SIZE - 12) {
+				pr_err("diag: log masks: buffer overflow\n");
+				return -EIO;
+			}
 			for (i = 0; i < payload_length; i++)
 				*(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
 
@@ -608,6 +612,10 @@
 					rt_last_ssid) {
 					rt_mask_size = 4 * (rt_last_ssid -
 						rt_first_ssid + 1);
+					if (rt_mask_size > APPS_BUF_SIZE - 8) {
+						pr_err("diag: rt masks: buffer overflow\n");
+						return -EIO;
+					}
 					memcpy(driver->apps_rsp_buf+8,
 						rt_mask_ptr, rt_mask_size);
 					encode_rsp_and_send(8+rt_mask_size-1);
@@ -621,7 +629,17 @@
 	else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
 		ssid_first = *(uint16_t *)(buf + 2);
 		ssid_last = *(uint16_t *)(buf + 4);
+		if (ssid_last < ssid_first) {
+			pr_err("diag: Invalid msg mask ssid values, first: %d, last: %d\n",
+				ssid_first, ssid_last);
+			return -EIO;
+		}
 		ssid_range = 4 * (ssid_last - ssid_first + 1);
+		if (ssid_range > APPS_BUF_SIZE - 8) {
+			pr_err("diag: Not enough space for message mask, ssid_range: %d\n",
+				ssid_range);
+			return -EIO;
+		}
 		pr_debug("diag: received mask update for ssid_first = %d, ssid_last = %d",
 			ssid_first, ssid_last);
 		diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 0e74cdf..df28dab 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -38,16 +38,19 @@
 #define POOL_TYPE_COPY		1
 #define POOL_TYPE_HDLC		2
 #define POOL_TYPE_WRITE_STRUCT	4
-#define POOL_TYPE_HSIC		8
-#define POOL_TYPE_HSIC_WRITE	16
-#define POOL_TYPE_ALL		7
+#define POOL_TYPE_HSIC		5
+#define POOL_TYPE_HSIC_2	6
+#define POOL_TYPE_HSIC_WRITE	11
+#define POOL_TYPE_HSIC_2_WRITE	12
+#define POOL_TYPE_ALL		10
 #define MODEM_DATA		0
 #define LPASS_DATA		1
 #define WCNSS_DATA		2
 #define APPS_DATA		3
 #define SDIO_DATA		4
 #define HSIC_DATA		5
-#define SMUX_DATA		6
+#define HSIC_2_DATA		6
+#define SMUX_DATA		10
 #define APPS_PROC		1
 #define MSG_MASK_SIZE 10000
 #define LOG_MASK_SIZE 8000
@@ -96,7 +99,10 @@
 /* List of remote processor supported */
 enum remote_procs {
 	MDM = 1,
-	QSC = 2,
+	MDM2 = 2,
+	MDM3 = 3,
+	MDM4 = 4,
+	QSC = 5,
 };
 
 struct diag_master_table {
@@ -295,30 +301,11 @@
 	int diag_smux_enabled;
 	int smux_connected;
 	struct diag_request *write_ptr_mdm;
-	/* HSIC variables */
-	int hsic_ch;
-	int hsic_inited;
-	int hsic_device_enabled;
-	int hsic_device_opened;
-	int hsic_suspend;
-	int in_busy_hsic_read_on_device;
-	int in_busy_hsic_write;
-	struct work_struct diag_read_hsic_work;
-	int count_hsic_pool;
-	int count_hsic_write_pool;
-	unsigned int poolsize_hsic;
-	unsigned int poolsize_hsic_write;
-	unsigned int itemsize_hsic;
-	unsigned int itemsize_hsic_write;
-	mempool_t *diag_hsic_pool;
-	mempool_t *diag_hsic_write_pool;
-	int num_hsic_buf_tbl_entries;
-	struct diag_write_device *hsic_buf_tbl;
-	spinlock_t hsic_spinlock;
 #endif
 };
 
 extern struct diag_bridge_dev *diag_bridge;
+extern struct diag_hsic_dev *diag_hsic;
 extern struct diagchar_dev *driver;
 
 extern int wrap_enabled;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index d2454f4..13e52df 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/uaccess.h>
 #include <linux/diagchar.h>
+#include <linux/platform_device.h>
 #include <linux/sched.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <mach/usbdiag.h>
@@ -141,18 +142,23 @@
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 void diag_clear_hsic_tbl(void)
 {
-	int i;
+	int i, j;
 
-	driver->num_hsic_buf_tbl_entries = 0;
-	for (i = 0; i < driver->poolsize_hsic_write; i++) {
-		if (driver->hsic_buf_tbl[i].buf) {
-			/* Return the buffer to the pool */
-			diagmem_free(driver, (unsigned char *)
-				(driver->hsic_buf_tbl[i].buf),
-				POOL_TYPE_HSIC);
-			driver->hsic_buf_tbl[i].buf = 0;
+	/* Clear for all active HSIC bridges */
+	for (j = 0; j < MAX_HSIC_CH; j++) {
+		if (diag_hsic[j].hsic_ch) {
+			diag_hsic[j].num_hsic_buf_tbl_entries = 0;
+			for (i = 0; i < diag_hsic[j].poolsize_hsic_write; i++) {
+				if (diag_hsic[j].hsic_buf_tbl[i].buf) {
+					/* Return the buffer to the pool */
+					diagmem_free(driver, (unsigned char *)
+						(diag_hsic[j].hsic_buf_tbl[i].
+						 buf), j+POOL_TYPE_HSIC);
+					diag_hsic[j].hsic_buf_tbl[i].buf = 0;
+				}
+				diag_hsic[j].hsic_buf_tbl[i].length = 0;
+			}
 		}
-		driver->hsic_buf_tbl[i].length = 0;
 	}
 }
 #else
@@ -298,7 +304,7 @@
 	diagmem_exit(driver, POOL_TYPE_WRITE_STRUCT);
 	for (i = 0; i < driver->num_clients; i++) {
 		if (NULL != diagpriv_data && diagpriv_data->pid ==
-			 driver->client_map[i].pid) {
+						driver->client_map[i].pid) {
 			driver->client_map[i].pid = 0;
 			kfree(diagpriv_data);
 			diagpriv_data = NULL;
@@ -376,25 +382,6 @@
 	(*count_entries)++;
 }
 
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-uint16_t diag_get_remote_device_mask(void)
-{
-	uint16_t remote_dev = 0;
-
-	/* Check for MDM processor */
-	if (driver->hsic_inited)
-		remote_dev |= 1 << 0;
-
-	/* Check for QSC processor */
-	if (driver->diag_smux_enabled)
-		remote_dev |= 1 << 1;
-
-	return remote_dev;
-}
-#else
-inline uint16_t diag_get_remote_device_mask(void) { return 0; }
-#endif
-
 static int diag_get_remote(int remote_info)
 {
 	int val = (remote_info < 0) ? -remote_info : remote_info;
@@ -402,6 +389,9 @@
 
 	switch (val) {
 	case MDM:
+	case MDM2:
+	case MDM3:
+	case MDM4:
 	case QSC:
 		remote_val = -remote_info;
 		break;
@@ -413,6 +403,130 @@
 	return remote_val;
 }
 
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+uint16_t diag_get_remote_device_mask(void)
+{
+	uint16_t remote_dev = 0;
+	int i;
+
+	/* Check for MDM processor */
+	for (i = 0; i < MAX_HSIC_CH; i++)
+		if (diag_hsic[i].hsic_inited)
+			remote_dev |= 1 << i;
+
+	/* Check for QSC processor */
+	if (driver->diag_smux_enabled)
+		remote_dev |= 1 << SMUX;
+
+	return remote_dev;
+}
+
+int diag_copy_remote(char __user *buf, size_t count, int *pret, int *pnum_data)
+{
+	int i;
+	int index;
+	int exit_stat = 1;
+	int ret = *pret;
+	int num_data = *pnum_data;
+	int remote_token;
+	unsigned long spin_lock_flags;
+	struct diag_write_device hsic_buf_tbl[NUM_HSIC_BUF_TBL_ENTRIES];
+
+	remote_token = diag_get_remote(MDM);
+	for (index = 0; index < MAX_HSIC_CH; index++) {
+		if (!diag_hsic[index].hsic_inited) {
+			remote_token--;
+			continue;
+		}
+
+		spin_lock_irqsave(&diag_hsic[index].hsic_spinlock,
+			spin_lock_flags);
+		for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) {
+			hsic_buf_tbl[i].buf =
+				diag_hsic[index].hsic_buf_tbl[i].buf;
+			diag_hsic[index].hsic_buf_tbl[i].buf = 0;
+			hsic_buf_tbl[i].length =
+				diag_hsic[index].hsic_buf_tbl[i].length;
+			diag_hsic[index].hsic_buf_tbl[i].length = 0;
+		}
+		diag_hsic[index].num_hsic_buf_tbl_entries = 0;
+		spin_unlock_irqrestore(&diag_hsic[index].hsic_spinlock,
+			spin_lock_flags);
+
+		for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) {
+			if (hsic_buf_tbl[i].length > 0) {
+				pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n",
+					i, (unsigned int)hsic_buf_tbl[i].buf,
+					hsic_buf_tbl[i].length);
+				num_data++;
+
+				/* Copy the negative token */
+				if (copy_to_user(buf+ret,
+					&remote_token, 4)) {
+						num_data--;
+						goto drop_hsic;
+				}
+				ret += 4;
+
+				/* Copy the length of data being passed */
+				if (copy_to_user(buf+ret,
+					(void *)&(hsic_buf_tbl[i].length),
+					4)) {
+						num_data--;
+						goto drop_hsic;
+				}
+				ret += 4;
+
+				/* Copy the actual data being passed */
+				if (copy_to_user(buf+ret,
+					(void *)hsic_buf_tbl[i].buf,
+					hsic_buf_tbl[i].length)) {
+						ret -= 4;
+						num_data--;
+						goto drop_hsic;
+				}
+				ret += hsic_buf_tbl[i].length;
+drop_hsic:
+				/* Return the buffer to the pool */
+				diagmem_free(driver,
+					(unsigned char *)(hsic_buf_tbl[i].buf),
+					index+POOL_TYPE_HSIC);
+
+				/* Call the write complete function */
+				diagfwd_write_complete_hsic(NULL, index);
+			}
+		}
+		remote_token--;
+	}
+	if (driver->in_busy_smux == 1) {
+		remote_token = diag_get_remote(QSC);
+		num_data++;
+
+		/* Copy the negative  token of data being passed */
+		COPY_USER_SPACE_OR_EXIT(buf+ret,
+			remote_token, 4);
+		/* Copy the length of data being passed */
+		COPY_USER_SPACE_OR_EXIT(buf+ret,
+			(driver->write_ptr_mdm->length), 4);
+		/* Copy the actual data being passed */
+		COPY_USER_SPACE_OR_EXIT(buf+ret,
+			*(driver->buf_in_smux),
+			driver->write_ptr_mdm->length);
+		pr_debug("diag: SMUX  data copied\n");
+		driver->in_busy_smux = 0;
+	}
+	exit_stat = 0;
+exit:
+	*pret = ret;
+	*pnum_data = num_data;
+	return exit_stat;
+}
+#else
+inline uint16_t diag_get_remote_device_mask(void) { return 0; }
+inline int diag_copy_remote(char __user *buf, size_t count, int *pret,
+			    int *pnum_data) { return 0; }
+#endif
+
 long diagchar_ioctl(struct file *filp,
 			   unsigned int iocmd, unsigned long ioarg)
 {
@@ -577,8 +691,10 @@
 			return -ENOMEM;
 		}
 		if (copy_from_user(dci_params, (void *)ioarg,
-				 sizeof(struct diag_dci_client_tbl)))
+				 sizeof(struct diag_dci_client_tbl))) {
+			kfree(dci_params);
 			return -EFAULT;
+		}
 		mutex_lock(&driver->dci_mutex);
 		if (!(driver->num_dci_client))
 			for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++)
@@ -610,8 +726,8 @@
 				break;
 			}
 		}
-		mutex_unlock(&driver->dci_mutex);
 		kfree(dci_params);
+		mutex_unlock(&driver->dci_mutex);
 		return driver->dci_client_id;
 	} else if (iocmd == DIAG_IOCTL_DCI_DEINIT) {
 		success = -1;
@@ -819,6 +935,7 @@
 	int index = -1, i = 0, ret = 0;
 	int num_data = 0, data_type;
 	int remote_token;
+	int exit_stat;
 
 	for (i = 0; i < driver->num_clients; i++)
 		if (driver->client_map[i].pid == current->tgid)
@@ -835,10 +952,6 @@
 
 	if ((driver->data_ready[index] & USER_SPACE_DATA_TYPE) && (driver->
 					logging_mode == MEMORY_DEVICE_MODE)) {
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-		unsigned long spin_lock_flags;
-		struct diag_write_device hsic_buf_tbl[NUM_HSIC_BUF_TBL_ENTRIES];
-#endif
 		remote_token = 0;
 		pr_debug("diag: process woken up\n");
 		/*Copy the type of data being passed*/
@@ -931,81 +1044,11 @@
 			driver->in_busy_sdio = 0;
 		}
 #endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-		spin_lock_irqsave(&driver->hsic_spinlock, spin_lock_flags);
-		for (i = 0; i < driver->poolsize_hsic_write; i++) {
-			hsic_buf_tbl[i].buf = driver->hsic_buf_tbl[i].buf;
-			driver->hsic_buf_tbl[i].buf = 0;
-			hsic_buf_tbl[i].length =
-					driver->hsic_buf_tbl[i].length;
-			driver->hsic_buf_tbl[i].length = 0;
-		}
-		driver->num_hsic_buf_tbl_entries = 0;
-		spin_unlock_irqrestore(&driver->hsic_spinlock,
-					spin_lock_flags);
+		/* Copy date from remote processors */
+		exit_stat = diag_copy_remote(buf, count, &ret, &num_data);
+		if (exit_stat == 1)
+			goto exit;
 
-		remote_token = diag_get_remote(MDM);
-		for (i = 0; i < driver->poolsize_hsic_write; i++) {
-			if (hsic_buf_tbl[i].length > 0) {
-				pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n",
-					 i, (unsigned int)hsic_buf_tbl[i].buf,
-					hsic_buf_tbl[i].length);
-				num_data++;
-
-				/* Copy the negative token */
-				if (copy_to_user(buf+ret,
-						&remote_token, 4)) {
-					num_data--;
-					goto drop_hsic;
-				}
-				ret += 4;
-
-				/* Copy the length of data being passed */
-				if (copy_to_user(buf+ret,
-					(void *)&(hsic_buf_tbl[i].length),
-					4)) {
-					num_data--;
-					goto drop_hsic;
-				}
-				ret += 4;
-
-				/* Copy the actual data being passed */
-				if (copy_to_user(buf+ret,
-						(void *)hsic_buf_tbl[i].buf,
-						hsic_buf_tbl[i].length)) {
-					ret -= 4;
-					num_data--;
-					goto drop_hsic;
-				}
-				ret += hsic_buf_tbl[i].length;
-drop_hsic:
-				/* Return the buffer to the pool */
-				diagmem_free(driver,
-					(unsigned char *)(hsic_buf_tbl[i].buf),
-					POOL_TYPE_HSIC);
-
-				/* Call the write complete function */
-				diagfwd_write_complete_hsic(NULL);
-			}
-		}
-		if (driver->in_busy_smux == 1) {
-			remote_token = diag_get_remote(QSC);
-			num_data++;
-
-			/* Copy the negative  token of data being passed */
-			COPY_USER_SPACE_OR_EXIT(buf+ret,
-						remote_token, 4);
-			/* Copy the length of data being passed */
-			COPY_USER_SPACE_OR_EXIT(buf+ret,
-					(driver->write_ptr_mdm->length), 4);
-			/* Copy the actual data being passed */
-			COPY_USER_SPACE_OR_EXIT(buf+ret,
-					*(driver->buf_in_smux),
-					driver->write_ptr_mdm->length);
-			pr_debug("diag: SMUX  data copied\n");
-			driver->in_busy_smux = 0;
-		}
-#endif
 		/* copy number of data fields */
 		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
 		ret -= 4;
@@ -1112,7 +1155,7 @@
 				size_t count, loff_t *ppos)
 {
 	int err, ret = 0, pkt_type, token_offset = 0;
-	int remote_proc = 0;
+	int remote_proc = 0, index;
 #ifdef DIAG_DEBUG
 	int length = 0, i;
 #endif
@@ -1127,6 +1170,7 @@
 		return -EIO;
 	}
 #endif /* DIAG over USB */
+	index = 0;
 	/* Get the packet type F3/log/event/Pkt response */
 	err = copy_from_user((&pkt_type), buf, 4);
 	/* First 4 bytes indicate the type of payload - ignore these */
@@ -1155,6 +1199,10 @@
 	if (pkt_type == USER_SPACE_DATA_TYPE) {
 		err = copy_from_user(driver->user_space_data, buf + 4,
 							 payload_size);
+		if (err) {
+			pr_err("diag: copy failed for user space data\n");
+			return -EIO;
+		}
 		/* Check for proc_type */
 		remote_proc = diag_get_remote(*(int *)driver->user_space_data);
 
@@ -1193,30 +1241,37 @@
 		}
 #endif
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-		/* send masks to 9k too */
-		if (driver->hsic_ch && (payload_size > 0) &&
-						(remote_proc == MDM)) {
-			/* wait sending mask updates if HSIC ch not ready */
-			if (driver->in_busy_hsic_write)
-				wait_event_interruptible(driver->wait_q,
-					(driver->in_busy_hsic_write != 1));
-			driver->in_busy_hsic_write = 1;
-			driver->in_busy_hsic_read_on_device = 0;
-			err = diag_bridge_write(
-					driver->user_space_data + token_offset,
-					payload_size);
-			if (err) {
-				pr_err("diag: err sending mask to MDM: %d\n",
-									 err);
-				/*
-				* If the error is recoverable, then clear
-				* the write flag, so we will resubmit a
-				* write on the next frame.  Otherwise, don't
-				* resubmit a write on the next frame.
-				*/
-				if ((-ESHUTDOWN) != err)
-					driver->in_busy_hsic_write = 0;
-			}
+		/* send masks to All 9k */
+		if ((remote_proc >= MDM) && (remote_proc <= MDM4)) {
+			index = remote_proc - MDM;
+			if (diag_hsic[index].hsic_ch && (payload_size > 0)) {
+				/* wait sending mask updates
+				 * if HSIC ch not ready */
+				if (diag_hsic[index].in_busy_hsic_write)
+					wait_event_interruptible(driver->wait_q,
+						(diag_hsic[index].
+						 in_busy_hsic_write != 1));
+				diag_hsic[index].in_busy_hsic_write = 1;
+				diag_hsic[index].in_busy_hsic_read_on_device =
+									0;
+				err = diag_bridge_write(index,
+						driver->user_space_data +
+						token_offset, payload_size);
+				if (err) {
+					pr_err("diag: err sending mask to MDM: %d\n",
+					       err);
+					/*
+					* If the error is recoverable, then
+					* clear the write flag, so we will
+					* resubmit a write on the next frame.
+					* Otherwise, don't resubmit a write
+					* on the next frame.
+					*/
+					if ((-ESHUTDOWN) != err)
+						diag_hsic[index].
+							in_busy_hsic_write = 0;
+				 }
+			 }
 		}
 		if (driver->diag_smux_enabled && (remote_proc == QSC)
 						&& driver->lcid) {
@@ -1540,15 +1595,20 @@
 static int __init diagchar_init(void)
 {
 	dev_t dev;
-	int error;
+	int error, ret;
 
 	pr_debug("diagfwd initializing ..\n");
+	ret = 0;
 	driver = kzalloc(sizeof(struct diagchar_dev) + 5, GFP_KERNEL);
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 	diag_bridge = kzalloc(MAX_BRIDGES * sizeof(struct diag_bridge_dev),
-								 GFP_KERNEL);
+								GFP_KERNEL);
 	if (!diag_bridge)
-		pr_warning("diag: could not allocate memory for bridge\n");
+		pr_warn("diag: could not allocate memory for bridges\n");
+	diag_hsic = kzalloc(MAX_HSIC_CH * sizeof(struct diag_hsic_dev),
+								GFP_KERNEL);
+	if (!diag_hsic)
+		pr_warn("diag: could not allocate memory for hsic ch\n");
 #endif
 
 	if (driver) {
@@ -1577,6 +1637,12 @@
 		diagfwd_init();
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 		diagfwd_bridge_init(HSIC);
+		diagfwd_bridge_init(HSIC_2);
+		/* register HSIC device */
+		ret = platform_driver_register(&msm_hsic_ch_driver);
+		if (ret)
+			pr_err("diag: could not register HSIC device, ret: %d\n",
+				ret);
 		diagfwd_bridge_init(SMUX);
 		INIT_WORK(&(driver->diag_disconnect_work),
 						 diag_disconnect_work_fn);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6091b1b..7f4edd1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -34,6 +34,7 @@
 #include "diagchar.h"
 #include "diagfwd.h"
 #include "diagfwd_cntl.h"
+#include "diagfwd_hsic.h"
 #include "diagchar_hdlc.h"
 #ifdef CONFIG_DIAG_SDIO_PIPE
 #include "diagfwd_sdio.h"
@@ -97,7 +98,7 @@
 
 int chk_config_get_id(void)
 {
-	/* For all Fusion targets, Modem will always be present */
+	/* For all Fusion targets,  Modem will always be present */
 	if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
 		return 0;
 
@@ -115,6 +116,7 @@
 			return AO8960_TOOLS_ID;
 		case MSM_CPU_8064:
 		case MSM_CPU_8064AB:
+		case MSM_CPU_8064AA:
 			return APQ8064_TOOLS_ID;
 		case MSM_CPU_8930:
 		case MSM_CPU_8930AA:
@@ -144,6 +146,7 @@
 	case MSM_CPU_8960AB:
 	case MSM_CPU_8064:
 	case MSM_CPU_8064AB:
+	case MSM_CPU_8064AA:
 	case MSM_CPU_8930:
 	case MSM_CPU_8930AA:
 	case MSM_CPU_8930AB:
@@ -350,7 +353,8 @@
 
 int diag_device_write(void *buf, int data_type, struct diag_request *write_ptr)
 {
-	int i, err = 0;
+	int i, err = 0, index;
+	index = 0;
 
 	if (driver->logging_mode == MEMORY_DEVICE_MODE) {
 		if (data_type == APPS_DATA) {
@@ -370,28 +374,34 @@
 		}
 
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-		else if (data_type == HSIC_DATA) {
+		else if (data_type == HSIC_DATA || data_type == HSIC_2_DATA) {
 			unsigned long flags;
 			int foundIndex = -1;
-
-			spin_lock_irqsave(&driver->hsic_spinlock, flags);
-			for (i = 0; i < driver->poolsize_hsic_write; i++) {
-				if (driver->hsic_buf_tbl[i].length == 0) {
-					driver->hsic_buf_tbl[i].buf = buf;
-					driver->hsic_buf_tbl[i].length =
-						diag_bridge[HSIC].write_len;
-					driver->num_hsic_buf_tbl_entries++;
+			index = data_type - HSIC_DATA;
+			spin_lock_irqsave(&diag_hsic[index].hsic_spinlock,
+									flags);
+			for (i = 0; i < diag_hsic[index].poolsize_hsic_write;
+									i++) {
+				if (diag_hsic[index].hsic_buf_tbl[i].length
+									== 0) {
+					diag_hsic[index].hsic_buf_tbl[i].buf
+									= buf;
+					diag_hsic[index].hsic_buf_tbl[i].length
+						= diag_bridge[index].write_len;
+					diag_hsic[index].
+						num_hsic_buf_tbl_entries++;
 					foundIndex = i;
 					break;
 				}
 			}
-			spin_unlock_irqrestore(&driver->hsic_spinlock, flags);
+			spin_unlock_irqrestore(&diag_hsic[index].hsic_spinlock,
+									flags);
 			if (foundIndex == -1)
 				err = -1;
 			else
-				pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d\n",
+				pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d, ch %d\n",
 					(unsigned int)buf,
-					 diag_bridge[HSIC].write_len);
+					 diag_bridge[index].write_len, index);
 		}
 #endif
 		for (i = 0; i < driver->num_clients; i++)
@@ -420,10 +430,12 @@
 		}
 #endif
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-		else if (data_type == HSIC_DATA) {
-			if (driver->hsic_ch)
-				queue_work(diag_bridge[HSIC].wq,
-					&(driver->diag_read_hsic_work));
+		else if (data_type == HSIC_DATA || data_type == HSIC_2_DATA) {
+			index = data_type - HSIC_DATA;
+			if (diag_hsic[index].hsic_ch)
+				queue_work(diag_bridge[index].wq,
+					   &(diag_hsic[index].
+					     diag_read_hsic_work));
 		}
 #endif
 		err = -1;
@@ -465,27 +477,30 @@
 		}
 #endif
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-		else if (data_type == HSIC_DATA) {
-			if (driver->hsic_device_enabled) {
+		else if (data_type == HSIC_DATA || data_type == HSIC_2_DATA) {
+			index = data_type - HSIC_DATA;
+			if (diag_hsic[index].hsic_device_enabled) {
 				struct diag_request *write_ptr_mdm;
 				write_ptr_mdm = (struct diag_request *)
 						diagmem_alloc(driver,
 						sizeof(struct diag_request),
+							index +
 							POOL_TYPE_HSIC_WRITE);
 				if (write_ptr_mdm) {
 					write_ptr_mdm->buf = buf;
 					write_ptr_mdm->length =
-					   diag_bridge[HSIC].write_len;
-					write_ptr_mdm->context = (void *)HSIC;
+					   diag_bridge[index].write_len;
+					write_ptr_mdm->context = (void *)index;
 					err = usb_diag_write(
-					diag_bridge[HSIC].ch, write_ptr_mdm);
+					diag_bridge[index].ch, write_ptr_mdm);
 					/* Return to the pool immediately */
 					if (err) {
 						diagmem_free(driver,
 							write_ptr_mdm,
+							index +
 							POOL_TYPE_HSIC_WRITE);
-						pr_err_ratelimited("diag: HSIC write failure, err: %d\n",
-							err);
+						pr_err_ratelimited("diag: HSIC write failure, err: %d, ch %d\n",
+							err, index);
 					}
 				} else {
 					pr_err("diag: allocate write fail\n");
@@ -596,13 +611,15 @@
 	int packet_type = 1, i, cmd_code;
 	unsigned char *temp = buf;
 	int data_type;
+	int mask_ret;
 #if defined(CONFIG_DIAG_OVER_USB)
 	unsigned char *ptr;
 #endif
 
 	/* Check if the command is a supported mask command */
-	if (diag_process_apps_masks(buf, len) == 0)
-		return 0;
+	mask_ret = diag_process_apps_masks(buf, len);
+	if (mask_ret <= 0)
+		return mask_ret;
 
 	/* Check for registered clients and forward packet to apropriate proc */
 	cmd_code = (int)(*(char *)buf);
@@ -976,10 +993,16 @@
 
 	ret = diag_hdlc_decode(&hdlc);
 
-	if (ret)
+	if (hdlc.dest_idx < 3) {
+		pr_err("diag: Integer underflow in hdlc processing\n");
+		return;
+	}
+	if (ret) {
 		type = diag_process_apps_pkt(driver->hdlc_buf,
 							  hdlc.dest_idx - 3);
-	else if (driver->debug_flag) {
+		if (type < 0)
+			return;
+	} else if (driver->debug_flag) {
 		printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
 				" errors or partial packet received, packet"
 				" length = %d\n", len);
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
index 75fdeb4..b934805 100644
--- a/drivers/char/diag/diagfwd_bridge.c
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -55,8 +55,8 @@
 		err = usb_diag_alloc_req(diag_bridge[index].ch, N_MDM_WRITE,
 			       N_MDM_READ);
 		if (err)
-			pr_err("diag: unable to alloc USB req on mdm ch err:%d\n",
-							 err);
+			pr_err("diag: unable to alloc USB req for ch %d err:%d\n",
+							 index, err);
 
 		diag_bridge[index].usb_connected = 1;
 	}
@@ -64,35 +64,45 @@
 	if (index == SMUX && driver->diag_smux_enabled) {
 		driver->in_busy_smux = 0;
 		diagfwd_connect_smux();
-	} else if (index == HSIC && driver->hsic_device_enabled) {
-		driver->in_busy_hsic_read_on_device = 0;
-		driver->in_busy_hsic_write = 0;
-		/* If the HSIC (diag_bridge) platform device is not open */
-		if (!driver->hsic_device_opened) {
-			err = diag_bridge_open(&hsic_diag_bridge_ops);
-			if (err) {
-				pr_err("diag: HSIC channel open error: %d\n",
-					  err);
+	} else {
+		if (diag_hsic[index].hsic_device_enabled) {
+			diag_hsic[index].in_busy_hsic_read_on_device = 0;
+			diag_hsic[index].in_busy_hsic_write = 0;
+			/* If the HSIC (diag_bridge) platform
+			 * device is not open */
+			if (!diag_hsic[index].hsic_device_opened) {
+				hsic_diag_bridge_ops[index].ctxt =
+							(void *)(index);
+				err = diag_bridge_open(index,
+						 &hsic_diag_bridge_ops[index]);
+				if (err) {
+					pr_err("diag: HSIC channel open error: %d\n",
+						   err);
+				} else {
+					pr_debug("diag: opened HSIC channel\n");
+					diag_hsic[index].hsic_device_opened =
+									1;
+				}
 			} else {
-				pr_debug("diag: opened HSIC channel\n");
-				driver->hsic_device_opened = 1;
+				pr_debug("diag: HSIC channel already open\n");
 			}
-		} else {
-			pr_debug("diag: HSIC channel already open\n");
-		}
-		/*
-		 * Turn on communication over usb mdm and HSIC, if the HSIC
-		 * device driver is enabled and opened
-		 */
-		if (driver->hsic_device_opened) {
-			driver->hsic_ch = 1;
-			/* Poll USB mdm channel to check for data */
-			if (driver->logging_mode == USB_MODE)
-				queue_work(diag_bridge[HSIC].wq,
-					  &diag_bridge[HSIC].diag_read_work);
-			/* Poll HSIC channel to check for data */
-			queue_work(diag_bridge[HSIC].wq,
-				   &driver->diag_read_hsic_work);
+			/*
+			 * Turn on communication over usb mdm and HSIC,
+			 * if the HSIC device driver is enabled
+			 * and opened
+			 */
+			if (diag_hsic[index].hsic_device_opened) {
+				diag_hsic[index].hsic_ch = 1;
+				/* Poll USB mdm channel to check for data */
+				if (driver->logging_mode == USB_MODE)
+					queue_work(diag_bridge[index].wq,
+						   &diag_bridge[index].
+							diag_read_work);
+				/* Poll HSIC channel to check for data */
+				queue_work(diag_bridge[index].wq,
+					   &diag_hsic[index].
+					   diag_read_hsic_work);
+			}
 		}
 	}
 	mutex_unlock(&diag_bridge[index].bridge_mutex);
@@ -116,19 +126,25 @@
 				usb_diag_free_req(diag_bridge[i].ch);
 			}
 
-			if (i == HSIC && driver->hsic_device_enabled &&
-				 driver->logging_mode != MEMORY_DEVICE_MODE) {
-				driver->in_busy_hsic_read_on_device = 1;
-				driver->in_busy_hsic_write = 1;
-				/* Turn off communication over usb and HSIC */
-				diag_hsic_close();
-			} else if (i == SMUX && driver->diag_smux_enabled &&
+			if (i == SMUX && driver->diag_smux_enabled &&
 					driver->logging_mode == USB_MODE) {
 				driver->in_busy_smux = 1;
 				driver->lcid = LCID_INVALID;
 				driver->smux_connected = 0;
 				/* Turn off communication over usb and smux */
 				msm_smux_close(LCID_VALID);
+			}  else {
+				if (diag_hsic[i].hsic_device_enabled &&
+				     driver->logging_mode !=
+							MEMORY_DEVICE_MODE) {
+					diag_hsic[i].
+						in_busy_hsic_read_on_device
+						= 1;
+					diag_hsic[i].in_busy_hsic_write = 1;
+					/* Turn off communication over usb
+					 * and HSIC */
+					diag_hsic_close(i);
+				}
 			}
 			mutex_unlock(&diag_bridge[i].bridge_mutex);
 		}
@@ -154,9 +170,9 @@
 	}
 
 	/* If SMUX not enabled, check for HSIC */
-	driver->in_busy_hsic_read_on_device = 0;
-	if (!driver->hsic_ch) {
-		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+	diag_hsic[index].in_busy_hsic_read_on_device = 0;
+	if (!diag_hsic[index].hsic_ch) {
+		pr_err("DIAG in %s: hsic_ch == 0, ch %d\n", __func__, index);
 		return 0;
 	}
 
@@ -166,8 +182,9 @@
 	 * read has data to pass on to the HSIC. If so, pass the usb
 	 * mdm data on to the HSIC.
 	 */
-	if (!driver->in_busy_hsic_write && diag_bridge[HSIC].usb_buf_out &&
-		(diag_bridge[HSIC].read_len > 0)) {
+	if (!diag_hsic[index].in_busy_hsic_write &&
+		diag_bridge[index].usb_buf_out &&
+		(diag_bridge[index].read_len > 0)) {
 
 		/*
 		 * Initiate the HSIC write. The HSIC write is
@@ -175,9 +192,9 @@
 		 * complete callback function will be called
 		 */
 		int err;
-		driver->in_busy_hsic_write = 1;
-		err = diag_bridge_write(diag_bridge[HSIC].usb_buf_out,
-					diag_bridge[HSIC].read_len);
+		diag_hsic[index].in_busy_hsic_write = 1;
+		err = diag_bridge_write(index, diag_bridge[index].usb_buf_out,
+					diag_bridge[index].read_len);
 		if (err) {
 			pr_err_ratelimited("diag: mdm data on HSIC write err: %d\n",
 					err);
@@ -188,7 +205,7 @@
 			 * resubmit a write on the next frame.
 			 */
 			if ((-ENODEV) != err)
-				driver->in_busy_hsic_write = 0;
+				diag_hsic[index].in_busy_hsic_write = 0;
 		}
 	}
 
@@ -196,9 +213,9 @@
 	 * If there is no write of the usb mdm data on the
 	 * HSIC channel
 	 */
-	if (!driver->in_busy_hsic_write)
-		queue_work(diag_bridge[HSIC].wq,
-			 &diag_bridge[HSIC].diag_read_work);
+	if (!diag_hsic[index].in_busy_hsic_write)
+		queue_work(diag_bridge[index].wq,
+			 &diag_bridge[index].diag_read_work);
 
 	return 0;
 }
@@ -223,10 +240,10 @@
 		break;
 	case USB_DIAG_WRITE_DONE:
 		index = (int)(d_req->context);
-		if (index == HSIC &&  driver->hsic_device_enabled)
-			diagfwd_write_complete_hsic(d_req);
-		else if (index == SMUX && driver->diag_smux_enabled)
+		if (index == SMUX && driver->diag_smux_enabled)
 			diagfwd_write_complete_smux();
+		else if (diag_hsic[index].hsic_device_enabled)
+			diagfwd_write_complete_hsic(d_req, index);
 		break;
 	default:
 		pr_err("diag: in %s: Unknown event from USB diag:%u\n",
@@ -240,14 +257,21 @@
 	int ret;
 	unsigned char name[20];
 
-	if (index == HSIC)
+	if (index == HSIC) {
 		strlcpy(name, "hsic", sizeof(name));
-	else
+	} else if (index == HSIC_2) {
+		strlcpy(name, "hsic_2", sizeof(name));
+	} else if (index == SMUX) {
 		strlcpy(name, "smux", sizeof(name));
+	} else {
+		pr_err("diag: incorrect bridge init, instance: %d\n", index);
+		return;
+	}
 
-	strlcpy(diag_bridge[index].name, name, sizeof(diag_bridge[index].name));
+	strlcpy(diag_bridge[index].name, name,
+				sizeof(diag_bridge[index].name));
 	strlcat(name, "_diag_wq", sizeof(diag_bridge[index].name));
-	diag_bridge[index].enabled = 1;
+	diag_bridge[index].id = index;
 	diag_bridge[index].wq = create_singlethread_workqueue(name);
 	diag_bridge[index].read_len = 0;
 	diag_bridge[index].write_len = 0;
@@ -268,24 +292,24 @@
 		goto err;
 	mutex_init(&diag_bridge[index].bridge_mutex);
 
-	if (index == HSIC) {
+	if (index == HSIC || index == HSIC_2) {
 		INIT_WORK(&(diag_bridge[index].usb_read_complete_work),
 				 diag_usb_read_complete_hsic_fn);
 #ifdef CONFIG_DIAG_OVER_USB
 		INIT_WORK(&(diag_bridge[index].diag_read_work),
 		      diag_read_usb_hsic_work_fn);
-		diag_bridge[index].ch = usb_diag_open(DIAG_MDM, (void *)index,
-						  diagfwd_bridge_notifier);
+		if (index == HSIC)
+			diag_bridge[index].ch = usb_diag_open(DIAG_MDM,
+				 (void *)index, diagfwd_bridge_notifier);
+		else if (index == HSIC_2)
+			diag_bridge[index].ch = usb_diag_open(DIAG_MDM2,
+				 (void *)index, diagfwd_bridge_notifier);
 		if (IS_ERR(diag_bridge[index].ch)) {
-			pr_err("diag: Unable to open USB diag MDM channel\n");
+			pr_err("diag: Unable to open USB MDM ch = %d\n", index);
 			goto err;
-		}
+		} else
+			diag_bridge[index].enabled = 1;
 #endif
-		/* register HSIC device */
-		ret = platform_driver_register(&msm_hsic_ch_driver);
-		if (ret)
-			pr_err("diag: could not register HSIC device, ret: %d\n",
-									 ret);
 	} else if (index == SMUX) {
 		INIT_WORK(&(diag_bridge[index].usb_read_complete_work),
 					 diag_usb_read_complete_smux_fn);
@@ -297,7 +321,8 @@
 		if (IS_ERR(diag_bridge[index].ch)) {
 			pr_err("diag: Unable to open USB diag QSC channel\n");
 			goto err;
-		}
+		} else
+			diag_bridge[index].enabled = 1;
 #endif
 		ret = platform_driver_register(&msm_diagfwd_smux_driver);
 		if (ret)
@@ -308,7 +333,7 @@
 err:
 	pr_err("diag: Could not initialize for bridge forwarding\n");
 	kfree(diag_bridge[index].usb_buf_out);
-	kfree(driver->hsic_buf_tbl);
+	kfree(diag_hsic[index].hsic_buf_tbl);
 	kfree(driver->write_ptr_mdm);
 	kfree(diag_bridge[index].usb_read_ptr);
 	if (diag_bridge[index].wq)
@@ -321,12 +346,15 @@
 	int i;
 	pr_debug("diag: in %s\n", __func__);
 
-	if (driver->hsic_device_enabled) {
-		diag_hsic_close();
-		driver->hsic_device_enabled = 0;
-		diag_bridge[HSIC].enabled = 0;
+	for (i = 0; i < MAX_HSIC_CH; i++) {
+		if (diag_hsic[i].hsic_device_enabled) {
+			diag_hsic_close(i);
+			diag_hsic[i].hsic_device_enabled = 0;
+			diag_bridge[i].enabled = 0;
+		}
+		diag_hsic[i].hsic_inited = 0;
+		kfree(diag_hsic[i].hsic_buf_tbl);
 	}
-	driver->hsic_inited = 0;
 	diagmem_exit(driver, POOL_TYPE_ALL);
 	if (driver->diag_smux_enabled) {
 		driver->lcid = LCID_INVALID;
@@ -350,6 +378,5 @@
 			diag_bridge[i].enabled = 0;
 		}
 	}
-	kfree(driver->hsic_buf_tbl);
 	kfree(driver->write_ptr_mdm);
 }
diff --git a/drivers/char/diag/diagfwd_bridge.h b/drivers/char/diag/diagfwd_bridge.h
index 06e6a96..88c96ab 100644
--- a/drivers/char/diag/diagfwd_bridge.h
+++ b/drivers/char/diag/diagfwd_bridge.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,8 @@
 
 #define MAX_BRIDGES	5
 #define HSIC	0
-#define SMUX	1
+#define HSIC_2	1
+#define SMUX	4
 
 int diagfwd_connect_bridge(int);
 void connect_bridge(int, int);
@@ -30,6 +31,7 @@
  * for instance SMUX, HSIC working at same time
  */
 struct diag_bridge_dev {
+	int id;
 	char name[20];
 	int enabled;
 	struct mutex bridge_mutex;
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index abc5858..aa55578 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,7 @@
 #include "diagfwd_bridge.h"
 
 #define READ_HSIC_BUF_SIZE 2048
+struct diag_hsic_dev *diag_hsic;
 
 static void diag_read_hsic_work_fn(struct work_struct *work)
 {
@@ -41,9 +42,12 @@
 	int num_reads_submitted = 0;
 	int err = 0;
 	int write_ptrs_available;
+	struct diag_hsic_dev *hsic_struct = container_of(work,
+				struct diag_hsic_dev, diag_read_hsic_work);
+	int index = hsic_struct->id;
 
-	if (!driver->hsic_ch) {
-		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+	if (!diag_hsic[index].hsic_ch) {
+		pr_err("DIAG in %s: diag_hsic[index].hsic_ch == 0\n", __func__);
 		return;
 	}
 
@@ -52,11 +56,12 @@
 	 * reading from the HSIC has completed.
 	 */
 	if (driver->logging_mode == MEMORY_DEVICE_MODE)
-		write_ptrs_available = driver->poolsize_hsic_write -
-					driver->num_hsic_buf_tbl_entries;
+		write_ptrs_available = diag_hsic[index].poolsize_hsic_write -
+					diag_hsic[index].
+						num_hsic_buf_tbl_entries;
 	else
-		write_ptrs_available = driver->poolsize_hsic_write -
-					driver->count_hsic_write_pool;
+		write_ptrs_available = diag_hsic[index].poolsize_hsic_write -
+					diag_hsic[index].count_hsic_write_pool;
 
 	/*
 	 * Queue up a read on the HSIC for all available buffers in the
@@ -76,11 +81,11 @@
 		 * No sense queuing a read if the HSIC bridge was
 		 * closed in another thread
 		 */
-		if (!driver->hsic_ch)
+		if (!diag_hsic[index].hsic_ch)
 			break;
 
 		buf_in_hsic = diagmem_alloc(driver, READ_HSIC_BUF_SIZE,
-							POOL_TYPE_HSIC);
+							index+POOL_TYPE_HSIC);
 		if (buf_in_hsic) {
 			/*
 			 * Initiate the read from the HSIC.  The HSIC read is
@@ -89,14 +94,14 @@
 			 */
 			pr_debug("diag: read from HSIC\n");
 			num_reads_submitted++;
-			err = diag_bridge_read((char *)buf_in_hsic,
+			err = diag_bridge_read(index, (char *)buf_in_hsic,
 							READ_HSIC_BUF_SIZE);
 			if (err) {
 				num_reads_submitted--;
 
 				/* Return the buffer to the pool */
 				diagmem_free(driver, buf_in_hsic,
-						POOL_TYPE_HSIC);
+						index+POOL_TYPE_HSIC);
 
 				pr_err_ratelimited("diag: Error initiating HSIC read, err: %d\n",
 					err);
@@ -114,25 +119,27 @@
 	 * read was not queued, and if no unrecoverable error occurred
 	 * (-ENODEV is an unrecoverable error), then set up the next read
 	 */
-	if ((driver->count_hsic_pool < driver->poolsize_hsic) &&
+	if ((diag_hsic[index].count_hsic_pool <
+		diag_hsic[index].poolsize_hsic) &&
 		(num_reads_submitted == 0) && (err != -ENODEV) &&
-		(driver->hsic_ch != 0))
-		queue_work(diag_bridge[HSIC].wq,
-				 &driver->diag_read_hsic_work);
+		(diag_hsic[index].hsic_ch != 0))
+		queue_work(diag_bridge[index].wq,
+				 &diag_hsic[index].diag_read_hsic_work);
 }
 
 static void diag_hsic_read_complete_callback(void *ctxt, char *buf,
 					int buf_size, int actual_size)
 {
 	int err = -2;
+	int index = (int)ctxt;
 
-	if (!driver->hsic_ch) {
+	if (!diag_hsic[index].hsic_ch) {
 		/*
 		 * The HSIC channel is closed. Return the buffer to
 		 * the pool.  Do not send it on.
 		 */
-		diagmem_free(driver, buf, POOL_TYPE_HSIC);
-		pr_debug("diag: In %s: driver->hsic_ch == 0, actual_size: %d\n",
+		diagmem_free(driver, buf, index+POOL_TYPE_HSIC);
+		pr_debug("diag: In %s: hsic_ch == 0, actual_size: %d\n",
 			__func__, actual_size);
 		return;
 	}
@@ -150,11 +157,13 @@
 			 * Send data in buf to be written on the
 			 * appropriate device, e.g. USB MDM channel
 			 */
-			diag_bridge[HSIC].write_len = actual_size;
-			err = diag_device_write((void *)buf, HSIC_DATA, NULL);
+			diag_bridge[index].write_len = actual_size;
+			err = diag_device_write((void *)buf, index+HSIC_DATA,
+									NULL);
 			/* If an error, return buffer to the pool */
 			if (err) {
-				diagmem_free(driver, buf, POOL_TYPE_HSIC);
+				diagmem_free(driver, buf, index +
+							POOL_TYPE_HSIC);
 				pr_err_ratelimited("diag: In %s, error calling diag_device_write, err: %d\n",
 					__func__, err);
 			}
@@ -165,7 +174,7 @@
 		 * pass it on. Note that -ENOENT is sent when the diag bridge
 		 * is closed.
 		 */
-		diagmem_free(driver, buf, POOL_TYPE_HSIC);
+		diagmem_free(driver, buf, index+POOL_TYPE_HSIC);
 		pr_debug("diag: In %s: error status: %d\n", __func__,
 			actual_size);
 	}
@@ -176,108 +185,135 @@
 	 */
 	if (err &&
 		((driver->logging_mode == MEMORY_DEVICE_MODE) ||
-		(diag_bridge[HSIC].usb_connected && !driver->hsic_suspend))) {
-		queue_work(diag_bridge[HSIC].wq,
-				 &driver->diag_read_hsic_work);
+		(diag_bridge[index].usb_connected &&
+		!diag_hsic[index].hsic_suspend))) {
+		queue_work(diag_bridge[index].wq,
+				 &diag_hsic[index].diag_read_hsic_work);
 	}
 }
 
 static void diag_hsic_write_complete_callback(void *ctxt, char *buf,
 					int buf_size, int actual_size)
 {
-	/* The write of the data to the HSIC bridge is complete */
-	driver->in_busy_hsic_write = 0;
+	int index = (int)ctxt;
 
-	if (!driver->hsic_ch) {
-		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+	/* The write of the data to the HSIC bridge is complete */
+	diag_hsic[index].in_busy_hsic_write = 0;
+
+	if (!diag_hsic[index].hsic_ch) {
+		pr_err("DIAG in %s: hsic_ch == 0, ch = %d\n", __func__, index);
 		return;
 	}
 
 	if (actual_size < 0)
 		pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
 
-	if (diag_bridge[HSIC].usb_connected &&
+	if (diag_bridge[index].usb_connected &&
 				 (driver->logging_mode == USB_MODE))
-		queue_work(diag_bridge[HSIC].wq,
-				 &diag_bridge[HSIC].diag_read_work);
+		queue_work(diag_bridge[index].wq,
+				 &diag_bridge[index].diag_read_work);
 }
 
 static int diag_hsic_suspend(void *ctxt)
 {
+	int index = (int)ctxt;
 	pr_debug("diag: hsic_suspend\n");
 
 	/* Don't allow suspend if a write in the HSIC is in progress */
-	if (driver->in_busy_hsic_write)
+	if (diag_hsic[index].in_busy_hsic_write)
 		return -EBUSY;
 
 	/* Don't allow suspend if in MEMORY_DEVICE_MODE */
 	if (driver->logging_mode == MEMORY_DEVICE_MODE)
 		return -EBUSY;
 
-	driver->hsic_suspend = 1;
+	diag_hsic[index].hsic_suspend = 1;
 
 	return 0;
 }
 
 static void diag_hsic_resume(void *ctxt)
 {
-	pr_debug("diag: hsic_resume\n");
-	driver->hsic_suspend = 0;
+	 int index = (int)ctxt;
 
-	if ((driver->count_hsic_pool < driver->poolsize_hsic) &&
+	pr_debug("diag: hsic_resume\n");
+	diag_hsic[index].hsic_suspend = 0;
+
+	if ((diag_hsic[index].count_hsic_pool <
+		diag_hsic[index].poolsize_hsic) &&
 		((driver->logging_mode == MEMORY_DEVICE_MODE) ||
-				(diag_bridge[HSIC].usb_connected)))
-		queue_work(diag_bridge[HSIC].wq,
-			 &driver->diag_read_hsic_work);
+				(diag_bridge[index].usb_connected)))
+		queue_work(diag_bridge[index].wq,
+			 &diag_hsic[index].diag_read_hsic_work);
 }
 
-struct diag_bridge_ops hsic_diag_bridge_ops = {
+struct diag_bridge_ops hsic_diag_bridge_ops[MAX_HSIC_CH] = {
+	{
 	.ctxt = NULL,
 	.read_complete_cb = diag_hsic_read_complete_callback,
 	.write_complete_cb = diag_hsic_write_complete_callback,
 	.suspend = diag_hsic_suspend,
 	.resume = diag_hsic_resume,
+	},
+	{
+	.ctxt = NULL,
+	.read_complete_cb = diag_hsic_read_complete_callback,
+	.write_complete_cb = diag_hsic_write_complete_callback,
+	.suspend = diag_hsic_suspend,
+	.resume = diag_hsic_resume,
+	}
 };
 
-void diag_hsic_close(void)
+void diag_hsic_close(int ch_id)
 {
-	if (driver->hsic_device_enabled) {
-		driver->hsic_ch = 0;
-		if (driver->hsic_device_opened) {
-			driver->hsic_device_opened = 0;
-			diag_bridge_close();
-			pr_debug("diag: %s: closed successfully\n", __func__);
+	if (diag_hsic[ch_id].hsic_device_enabled) {
+		diag_hsic[ch_id].hsic_ch = 0;
+		if (diag_hsic[ch_id].hsic_device_opened) {
+			diag_hsic[ch_id].hsic_device_opened = 0;
+			diag_bridge_close(ch_id);
+			pr_debug("diag: %s: closed successfully ch %d\n",
+							__func__, ch_id);
 		} else {
-			pr_debug("diag: %s: already closed\n", __func__);
+			pr_debug("diag: %s: already closed ch %d\n",
+							__func__, ch_id);
 		}
 	} else {
-		pr_debug("diag: %s: HSIC device already removed\n", __func__);
+		pr_debug("diag: %s: HSIC device already removed ch %d\n",
+							__func__, ch_id);
 	}
 }
 
 /* diagfwd_cancel_hsic is called to cancel outstanding read/writes */
 int diagfwd_cancel_hsic(void)
 {
-	int err;
+	int err, i;
 
-	mutex_lock(&diag_bridge[HSIC].bridge_mutex);
-	if (driver->hsic_device_enabled) {
-		if (driver->hsic_device_opened) {
-			driver->hsic_ch = 0;
-			driver->hsic_device_opened = 0;
-			diag_bridge_close();
-			err = diag_bridge_open(&hsic_diag_bridge_ops);
-			if (err) {
-				pr_err("diag: HSIC channel open error: %d\n",
-					err);
-			} else {
-				pr_debug("diag: opened HSIC channel\n");
-				driver->hsic_device_opened = 1;
-				driver->hsic_ch = 1;
+	/* Cancel it for all active HSIC bridges */
+	for (i = 0; i < MAX_HSIC_CH; i++) {
+		if (!diag_bridge[i].enabled)
+			continue;
+		mutex_lock(&diag_bridge[i].bridge_mutex);
+		if (diag_hsic[i].hsic_device_enabled) {
+			if (diag_hsic[i].hsic_device_opened) {
+				diag_hsic[i].hsic_ch = 0;
+				diag_hsic[i].hsic_device_opened = 0;
+				diag_bridge_close(i);
+				hsic_diag_bridge_ops[i].ctxt = (void *)(i);
+				err = diag_bridge_open(i,
+						   &hsic_diag_bridge_ops[i]);
+				if (err) {
+					pr_err("diag: HSIC %d channel open error: %d\n",
+						 i, err);
+				} else {
+					pr_debug("diag: opened HSIC channel: %d\n",
+						i);
+					diag_hsic[i].hsic_device_opened = 1;
+					diag_hsic[i].hsic_ch = 1;
+				}
 			}
 		}
+		mutex_unlock(&diag_bridge[i].bridge_mutex);
 	}
-	mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
 	return 0;
 }
 
@@ -285,38 +321,48 @@
  * diagfwd_write_complete_hsic is called after the asynchronous
  * usb_diag_write() on mdm channel is complete
  */
-int diagfwd_write_complete_hsic(struct diag_request *diag_write_ptr)
+int diagfwd_write_complete_hsic(struct diag_request *diag_write_ptr, int index)
 {
 	unsigned char *buf = (diag_write_ptr) ? diag_write_ptr->buf : NULL;
 
 	if (buf) {
 		/* Return buffers to their pools */
-		diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HSIC);
+		diagmem_free(driver, (unsigned char *)buf, index +
+							POOL_TYPE_HSIC);
 		diagmem_free(driver, (unsigned char *)diag_write_ptr,
+							index +
 							POOL_TYPE_HSIC_WRITE);
 	}
 
-	if (!driver->hsic_ch) {
-		pr_err("diag: In %s: driver->hsic_ch == 0\n", __func__);
+	if (!diag_hsic[index].hsic_ch) {
+		pr_err("diag: In %s: hsic_ch == 0\n", __func__);
 		return 0;
 	}
 
 	/* Read data from the HSIC */
-	queue_work(diag_bridge[HSIC].wq, &driver->diag_read_hsic_work);
+	queue_work(diag_bridge[index].wq,
+				&diag_hsic[index].diag_read_hsic_work);
 
 	return 0;
 }
 
 void diag_usb_read_complete_hsic_fn(struct work_struct *w)
 {
-	diagfwd_read_complete_bridge(diag_bridge[HSIC].usb_read_ptr);
-}
+	struct diag_bridge_dev *bridge_struct = container_of(w,
+			struct diag_bridge_dev, usb_read_complete_work);
 
+	diagfwd_read_complete_bridge(
+			diag_bridge[bridge_struct->id].usb_read_ptr);
+}
 
 void diag_read_usb_hsic_work_fn(struct work_struct *work)
 {
-	if (!driver->hsic_ch) {
-		pr_err("diag: in %s: driver->hsic_ch == 0\n", __func__);
+	struct diag_bridge_dev *bridge_struct = container_of(work,
+				struct diag_bridge_dev, diag_read_work);
+	int index = bridge_struct->id;
+
+	if (!diag_hsic[index].hsic_ch) {
+		pr_err("diag: in %s: hsic_ch == 0\n", __func__);
 		return;
 	}
 	/*
@@ -324,104 +370,114 @@
 	 * and there is no mdm channel data currently being written
 	 * to the HSIC
 	 */
-	if (!driver->in_busy_hsic_read_on_device &&
-	     !driver->in_busy_hsic_write) {
+	if (!diag_hsic[index].in_busy_hsic_read_on_device &&
+	     !diag_hsic[index].in_busy_hsic_write) {
 		APPEND_DEBUG('x');
 		/* Setup the next read from usb mdm channel */
-		driver->in_busy_hsic_read_on_device = 1;
-		diag_bridge[HSIC].usb_read_ptr->buf =
-				 diag_bridge[HSIC].usb_buf_out;
-		diag_bridge[HSIC].usb_read_ptr->length = USB_MAX_OUT_BUF;
-		diag_bridge[HSIC].usb_read_ptr->context = (void *)HSIC;
-		usb_diag_read(diag_bridge[HSIC].ch,
-				 diag_bridge[HSIC].usb_read_ptr);
+		diag_hsic[index].in_busy_hsic_read_on_device = 1;
+		diag_bridge[index].usb_read_ptr->buf =
+				 diag_bridge[index].usb_buf_out;
+		diag_bridge[index].usb_read_ptr->length = USB_MAX_OUT_BUF;
+		diag_bridge[index].usb_read_ptr->context = (void *)index;
+		usb_diag_read(diag_bridge[index].ch,
+				 diag_bridge[index].usb_read_ptr);
 		APPEND_DEBUG('y');
 	}
 	/* If for some reason there was no mdm channel read initiated,
 	 * queue up the reading of data from the mdm channel
 	 */
 
-	if (!driver->in_busy_hsic_read_on_device &&
+	if (!diag_hsic[index].in_busy_hsic_read_on_device &&
 		(driver->logging_mode == USB_MODE))
-		queue_work(diag_bridge[HSIC].wq,
-			 &(diag_bridge[HSIC].diag_read_work));
+		queue_work(diag_bridge[index].wq,
+			 &(diag_bridge[index].diag_read_work));
 }
 
 static int diag_hsic_probe(struct platform_device *pdev)
 {
 	int err = 0;
 
-	pr_debug("diag: in %s\n", __func__);
-	mutex_lock(&diag_bridge[HSIC].bridge_mutex);
-	if (!driver->hsic_inited) {
-		spin_lock_init(&driver->hsic_spinlock);
-		driver->num_hsic_buf_tbl_entries = 0;
-		if (driver->hsic_buf_tbl == NULL)
-			driver->hsic_buf_tbl = kzalloc(NUM_HSIC_BUF_TBL_ENTRIES
-				* sizeof(struct diag_write_device), GFP_KERNEL);
-		if (driver->hsic_buf_tbl == NULL) {
-			mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
+	/* pdev->Id will indicate which HSIC is working. 0 stands for HSIC
+	 *  or CP1 1 indicates HS-USB or CP2
+	 */
+	pr_debug("diag: in %s, ch = %d\n", __func__, pdev->id);
+	mutex_lock(&diag_bridge[pdev->id].bridge_mutex);
+	if (!diag_hsic[pdev->id].hsic_inited) {
+		spin_lock_init(&diag_hsic[pdev->id].hsic_spinlock);
+		diag_hsic[pdev->id].num_hsic_buf_tbl_entries = 0;
+		if (diag_hsic[pdev->id].hsic_buf_tbl == NULL)
+			diag_hsic[pdev->id].hsic_buf_tbl =
+				kzalloc(NUM_HSIC_BUF_TBL_ENTRIES *
+				sizeof(struct diag_write_device), GFP_KERNEL);
+		if (diag_hsic[pdev->id].hsic_buf_tbl == NULL) {
+			mutex_unlock(&diag_bridge[pdev->id].bridge_mutex);
 			return -ENOMEM;
 		}
-		driver->count_hsic_pool = 0;
-		driver->count_hsic_write_pool = 0;
-		driver->itemsize_hsic = READ_HSIC_BUF_SIZE;
-		driver->poolsize_hsic = N_MDM_WRITE;
-		driver->itemsize_hsic_write = sizeof(struct diag_request);
-		driver->poolsize_hsic_write = N_MDM_WRITE;
-		diagmem_hsic_init(driver);
-		INIT_WORK(&(driver->diag_read_hsic_work),
+		diag_hsic[pdev->id].id = pdev->id;
+		diag_hsic[pdev->id].count_hsic_pool = 0;
+		diag_hsic[pdev->id].count_hsic_write_pool = 0;
+		diag_hsic[pdev->id].itemsize_hsic = READ_HSIC_BUF_SIZE;
+		diag_hsic[pdev->id].poolsize_hsic = N_MDM_WRITE;
+		diag_hsic[pdev->id].itemsize_hsic_write =
+					sizeof(struct diag_request);
+		diag_hsic[pdev->id].poolsize_hsic_write = N_MDM_WRITE;
+		diagmem_hsic_init(pdev->id);
+		INIT_WORK(&(diag_hsic[pdev->id].diag_read_hsic_work),
 			    diag_read_hsic_work_fn);
-		driver->hsic_inited = 1;
+		diag_hsic[pdev->id].hsic_inited = 1;
 	}
 	/*
 	 * The probe function was called after the usb was connected
 	 * on the legacy channel OR ODL is turned on. Communication over usb
 	 * mdm and HSIC needs to be turned on.
 	 */
-	if (diag_bridge[HSIC].usb_connected || (driver->logging_mode ==
+	if (diag_bridge[pdev->id].usb_connected || (driver->logging_mode ==
 						   MEMORY_DEVICE_MODE)) {
-		if (driver->hsic_device_opened) {
+		if (diag_hsic[pdev->id].hsic_device_opened) {
 			/* should not happen. close it before re-opening */
 			pr_warn("diag: HSIC channel already opened in probe\n");
-			diag_bridge_close();
+			diag_bridge_close(pdev->id);
 		}
-		err = diag_bridge_open(&hsic_diag_bridge_ops);
+		hsic_diag_bridge_ops[pdev->id].ctxt = (void *)(pdev->id);
+		err = diag_bridge_open(pdev->id,
+				       &hsic_diag_bridge_ops[pdev->id]);
 		if (err) {
 			pr_err("diag: could not open HSIC, err: %d\n", err);
-			driver->hsic_device_opened = 0;
-			mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
+			diag_hsic[pdev->id].hsic_device_opened = 0;
+			mutex_unlock(&diag_bridge[pdev->id].bridge_mutex);
 			return err;
 		}
 
-		pr_info("diag: opened HSIC channel\n");
-		driver->hsic_device_opened = 1;
-		driver->hsic_ch = 1;
-		driver->in_busy_hsic_read_on_device = 0;
-		driver->in_busy_hsic_write = 0;
+		pr_info("diag: opened HSIC bridge, ch = %d\n", pdev->id);
+		diag_hsic[pdev->id].hsic_device_opened = 1;
+		diag_hsic[pdev->id].hsic_ch = 1;
+		diag_hsic[pdev->id].in_busy_hsic_read_on_device = 0;
+		diag_hsic[pdev->id].in_busy_hsic_write = 0;
 
-		if (diag_bridge[HSIC].usb_connected) {
+		if (diag_bridge[pdev->id].usb_connected) {
 			/* Poll USB mdm channel to check for data */
-			queue_work(diag_bridge[HSIC].wq,
-			     &diag_bridge[HSIC].diag_read_work);
+			queue_work(diag_bridge[pdev->id].wq,
+			     &diag_bridge[pdev->id].diag_read_work);
 		}
 		/* Poll HSIC channel to check for data */
-		queue_work(diag_bridge[HSIC].wq,
-			  &driver->diag_read_hsic_work);
+		queue_work(diag_bridge[pdev->id].wq,
+			  &diag_hsic[pdev->id].diag_read_hsic_work);
 	}
 	/* The HSIC (diag_bridge) platform device driver is enabled */
-	driver->hsic_device_enabled = 1;
-	mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
+	diag_hsic[pdev->id].hsic_device_enabled = 1;
+	mutex_unlock(&diag_bridge[pdev->id].bridge_mutex);
 	return err;
 }
 
 static int diag_hsic_remove(struct platform_device *pdev)
 {
 	pr_debug("diag: %s called\n", __func__);
-	mutex_lock(&diag_bridge[HSIC].bridge_mutex);
-	diag_hsic_close();
-	driver->hsic_device_enabled = 0;
-	mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
+	if (diag_hsic[pdev->id].hsic_device_enabled) {
+		mutex_lock(&diag_bridge[pdev->id].bridge_mutex);
+		diag_hsic_close(pdev->id);
+		diag_hsic[pdev->id].hsic_device_enabled = 0;
+		mutex_unlock(&diag_bridge[pdev->id].bridge_mutex);
+	}
 
 	return 0;
 }
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index f084fc0..d171efa 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,13 +18,39 @@
 #define N_MDM_WRITE	8
 #define N_MDM_READ	1
 #define NUM_HSIC_BUF_TBL_ENTRIES N_MDM_WRITE
-
-int diagfwd_write_complete_hsic(struct diag_request *);
+#define MAX_HSIC_CH	4
+int diagfwd_write_complete_hsic(struct diag_request *, int index);
 int diagfwd_cancel_hsic(void);
 void diag_read_usb_hsic_work_fn(struct work_struct *work);
 void diag_usb_read_complete_hsic_fn(struct work_struct *w);
-extern struct diag_bridge_ops hsic_diag_bridge_ops;
+extern struct diag_bridge_ops hsic_diag_bridge_ops[MAX_HSIC_CH];
 extern struct platform_driver msm_hsic_ch_driver;
-void diag_hsic_close(void);
+void diag_hsic_close(int);
+
+/* Diag-HSIC structure, n HSIC bridges can be used at same time
+ * for instance HSIC(0), HS-USB(1) working at same time
+ */
+struct diag_hsic_dev {
+	int id;
+	int hsic_ch;
+	int hsic_inited;
+	int hsic_device_enabled;
+	int hsic_device_opened;
+	int hsic_suspend;
+	int in_busy_hsic_read_on_device;
+	int in_busy_hsic_write;
+	struct work_struct diag_read_hsic_work;
+	int count_hsic_pool;
+	int count_hsic_write_pool;
+	unsigned int poolsize_hsic;
+	unsigned int poolsize_hsic_write;
+	unsigned int itemsize_hsic;
+	unsigned int itemsize_hsic_write;
+	mempool_t *diag_hsic_pool;
+	mempool_t *diag_hsic_write_pool;
+	int num_hsic_buf_tbl_entries;
+	struct diag_write_device *hsic_buf_tbl;
+	spinlock_t hsic_spinlock;
+};
 
 #endif
diff --git a/drivers/char/diag/diagfwd_sdio.c b/drivers/char/diag/diagfwd_sdio.c
index 7d98113..7d4e0d5 100644
--- a/drivers/char/diag/diagfwd_sdio.c
+++ b/drivers/char/diag/diagfwd_sdio.c
@@ -105,8 +105,8 @@
 {
 	int err;
 
-	err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE,
-							 N_MDM_READ);
+	err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_SDIO_WRITE,
+							 N_MDM_SDIO_READ);
 	if (err)
 		pr_err("diag: unable to alloc USB req on mdm ch\n");
 
diff --git a/drivers/char/diag/diagfwd_sdio.h b/drivers/char/diag/diagfwd_sdio.h
index ca5d9f9..bde4776 100644
--- a/drivers/char/diag/diagfwd_sdio.h
+++ b/drivers/char/diag/diagfwd_sdio.h
@@ -14,8 +14,8 @@
 #define DIAGFWD_SDIO_H
 
 #include <mach/sdio_al.h>
-#define N_MDM_WRITE	1 /* Upgrade to 2 with ping pong buffer */
-#define N_MDM_READ	1
+#define N_MDM_SDIO_WRITE	1 /* Upgrade to 2 with ping pong buffer */
+#define N_MDM_SDIO_READ	1
 
 void diagfwd_sdio_init(void);
 void diagfwd_sdio_exit(void);
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index e4b8b9e..0cd8267 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -17,11 +17,15 @@
 #include <linux/mutex.h>
 #include <asm/atomic.h>
 #include "diagchar.h"
+#include "diagfwd_bridge.h"
+#include "diagfwd_hsic.h"
 
 void *diagmem_alloc(struct diagchar_dev *driver, int size, int pool_type)
 {
 	void *buf = NULL;
+	int index;
 
+	index = 0;
 	if (pool_type == POOL_TYPE_COPY) {
 		if (driver->diagpool) {
 			mutex_lock(&driver->diagmem_mutex);
@@ -52,23 +56,30 @@
 			}
 		}
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-	} else if (pool_type == POOL_TYPE_HSIC) {
-		if (driver->diag_hsic_pool) {
-			if (driver->count_hsic_pool < driver->poolsize_hsic) {
-				atomic_add(1,
-					(atomic_t *)&driver->count_hsic_pool);
-				buf = mempool_alloc(driver->diag_hsic_pool,
-								GFP_ATOMIC);
+	} else if (pool_type == POOL_TYPE_HSIC ||
+				pool_type == POOL_TYPE_HSIC_2) {
+		index = pool_type - POOL_TYPE_HSIC;
+		if (diag_hsic[index].diag_hsic_pool) {
+			if (diag_hsic[index].count_hsic_pool <
+					diag_hsic[index].poolsize_hsic) {
+				atomic_add(1, (atomic_t *)
+					&diag_hsic[index].count_hsic_pool);
+				buf = mempool_alloc(
+					diag_hsic[index].diag_hsic_pool,
+					GFP_ATOMIC);
 			}
 		}
-	} else if (pool_type == POOL_TYPE_HSIC_WRITE) {
-		if (driver->diag_hsic_write_pool) {
-			if (driver->count_hsic_write_pool <
-				driver->poolsize_hsic_write) {
+	} else if (pool_type == POOL_TYPE_HSIC_WRITE ||
+					pool_type == POOL_TYPE_HSIC_2_WRITE) {
+		index = pool_type - POOL_TYPE_HSIC_WRITE;
+		if (diag_hsic[index].diag_hsic_write_pool) {
+			if (diag_hsic[index].count_hsic_write_pool <
+				diag_hsic[index].poolsize_hsic_write) {
 				atomic_add(1, (atomic_t *)
-					&driver->count_hsic_write_pool);
+					&diag_hsic[index].
+					count_hsic_write_pool);
 				buf = mempool_alloc(
-					driver->diag_hsic_write_pool,
+					diag_hsic[index].diag_hsic_write_pool,
 					GFP_ATOMIC);
 			}
 		}
@@ -79,11 +90,15 @@
 
 void diagmem_exit(struct diagchar_dev *driver, int pool_type)
 {
+	int index;
+	index = 0;
+
 	if (driver->diagpool) {
 		if (driver->count == 0 && driver->ref_count == 0) {
 			mempool_destroy(driver->diagpool);
 			driver->diagpool = NULL;
-		} else if (driver->ref_count == 0 && pool_type == POOL_TYPE_ALL)
+		} else if (driver->ref_count == 0 && pool_type ==
+							POOL_TYPE_ALL)
 			printk(KERN_ALERT "Unable to destroy COPY mempool");
 	}
 
@@ -91,7 +106,8 @@
 		if (driver->count_hdlc_pool == 0 && driver->ref_count == 0) {
 			mempool_destroy(driver->diag_hdlc_pool);
 			driver->diag_hdlc_pool = NULL;
-		} else if (driver->ref_count == 0 && pool_type == POOL_TYPE_ALL)
+		} else if (driver->ref_count == 0 && pool_type ==
+							POOL_TYPE_ALL)
 			printk(KERN_ALERT "Unable to destroy HDLC mempool");
 	}
 
@@ -102,35 +118,46 @@
 		 driver->count_hdlc_pool == 0 && driver->ref_count == 0) {
 			mempool_destroy(driver->diag_write_struct_pool);
 			driver->diag_write_struct_pool = NULL;
-		} else if (driver->ref_count == 0 && pool_type == POOL_TYPE_ALL)
+		} else if (driver->ref_count == 0 && pool_type ==
+								POOL_TYPE_ALL)
 			printk(KERN_ALERT "Unable to destroy STRUCT mempool");
 	}
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-	if (driver->diag_hsic_pool && (driver->hsic_inited == 0)) {
-		if (driver->count_hsic_pool == 0) {
-			mempool_destroy(driver->diag_hdlc_pool);
-			driver->diag_hdlc_pool = NULL;
-		} else if (pool_type == POOL_TYPE_ALL)
-			pr_err("Unable to destroy HDLC mempool");
-	}
+	for (index = 0; index < MAX_HSIC_CH; index++) {
+		if (diag_hsic[index].diag_hsic_pool &&
+				(diag_hsic[index].hsic_inited == 0)) {
+			if (diag_hsic[index].count_hsic_pool == 0) {
+				mempool_destroy(driver->diag_hdlc_pool);
+				driver->diag_hdlc_pool = NULL;
+			} else if (pool_type == POOL_TYPE_ALL)
+				pr_err("Unable to destroy HDLC mempool for ch %d"
+								, index);
+		}
 
-	if (driver->diag_hsic_write_pool && (driver->hsic_inited == 0)) {
-		/*
-		 * Free up struct pool ONLY if there are no outstanding
-		 * transactions(aggregation buffer) with USB
-		 */
-		if (driver->count_hsic_write_pool == 0 &&
-			driver->count_hsic_pool == 0) {
-			mempool_destroy(driver->diag_hsic_write_pool);
-			driver->diag_hsic_write_pool = NULL;
-		} else if (pool_type == POOL_TYPE_ALL)
-			pr_err("Unable to destroy HSIC USB struct mempool");
+		if (diag_hsic[index].diag_hsic_write_pool &&
+					(diag_hsic[index].hsic_inited == 0)) {
+			/*
+			 * Free up struct pool ONLY if there are no outstanding
+			 * transactions(aggregation buffer) with USB
+			 */
+			if (diag_hsic[index].count_hsic_write_pool == 0 &&
+				diag_hsic[index].count_hsic_pool == 0) {
+				mempool_destroy(
+					diag_hsic[index].diag_hsic_write_pool);
+				diag_hsic[index].diag_hsic_write_pool = NULL;
+			} else if (pool_type == POOL_TYPE_ALL)
+				pr_err("Unable to destroy HSIC USB struct mempool for ch %d"
+								, index);
+		}
 	}
 #endif
 }
 
 void diagmem_free(struct diagchar_dev *driver, void *buf, int pool_type)
 {
+	int index;
+
+	index = 0;
 	if (pool_type == POOL_TYPE_COPY) {
 		if (driver->diagpool != NULL && driver->count > 0) {
 			mempool_free(buf, driver->diagpool);
@@ -157,23 +184,29 @@
 			   "USB structure mempool which is already free %d ",
 				    driver->count_write_struct_pool);
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-	} else if (pool_type == POOL_TYPE_HSIC) {
-		if (driver->diag_hsic_pool != NULL &&
-			driver->count_hsic_pool > 0) {
-			mempool_free(buf, driver->diag_hsic_pool);
-			atomic_add(-1, (atomic_t *)&driver->count_hsic_pool);
+	} else if (pool_type == POOL_TYPE_HSIC ||
+				pool_type == POOL_TYPE_HSIC_2) {
+		index = pool_type - POOL_TYPE_HSIC;
+		if (diag_hsic[index].diag_hsic_pool != NULL &&
+			diag_hsic[index].count_hsic_pool > 0) {
+			mempool_free(buf, diag_hsic[index].diag_hsic_pool);
+			atomic_add(-1, (atomic_t *)
+				   &diag_hsic[index].count_hsic_pool);
 		} else
-			pr_err("diag: Attempt to free up DIAG driver HSIC mempool which is already free %d ",
-				driver->count_hsic_pool);
-	} else if (pool_type == POOL_TYPE_HSIC_WRITE) {
-		if (driver->diag_hsic_write_pool != NULL &&
-			driver->count_hsic_write_pool > 0) {
-			mempool_free(buf, driver->diag_hsic_write_pool);
-			atomic_add(-1,
-				(atomic_t *)&driver->count_hsic_write_pool);
+			pr_err("diag: Attempt to free up DIAG driver HSIC mempool which is already free %d, ch = %d",
+				diag_hsic[index].count_hsic_pool, index);
+	} else if (pool_type == POOL_TYPE_HSIC_WRITE ||
+				pool_type == POOL_TYPE_HSIC_2_WRITE) {
+		index = pool_type - POOL_TYPE_HSIC_WRITE;
+		if (diag_hsic[index].diag_hsic_write_pool != NULL &&
+			diag_hsic[index].count_hsic_write_pool > 0) {
+			mempool_free(buf,
+					diag_hsic[index].diag_hsic_write_pool);
+			atomic_add(-1, (atomic_t *)
+				&diag_hsic[index].count_hsic_write_pool);
 		} else
-			pr_err("diag: Attempt to free up DIAG driver HSIC USB structure mempool which is already free %d ",
-				driver->count_write_struct_pool);
+			pr_err("diag: Attempt to free up DIAG driver HSIC USB structure mempool which is already free %d, ch = %d",
+				driver->count_write_struct_pool, index);
 #endif
 	} else {
 		pr_err("diag: In %s, unknown pool type: %d\n",
@@ -211,23 +244,25 @@
 }
 
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-void diagmem_hsic_init(struct diagchar_dev *driver)
+void diagmem_hsic_init(int index)
 {
-	if (driver->count_hsic_pool == 0)
-		driver->diag_hsic_pool = mempool_create_kmalloc_pool(
-					driver->poolsize_hsic,
-					driver->itemsize_hsic);
+	if (diag_hsic[index].count_hsic_pool == 0)
+		diag_hsic[index].diag_hsic_pool = mempool_create_kmalloc_pool(
+					diag_hsic[index].poolsize_hsic,
+					diag_hsic[index].itemsize_hsic);
 
-	if (driver->count_hsic_write_pool == 0)
-		driver->diag_hsic_write_pool = mempool_create_kmalloc_pool(
-					driver->poolsize_hsic_write,
-					driver->itemsize_hsic_write);
+	if (diag_hsic[index].count_hsic_write_pool == 0)
+		diag_hsic[index].diag_hsic_write_pool =
+				mempool_create_kmalloc_pool(
+					diag_hsic[index].poolsize_hsic_write,
+					diag_hsic[index].itemsize_hsic_write);
 
-	if (!driver->diag_hsic_pool)
-		pr_err("Cannot allocate diag HSIC mempool\n");
+	if (!diag_hsic[index].diag_hsic_pool)
+		pr_err("Cannot allocate diag HSIC mempool for ch %d\n", index);
 
-	if (!driver->diag_hsic_write_pool)
-		pr_err("Cannot allocate diag HSIC struct mempool\n");
+	if (!diag_hsic[index].diag_hsic_write_pool)
+		pr_err("Cannot allocate diag HSIC struct mempool for ch %d\n",
+									index);
 
 }
 #endif
diff --git a/drivers/char/diag/diagmem.h b/drivers/char/diag/diagmem.h
index 92b4df8..f478263 100644
--- a/drivers/char/diag/diagmem.h
+++ b/drivers/char/diag/diagmem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -19,6 +19,6 @@
 void diagmem_init(struct diagchar_dev *driver);
 void diagmem_exit(struct diagchar_dev *driver, int pool_type);
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-void diagmem_hsic_init(struct diagchar_dev *driver);
+void diagmem_hsic_init(int index);
 #endif
 #endif
diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index ea4ad4f..c77df95 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -1,51 +1,135 @@
-config MSM_QDSS
-	bool "CoreSight tracing"
+menuconfig CORESIGHT
+	bool "CoreSight Tracing Support"
 	help
-	  Enables support for CoreSight tracing. This uses CoreSight trace
-	  components and buses to support both hardware (eg. processor ETM)
-	  and hardware assisted software instrumentation based (eg. STM)
-	  tracing.
+	  CoreSight components are compliant with the ARM CoreSight
+	  architecture specification and can be connected in various
+	  topologies to suite a particular SoCs tracing needs. These trace
+	  components can generally be classified as sources, links and
+	  sinks. Trace data produced by one or more sources flows through
+	  the intermediate links connecting the source to the currently
+	  selected sink.
 
-	  For production builds, you should probably say 'N' here to avoid
-	  potential power, performance and memory penalty.
+	  This framework provides an interface for the CoreSight debug and
+	  trace drivers to register themselves with. It's intended to build
+	  up a topological view of the CoreSight components and configure
+	  the right series of components on user input via sysfs. It also
+	  provides status information to user space applications through
+	  sysfs interface.
 
-config MSM_QDSS_STM_DEFAULT_ENABLE
-	bool "Turn on CoreSight STM tracing by default"
-	depends on MSM_QDSS
+	  If unsure, say 'N' here to avoid potential power, performance and
+	  memory penalty.
+
+if CORESIGHT
+
+config HAVE_CORESIGHT_SINK
+	bool
+
+config CORESIGHT_CSR
+	bool "CoreSight Slave Register driver"
+	help
+	  This driver provides support for CoreSight Slave Register block
+	  that hosts miscellaneous configuration registers.
+
+config CORESIGHT_TMC
+	bool "CoreSight Trace Memory Controller driver"
+	select CORESIGHT_CSR
+	select HAVE_CORESIGHT_SINK
+	help
+	  This driver provides support for Trace Memory Controller which
+	  can be configured as either an ETB (Embedded Trace Buffer),
+	  ETR (Embedded Trace Router) or ETF (Embedded Trace Fifo). It acts
+	  as sink when configured as ETB, ETR or ETF in circular buffer mode
+	  whereas it is a link when configured as ETF in hardware fifo mode.
+
+	  ETB collects trace data in a circular buffer whereas ETR can be
+	  used to route trace data to memory allocated in RAM. ETF in
+	  circular buffer mode is like an ETB whereas in hardware fifo mode
+	  it is a fifo link.
+
+config CORESIGHT_TPIU
+	bool "CoreSight Trace Port Interface Unit driver"
+	select HAVE_CORESIGHT_SINK
+	help
+	  This driver provides support for Trace Port Interface Unit which
+	  acts as a conduit for offchip trace collection.
+
+config CORESIGHT_ETB
+	bool "CoreSight Embedded Trace Buffer driver"
+	select HAVE_CORESIGHT_SINK
+	help
+	  This driver provides support for the legacy Embedded Trace Buffer
+	  which is a circular buffer.
+
+if HAVE_CORESIGHT_SINK
+
+config CORESIGHT_FUNNEL
+	bool "CoreSight Funnel driver"
+	help
+	  This driver provides support for Funnel which is a link that
+	  typically has multiple input ports and a single output port. Input
+	  trace data streams from the input ports are interleaved into a
+	  single output trace data stream coming out of the output port.
+
+config CORESIGHT_REPLICATOR
+	bool "CoreSight Replicator driver"
+	help
+	  This driver provides support for Replicator that typically has
+	  a single input port and two output ports. Single trace data
+	  stream on the input port is replicated to produce two identical
+	  trace data output streams coming out of the two output ports.
+
+config CORESIGHT_STM
+	bool "CoreSight System Trace Macrocell driver"
+	help
+	  This driver provides support for hardware assisted software
+	  instrumentation based tracing. This is primarily useful for
+	  logging useful software events or data.
+
+config CORESIGHT_STM_DEFAULT_ENABLE
+	bool "Turn on STM tracing by default"
+	depends on CORESIGHT_STM
 	help
 	  Turns on CoreSight STM tracing (hardware assisted software
 	  instrumentation based tracing) by default. Otherwise, tracing is
 	  disabled by default but can be enabled via sysfs.
 
-	  For production builds, you should probably say 'N' here to avoid
-	  potential power, performance and memory penalty.
+	  If unsure, say 'N' here to avoid potential power and performance
+	  penalty.
 
-config MSM_QDSS_ETM_DEFAULT_ENABLE
-	bool "Turn on CoreSight ETM tracing by default"
-	depends on MSM_QDSS
+config CORESIGHT_ETM
+	bool "CoreSight Embedded Trace Macrocell driver"
+	help
+	  This driver provides support for processor tracing which allows
+	  tracing the instructions that the processor is executing. This is
+	  primarily useful for instruction level tracing.
+
+config CORESIGHT_ETM_DEFAULT_ENABLE
+	bool "Turn on ETM tracing by default"
+	depends on CORESIGHT_ETM
 	help
 	  Turns on CoreSight ETM tracing (processor tracing) by default.
 	  Otherwise, tracing is disabled by default but can be enabled via
 	  sysfs.
 
-	  For production builds, you should probably say 'N' here to avoid
-	  potential power, performance and memory penalty.
+	  If unsure, say 'N' here to avoid potential power and performance
+	  penalty.
 
-config MSM_QDSS_ETM_PCSAVE_DEFAULT_ENABLE
+config CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE
 	bool "Turn on PC saving by default"
-	depends on MSM_QDSS
+	depends on CORESIGHT_ETM
 	help
 	  Turns on program counter saving on reset by default. Otherwise,
 	  PC saving is disabled by default but can be enabled via sysfs.
 
-	  For production builds, you should probably say 'N' here to avoid
-	  potential power penalty.
+	  If unsure, say 'N' here to avoid potential power penalty.
 
-config CONTROL_TRACE
-	tristate "Turn on to control tracing"
+endif
+
+config CORESIGHT_EVENT
+	tristate "CoreSight Event driver"
 	help
-	  Builds module to abort tracing on a user space data, instruction
-	  or prefetch abort.
+	  This driver provides support for registering with various events
+	  and performing CoreSight actions like aborting trace on their
+	  occurrence.
 
-	  For production builds, you should probably say 'N' here to avoid
-	  potential power, performance and memory penalty.
+endif
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 033e5a0..8c73794 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -1,3 +1,14 @@
-obj-$(CONFIG_CONTROL_TRACE) += control_trace.o
+#
+# Makefile for CoreSight drivers.
+#
+obj-$(CONFIG_CORESIGHT) += coresight.o
 obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-csr.o coresight-tmc.o coresight-tpiu.o coresight-etb.o coresight-funnel.o coresight-replicator.o coresight-stm.o coresight-etm.o coresight-etm-cp14.o
+obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
+obj-$(CONFIG_CORESIGHT_TMC) += coresight-tmc.o
+obj-$(CONFIG_CORESIGHT_TPIU) += coresight-tpiu.o
+obj-$(CONFIG_CORESIGHT_ETB) += coresight-etb.o
+obj-$(CONFIG_CORESIGHT_FUNNEL) += coresight-funnel.o
+obj-$(CONFIG_CORESIGHT_REPLICATOR) += coresight-replicator.o
+obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
+obj-$(CONFIG_CORESIGHT_ETM) += coresight-etm.o coresight-etm-cp14.o
+obj-$(CONFIG_CORESIGHT_EVENT) += coresight-event.o
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index e734ece..4774c76 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -119,6 +119,21 @@
 }
 EXPORT_SYMBOL_GPL(msm_qdss_csr_disable_bam_to_usb);
 
+void msm_qdss_csr_disable_flush(void)
+{
+	struct csr_drvdata *drvdata = csrdrvdata;
+	uint32_t usbflshctrl;
+
+	CSR_UNLOCK(drvdata);
+
+	usbflshctrl = csr_readl(drvdata, CSR_USBFLSHCTRL);
+	usbflshctrl &= ~0x2;
+	csr_writel(drvdata, usbflshctrl, CSR_USBFLSHCTRL);
+
+	CSR_LOCK(drvdata);
+}
+EXPORT_SYMBOL_GPL(msm_qdss_csr_disable_flush);
+
 static int __devinit csr_probe(struct platform_device *pdev)
 {
 	int ret;
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 521d9ec..73c1499 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -181,7 +181,7 @@
 	ETM_ADDR_TYPE_STOP,
 };
 
-#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
+#ifdef CONFIG_CORESIGHT_ETM_DEFAULT_ENABLE
 static int boot_enable = 1;
 #else
 static int boot_enable;
@@ -190,7 +190,7 @@
 	boot_enable, boot_enable, int, S_IRUGO
 );
 
-#ifdef CONFIG_MSM_QDSS_ETM_PCSAVE_DEFAULT_ENABLE
+#ifdef CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE
 static int boot_pcsave_enable = 1;
 #else
 static int boot_pcsave_enable;
diff --git a/drivers/coresight/control_trace.c b/drivers/coresight/coresight-event.c
similarity index 100%
rename from drivers/coresight/control_trace.c
rename to drivers/coresight/coresight-event.c
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index 0cf2b3d..258ff09 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -36,14 +36,19 @@
 #define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
 #define BVAL(val, n)		((val & BIT(n)) >> n)
 
-#ifdef CONFIG_MSM_QDSS
+#ifdef CONFIG_CORESIGHT_CSR
 extern void msm_qdss_csr_enable_bam_to_usb(void);
 extern void msm_qdss_csr_disable_bam_to_usb(void);
-extern unsigned int etm_readl_cp14(uint32_t off);
-extern void etm_writel_cp14(uint32_t val, uint32_t off);
+extern void msm_qdss_csr_disable_flush(void);
 #else
 static inline void msm_qdss_csr_enable_bam_to_usb(void) {}
 static inline void msm_qdss_csr_disable_bam_to_usb(void) {}
+static inline void msm_qdss_csr_disable_flush(void) {}
+#endif
+#ifdef CONFIG_CORESIGHT_ETM
+extern unsigned int etm_readl_cp14(uint32_t off);
+extern void etm_writel_cp14(uint32_t val, uint32_t off);
+#else
 static inline unsigned int etm_readl_cp14(uint32_t off) { return 0; }
 static inline void etm_writel_cp14(uint32_t val, uint32_t off) {}
 #endif
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 86e792a..bc72e02 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -102,7 +102,7 @@
 					(ch * BYTES_PER_CHANNEL))
 #define stm_channel_off(type, opts)	(type & ~opts)
 
-#ifdef CONFIG_MSM_QDSS_STM_DEFAULT_ENABLE
+#ifdef CONFIG_CORESIGHT_STM_DEFAULT_ENABLE
 static int boot_enable = 1;
 #else
 static int boot_enable;
@@ -768,13 +768,6 @@
 
 	dev_info(drvdata->dev, "STM initialized\n");
 
-	/*
-	 * Enable and disable STM to undo the temporary default STM enable
-	 * done by RPM.
-	 */
-	coresight_enable(drvdata->csdev);
-	coresight_disable(drvdata->csdev);
-
 	if (boot_enable)
 		coresight_enable(drvdata->csdev);
 
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index d49652f..10eabca 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -155,6 +155,18 @@
 	uint32_t		trigger_cntr;
 };
 
+static void tmc_wait_for_flush(struct tmc_drvdata *drvdata)
+{
+	int count;
+
+	/* Ensure no flush is in progress */
+	for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_FFSR), 0) != 0
+				&& count > 0; count--)
+		udelay(1);
+	WARN(count == 0, "timeout while waiting for TMC flush, TMC_FFSR: %#x\n",
+	     tmc_readl(drvdata, TMC_FFSR));
+}
+
 static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
 {
 	int count;
@@ -238,7 +250,7 @@
 
 	tmc_writel(drvdata, bamdata->data_fifo.phys_base, TMC_DBALO);
 	tmc_writel(drvdata, 0x0, TMC_DBAHI);
-	tmc_writel(drvdata, 0x133, TMC_FFCR);
+	tmc_writel(drvdata, 0x103, TMC_FFCR);
 	tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
 	__tmc_enable(drvdata);
 
@@ -255,7 +267,12 @@
 	if (bamdata->enable)
 		return 0;
 
-	/* Configure and enable ndp bam */
+	/* Reset bam to start with */
+	ret = sps_device_reset(bamdata->handle);
+	if (ret)
+		goto err0;
+
+	/* Now configure and enable bam */
 
 	bamdata->pipe = sps_alloc_endpoint();
 	if (!bamdata->pipe)
@@ -263,7 +280,7 @@
 
 	ret = sps_get_config(bamdata->pipe, &bamdata->connect);
 	if (ret)
-		goto err;
+		goto err1;
 
 	bamdata->connect.mode = SPS_MODE_SRC;
 	bamdata->connect.source = bamdata->handle;
@@ -278,12 +295,13 @@
 
 	ret = sps_connect(bamdata->pipe, &bamdata->connect);
 	if (ret)
-		goto err;
+		goto err1;
 
 	bamdata->enable = true;
 	return 0;
-err:
+err1:
 	sps_free_endpoint(bamdata->pipe);
+err0:
 	return ret;
 }
 
@@ -292,14 +310,18 @@
 	if (!drvdata->enable_to_bam)
 		return;
 
+	/* Ensure periodic flush is disabled in CSR block */
+	msm_qdss_csr_disable_flush();
+
 	TMC_UNLOCK(drvdata);
 
+	tmc_wait_for_flush(drvdata);
 	tmc_flush_and_stop(drvdata);
 	__tmc_disable(drvdata);
 
 	TMC_LOCK(drvdata);
 
-	/* Disable CSR registers */
+	/* Disable CSR configuration */
 	msm_qdss_csr_disable_bam_to_usb();
 	drvdata->enable_to_bam = false;
 }
diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c
index 39bc9ff..aef3d26 100644
--- a/drivers/coresight/coresight.c
+++ b/drivers/coresight/coresight.c
@@ -196,6 +196,9 @@
 	struct list_head *p;
 	struct coresight_connection *conn;
 
+	if (!csdev)
+		return NULL;
+
 	if (csdev->id == curr_sink) {
 		list_add_tail(&csdev->path_link, path);
 		return path;
@@ -273,9 +276,9 @@
 
 static int coresight_switch_sink(struct coresight_device *csdev)
 {
-	int ret = 0;
+	int ret, prev_sink;
 	LIST_HEAD(path);
-	struct coresight_device *cd;
+	struct coresight_device *cd, *err_cd;
 
 	if (IS_ERR_OR_NULL(csdev))
 		return -EINVAL;
@@ -291,10 +294,15 @@
 			coresight_release_path(&path);
 		}
 	}
+	prev_sink = curr_sink;
 	curr_sink = csdev->id;
 	list_for_each_entry(cd, &coresight_devs, dev_link) {
 		if (cd->type == CORESIGHT_DEV_TYPE_SOURCE && cd->enable) {
-			coresight_build_path(cd, &path);
+			if (!coresight_build_path(cd, &path)) {
+				ret = -EINVAL;
+				pr_err("coresight: build path failed\n");
+				goto err;
+			}
 			ret = coresight_enable_path(&path, false);
 			coresight_release_path(&path);
 			if (ret)
@@ -305,17 +313,30 @@
 	up(&coresight_mutex);
 	return 0;
 err:
-	list_for_each_entry(cd, &coresight_devs, dev_link) {
+	err_cd = cd;
+	list_for_each_entry_continue_reverse(cd, &coresight_devs, dev_link) {
+		if (cd->type == CORESIGHT_DEV_TYPE_SOURCE && cd->enable) {
+			coresight_build_path(cd, &path);
+			coresight_disable_path(&path, true);
+			coresight_release_path(&path);
+		}
+	}
+	cd = err_cd;
+	/* This should be an enabled source, so we can disable it directly */
+	coresight_disable_source(cd);
+	list_for_each_entry_continue(cd, &coresight_devs, dev_link) {
 		if (cd->type == CORESIGHT_DEV_TYPE_SOURCE && cd->enable)
 			coresight_disable_source(cd);
 	}
+	curr_sink = prev_sink;
+	up(&coresight_mutex);
 	pr_err("coresight: sink switch failed, sources disabled; try again\n");
 	return ret;
 }
 
 int coresight_enable(struct coresight_device *csdev)
 {
-	int ret = 0;
+	int ret;
 	LIST_HEAD(path);
 
 	if (IS_ERR_OR_NULL(csdev))
@@ -325,18 +346,26 @@
 	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
 		ret = -EINVAL;
 		pr_err("coresight: wrong device type in %s\n", __func__);
-		goto out;
+		goto err;
 	}
 	if (csdev->enable)
 		goto out;
 
-	coresight_build_path(csdev, &path);
+	if (!coresight_build_path(csdev, &path)) {
+		ret = -EINVAL;
+		pr_err("coresight: build path failed\n");
+		goto err;
+	}
 	ret = coresight_enable_path(&path, true);
 	coresight_release_path(&path);
 	if (ret)
-		pr_err("coresight: enable failed\n");
+		goto err;
 out:
 	up(&coresight_mutex);
+	return 0;
+err:
+	up(&coresight_mutex);
+	pr_err("coresight: enable failed\n");
 	return ret;
 }
 EXPORT_SYMBOL_GPL(coresight_enable);
@@ -670,7 +699,7 @@
 {
 	return bus_register(&coresight_bus_type);
 }
-subsys_initcall(coresight_init);
+core_initcall(coresight_init);
 
 static void __exit coresight_exit(void)
 {
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 043d6b6..3da06a5 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -39,6 +39,8 @@
 #include "qcryptohw_50.h"
 
 #define CRYPTO_CONFIG_RESET 0xE001F
+#define QCE_MAX_NUM_DSCR    0x400
+#define QCE_SIZE_BAM_DSCR   0x08
 
 static DEFINE_MUTEX(bam_register_cnt);
 struct bam_registration_info {
@@ -139,11 +141,37 @@
 {
 	int i;
 
-	for (i = 0; nbytes > 0; i++, sg = sg_next(sg))
+	for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg))
 		nbytes -= sg->length;
 	return i;
 }
 
+static int qce_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; ++i) {
+		dma_map_sg(dev, sg, 1, direction);
+		sg = scatterwalk_sg_next(sg);
+	}
+
+	return nents;
+}
+
+static int qce_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+	int nents, enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; ++i) {
+		dma_unmap_sg(dev, sg, 1, direction);
+		sg = scatterwalk_sg_next(sg);
+	}
+
+	return nents;
+}
+
 static int _probe_ce_engine(struct qce_device *pce_dev)
 {
 	unsigned int rev;
@@ -675,13 +703,13 @@
 
 	areq = (struct aead_request *) pce_dev->areq;
 	if (areq->src != areq->dst) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 					DMA_FROM_DEVICE);
 	}
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 							DMA_TO_DEVICE);
-	dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
 			DMA_TO_DEVICE);
 	/* check MAC */
 	memcpy(mac, (char *)(&pce_dev->ce_sps.result->auth_iv[0]),
@@ -721,7 +749,7 @@
 	uint32_t bytecount32[2];
 
 	areq = (struct ahash_request *) pce_dev->areq;
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 				DMA_TO_DEVICE);
 	memcpy(digest, (char *)(&pce_dev->ce_sps.result->auth_iv[0]),
 						SHA256_DIGEST_SIZE);
@@ -743,10 +771,10 @@
 	areq = (struct ablkcipher_request *) pce_dev->areq;
 
 	if (areq->src != areq->dst) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
 			pce_dev->dst_nents, DMA_FROM_DEVICE);
 	}
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 		(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 						DMA_TO_DEVICE);
 	if (_qce_unlock_other_pipes(pce_dev))
@@ -910,7 +938,7 @@
 			addr += data_cnt;
 			len -= data_cnt;
 		}
-		sg_src++;
+		sg_src = scatterwalk_sg_next(sg_src);
 	}
 	return 0;
 }
@@ -1042,7 +1070,7 @@
 	 * descriptor memory (256 bytes + 8 bytes). But in order to be
 	 * in power of 2, we are allocating 512 bytes of memory.
 	 */
-	sps_connect_info->desc.size = 512;
+	sps_connect_info->desc.size = QCE_MAX_NUM_DSCR * QCE_SIZE_BAM_DSCR;
 	sps_connect_info->desc.base = dma_alloc_coherent(pce_dev->pdev,
 					sps_connect_info->desc.size,
 					&sps_connect_info->desc.phys_base,
@@ -2248,16 +2276,16 @@
 	pce_dev->phy_iv_in = 0;
 
 	/* associated data input */
-	dma_map_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
 					 DMA_TO_DEVICE);
 	/* cipher input */
-	dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 							DMA_TO_DEVICE);
 	/* cipher + mac output  for encryption    */
 	if (areq->src != areq->dst) {
 		pce_dev->dst_nents = count_sg(areq->dst, out_len);
-		dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 				DMA_FROM_DEVICE);
 	} else {
 		pce_dev->dst_nents = pce_dev->src_nents;
@@ -2374,16 +2402,16 @@
 
 bad:
 	if (pce_dev->assoc_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
-				DMA_TO_DEVICE);
+		qce_dma_unmap_sg(pce_dev->pdev, areq->assoc,
+				pce_dev->assoc_nents, DMA_TO_DEVICE);
 	}
 	if (pce_dev->src_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 				(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 								DMA_TO_DEVICE);
 	}
 	if (areq->src != areq->dst) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 				DMA_FROM_DEVICE);
 	}
 	if (pce_dev->phy_iv_in) {
@@ -2410,14 +2438,14 @@
 	/* cipher input */
 	pce_dev->src_nents = count_sg(areq->src, areq->nbytes);
 
-	dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 		(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 							DMA_TO_DEVICE);
 	/* cipher output */
 	if (areq->src != areq->dst) {
 		pce_dev->dst_nents = count_sg(areq->dst, areq->nbytes);
-			dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
-							DMA_FROM_DEVICE);
+			qce_dma_map_sg(pce_dev->pdev, areq->dst,
+				pce_dev->dst_nents, DMA_FROM_DEVICE);
 	} else {
 		pce_dev->dst_nents = pce_dev->src_nents;
 	}
@@ -2488,12 +2516,14 @@
 		goto bad;
 		return 0;
 bad:
-	if (pce_dev->dst_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst,
-		pce_dev->dst_nents, DMA_FROM_DEVICE);
+	if (areq->src != areq->dst) {
+		if (pce_dev->dst_nents) {
+			qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
+			pce_dev->dst_nents, DMA_FROM_DEVICE);
+		}
 	}
 	if (pce_dev->src_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->src,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->src,
 				pce_dev->src_nents,
 				(areq->src == areq->dst) ?
 				DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
@@ -2512,7 +2542,7 @@
 
 	pce_dev->src_nents = count_sg(sreq->src, sreq->size);
 	_ce_get_hash_cmdlistinfo(pce_dev, sreq, &cmdlistinfo);
-	dma_map_sg(pce_dev->pdev, sreq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, sreq->src, pce_dev->src_nents,
 							DMA_TO_DEVICE);
 	rc = _ce_setup_hash(pce_dev, sreq, cmdlistinfo);
 	if (rc < 0)
@@ -2558,7 +2588,7 @@
 		return 0;
 bad:
 	if (pce_dev->src_nents) {
-		dma_unmap_sg(pce_dev->pdev, sreq->src,
+		qce_dma_unmap_sg(pce_dev->pdev, sreq->src,
 				pce_dev->src_nents, DMA_TO_DEVICE);
 	}
 	return rc;
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 4d32e0f..50d454c 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1,6 +1,6 @@
 /* Qualcomm CE device driver.
  *
- * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -721,11 +721,11 @@
 
 
 static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
-				struct qcedev_handle *handle)
+				struct qcedev_handle *handle,
+				struct scatterlist *sg_src)
 {
 	int err = 0;
 	int i = 0;
-	struct scatterlist sg_src[2];
 	uint32_t total;
 
 	uint8_t *user_src = NULL;
@@ -814,7 +814,7 @@
 	sha_pad_len = ALIGN(total, CE_SHA_BLOCK_SIZE) - total;
 	trailing_buf_len =  CE_SHA_BLOCK_SIZE - sha_pad_len;
 
-	qcedev_areq->sha_req.sreq.src = (struct scatterlist *) &sg_src[0];
+	qcedev_areq->sha_req.sreq.src = sg_src;
 	sg_set_buf(qcedev_areq->sha_req.sreq.src, k_align_src,
 						total-trailing_buf_len);
 	sg_mark_end(qcedev_areq->sha_req.sreq.src);
@@ -840,7 +840,8 @@
 }
 
 static int qcedev_sha_update(struct qcedev_async_req *qcedev_areq,
-				struct qcedev_handle *handle)
+				struct qcedev_handle *handle,
+				struct scatterlist *sg_src)
 {
 	int err = 0;
 	int i = 0;
@@ -887,7 +888,7 @@
 				sreq->entries = 1;
 
 				err = qcedev_sha_update_max_xfer(qcedev_areq,
-									handle);
+								handle, sg_src);
 
 				sreq->data[i].len = req.data[i].len -
 							QCE_MAX_OPER_DATA;
@@ -921,7 +922,7 @@
 
 				i = j;
 				err = qcedev_sha_update_max_xfer(qcedev_areq,
-									handle);
+								handle, sg_src);
 				num_entries = 0;
 
 				sreq->data[i].vaddr = req.data[i].vaddr +
@@ -945,7 +946,7 @@
 		sreq->data_len = saved_req->data_len;
 		kfree(saved_req);
 	} else
-		err = qcedev_sha_update_max_xfer(qcedev_areq, handle);
+		err = qcedev_sha_update_max_xfer(qcedev_areq, handle, sg_src);
 
 	return err;
 }
@@ -997,11 +998,11 @@
 }
 
 static int qcedev_hash_cmac(struct qcedev_async_req *qcedev_areq,
-					struct qcedev_handle *handle)
+					struct qcedev_handle *handle,
+					struct scatterlist *sg_src)
 {
 	int err = 0;
 	int i = 0;
-	struct scatterlist sg_src[2];
 	uint32_t total;
 
 	uint8_t *user_src = NULL;
@@ -1050,7 +1051,7 @@
 		k_src += qcedev_areq->sha_op_req.data[i].len;
 	}
 
-	qcedev_areq->sha_req.sreq.src = (struct scatterlist *) &sg_src[0];
+	qcedev_areq->sha_req.sreq.src = sg_src;
 	sg_set_buf(qcedev_areq->sha_req.sreq.src, k_buf_src, total);
 	sg_mark_end(qcedev_areq->sha_req.sreq.src);
 
@@ -1063,7 +1064,8 @@
 }
 
 static int qcedev_set_hmac_auth_key(struct qcedev_async_req *areq,
-					struct qcedev_handle *handle)
+					struct qcedev_handle *handle,
+					struct scatterlist *sg_src)
 {
 	int err = 0;
 
@@ -1102,7 +1104,7 @@
 		authkey_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
 
 		qcedev_sha_init(&authkey_areq, handle);
-		err = qcedev_sha_update(&authkey_areq, handle);
+		err = qcedev_sha_update(&authkey_areq, handle, sg_src);
 		if (!err)
 			err = qcedev_sha_final(&authkey_areq, handle);
 		else
@@ -1208,12 +1210,13 @@
 }
 
 static int qcedev_hmac_init(struct qcedev_async_req *areq,
-				struct qcedev_handle *handle)
+				struct qcedev_handle *handle,
+				struct scatterlist *sg_src)
 {
 	int err;
 	struct qcedev_control *podev = handle->cntl;
 
-	err = qcedev_set_hmac_auth_key(areq, handle);
+	err = qcedev_set_hmac_auth_key(areq, handle, sg_src);
 	if (err)
 		return err;
 	if (!podev->ce_support.sha_hmac)
@@ -1241,19 +1244,21 @@
 }
 
 static int qcedev_hash_init(struct qcedev_async_req *areq,
-				struct qcedev_handle *handle)
+				struct qcedev_handle *handle,
+				struct scatterlist *sg_src)
 {
 	if ((areq->sha_op_req.alg == QCEDEV_ALG_SHA1) ||
 			(areq->sha_op_req.alg == QCEDEV_ALG_SHA256))
 		return qcedev_sha_init(areq, handle);
 	else
-		return qcedev_hmac_init(areq, handle);
+		return qcedev_hmac_init(areq, handle, sg_src);
 }
 
 static int qcedev_hash_update(struct qcedev_async_req *qcedev_areq,
-				struct qcedev_handle *handle)
+				struct qcedev_handle *handle,
+				struct scatterlist *sg_src)
 {
-	return qcedev_sha_update(qcedev_areq, handle);
+	return qcedev_sha_update(qcedev_areq, handle, sg_src);
 }
 
 static int qcedev_hash_final(struct qcedev_async_req *areq,
@@ -1895,7 +1900,8 @@
 		break;
 
 	case QCEDEV_IOCTL_SHA_INIT_REQ:
-
+		{
+		struct scatterlist sg_src;
 		if (!access_ok(VERIFY_WRITE, (void __user *)arg,
 				sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
@@ -1907,17 +1913,20 @@
 		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
 			return -EINVAL;
 		qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
-		err = qcedev_hash_init(&qcedev_areq, handle);
+		err = qcedev_hash_init(&qcedev_areq, handle, &sg_src);
 		if (err)
 			return err;
 		if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
 				return -EFAULT;
+		}
 		break;
 	case QCEDEV_IOCTL_GET_CMAC_REQ:
 		if (!podev->ce_support.cmac)
 			return -ENOTTY;
 	case QCEDEV_IOCTL_SHA_UPDATE_REQ:
+		{
+		struct scatterlist sg_src;
 		if (!access_ok(VERIFY_WRITE, (void __user *)arg,
 				sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
@@ -1931,11 +1940,11 @@
 		qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
 
 		if (qcedev_areq.sha_op_req.alg == QCEDEV_ALG_AES_CMAC) {
-			err = qcedev_hash_cmac(&qcedev_areq, handle);
+			err = qcedev_hash_cmac(&qcedev_areq, handle, &sg_src);
 			if (err)
 				return err;
 		} else {
-			err = qcedev_hash_update(&qcedev_areq, handle);
+			err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
 			if (err)
 				return err;
 		}
@@ -1946,6 +1955,7 @@
 		if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
+		}
 		break;
 
 	case QCEDEV_IOCTL_SHA_FINAL_REQ:
@@ -1974,7 +1984,8 @@
 		break;
 
 	case QCEDEV_IOCTL_GET_SHA_REQ:
-
+		{
+		struct scatterlist sg_src;
 		if (!access_ok(VERIFY_WRITE, (void __user *)arg,
 				sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
@@ -1986,8 +1997,8 @@
 		if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
 			return -EINVAL;
 		qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
-		qcedev_hash_init(&qcedev_areq, handle);
-		err = qcedev_hash_update(&qcedev_areq, handle);
+		qcedev_hash_init(&qcedev_areq, handle, &sg_src);
+		err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
 		if (err)
 			return err;
 		err = qcedev_hash_final(&qcedev_areq, handle);
@@ -2000,6 +2011,7 @@
 		if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
 			return -EFAULT;
+		}
 		break;
 
 	default:
@@ -2126,6 +2138,10 @@
 	struct qcedev_stat *pstat;
 	int len = 0;
 
+	if (id < 0) {
+		pr_err("Crypto id is %d, cannot be negative\n", id);
+		return len;
+	}
 	pstat = &_qcedev_stat[id];
 	len = snprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
 			"\nQualcomm QCE dev driver %d Statistics:\n",
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index b64368d..7e063ca 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -367,7 +367,17 @@
 	mutex_unlock(&sent_bw_req);
 }
 
-static void _start_qcrypto_process(struct crypto_priv *cp);
+static int _start_qcrypto_process(struct crypto_priv *cp);
+
+static int qcrypto_count_sg(struct scatterlist *sg, int nbytes)
+{
+	int i;
+
+	for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg))
+		nbytes -= sg->length;
+
+	return i;
+}
 
 static struct qcrypto_alg *_qcrypto_sha_alg_alloc(struct crypto_priv *cp,
 		struct ahash_alg *template)
@@ -545,6 +555,10 @@
 	struct crypto_stat *pstat;
 	int len = 0;
 
+	if (id < 0) {
+		pr_err("Crypto id is %d, cannot be negative\n", id);
+		return len;
+	}
 	pstat = &_qcrypto_stat[id];
 	len = snprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
 			"\nQualcomm crypto accelerator %d Statistics:\n",
@@ -865,18 +879,19 @@
 
 	if (cp->ce_support.aligned_only)  {
 		struct qcrypto_cipher_req_ctx *rctx;
-		struct scatterlist *sg;
+		uint32_t num_sg = 0;
 		uint32_t bytes = 0;
 
 		rctx = ablkcipher_request_ctx(areq);
 		areq->src = rctx->orig_src;
 		areq->dst = rctx->orig_dst;
 
-		for (sg = areq->dst; bytes != areq->nbytes; sg++) {
-			memcpy(sg_virt(sg), ((char *)rctx->data + bytes),
-								sg->length);
-			bytes += sg->length;
-		}
+		num_sg = qcrypto_count_sg(areq->dst, areq->nbytes);
+		bytes = sg_copy_from_buffer(areq->dst, num_sg,
+			rctx->data, areq->nbytes);
+		if (bytes != areq->nbytes)
+			pr_warn("bytes copied=0x%x bytes to copy= 0x%x", bytes,
+								areq->nbytes);
 		kfree(rctx->data);
 	}
 
@@ -903,9 +918,9 @@
 	if (rctx->mode == QCE_MODE_CCM) {
 		if (cp->ce_support.aligned_only)  {
 			struct qcrypto_cipher_req_ctx *rctx;
-			struct scatterlist *sg;
 			uint32_t bytes = 0;
 			uint32_t nbytes = 0;
+			uint32_t num_sg = 0;
 
 			rctx = aead_request_ctx(areq);
 			areq->src = rctx->orig_src;
@@ -916,13 +931,13 @@
 			else
 				nbytes = areq->cryptlen -
 						crypto_aead_authsize(aead);
-
-			for (sg = areq->dst; bytes != nbytes; sg++) {
-				memcpy(sg_virt(sg),
-				((char *)rctx->data + areq->assoclen + bytes),
-								sg->length);
-				bytes += sg->length;
-			}
+			num_sg = qcrypto_count_sg(areq->dst, nbytes);
+			bytes = sg_copy_from_buffer(areq->dst, num_sg,
+					((char *)rctx->data + areq->assoclen),
+					nbytes);
+			if (bytes != nbytes)
+				pr_warn("bytes copied=0x%x bytes to copy= 0x%x",
+						bytes, nbytes);
 			kfree(rctx->data);
 		}
 		kzfree(rctx->assoc);
@@ -1014,7 +1029,9 @@
 						struct scatterlist *sg)
 {
 	unsigned char *adata;
-	uint32_t len, l;
+	uint32_t len;
+	uint32_t bytes = 0;
+	uint32_t num_sg = 0;
 
 	qreq->assoc = kzalloc((alen + 0x64), (GFP_KERNEL | __GFP_DMA));
 	if (!qreq->assoc) {
@@ -1043,11 +1060,12 @@
 	}
 	adata += len;
 	qreq->assoclen = ALIGN((alen + len), 16);
-	for (l = alen; l > 0; sg = scatterwalk_sg_next(sg)) {
-		memcpy(adata, sg_virt(sg), sg->length);
-		l -= sg->length;
-		adata += sg->length;
-	}
+
+	num_sg = qcrypto_count_sg(sg, alen);
+	bytes = sg_copy_to_buffer(sg, num_sg, adata, alen);
+	if (bytes != alen)
+		pr_warn("bytes copied=0x%x bytes to copy= 0x%x", bytes, alen);
+
 	return 0;
 }
 
@@ -1067,23 +1085,29 @@
 	tfm = crypto_ablkcipher_reqtfm(req);
 	if (cp->ce_support.aligned_only) {
 		uint32_t bytes = 0;
-		struct scatterlist *sg = req->src;
+		uint32_t num_sg = 0;
 
 		rctx->orig_src = req->src;
 		rctx->orig_dst = req->dst;
 		rctx->data = kzalloc((req->nbytes + 64), GFP_KERNEL);
-		for (sg = req->src; bytes != req->nbytes; sg++) {
-			memcpy(((char *)rctx->data + bytes),
-					sg_virt(sg), sg->length);
-			bytes += sg->length;
+
+		if (rctx->data == NULL) {
+			pr_err("Mem Alloc fail rctx->data, err %ld for 0x%x\n",
+				PTR_ERR(rctx->data), (req->nbytes + 64));
+			return -ENOMEM;
 		}
+		num_sg = qcrypto_count_sg(req->src, req->nbytes);
+		bytes = sg_copy_to_buffer(req->src, num_sg, rctx->data,
+								req->nbytes);
+		if (bytes != req->nbytes)
+			pr_warn("bytes copied=0x%x bytes to copy= 0x%x", bytes,
+								req->nbytes);
 		sg_set_buf(&rctx->dsg, rctx->data, req->nbytes);
 		sg_mark_end(&rctx->dsg);
 		rctx->iv = req->info;
 
 		req->src = &rctx->dsg;
 		req->dst = &rctx->dsg;
-
 	}
 	qreq.op = QCE_REQ_ABLK_CIPHER;
 	qreq.qce_cb = _qce_ablk_cipher_complete;
@@ -1207,20 +1231,26 @@
 
 		if (cp->ce_support.aligned_only) {
 			uint32_t bytes = 0;
-			struct scatterlist *sg = req->src;
+			uint32_t num_sg = 0;
 
 			rctx->orig_src = req->src;
 			rctx->orig_dst = req->dst;
 			rctx->data = kzalloc((req->cryptlen + qreq.assoclen +
 					qreq.authsize + 64*2), GFP_KERNEL);
+			if (rctx->data == NULL) {
+				pr_err("Mem Alloc fail rctx->data, err %ld\n",
+							PTR_ERR(rctx->data));
+				return -ENOMEM;
+			}
 
 			memcpy((char *)rctx->data, qreq.assoc, qreq.assoclen);
 
-			for (sg = req->src; bytes != req->cryptlen; sg++) {
-				memcpy((rctx->data + bytes + qreq.assoclen),
-						sg_virt(sg), sg->length);
-				bytes += sg->length;
-			}
+			num_sg = qcrypto_count_sg(req->src, req->cryptlen);
+			bytes = sg_copy_to_buffer(req->src, num_sg,
+				rctx->data + qreq.assoclen , req->cryptlen);
+			if (bytes != req->cryptlen)
+				pr_warn("bytes copied=0x%x bytes to copy= 0x%x",
+							bytes, req->cryptlen);
 			sg_set_buf(&rctx->ssg, rctx->data, req->cryptlen +
 							qreq.assoclen);
 			sg_mark_end(&rctx->ssg);
@@ -1260,13 +1290,13 @@
 	return ret;
 }
 
-static void _start_qcrypto_process(struct crypto_priv *cp)
+static int _start_qcrypto_process(struct crypto_priv *cp)
 {
 	struct crypto_async_request *async_req = NULL;
 	struct crypto_async_request *backlog = NULL;
 	unsigned long flags;
 	u32 type;
-	int ret;
+	int ret = 0;
 	struct crypto_stat *pstat;
 
 	pstat = &_qcrypto_stat[cp->pdev->id];
@@ -1280,7 +1310,7 @@
 	}
 	spin_unlock_irqrestore(&cp->lock, flags);
 	if (!async_req)
-		return;
+		return ret;
 	if (backlog)
 		backlog->complete(backlog, -EINPROGRESS);
 	type = crypto_tfm_alg_type(async_req->tfm);
@@ -1315,6 +1345,7 @@
 		async_req->complete(async_req, ret);
 		goto again;
 	};
+	return ret;
 };
 
 static int _qcrypto_queue_req(struct crypto_priv *cp,
@@ -2114,16 +2145,6 @@
 	return _qcrypto_queue_req(cp, &areq->base);
 }
 
-static int qcrypto_count_sg(struct scatterlist *sg, int nbytes)
-{
-	int i;
-
-	for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg))
-		nbytes -= sg->length;
-
-	return i;
-}
-
 static int _sha_init(struct qcrypto_sha_ctx *ctx)
 {
 	ctx->first_blk = 1;
@@ -2259,25 +2280,32 @@
 	return 0;
 }
 
-static void _copy_source(struct ahash_request  *req)
+static int _copy_source(struct ahash_request  *req)
 {
 	struct qcrypto_sha_req_ctx *srctx = NULL;
 	uint32_t bytes = 0;
-	struct scatterlist *sg = req->src;
+	uint32_t num_sg = 0;
 
 	srctx = ahash_request_ctx(req);
 	srctx->orig_src = req->src;
 	srctx->data = kzalloc((req->nbytes + 64), GFP_KERNEL);
-	for (sg = req->src; bytes != req->nbytes;
-						sg++) {
-		memcpy(((char *)srctx->data + bytes),
-			sg_virt(sg), sg->length);
-		bytes += sg->length;
+	if (srctx->data == NULL) {
+		pr_err("Mem Alloc fail rctx->data, err %ld for 0x%x\n",
+				PTR_ERR(srctx->data), (req->nbytes + 64));
+		return -ENOMEM;
 	}
+
+	num_sg = qcrypto_count_sg(req->src, req->nbytes);
+	bytes = sg_copy_to_buffer(req->src, num_sg, srctx->data, req->nbytes);
+	if (bytes != req->nbytes)
+		pr_warn("bytes copied=0x%x bytes to copy= 0x%x", bytes,
+							req->nbytes);
 	sg_set_buf(&srctx->dsg, srctx->data,
 				req->nbytes);
 	sg_mark_end(&srctx->dsg);
 	req->src = &srctx->dsg;
+
+	return 0;
 }
 
 static int _sha_update(struct ahash_request  *req, uint32_t sha_block_size)
@@ -2285,13 +2313,15 @@
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_priv *cp = sha_ctx->cp;
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	uint32_t total, len, i, num_sg;
+	uint32_t total, len, num_sg;
+	struct scatterlist *sg_last;
 	uint8_t *k_src = NULL;
 	uint32_t sha_pad_len = 0;
-	uint32_t end_src = 0;
 	uint32_t trailing_buf_len = 0;
-	uint32_t nbytes, index = 0;
-	uint32_t saved_length = 0;
+	uint32_t nbytes;
+	uint32_t offset = 0;
+	uint32_t bytes = 0;
+
 	int ret = 0;
 
 	/* check for trailing buffer from previous updates and append it */
@@ -2299,16 +2329,10 @@
 	len = req->nbytes;
 
 	if (total <= sha_block_size) {
-		i = 0;
-
 		k_src = &sha_ctx->trailing_buf[sha_ctx->trailing_buf_len];
-		while (len > 0) {
-			memcpy(k_src, sg_virt(&req->src[i]),
-							req->src[i].length);
-			len -= req->src[i].length;
-			k_src += req->src[i].length;
-			i++;
-		}
+		num_sg = qcrypto_count_sg(req->src, len);
+		bytes = sg_copy_to_buffer(req->src, num_sg, k_src, len);
+
 		sha_ctx->trailing_buf_len = total;
 		if (sha_ctx->alg == QCE_HASH_SHA1)
 			_update_sha1_ctx(req);
@@ -2327,37 +2351,24 @@
 	/*  get new trailing buffer */
 	sha_pad_len = ALIGN(total, sha_block_size) - total;
 	trailing_buf_len =  sha_block_size - sha_pad_len;
+	offset = req->nbytes - trailing_buf_len;
+
+	if (offset != req->nbytes)
+		scatterwalk_map_and_copy(k_src, req->src, offset,
+						trailing_buf_len, 0);
+
 	nbytes = total - trailing_buf_len;
 	num_sg = qcrypto_count_sg(req->src, req->nbytes);
 
 	len = sha_ctx->trailing_buf_len;
-	i = 0;
+	sg_last = req->src;
 
 	while (len < nbytes) {
-		if ((len + req->src[i].length) > nbytes)
+		if ((len + sg_last->length) > nbytes)
 			break;
-		len += req->src[i].length;
-		i++;
+		len += sg_last->length;
+		sg_last = scatterwalk_sg_next(sg_last);
 	}
-
-	end_src = i;
-	if (len < nbytes) {
-		uint32_t remnant = (nbytes - len);
-		memcpy(k_src, (sg_virt(&req->src[i]) + remnant),
-				(req->src[i].length - remnant));
-		k_src += (req->src[i].length - remnant);
-		saved_length = req->src[i].length;
-		index = i;
-		req->src[i].length = remnant;
-		i++;
-	}
-
-	while (i < num_sg) {
-		memcpy(k_src, sg_virt(&req->src[i]), req->src[i].length);
-		k_src += req->src[i].length;
-		i++;
-	}
-
 	if (sha_ctx->trailing_buf_len) {
 		if (cp->ce_support.aligned_only)  {
 			sha_ctx->sg = kzalloc(sizeof(struct scatterlist),
@@ -2377,20 +2388,18 @@
 			memcpy(rctx->data2, sha_ctx->tmp_tbuf,
 						sha_ctx->trailing_buf_len);
 			memcpy((rctx->data2 + sha_ctx->trailing_buf_len),
-					rctx->data, req->src[i-1].length);
+					rctx->data, req->src->length);
 			kfree(rctx->data);
 			rctx->data = rctx->data2;
 			sg_set_buf(&sha_ctx->sg[0], rctx->data,
 					(sha_ctx->trailing_buf_len +
-							req->src[i-1].length));
+							req->src->length));
 			req->src = sha_ctx->sg;
 			sg_mark_end(&sha_ctx->sg[0]);
-
 		} else {
-			num_sg = end_src + 2;
-
-			sha_ctx->sg = kzalloc(num_sg *
-				(sizeof(struct scatterlist)), GFP_KERNEL);
+			sg_mark_end(sg_last);
+			sha_ctx->sg = kzalloc(2 * (sizeof(struct scatterlist)),
+								GFP_KERNEL);
 			if (sha_ctx->sg == NULL) {
 				pr_err("MEMalloc fail sha_ctx->sg, error %ld\n",
 							PTR_ERR(sha_ctx->sg));
@@ -2399,21 +2408,14 @@
 
 			sg_set_buf(&sha_ctx->sg[0], sha_ctx->tmp_tbuf,
 						sha_ctx->trailing_buf_len);
-			for (i = 1; i < num_sg; i++)
-				sg_set_buf(&sha_ctx->sg[i],
-						sg_virt(&req->src[i-1]),
-						req->src[i-1].length);
-
+			sg_mark_end(&sha_ctx->sg[1]);
+			sg_chain(sha_ctx->sg, 2, req->src);
 			req->src = sha_ctx->sg;
-			sg_mark_end(&sha_ctx->sg[num_sg - 1]);
-
 		}
 	} else
-		sg_mark_end(&req->src[end_src]);
+		sg_mark_end(sg_last);
 
 	req->nbytes = nbytes;
-	if (saved_length > 0)
-		rctx->src[index].length = saved_length;
 	sha_ctx->trailing_buf_len = trailing_buf_len;
 
 	ret =  _qcrypto_queue_req(cp, &req->base);
@@ -2428,9 +2430,10 @@
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_priv *cp = sha_ctx->cp;
 
-	if (cp->ce_support.aligned_only)
-		_copy_source(req);
-
+	if (cp->ce_support.aligned_only) {
+		if (_copy_source(req))
+			return -ENOMEM;
+	}
 	sha_state_ctx->count += req->nbytes;
 	return _sha_update(req, SHA1_BLOCK_SIZE);
 }
@@ -2442,8 +2445,10 @@
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_priv *cp = sha_ctx->cp;
 
-	if (cp->ce_support.aligned_only)
-		_copy_source(req);
+	if (cp->ce_support.aligned_only) {
+		if (_copy_source(req))
+			return -ENOMEM;
+	}
 
 	sha_state_ctx->count += req->nbytes;
 	return _sha_update(req, SHA256_BLOCK_SIZE);
@@ -2456,8 +2461,10 @@
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 	int ret = 0;
 
-	if (cp->ce_support.aligned_only)
-		_copy_source(req);
+	if (cp->ce_support.aligned_only) {
+		if (_copy_source(req))
+			return -ENOMEM;
+	}
 
 	sha_ctx->last_blk = 1;
 
@@ -2494,8 +2501,10 @@
 	struct crypto_priv *cp = sha_ctx->cp;
 	int ret = 0;
 
-	if (cp->ce_support.aligned_only)
-		_copy_source(req);
+	if (cp->ce_support.aligned_only) {
+		if (_copy_source(req))
+			return -ENOMEM;
+	}
 
 	/* save the original req structure fields*/
 	rctx->src = req->src;
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 7ef8c15..cd15d71 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -648,6 +648,19 @@
 	struct ion_iommu_map *iommu_map;
 	int ret = 0;
 
+	if (IS_ERR_OR_NULL(client)) {
+		pr_err("%s: client pointer is invalid\n", __func__);
+		return -EINVAL;
+	}
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: handle pointer is invalid\n", __func__);
+		return -EINVAL;
+	}
+	if (IS_ERR_OR_NULL(handle->buffer)) {
+		pr_err("%s: buffer pointer is invalid\n", __func__);
+		return -EINVAL;
+	}
+
 	if (ION_IS_CACHED(flags)) {
 		pr_err("%s: Cannot map iommu as cached.\n", __func__);
 		return -EINVAL;
@@ -755,6 +768,19 @@
 	struct ion_iommu_map *iommu_map;
 	struct ion_buffer *buffer;
 
+	if (IS_ERR_OR_NULL(client)) {
+		pr_err("%s: client pointer is invalid\n", __func__);
+		return;
+	}
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: handle pointer is invalid\n", __func__);
+		return;
+	}
+	if (IS_ERR_OR_NULL(handle->buffer)) {
+		pr_err("%s: buffer pointer is invalid\n", __func__);
+		return;
+	}
+
 	mutex_lock(&client->lock);
 	buffer = handle->buffer;
 
@@ -1533,6 +1559,10 @@
 {
 	struct ion_device *dev = heap->dev;
 	struct rb_node *n;
+	size_t size;
+
+	if (!heap->ops->phys)
+		return;
 
 	for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
 		struct ion_buffer *buffer =
@@ -1545,9 +1575,11 @@
 					   "Part of memory map will not be logged\n");
 				break;
 			}
-			data->addr = buffer->priv_phys;
-			data->addr_end = buffer->priv_phys + buffer->size-1;
-			data->size = buffer->size;
+
+			buffer->heap->ops->phys(buffer->heap, buffer,
+						&(data->addr), &size);
+			data->size = (unsigned long) size;
+			data->addr_end = data->addr + data->size - 1;
 			data->client_name = ion_debug_locate_owner(dev, buffer);
 			ion_debug_mem_map_add(mem_map, data);
 		}
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 849d72e..3e55a57 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -2,7 +2,7 @@
  * drivers/gpu/ion/ion_carveout_heap.c
  *
  * Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -377,8 +377,9 @@
 
 	if (extra) {
 		unsigned long extra_iova_addr = data->iova_addr + buffer->size;
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, extra,
-					  SZ_4K, prot);
+		unsigned long phys_addr = sg_phys(sglist);
+		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+					extra, SZ_4K, prot);
 		if (ret)
 			goto out2;
 	}
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c
index bef6b6f..4f5ac75 100644
--- a/drivers/gpu/ion/ion_cma_heap.c
+++ b/drivers/gpu/ion/ion_cma_heap.c
@@ -228,8 +228,9 @@
 
 	extra_iova_addr = data->iova_addr + buffer->size;
 	if (extra) {
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, extra, SZ_4K,
-						prot);
+		unsigned long phys_addr = sg_phys(table->sgl);
+		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+					extra, SZ_4K, prot);
 		if (ret)
 			goto out2;
 	}
@@ -304,6 +305,35 @@
 	return 0;
 }
 
+static int ion_cma_print_debug(struct ion_heap *heap, struct seq_file *s,
+			const struct rb_root *mem_map)
+{
+	if (mem_map) {
+		struct rb_node *n;
+
+		seq_printf(s, "\nMemory Map\n");
+		seq_printf(s, "%16.s %14.s %14.s %14.s\n",
+			   "client", "start address", "end address",
+			   "size (hex)");
+
+		for (n = rb_first(mem_map); n; n = rb_next(n)) {
+			struct mem_map_data *data =
+					rb_entry(n, struct mem_map_data, node);
+			const char *client_name = "(null)";
+
+
+			if (data->client_name)
+				client_name = data->client_name;
+
+			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
+				   client_name, data->addr,
+				   data->addr_end,
+				   data->size, data->size);
+		}
+	}
+	return 0;
+}
+
 static struct ion_heap_ops ion_cma_ops = {
 	.allocate = ion_cma_allocate,
 	.free = ion_cma_free,
@@ -316,6 +346,7 @@
 	.map_iommu = ion_cma_map_iommu,
 	.unmap_iommu = ion_cma_unmap_iommu,
 	.cache_op = ion_cma_cache_ops,
+	.print_debug = ion_cma_print_debug,
 };
 
 struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 4649606..f4d85fa 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -861,7 +861,7 @@
 	struct ion_cp_buffer *buf = buffer->priv_virt;
 
 	mutex_lock(&cp_heap->lock);
-	if (cp_heap->heap_protected == HEAP_NOT_PROTECTED) {
+	if (cp_heap->heap_protected == HEAP_NOT_PROTECTED && !buf->is_secure) {
 		if (ion_cp_request_region(cp_heap)) {
 			mutex_unlock(&cp_heap->lock);
 			return -EINVAL;
@@ -1086,6 +1086,7 @@
 		}
 		if (domain_num == cp_heap->iommu_2x_map_domain)
 			ret_value = msm_iommu_map_extra(domain, temp_iova,
+							cp_heap->base,
 							cp_heap->total_size,
 							SZ_64K, prot);
 		if (ret_value)
@@ -1179,8 +1180,9 @@
 
 	if (extra) {
 		unsigned long extra_iova_addr = data->iova_addr + buffer->size;
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, extra,
-					  SZ_4K, prot);
+		unsigned long phys_addr = sg_phys(buffer->sg_table->sgl);
+		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+					extra, SZ_4K, prot);
 		if (ret)
 			goto out2;
 	}
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 3834f80..304a39e 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -351,8 +351,9 @@
 
 	if (extra) {
 		unsigned long extra_iova_addr = data->iova_addr + buffer->size;
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, extra, SZ_4K,
-					  prot);
+		unsigned long phys_addr = sg_phys(buffer->sg_table->sgl);
+		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+					extra, SZ_4K, prot);
 		if (ret)
 			goto out2;
 	}
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 566286c..f33fc18 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -2,7 +2,7 @@
  * drivers/gpu/ion/ion_system_heap.c
  *
  * Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -280,8 +280,9 @@
 
 	extra_iova_addr = data->iova_addr + buffer->size;
 	if (extra) {
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, extra, SZ_4K,
-					  prot);
+		unsigned long phys_addr = sg_phys(table->sgl);
+		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+					extra, SZ_4K, prot);
 		if (ret)
 			goto out2;
 	}
@@ -500,8 +501,9 @@
 
 	if (extra) {
 		unsigned long extra_iova_addr = data->iova_addr + buffer->size;
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, extra, SZ_4K,
-					  prot);
+		unsigned long phys_addr = sg_phys(sglist);
+		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+					extra, SZ_4K, prot);
 		if (ret)
 			goto out2;
 	}
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index fec5363..3441afa 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Iinclude/drm -Idrivers/gpu/msm
+ccflags-y := -Iinclude/uapi/drm -Iinclude/drm -Idrivers/gpu/msm
 
 msm_kgsl_core-y = \
 	kgsl.o \
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 4a47c59..0127735 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -537,11 +537,14 @@
 #define RBBM_BLOCK_ID_MARB_3           0x2b
 
 /* RBBM_CLOCK_CTL default value */
-#define A305_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
-#define A320_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
-#define A330_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
+#define A305_RBBM_CLOCK_CTL_DEFAULT   0xAAAAAAAA
+#define A320_RBBM_CLOCK_CTL_DEFAULT   0xBFFFFFFF
+#define A330_RBBM_CLOCK_CTL_DEFAULT   0xAAAAAAAE
+#define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
+#define A305B_RBBM_CLOCK_CTL_DEFAULT  0xAAAAAAAA
 
-#define A330_RBBM_GPR0_CTL_DEFAULT  0x00000000
+#define A330_RBBM_GPR0_CTL_DEFAULT  0x0AE2B8AE
+#define A330v2_RBBM_GPR0_CTL_DEFAULT  0x00000000
 
 /* COUNTABLE FOR SP PERFCOUNTER */
 #define SP_FS_FULL_ALU_INSTRUCTIONS    0x0E
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 0a46da3..c495890 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -192,16 +192,19 @@
 		"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
 		1536, 768, 3, SZ_512K, 0x225011, 0x225002 },
 	/* A3XX doesn't use the pix_shader_start */
-	{ ADRENO_REV_A305, 3, 0, 5, ANY_ID,
+	{ ADRENO_REV_A305, 3, 0, 5, 0,
 		"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
 		512, 0, 2, SZ_256K, 0x3FF037, 0x3FF016 },
 	/* A3XX doesn't use the pix_shader_start */
 	{ ADRENO_REV_A320, 3, 2, ANY_ID, ANY_ID,
 		"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
 		512, 0, 2, SZ_512K, 0x3FF037, 0x3FF016 },
-	{ ADRENO_REV_A330, 3, 3, 0, 0,
+	{ ADRENO_REV_A330, 3, 3, 0, ANY_ID,
 		"a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev,
 		512, 0, 2, SZ_1M, NO_VER, NO_VER },
+	{ ADRENO_REV_A305B, 3, 0, 5, 0x10,
+		"a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev,
+		512, 0, 2, SZ_128K, NO_VER, NO_VER },
 };
 
 static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
@@ -986,7 +989,7 @@
 			KGSL_CORE_ERR("Unable to read KGSL IOMMU 'reg'\n");
 			goto err;
 		}
-		if (msm_soc_version_supports_iommu_v1())
+		if (msm_soc_version_supports_iommu_v0())
 			ctxs[ctx_index].ctx_id = (reg_val[0] -
 				data->physstart) >> KGSL_IOMMU_CTX_SHIFT;
 		else
@@ -1046,10 +1049,9 @@
 	if (ret)
 		goto err;
 
-	/* Default value is 83, if not found in DT */
 	if (adreno_of_read_property(pdev->dev.of_node, "qcom,idle-timeout",
 		&pdata->idle_timeout))
-		pdata->idle_timeout = 83;
+		pdata->idle_timeout = HZ/12;
 
 	if (adreno_of_read_property(pdev->dev.of_node, "qcom,nap-allowed",
 		&pdata->nap_allowed))
@@ -1109,7 +1111,8 @@
 static int
 adreno_ocmem_gmem_malloc(struct adreno_device *adreno_dev)
 {
-	if (!adreno_is_a330(adreno_dev))
+	if (!(adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)))
 		return 0;
 
 	/* OCMEM is only needed once, do not support consective allocation */
@@ -1130,7 +1133,8 @@
 static void
 adreno_ocmem_gmem_free(struct adreno_device *adreno_dev)
 {
-	if (!adreno_is_a330(adreno_dev))
+	if (!(adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)))
 		return;
 
 	if (adreno_dev->ocmem_hdl == NULL)
@@ -2238,7 +2242,7 @@
 		 * get an interrupt
 		 */
 
-		if (context) {
+		if (context && device->state != KGSL_STATE_SLUMBER) {
 			adreno_ringbuffer_issuecmds(device, context->devctxt,
 					KGSL_CMD_FLAGS_NONE, NULL, 0);
 		}
@@ -2247,10 +2251,11 @@
 	return 0;
 }
 
-static void adreno_next_event(struct kgsl_device *device,
+/* Return 1 if the event timestmp has already passed, 0 if it was marked */
+static int adreno_next_event(struct kgsl_device *device,
 		struct kgsl_event *event)
 {
-	adreno_check_hw_ts(device, event->context, event->timestamp);
+	return adreno_check_hw_ts(device, event->context, event->timestamp);
 }
 
 static int adreno_check_interrupt_timestamp(struct kgsl_device *device,
@@ -2290,6 +2295,7 @@
 	unsigned int curr_reg_val[hang_detect_regs_count];
 	unsigned int hang_detected = 1;
 	unsigned int i;
+	static unsigned long next_hang_detect_time;
 
 	if (!adreno_dev->fast_hang_detect)
 		return 0;
@@ -2313,6 +2319,18 @@
 		return 0;
 	}
 
+	/*
+	 * Time interval between hang detection should be KGSL_TIMEOUT_PART
+	 * or more, if next hang detection is requested < KGSL_TIMEOUT_PART
+	 * from the last time do nothing.
+	 */
+	if ((next_hang_detect_time) &&
+		(time_before(jiffies, next_hang_detect_time)))
+			return 0;
+	else
+		next_hang_detect_time = (jiffies +
+			msecs_to_jiffies(KGSL_TIMEOUT_PART-1));
+
 	for (i = 0; i < hang_detect_regs_count; i++) {
 
 		if (hang_detect_regs[i] == 0)
@@ -2573,7 +2591,8 @@
 		break;
 	}
 	case KGSL_TIMESTAMP_CONSUMED:
-		adreno_regread(device, REG_CP_TIMESTAMP, &timestamp);
+		kgsl_sharedmem_readl(&device->memstore, &timestamp,
+			KGSL_MEMSTORE_OFFSET(context_id, soptimestamp));
 		break;
 	case KGSL_TIMESTAMP_RETIRED:
 		kgsl_sharedmem_readl(&device->memstore, &timestamp,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 2d35e8a..cc6eb16 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -72,6 +72,7 @@
 	ADRENO_REV_A305 = 305,
 	ADRENO_REV_A320 = 320,
 	ADRENO_REV_A330 = 330,
+	ADRENO_REV_A305B = 335,
 };
 
 struct adreno_gpudev;
@@ -265,6 +266,11 @@
 	return (adreno_dev->gpurev == ADRENO_REV_A305);
 }
 
+static inline int adreno_is_a305b(struct adreno_device *adreno_dev)
+{
+	return (adreno_dev->gpurev == ADRENO_REV_A305B);
+}
+
 static inline int adreno_is_a320(struct adreno_device *adreno_dev)
 {
 	return (adreno_dev->gpurev == ADRENO_REV_A320);
@@ -275,6 +281,12 @@
 	return (adreno_dev->gpurev == ADRENO_REV_A330);
 }
 
+static inline int adreno_is_a330v2(struct adreno_device *adreno_dev)
+{
+	return ((adreno_dev->gpurev == ADRENO_REV_A330) &&
+		(ADRENO_CHIPID_PATCH(adreno_dev->chip_id) > 0));
+}
+
 static inline int adreno_rb_ctxtswitch(unsigned int *cmd)
 {
 	return (cmd[0] == cp_nop_packet(1) &&
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index c408f1b..bbe97de 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -452,8 +452,12 @@
 		return A305_RBBM_CLOCK_CTL_DEFAULT;
 	else if (adreno_is_a320(adreno_dev))
 		return A320_RBBM_CLOCK_CTL_DEFAULT;
+	else if (adreno_is_a330v2(adreno_dev))
+		return A330v2_RBBM_CLOCK_CTL_DEFAULT;
 	else if (adreno_is_a330(adreno_dev))
 		return A330_RBBM_CLOCK_CTL_DEFAULT;
+	else if (adreno_is_a305b(adreno_dev))
+		return A305B_RBBM_CLOCK_CTL_DEFAULT;
 
 	BUG_ON(1);
 }
@@ -2759,6 +2763,11 @@
 	{0, 0},
 };
 
+static struct a3xx_vbif_data a305b_vbif[] = {
+	{ A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 },
+	{0, 0},
+};
+
 static struct a3xx_vbif_data a320_vbif[] = {
 	/* Set up 16 deep read/write request queues */
 	{ A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 },
@@ -2809,17 +2818,50 @@
 	{0, 0},
 };
 
+/*
+ * Most of the VBIF registers on 8974v2 have the correct values at power on, so
+ * we won't modify those if we don't need to
+ */
+static struct a3xx_vbif_data a330v2_vbif[] = {
+	/* Enable 1k sort */
+	{ A3XX_VBIF_ABIT_SORT, 0x0001003F },
+	{ A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4 },
+	/* Enable WR-REQ */
+	{ A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003F },
+	{ A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303 },
+	/* Set up VBIF_ROUND_ROBIN_QOS_ARB */
+	{ A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 },
+	/* Disable VBIF clock gating. This is to enable AXI running
+	 * higher frequency than GPU.
+	 */
+	{ A3XX_VBIF_CLKON, 1 },
+	{0, 0},
+};
+
+static struct {
+	int(*devfunc)(struct adreno_device *);
+	struct a3xx_vbif_data *vbif;
+} a3xx_vbif_platforms[] = {
+	{ adreno_is_a305, a305_vbif },
+	{ adreno_is_a320, a320_vbif },
+	/* A330v2 needs to be ahead of A330 so the right device matches */
+	{ adreno_is_a330v2, a330v2_vbif },
+	{ adreno_is_a330, a330_vbif },
+	{ adreno_is_a305b, a305b_vbif },
+};
+
 static void a3xx_start(struct adreno_device *adreno_dev)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 	struct a3xx_vbif_data *vbif = NULL;
+	int i;
 
-	if (adreno_is_a305(adreno_dev))
-		vbif = a305_vbif;
-	else if (adreno_is_a320(adreno_dev))
-		vbif = a320_vbif;
-	else if (adreno_is_a330(adreno_dev))
-		vbif = a330_vbif;
+	for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) {
+		if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) {
+			vbif = a3xx_vbif_platforms[i].vbif;
+			break;
+		}
+	}
 
 	BUG_ON(vbif == NULL);
 
@@ -2859,12 +2901,16 @@
 	adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL,
 		adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
 
-	if (adreno_is_a330(adreno_dev))
+	if (adreno_is_a330v2(adreno_dev))
 		adreno_regwrite(device, A3XX_RBBM_GPR0_CTL,
-		A330_RBBM_GPR0_CTL_DEFAULT);
+			A330v2_RBBM_GPR0_CTL_DEFAULT);
+	else if (adreno_is_a330(adreno_dev))
+		adreno_regwrite(device, A3XX_RBBM_GPR0_CTL,
+			A330_RBBM_GPR0_CTL_DEFAULT);
 
 	/* Set the OCMEM base address for A330 */
-	if (adreno_is_a330(adreno_dev)) {
+	if (adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)) {
 		adreno_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
 			(unsigned int)(adreno_dev->ocmem_base >> 14));
 	}
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index c3f0ae6..58e3126 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -214,7 +214,8 @@
 	int i, size;
 
 	/* The size of the ROQ buffer is core dependent */
-	size = adreno_is_a330(adreno_dev) ?
+	size = (adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)) ?
 		A330_CP_ROQ_SIZE : A320_CP_ROQ_SIZE;
 
 	if (remain < DEBUG_SECTION_SZ(size)) {
@@ -287,7 +288,8 @@
 	 * like CP are larger
 	 */
 
-	dwords = adreno_is_a330(adreno_dev) ?
+	dwords = (adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)) ?
 		block->dwords : 0x40;
 
 	size = (dwords * sizeof(unsigned int)) + sizeof(*header);
@@ -447,7 +449,7 @@
 	/* Store relevant registers in list to snapshot */
 	_snapshot_a3xx_regs(regs, &list);
 	_snapshot_hlsq_regs(regs, &list, adreno_dev);
-	if (adreno_is_a330(adreno_dev))
+	if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev))
 		_snapshot_a330_regs(regs, &list);
 
 	/* Master set of (non debug) registers */
@@ -458,7 +460,8 @@
 	/*
 	 * CP_STATE_DEBUG indexed registers - 20 on 305 and 320 and 46 on A330
 	 */
-	size = adreno_is_a330(adreno_dev) ? 0x2E : 0x14;
+	size = (adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)) ? 0x2E : 0x14;
 
 	snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
 			remain, REG_CP_STATE_DEBUG_INDEX,
@@ -503,7 +506,8 @@
 			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
 			a3xx_snapshot_cp_roq, NULL);
 
-	if (adreno_is_a330(adreno_dev)) {
+	if (adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)) {
 		snapshot = kgsl_snapshot_add_section(device,
 			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
 			a330_snapshot_cp_merciu, NULL);
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index d81d72e..2b9c286 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -912,7 +912,8 @@
 			adreno_dump_regs(device, a3xx_registers,
 					a3xx_registers_count);
 
-			if (adreno_is_a330(adreno_dev))
+			if (adreno_is_a330(adreno_dev) ||
+				adreno_is_a305b(adreno_dev))
 				adreno_dump_regs(device, a330_registers,
 					a330_registers_count);
 		}
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 03828c6..d4cccbd 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -577,14 +577,13 @@
 		total_sizedwords += 2; /* CP_WAIT_FOR_IDLE */
 
 	total_sizedwords += 2; /* scratchpad ts for recovery */
+	total_sizedwords += 3; /* sop timestamp */
+	total_sizedwords += 4; /* eop timestamp */
+
 	if (context && context->flags & CTXT_FLAGS_PER_CONTEXT_TS &&
 			!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
-		total_sizedwords += 3; /* sop timestamp */
-		total_sizedwords += 4; /* eop timestamp */
 		total_sizedwords += 3; /* global timestamp without cache
 					* flush for non-zero context */
-	} else {
-		total_sizedwords += 4; /* global timestamp for recovery*/
 	}
 
 	if (adreno_is_a20x(adreno_dev))
@@ -610,6 +609,31 @@
 		GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_INTERNAL_IDENTIFIER);
 	}
 
+	/* always increment the global timestamp. once. */
+	rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
+
+	/* Do not update context's timestamp for internal submissions */
+	if (context && !(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
+		if (context_id == KGSL_MEMSTORE_GLOBAL)
+			rb->timestamp[context->id] =
+				rb->timestamp[KGSL_MEMSTORE_GLOBAL];
+		else if (context->flags & CTXT_FLAGS_USER_GENERATED_TS)
+			rb->timestamp[context_id] = timestamp;
+		else
+			rb->timestamp[context_id]++;
+	}
+	timestamp = rb->timestamp[context_id];
+
+	/* scratchpad ts for recovery */
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+
+	/* start-of-pipeline timestamp */
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2));
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+		KGSL_MEMSTORE_OFFSET(context_id, soptimestamp)));
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
+
 	if (flags & KGSL_CMD_FLAGS_PMODE) {
 		/* disable protected mode error checking */
 		GSL_RB_WRITE(ringcmds, rcmd_gpu,
@@ -629,21 +653,6 @@
 		GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
 	}
 
-	/* always increment the global timestamp. once. */
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
-
-	/* Do not update context's timestamp for internal submissions */
-	if (context && !(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
-		if (context_id == KGSL_MEMSTORE_GLOBAL)
-			rb->timestamp[context->id] =
-				rb->timestamp[KGSL_MEMSTORE_GLOBAL];
-		else if (context->flags & CTXT_FLAGS_USER_GENERATED_TS)
-			rb->timestamp[context_id] = timestamp;
-		else
-			rb->timestamp[context_id]++;
-	}
-	timestamp = rb->timestamp[context_id];
-
 	/* HW Workaround for MMU Page fault
 	* due to memory getting free early before
 	* GPU completes it.
@@ -654,14 +663,10 @@
 		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
 	}
 
-	/* scratchpad ts for recovery */
-	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
-	GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
-
 	if (adreno_is_a3xx(adreno_dev)) {
 		/*
-		 * FLush HLSQ lazy updates to make sure there are no
-		 * rsources pending for indirect loads after the timestamp
+		 * Flush HLSQ lazy updates to make sure there are no
+		 * resources pending for indirect loads after the timestamp
 		 */
 
 		GSL_RB_WRITE(ringcmds, rcmd_gpu,
@@ -672,22 +677,19 @@
 		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
 	}
 
+	/*
+	 * end-of-pipeline timestamp.  If per context timestamps is not
+	 * enabled, then context_id will be KGSL_MEMSTORE_GLOBAL so all
+	 * eop timestamps will work out.
+	 */
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3));
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+		KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
+	GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
+
 	if (context && context->flags & CTXT_FLAGS_PER_CONTEXT_TS
 			&& !(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
-		/* start-of-pipeline timestamp */
-		GSL_RB_WRITE(ringcmds, rcmd_gpu,
-			cp_type3_packet(CP_MEM_WRITE, 2));
-		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
-			KGSL_MEMSTORE_OFFSET(context_id, soptimestamp)));
-		GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
-
-		/* end-of-pipeline timestamp */
-		GSL_RB_WRITE(ringcmds, rcmd_gpu,
-			cp_type3_packet(CP_EVENT_WRITE, 3));
-		GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
-		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
-			KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
-		GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
 
 		GSL_RB_WRITE(ringcmds, rcmd_gpu,
 			cp_type3_packet(CP_MEM_WRITE, 2));
@@ -696,15 +698,6 @@
 				eoptimestamp)));
 		GSL_RB_WRITE(ringcmds, rcmd_gpu,
 			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
-	} else {
-		GSL_RB_WRITE(ringcmds, rcmd_gpu,
-			cp_type3_packet(CP_EVENT_WRITE, 3));
-		GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
-		GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
-			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
-						eoptimestamp)));
-		GSL_RB_WRITE(ringcmds, rcmd_gpu,
-				rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
 	}
 
 	if (adreno_is_a20x(adreno_dev)) {
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index f234d67..115fcb7 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1766,6 +1766,8 @@
 		entry->memdesc.sglen++;
 	}
 
+	entry->memdesc.size = PAGE_ALIGN(entry->memdesc.size);
+
 	return 0;
 err:
 	ion_free(kgsl_ion_client, handle);
@@ -1948,8 +1950,10 @@
 
 	mode = kgsl_memdesc_get_cachemode(&entry->memdesc);
 	if (mode != KGSL_CACHEMODE_UNCACHED
-		&& mode != KGSL_CACHEMODE_WRITECOMBINE)
+		&& mode != KGSL_CACHEMODE_WRITECOMBINE) {
+		trace_kgsl_mem_sync_cache(entry, op);
 		kgsl_cache_range_op(&entry->memdesc, cacheop);
+	}
 
 done:
 	return ret;
@@ -2324,34 +2328,48 @@
 typedef long (*kgsl_ioctl_func_t)(struct kgsl_device_private *,
 	unsigned int, void *);
 
-#define KGSL_IOCTL_FUNC(_cmd, _func, _lock) \
-	[_IOC_NR(_cmd)] = { .cmd = _cmd, .func = _func, .lock = _lock }
+#define KGSL_IOCTL_FUNC(_cmd, _func, _flags) \
+	[_IOC_NR((_cmd))] = \
+		{ .cmd = (_cmd), .func = (_func), .flags = (_flags) }
+
+#define KGSL_IOCTL_LOCK		BIT(0)
+#define KGSL_IOCTL_WAKE		BIT(1)
 
 static const struct {
 	unsigned int cmd;
 	kgsl_ioctl_func_t func;
-	int lock;
+	unsigned int flags;
 } kgsl_ioctl_funcs[] = {
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_GETPROPERTY,
-			kgsl_ioctl_device_getproperty, 1),
+			kgsl_ioctl_device_getproperty,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP,
-			kgsl_ioctl_device_waittimestamp, 1),
+			kgsl_ioctl_device_waittimestamp,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID,
-			kgsl_ioctl_device_waittimestamp_ctxtid, 1),
+			kgsl_ioctl_device_waittimestamp_ctxtid,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS,
-			kgsl_ioctl_rb_issueibcmds, 1),
+			kgsl_ioctl_rb_issueibcmds,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_READTIMESTAMP,
-			kgsl_ioctl_cmdstream_readtimestamp, 1),
+			kgsl_ioctl_cmdstream_readtimestamp,
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_CTXTID,
-			kgsl_ioctl_cmdstream_readtimestamp_ctxtid, 1),
+			kgsl_ioctl_cmdstream_readtimestamp_ctxtid,
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP,
-			kgsl_ioctl_cmdstream_freememontimestamp, 1),
+			kgsl_ioctl_cmdstream_freememontimestamp,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID,
-			kgsl_ioctl_cmdstream_freememontimestamp_ctxtid, 1),
+			kgsl_ioctl_cmdstream_freememontimestamp_ctxtid,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_CREATE,
-			kgsl_ioctl_drawctxt_create, 1),
+			kgsl_ioctl_drawctxt_create,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_DESTROY,
-			kgsl_ioctl_drawctxt_destroy, 1),
+			kgsl_ioctl_drawctxt_destroy,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_MAP_USER_MEM,
 			kgsl_ioctl_map_user_mem, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FROM_PMEM,
@@ -2367,9 +2385,11 @@
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_CFF_USER_EVENT,
 			kgsl_ioctl_cff_user_event, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
-			kgsl_ioctl_timestamp_event, 1),
+			kgsl_ioctl_timestamp_event,
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_SETPROPERTY,
-			kgsl_ioctl_device_setproperty, 1),
+			kgsl_ioctl_device_setproperty,
+			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC_ID,
 			kgsl_ioctl_gpumem_alloc_id, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_FREE_ID,
@@ -2385,7 +2405,7 @@
 	struct kgsl_device_private *dev_priv = filep->private_data;
 	unsigned int nr;
 	kgsl_ioctl_func_t func;
-	int lock, ret;
+	int lock, ret, use_hw;
 	char ustack[64];
 	void *uptr = NULL;
 
@@ -2442,7 +2462,8 @@
 		}
 
 		func = kgsl_ioctl_funcs[nr].func;
-		lock = kgsl_ioctl_funcs[nr].lock;
+		lock = kgsl_ioctl_funcs[nr].flags & KGSL_IOCTL_LOCK;
+		use_hw = kgsl_ioctl_funcs[nr].flags & KGSL_IOCTL_WAKE;
 	} else {
 		func = dev_priv->device->ftbl->ioctl;
 		if (!func) {
@@ -2452,11 +2473,13 @@
 			goto done;
 		}
 		lock = 1;
+		use_hw = 1;
 	}
 
 	if (lock) {
 		mutex_lock(&dev_priv->device->mutex);
-		kgsl_check_suspended(dev_priv->device);
+		if (use_hw)
+			kgsl_check_suspended(dev_priv->device);
 	}
 
 	ret = func(dev_priv, cmd, uptr);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 65598ba..62316f3 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -113,7 +113,7 @@
 		enum kgsl_property_type type, void *value,
 		unsigned int sizebytes);
 	int (*postmortem_dump) (struct kgsl_device *device, int manual);
-	void (*next_event)(struct kgsl_device *device,
+	int (*next_event)(struct kgsl_device *device,
 		struct kgsl_event *event);
 };
 
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 7606caa..764b044 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-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
@@ -131,88 +131,18 @@
 	struct list_head wait_list;
 };
 
-static struct ion_client *kgsl_drm_ion_phys_client;
+static struct ion_client *kgsl_drm_ion_client;
 
 static int kgsl_drm_inited = DRM_KGSL_NOT_INITED;
 
 /* This is a global list of all the memory currently mapped in the MMU */
 static struct list_head kgsl_mem_list;
 
-static void kgsl_gem_mem_flush(struct kgsl_memdesc *memdesc, int type, int op)
-{
-	int cacheop = 0;
-
-	switch (op) {
-	case DRM_KGSL_GEM_CACHE_OP_TO_DEV:
-		if (type & (DRM_KGSL_GEM_CACHE_WBACK |
-			    DRM_KGSL_GEM_CACHE_WBACKWA))
-			cacheop = KGSL_CACHE_OP_CLEAN;
-
-		break;
-
-	case DRM_KGSL_GEM_CACHE_OP_FROM_DEV:
-		if (type & (DRM_KGSL_GEM_CACHE_WBACK |
-			    DRM_KGSL_GEM_CACHE_WBACKWA |
-			    DRM_KGSL_GEM_CACHE_WTHROUGH))
-			cacheop = KGSL_CACHE_OP_INV;
-	}
-
-	kgsl_cache_range_op(memdesc, cacheop);
-}
-
-/* TODO:
- * Add vsync wait */
-
-static int kgsl_drm_load(struct drm_device *dev, unsigned long flags)
-{
-	return 0;
-}
-
-static int kgsl_drm_unload(struct drm_device *dev)
-{
-	return 0;
-}
-
 struct kgsl_drm_device_priv {
 	struct kgsl_device *device[KGSL_DEVICE_MAX];
 	struct kgsl_device_private *devpriv[KGSL_DEVICE_MAX];
 };
 
-void kgsl_drm_preclose(struct drm_device *dev, struct drm_file *file_priv)
-{
-}
-
-static int kgsl_drm_suspend(struct drm_device *dev, pm_message_t state)
-{
-	return 0;
-}
-
-static int kgsl_drm_resume(struct drm_device *dev)
-{
-	return 0;
-}
-
-static void
-kgsl_gem_free_mmap_offset(struct drm_gem_object *obj)
-{
-	struct drm_device *dev = obj->dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_kgsl_gem_object *priv = obj->driver_private;
-	struct drm_map_list *list;
-
-	list = &obj->map_list;
-	drm_ht_remove_item(&mm->offset_hash, &list->hash);
-	if (list->file_offset_node) {
-		drm_mm_put_block(list->file_offset_node);
-		list->file_offset_node = NULL;
-	}
-
-	kfree(list->map);
-	list->map = NULL;
-
-	priv->mmap_offset = 0;
-}
-
 static int
 kgsl_gem_memory_allocated(struct drm_gem_object *obj)
 {
@@ -224,6 +154,8 @@
 kgsl_gem_alloc_memory(struct drm_gem_object *obj)
 {
 	struct drm_kgsl_gem_object *priv = obj->driver_private;
+	struct sg_table *sg_table;
+	struct scatterlist *s;
 	int index;
 	int result = 0;
 
@@ -241,13 +173,10 @@
 		}
 	}
 
-	/* Set the flags for the memdesc (probably 0, unless it is cached) */
-	priv->memdesc.priv = 0;
-
 	if (TYPE_IS_PMEM(priv->type)) {
 		if (priv->type == DRM_KGSL_GEM_TYPE_EBI ||
 		    priv->type & DRM_KGSL_GEM_PMEM_EBI) {
-			priv->ion_handle = ion_alloc(kgsl_drm_ion_phys_client,
+			priv->ion_handle = ion_alloc(kgsl_drm_ion_client,
 				obj->size * priv->bufcount, PAGE_SIZE,
 				ION_HEAP(ION_SF_HEAP_ID), 0);
 			if (IS_ERR_OR_NULL(priv->ion_handle)) {
@@ -258,13 +187,13 @@
 
 			priv->memdesc.pagetable = priv->pagetable;
 
-			result = ion_phys(kgsl_drm_ion_phys_client,
+			result = ion_phys(kgsl_drm_ion_client,
 				priv->ion_handle, (ion_phys_addr_t *)
 				&priv->memdesc.physaddr, &priv->memdesc.size);
 			if (result) {
 				DRM_ERROR(
 				"Unable to get ION Physical memory address\n");
-				ion_free(kgsl_drm_ion_phys_client,
+				ion_free(kgsl_drm_ion_client,
 					priv->ion_handle);
 				priv->ion_handle = NULL;
 				return result;
@@ -275,7 +204,7 @@
 			if (result) {
 				DRM_ERROR(
 				"Unable to get sg list\n");
-				ion_free(kgsl_drm_ion_phys_client,
+				ion_free(kgsl_drm_ion_client,
 					priv->ion_handle);
 				priv->ion_handle = NULL;
 				return result;
@@ -285,8 +214,8 @@
 					GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
 			if (result) {
 				DRM_ERROR(
-				"Unable to map GPU\n");
-				ion_free(kgsl_drm_ion_phys_client,
+				"kgsl_mmu_map failed.  result = %d\n", result);
+				ion_free(kgsl_drm_ion_client,
 					priv->ion_handle);
 				priv->ion_handle = NULL;
 				return result;
@@ -301,15 +230,44 @@
 			priv->type & DRM_KGSL_GEM_CACHE_MASK)
 				list_add(&priv->list, &kgsl_mem_list);
 
-		result = kgsl_sharedmem_page_alloc_user(&priv->memdesc,
-					priv->pagetable,
-					obj->size * priv->bufcount);
+		priv->memdesc.pagetable = priv->pagetable;
 
-		if (result != 0) {
-				DRM_ERROR(
-				"Unable to allocate Vmalloc user memory\n");
-				return result;
+		priv->ion_handle = ion_alloc(kgsl_drm_ion_client,
+				obj->size * priv->bufcount, PAGE_SIZE,
+				ION_HEAP(ION_IOMMU_HEAP_ID), 0);
+		if (IS_ERR_OR_NULL(priv->ion_handle)) {
+			DRM_ERROR(
+				"Unable to allocate ION IOMMU memory handle\n");
+				return -ENOMEM;
 		}
+
+		sg_table = ion_sg_table(kgsl_drm_ion_client,
+				priv->ion_handle);
+		if (IS_ERR_OR_NULL(priv->ion_handle)) {
+			DRM_ERROR(
+			"Unable to get ION sg table\n");
+			goto memerr;
+		}
+
+		priv->memdesc.sg = sg_table->sgl;
+
+		/* Calculate the size of the memdesc from the sglist */
+
+		priv->memdesc.sglen = 0;
+
+		for (s = priv->memdesc.sg; s != NULL; s = sg_next(s)) {
+			priv->memdesc.size += s->length;
+			priv->memdesc.sglen++;
+		}
+
+		result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
+				GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+		if (result) {
+			DRM_ERROR(
+			"kgsl_mmu_map failed.  result = %d\n", result);
+			goto memerr;
+		}
+
 	} else
 		return -EINVAL;
 
@@ -321,7 +279,15 @@
 	}
 	priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED;
 
+
 	return 0;
+
+memerr:
+	ion_free(kgsl_drm_ion_client,
+		priv->ion_handle);
+	priv->ion_handle = NULL;
+	return -ENOMEM;
+
 }
 
 static void
@@ -332,16 +298,16 @@
 	if (!kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
 		return;
 
-	kgsl_gem_mem_flush(&priv->memdesc,  priv->type,
-			   DRM_KGSL_GEM_CACHE_OP_FROM_DEV);
-
 	if (priv->memdesc.gpuaddr)
 		kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc);
 
-	kgsl_sg_free(priv->memdesc.sg, priv->memdesc.sglen);
+	/* ION will take care of freeing the sg table. */
+	priv->memdesc.sg = NULL;
+	priv->memdesc.sglen = 0;
 
 	if (priv->ion_handle)
-		ion_free(kgsl_drm_ion_phys_client, priv->ion_handle);
+		ion_free(kgsl_drm_ion_client, priv->ion_handle);
+
 	priv->ion_handle = NULL;
 
 	memset(&priv->memdesc, 0, sizeof(priv->memdesc));
@@ -377,66 +343,10 @@
 kgsl_gem_free_object(struct drm_gem_object *obj)
 {
 	kgsl_gem_free_memory(obj);
-	kgsl_gem_free_mmap_offset(obj);
 	drm_gem_object_release(obj);
 	kfree(obj->driver_private);
 }
 
-static int
-kgsl_gem_create_mmap_offset(struct drm_gem_object *obj)
-{
-	struct drm_device *dev = obj->dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_kgsl_gem_object *priv = obj->driver_private;
-	struct drm_map_list *list;
-	int msize;
-
-	list = &obj->map_list;
-	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-	if (list->map == NULL) {
-		DRM_ERROR("Unable to allocate drm_map_list\n");
-		return -ENOMEM;
-	}
-
-	msize = obj->size * priv->bufcount;
-
-	list->map->type = _DRM_GEM;
-	list->map->size = msize;
-	list->map->handle = obj;
-
-	/* Allocate a mmap offset */
-	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-						    msize / PAGE_SIZE,
-						    0, 0);
-
-	if (!list->file_offset_node) {
-		DRM_ERROR("Failed to allocate offset for %d\n", obj->name);
-		kfree(list->map);
-		return -ENOMEM;
-	}
-
-	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-						  msize / PAGE_SIZE, 0);
-
-	if (!list->file_offset_node) {
-		DRM_ERROR("Unable to create the file_offset_node\n");
-		kfree(list->map);
-		return -ENOMEM;
-	}
-
-	list->hash.key = list->file_offset_node->start;
-	if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) {
-		DRM_ERROR("Failed to add to map hash\n");
-		drm_mm_put_block(list->file_offset_node);
-		kfree(list->map);
-		return -ENOMEM;
-	}
-
-	priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT;
-
-	return 0;
-}
-
 int
 kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
 			unsigned long *len)
@@ -483,9 +393,6 @@
 			priv->bufs[priv->active].offset;
 
 		*len = priv->memdesc.size;
-
-		kgsl_gem_mem_flush(&priv->memdesc,
-				   priv->type, DRM_KGSL_GEM_CACHE_OP_TO_DEV);
 	} else {
 		*start = 0;
 		*len = 0;
@@ -516,10 +423,7 @@
 	priv->active = 0;
 	priv->bound = 0;
 
-	/* To preserve backwards compatability, the default memory source
-	   is EBI */
-
-	priv->type = DRM_KGSL_GEM_TYPE_PMEM | DRM_KGSL_GEM_PMEM_EBI;
+	priv->type = DRM_KGSL_GEM_TYPE_KMEM;
 
 	ret = drm_gem_handle_create(file_priv, obj, handle);
 
@@ -655,10 +559,10 @@
 
 	if (TYPE_IS_FD(priv->type))
 		ret = -EINVAL;
-	else {
+	else if (TYPE_IS_PMEM(priv->type) || TYPE_IS_MEM(priv->type)) {
 		if (priv->ion_handle) {
 			args->ion_fd = ion_share_dma_buf(
-			kgsl_drm_ion_phys_client, priv->ion_handle);
+				kgsl_drm_ion_client, priv->ion_handle);
 		} else {
 			DRM_ERROR("GEM object has no ion memory allocated.\n");
 			ret = -EINVAL;
@@ -770,13 +674,9 @@
 
 	if (ret) {
 		DRM_ERROR("Unable to allocate object memory\n");
-	} else if (!priv->mmap_offset) {
-		ret = kgsl_gem_create_mmap_offset(obj);
-		if (ret)
-			DRM_ERROR("Unable to create a mmap offset\n");
 	}
 
-	args->offset = priv->mmap_offset;
+	args->offset = 0;
 
 	drm_gem_object_unreference(obj);
 	mutex_unlock(&dev->struct_mutex);
@@ -788,33 +688,7 @@
 kgsl_gem_mmap_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
-	struct drm_kgsl_gem_mmap *args = data;
-	struct drm_gem_object *obj;
-	unsigned long addr;
-
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-
-	if (obj == NULL) {
-		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
-		return -EBADF;
-	}
-
-	down_write(&current->mm->mmap_sem);
-
-	addr = do_mmap(obj->filp, 0, args->size,
-		       PROT_READ | PROT_WRITE, MAP_SHARED,
-		       args->offset);
-
-	up_write(&current->mm->mmap_sem);
-
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
-
-	if (IS_ERR((void *) addr))
-		return addr;
-
-	args->hostptr = (uint32_t) addr;
+	/* Ion is used for mmap at this time */
 	return 0;
 }
 
@@ -847,18 +721,6 @@
 		return ret;
 	}
 
-	if (priv->mmap_offset == 0) {
-		ret = kgsl_gem_create_mmap_offset(obj);
-		if (ret) {
-			drm_gem_object_unreference(obj);
-			mutex_unlock(&dev->struct_mutex);
-			return ret;
-		}
-	}
-
-	args->offset = priv->mmap_offset;
-	args->phys = priv->memdesc.physaddr;
-
 	drm_gem_object_unreference(obj);
 	mutex_unlock(&dev->struct_mutex);
 
@@ -1042,122 +904,6 @@
 	}
 }
 
-static struct vm_operations_struct kgsl_gem_kmem_vm_ops = {
-	.fault = kgsl_gem_kmem_fault,
-	.open = drm_gem_vm_open,
-	.close = drm_gem_vm_close,
-};
-
-static struct vm_operations_struct kgsl_gem_phys_vm_ops = {
-	.fault = kgsl_gem_phys_fault,
-	.open = drm_gem_vm_open,
-	.close = drm_gem_vm_close,
-};
-
-/* This is a clone of the standard drm_gem_mmap function modified to allow
-   us to properly map KMEM regions as well as the PMEM regions */
-
-int msm_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	struct drm_file *priv = filp->private_data;
-	struct drm_device *dev = priv->minor->dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_local_map *map = NULL;
-	struct drm_gem_object *obj;
-	struct drm_hash_item *hash;
-	struct drm_kgsl_gem_object *gpriv;
-	int ret = 0;
-
-	mutex_lock(&dev->struct_mutex);
-
-	if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) {
-		mutex_unlock(&dev->struct_mutex);
-		return drm_mmap(filp, vma);
-	}
-
-	map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
-	if (!map ||
-	    ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
-		ret =  -EPERM;
-		goto out_unlock;
-	}
-
-	/* Check for valid size. */
-	if (map->size < vma->vm_end - vma->vm_start) {
-		ret = -EINVAL;
-		goto out_unlock;
-	}
-
-	obj = map->handle;
-
-	gpriv = obj->driver_private;
-
-	/* VM_PFNMAP is only for memory that doesn't use struct page
-	 * in other words, not "normal" memory.  If you try to use it
-	 * with "normal" memory then the mappings don't get flushed. */
-
-	if (TYPE_IS_MEM(gpriv->type)) {
-		vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
-		vma->vm_ops = &kgsl_gem_kmem_vm_ops;
-	} else {
-		vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP |
-			VM_DONTEXPAND;
-		vma->vm_ops = &kgsl_gem_phys_vm_ops;
-	}
-
-	vma->vm_private_data = map->handle;
-
-
-	/* Take care of requested caching policy */
-	if (gpriv->type == DRM_KGSL_GEM_TYPE_KMEM ||
-	    gpriv->type & DRM_KGSL_GEM_CACHE_MASK) {
-		if (gpriv->type & DRM_KGSL_GEM_CACHE_WBACKWA)
-			vma->vm_page_prot =
-			pgprot_writebackwacache(vma->vm_page_prot);
-		else if (gpriv->type & DRM_KGSL_GEM_CACHE_WBACK)
-				vma->vm_page_prot =
-				pgprot_writebackcache(vma->vm_page_prot);
-		else if (gpriv->type & DRM_KGSL_GEM_CACHE_WTHROUGH)
-				vma->vm_page_prot =
-				pgprot_writethroughcache(vma->vm_page_prot);
-		else
-			vma->vm_page_prot =
-			pgprot_writecombine(vma->vm_page_prot);
-	} else {
-		if (gpriv->type == DRM_KGSL_GEM_TYPE_KMEM_NOCACHE)
-			vma->vm_page_prot =
-			pgprot_noncached(vma->vm_page_prot);
-		else
-			/* default pmem is WC */
-			vma->vm_page_prot =
-			pgprot_writecombine(vma->vm_page_prot);
-	}
-
-	/* flush out existing KMEM cached mappings if new ones are
-	 * of uncached type */
-	if (IS_MEM_UNCACHED(gpriv->type))
-		kgsl_cache_range_op(&gpriv->memdesc,
-				    KGSL_CACHE_OP_FLUSH);
-
-	/* Add the other memory types here */
-
-	/* Take a ref for this mapping of the object, so that the fault
-	 * handler can dereference the mmap offset's pointer to the object.
-	 * This reference is cleaned up by the corresponding vm_close
-	 * (which should happen whether the vma was created by this call, or
-	 * by a vm_open due to mremap or partial unmap or whatever).
-	 */
-	drm_gem_object_reference(obj);
-
-	vma->vm_file = filp;	/* Needed for drm_vm_open() */
-	drm_vm_open_locked(vma);
-
-out_unlock:
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-}
-
 void
 cleanup_fence(struct drm_kgsl_gem_object_fence *fence, int check_waiting)
 {
@@ -1538,19 +1284,13 @@
 	.open = drm_open,
 	.release = drm_release,
 	.unlocked_ioctl = drm_ioctl,
-	.mmap = msm_drm_gem_mmap,
+	.mmap = drm_gem_mmap,
 	.poll = drm_poll,
 	.fasync = drm_fasync,
 };
 
 static struct drm_driver driver = {
 	.driver_features = DRIVER_GEM,
-	.load = kgsl_drm_load,
-	.unload = kgsl_drm_unload,
-	.preclose = kgsl_drm_preclose,
-	.suspend = kgsl_drm_suspend,
-	.resume = kgsl_drm_resume,
-	.reclaim_buffers = drm_core_reclaim_buffers,
 	.gem_init_object = kgsl_gem_init_object,
 	.gem_free_object = kgsl_gem_free_object,
 	.ioctls = kgsl_drm_ioctls,
@@ -1584,9 +1324,9 @@
 	}
 
 	/* Create ION Client */
-	kgsl_drm_ion_phys_client = msm_ion_client_create(
-			ION_HEAP_CARVEOUT_MASK, "kgsl_drm");
-	if (!kgsl_drm_ion_phys_client) {
+	kgsl_drm_ion_client = msm_ion_client_create(
+			0xffffffff, "kgsl_drm");
+	if (!kgsl_drm_ion_client) {
 		DRM_ERROR("Unable to create ION client\n");
 		return -ENOMEM;
 	}
@@ -1598,9 +1338,9 @@
 {
 	kgsl_drm_inited = DRM_KGSL_NOT_INITED;
 
-	if (kgsl_drm_ion_phys_client)
-		ion_client_destroy(kgsl_drm_ion_phys_client);
-	kgsl_drm_ion_phys_client = NULL;
+	if (kgsl_drm_ion_client)
+		ion_client_destroy(kgsl_drm_ion_client);
+	kgsl_drm_ion_client = NULL;
 
 	drm_platform_exit(&driver, driver.kdriver.platform_device);
 }
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 3ea8f4b..be9b5eb 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -63,10 +63,15 @@
 	}
 	cur_ts = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED);
 
-	/* Check to see if the requested timestamp has already fired */
+	/*
+	 * Check to see if the requested timestamp has already fired.  If it
+	 * did do the callback right away.  Make sure to send the timestamp that
+	 * the event expected instead of the current timestamp because sometimes
+	 * the event handlers can get confused.
+	 */
 
 	if (timestamp_cmp(cur_ts, ts) >= 0) {
-		cb(device, priv, id, cur_ts);
+		cb(device, priv, id, ts);
 		return 0;
 	}
 
@@ -127,7 +132,11 @@
 		 * Currently, events are used for lock and memory
 		 * management, so if the process is dying the right
 		 * thing to do is release or free.
+		 *
+		 * Send the current timestamp so the event knows how far the
+		 * system got before the event was canceled
 		 */
+
 		if (event->func)
 			event->func(device, event->priv, id, cur);
 
@@ -162,7 +171,9 @@
 		 * "cancel" the events by calling their callback.
 		 * Currently, events are used for lock and memory
 		 * management, so if the process is dying the right
-		 * thing to do is release or free.
+		 * thing to do is release or free. Send the current timestamp so
+		 * the callback knows how far the GPU made it before things went
+		 * explosion
 		 */
 		if (event->func)
 			event->func(device, event->priv, KGSL_MEMSTORE_GLOBAL,
@@ -189,8 +200,15 @@
 
 		id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL;
 
+		/*
+		 * Send the timestamp of the expired event, not the current
+		 * timestamp.  This prevents the event handlers from getting
+		 * confused if they don't bother comparing the current timetamp
+		 * to the timestamp they wanted
+		 */
+
 		if (event->func)
-			event->func(device, event->priv, id, timestamp);
+			event->func(device, event->priv, id, event->timestamp);
 
 		if (event->context)
 			kgsl_context_put(event->context);
@@ -200,27 +218,43 @@
 	}
 }
 
-static inline void _mark_next_event(struct kgsl_device *device,
+static inline int _mark_next_event(struct kgsl_device *device,
 		struct list_head *head)
 {
 	struct kgsl_event *event;
 
 	if (!list_empty(head)) {
 		event = list_first_entry(head, struct kgsl_event, list);
-		device->ftbl->next_event(device, event);
+
+		/*
+		 * Next event will return 0 if the event was marked or 1 if the
+		 * timestamp on the event has passed - return that up a layer
+		 */
+
+		return device->ftbl->next_event(device, event);
 	}
+
+	return 0;
 }
 
 static int kgsl_process_context_events(struct kgsl_device *device,
 		struct kgsl_context *context)
 {
-	unsigned int timestamp = kgsl_readtimestamp(device, context,
-		KGSL_TIMESTAMP_RETIRED);
+	while (1) {
+		unsigned int timestamp = kgsl_readtimestamp(device, context,
+			KGSL_TIMESTAMP_RETIRED);
 
-	_process_event_list(device, &context->events, timestamp);
+		_process_event_list(device, &context->events, timestamp);
 
-	/* Mark the next pending event on the list to fire an interrupt */
-	_mark_next_event(device, &context->events);
+		/*
+		 * _mark_next event will return 1 as long as the next event
+		 * timestamp has expired - this is to cope with an unavoidable
+		 * race condition with the GPU that is still processing events.
+		 */
+
+		if (!_mark_next_event(device, &context->events))
+			break;
+	}
 
 	/*
 	 * Return 0 if the list is empty so the calling function can remove the
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index abf125f..df190ff 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -565,8 +565,8 @@
 				sizeof(struct kgsl_iommu_pt));
 		return NULL;
 	}
-	/* L2 redirect is not stable on IOMMU v2 */
-	if (msm_soc_version_supports_iommu_v1())
+	/* L2 redirect is not stable on IOMMU v1 */
+	if (msm_soc_version_supports_iommu_v0())
 		iommu_pt->domain = iommu_domain_alloc(&platform_bus_type,
 					MSM_IOMMU_DOMAIN_PT_CACHEABLE);
 	else
@@ -749,7 +749,7 @@
 	uint32_t lock_gpu_addr = 0;
 
 	if (KGSL_DEVICE_3D0 != mmu->device->id ||
-		!msm_soc_version_supports_iommu_v1() ||
+		!msm_soc_version_supports_iommu_v0() ||
 		!kgsl_mmu_is_perprocess() ||
 		iommu->sync_lock_vars)
 		return 0;
@@ -790,7 +790,7 @@
 	uint32_t lock_phy_addr = 0;
 	uint32_t page_offset = 0;
 
-	if (!msm_soc_version_supports_iommu_v1() ||
+	if (!msm_soc_version_supports_iommu_v0() ||
 		!kgsl_mmu_is_perprocess())
 		return status;
 
@@ -1113,7 +1113,7 @@
 	int i = 0;
 	struct kgsl_iommu *iommu = mmu->priv;
 
-	if (!msm_soc_version_supports_iommu_v1())
+	if (!msm_soc_version_supports_iommu_v0())
 		return 0;
 
 	for (i = 0; i < iommu->unit_count; i++) {
@@ -1194,7 +1194,7 @@
 	iommu->iommu_reg_list = kgsl_iommuv1_reg;
 	iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V1;
 
-	if (msm_soc_version_supports_iommu_v1()) {
+	if (msm_soc_version_supports_iommu_v0()) {
 		iommu->iommu_reg_list = kgsl_iommuv1_reg;
 		iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V1;
 	} else {
@@ -1242,7 +1242,7 @@
 
 	/* If chip is not 8960 then we use the 2nd context bank for pagetable
 	 * switching on the 3D side for which a separate table is allocated */
-	if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v1()) {
+	if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v0()) {
 		mmu->priv_bank_table =
 			kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME);
 		if (mmu->priv_bank_table == NULL) {
@@ -1644,15 +1644,15 @@
 	pt_base &= (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask <<
 			iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift);
 
-	/* For v1 SMMU GPU needs to be idle for tlb invalidate as well */
-	if (msm_soc_version_supports_iommu_v1())
+	/* For v0 SMMU GPU needs to be idle for tlb invalidate as well */
+	if (msm_soc_version_supports_iommu_v0())
 		kgsl_idle(mmu->device);
 
 	/* Acquire GPU-CPU sync Lock here */
 	msm_iommu_lock();
 
 	if (flags & KGSL_MMUFLAGS_PTUPDATE) {
-		if (!msm_soc_version_supports_iommu_v1())
+		if (!msm_soc_version_supports_iommu_v0())
 			kgsl_idle(mmu->device);
 		for (i = 0; i < iommu->unit_count; i++) {
 			/* get the lsb value which should not change when
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 9141af4..2b33baf 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -341,9 +341,9 @@
 static inline int kgsl_mmu_is_perprocess(void)
 {
 
-	/* We presently do not support per-process for IOMMU-v2 */
+	/* We presently do not support per-process for IOMMU-v1 */
 	return (kgsl_mmu_get_mmutype() != KGSL_MMU_TYPE_IOMMU)
-		|| msm_soc_version_supports_iommu_v1();
+		|| msm_soc_version_supports_iommu_v0();
 }
 #else
 static inline int kgsl_mmu_is_perprocess(void)
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 7016931..2945b7b 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -515,7 +515,6 @@
 	struct kgsl_device *device = kgsl_device_from_dev(dev);
 	struct kgsl_pwrctrl *pwr;
 	const long div = 1000/HZ;
-	static unsigned int org_interval_timeout = 1;
 	int rc;
 
 	if (device == NULL)
@@ -528,15 +527,11 @@
 	if (rc)
 		return rc;
 
-	if (org_interval_timeout == 1)
-		org_interval_timeout = pwr->interval_timeout;
-
 	mutex_lock(&device->mutex);
 
 	/* Let the timeout be requested in ms, but convert to jiffies. */
 	val /= div;
-	if (val >= org_interval_timeout)
-		pwr->interval_timeout = val;
+	pwr->interval_timeout = val;
 
 	mutex_unlock(&device->mutex);
 
@@ -548,10 +543,12 @@
 					char *buf)
 {
 	struct kgsl_device *device = kgsl_device_from_dev(dev);
+	int mul = 1000/HZ;
 	if (device == NULL)
 		return 0;
+	/* Show the idle_timeout converted to msec */
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-		device->pwrctrl.interval_timeout);
+		device->pwrctrl.interval_timeout * mul);
 }
 
 static int kgsl_pwrctrl_pmqos_latency_store(struct device *dev,
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index ab2fd75..b97004a 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -549,6 +549,7 @@
 	pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
 	void *ptr;
 	unsigned int align;
+	int step = ((VMALLOC_END - VMALLOC_START)/8) >> PAGE_SHIFT;
 
 	align = (memdesc->flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT;
 
@@ -676,30 +677,36 @@
 	 * zeroed and unmaped each individual page, and then we had to turn
 	 * around and call flush_dcache_page() on that page to clear the caches.
 	 * This was killing us for performance. Instead, we found it is much
-	 * faster to allocate the pages without GFP_ZERO, map the entire range,
-	 * memset it, flush the range and then unmap - this results in a factor
-	 * of 4 improvement for speed for large buffers.  There is a small
-	 * increase in speed for small buffers, but only on the order of a few
-	 * microseconds at best.  The only downside is that there needs to be
-	 * enough temporary space in vmalloc to accomodate the map. This
-	 * shouldn't be a problem, but if it happens, fall back to a much slower
-	 * path
+	 * faster to allocate the pages without GFP_ZERO, map a chunk of the
+	 * range ('step' pages), memset it, flush it and then unmap
+	 * - this results in a factor of 4 improvement for speed for large
+	 * buffers. There is a small decrease in speed for small buffers,
+	 * but only on the order of a few microseconds at best. The 'step'
+	 * size is based on a guess at the amount of free vmalloc space, but
+	 * will scale down if there's not enough free space.
 	 */
+	for (j = 0; j < pcount; j += step) {
+		step = min(step, pcount - j);
 
-	ptr = vmap(pages, pcount, VM_IOREMAP, page_prot);
+		ptr = vmap(&pages[j], step, VM_IOREMAP, page_prot);
 
-	if (ptr != NULL) {
-		memset(ptr, 0, memdesc->size);
-		dmac_flush_range(ptr, ptr + memdesc->size);
-		vunmap(ptr);
-	} else {
-		/* Very, very, very slow path */
+		if (ptr != NULL) {
+			memset(ptr, 0, step * PAGE_SIZE);
+			dmac_flush_range(ptr, ptr + step * PAGE_SIZE);
+			vunmap(ptr);
+		} else {
+			int k;
+			/* Very, very, very slow path */
 
-		for (j = 0; j < pcount; j++) {
-			ptr = kmap_atomic(pages[j]);
-			memset(ptr, 0, PAGE_SIZE);
-			dmac_flush_range(ptr, ptr + PAGE_SIZE);
-			kunmap_atomic(ptr);
+			for (k = j; k < j + step; k++) {
+				ptr = kmap_atomic(pages[k]);
+				memset(ptr, 0, PAGE_SIZE);
+				dmac_flush_range(ptr, ptr + PAGE_SIZE);
+				kunmap_atomic(ptr);
+			}
+			/* scale down the step size to avoid this path */
+			if (step > 1)
+				step >>= 1;
 		}
 	}
 
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index a2dfe3b..98edb83 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -179,6 +179,7 @@
 }
 
 static const struct sync_timeline_ops kgsl_sync_timeline_ops = {
+	.driver_name = "kgsl-timeline",
 	.dup = kgsl_sync_pt_dup,
 	.has_signaled = kgsl_sync_pt_has_signaled,
 	.compare = kgsl_sync_pt_compare,
@@ -204,7 +205,9 @@
 {
 	struct kgsl_sync_timeline *ktimeline =
 		(struct kgsl_sync_timeline *) timeline;
-	ktimeline->last_timestamp = timestamp;
+
+	if (timestamp_cmp(timestamp, ktimeline->last_timestamp > 0))
+		ktimeline->last_timestamp = timestamp;
 	sync_timeline_signal(timeline);
 }
 
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 94bdd51..f7818bb 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -494,6 +494,40 @@
 	)
 );
 
+TRACE_EVENT(kgsl_mem_sync_cache,
+
+	TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned int op),
+
+	TP_ARGS(mem_entry, op),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, gpuaddr)
+		__field(unsigned int, size)
+		__array(char, usage, 16)
+		__field(unsigned int, tgid)
+		__field(unsigned int, id)
+		__field(unsigned int, op)
+	),
+
+	TP_fast_assign(
+		__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+		__entry->size = mem_entry->memdesc.size;
+		__entry->tgid = mem_entry->priv->pid;
+		__entry->id = mem_entry->id;
+		kgsl_get_memory_usage(__entry->usage, sizeof(__entry->usage),
+				     mem_entry->memdesc.flags);
+		__entry->op = op;
+	),
+
+	TP_printk(
+		"gpuaddr=0x%08x size=%d tgid=%d usage=%s id=%d op=%c%c",
+		__entry->gpuaddr, __entry->size, __entry->tgid, __entry->usage,
+		__entry->id,
+		(__entry->op & KGSL_GPUMEM_CACHE_CLEAN) ? 'c' : '.',
+		(__entry->op & KGSL_GPUMEM_CACHE_INV) ? 'i' : '.'
+	)
+);
+
 DECLARE_EVENT_CLASS(kgsl_mem_timestamp_template,
 
 	TP_PROTO(struct kgsl_device *device, struct kgsl_mem_entry *mem_entry,
@@ -628,7 +662,7 @@
 	),
 
 	TP_printk(
-		"d_name=%s page=0x%08x pt=%d op=%s\n",
+		"d_name=%s page=0x%08x pt=%d op=%s",
 		__get_str(device_name), __entry->page, __entry->pt,
 		__get_str(op)
 	)
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index bde18d4..ecd4bbb 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -582,7 +582,7 @@
 {
 	struct qpnp_vadc_linear_graph usb_param;
 
-	qpnp_get_vadc_gain_and_offset(&usb_param, CALIB_ABSOLUTE);
+	qpnp_get_vadc_gain_and_offset(&usb_param, CALIB_RATIOMETRIC);
 
 	*low_threshold = param->low_thr * usb_param.dy;
 	do_div(*low_threshold, usb_param.adc_vref);
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index b562350..717f763 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1305,6 +1305,7 @@
 		"QUP I2C adapter",
 		sizeof(dev->adapter.name));
 	dev->adapter.nr = pdev->id;
+	dev->adapter.dev.parent = &pdev->dev;
 	if (pdata->msm_i2c_config_gpio)
 		pdata->msm_i2c_config_gpio(dev->adapter.nr, 1);
 
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index a867fc9..1d56a0a 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -27,7 +27,12 @@
 #include <linux/regulator/consumer.h>
 #include <linux/string.h>
 #include <linux/of_gpio.h>
-#if defined(CONFIG_HAS_EARLYSUSPEND)
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
 #include <linux/earlysuspend.h>
 /* Early-suspend level */
 #define MXT_SUSPEND_LEVEL 1
@@ -356,8 +361,9 @@
 	struct regulator *vcc_ana;
 	struct regulator *vcc_dig;
 	struct regulator *vcc_i2c;
-	struct mxt_address_pair addr_pair;
-#if defined(CONFIG_HAS_EARLYSUSPEND)
+#if defined(CONFIG_FB)
+	struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
 	struct early_suspend early_suspend;
 #endif
 
@@ -471,27 +477,9 @@
 	dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
 }
 
-static int mxt_lookup_bootloader_address(struct mxt_data *data)
-{
-	int i;
-
-	for (i = 0; mxt_slave_addresses[i].application != 0;  i++) {
-		if (mxt_slave_addresses[i].application ==
-				data->client->addr) {
-			data->addr_pair.bootloader =
-				mxt_slave_addresses[i].bootloader;
-			return 0;
-		}
-	}
-
-	dev_err(&data->client->dev, "Address 0x%02x not found in address table",
-							data->client->addr);
-	return -EINVAL;
-
-};
-
 static int mxt_switch_to_bootloader_address(struct mxt_data *data)
 {
+	int i;
 	struct i2c_client *client = data->client;
 
 	if (data->state == BOOTLOADER) {
@@ -499,16 +487,27 @@
 		return -EINVAL;
 	}
 
-	dev_info(&client->dev, "Changing to bootloader address: 0x%02x -> 0x%02x",
-			client->addr, data->addr_pair.bootloader);
+	for (i = 0; mxt_slave_addresses[i].application != 0;  i++) {
+		if (mxt_slave_addresses[i].application == client->addr) {
+			dev_info(&client->dev, "Changing to bootloader address: "
+				"%02x -> %02x",
+				client->addr,
+				mxt_slave_addresses[i].bootloader);
 
-	client->addr = data->addr_pair.bootloader;
-	data->state = BOOTLOADER;
-	return 0;
+			client->addr = mxt_slave_addresses[i].bootloader;
+			data->state = BOOTLOADER;
+			return 0;
+		}
+	}
+
+	dev_err(&client->dev, "Address 0x%02x not found in address table",
+								client->addr);
+	return -EINVAL;
 }
 
 static int mxt_switch_to_appmode_address(struct mxt_data *data)
 {
+	int i;
 	struct i2c_client *client = data->client;
 
 	if (data->state == APPMODE) {
@@ -516,13 +515,23 @@
 		return -EINVAL;
 	}
 
-	dev_info(&client->dev, "Changing to application mode address: " \
-			"0x%02x -> 0x%02x", client->addr,
-			data->addr_pair.application);
+	for (i = 0; mxt_slave_addresses[i].application != 0;  i++) {
+		if (mxt_slave_addresses[i].bootloader == client->addr) {
+			dev_info(&client->dev,
+				"Changing to application mode address: "
+							"0x%02x -> 0x%02x",
+				client->addr,
+				mxt_slave_addresses[i].application);
 
-	client->addr = data->addr_pair.application;
-	data->state = APPMODE;
-	return 0;
+			client->addr = mxt_slave_addresses[i].application;
+			data->state = APPMODE;
+			return 0;
+		}
+	}
+
+	dev_err(&client->dev, "Address 0x%02x not found in address table",
+								client->addr);
+	return -EINVAL;
 }
 
 static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
@@ -1653,11 +1662,9 @@
 	switch (data->info.family_id) {
 	case MXT224_ID:
 	case MXT224E_ID:
-	case MXT336S_ID:
 		max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
 		break;
 	case MXT1386_ID:
-	case MXT1664S_ID:
 		max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
 		break;
 	default:
@@ -2330,24 +2337,8 @@
 	return 0;
 }
 
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-static void mxt_early_suspend(struct early_suspend *h)
-{
-	struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
-
-	mxt_suspend(&data->client->dev);
-}
-
-static void mxt_late_resume(struct early_suspend *h)
-{
-	struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
-
-	mxt_resume(&data->client->dev);
-}
-#endif
-
 static const struct dev_pm_ops mxt_pm_ops = {
-#ifndef CONFIG_HAS_EARLYSUSPEND
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
 	.suspend	= mxt_suspend,
 	.resume		= mxt_resume,
 #endif
@@ -2564,12 +2555,6 @@
 		return -ENOMEM;
 	}
 
-	rc = of_property_read_u32(np, "atmel,bl-addr", &temp_val);
-	if (rc && (rc != -EINVAL))
-		dev_err(dev, "Unable to read bootloader address\n");
-	else if (rc != -EINVAL)
-		pdata->bl_addr = (u8) temp_val;
-
 	pdata->config_array  = info;
 
 	for_each_child_of_node(np, temp) {
@@ -2608,7 +2593,7 @@
 		} else
 			info->build = (u8) temp_val;
 
-		rc = of_property_read_u32(temp,
+		info->bootldr_id = of_property_read_u32(temp,
 					"atmel,bootldr-id", &temp_val);
 		if (rc) {
 			dev_err(dev, "Unable to read bootldr-id\n");
@@ -2633,6 +2618,43 @@
 }
 #endif
 
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+				 unsigned long event, void *data)
+{
+	struct fb_event *evdata = data;
+	int *blank;
+	struct mxt_data *mxt_dev_data =
+		container_of(self, struct mxt_data, fb_notif);
+
+	if (evdata && evdata->data && event == FB_EVENT_BLANK && mxt_dev_data &&
+			mxt_dev_data->client) {
+		blank = evdata->data;
+		if (*blank == FB_BLANK_UNBLANK)
+			mxt_resume(&mxt_dev_data->client->dev);
+		else if (*blank == FB_BLANK_POWERDOWN)
+			mxt_suspend(&mxt_dev_data->client->dev);
+	}
+
+	return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void mxt_early_suspend(struct early_suspend *h)
+{
+	struct mxt_data *data = container_of(h, struct mxt_data,
+						early_suspend);
+	mxt_suspend(&data->client->dev);
+}
+
+static void mxt_late_resume(struct early_suspend *h)
+{
+	struct mxt_data *data = container_of(h, struct mxt_data,
+						early_suspend);
+	mxt_resume(&data->client->dev);
+}
+
+#endif
+
 static int __devinit mxt_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
@@ -2773,13 +2795,6 @@
 
 	mxt_power_on_delay(data);
 
-	data->addr_pair.application = data->client->addr;
-
-	if (pdata->bl_addr)
-		data->addr_pair.bootloader = pdata->bl_addr;
-	else
-		mxt_lookup_bootloader_address(data);
-
 	error = mxt_initialize(data);
 	if (error)
 		goto err_reset_gpio_req;
@@ -2807,7 +2822,15 @@
 	if (error)
 		goto err_unregister_device;
 
-#if defined(CONFIG_HAS_EARLYSUSPEND)
+#if defined(CONFIG_FB)
+	data->fb_notif.notifier_call = fb_notifier_callback;
+
+	error = fb_register_client(&data->fb_notif);
+
+	if (error)
+		dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
+			error);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
 	data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
 						MXT_SUSPEND_LEVEL;
 	data->early_suspend.suspend = mxt_early_suspend;
@@ -2855,7 +2878,10 @@
 	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
 	free_irq(data->irq, data);
 	input_unregister_device(data->input_dev);
-#if defined(CONFIG_HAS_EARLYSUSPEND)
+#if defined(CONFIG_FB)
+	if (fb_unregister_client(&data->fb_notif))
+		dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
 	unregister_early_suspend(&data->early_suspend);
 #endif
 
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 4f54a0c..b126aa2 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -16,7 +16,7 @@
 # MSM IOMMU support
 config MSM_IOMMU
 	bool "MSM IOMMU Support"
-	depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8974 || ARCH_MPQ8092 || ARCH_MSM8910 || ARCH_MSM8226
+	depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8974 || ARCH_MPQ8092 || ARCH_MSM8610 || ARCH_MSM8226
 	select IOMMU_API
 	help
 	  Support for the IOMMUs found on certain Qualcomm SOCs.
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 5db4258..112b62b 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,7 +1,7 @@
 obj-$(CONFIG_IOMMU_API) += iommu.o
-obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
+obj-$(CONFIG_MSM_IOMMU) += msm_iommu-v0.o msm_iommu_dev-v0.o
 ifdef CONFIG_OF
-obj-$(CONFIG_MSM_IOMMU) += msm_iommu-v2.o msm_iommu_dev-v2.o msm_iommu_pagetable.o msm_iommu_sec.o
+obj-$(CONFIG_MSM_IOMMU) += msm_iommu-v1.o msm_iommu_dev-v1.o msm_iommu_pagetable.o msm_iommu_sec.o
 endif
 obj-$(CONFIG_MSM_IOMMU_PMON) += msm_iommu_perfmon.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu-v0.c
similarity index 99%
rename from drivers/iommu/msm_iommu.c
rename to drivers/iommu/msm_iommu-v0.c
index 38e6fb7..28f1516 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,7 +27,7 @@
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
 
-#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu_hw-v0.h>
 #include <mach/iommu.h>
 #include <mach/msm_smsm.h>
 
@@ -1355,7 +1355,7 @@
 
 static int __init msm_iommu_init(void)
 {
-	if (!msm_soc_version_supports_iommu_v1())
+	if (!msm_soc_version_supports_iommu_v0())
 		return -ENODEV;
 
 	msm_iommu_lock_initialize();
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v1.c
similarity index 95%
rename from drivers/iommu/msm_iommu-v2.c
rename to drivers/iommu/msm_iommu-v1.c
index 687269e..88e3fea 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -28,7 +28,7 @@
 #include <linux/regulator/consumer.h>
 #include <asm/sizes.h>
 
-#include <mach/iommu_hw-v2.h>
+#include <mach/iommu_hw-v1.h>
 #include <mach/iommu.h>
 #include <mach/iommu_perfmon.h>
 #include "msm_iommu_pagetable.h"
@@ -92,6 +92,8 @@
 		value = readl_relaxed(drvdata->clk_reg_virt);
 		value &= ~0x1;
 		writel_relaxed(value, drvdata->clk_reg_virt);
+		/* Ensure clock is on before continuing */
+		mb();
 	}
 fail:
 	return ret;
@@ -152,6 +154,36 @@
 	.iommu_lock_release = _iommu_lock_release,
 };
 
+void iommu_halt(const struct msm_iommu_drvdata *iommu_drvdata)
+{
+	if (iommu_drvdata->halt_enabled) {
+		SET_MICRO_MMU_CTRL_HALT_REQ(iommu_drvdata->base, 1);
+
+		while (GET_MICRO_MMU_CTRL_IDLE(iommu_drvdata->base) == 0)
+			cpu_relax();
+		/* Ensure device is idle before continuing */
+		mb();
+	}
+}
+
+void iommu_resume(const struct msm_iommu_drvdata *iommu_drvdata)
+{
+	if (iommu_drvdata->halt_enabled) {
+		/*
+		 * Ensure transactions have completed before releasing
+		 * the halt
+		 */
+		mb();
+		SET_MICRO_MMU_CTRL_HALT_REQ(iommu_drvdata->base, 0);
+		/*
+		 * Ensure write is complete before continuing to ensure
+		 * we don't turn off clocks while transaction is still
+		 * pending.
+		 */
+		mb();
+	}
+}
+
 static void __sync_tlb(void __iomem *base, int ctx)
 {
 	SET_TLBSYNC(base, ctx, 0);
@@ -570,9 +602,12 @@
 		goto fail;
 	}
 
+
 	if (!msm_iommu_ctx_attached(dev->parent)) {
 		if (!is_secure) {
+			iommu_halt(iommu_drvdata);
 			__program_iommu(iommu_drvdata->base);
+			iommu_resume(iommu_drvdata);
 		} else {
 			ret = msm_iommu_sec_program_iommu(
 				iommu_drvdata->sec_id);
@@ -586,9 +621,13 @@
 					   iommu_drvdata->bfb_settings);
 	}
 
+	iommu_halt(iommu_drvdata);
+
 	__program_context(iommu_drvdata, ctx_drvdata, __pa(priv->pt.fl_table),
 			  priv->pt.redirect, is_secure);
 
+	iommu_resume(iommu_drvdata);
+
 	__disable_clocks(iommu_drvdata);
 
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
@@ -633,10 +672,14 @@
 	SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num, ctx_drvdata->asid);
 	ctx_drvdata->asid = -1;
 
+	iommu_halt(iommu_drvdata);
+
 	__reset_context(iommu_drvdata->base, ctx_drvdata->num);
 	if (!is_secure)
 		__release_smg(iommu_drvdata->base, ctx_drvdata->num);
 
+	iommu_resume(iommu_drvdata);
+
 	__disable_clocks(iommu_drvdata);
 
 	__disable_regulators(iommu_drvdata);
@@ -846,6 +889,8 @@
 		goto fail;
 	}
 
+	iommu_halt(drvdata);
+
 	fsr = GET_FSR(drvdata->base, ctx_drvdata->num);
 	if (fsr) {
 		if (!ctx_drvdata->attached_domain) {
@@ -870,6 +915,8 @@
 	} else
 		ret = IRQ_NONE;
 
+	iommu_resume(drvdata);
+
 	__disable_clocks(drvdata);
 fail:
 	mutex_unlock(&msm_iommu_lock);
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev-v0.c
similarity index 98%
rename from drivers/iommu/msm_iommu_dev.c
rename to drivers/iommu/msm_iommu_dev-v0.c
index 470d8ce..3a9cc23 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,7 +27,7 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 
-#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu_hw-v0.h>
 #include <mach/iommu.h>
 
 static DEFINE_MUTEX(iommu_list_lock);
@@ -549,13 +549,13 @@
 
 
 static struct of_device_id msm_iommu_match_table[] = {
-	{ .compatible = "qcom,msm-smmu-v1", },
+	{ .compatible = "qcom,msm-smmu-v0", },
 	{}
 };
 
 static struct platform_driver msm_iommu_driver = {
 	.driver = {
-		.name	= "msm_iommu",
+		.name	= "msm_iommu-v0",
 		.of_match_table = msm_iommu_match_table,
 	},
 	.probe		= msm_iommu_probe,
diff --git a/drivers/iommu/msm_iommu_dev-v2.c b/drivers/iommu/msm_iommu_dev-v1.c
similarity index 81%
rename from drivers/iommu/msm_iommu_dev-v2.c
rename to drivers/iommu/msm_iommu_dev-v1.c
index 4571595..ec761a9 100644
--- a/drivers/iommu/msm_iommu_dev-v2.c
+++ b/drivers/iommu/msm_iommu_dev-v1.c
@@ -25,7 +25,7 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 
-#include <mach/iommu_hw-v2.h>
+#include <mach/iommu_hw-v1.h>
 #include <mach/iommu.h>
 #include <mach/iommu_perfmon.h>
 
@@ -130,29 +130,76 @@
 		}
 	}
 
+	drvdata->halt_enabled = of_property_read_bool(pdev->dev.of_node,
+						      "qcom,iommu-enable-halt");
+
 	return 0;
 fail:
 	return ret;
 }
 
 static int msm_iommu_pmon_parse_dt(struct platform_device *pdev,
-					struct iommu_info *pmon_info)
+					struct iommu_pmon *pmon_info)
 {
 	int ret = 0;
 	int irq = platform_get_irq(pdev, 0);
+	unsigned int cls_prop_size;
 
 	if (irq > 0) {
-		pmon_info->evt_irq = platform_get_irq(pdev, 0);
+		pmon_info->iommu.evt_irq = platform_get_irq(pdev, 0);
+
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   "qcom,iommu-pmu-ngroups",
+					   &pmon_info->num_groups);
+		if (ret) {
+			pr_err("Error reading qcom,iommu-pmu-ngroups\n");
+			goto fail;
+		}
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   "qcom,iommu-pmu-ncounters",
+					   &pmon_info->num_counters);
+		if (ret) {
+			pr_err("Error reading qcom,iommu-pmu-ncounters\n");
+			goto fail;
+		}
+
+		if (!of_get_property(pdev->dev.of_node,
+				     "qcom,iommu-pmu-event-classes",
+				     &cls_prop_size)) {
+			pr_err("Error reading qcom,iommu-pmu-event-classes\n");
+			return -EINVAL;
+		}
+
+		pmon_info->event_cls_supported =
+			   devm_kzalloc(&pdev->dev, cls_prop_size, GFP_KERNEL);
+
+		if (!pmon_info->event_cls_supported) {
+			pr_err("Unable to get memory for event class array\n");
+			return -ENOMEM;
+		}
+
+		pmon_info->nevent_cls_supported = cls_prop_size / sizeof(u32);
+
+		ret = of_property_read_u32_array(pdev->dev.of_node,
+					"qcom,iommu-pmu-event-classes",
+					pmon_info->event_cls_supported,
+					pmon_info->nevent_cls_supported);
+		if (ret) {
+			pr_err("Error reading qcom,iommu-pmu-event-classes\n");
+			return ret;
+		}
 	} else {
-		pmon_info->evt_irq = -1;
+		pmon_info->iommu.evt_irq = -1;
 		ret = irq;
 	}
+
+fail:
 	return ret;
 }
 
 static int __devinit msm_iommu_probe(struct platform_device *pdev)
 {
-	struct iommu_info *pmon_info;
+	struct iommu_pmon *pmon_info;
 	struct msm_iommu_drvdata *drvdata;
 	struct resource *r;
 	int ret, needs_alt_core_clk;
@@ -221,9 +268,9 @@
 			msm_iommu_pm_free(&pdev->dev);
 			pr_info("%s: pmon not available.\n", drvdata->name);
 		} else {
-			pmon_info->base = drvdata->base;
-			pmon_info->ops = &iommu_access_ops;
-			pmon_info->iommu_name = drvdata->name;
+			pmon_info->iommu.base = drvdata->base;
+			pmon_info->iommu.ops = &iommu_access_ops;
+			pmon_info->iommu.iommu_name = drvdata->name;
 			ret = msm_iommu_pm_iommu_register(pmon_info);
 			if (ret) {
 				pr_err("%s iommu register fail\n",
@@ -231,7 +278,7 @@
 				msm_iommu_pm_free(&pdev->dev);
 			} else {
 				pr_debug("%s iommu registered for pmon\n",
-						pmon_info->iommu_name);
+						pmon_info->iommu.iommu_name);
 			}
 		}
 	}
@@ -263,15 +310,21 @@
 	int irq, ret;
 	u32 nsid;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq > 0) {
-		ret = request_threaded_irq(irq, NULL,
-				msm_iommu_fault_handler_v2,
-				IRQF_ONESHOT | IRQF_SHARED,
-				"msm_iommu_nonsecure_irq", pdev);
-		if (ret) {
-			pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-			return ret;
+	ctx_drvdata->secure_context = of_property_read_bool(pdev->dev.of_node,
+							"qcom,secure-context");
+
+	if (!ctx_drvdata->secure_context) {
+		irq = platform_get_irq(pdev, 0);
+		if (irq > 0) {
+			ret = request_threaded_irq(irq, NULL,
+					msm_iommu_fault_handler_v2,
+					IRQF_ONESHOT | IRQF_SHARED,
+					"msm_iommu_nonsecure_irq", pdev);
+			if (ret) {
+				pr_err("Request IRQ %d failed with ret=%d\n",
+					irq, ret);
+				return ret;
+			}
 		}
 	}
 
@@ -307,8 +360,6 @@
 	}
 	ctx_drvdata->nsid = nsid;
 
-	ctx_drvdata->secure_context = of_property_read_bool(pdev->dev.of_node,
-							"qcom,secure-context");
 	ctx_drvdata->asid = -1;
 	return 0;
 }
@@ -345,13 +396,13 @@
 }
 
 static struct of_device_id msm_iommu_match_table[] = {
-	{ .compatible = "qcom,msm-smmu-v2", },
+	{ .compatible = "qcom,msm-smmu-v1", },
 	{}
 };
 
 static struct platform_driver msm_iommu_driver = {
 	.driver = {
-		.name	= "msm_iommu_v2",
+		.name	= "msm_iommu_v1",
 		.of_match_table = msm_iommu_match_table,
 	},
 	.probe		= msm_iommu_probe,
@@ -365,7 +416,7 @@
 
 static struct platform_driver msm_iommu_ctx_driver = {
 	.driver = {
-		.name	= "msm_iommu_ctx_v2",
+		.name	= "msm_iommu_ctx_v1",
 		.of_match_table = msm_iommu_ctx_match_table,
 	},
 	.probe		= msm_iommu_ctx_probe,
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index 15302b1..97bd660 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
-#include <mach/iommu_hw-v2.h>
+#include <mach/iommu_hw-v1.h>
 #include <mach/iommu.h>
 #include <mach/iommu_perfmon.h>
 
@@ -70,9 +70,6 @@
 	{ 0x10, "access"           },
 	{ 0x11, "access_read"      },
 	{ 0x12, "access_write"     },
-};
-
-static struct event_class pmu_event_classes_impl_defined[] = {
 	{ 0x80, "full_misses"      },
 	{ 0x81, "partial_miss_1lbfb_hit" },
 	{ 0x82, "partial_miss_2lbfb_hit" },
@@ -90,22 +87,28 @@
 }
 
 static unsigned int iommu_pm_create_sup_cls_str(char **buf,
-						unsigned int event_cls)
+						struct iommu_pmon *pmon)
 {
-	unsigned long buf_size = (ARRAY_SIZE(pmu_event_classes) +
-			ARRAY_SIZE(pmu_event_classes_impl_defined)) *
-			MAX_EVEN_CLASS_NAME_LEN;
+	unsigned long buf_size = ARRAY_SIZE(pmu_event_classes) *
+				 MAX_EVEN_CLASS_NAME_LEN;
 	unsigned int pos = 0;
+	unsigned int nevent_cls = pmon->nevent_cls_supported;
 
 	*buf = kzalloc(buf_size, GFP_KERNEL);
 	if (*buf) {
+		unsigned int j;
 		int i;
 		struct event_class *ptr;
 		size_t array_len = ARRAY_SIZE(pmu_event_classes);
 		ptr = pmu_event_classes;
 
-		for (i = 0; i < array_len; ++i) {
-			if ((1 << ptr[i].event_number) & event_cls) {
+		for (j = 0; j < nevent_cls; ++j) {
+			for (i = 0; i < array_len; ++i) {
+
+				if (ptr[i].event_number !=
+						pmon->event_cls_supported[j])
+					continue;
+
 				if (pos < buf_size) {
 					pos += snprintf(&(*buf)[pos],
 							buf_size-pos,
@@ -113,25 +116,7 @@
 							ptr[i].event_number,
 							ptr[i].desc);
 				}
-
-			}
-		}
-
-		/*
-		 * No way to read a register to check if impl. defined
-		 * classes are supported or not so we just assume all of them
-		 * are
-		 */
-		array_len = ARRAY_SIZE(pmu_event_classes_impl_defined);
-		ptr = pmu_event_classes_impl_defined;
-
-		for (i = 0; i < array_len; ++i) {
-			if (buf_size > pos) {
-				pos += snprintf(&(*buf)[pos],
-						buf_size-pos,
-						"[%u] %s\n",
-						ptr[i].event_number,
-						ptr[i].desc);
+				break;
 			}
 		}
 	}
@@ -144,16 +129,11 @@
 	struct event_class *ptr;
 	int i;
 	const char *event_class_name = NO_EVENT_CLASS_NAME;
-	if (event_class < 0) {
+	if (event_class < 0)
 		goto out;
-	} else if (event_class < 0x80) {
-		array_len = ARRAY_SIZE(pmu_event_classes);
-		ptr = pmu_event_classes;
-	} else {
-		/* All implementation defined classes are above 0x7F */
-		array_len = ARRAY_SIZE(pmu_event_classes_impl_defined);
-		ptr = pmu_event_classes_impl_defined;
-	}
+
+	array_len = ARRAY_SIZE(pmu_event_classes);
+	ptr = pmu_event_classes;
 
 	for (i = 0; i < array_len; ++i) {
 		if (ptr[i].event_number == event_class) {
@@ -186,16 +166,6 @@
 		}
 	}
 
-	array_len = ARRAY_SIZE(pmu_event_classes_impl_defined);
-	ptr = pmu_event_classes_impl_defined;
-
-	for (i = 0; i < array_len; ++i) {
-		if (strcmp(ptr[i].desc, event_class_name) == 0) {
-			event_class =  ptr[i].event_number;
-			goto out;
-		}
-	}
-
 out:
 	return event_class;
 }
@@ -248,7 +218,7 @@
 	writel_relaxed(pmcr, iommu->base + PMCR);
 }
 
-void iommu_pm_disable(struct iommu_info *iommu)
+static void iommu_pm_disable(struct iommu_info *iommu)
 {
 	unsigned int pmcr;
 	pmcr = readl_relaxed(iommu->base + PMCR);
@@ -533,48 +503,6 @@
 		pmon->iommu.iommu_name);
 }
 
-static unsigned int iommu_pm_get_num_groups(struct iommu_pmon *iommu_pmon)
-{
-	unsigned int pmcfgr;
-	unsigned int num_cntgrp;
-	struct iommu_info *iommu = &iommu_pmon->iommu;
-
-	pmcfgr = readl_relaxed(iommu->base + PMCFGR);
-
-	/* Due to a bug in IOMMU hardware the counter register is returning
-	 * the wrong information. num_cntgrp should return "total number
-	 * of counter groups - 1". However, it returns "total number
-	 * of counter groups". Thus we do not add 1 to the total number of
-	 * counter groups. If we find that the number of counter group is 0
-	 * then we assume the bug has been fixed and add 1 to the count.
-	 */
-	num_cntgrp = ((pmcfgr & PMCFGR_NCG) >> PMCFGR_NCG_SHIFT);
-	if (num_cntgrp == 0)
-		num_cntgrp++;
-
-	return num_cntgrp;
-
-}
-
-static unsigned int iommu_pm_get_num_counters(struct iommu_pmon *iommu_pmon,
-						unsigned int group_no)
-{
-	unsigned int num_counters;
-	unsigned int tmp;
-	struct iommu_info *iommu = &iommu_pmon->iommu;
-
-	tmp = readl_relaxed(iommu->base + PMCGCR_(group_no));
-	num_counters = ((tmp & PMCGCR_CGNC) >> PMCGCR_CGNC_SHIFT);
-
-	return num_counters;
-
-}
-
-static unsigned int iommu_pm_get_sup_ev_cls(struct iommu_info *iommu)
-{
-	return readl_relaxed(iommu->base + PMCEID0);
-}
-
 static int iommu_pm_debug_open(struct inode *inode, struct file *file)
 {
 	file->private_data = inode->i_private;
@@ -659,7 +587,7 @@
 		int rv;
 		long value;
 		buf[wr_cnt-1] = '\0';
-		rv = kstrtol(buf, 50, &value);
+		rv = kstrtol(buf, 10, &value);
 		if (!rv) {
 			counter->current_event_class =
 				iommu_pm_find_event_class(
@@ -799,7 +727,7 @@
 
 	mutex_lock(&pmon->lock);
 
-	len = iommu_pm_create_sup_cls_str(&buf, pmon->event_cls_supp_value);
+	len = iommu_pm_create_sup_cls_str(&buf, pmon);
 	if (buf) {
 		rd_cnt = simple_read_from_buffer(user_buff, count, pos,
 						 buf, len);
@@ -877,8 +805,7 @@
 	for (i = 0; i < pmon_entry->num_groups; ++i) {
 		pmon_entry->cnt_grp[i].pmon = pmon_entry;
 		pmon_entry->cnt_grp[i].grp_no = i;
-		pmon_entry->cnt_grp[i].num_counters =
-			iommu_pm_get_num_counters(pmon_entry, i);
+		pmon_entry->cnt_grp[i].num_counters = pmon_entry->num_counters;
 		pmon_entry->cnt_grp[i].counters =
 			kzalloc(sizeof(*pmon_entry->cnt_grp[i].counters)
 			* pmon_entry->cnt_grp[i].num_counters, GFP_KERNEL);
@@ -907,11 +834,10 @@
 	return ret;
 }
 
-int msm_iommu_pm_iommu_register(struct iommu_info *iommu)
+int msm_iommu_pm_iommu_register(struct iommu_pmon *pmon_entry)
 {
-	struct iommu_pmon *pmon_entry;
 	int ret = 0;
-	struct msm_iommu_drvdata *iommu_drvdata;
+	struct iommu_info *iommu = &pmon_entry->iommu;
 	int i;
 
 	if (!iommu->ops || !iommu->iommu_name || !iommu->base
@@ -928,14 +854,7 @@
 			goto out;
 		}
 	}
-	pmon_entry = (struct iommu_pmon *)container_of(iommu,
-						struct iommu_pmon, iommu);
-	iommu_drvdata = dev_get_drvdata(iommu->iommu_dev);
 
-	iommu->ops->iommu_power_on(iommu_drvdata);
-	iommu->ops->iommu_lock_acquire();
-
-	pmon_entry->num_groups = iommu_pm_get_num_groups(pmon_entry);
 	pmon_entry->cnt_grp = kzalloc(sizeof(*pmon_entry->cnt_grp)
 				      * pmon_entry->num_groups, GFP_KERNEL);
 	if (!pmon_entry->cnt_grp) {
@@ -943,8 +862,6 @@
 		ret = -ENOMEM;
 		goto file_err;
 	}
-	pmon_entry->event_cls_supp_value = iommu_pm_get_sup_ev_cls(iommu);
-
 	pmon_entry->iommu_dir = debugfs_create_dir(iommu->iommu_name,
 						   msm_iommu_root_debugfs_dir);
 	if (IS_ERR_OR_NULL(pmon_entry->iommu_dir)) {
@@ -977,9 +894,6 @@
 	if (ret)
 		goto free_mem;
 
-	iommu->ops->iommu_lock_release();
-	iommu->ops->iommu_power_off(iommu_drvdata);
-
 	if (iommu->evt_irq > 0) {
 		ret = request_threaded_irq(iommu->evt_irq, NULL,
 				iommu_pm_evt_ovfl_int_handler,
@@ -995,8 +909,7 @@
 		pr_info("%s: Overflow interrupt not available\n", __func__);
 	}
 
-	dev_dbg(iommu->iommu_dev, "%s iommu registered\n",
-							iommu->iommu_name);
+	dev_dbg(iommu->iommu_dev, "%s iommu registered\n", iommu->iommu_name);
 
 	goto out;
 free_mem:
@@ -1042,7 +955,7 @@
 }
 EXPORT_SYMBOL(msm_iommu_pm_iommu_unregister);
 
-struct iommu_info *msm_iommu_pm_alloc(struct device *dev)
+struct iommu_pmon *msm_iommu_pm_alloc(struct device *dev)
 {
 	struct iommu_pmon *pmon_entry;
 	struct iommu_info *info;
@@ -1053,7 +966,7 @@
 	info->iommu_dev = dev;
 	mutex_init(&pmon_entry->lock);
 	iommu_pm_add_to_iommu_list(pmon_entry);
-	return &pmon_entry->iommu;
+	return pmon_entry;
 }
 EXPORT_SYMBOL(msm_iommu_pm_alloc);
 
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index e57fcd8..4e55bd6 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -29,7 +29,8 @@
 
 #include <asm/sizes.h>
 
-#include <mach/iommu_hw-v2.h>
+#include <mach/iommu_perfmon.h>
+#include <mach/iommu_hw-v1.h>
 #include <mach/iommu.h>
 #include <mach/scm.h>
 
@@ -79,7 +80,7 @@
 	unsigned int spare;
 	int ret, ptbl_ret = 0;
 
-	for_each_compatible_node(np, NULL, "qcom,msm-smmu-v2")
+	for_each_compatible_node(np, NULL, "qcom,msm-smmu-v1")
 		if (of_find_property(np, "qcom,iommu-secure-id", NULL))
 			break;
 
@@ -379,6 +380,10 @@
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ctx_drvdata->attached_domain = domain;
 
+	mutex_unlock(&msm_iommu_lock);
+
+	msm_iommu_attached(dev->parent);
+	return ret;
 fail:
 	mutex_unlock(&msm_iommu_lock);
 	return ret;
@@ -390,6 +395,8 @@
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 
+	msm_iommu_detached(dev->parent);
+
 	mutex_lock(&msm_iommu_lock);
 	if (!dev)
 		goto fail;
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 9575db4..890037a 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -106,6 +106,8 @@
 source "drivers/media/common/Kconfig"
 source "drivers/media/rc/Kconfig"
 
+source "drivers/media/platform/Kconfig"
+
 #
 # Tuner drivers for DVB and V4L
 #
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 64755c9..133a74f 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -8,7 +8,7 @@
   obj-$(CONFIG_MEDIA_SUPPORT) += media.o
 endif
 
-obj-y += common/ rc/ video/
+obj-y += common/ platform/ rc/ video/
 
 obj-$(CONFIG_VIDEO_DEV) += radio/
 obj-$(CONFIG_DVB_CORE)  += dvb/
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 915dcaa..f6e40b3 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -88,8 +88,4 @@
 	depends on DVB_CORE
 source "drivers/media/dvb/frontends/Kconfig"
 
-comment "Qualcomm MPQ adapter"
-	depends on ARCH_MSM && DVB_CORE
-source "drivers/media/dvb/mpq/Kconfig"
-
 endif # DVB_CAPTURE_DRIVERS
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index d3438d6..b2cefe6 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -19,5 +19,3 @@
 		ddbridge/
 
 obj-$(CONFIG_DVB_FIREDTV)	+= firewire/
-obj-$(CONFIG_DVB_MPQ)		+= mpq/
-
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
new file mode 100644
index 0000000..10c803e
--- /dev/null
+++ b/drivers/media/platform/Kconfig
@@ -0,0 +1 @@
+source "drivers/media/platform/msm/Kconfig"
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
new file mode 100644
index 0000000..3d080b7
--- /dev/null
+++ b/drivers/media/platform/Makefile
@@ -0,0 +1 @@
+obj-y += msm/
diff --git a/drivers/media/platform/msm/Kconfig b/drivers/media/platform/msm/Kconfig
new file mode 100644
index 0000000..e344719
--- /dev/null
+++ b/drivers/media/platform/msm/Kconfig
@@ -0,0 +1,48 @@
+#
+# MSM camera configuration
+#
+
+comment "Qualcomm MSM Camera And Video"
+
+menuconfig MSM_CAMERA
+	bool "Qualcomm MSM camera and video capture support"
+	depends on ARCH_MSM && VIDEO_V4L2 && I2C
+	default y
+	help
+	  Say Y here to enable selecting the video adapters for
+	  Qualcomm msm camera and video encoding
+
+config MSM_CAMERA_DEBUG
+	bool "Qualcomm MSM camera debugging with printk"
+	depends on MSM_CAMERA
+	default n
+	help
+	  Enable printk() debug for msm camera
+
+if MSM_CAMERA
+source "drivers/media/platform/msm/camera_v1/Kconfig"
+endif # MSM_CAMERA
+
+menuconfig MSMB_CAMERA
+	bool "Qualcomm MSM camera and video capture 2.0 support"
+	depends on ARCH_MSM && VIDEO_V4L2 && I2C
+	---help---
+	  Say Y here to enable selecting the video adapters for
+	  Qualcomm msm camera and video capture 2.0, enabling this
+	  adds support for the camera driver stack including sensor, isp
+	  and postprocessing drivers.
+
+config MSMB_CAMERA_DEBUG
+	bool "Qualcomm MSM camera 2.0 debugging with printk"
+	depends on MSMB_CAMERA
+	---help---
+	  Enable printk() debug for msm camera 2.0
+
+if MSMB_CAMERA
+source "drivers/media/platform/msm/camera_v2/Kconfig"
+endif # MSMB_CAMERA
+
+source "drivers/media/platform/msm/vidc/Kconfig"
+source "drivers/media/platform/msm/wfd/Kconfig"
+source "drivers/media/platform/msm/dvb/Kconfig"
+source "drivers/media/platform/msm/vcap/Kconfig"
diff --git a/drivers/media/platform/msm/Makefile b/drivers/media/platform/msm/Makefile
new file mode 100644
index 0000000..c1d86df
--- /dev/null
+++ b/drivers/media/platform/msm/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_MSM_VIDC_V4L2) += vidc/
+obj-$(CONFIG_MSM_WFD) += wfd/
+obj-$(CONFIG_DVB_MPQ) += dvb/
+obj-$(CONFIG_MSM_CAMERA) += camera_v1/
+obj-$(CONFIG_MSMB_CAMERA) += camera_v2/
+obj-y += vcap/
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/platform/msm/camera_v1/Kconfig
similarity index 97%
rename from drivers/media/video/msm/Kconfig
rename to drivers/media/platform/msm/camera_v1/Kconfig
index 24f6556..ac449cc 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/platform/msm/camera_v1/Kconfig
@@ -274,15 +274,6 @@
         ---help---
           Enable support for Mercury Jpeg Engine
 
-config MSM_JPEG
-	tristate "Qualcomm MSM Jpeg Encoder Engine support"
-	depends on MSM_CAMERA && ARCH_MSM8974
-	---help---
-          Enable support for Jpeg Encoder/Decoder
-	  Engine for 8974.
-	  This module serves as the common driver
-	  for the JPEG 1.0 encoder and decoder.
-
 config MSM_VPE
 	tristate "Qualcomm MSM Video Pre-processing Engine support"
 	depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60)
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/platform/msm/camera_v1/Makefile
similarity index 78%
rename from drivers/media/video/msm/Makefile
rename to drivers/media/platform/msm/camera_v1/Makefile
index 67ac906..eb66b29 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/platform/msm/camera_v1/Makefile
@@ -1,16 +1,16 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
 
-ccflags-y += -Idrivers/media/video/msm/io
-ccflags-y += -Idrivers/media/video/msm/vfe
+ccflags-y += -Idrivers/media/platform/msm/camera_v1/io
+ccflags-y += -Idrivers/media/platform/msm/camera_v1/vfe
 obj-$(CONFIG_MSM_CAMERA) += io/
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/cci
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/server
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/flash
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/cci
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/csi
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/eeprom
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/sensors
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/actuators
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/server
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/flash
   obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
   obj-$(CONFIG_MSM_CAMERA) += server/
   obj-$(CONFIG_MSM_CAM_IRQ_ROUTER) += msm_camirq_router.o
@@ -23,7 +23,6 @@
 endif
 obj-$(CONFIG_MSM_CAMERA) += vfe/
 obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/ mercury/
-obj-$(CONFIG_MSM_JPEG) += jpeg_10/
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   obj-$(CONFIG_ARCH_MSM8X60) += msm_vpe.o
   obj-$(CONFIG_ARCH_MSM7X30) += msm_vpe.o msm_axi_qos.o
diff --git a/drivers/media/platform/msm/camera_v1/actuators/Makefile b/drivers/media/platform/msm/camera_v1/actuators/Makefile
new file mode 100644
index 0000000..95713a1
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v1/actuators/Makefile
@@ -0,0 +1,4 @@
+GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/io
+obj-$(CONFIG_MSM_ACTUATOR) += msm_actuator.o
diff --git a/drivers/media/video/msm/actuators/msm_actuator.c b/drivers/media/platform/msm/camera_v1/actuators/msm_actuator.c
similarity index 100%
rename from drivers/media/video/msm/actuators/msm_actuator.c
rename to drivers/media/platform/msm/camera_v1/actuators/msm_actuator.c
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/platform/msm/camera_v1/actuators/msm_actuator.h
similarity index 100%
rename from drivers/media/video/msm/actuators/msm_actuator.h
rename to drivers/media/platform/msm/camera_v1/actuators/msm_actuator.h
diff --git a/drivers/media/platform/msm/camera_v1/cci/Makefile b/drivers/media/platform/msm/camera_v1/cci/Makefile
new file mode 100644
index 0000000..0f23f6c
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v1/cci/Makefile
@@ -0,0 +1,3 @@
+GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+ccflags-y += -Idrivers/media/platform/msm/camera_v1 -Idrivers/media/platform/msm/camera_v1/server
+obj-$(CONFIG_MSM_CCI) += msm_cci.o
diff --git a/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h b/drivers/media/platform/msm/camera_v1/cci/msm_cam_cci_hwreg.h
similarity index 100%
rename from drivers/media/video/msm/cci/msm_cam_cci_hwreg.h
rename to drivers/media/platform/msm/camera_v1/cci/msm_cam_cci_hwreg.h
diff --git a/drivers/media/video/msm/cci/msm_cci.c b/drivers/media/platform/msm/camera_v1/cci/msm_cci.c
similarity index 100%
rename from drivers/media/video/msm/cci/msm_cci.c
rename to drivers/media/platform/msm/camera_v1/cci/msm_cci.c
diff --git a/drivers/media/video/msm/cci/msm_cci.h b/drivers/media/platform/msm/camera_v1/cci/msm_cci.h
similarity index 100%
rename from drivers/media/video/msm/cci/msm_cci.h
rename to drivers/media/platform/msm/camera_v1/cci/msm_cci.h
diff --git a/drivers/media/platform/msm/camera_v1/cpp/Makefile b/drivers/media/platform/msm/camera_v1/cpp/Makefile
new file mode 100644
index 0000000..aa4c362
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v1/cpp/Makefile
@@ -0,0 +1,5 @@
+GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+ccflags-y += -Idrivers/media/platform/msm/camera_v1
+ccflags-y += -Idrivers/media/platform/msm/camera_v1/io
+obj-$(CONFIG_MSM_CPP) += msm_cpp.o
+
diff --git a/drivers/media/video/msm/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v1/cpp/msm_cpp.c
similarity index 100%
rename from drivers/media/video/msm/cpp/msm_cpp.c
rename to drivers/media/platform/msm/camera_v1/cpp/msm_cpp.c
diff --git a/drivers/media/video/msm/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v1/cpp/msm_cpp.h
similarity index 100%
rename from drivers/media/video/msm/cpp/msm_cpp.h
rename to drivers/media/platform/msm/camera_v1/cpp/msm_cpp.h
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/platform/msm/camera_v1/csi/Makefile
similarity index 71%
rename from drivers/media/video/msm/csi/Makefile
rename to drivers/media/platform/msm/camera_v1/csi/Makefile
index 5aaaff7..6284511 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/platform/msm/camera_v1/csi/Makefile
@@ -1,9 +1,9 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-ccflags-y += -Idrivers/media/video/msm -Idrivers/media/video/msm/server
+ccflags-y += -Idrivers/media/platform/msm/camera_v1 -Idrivers/media/platform/msm/camera_v1/server
 ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
-  ccflags-y += -Idrivers/media/video/msm/csi/include/csi2.0
+  ccflags-y += -Idrivers/media/platform/msm/camera_v1/csi/include/csi2.0
 else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
-  ccflags-y += -Idrivers/media/video/msm/csi/include/csi3.0
+  ccflags-y += -Idrivers/media/platform/msm/camera_v1/csi/include/csi3.0
 endif
 obj-$(CONFIG_MSM_CSI2_REGISTER) += msm_csi2_register.o
 obj-$(CONFIG_MSM_CSIPHY) += msm_csiphy.o
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h b/drivers/media/platform/msm/camera_v1/csi/include/csi2.0/msm_csid_hwreg.h
similarity index 100%
rename from drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
rename to drivers/media/platform/msm/camera_v1/csi/include/csi2.0/msm_csid_hwreg.h
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h b/drivers/media/platform/msm/camera_v1/csi/include/csi2.0/msm_csiphy_hwreg.h
similarity index 100%
rename from drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
rename to drivers/media/platform/msm/camera_v1/csi/include/csi2.0/msm_csiphy_hwreg.h
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h b/drivers/media/platform/msm/camera_v1/csi/include/csi2.0/msm_ispif_hwreg.h
similarity index 100%
rename from drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
rename to drivers/media/platform/msm/camera_v1/csi/include/csi2.0/msm_ispif_hwreg.h
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h b/drivers/media/platform/msm/camera_v1/csi/include/csi3.0/msm_csid_hwreg.h
similarity index 100%
rename from drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
rename to drivers/media/platform/msm/camera_v1/csi/include/csi3.0/msm_csid_hwreg.h
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h b/drivers/media/platform/msm/camera_v1/csi/include/csi3.0/msm_csiphy_hwreg.h
similarity index 100%
rename from drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
rename to drivers/media/platform/msm/camera_v1/csi/include/csi3.0/msm_csiphy_hwreg.h
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h b/drivers/media/platform/msm/camera_v1/csi/include/csi3.0/msm_ispif_hwreg.h
similarity index 100%
rename from drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
rename to drivers/media/platform/msm/camera_v1/csi/include/csi3.0/msm_ispif_hwreg.h
diff --git a/drivers/media/video/msm/csi/msm_csi2_register.c b/drivers/media/platform/msm/camera_v1/csi/msm_csi2_register.c
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csi2_register.c
rename to drivers/media/platform/msm/camera_v1/csi/msm_csi2_register.c
diff --git a/drivers/media/video/msm/csi/msm_csi_register.h b/drivers/media/platform/msm/camera_v1/csi/msm_csi_register.h
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csi_register.h
rename to drivers/media/platform/msm/camera_v1/csi/msm_csi_register.h
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/platform/msm/camera_v1/csi/msm_csic.c
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csic.c
rename to drivers/media/platform/msm/camera_v1/csi/msm_csic.c
diff --git a/drivers/media/video/msm/csi/msm_csic.h b/drivers/media/platform/msm/camera_v1/csi/msm_csic.h
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csic.h
rename to drivers/media/platform/msm/camera_v1/csi/msm_csic.h
diff --git a/drivers/media/video/msm/csi/msm_csic_register.c b/drivers/media/platform/msm/camera_v1/csi/msm_csic_register.c
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csic_register.c
rename to drivers/media/platform/msm/camera_v1/csi/msm_csic_register.c
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/platform/msm/camera_v1/csi/msm_csid.c
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csid.c
rename to drivers/media/platform/msm/camera_v1/csi/msm_csid.c
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/platform/msm/camera_v1/csi/msm_csid.h
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csid.h
rename to drivers/media/platform/msm/camera_v1/csi/msm_csid.h
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/platform/msm/camera_v1/csi/msm_csiphy.c
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csiphy.c
rename to drivers/media/platform/msm/camera_v1/csi/msm_csiphy.c
diff --git a/drivers/media/video/msm/csi/msm_csiphy.h b/drivers/media/platform/msm/camera_v1/csi/msm_csiphy.h
similarity index 100%
rename from drivers/media/video/msm/csi/msm_csiphy.h
rename to drivers/media/platform/msm/camera_v1/csi/msm_csiphy.h
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/platform/msm/camera_v1/csi/msm_ispif.c
similarity index 100%
rename from drivers/media/video/msm/csi/msm_ispif.c
rename to drivers/media/platform/msm/camera_v1/csi/msm_ispif.c
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/platform/msm/camera_v1/csi/msm_ispif.h
similarity index 100%
rename from drivers/media/video/msm/csi/msm_ispif.h
rename to drivers/media/platform/msm/camera_v1/csi/msm_ispif.h
diff --git a/drivers/media/video/msm/eeprom/Makefile b/drivers/media/platform/msm/camera_v1/eeprom/Makefile
similarity index 80%
rename from drivers/media/video/msm/eeprom/Makefile
rename to drivers/media/platform/msm/camera_v1/eeprom/Makefile
index f7b7f5d..6474aee 100644
--- a/drivers/media/video/msm/eeprom/Makefile
+++ b/drivers/media/platform/msm/camera_v1/eeprom/Makefile
@@ -1,5 +1,5 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-EXTRA_CFLAGS += -Idrivers/media/video/msm/io
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/io
 obj-$(CONFIG_MSM_EEPROM) += msm_camera_eeprom.o
 obj-$(CONFIG_IMX074_EEPROM) += imx074_eeprom.o
 obj-$(CONFIG_IMX091_EEPROM) += imx091_eeprom.o
\ No newline at end of file
diff --git a/drivers/media/video/msm/eeprom/imx074_eeprom.c b/drivers/media/platform/msm/camera_v1/eeprom/imx074_eeprom.c
similarity index 100%
rename from drivers/media/video/msm/eeprom/imx074_eeprom.c
rename to drivers/media/platform/msm/camera_v1/eeprom/imx074_eeprom.c
diff --git a/drivers/media/video/msm/eeprom/imx091_eeprom.c b/drivers/media/platform/msm/camera_v1/eeprom/imx091_eeprom.c
similarity index 100%
rename from drivers/media/video/msm/eeprom/imx091_eeprom.c
rename to drivers/media/platform/msm/camera_v1/eeprom/imx091_eeprom.c
diff --git a/drivers/media/video/msm/eeprom/msm_camera_eeprom.c b/drivers/media/platform/msm/camera_v1/eeprom/msm_camera_eeprom.c
similarity index 100%
rename from drivers/media/video/msm/eeprom/msm_camera_eeprom.c
rename to drivers/media/platform/msm/camera_v1/eeprom/msm_camera_eeprom.c
diff --git a/drivers/media/video/msm/eeprom/msm_camera_eeprom.h b/drivers/media/platform/msm/camera_v1/eeprom/msm_camera_eeprom.h
similarity index 100%
rename from drivers/media/video/msm/eeprom/msm_camera_eeprom.h
rename to drivers/media/platform/msm/camera_v1/eeprom/msm_camera_eeprom.h
diff --git a/drivers/media/video/msm/flash/Makefile b/drivers/media/platform/msm/camera_v1/flash/Makefile
similarity index 81%
rename from drivers/media/video/msm/flash/Makefile
rename to drivers/media/platform/msm/camera_v1/flash/Makefile
index 8d0812b..ad1d452 100644
--- a/drivers/media/video/msm/flash/Makefile
+++ b/drivers/media/platform/msm/camera_v1/flash/Makefile
@@ -1,6 +1,6 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-ccflags-y += -Idrivers/media/video/msm
-ccflags-y += -Idrivers/media/video/msm/io
+ccflags-y += -Idrivers/media/platform/msm/camera_v1
+ccflags-y += -Idrivers/media/platform/msm/camera_v1/io
 obj-$(CONFIG_MSM_CAMERA_FLASH) += msm_flash.o
 obj-$(CONFIG_MSM_CAMERA_FLASH_SC628A) += sc628a.o
 obj-$(CONFIG_MSM_CAMERA_FLASH_TPS61310) += tps61310.o
diff --git a/drivers/media/video/msm/flash/led_trigger_flash.c b/drivers/media/platform/msm/camera_v1/flash/led_trigger_flash.c
similarity index 100%
rename from drivers/media/video/msm/flash/led_trigger_flash.c
rename to drivers/media/platform/msm/camera_v1/flash/led_trigger_flash.c
diff --git a/drivers/media/video/msm/flash/msm_flash.c b/drivers/media/platform/msm/camera_v1/flash/msm_flash.c
similarity index 100%
rename from drivers/media/video/msm/flash/msm_flash.c
rename to drivers/media/platform/msm/camera_v1/flash/msm_flash.c
diff --git a/drivers/media/video/msm/flash/msm_flash.h b/drivers/media/platform/msm/camera_v1/flash/msm_flash.h
similarity index 100%
rename from drivers/media/video/msm/flash/msm_flash.h
rename to drivers/media/platform/msm/camera_v1/flash/msm_flash.h
diff --git a/drivers/media/video/msm/flash/pmic8058_flash.c b/drivers/media/platform/msm/camera_v1/flash/pmic8058_flash.c
similarity index 100%
rename from drivers/media/video/msm/flash/pmic8058_flash.c
rename to drivers/media/platform/msm/camera_v1/flash/pmic8058_flash.c
diff --git a/drivers/media/video/msm/flash/pmic8058_pwm.c b/drivers/media/platform/msm/camera_v1/flash/pmic8058_pwm.c
similarity index 100%
rename from drivers/media/video/msm/flash/pmic8058_pwm.c
rename to drivers/media/platform/msm/camera_v1/flash/pmic8058_pwm.c
diff --git a/drivers/media/video/msm/flash/sc628a.c b/drivers/media/platform/msm/camera_v1/flash/sc628a.c
similarity index 100%
rename from drivers/media/video/msm/flash/sc628a.c
rename to drivers/media/platform/msm/camera_v1/flash/sc628a.c
diff --git a/drivers/media/video/msm/flash/sgm3141.c b/drivers/media/platform/msm/camera_v1/flash/sgm3141.c
similarity index 100%
rename from drivers/media/video/msm/flash/sgm3141.c
rename to drivers/media/platform/msm/camera_v1/flash/sgm3141.c
diff --git a/drivers/media/video/msm/flash/tps61310.c b/drivers/media/platform/msm/camera_v1/flash/tps61310.c
similarity index 100%
rename from drivers/media/video/msm/flash/tps61310.c
rename to drivers/media/platform/msm/camera_v1/flash/tps61310.c
diff --git a/drivers/media/video/msm/gemini/Makefile b/drivers/media/platform/msm/camera_v1/gemini/Makefile
similarity index 79%
rename from drivers/media/video/msm/gemini/Makefile
rename to drivers/media/platform/msm/camera_v1/gemini/Makefile
index 8a7cd93..6d4166c 100644
--- a/drivers/media/video/msm/gemini/Makefile
+++ b/drivers/media/platform/msm/camera_v1/gemini/Makefile
@@ -1,3 +1,3 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-EXTRA_CFLAGS += -Idrivers/media/video/msm
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1
 obj-$(CONFIG_MSM_GEMINI) += msm_gemini_dev.o msm_gemini_sync.o msm_gemini_core.o msm_gemini_hw.o msm_gemini_platform.o
diff --git a/drivers/media/video/msm/gemini/msm_gemini_common.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_common.h
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_common.h
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_common.h
diff --git a/drivers/media/video/msm/gemini/msm_gemini_core.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_core.c
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c
diff --git a/drivers/media/video/msm/gemini/msm_gemini_core.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.h
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_core.h
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.h
diff --git a/drivers/media/video/msm/gemini/msm_gemini_dev.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_dev.c
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_dev.c
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_dev.c
diff --git a/drivers/media/video/msm/gemini/msm_gemini_hw.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_hw.c
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c
diff --git a/drivers/media/video/msm/gemini/msm_gemini_hw.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_hw.h
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h
diff --git a/drivers/media/video/msm/gemini/msm_gemini_hw_reg.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_hw_reg.h
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_platform.c
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.h
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_platform.h
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.h
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_sync.c
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h
similarity index 100%
rename from drivers/media/video/msm/gemini/msm_gemini_sync.h
rename to drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h
diff --git a/drivers/media/video/msm/imx072.c b/drivers/media/platform/msm/camera_v1/imx072.c
similarity index 100%
rename from drivers/media/video/msm/imx072.c
rename to drivers/media/platform/msm/camera_v1/imx072.c
diff --git a/drivers/media/video/msm/imx072.h b/drivers/media/platform/msm/camera_v1/imx072.h
similarity index 100%
rename from drivers/media/video/msm/imx072.h
rename to drivers/media/platform/msm/camera_v1/imx072.h
diff --git a/drivers/media/video/msm/imx072_reg.c b/drivers/media/platform/msm/camera_v1/imx072_reg.c
similarity index 100%
rename from drivers/media/video/msm/imx072_reg.c
rename to drivers/media/platform/msm/camera_v1/imx072_reg.c
diff --git a/drivers/media/video/msm/imx074.c b/drivers/media/platform/msm/camera_v1/imx074.c
similarity index 100%
rename from drivers/media/video/msm/imx074.c
rename to drivers/media/platform/msm/camera_v1/imx074.c
diff --git a/drivers/media/video/msm/imx074.h b/drivers/media/platform/msm/camera_v1/imx074.h
similarity index 100%
rename from drivers/media/video/msm/imx074.h
rename to drivers/media/platform/msm/camera_v1/imx074.h
diff --git a/drivers/media/video/msm/imx074_reg.c b/drivers/media/platform/msm/camera_v1/imx074_reg.c
similarity index 100%
rename from drivers/media/video/msm/imx074_reg.c
rename to drivers/media/platform/msm/camera_v1/imx074_reg.c
diff --git a/drivers/media/video/msm/io/Makefile b/drivers/media/platform/msm/camera_v1/io/Makefile
similarity index 87%
rename from drivers/media/video/msm/io/Makefile
rename to drivers/media/platform/msm/camera_v1/io/Makefile
index fdff226..9ec119c 100644
--- a/drivers/media/video/msm/io/Makefile
+++ b/drivers/media/platform/msm/camera_v1/io/Makefile
@@ -1,6 +1,6 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
 
-ccflags-y += -Idrivers/media/video/msm -Idrivers/media/video/msm/cci
+ccflags-y += -Idrivers/media/platform/msm/camera_v1 -Idrivers/media/platform/msm/camera_v1/cci
 obj-$(CONFIG_MSM_CAMERA)   += msm_camera_io_util.o msm_camera_i2c.o
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c_mux.o
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.c b/drivers/media/platform/msm/camera_v1/io/msm_camera_i2c.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_camera_i2c.c
rename to drivers/media/platform/msm/camera_v1/io/msm_camera_i2c.c
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/platform/msm/camera_v1/io/msm_camera_i2c.h
similarity index 100%
rename from drivers/media/video/msm/io/msm_camera_i2c.h
rename to drivers/media/platform/msm/camera_v1/io/msm_camera_i2c.h
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.c b/drivers/media/platform/msm/camera_v1/io/msm_camera_i2c_mux.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_camera_i2c_mux.c
rename to drivers/media/platform/msm/camera_v1/io/msm_camera_i2c_mux.c
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.h b/drivers/media/platform/msm/camera_v1/io/msm_camera_i2c_mux.h
similarity index 100%
rename from drivers/media/video/msm/io/msm_camera_i2c_mux.h
rename to drivers/media/platform/msm/camera_v1/io/msm_camera_i2c_mux.h
diff --git a/drivers/media/video/msm/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v1/io/msm_camera_io_util.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_camera_io_util.c
rename to drivers/media/platform/msm/camera_v1/io/msm_camera_io_util.c
diff --git a/drivers/media/video/msm/io/msm_io7x.c b/drivers/media/platform/msm/camera_v1/io/msm_io7x.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_io7x.c
rename to drivers/media/platform/msm/camera_v1/io/msm_io7x.c
diff --git a/drivers/media/video/msm/io/msm_io8x.c b/drivers/media/platform/msm/camera_v1/io/msm_io8x.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_io8x.c
rename to drivers/media/platform/msm/camera_v1/io/msm_io8x.c
diff --git a/drivers/media/video/msm/io/msm_io_7x27a.c b/drivers/media/platform/msm/camera_v1/io/msm_io_7x27a.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_io_7x27a.c
rename to drivers/media/platform/msm/camera_v1/io/msm_io_7x27a.c
diff --git a/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c b/drivers/media/platform/msm/camera_v1/io/msm_io_7x27a_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
rename to drivers/media/platform/msm/camera_v1/io/msm_io_7x27a_v4l2.c
diff --git a/drivers/media/video/msm/io/msm_io_8960.c b/drivers/media/platform/msm/camera_v1/io/msm_io_8960.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_io_8960.c
rename to drivers/media/platform/msm/camera_v1/io/msm_io_8960.c
diff --git a/drivers/media/video/msm/io/msm_io_8x60.c b/drivers/media/platform/msm/camera_v1/io/msm_io_8x60.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_io_8x60.c
rename to drivers/media/platform/msm/camera_v1/io/msm_io_8x60.c
diff --git a/drivers/media/video/msm/io/msm_io_vfe31.c b/drivers/media/platform/msm/camera_v1/io/msm_io_vfe31.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_io_vfe31.c
rename to drivers/media/platform/msm/camera_v1/io/msm_io_vfe31.c
diff --git a/drivers/media/video/msm/io/msm_io_vfe31_v4l2.c b/drivers/media/platform/msm/camera_v1/io/msm_io_vfe31_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/io/msm_io_vfe31_v4l2.c
rename to drivers/media/platform/msm/camera_v1/io/msm_io_vfe31_v4l2.c
diff --git a/drivers/media/video/msm/mercury/Makefile b/drivers/media/platform/msm/camera_v1/mercury/Makefile
similarity index 79%
rename from drivers/media/video/msm/mercury/Makefile
rename to drivers/media/platform/msm/camera_v1/mercury/Makefile
index ce4c86d..bc9c950 100644
--- a/drivers/media/video/msm/mercury/Makefile
+++ b/drivers/media/platform/msm/camera_v1/mercury/Makefile
@@ -1,3 +1,3 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-EXTRA_CFLAGS += -Idrivers/media/video/msm
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1
 obj-$(CONFIG_MSM_MERCURY) += msm_mercury_dev.o msm_mercury_core.o msm_mercury_hw.o msm_mercury_platform.o msm_mercury_sync.o
diff --git a/drivers/media/video/msm/mercury/msm_mercury_common.h b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_common.h
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_common.h
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_common.h
diff --git a/drivers/media/video/msm/mercury/msm_mercury_core.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_core.c
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_core.c
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_core.c
diff --git a/drivers/media/video/msm/mercury/msm_mercury_core.h b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_core.h
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_core.h
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_core.h
diff --git a/drivers/media/video/msm/mercury/msm_mercury_dev.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_dev.c
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_dev.c
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_dev.c
diff --git a/drivers/media/video/msm/mercury/msm_mercury_hw.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_hw.c
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_hw.c
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_hw.c
diff --git a/drivers/media/video/msm/mercury/msm_mercury_hw.h b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_hw.h
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_hw.h
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_hw.h
diff --git a/drivers/media/video/msm/mercury/msm_mercury_hw_reg.h b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_hw_reg.h
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_hw_reg.h
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_hw_reg.h
diff --git a/drivers/media/video/msm/mercury/msm_mercury_macros.h b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_macros.h
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_macros.h
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_macros.h
diff --git a/drivers/media/video/msm/mercury/msm_mercury_platform.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_platform.c
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
diff --git a/drivers/media/video/msm/mercury/msm_mercury_platform.h b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.h
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_platform.h
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.h
diff --git a/drivers/media/video/msm/mercury/msm_mercury_sync.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_sync.c
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_sync.c
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_sync.c
diff --git a/drivers/media/video/msm/mercury/msm_mercury_sync.h b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_sync.h
similarity index 100%
rename from drivers/media/video/msm/mercury/msm_mercury_sync.h
rename to drivers/media/platform/msm/camera_v1/mercury/msm_mercury_sync.h
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/platform/msm/camera_v1/msm.c
similarity index 100%
rename from drivers/media/video/msm/msm.c
rename to drivers/media/platform/msm/camera_v1/msm.c
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/platform/msm/camera_v1/msm.h
similarity index 100%
rename from drivers/media/video/msm/msm.h
rename to drivers/media/platform/msm/camera_v1/msm.h
diff --git a/drivers/media/video/msm/msm_axi_qos.c b/drivers/media/platform/msm/camera_v1/msm_axi_qos.c
similarity index 100%
rename from drivers/media/video/msm/msm_axi_qos.c
rename to drivers/media/platform/msm/camera_v1/msm_axi_qos.c
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/platform/msm/camera_v1/msm_camera.c
similarity index 100%
rename from drivers/media/video/msm/msm_camera.c
rename to drivers/media/platform/msm/camera_v1/msm_camera.c
diff --git a/drivers/media/video/msm/msm_camirq_router.c b/drivers/media/platform/msm/camera_v1/msm_camirq_router.c
similarity index 100%
rename from drivers/media/video/msm/msm_camirq_router.c
rename to drivers/media/platform/msm/camera_v1/msm_camirq_router.c
diff --git a/drivers/media/video/msm/msm_camirq_router.h b/drivers/media/platform/msm/camera_v1/msm_camirq_router.h
similarity index 100%
rename from drivers/media/video/msm/msm_camirq_router.h
rename to drivers/media/platform/msm/camera_v1/msm_camirq_router.h
diff --git a/drivers/media/video/msm/msm_gesture.c b/drivers/media/platform/msm/camera_v1/msm_gesture.c
similarity index 100%
rename from drivers/media/video/msm/msm_gesture.c
rename to drivers/media/platform/msm/camera_v1/msm_gesture.c
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/platform/msm/camera_v1/msm_isp.c
similarity index 100%
rename from drivers/media/video/msm/msm_isp.c
rename to drivers/media/platform/msm/camera_v1/msm_isp.c
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/platform/msm/camera_v1/msm_mctl.c
similarity index 100%
rename from drivers/media/video/msm/msm_mctl.c
rename to drivers/media/platform/msm/camera_v1/msm_mctl.c
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c
similarity index 100%
rename from drivers/media/video/msm/msm_mctl_buf.c
rename to drivers/media/platform/msm/camera_v1/msm_mctl_buf.c
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c
similarity index 100%
rename from drivers/media/video/msm/msm_mctl_pp.c
rename to drivers/media/platform/msm/camera_v1/msm_mctl_pp.c
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/platform/msm/camera_v1/msm_mem.c
similarity index 100%
rename from drivers/media/video/msm/msm_mem.c
rename to drivers/media/platform/msm/camera_v1/msm_mem.c
diff --git a/drivers/media/video/msm/msm_v4l2_video.c b/drivers/media/platform/msm/camera_v1/msm_v4l2_video.c
similarity index 100%
rename from drivers/media/video/msm/msm_v4l2_video.c
rename to drivers/media/platform/msm/camera_v1/msm_v4l2_video.c
diff --git a/drivers/media/video/msm/msm_v4l2_video.h b/drivers/media/platform/msm/camera_v1/msm_v4l2_video.h
similarity index 100%
rename from drivers/media/video/msm/msm_v4l2_video.h
rename to drivers/media/platform/msm/camera_v1/msm_v4l2_video.h
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/platform/msm/camera_v1/msm_vpe.c
similarity index 100%
rename from drivers/media/video/msm/msm_vpe.c
rename to drivers/media/platform/msm/camera_v1/msm_vpe.c
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/platform/msm/camera_v1/msm_vpe.h
similarity index 100%
rename from drivers/media/video/msm/msm_vpe.h
rename to drivers/media/platform/msm/camera_v1/msm_vpe.h
diff --git a/drivers/media/video/msm/msm_vpe1.c b/drivers/media/platform/msm/camera_v1/msm_vpe1.c
similarity index 100%
rename from drivers/media/video/msm/msm_vpe1.c
rename to drivers/media/platform/msm/camera_v1/msm_vpe1.c
diff --git a/drivers/media/video/msm/msm_vpe1.h b/drivers/media/platform/msm/camera_v1/msm_vpe1.h
similarity index 100%
rename from drivers/media/video/msm/msm_vpe1.h
rename to drivers/media/platform/msm/camera_v1/msm_vpe1.h
diff --git a/drivers/media/video/msm/mt9d112.c b/drivers/media/platform/msm/camera_v1/mt9d112.c
similarity index 100%
rename from drivers/media/video/msm/mt9d112.c
rename to drivers/media/platform/msm/camera_v1/mt9d112.c
diff --git a/drivers/media/video/msm/mt9d112.h b/drivers/media/platform/msm/camera_v1/mt9d112.h
similarity index 100%
rename from drivers/media/video/msm/mt9d112.h
rename to drivers/media/platform/msm/camera_v1/mt9d112.h
diff --git a/drivers/media/video/msm/mt9d112_reg.c b/drivers/media/platform/msm/camera_v1/mt9d112_reg.c
similarity index 100%
rename from drivers/media/video/msm/mt9d112_reg.c
rename to drivers/media/platform/msm/camera_v1/mt9d112_reg.c
diff --git a/drivers/media/video/msm/mt9d113.c b/drivers/media/platform/msm/camera_v1/mt9d113.c
similarity index 100%
rename from drivers/media/video/msm/mt9d113.c
rename to drivers/media/platform/msm/camera_v1/mt9d113.c
diff --git a/drivers/media/video/msm/mt9d113.h b/drivers/media/platform/msm/camera_v1/mt9d113.h
similarity index 100%
rename from drivers/media/video/msm/mt9d113.h
rename to drivers/media/platform/msm/camera_v1/mt9d113.h
diff --git a/drivers/media/video/msm/mt9d113_reg.c b/drivers/media/platform/msm/camera_v1/mt9d113_reg.c
similarity index 100%
rename from drivers/media/video/msm/mt9d113_reg.c
rename to drivers/media/platform/msm/camera_v1/mt9d113_reg.c
diff --git a/drivers/media/video/msm/mt9e013.c b/drivers/media/platform/msm/camera_v1/mt9e013.c
similarity index 100%
rename from drivers/media/video/msm/mt9e013.c
rename to drivers/media/platform/msm/camera_v1/mt9e013.c
diff --git a/drivers/media/video/msm/mt9e013.h b/drivers/media/platform/msm/camera_v1/mt9e013.h
similarity index 100%
rename from drivers/media/video/msm/mt9e013.h
rename to drivers/media/platform/msm/camera_v1/mt9e013.h
diff --git a/drivers/media/video/msm/mt9e013_reg.c b/drivers/media/platform/msm/camera_v1/mt9e013_reg.c
similarity index 100%
rename from drivers/media/video/msm/mt9e013_reg.c
rename to drivers/media/platform/msm/camera_v1/mt9e013_reg.c
diff --git a/drivers/media/video/msm/mt9p012.h b/drivers/media/platform/msm/camera_v1/mt9p012.h
similarity index 100%
rename from drivers/media/video/msm/mt9p012.h
rename to drivers/media/platform/msm/camera_v1/mt9p012.h
diff --git a/drivers/media/video/msm/mt9p012_bam.c b/drivers/media/platform/msm/camera_v1/mt9p012_bam.c
similarity index 100%
rename from drivers/media/video/msm/mt9p012_bam.c
rename to drivers/media/platform/msm/camera_v1/mt9p012_bam.c
diff --git a/drivers/media/video/msm/mt9p012_fox.c b/drivers/media/platform/msm/camera_v1/mt9p012_fox.c
similarity index 100%
rename from drivers/media/video/msm/mt9p012_fox.c
rename to drivers/media/platform/msm/camera_v1/mt9p012_fox.c
diff --git a/drivers/media/video/msm/mt9p012_km.c b/drivers/media/platform/msm/camera_v1/mt9p012_km.c
similarity index 100%
rename from drivers/media/video/msm/mt9p012_km.c
rename to drivers/media/platform/msm/camera_v1/mt9p012_km.c
diff --git a/drivers/media/video/msm/mt9p012_km.h b/drivers/media/platform/msm/camera_v1/mt9p012_km.h
similarity index 100%
rename from drivers/media/video/msm/mt9p012_km.h
rename to drivers/media/platform/msm/camera_v1/mt9p012_km.h
diff --git a/drivers/media/video/msm/mt9p012_km_reg.c b/drivers/media/platform/msm/camera_v1/mt9p012_km_reg.c
similarity index 100%
rename from drivers/media/video/msm/mt9p012_km_reg.c
rename to drivers/media/platform/msm/camera_v1/mt9p012_km_reg.c
diff --git a/drivers/media/video/msm/mt9p012_reg.c b/drivers/media/platform/msm/camera_v1/mt9p012_reg.c
similarity index 100%
rename from drivers/media/video/msm/mt9p012_reg.c
rename to drivers/media/platform/msm/camera_v1/mt9p012_reg.c
diff --git a/drivers/media/video/msm/mt9t013.c b/drivers/media/platform/msm/camera_v1/mt9t013.c
similarity index 100%
rename from drivers/media/video/msm/mt9t013.c
rename to drivers/media/platform/msm/camera_v1/mt9t013.c
diff --git a/drivers/media/video/msm/mt9t013.h b/drivers/media/platform/msm/camera_v1/mt9t013.h
similarity index 100%
rename from drivers/media/video/msm/mt9t013.h
rename to drivers/media/platform/msm/camera_v1/mt9t013.h
diff --git a/drivers/media/video/msm/mt9t013_reg.c b/drivers/media/platform/msm/camera_v1/mt9t013_reg.c
similarity index 100%
rename from drivers/media/video/msm/mt9t013_reg.c
rename to drivers/media/platform/msm/camera_v1/mt9t013_reg.c
diff --git a/drivers/media/video/msm/ov5640.c b/drivers/media/platform/msm/camera_v1/ov5640.c
similarity index 100%
rename from drivers/media/video/msm/ov5640.c
rename to drivers/media/platform/msm/camera_v1/ov5640.c
diff --git a/drivers/media/video/msm/ov5640.h b/drivers/media/platform/msm/camera_v1/ov5640.h
similarity index 100%
rename from drivers/media/video/msm/ov5640.h
rename to drivers/media/platform/msm/camera_v1/ov5640.h
diff --git a/drivers/media/video/msm/ov5647.c b/drivers/media/platform/msm/camera_v1/ov5647.c
similarity index 100%
rename from drivers/media/video/msm/ov5647.c
rename to drivers/media/platform/msm/camera_v1/ov5647.c
diff --git a/drivers/media/video/msm/ov5647.h b/drivers/media/platform/msm/camera_v1/ov5647.h
similarity index 100%
rename from drivers/media/video/msm/ov5647.h
rename to drivers/media/platform/msm/camera_v1/ov5647.h
diff --git a/drivers/media/video/msm/ov5647_reg.c b/drivers/media/platform/msm/camera_v1/ov5647_reg.c
similarity index 100%
rename from drivers/media/video/msm/ov5647_reg.c
rename to drivers/media/platform/msm/camera_v1/ov5647_reg.c
diff --git a/drivers/media/video/msm/ov7692.c b/drivers/media/platform/msm/camera_v1/ov7692.c
similarity index 100%
rename from drivers/media/video/msm/ov7692.c
rename to drivers/media/platform/msm/camera_v1/ov7692.c
diff --git a/drivers/media/video/msm/ov7692.h b/drivers/media/platform/msm/camera_v1/ov7692.h
similarity index 100%
rename from drivers/media/video/msm/ov7692.h
rename to drivers/media/platform/msm/camera_v1/ov7692.h
diff --git a/drivers/media/video/msm/ov7692_qrd.c b/drivers/media/platform/msm/camera_v1/ov7692_qrd.c
similarity index 100%
rename from drivers/media/video/msm/ov7692_qrd.c
rename to drivers/media/platform/msm/camera_v1/ov7692_qrd.c
diff --git a/drivers/media/video/msm/ov9726.c b/drivers/media/platform/msm/camera_v1/ov9726.c
similarity index 100%
rename from drivers/media/video/msm/ov9726.c
rename to drivers/media/platform/msm/camera_v1/ov9726.c
diff --git a/drivers/media/video/msm/ov9726.h b/drivers/media/platform/msm/camera_v1/ov9726.h
similarity index 100%
rename from drivers/media/video/msm/ov9726.h
rename to drivers/media/platform/msm/camera_v1/ov9726.h
diff --git a/drivers/media/video/msm/ov9726_reg.c b/drivers/media/platform/msm/camera_v1/ov9726_reg.c
similarity index 100%
rename from drivers/media/video/msm/ov9726_reg.c
rename to drivers/media/platform/msm/camera_v1/ov9726_reg.c
diff --git a/drivers/media/video/msm/qs_s5k4e1.c b/drivers/media/platform/msm/camera_v1/qs_s5k4e1.c
similarity index 100%
rename from drivers/media/video/msm/qs_s5k4e1.c
rename to drivers/media/platform/msm/camera_v1/qs_s5k4e1.c
diff --git a/drivers/media/video/msm/qs_s5k4e1.h b/drivers/media/platform/msm/camera_v1/qs_s5k4e1.h
similarity index 100%
rename from drivers/media/video/msm/qs_s5k4e1.h
rename to drivers/media/platform/msm/camera_v1/qs_s5k4e1.h
diff --git a/drivers/media/video/msm/qs_s5k4e1_reg.c b/drivers/media/platform/msm/camera_v1/qs_s5k4e1_reg.c
similarity index 100%
rename from drivers/media/video/msm/qs_s5k4e1_reg.c
rename to drivers/media/platform/msm/camera_v1/qs_s5k4e1_reg.c
diff --git a/drivers/media/video/msm/s5k3e2fx.c b/drivers/media/platform/msm/camera_v1/s5k3e2fx.c
similarity index 100%
rename from drivers/media/video/msm/s5k3e2fx.c
rename to drivers/media/platform/msm/camera_v1/s5k3e2fx.c
diff --git a/drivers/media/video/msm/s5k3e2fx.h b/drivers/media/platform/msm/camera_v1/s5k3e2fx.h
similarity index 100%
rename from drivers/media/video/msm/s5k3e2fx.h
rename to drivers/media/platform/msm/camera_v1/s5k3e2fx.h
diff --git a/drivers/media/video/msm/s5k4e1.c b/drivers/media/platform/msm/camera_v1/s5k4e1.c
similarity index 100%
rename from drivers/media/video/msm/s5k4e1.c
rename to drivers/media/platform/msm/camera_v1/s5k4e1.c
diff --git a/drivers/media/video/msm/s5k4e1.h b/drivers/media/platform/msm/camera_v1/s5k4e1.h
similarity index 100%
rename from drivers/media/video/msm/s5k4e1.h
rename to drivers/media/platform/msm/camera_v1/s5k4e1.h
diff --git a/drivers/media/video/msm/s5k4e1_reg.c b/drivers/media/platform/msm/camera_v1/s5k4e1_reg.c
similarity index 100%
rename from drivers/media/video/msm/s5k4e1_reg.c
rename to drivers/media/platform/msm/camera_v1/s5k4e1_reg.c
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/platform/msm/camera_v1/sensors/Makefile
similarity index 73%
rename from drivers/media/video/msm/sensors/Makefile
rename to drivers/media/platform/msm/camera_v1/sensors/Makefile
index a70a632..174e9ba 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/platform/msm/camera_v1/sensors/Makefile
@@ -1,8 +1,8 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-EXTRA_CFLAGS += -Idrivers/media/video/msm
-EXTRA_CFLAGS += -Idrivers/media/video/msm/io
-EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
-EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/io
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/eeprom
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/csi
 obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor_common.o msm_sensor.o msm_sensor_bayer.o msm_sensor_init.o
 obj-$(CONFIG_OV5647) += ov5647_v4l2.o
 obj-$(CONFIG_OV8825) += ov8825_v4l2.o
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/imx074_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/imx074_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/imx074_v4l2.c
diff --git a/drivers/media/video/msm/sensors/imx091.h b/drivers/media/platform/msm/camera_v1/sensors/imx091.h
similarity index 100%
rename from drivers/media/video/msm/sensors/imx091.h
rename to drivers/media/platform/msm/camera_v1/sensors/imx091.h
diff --git a/drivers/media/video/msm/sensors/imx135_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/imx135_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/imx135_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/imx135_v4l2.c
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/platform/msm/camera_v1/sensors/msm_sensor.c
similarity index 100%
rename from drivers/media/video/msm/sensors/msm_sensor.c
rename to drivers/media/platform/msm/camera_v1/sensors/msm_sensor.c
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/platform/msm/camera_v1/sensors/msm_sensor.h
similarity index 100%
rename from drivers/media/video/msm/sensors/msm_sensor.h
rename to drivers/media/platform/msm/camera_v1/sensors/msm_sensor.h
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.c b/drivers/media/platform/msm/camera_v1/sensors/msm_sensor_bayer.c
similarity index 100%
rename from drivers/media/video/msm/sensors/msm_sensor_bayer.c
rename to drivers/media/platform/msm/camera_v1/sensors/msm_sensor_bayer.c
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.h b/drivers/media/platform/msm/camera_v1/sensors/msm_sensor_bayer.h
similarity index 100%
rename from drivers/media/video/msm/sensors/msm_sensor_bayer.h
rename to drivers/media/platform/msm/camera_v1/sensors/msm_sensor_bayer.h
diff --git a/drivers/media/video/msm/sensors/msm_sensor_common.c b/drivers/media/platform/msm/camera_v1/sensors/msm_sensor_common.c
similarity index 100%
rename from drivers/media/video/msm/sensors/msm_sensor_common.c
rename to drivers/media/platform/msm/camera_v1/sensors/msm_sensor_common.c
diff --git a/drivers/media/video/msm/sensors/msm_sensor_common.h b/drivers/media/platform/msm/camera_v1/sensors/msm_sensor_common.h
similarity index 100%
rename from drivers/media/video/msm/sensors/msm_sensor_common.h
rename to drivers/media/platform/msm/camera_v1/sensors/msm_sensor_common.h
diff --git a/drivers/media/video/msm/sensors/msm_sensor_init.c b/drivers/media/platform/msm/camera_v1/sensors/msm_sensor_init.c
similarity index 100%
rename from drivers/media/video/msm/sensors/msm_sensor_init.c
rename to drivers/media/platform/msm/camera_v1/sensors/msm_sensor_init.c
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/mt9e013_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/mt9e013_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/mt9e013_v4l2.c
diff --git a/drivers/media/video/msm/sensors/mt9m114_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/mt9m114_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/mt9m114_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/mt9m114_v4l2.c
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/platform/msm/camera_v1/sensors/ov2720.c
similarity index 100%
rename from drivers/media/video/msm/sensors/ov2720.c
rename to drivers/media/platform/msm/camera_v1/sensors/ov2720.c
diff --git a/drivers/media/video/msm/sensors/ov2720.h b/drivers/media/platform/msm/camera_v1/sensors/ov2720.h
similarity index 100%
rename from drivers/media/video/msm/sensors/ov2720.h
rename to drivers/media/platform/msm/camera_v1/sensors/ov2720.h
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/ov5647_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/ov5647_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/ov5647_v4l2.c
diff --git a/drivers/media/video/msm/sensors/ov7692_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/ov7692_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/ov7692_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/ov7692_v4l2.c
diff --git a/drivers/media/video/msm/sensors/ov8825_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/ov8825_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/ov8825_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/ov8825_v4l2.c
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/ov9726_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/ov9726_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/ov9726_v4l2.c
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/platform/msm/camera_v1/sensors/s5k3l1yx.c
similarity index 100%
rename from drivers/media/video/msm/sensors/s5k3l1yx.c
rename to drivers/media/platform/msm/camera_v1/sensors/s5k3l1yx.c
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/platform/msm/camera_v1/sensors/s5k4e1_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/sensors/s5k4e1_v4l2.c
rename to drivers/media/platform/msm/camera_v1/sensors/s5k4e1_v4l2.c
diff --git a/drivers/media/video/msm/sensors/vx6953.c b/drivers/media/platform/msm/camera_v1/sensors/vx6953.c
similarity index 100%
rename from drivers/media/video/msm/sensors/vx6953.c
rename to drivers/media/platform/msm/camera_v1/sensors/vx6953.c
diff --git a/drivers/media/video/msm/sensors/vx6953.h b/drivers/media/platform/msm/camera_v1/sensors/vx6953.h
similarity index 100%
rename from drivers/media/video/msm/sensors/vx6953.h
rename to drivers/media/platform/msm/camera_v1/sensors/vx6953.h
diff --git a/drivers/media/video/msm/sensors/vx6953_reg.h b/drivers/media/platform/msm/camera_v1/sensors/vx6953_reg.h
similarity index 100%
rename from drivers/media/video/msm/sensors/vx6953_reg.h
rename to drivers/media/platform/msm/camera_v1/sensors/vx6953_reg.h
diff --git a/drivers/media/platform/msm/camera_v1/server/Makefile b/drivers/media/platform/msm/camera_v1/server/Makefile
new file mode 100644
index 0000000..a64be59
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v1/server/Makefile
@@ -0,0 +1,11 @@
+GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+
+ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/io
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/csi
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/eeprom
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/sensors
+  EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1/actuators
+  obj-$(CONFIG_MSM_CAMERA)   += msm_cam_server.o
+endif
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/platform/msm/camera_v1/server/msm_cam_server.c
similarity index 100%
rename from drivers/media/video/msm/server/msm_cam_server.c
rename to drivers/media/platform/msm/camera_v1/server/msm_cam_server.c
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/platform/msm/camera_v1/server/msm_cam_server.h
similarity index 100%
rename from drivers/media/video/msm/server/msm_cam_server.h
rename to drivers/media/platform/msm/camera_v1/server/msm_cam_server.h
diff --git a/drivers/media/video/msm/sn12m0pz.c b/drivers/media/platform/msm/camera_v1/sn12m0pz.c
similarity index 100%
rename from drivers/media/video/msm/sn12m0pz.c
rename to drivers/media/platform/msm/camera_v1/sn12m0pz.c
diff --git a/drivers/media/video/msm/sn12m0pz.h b/drivers/media/platform/msm/camera_v1/sn12m0pz.h
similarity index 100%
rename from drivers/media/video/msm/sn12m0pz.h
rename to drivers/media/platform/msm/camera_v1/sn12m0pz.h
diff --git a/drivers/media/video/msm/sn12m0pz_reg.c b/drivers/media/platform/msm/camera_v1/sn12m0pz_reg.c
similarity index 100%
rename from drivers/media/video/msm/sn12m0pz_reg.c
rename to drivers/media/platform/msm/camera_v1/sn12m0pz_reg.c
diff --git a/drivers/media/video/msm/vb6801.c b/drivers/media/platform/msm/camera_v1/vb6801.c
similarity index 100%
rename from drivers/media/video/msm/vb6801.c
rename to drivers/media/platform/msm/camera_v1/vb6801.c
diff --git a/drivers/media/video/msm/vb6801.h b/drivers/media/platform/msm/camera_v1/vb6801.h
similarity index 100%
rename from drivers/media/video/msm/vb6801.h
rename to drivers/media/platform/msm/camera_v1/vb6801.h
diff --git a/drivers/media/video/msm/vfe/Makefile b/drivers/media/platform/msm/camera_v1/vfe/Makefile
similarity index 86%
rename from drivers/media/video/msm/vfe/Makefile
rename to drivers/media/platform/msm/camera_v1/vfe/Makefile
index 250b55f..ead1075 100644
--- a/drivers/media/video/msm/vfe/Makefile
+++ b/drivers/media/platform/msm/camera_v1/vfe/Makefile
@@ -1,6 +1,6 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-ccflags-y += -Idrivers/media/video/msm
-ccflags-y += -Idrivers/media/video/msm/server
+ccflags-y += -Idrivers/media/platform/msm/camera_v1
+ccflags-y += -Idrivers/media/platform/msm/camera_v1/server
 ifeq ($(GCC_VERSION),0404)
 CFLAGS_REMOVE_msm_vfe8x.o = -Wframe-larger-than=1024
 endif
diff --git a/drivers/media/video/msm/vfe/msm_vfe31.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe31.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe31.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe31.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe31.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe31.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe31.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe31.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe31_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe31_v4l2.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe31_v4l2.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe31_v4l2.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe32.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe32.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe32.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe32.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe32.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe32.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe40.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe40.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe40.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe40.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe40.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe40.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe40_axi.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe40_axi.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe40_axi.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe40_axi.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe7x.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe7x.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe7x27a.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe7x27a.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe8x.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe8x.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe8x.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe8x.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe8x.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe8x.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe8x.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe8x.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe8x_proc.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe8x_proc.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe8x_proc.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe8x_proc.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe8x_proc.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe8x_proc.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe8x_proc.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe8x_proc.h
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.h
similarity index 100%
rename from drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
rename to drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.h
diff --git a/drivers/media/video/msm/vx6953.c b/drivers/media/platform/msm/camera_v1/vx6953.c
similarity index 100%
rename from drivers/media/video/msm/vx6953.c
rename to drivers/media/platform/msm/camera_v1/vx6953.c
diff --git a/drivers/media/video/msm/vx6953.h b/drivers/media/platform/msm/camera_v1/vx6953.h
similarity index 100%
rename from drivers/media/video/msm/vx6953.h
rename to drivers/media/platform/msm/camera_v1/vx6953.h
diff --git a/drivers/media/video/msm/vx6953_reg.c b/drivers/media/platform/msm/camera_v1/vx6953_reg.c
similarity index 100%
rename from drivers/media/video/msm/vx6953_reg.c
rename to drivers/media/platform/msm/camera_v1/vx6953_reg.c
diff --git a/drivers/media/video/msm/vx6953_reg_v4l2.c b/drivers/media/platform/msm/camera_v1/vx6953_reg_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/vx6953_reg_v4l2.c
rename to drivers/media/platform/msm/camera_v1/vx6953_reg_v4l2.c
diff --git a/drivers/media/video/msm/vx6953_v4l2.c b/drivers/media/platform/msm/camera_v1/vx6953_v4l2.c
similarity index 100%
rename from drivers/media/video/msm/vx6953_v4l2.c
rename to drivers/media/platform/msm/camera_v1/vx6953_v4l2.c
diff --git a/drivers/media/video/msm/vx6953_v4l2.h b/drivers/media/platform/msm/camera_v1/vx6953_v4l2.h
similarity index 100%
rename from drivers/media/video/msm/vx6953_v4l2.h
rename to drivers/media/platform/msm/camera_v1/vx6953_v4l2.h
diff --git a/drivers/media/video/msmb/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
similarity index 79%
rename from drivers/media/video/msmb/Kconfig
rename to drivers/media/platform/msm/camera_v2/Kconfig
index c128b0d..2bbdc22 100644
--- a/drivers/media/video/msmb/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -82,6 +82,24 @@
 		snapshot config = 4000 * 3000 at 20 fps,
 		hfr video at 60, 90 and 120 fps.
 
+config OV2720
+	bool "Sensor OV2720 (BAYER 2M)"
+	depends on MSMB_CAMERA
+	---help---
+		OmniVision 2 MP Bayer Sensor, supports 2 mipi lanes,
+		preview and snapshot config at 1932 * 1092 at 30 fps,
+		hfr video at 60, 90 and 120 fps. This sensor driver does
+		not support auto focus.
+
+config MT9M114
+	bool "Sensor MT9M114 (YUV 1.26MP)"
+	depends on MSMB_CAMERA
+	---help---
+		MT9M114 is Aptina YUV sensor. It supports 1.26 MP preview
+		and snapshot. The preview and snapshot resolution shall be
+		1280 * 270. It does not support auto focus. It supports
+		few special effects like saturation.
+
 config MSM_V4L2_VIDEO_OVERLAY_DEVICE
 	tristate "Qualcomm MSM V4l2 video overlay device"
 	---help---
@@ -90,4 +108,12 @@
 	  apps to render overlaid video using Video4Linux2
 	  APIs, by using /dev/videoX device
 
+config MSMB_JPEG
+	tristate "Qualcomm MSM Jpeg Encoder Engine support"
+	depends on MSMB_CAMERA && ARCH_MSM8974
+	---help---
+	  Enable support for Jpeg Encoder/Decoder
+	  Engine for 8974.
+	  This module serves as the common driver
+	  for the JPEG 1.0 encoder and decoder.
 
diff --git a/drivers/media/platform/msm/camera_v2/Makefile b/drivers/media/platform/msm/camera_v2/Makefile
new file mode 100644
index 0000000..25dfd37
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/Makefile
@@ -0,0 +1,17 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/codecs
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/isps
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/pps
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/msm_vb2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/jpeg_10
+
+obj-$(CONFIG_MSMB_CAMERA) += msm.o
+obj-$(CONFIG_MSMB_CAMERA) += camera/
+obj-$(CONFIG_MSMB_CAMERA) += msm_vb2/
+obj-$(CONFIG_MSMB_CAMERA) += sensor/
+obj-$(CONFIG_MSMB_CAMERA) += isp/
+obj-$(CONFIG_MSMB_CAMERA) += ispif/
+obj-$(CONFIG_MSMB_JPEG) += jpeg_10/
+obj-$(CONFIG_MSMB_CAMERA) += msm_buf_mgr/
diff --git a/drivers/media/platform/msm/camera_v2/camera/Makefile b/drivers/media/platform/msm/camera_v2/camera/Makefile
new file mode 100644
index 0000000..bd70750
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/camera/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/msm_vb2
+obj-$(CONFIG_MSMB_CAMERA) += camera.o
diff --git a/drivers/media/video/msmb/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
similarity index 96%
rename from drivers/media/video/msmb/camera/camera.c
rename to drivers/media/platform/msm/camera_v2/camera/camera.c
index c726958..63ab4bf 100644
--- a/drivers/media/video/msmb/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -93,7 +93,7 @@
 	int rc = 0;
 	struct v4l2_event event;
 
-	if (crop->type == V4L2_BUF_TYPE_PRIVATE) {
+	if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 
 		camera_pack_event(filep, MSM_CAMERA_SET_PARM,
 			MSM_CAMERA_PRIV_S_CROP, &event);
@@ -254,7 +254,7 @@
 	return rc;
 }
 
-static int camera_v4l2_g_fmt_cap_private(struct file *filep, void *fh,
+static int camera_v4l2_g_fmt_vid_cap_mplane(struct file *filep, void *fh,
 	struct v4l2_format *pfmt)
 {
 	int rc = -EINVAL;
@@ -275,7 +275,7 @@
 	return rc;
 }
 
-static int camera_v4l2_s_fmt_cap_private(struct file *filep, void *fh,
+static int camera_v4l2_s_fmt_vid_cap_mplane(struct file *filep, void *fh,
 	struct v4l2_format *pfmt)
 {
 	int rc = 0;
@@ -284,7 +284,7 @@
 	struct camera_v4l2_private *sp = fh_to_private(fh);
 	struct msm_v4l2_format_data *user_fmt;
 
-	if (pfmt->type == V4L2_BUF_TYPE_PRIVATE) {
+	if (pfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 
 		if (WARN_ON(!sp->vb2_q.drv_priv))
 			return -ENOMEM;
@@ -318,17 +318,12 @@
 	return rc;
 }
 
-static int camera_v4l2_try_fmt_cap_private(struct file *filep, void *fh,
+static int camera_v4l2_try_fmt_vid_cap_mplane(struct file *filep, void *fh,
 	struct v4l2_format *pfmt)
 {
 	return 0;
 }
 
-int camera_v4l2_g_fmt_vid_cap_mplane(struct file *file, void *fh,
-	struct v4l2_format *f)
-{
-	return 0;
-}
 
 static int camera_v4l2_g_parm(struct file *filep, void *fh,
 	struct v4l2_streamparm *a)
@@ -408,10 +403,9 @@
 	.vidioc_dqbuf = camera_v4l2_dqbuf,
 	.vidioc_streamon =  camera_v4l2_streamon,
 	.vidioc_streamoff = camera_v4l2_streamoff,
-	.vidioc_g_fmt_type_private = camera_v4l2_g_fmt_cap_private,
-	.vidioc_s_fmt_type_private = camera_v4l2_s_fmt_cap_private,
-	.vidioc_try_fmt_type_private = camera_v4l2_try_fmt_cap_private,
 	.vidioc_g_fmt_vid_cap_mplane = camera_v4l2_g_fmt_vid_cap_mplane,
+	.vidioc_s_fmt_vid_cap_mplane = camera_v4l2_s_fmt_vid_cap_mplane,
+	.vidioc_try_fmt_vid_cap_mplane = camera_v4l2_try_fmt_vid_cap_mplane,
 
 	/* Stream type-dependent parameter ioctls */
 	.vidioc_g_parm = camera_v4l2_g_parm,
diff --git a/drivers/media/video/msmb/camera/camera.h b/drivers/media/platform/msm/camera_v2/camera/camera.h
similarity index 100%
rename from drivers/media/video/msmb/camera/camera.h
rename to drivers/media/platform/msm/camera_v2/camera/camera.h
diff --git a/drivers/media/platform/msm/camera_v2/isp/Makefile b/drivers/media/platform/msm/camera_v2/isp/Makefile
new file mode 100644
index 0000000..f6e7cc4
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/isp/Makefile
@@ -0,0 +1,4 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+obj-$(CONFIG_MSMB_CAMERA) += msm_isp.o msm_buf_mgr.o msm_isp_util.o msm_isp_axi_util.o msm_isp_stats_util.o
+obj-$(CONFIG_MSMB_CAMERA) += msm_isp40.o msm_isp32.o
diff --git a/drivers/media/video/msmb/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
similarity index 83%
rename from drivers/media/video/msmb/isp/msm_buf_mgr.c
rename to drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index aab97d7..b8c507e 100644
--- a/drivers/media/video/msmb/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -180,8 +180,10 @@
 		return rc;
 	}
 
-	if (buf_info->state == MSM_ISP_BUFFER_STATE_UNUSED ||
-			buf_info->state != MSM_ISP_BUFFER_STATE_INITIALIZED) {
+	if (buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED)
+		return buf_info->state;
+
+	if (buf_info->state != MSM_ISP_BUFFER_STATE_INITIALIZED) {
 		pr_err("%s: Invalid buffer state: %d\n",
 			__func__, buf_info->state);
 		return rc;
@@ -283,10 +285,9 @@
 		}
 	}
 
-	if (!(*buf_info)) {
-		pr_err("%s: No free buffer\n", __func__);
+	if (!(*buf_info))
 		return rc;
-	}
+
 
 	(*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
 	return 0;
@@ -315,6 +316,7 @@
 	case MSM_ISP_BUFFER_STATE_PREPARED:
 	case MSM_ISP_BUFFER_STATE_DEQUEUED:
 	case MSM_ISP_BUFFER_STATE_DISPATCHED:
+	case MSM_ISP_BUFFER_STATE_DIVERTED:
 		if (BUF_SRC(bufq->stream_id))
 			list_add_tail(&buf_info->list, &bufq->head);
 		else
@@ -351,9 +353,17 @@
 		return rc;
 	}
 
-	if (buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED) {
+	if (buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED ||
+		buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED) {
 		buf_info->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
-		if (!(BUF_SRC(bufq->stream_id))) {
+		if ((BUF_SRC(bufq->stream_id))) {
+			rc = msm_isp_put_buf(buf_mgr, buf_info->bufq_handle,
+						buf_info->buf_idx);
+			if (rc < 0) {
+				pr_err("%s: Buf put failed\n", __func__);
+				return rc;
+			}
+		} else {
 			buf_info->vb2_buf->v4l2_buf.timestamp = *tv;
 			buf_info->vb2_buf->v4l2_buf.sequence  = frame_id;
 			buf_mgr->vb2_ops->buf_done(buf_info->vb2_buf);
@@ -363,26 +373,99 @@
 	return 0;
 }
 
-static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
-	struct msm_isp_qbuf_info *info)
+static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr,
+		uint32_t bufq_handle, enum msm_isp_buffer_flush_t flush_type)
 {
-	int rc;
+	int rc = -1, i;
 	struct msm_isp_bufq *bufq = NULL;
-	rc = msm_isp_buf_prepare(buf_mgr, info, NULL);
-	if (rc < 0) {
-		pr_err("%s: Buf prepare failed\n", __func__);
+	struct msm_isp_buffer *buf_info = NULL;
+
+	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
+	if (!bufq) {
+		pr_err("Invalid bufq\n");
 		return rc;
 	}
 
-	bufq = msm_isp_get_bufq(buf_mgr, info->handle);
-	if (BUF_SRC(bufq->stream_id)) {
-		rc = msm_isp_put_buf(buf_mgr, info->handle, info->buf_idx);
-		if (rc < 0) {
-			pr_err("%s: Buf put failed\n", __func__);
-			return rc;
+	for (i = 0; i < bufq->num_bufs; i++) {
+		buf_info = msm_isp_get_buf_ptr(buf_mgr, bufq_handle, i);
+		if (!buf_info) {
+			pr_err("%s: buf not found\n", __func__);
+			continue;
+		}
+
+		if (flush_type == MSM_ISP_BUFFER_FLUSH_DIVERTED &&
+			buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED) {
+			buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
+		} else if (flush_type == MSM_ISP_BUFFER_FLUSH_ALL &&
+			(buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED ||
+			buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED ||
+			buf_info->state == MSM_ISP_BUFFER_STATE_DISPATCHED)) {
+			buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
 		}
 	}
+	return 0;
+}
 
+static int msm_isp_buf_divert(struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t bufq_handle, uint32_t buf_index,
+	struct timeval *tv, uint32_t frame_id)
+{
+	int rc = -1;
+	struct msm_isp_bufq *bufq = NULL;
+	struct msm_isp_buffer *buf_info = NULL;
+
+	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
+	if (!bufq) {
+		pr_err("Invalid bufq\n");
+		return rc;
+	}
+
+	buf_info = msm_isp_get_buf_ptr(buf_mgr, bufq_handle, buf_index);
+	if (!buf_info) {
+		pr_err("%s: buf not found\n", __func__);
+		return rc;
+	}
+
+	if (buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED) {
+		buf_info->state = MSM_ISP_BUFFER_STATE_DIVERTED;
+		buf_info->tv = tv;
+		buf_info->frame_id = frame_id;
+	}
+
+	return 0;
+}
+
+static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
+	struct msm_isp_qbuf_info *info)
+{
+	int rc = -1, buf_state;
+	struct msm_isp_bufq *bufq = NULL;
+	struct msm_isp_buffer *buf_info = NULL;
+	buf_state = msm_isp_buf_prepare(buf_mgr, info, NULL);
+	if (buf_state < 0) {
+		pr_err("%s: Buf prepare failed\n", __func__);
+		return -EINVAL;
+	}
+
+	if (buf_state == MSM_ISP_BUFFER_STATE_DIVERTED) {
+		buf_info = msm_isp_get_buf_ptr(buf_mgr,
+						info->handle, info->buf_idx);
+		if (info->dirty_buf)
+			msm_isp_put_buf(buf_mgr, info->handle, info->buf_idx);
+		else
+			msm_isp_buf_done(buf_mgr, info->handle, info->buf_idx,
+				buf_info->tv, buf_info->frame_id);
+	} else {
+		bufq = msm_isp_get_bufq(buf_mgr, info->handle);
+		if (BUF_SRC(bufq->stream_id)) {
+			rc = msm_isp_put_buf(buf_mgr,
+					info->handle, info->buf_idx);
+			if (rc < 0) {
+				pr_err("%s: Buf put failed\n", __func__);
+				return rc;
+			}
+		}
+	}
 	return rc;
 }
 
@@ -563,7 +646,9 @@
 	.get_bufq_handle = msm_isp_get_bufq_handle,
 	.get_buf = msm_isp_get_buf,
 	.put_buf = msm_isp_put_buf,
+	.flush_buf = msm_isp_flush_buf,
 	.buf_done = msm_isp_buf_done,
+	.buf_divert = msm_isp_buf_divert,
 	.attach_ctx = msm_isp_attach_ctx,
 	.detach_ctx = msm_isp_detach_ctx,
 	.buf_mgr_init = msm_isp_init_isp_buf_mgr,
diff --git a/drivers/media/video/msmb/isp/msm_buf_mgr.h b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
similarity index 86%
rename from drivers/media/video/msmb/isp/msm_buf_mgr.h
rename to drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
index b96d9fe..244a1e2 100644
--- a/drivers/media/video/msmb/isp/msm_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
@@ -28,7 +28,13 @@
 	MSM_ISP_BUFFER_STATE_PREPARED,       /* BUF mapped */
 	MSM_ISP_BUFFER_STATE_QUEUED,         /* buf queued */
 	MSM_ISP_BUFFER_STATE_DEQUEUED,       /* in use in VFE */
-	MSM_ISP_BUFFER_STATE_DISPATCHED,     /* sent to userspace */
+	MSM_ISP_BUFFER_STATE_DIVERTED,       /* Sent to other hardware*/
+	MSM_ISP_BUFFER_STATE_DISPATCHED,     /* Sent to HAL*/
+};
+
+enum msm_isp_buffer_flush_t {
+	MSM_ISP_BUFFER_FLUSH_DIVERTED,
+	MSM_ISP_BUFFER_FLUSH_ALL,
 };
 
 struct msm_isp_buffer_mapped_info {
@@ -43,6 +49,8 @@
 	struct msm_isp_buffer_mapped_info mapped_info[VIDEO_MAX_PLANES];
 	int buf_idx;
 	uint32_t bufq_handle;
+	uint32_t frame_id;
+	struct timeval *tv;
 
 	/*Native buffer*/
 	struct list_head list;
@@ -83,9 +91,15 @@
 	int (*put_buf) (struct msm_isp_buf_mgr *buf_mgr,
 		uint32_t bufq_handle, uint32_t buf_index);
 
+	int (*flush_buf) (struct msm_isp_buf_mgr *buf_mgr,
+		uint32_t bufq_handle, enum msm_isp_buffer_flush_t flush_type);
+
 	int (*buf_done) (struct msm_isp_buf_mgr *buf_mgr,
 		uint32_t bufq_handle, uint32_t buf_index,
 		struct timeval *tv, uint32_t frame_id);
+	int (*buf_divert) (struct msm_isp_buf_mgr *buf_mgr,
+		uint32_t bufq_handle, uint32_t buf_index,
+		struct timeval *tv, uint32_t frame_id);
 	int (*attach_ctx) (struct msm_isp_buf_mgr *buf_mgr,
 		struct device *iommu_ctx);
 	void (*detach_ctx) (struct msm_isp_buf_mgr *buf_mgr,
diff --git a/drivers/media/video/msmb/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
similarity index 95%
rename from drivers/media/video/msmb/isp/msm_isp.c
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index 960144e..ff86aae 100644
--- a/drivers/media/video/msmb/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -29,6 +29,7 @@
 #include "msm_isp_stats_util.h"
 #include "msm_sd.h"
 #include "msm_isp40.h"
+#include "msm_isp32.h"
 
 static struct msm_sd_req_vb2_q vfe_vb2_ops;
 
@@ -43,7 +44,7 @@
 MODULE_DEVICE_TABLE(of, msm_vfe_dt_match);
 
 static const struct platform_device_id msm_vfe_dev_id[] = {
-	{"msm_vfe32"},
+	{"msm_vfe32", (kernel_ulong_t) &vfe32_hw_info},
 	{}
 };
 
@@ -80,7 +81,8 @@
 		vfe_dev->hw_info =
 			(struct msm_vfe_hardware_info *) match_dev->data;
 	} else {
-		vfe_dev->hw_info = platform_get_drvdata(pdev);
+		vfe_dev->hw_info = (struct msm_vfe_hardware_info *)
+			platform_get_device_id(pdev)->driver_data;
 	}
 
 	if (!vfe_dev->hw_info) {
diff --git a/drivers/media/video/msmb/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
similarity index 85%
rename from drivers/media/video/msmb/isp/msm_isp.h
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 1c82f45..f6b97d4 100644
--- a/drivers/media/video/msmb/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -26,6 +26,7 @@
 
 #include "msm_buf_mgr.h"
 
+#define MAX_IOMMU_CTX 2
 #define MAX_NUM_WM 7
 #define MAX_NUM_RDI 3
 #define MAX_NUM_RDI_MASTER 3
@@ -34,6 +35,9 @@
 #define MAX_INIT_FRAME_DROP 31
 #define ISP_SUB(a) ((a > 0) ? a-1 : 0)
 
+#define VFE_PING_FLAG 0xFFFFFFFF
+#define VFE_PONG_FLAG 0x0
+
 struct vfe_device;
 struct msm_vfe_axi_stream;
 struct msm_vfe_stats_stream;
@@ -54,13 +58,15 @@
 	void (*read_irq_status) (struct vfe_device *vfe_dev,
 		uint32_t *irq_status0, uint32_t *irq_status1);
 	void (*process_reg_update) (struct vfe_device *vfe_dev,
-		uint32_t irq_status0, uint32_t irq_status1);
+		uint32_t irq_status0, uint32_t irq_status1,
+		struct timeval *tv);
 	void (*process_reset_irq) (struct vfe_device *vfe_dev,
 		uint32_t irq_status0, uint32_t irq_status1);
 	void (*process_halt_irq) (struct vfe_device *vfe_dev,
 		uint32_t irq_status0, uint32_t irq_status1);
 	void (*process_camif_irq) (struct vfe_device *vfe_dev,
-		uint32_t irq_status0, uint32_t irq_status1);
+		uint32_t irq_status0, uint32_t irq_status1,
+		struct timeval *tv);
 	void (*process_axi_irq) (struct vfe_device *vfe_dev,
 		uint32_t irq_status0, uint32_t irq_status1,
 		struct timeval *tv);
@@ -76,7 +82,8 @@
 		uint32_t reload_mask);
 	void (*enable_wm) (struct vfe_device *vfe_dev,
 		uint8_t wm_idx, uint8_t enable);
-
+	void (*cfg_io_format) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream_request_cmd *stream_req_cmd);
 	void (*cfg_framedrop) (struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info);
 	void (*clear_framedrop) (struct vfe_device *vfe_dev,
@@ -118,8 +125,6 @@
 };
 
 struct msm_vfe_core_ops {
-	void (*epoch_irq) (struct vfe_device *vfe_dev,
-		uint32_t epoch_line0, uint32_t epoch_line1);
 	void (*reg_update) (struct vfe_device *vfe_dev, uint32_t update_mask);
 	long (*reset_hw) (struct vfe_device *vfe_dev);
 	int (*init_hw) (struct vfe_device *vfe_dev);
@@ -130,16 +135,16 @@
 	void (*update_camif_state) (struct vfe_device *vfe_dev,
 		enum msm_isp_camif_update_state update_state);
 	int (*get_platform_data) (struct vfe_device *vfe_dev);
+	void (*get_error_mask) (uint32_t *error_mask0, uint32_t *error_mask1);
+	void (*process_error_status) (struct vfe_device *vfe_dev);
 };
 struct msm_vfe_stats_ops {
+	int (*get_stats_idx) (enum msm_isp_stats_type stats_type);
 	void (*cfg_framedrop) (struct vfe_device *vfe_dev,
 		struct msm_vfe_stats_stream *stream_info);
 	void (*clear_framedrop) (struct vfe_device *vfe_dev,
 		struct msm_vfe_stats_stream *stream_info);
-	void (*cfg_comp_mask) (struct vfe_device *vfe_dev,
-		struct msm_vfe_stats_stream *stream_info);
-	void (*clear_comp_mask) (struct vfe_device *vfe_dev,
-		struct msm_vfe_stats_stream *stream_info);
+	void (*cfg_comp_mask) (struct vfe_device *vfe_dev);
 	void (*cfg_wm_irq_mask) (struct vfe_device *vfe_dev,
 		struct msm_vfe_stats_stream *stream_info);
 	void (*clear_wm_irq_mask) (struct vfe_device *vfe_dev,
@@ -152,20 +157,17 @@
 
 	void (*cfg_ub) (struct vfe_device *vfe_dev);
 
-	void (*stats_enable) (struct vfe_device *vfe_dev,
+	void (*enable_module) (struct vfe_device *vfe_dev,
 		uint32_t stats_mask, uint8_t enable);
 
 	void (*update_ping_pong_addr) (struct vfe_device *vfe_dev,
-		enum msm_isp_stats_type stats_type, uint32_t pingpong_status,
-		unsigned long paddr);
+		struct msm_vfe_stats_stream *stream_info,
+		uint32_t pingpong_status, unsigned long paddr);
 
 	uint32_t (*get_frame_id) (struct vfe_device *vfe_dev);
 	uint32_t (*get_wm_mask) (uint32_t irq_status0, uint32_t irq_status1);
 	uint32_t (*get_comp_mask) (uint32_t irq_status0, uint32_t irq_status1);
 	uint32_t (*get_pingpong_status) (struct vfe_device *vfe_dev);
-	uint32_t (*get_active_pingpong_idx) (uint32_t pingpong_status,
-				enum msm_isp_stats_type stats_type);
-
 };
 
 struct msm_vfe_ops {
@@ -176,8 +178,10 @@
 };
 
 struct msm_vfe_hardware_info {
+	int num_iommu_ctx;
 	struct msm_vfe_ops vfe_ops;
 	struct msm_vfe_axi_hardware_info *axi_hw_info;
+	struct msm_vfe_stats_hardware_info *stats_hw_info;
 	struct v4l2_subdev_internal_ops *subdev_internal_ops;
 	struct v4l2_subdev_ops *subdev_ops;
 };
@@ -188,7 +192,6 @@
 	uint8_t num_rdi_master;
 	uint8_t num_comp_mask;
 	uint32_t min_wm_ub;
-	uint8_t num_stats_comp_mask;
 };
 
 enum msm_vfe_axi_state {
@@ -231,9 +234,11 @@
 	uint8_t buf_divert;
 	enum msm_vfe_axi_stream_type stream_type;
 
+	uint32_t framedrop_period;
 	uint32_t framedrop_pattern;
 	uint32_t init_frame_drop;
 	uint32_t burst_frame_count;/*number of sof before burst stop*/
+	uint32_t num_burst_capture;/*number of frame to capture*/
 	uint8_t auto_trigger_stop;
 	uint8_t framedrop_update;
 };
@@ -242,6 +247,7 @@
 	uint32_t stream_handle;
 	uint32_t stream_composite_mask;
 };
+
 struct msm_vfe_src_info {
 	unsigned long frame_id;
 	uint8_t active;
@@ -250,40 +256,12 @@
 	enum msm_vfe_inputmux input_mux;
 };
 
-enum msm_vfe_stats_state {
-	STATE_AVALIABLE,
-	STATE_INACTIVE,
-	STATE_ACTIVE,
-	STATE_START_PENDING,
-	STATE_STOP_PENDING,
-	STATE_STOPPING,
-};
-struct msm_vfe_stats_stream {
-	uint32_t frame_id;
-	uint8_t enable;
-	enum msm_isp_stats_type stats_type;
-	int8_t comp_mask_index;
-	struct msm_isp_buffer *buf[2];
-	uint32_t session_id;
-	uint32_t stream_id;
-	uint32_t bufq_handle;
-	uint32_t stream_handle;
-	uint32_t framedrop_pattern;
-	uint8_t comp_flag;
-	uint8_t comp_idx;
-	enum msm_vfe_stats_state state;
-};
-
-struct msm_vfe_stats_composite_info {
-	uint32_t stats_mask;
-	uint8_t comp_flag;
-};
-
 enum msm_wm_ub_cfg_type {
 	MSM_WM_UB_CFG_DEFAULT,
 	MSM_WM_UB_EQUAL_SLICING,
 	MSM_WM_UB_CFG_MAX_NUM
 };
+
 struct msm_vfe_axi_shared_data {
 	struct msm_vfe_axi_hardware_info *hw_info;
 	struct msm_vfe_axi_stream stream_info[MAX_NUM_STREAM];
@@ -304,14 +282,44 @@
 	unsigned long event_mask;
 };
 
+struct msm_vfe_stats_hardware_info {
+	uint32_t stats_capability_mask;
+	uint32_t stats_ping_pong_offset;
+	uint8_t num_stats_type;
+	uint8_t num_stats_comp_mask;
+};
+
+enum msm_vfe_stats_state {
+	STATS_AVALIABLE,
+	STATS_INACTIVE,
+	STATS_ACTIVE,
+	STATS_START_PENDING,
+	STATS_STOP_PENDING,
+	STATS_STOPPING,
+};
+
+struct msm_vfe_stats_stream {
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t stream_handle;
+	enum msm_isp_stats_type stats_type;
+	enum msm_vfe_stats_state state;
+	uint32_t framedrop_pattern;
+	uint32_t irq_subsample_pattern;
+
+	struct msm_isp_buffer *buf[2];
+	uint32_t bufq_handle;
+};
+
 struct msm_vfe_stats_shared_data {
 	struct msm_vfe_stats_stream stream_info[MSM_ISP_STATS_MAX];
-	struct msm_vfe_stats_composite_info
-		composite_info[MAX_NUM_STATS_COMP_MASK];
+	enum msm_vfe_stats_pipeline_policy stats_pipeline_policy;
+	uint32_t comp_framedrop_pattern;
+	uint32_t comp_irq_subsample_pattern;
 	uint8_t num_active_stream;
-	uint8_t num_used_composite_mask;
 	uint16_t stream_handle_cnt;
 };
+
 struct msm_vfe_tasklet_queue_cmd {
 	struct list_head list;
 	uint32_t vfeInterruptStatus0;
@@ -322,6 +330,17 @@
 
 #define MSM_VFE_TASKLETQ_SIZE 200
 
+struct msm_vfe_error_info {
+	uint32_t error_mask0;
+	uint32_t error_mask1;
+	uint32_t violation_status;
+	uint32_t camif_status;
+	uint32_t stream_framedrop_count[MAX_NUM_STREAM];
+	uint32_t stats_framedrop_count[MSM_ISP_STATS_MAX];
+	uint32_t info_dump_frame_count;
+	uint32_t error_count;
+};
+
 struct vfe_device {
 	struct platform_device *pdev;
 	struct msm_sd_subdev subdev;
@@ -333,7 +352,7 @@
 	void __iomem *vfe_base;
 	void __iomem *vfe_vbif_base;
 
-	struct device *iommu_ctx;
+	struct device *iommu_ctx[MAX_IOMMU_CTX];
 
 	struct regulator *fs_vfe;
 	struct clk *vfe_clk[7];
@@ -358,6 +377,7 @@
 
 	struct msm_vfe_axi_shared_data axi_data;
 	struct msm_vfe_stats_shared_data stats_data;
+	struct msm_vfe_error_info error_info;
 	struct msm_isp_buf_mgr *buf_mgr;
 	int dump_reg;
 	uint32_t vfe_open_cnt;
diff --git a/drivers/media/video/msmb/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
similarity index 78%
rename from drivers/media/video/msmb/isp/msm_isp32.c
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index d8ac4e0..a522bd6 100644
--- a/drivers/media/video/msmb/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -11,12 +11,15 @@
  */
 
 #include <linux/module.h>
+#include <linux/platform_device.h>
+#include <mach/iommu.h>
 
 #include "msm_isp32.h"
 #include "msm_isp_util.h"
 #include "msm_isp_axi_util.h"
 #include "msm_isp.h"
 #include "msm.h"
+#include "msm_camera_io_util.h"
 
 #define VFE32_BURST_LEN 4
 #define VFE32_EQUAL_SLICE_UB 117
@@ -67,7 +70,7 @@
 };
 
 static struct msm_cam_clk_info msm_vfe32_clk_info[] = {
-	{"vfe_clk", 228570000},
+	{"vfe_clk", 266667000},
 	{"vfe_pclk", -1},
 	{"csi_vfe_clk", -1},
 };
@@ -155,147 +158,147 @@
 static void msm_vfe32_process_reset_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1)
 {
-	if (irq_status1 & (1 << 23))
+	if (irq_status1 & BIT(23))
 		complete(&vfe_dev->reset_complete);
 }
 
 static void msm_vfe32_process_halt_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1)
 {
-	if (irq_status1 & (1 << 24))
+	if (irq_status1 & BIT(24))
 		complete(&vfe_dev->halt_complete);
 }
 
 static void msm_vfe32_process_camif_irq(struct vfe_device *vfe_dev,
-	uint32_t irq_status0, uint32_t irq_status1)
+	uint32_t irq_status0, uint32_t irq_status1, struct timeval *tv)
 {
 	if (!(irq_status0 & 0x1F))
 		return;
 
-	if (irq_status0 & (1 << 0)) {
+	if (irq_status0 & BIT(0)) {
 		ISP_DBG("%s: PIX0 frame id: %lu\n", __func__,
-			   vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
-		msm_isp_update_framedrop_count(vfe_dev);
-		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id++;
+			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
+		msm_isp_sof_notify(vfe_dev, VFE_PIX_0, tv);
 	}
 }
 
-static void msm_vfe32_process_violation_irq(struct vfe_device *vfe_dev)
+static void msm_vfe32_process_stats_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1, struct timeval *tv)
 {
-	uint32_t violation_status;
-	violation_status = msm_camera_io_r(vfe_dev->vfe_base + 0x48);
+	/* todo: add stats specific code */
+	return;
+}
+
+static void msm_vfe32_process_violation_status(struct vfe_device *vfe_dev)
+{
+	uint32_t violation_status = vfe_dev->error_info.violation_status;
 	if (!violation_status)
 		return;
 
-	if (violation_status & (1 << 0))
+	if (violation_status & BIT(0))
 		pr_err("%s: black violation\n", __func__);
-	if (violation_status & (1 << 1))
+	if (violation_status & BIT(1))
 		pr_err("%s: rolloff violation\n", __func__);
-	if (violation_status & (1 << 2))
+	if (violation_status & BIT(2))
 		pr_err("%s: demux violation\n", __func__);
-	if (violation_status & (1 << 3))
+	if (violation_status & BIT(3))
 		pr_err("%s: demosaic violation\n", __func__);
-	if (violation_status & (1 << 4))
+	if (violation_status & BIT(4))
 		pr_err("%s: crop violation\n", __func__);
-	if (violation_status & (1 << 5))
+	if (violation_status & BIT(5))
 		pr_err("%s: scale violation\n", __func__);
-	if (violation_status & (1 << 6))
+	if (violation_status & BIT(6))
 		pr_err("%s: wb violation\n", __func__);
-	if (violation_status & (1 << 7))
+	if (violation_status & BIT(7))
 		pr_err("%s: clf violation\n", __func__);
-	if (violation_status & (1 << 8))
+	if (violation_status & BIT(8))
 		pr_err("%s: matrix violation\n", __func__);
-	if (violation_status & (1 << 9))
+	if (violation_status & BIT(9))
 		pr_err("%s: rgb lut violation\n", __func__);
-	if (violation_status & (1 << 10))
+	if (violation_status & BIT(10))
 		pr_err("%s: la violation\n", __func__);
-	if (violation_status & (1 << 11))
+	if (violation_status & BIT(11))
 		pr_err("%s: chroma enhance violation\n", __func__);
-	if (violation_status & (1 << 12))
+	if (violation_status & BIT(12))
 		pr_err("%s: chroma supress mce violation\n", __func__);
-	if (violation_status & (1 << 13))
+	if (violation_status & BIT(13))
 		pr_err("%s: skin enhance violation\n", __func__);
-	if (violation_status & (1 << 14))
+	if (violation_status & BIT(14))
 		pr_err("%s: asf violation\n", __func__);
-	if (violation_status & (1 << 15))
+	if (violation_status & BIT(15))
 		pr_err("%s: scale y violation\n", __func__);
-	if (violation_status & (1 << 16))
+	if (violation_status & BIT(16))
 		pr_err("%s: scale cbcr violation\n", __func__);
-	if (violation_status & (1 << 17))
+	if (violation_status & BIT(17))
 		pr_err("%s: chroma subsample violation\n", __func__);
-	if (violation_status & (1 << 18))
+	if (violation_status & BIT(18))
 		pr_err("%s: framedrop enc y violation\n", __func__);
-	if (violation_status & (1 << 19))
+	if (violation_status & BIT(19))
 		pr_err("%s: framedrop enc cbcr violation\n", __func__);
-	if (violation_status & (1 << 20))
+	if (violation_status & BIT(20))
 		pr_err("%s: framedrop view y violation\n", __func__);
-	if (violation_status & (1 << 21))
+	if (violation_status & BIT(21))
 		pr_err("%s: framedrop view cbcr violation\n", __func__);
-	if (violation_status & (1 << 22))
+	if (violation_status & BIT(22))
 		pr_err("%s: realign buf y violation\n", __func__);
-	if (violation_status & (1 << 23))
+	if (violation_status & BIT(23))
 		pr_err("%s: realign buf cb violation\n", __func__);
-	if (violation_status & (1 << 24))
+	if (violation_status & BIT(24))
 		pr_err("%s: realign buf cr violation\n", __func__);
 }
 
-static void msm_vfe32_process_error_irq(struct vfe_device *vfe_dev,
-	uint32_t irq_status0, uint32_t irq_status1)
+static void msm_vfe32_process_error_status(struct vfe_device *vfe_dev)
 {
-	uint32_t camif_status;
-	if (!(irq_status1 & 0x7FFFFF))
-		return;
+	uint32_t error_status1 = vfe_dev->error_info.error_mask1;
 
-	if (irq_status1 & (1 << 0)) {
-		camif_status = msm_camera_io_r(vfe_dev->vfe_base + 0x204);
+	if (error_status1 & BIT(0))
 		pr_err("%s: camif error status: 0x%x\n",
-			__func__, camif_status);
-	}
-	if (irq_status1 & (1 << 1))
+			__func__, vfe_dev->error_info.camif_status);
+	if (error_status1 & BIT(1))
 		pr_err("%s: stats bhist overwrite\n", __func__);
-	if (irq_status1 & (1 << 2))
+	if (error_status1 & BIT(2))
 		pr_err("%s: stats cs overwrite\n", __func__);
-	if (irq_status1 & (1 << 3))
+	if (error_status1 & BIT(3))
 		pr_err("%s: stats ihist overwrite\n", __func__);
-	if (irq_status1 & (1 << 4))
+	if (error_status1 & BIT(4))
 		pr_err("%s: realign buf y overflow\n", __func__);
-	if (irq_status1 & (1 << 5))
+	if (error_status1 & BIT(5))
 		pr_err("%s: realign buf cb overflow\n", __func__);
-	if (irq_status1 & (1 << 6))
+	if (error_status1 & BIT(6))
 		pr_err("%s: realign buf cr overflow\n", __func__);
-	if (irq_status1 & (1 << 7)) {
+	if (error_status1 & BIT(7)) {
 		pr_err("%s: violation\n", __func__);
-		msm_vfe32_process_violation_irq(vfe_dev);
+		msm_vfe32_process_violation_status(vfe_dev);
 	}
-	if (irq_status1 & (1 << 8))
+	if (error_status1 & BIT(8))
 		pr_err("%s: image master 0 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 9))
+	if (error_status1 & BIT(9))
 		pr_err("%s: image master 1 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 10))
+	if (error_status1 & BIT(10))
 		pr_err("%s: image master 2 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 11))
+	if (error_status1 & BIT(11))
 		pr_err("%s: image master 3 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 12))
+	if (error_status1 & BIT(12))
 		pr_err("%s: image master 4 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 13))
+	if (error_status1 & BIT(13))
 		pr_err("%s: image master 5 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 14))
+	if (error_status1 & BIT(14))
 		pr_err("%s: image master 6 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 15))
+	if (error_status1 & BIT(15))
 		pr_err("%s: status ae/bg bus overflow\n", __func__);
-	if (irq_status1 & (1 << 16))
+	if (error_status1 & BIT(16))
 		pr_err("%s: status af/bf bus overflow\n", __func__);
-	if (irq_status1 & (1 << 17))
+	if (error_status1 & BIT(17))
 		pr_err("%s: status awb bus overflow\n", __func__);
-	if (irq_status1 & (1 << 18))
+	if (error_status1 & BIT(18))
 		pr_err("%s: status rs bus overflow\n", __func__);
-	if (irq_status1 & (1 << 19))
+	if (error_status1 & BIT(19))
 		pr_err("%s: status cs bus overflow\n", __func__);
-	if (irq_status1 & (1 << 20))
+	if (error_status1 & BIT(20))
 		pr_err("%s: status ihist bus overflow\n", __func__);
-	if (irq_status1 & (1 << 21))
+	if (error_status1 & BIT(21))
 		pr_err("%s: status skin bhist bus overflow\n", __func__);
-	if (irq_status1 & (1 << 22))
+	if (error_status1 & BIT(22))
 		pr_err("%s: axi error\n", __func__);
 }
 
@@ -307,10 +310,18 @@
 	msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x24);
 	msm_camera_io_w(*irq_status1, vfe_dev->vfe_base + 0x28);
 	msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x18);
+
+	if (*irq_status1 & BIT(0))
+		vfe_dev->error_info.camif_status =
+			msm_camera_io_r(vfe_dev->vfe_base + 0x204);
+
+	if (*irq_status1 & BIT(7))
+		vfe_dev->error_info.violation_status |=
+			msm_camera_io_r(vfe_dev->vfe_base + 0x7B4);
 }
 
 static void msm_vfe32_process_reg_update(struct vfe_device *vfe_dev,
-	uint32_t irq_status0, uint32_t irq_status1)
+	uint32_t irq_status0, uint32_t irq_status1, struct timeval *tv)
 {
 	if (!(irq_status0 & 0x20) && !(irq_status1 & 0x1C000000))
 		return;
@@ -319,6 +330,7 @@
 		msm_isp_axi_stream_update(vfe_dev);
 
 	msm_isp_update_framedrop_reg(vfe_dev);
+	msm_isp_update_error_frame_count(vfe_dev);
 
 	return;
 }
@@ -369,7 +381,7 @@
 	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x34);
 
 	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
-	irq_mask |= 1 << (comp_mask_index + 21);
+	irq_mask |= BIT(comp_mask_index + 21);
 	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
 }
 
@@ -384,7 +396,7 @@
 	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x34);
 
 	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
-	irq_mask &= ~(1 << (comp_mask_index + 21));
+	irq_mask &= ~BIT(comp_mask_index + 21);
 	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
 }
 
@@ -393,7 +405,7 @@
 {
 	uint32_t irq_mask;
 	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
-	irq_mask |= 1 << (stream_info->wm[0] + 6);
+	irq_mask |= BIT(stream_info->wm[0] + 6);
 	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
 }
 
@@ -402,30 +414,34 @@
 {
 	uint32_t irq_mask;
 	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
-	irq_mask &= ~(1 << (stream_info->wm[0] + 6));
+	irq_mask &= ~BIT(stream_info->wm[0] + 6);
 	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
 }
 
 static void msm_vfe32_cfg_framedrop(struct vfe_device *vfe_dev,
 	struct msm_vfe_axi_stream *stream_info)
 {
-	uint32_t framedrop_pattern = 0;
+	uint32_t framedrop_pattern = 0, framedrop_period = 0;
 
-	if (stream_info->init_frame_drop == 0)
+	if (stream_info->init_frame_drop == 0) {
 		framedrop_pattern = stream_info->framedrop_pattern;
+		framedrop_period = stream_info->framedrop_period;
+	}
 
 	if (stream_info->stream_type == BURST_STREAM &&
-		stream_info->burst_frame_count == 0)
+		stream_info->burst_frame_count == 0) {
 		framedrop_pattern = 0;
+		framedrop_period = 0;
+	}
 
 	if (stream_info->stream_src == PIX_ENCODER) {
-		msm_camera_io_w(0x1F, vfe_dev->vfe_base + 0x504);
-		msm_camera_io_w(0x1F, vfe_dev->vfe_base + 0x508);
+		msm_camera_io_w(framedrop_period, vfe_dev->vfe_base + 0x504);
+		msm_camera_io_w(framedrop_period, vfe_dev->vfe_base + 0x508);
 		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x50C);
 		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x510);
 	} else if (stream_info->stream_src == PIX_VIEWFINDER) {
-		msm_camera_io_w(0x1F, vfe_dev->vfe_base + 0x514);
-		msm_camera_io_w(0x1F, vfe_dev->vfe_base + 0x518);
+		msm_camera_io_w(framedrop_period, vfe_dev->vfe_base + 0x514);
+		msm_camera_io_w(framedrop_period, vfe_dev->vfe_base + 0x518);
 		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x51C);
 		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x520);
 	}
@@ -451,14 +467,10 @@
 	struct msm_vfe_camif_cfg *camif_cfg = &pix_cfg->camif_cfg;
 	uint32_t val;
 
-	first_pixel = camif_cfg->left_crop;
-	last_pixel = camif_cfg->pixels_per_line -
-					 camif_cfg->left_crop -
-					 camif_cfg->right_crop;
-	first_line = camif_cfg->left_crop;
-	last_line = camif_cfg->lines_per_frame -
-					 camif_cfg->top_crop -
-					 camif_cfg->bottom_crop;
+	first_pixel = camif_cfg->first_pixel;
+	last_pixel = camif_cfg->last_pixel;
+	first_line = camif_cfg->first_line;
+	last_line = camif_cfg->last_line;
 
 	msm_camera_io_w(pix_cfg->input_mux << 16 | pix_cfg->pixel_pattern,
 					vfe_dev->vfe_base + 0x14);
@@ -572,14 +584,13 @@
 	rdi_reg_cfg = msm_camera_io_r(
 		vfe_dev->vfe_base + VFE32_RDI_MN_BASE(rdi_master));
 	rdi_reg_cfg &= ~((0xF << VFE32_RDI_MN_SEL_SHIFT(rdi_master)) |
-		(0x1 << VFE32_RDI_MN_FB_SHIFT(rdi_master)));
+		BIT(VFE32_RDI_MN_FB_SHIFT(rdi_master)));
 	rdi_reg_cfg |= (plane_cfg->rdi_cid <<
 		VFE32_RDI_MN_SEL_SHIFT(rdi_master) |
 		(stream_cfg_cmd->frame_base <<
 			VFE32_RDI_MN_FB_SHIFT(rdi_master)));
-	msm_camera_io_w(rdi_reg_cfg,
-					vfe_dev->vfe_base +
-					VFE32_RDI_MN_BASE(rdi_master));
+	msm_camera_io_w(rdi_reg_cfg, vfe_dev->vfe_base +
+		VFE32_RDI_MN_BASE(rdi_master));
 }
 
 static void msm_vfe32_axi_cfg_wm_xbar_reg(
@@ -610,7 +621,7 @@
 				xbar_cfg |= 0x3 << 3; /*PAIR_STREAM_SWAP_CTRL*/
 				break;
 			}
-			xbar_cfg |= 0x1 << 1; /*PAIR_STREAM_EN*/
+			xbar_cfg |= BIT(1); /*PAIR_STREAM_EN*/
 		}
 		if (stream_cfg_cmd->stream_src == PIX_VIEWFINDER)
 			xbar_cfg |= 0x1; /*VIEW_STREAM_EN*/
@@ -675,7 +686,7 @@
 {
 	uint32_t halt_mask;
 	halt_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x20);
-	halt_mask |= (1 << 24);
+	halt_mask |= BIT(24);
 	msm_camera_io_w_mb(halt_mask, vfe_dev->vfe_base + 0x20);
 	init_completion(&vfe_dev->halt_complete);
 	/*TD: Need to fix crashes with this*/
@@ -701,6 +712,75 @@
 	return msm_camera_io_r(vfe_dev->vfe_base + 0x180);
 }
 
+static int msm_vfe32_get_stats_idx(enum msm_isp_stats_type stats_type)
+{
+	return 0;
+}
+
+static void msm_vfe32_stats_cfg_comp_mask(struct vfe_device *vfe_dev)
+{
+	return;
+}
+
+static void msm_vfe32_stats_cfg_wm_irq_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+	return;
+}
+
+static void msm_vfe32_stats_clear_wm_irq_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+	return;
+}
+
+static void msm_vfe32_stats_cfg_wm_reg(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+	return;
+}
+
+static void msm_vfe32_stats_clear_wm_reg(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+	return;
+}
+
+static void msm_vfe32_stats_cfg_ub(struct vfe_device *vfe_dev)
+{
+	return;
+}
+
+static void msm_vfe32_stats_enable_module(struct vfe_device *vfe_dev,
+	uint32_t stats_mask, uint8_t enable)
+{
+	return;
+}
+
+static void msm_vfe32_stats_update_ping_pong_addr(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info, uint32_t pingpong_status,
+	unsigned long paddr)
+{
+	return;
+}
+
+static uint32_t msm_vfe32_stats_get_wm_mask(uint32_t irq_status0,
+	uint32_t irq_status1)
+{
+	return 0;
+}
+
+static uint32_t msm_vfe32_stats_get_comp_mask(uint32_t irq_status0,
+	uint32_t irq_status1)
+{
+	return 0;
+}
+
+static uint32_t msm_vfe32_stats_get_frame_id(struct vfe_device *vfe_dev)
+{
+	return 0;
+}
+
 static int msm_vfe32_get_platform_data(struct vfe_device *vfe_dev)
 {
 	int rc = 0;
@@ -742,12 +822,18 @@
 		rc = -ENODEV;
 		goto vfe_no_resource;
 	}
-	vfe_dev->num_ctx = 2;
 
 vfe_no_resource:
 	return rc;
 }
 
+static void msm_vfe32_get_error_mask(uint32_t *error_mask0,
+	uint32_t *error_mask1)
+{
+	*error_mask0 = 0x00000000;
+	*error_mask1 = 0x007FFFFF;
+}
+
 struct msm_vfe_axi_hardware_info msm_vfe32_axi_hw_info = {
 	.num_wm = 7,
 	.num_comp_mask = 3,
@@ -771,16 +857,16 @@
 };
 
 struct msm_vfe_hardware_info vfe32_hw_info = {
+	.num_iommu_ctx = 2,
 	.vfe_ops = {
 		.irq_ops = {
 			.read_irq_status = msm_vfe32_read_irq_status,
 			.process_camif_irq = msm_vfe32_process_camif_irq,
 			.process_reset_irq = msm_vfe32_process_reset_irq,
 			.process_halt_irq = msm_vfe32_process_halt_irq,
-			.process_reset_irq = msm_vfe32_process_reset_irq,
-			.process_error_irq = msm_vfe32_process_error_irq,
 			.process_reg_update = msm_vfe32_process_reg_update,
 			.process_axi_irq = msm_isp_process_axi_irq,
+			.process_stats_irq = msm_vfe32_process_stats_irq,
 		},
 		.axi_ops = {
 			.reload_wm = msm_vfe32_axi_reload_wm,
@@ -813,6 +899,24 @@
 			.init_hw_reg = msm_vfe32_init_hardware_reg,
 			.release_hw = msm_vfe32_release_hardware,
 			.get_platform_data = msm_vfe32_get_platform_data,
+			.get_error_mask = msm_vfe32_get_error_mask,
+			.process_error_status = msm_vfe32_process_error_status,
+		},
+		.stats_ops = {
+			.get_stats_idx = msm_vfe32_get_stats_idx,
+			.cfg_comp_mask = msm_vfe32_stats_cfg_comp_mask,
+			.cfg_wm_irq_mask = msm_vfe32_stats_cfg_wm_irq_mask,
+			.clear_wm_irq_mask = msm_vfe32_stats_clear_wm_irq_mask,
+			.cfg_wm_reg = msm_vfe32_stats_cfg_wm_reg,
+			.clear_wm_reg = msm_vfe32_stats_clear_wm_reg,
+			.cfg_ub = msm_vfe32_stats_cfg_ub,
+			.enable_module = msm_vfe32_stats_enable_module,
+			.update_ping_pong_addr =
+				msm_vfe32_stats_update_ping_pong_addr,
+			.get_comp_mask = msm_vfe32_stats_get_comp_mask,
+			.get_wm_mask = msm_vfe32_stats_get_wm_mask,
+			.get_frame_id = msm_vfe32_stats_get_frame_id,
+			.get_pingpong_status = msm_vfe32_get_pingpong_status,
 		},
 	},
 	.axi_hw_info = &msm_vfe32_axi_hw_info,
diff --git a/drivers/media/video/msmb/isp/msm_isp32.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.h
similarity index 100%
rename from drivers/media/video/msmb/isp/msm_isp32.h
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp32.h
diff --git a/drivers/media/video/msmb/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
similarity index 73%
rename from drivers/media/video/msmb/isp/msm_isp40.c
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 6c90763..dba59d7 100644
--- a/drivers/media/video/msmb/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -29,8 +29,9 @@
 #define CDBG(fmt, args...) do { } while (0)
 #endif
 
-#define VFE40_BURST_LEN 4
-#define VFE40_EQUAL_SLICE_UB 117
+#define VFE40_BURST_LEN 3
+#define VFE40_UB_SIZE 1536
+#define VFE40_EQUAL_SLICE_UB 304
 #define VFE40_WM_BASE(idx) (0x6C + 0x24 * idx)
 #define VFE40_RDI_BASE(idx) (0x2E8 + 0x4 * idx)
 #define VFE40_RDI_MN_BASE(m) (0x2E8 + 0x4 * m/3)
@@ -41,22 +42,39 @@
 #define VFE40_PING_PONG_BASE(wm, ping_pong) \
 	(VFE40_WM_BASE(wm) + 0x4 * (1 + (~(ping_pong >> wm) & 0x1)))
 
-#define VFE40_VBIF_CLKON        0x4
-#define VFE40_VBIF_IN_RD_LIM_CONF0    0xB0
-#define VFE40_VBIF_IN_RD_LIM_CONF1    0xB4
-#define VFE40_VBIF_IN_RD_LIM_CONF2    0xB8
-#define VFE40_VBIF_IN_WR_LIM_CONF0    0xC0
-#define VFE40_VBIF_IN_WR_LIM_CONF1    0xC4
-#define VFE40_VBIF_IN_WR_LIM_CONF2    0xC8
-#define VFE40_VBIF_OUT_RD_LIM_CONF0   0xD0
-#define VFE40_VBIF_OUT_WR_LIM_CONF0   0xD4
-#define VFE40_VBIF_DDR_OUT_MAX_BURST  0xD8
-#define VFE40_VBIF_ARB_CTL        0xF0
-#define VFE40_VBIF_DDR_ARB_CONF0    0xF4
-#define VFE40_VBIF_DDR_ARB_CONF1    0xF8
-#define VFE40_VBIF_ROUND_ROBIN_QOS_ARB  0x124
-#define VFE40_VBIF_OUT_AXI_AOOO_EN    0x178
-#define VFE40_VBIF_OUT_AXI_AOOO     0x17C
+#define VFE40_NUM_STATS_TYPE 8
+#define VFE40_STATS_PING_PONG_OFFSET 8
+#define VFE40_STATS_BASE(idx) (0x168 + 0x18 * idx)
+#define VFE40_STATS_PING_PONG_BASE(idx, ping_pong) \
+	(VFE40_STATS_BASE(idx) + 0x4 * \
+	(~(ping_pong >> (idx + VFE40_STATS_PING_PONG_OFFSET)) & 0x1))
+
+#define VFE40_VBIF_CLKON                    0x4
+#define VFE40_VBIF_IN_RD_LIM_CONF0          0xB0
+#define VFE40_VBIF_IN_RD_LIM_CONF1          0xB4
+#define VFE40_VBIF_IN_RD_LIM_CONF2          0xB8
+#define VFE40_VBIF_IN_WR_LIM_CONF0          0xC0
+#define VFE40_VBIF_IN_WR_LIM_CONF1          0xC4
+#define VFE40_VBIF_IN_WR_LIM_CONF2          0xC8
+#define VFE40_VBIF_OUT_RD_LIM_CONF0         0xD0
+#define VFE40_VBIF_OUT_WR_LIM_CONF0         0xD4
+#define VFE40_VBIF_DDR_OUT_MAX_BURST        0xD8
+#define VFE40_VBIF_OCMEM_OUT_MAX_BURST      0xDC
+#define VFE40_VBIF_ARB_CTL                  0xF0
+#define VFE40_VBIF_ROUND_ROBIN_QOS_ARB      0x124
+#define VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF0   0x160
+#define VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF1   0x164
+#define VFE40_VBIF_OUT_AXI_AOOO_EN          0x178
+#define VFE40_VBIF_OUT_AXI_AOOO             0x17C
+
+#define VFE40_BUS_BDG_QOS_CFG_0     0x000002C4
+#define VFE40_BUS_BDG_QOS_CFG_1     0x000002C8
+#define VFE40_BUS_BDG_QOS_CFG_2     0x000002CC
+#define VFE40_BUS_BDG_QOS_CFG_3     0x000002D0
+#define VFE40_BUS_BDG_QOS_CFG_4     0x000002D4
+#define VFE40_BUS_BDG_QOS_CFG_5     0x000002D8
+#define VFE40_BUS_BDG_QOS_CFG_6     0x000002DC
+#define VFE40_BUS_BDG_QOS_CFG_7     0x000002E0
 
 /*Temporary use fixed bus vectors in VFE */
 static struct msm_bus_vectors msm_vfe40_init_vectors[] = {
@@ -104,42 +122,56 @@
 	{"alt_bus_clk", -1},
 };
 
+static void msm_vfe40_init_qos_parms(struct vfe_device *vfe_dev)
+{
+	void __iomem *vfebase = vfe_dev->vfe_base;
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_3);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_4);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
+	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
+	msm_camera_io_w(0x0002AAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
+}
+
 static void msm_vfe40_init_vbif_parms(
 	void __iomem *vfe_vbif_base)
 {
-	msm_camera_io_w_mb(0x1,
+	msm_camera_io_w(0x1,
 		vfe_vbif_base + VFE40_VBIF_CLKON);
-	msm_camera_io_w_mb(0x1,
-		vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
-	msm_camera_io_w_mb(0xFFFF,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
-	msm_camera_io_w_mb(0xFFFFFFFF,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
-
-	msm_camera_io_w_mb(0x10101010,
+	msm_camera_io_w(0x01010101,
 		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
-	msm_camera_io_w_mb(0x10101010,
+	msm_camera_io_w(0x01010101,
 		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
-	msm_camera_io_w_mb(0x10101010,
+	msm_camera_io_w(0x10010110,
 		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
-	msm_camera_io_w_mb(0x10101010,
+	msm_camera_io_w(0x10101010,
 		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
-	msm_camera_io_w_mb(0x10101010,
+	msm_camera_io_w(0x10101010,
 		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
-	msm_camera_io_w_mb(0x10101010,
+	msm_camera_io_w(0x10101010,
 		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
-	msm_camera_io_w_mb(0x00001010,
+	msm_camera_io_w(0x00001010,
 		vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
-	msm_camera_io_w_mb(0x00001010,
+	msm_camera_io_w(0x00001010,
 		vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
-	msm_camera_io_w_mb(0x00000707,
+	msm_camera_io_w(0x00000707,
 		vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
-	msm_camera_io_w_mb(0x00000030,
+	msm_camera_io_w(0x00000707,
+		vfe_vbif_base + VFE40_VBIF_OCMEM_OUT_MAX_BURST);
+	msm_camera_io_w(0x00000030,
 		vfe_vbif_base + VFE40_VBIF_ARB_CTL);
-	msm_camera_io_w_mb(0x04210842,
-		vfe_vbif_base + VFE40_VBIF_DDR_ARB_CONF0);
-	msm_camera_io_w_mb(0x04210842,
-	vfe_vbif_base + VFE40_VBIF_DDR_ARB_CONF1);
+	msm_camera_io_w(0x00000FFF,
+		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
+	msm_camera_io_w(0x0FFF0FFF,
+		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
+	msm_camera_io_w(0x00000001,
+		vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
+	msm_camera_io_w(0x22222222,
+		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF0);
+	msm_camera_io_w(0x00002222,
+		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF1);
 }
 
 static int msm_vfe40_init_hardware(struct vfe_device *vfe_dev)
@@ -192,6 +224,7 @@
 		goto irq_req_failed;
 	}
 
+	msm_vfe40_init_qos_parms(vfe_dev);
 	msm_vfe40_init_vbif_parms(vfe_dev->vfe_vbif_base);
 	return rc;
 irq_req_failed:
@@ -227,8 +260,9 @@
 {
 	/* CGC_OVERRIDE */
 	msm_camera_io_w(0x3FFFFFFF, vfe_dev->vfe_base + 0x14);
+	msm_camera_io_w(0xC001FF7F, vfe_dev->vfe_base + 0x974);
 	/* BUS_CFG */
-	msm_camera_io_w(0x00000001, vfe_dev->vfe_base + 0x50);
+	msm_camera_io_w(0x10000001, vfe_dev->vfe_base + 0x50);
 	msm_camera_io_w(0x800000F3, vfe_dev->vfe_base + 0x28);
 	msm_camera_io_w_mb(0xFEFFFFFF, vfe_dev->vfe_base + 0x2C);
 	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x30);
@@ -250,32 +284,32 @@
 }
 
 static void msm_vfe40_process_camif_irq(struct vfe_device *vfe_dev,
-	uint32_t irq_status0, uint32_t irq_status1)
+	uint32_t irq_status0, uint32_t irq_status1, struct timeval *tv)
 {
 	if (!(irq_status0 & 0xF))
 		return;
 
-	if (vfe_dev->hw_info->vfe_ops.core_ops.epoch_irq) {
-		if (irq_status0 & (1 << 2)) {
-			ISP_DBG("%s: EPOCH0 IRQ, PIX0_frameid = 0x%lu\n",
-				__func__,
-				vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
-			msm_isp_new_frame_notify(vfe_dev, VFE_PIX_0);
-		}
-	} else {
-		if (irq_status0 & (1 << 0)) {
-			ISP_DBG("%s: SOF: PIX0 frame id: %lu\n", __func__,
-			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
-			msm_isp_new_frame_notify(vfe_dev, VFE_PIX_0);
+	if (irq_status0 & (1 << 0)) {
+		ISP_DBG("%s: SOF IRQ\n", __func__);
+		if (vfe_dev->axi_data.src_info[VFE_PIX_0].raw_stream_count > 0
+			&& vfe_dev->axi_data.src_info[VFE_PIX_0].
+			pix_stream_count == 0) {
+			msm_isp_sof_notify(vfe_dev, VFE_PIX_0, tv);
+			msm_isp_update_framedrop_reg(vfe_dev);
 		}
 	}
+	if (irq_status0 & (1 << 1))
+		ISP_DBG("%s: EOF IRQ\n", __func__);
+	if (irq_status0 & (1 << 2))
+		ISP_DBG("%s: EPOCH0 IRQ\n", __func__);
+	if (irq_status0 & (1 << 3))
+		ISP_DBG("%s: EPOCH1 IRQ\n", __func__);
 }
 
-static void msm_vfe40_process_violation_irq(
+static void msm_vfe40_process_violation_status(
 	struct vfe_device *vfe_dev)
 {
-	uint32_t violation_status;
-	violation_status = msm_camera_io_r(vfe_dev->vfe_base + 0x48);
+	uint32_t violation_status = vfe_dev->error_info.violation_status;
 	if (!violation_status)
 		return;
 
@@ -337,63 +371,57 @@
 		pr_err("%s: realign buf cr violation\n", __func__);
 }
 
-static void msm_vfe40_process_error_irq(struct vfe_device *vfe_dev,
-	uint32_t irq_status0, uint32_t irq_status1)
+static void msm_vfe40_process_error_status(struct vfe_device *vfe_dev)
 {
-	uint32_t camif_status;
-	if (!(irq_status1 & 0x00FFFEFF))
-		return;
-
-	if (irq_status1 & (1 << 0)) {
-		camif_status = msm_camera_io_r(vfe_dev->vfe_base + 0x31C);
+	uint32_t error_status1 = vfe_dev->error_info.error_mask1;
+	if (error_status1 & (1 << 0))
 		pr_err("%s: camif error status: 0x%x\n",
-			__func__, camif_status);
-	}
-	if (irq_status1 & (1 << 1))
+			__func__, vfe_dev->error_info.camif_status);
+	if (error_status1 & (1 << 1))
 		pr_err("%s: stats bhist overwrite\n", __func__);
-	if (irq_status1 & (1 << 2))
+	if (error_status1 & (1 << 2))
 		pr_err("%s: stats cs overwrite\n", __func__);
-	if (irq_status1 & (1 << 3))
+	if (error_status1 & (1 << 3))
 		pr_err("%s: stats ihist overwrite\n", __func__);
-	if (irq_status1 & (1 << 4))
+	if (error_status1 & (1 << 4))
 		pr_err("%s: realign buf y overflow\n", __func__);
-	if (irq_status1 & (1 << 5))
+	if (error_status1 & (1 << 5))
 		pr_err("%s: realign buf cb overflow\n", __func__);
-	if (irq_status1 & (1 << 6))
+	if (error_status1 & (1 << 6))
 		pr_err("%s: realign buf cr overflow\n", __func__);
-	if (irq_status1 & (1 << 7)) {
+	if (error_status1 & (1 << 7)) {
 		pr_err("%s: violation\n", __func__);
-		msm_vfe40_process_violation_irq(vfe_dev);
+		msm_vfe40_process_violation_status(vfe_dev);
 	}
-	if (irq_status1 & (1 << 9))
+	if (error_status1 & (1 << 9))
 		pr_err("%s: image master 0 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 10))
+	if (error_status1 & (1 << 10))
 		pr_err("%s: image master 1 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 11))
+	if (error_status1 & (1 << 11))
 		pr_err("%s: image master 2 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 12))
+	if (error_status1 & (1 << 12))
 		pr_err("%s: image master 3 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 13))
+	if (error_status1 & (1 << 13))
 		pr_err("%s: image master 4 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 14))
+	if (error_status1 & (1 << 14))
 		pr_err("%s: image master 5 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 15))
+	if (error_status1 & (1 << 15))
 		pr_err("%s: image master 6 bus overflow\n", __func__);
-	if (irq_status1 & (1 << 16))
+	if (error_status1 & (1 << 16))
 		pr_err("%s: status be bus overflow\n", __func__);
-	if (irq_status1 & (1 << 17))
+	if (error_status1 & (1 << 17))
 		pr_err("%s: status bg bus overflow\n", __func__);
-	if (irq_status1 & (1 << 18))
+	if (error_status1 & (1 << 18))
 		pr_err("%s: status bf bus overflow\n", __func__);
-	if (irq_status1 & (1 << 19))
+	if (error_status1 & (1 << 19))
 		pr_err("%s: status awb bus overflow\n", __func__);
-	if (irq_status1 & (1 << 20))
+	if (error_status1 & (1 << 20))
 		pr_err("%s: status rs bus overflow\n", __func__);
-	if (irq_status1 & (1 << 21))
+	if (error_status1 & (1 << 21))
 		pr_err("%s: status cs bus overflow\n", __func__);
-	if (irq_status1 & (1 << 22))
+	if (error_status1 & (1 << 22))
 		pr_err("%s: status ihist bus overflow\n", __func__);
-	if (irq_status1 & (1 << 23))
+	if (error_status1 & (1 << 23))
 		pr_err("%s: status skin bhist bus overflow\n", __func__);
 }
 
@@ -405,49 +433,43 @@
 	msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x30);
 	msm_camera_io_w(*irq_status1, vfe_dev->vfe_base + 0x34);
 	msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x24);
+
+	if (*irq_status1 & (1 << 0))
+		vfe_dev->error_info.camif_status =
+		msm_camera_io_r(vfe_dev->vfe_base + 0x31C);
+
+	if (*irq_status1 & (1 << 7))
+		vfe_dev->error_info.violation_status |=
+		msm_camera_io_r(vfe_dev->vfe_base + 0x48);
+
 }
 
 static void msm_vfe40_process_reg_update(struct vfe_device *vfe_dev,
-	uint32_t irq_status0, uint32_t irq_status1)
+	uint32_t irq_status0, uint32_t irq_status1, struct timeval *tv)
 {
 	uint32_t update_mask = 0xF;
-
 	if (!(irq_status0 & 0xF0))
 		return;
 
+	if (irq_status0 & BIT(4))
+		msm_isp_sof_notify(vfe_dev, VFE_PIX_0, tv);
+	if (irq_status0 & BIT(5))
+		msm_isp_sof_notify(vfe_dev, VFE_RAW_0, tv);
+	if (irq_status0 & BIT(6))
+		msm_isp_sof_notify(vfe_dev, VFE_RAW_1, tv);
+	if (irq_status0 & BIT(7))
+		msm_isp_sof_notify(vfe_dev, VFE_RAW_2, tv);
+
 	if (vfe_dev->axi_data.stream_update)
 		msm_isp_axi_stream_update(vfe_dev);
 	msm_isp_update_framedrop_reg(vfe_dev);
+	msm_isp_update_error_frame_count(vfe_dev);
 
 	vfe_dev->hw_info->vfe_ops.core_ops.
 		reg_update(vfe_dev, update_mask);
 	return;
 }
 
-static void msm_vfe40_epoch_irq_enb(struct vfe_device *vfe_dev,
-	uint32_t epoch_line0, uint32_t epoch_line1)
-{
-	uint32_t irq_mask = 0;
-	uint32_t epoch_val = 0;
-	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
-	if (epoch_line0 > 0) {
-		irq_mask |= 0x4;
-		epoch_val |= (epoch_line0 - 1) << 16;
-	} else {
-		irq_mask &= ~0x4;
-		epoch_val &= 0xFFFF;
-	}
-	if (epoch_line1 > 0) {
-		irq_mask |= 0x8;
-		epoch_val |= epoch_line1 - 1;
-	} else {
-		irq_mask &= ~0x8;
-		epoch_val &= 0xFFFF0000;
-	}
-	msm_camera_io_w_mb(epoch_val, vfe_dev->vfe_base + 0x318);
-	msm_camera_io_w_mb(irq_mask, vfe_dev->vfe_base + 0x28);
-}
-
 static void msm_vfe40_reg_update(
 	struct vfe_device *vfe_dev, uint32_t update_mask)
 {
@@ -534,19 +556,29 @@
 static void msm_vfe40_cfg_framedrop(struct vfe_device *vfe_dev,
 	struct msm_vfe_axi_stream *stream_info)
 {
-	uint32_t i;
-	uint32_t framedrop_pattern = 0;
+	uint32_t i, temp;
+	uint32_t framedrop_pattern = 0, framedrop_period = 0;
 
-	if (stream_info->init_frame_drop == 0)
+	if (stream_info->init_frame_drop == 0) {
 		framedrop_pattern = stream_info->framedrop_pattern;
+		framedrop_period = stream_info->framedrop_period;
+	}
 
 	if (stream_info->stream_type == BURST_STREAM &&
-			stream_info->burst_frame_count == 0)
+			stream_info->burst_frame_count == 0) {
 		framedrop_pattern = 0;
+		framedrop_period = 0;
+	}
 
-	for (i = 0; i < stream_info->num_planes; i++)
+	for (i = 0; i < stream_info->num_planes; i++) {
 		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base +
 			VFE40_WM_BASE(stream_info->wm[i]) + 0x1C);
+		temp = msm_camera_io_r(vfe_dev->vfe_base +
+			VFE40_WM_BASE(stream_info->wm[i]) + 0xC);
+		temp &= 0xFFFFFF83;
+		msm_camera_io_w(temp | framedrop_period << 2,
+		vfe_dev->vfe_base + VFE40_WM_BASE(stream_info->wm[i]) + 0xC);
+	}
 
 	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x378);
 }
@@ -560,6 +592,44 @@
 			VFE40_WM_BASE(stream_info->wm[i]) + 0x1C);
 }
 
+static void msm_vfe40_cfg_io_format(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_request_cmd *stream_req_cmd)
+{
+	int bpp, bpp_reg = 0;
+	uint32_t io_format_reg;
+	bpp = msm_isp_get_bit_per_pixel(stream_req_cmd->output_format);
+
+	switch (bpp) {
+	case 8:
+		bpp_reg = 0;
+		break;
+	case 10:
+		bpp_reg = 1 << 0;
+		break;
+	case 12:
+		bpp_reg = 1 << 1;
+		break;
+	}
+	io_format_reg = msm_camera_io_r(vfe_dev->vfe_base + 0x54);
+	switch (stream_req_cmd->stream_src) {
+	case CAMIF_RAW:
+		io_format_reg &= 0xFFFFCFFF;
+		io_format_reg |= bpp_reg << 12;
+		break;
+	case IDEAL_RAW:
+		io_format_reg &= 0xFFFFFFC8;
+		io_format_reg |= bpp_reg << 4;
+		break;
+	case PIX_ENCODER:
+	case PIX_VIEWFINDER:
+	case RDI:
+	default:
+		pr_err("%s: Invalid stream source\n", __func__);
+		return;
+	}
+	msm_camera_io_w(io_format_reg, vfe_dev->vfe_base + 0x54);
+}
+
 static void msm_vfe40_cfg_camif(struct vfe_device *vfe_dev,
 	struct msm_vfe_pix_cfg *pix_cfg)
 {
@@ -590,9 +660,6 @@
 	val |= camif_cfg->camif_input;
 	msm_camera_io_w(val, vfe_dev->vfe_base + 0x2E8);
 
-	vfe_dev->hw_info->vfe_ops.core_ops.epoch_irq(vfe_dev,
-		camif_cfg->epoch_line0, camif_cfg->epoch_line1);
-
 	switch (pix_cfg->input_mux) {
 	case CAMIF:
 		val = 0x01;
@@ -652,9 +719,6 @@
 			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	uint32_t wm_base = VFE40_WM_BASE(stream_info->wm[plane_idx]);
 
-	/*WR_ADDR_CFG*/
-	msm_camera_io_w(0x7C, vfe_dev->vfe_base + wm_base + 0xC);
-
 	/*WR_IMAGE_SIZE*/
 	val =
 		((msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
@@ -670,8 +734,8 @@
 		stream_cfg_cmd->plane_cfg[
 			plane_idx].output_stride) << 16 |
 		(stream_cfg_cmd->plane_cfg[
-			plane_idx].output_scan_lines - 1) << 4 |
-		VFE40_BURST_LEN >> 2;
+			plane_idx].output_height - 1) << 4 |
+		VFE40_BURST_LEN;
 	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x18);
 
 	/*WR_IRQ_SUBSAMPLE_PATTERN*/
@@ -907,64 +971,160 @@
 	return msm_camera_io_r(vfe_dev->vfe_base + 0x268);
 }
 
-static void msm_vfe40_stats_cfg_comp_mask(
-	struct vfe_device *vfe_dev,
-	struct msm_vfe_stats_stream *stream_info)
+static int msm_vfe40_get_stats_idx(enum msm_isp_stats_type stats_type)
 {
-
+	switch (stats_type) {
+	case MSM_ISP_STATS_BE:
+		return 0;
+	case MSM_ISP_STATS_BG:
+		return 1;
+	case MSM_ISP_STATS_BF:
+		return 2;
+	case MSM_ISP_STATS_AWB:
+		return 3;
+	case MSM_ISP_STATS_RS:
+		return 4;
+	case MSM_ISP_STATS_CS:
+		return 5;
+	case MSM_ISP_STATS_IHIST:
+		return 6;
+	case MSM_ISP_STATS_BHIST:
+		return 7;
+	default:
+		pr_err("%s: Invalid stats type\n", __func__);
+		return -EINVAL;
+	}
 }
 
-static void msm_vfe40_stats_clear_comp_mask(
-	struct vfe_device *vfe_dev,
-	struct msm_vfe_stats_stream *stream_info)
+static void msm_vfe40_stats_cfg_comp_mask(struct vfe_device *vfe_dev)
 {
-
+	if (vfe_dev->stats_data.stats_pipeline_policy == STATS_COMP_ALL)
+		msm_camera_io_w(0x00FF0000, vfe_dev->vfe_base + 0x44);
+	else
+		msm_camera_io_w(0x00000000, vfe_dev->vfe_base + 0x44);
 }
 
 static void msm_vfe40_stats_cfg_wm_irq_mask(
 	struct vfe_device *vfe_dev,
 	struct msm_vfe_stats_stream *stream_info)
 {
-
+	uint32_t irq_mask;
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
+	irq_mask |= 1 << (STATS_IDX(stream_info->stream_handle) + 16);
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
 }
 
 static void msm_vfe40_stats_clear_wm_irq_mask(
 	struct vfe_device *vfe_dev,
 	struct msm_vfe_stats_stream *stream_info)
 {
-
+	uint32_t irq_mask;
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
+	irq_mask &= ~(1 << (STATS_IDX(stream_info->stream_handle) + 16));
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
 }
 
 static void msm_vfe40_stats_cfg_wm_reg(
 	struct vfe_device *vfe_dev,
 	struct msm_vfe_stats_stream *stream_info)
 {
+	int stats_idx = STATS_IDX(stream_info->stream_handle);
+	uint32_t stats_base = VFE40_STATS_BASE(stats_idx);
 
+	/*WR_ADDR_CFG*/
+	msm_camera_io_w(0x7C, vfe_dev->vfe_base + stats_base + 0x8);
+	/*WR_IRQ_FRAMEDROP_PATTERN*/
+	msm_camera_io_w(0xFFFFFFFF,
+		vfe_dev->vfe_base + stats_base + 0x10);
+	/*WR_IRQ_SUBSAMPLE_PATTERN*/
+	msm_camera_io_w(0xFFFFFFFF,
+		vfe_dev->vfe_base + stats_base + 0x14);
 }
 
 static void msm_vfe40_stats_clear_wm_reg(
 	struct vfe_device *vfe_dev,
 	struct msm_vfe_stats_stream *stream_info)
 {
+	uint32_t val = 0;
+	int stats_idx = STATS_IDX(stream_info->stream_handle);
+	uint32_t stats_base = VFE40_STATS_BASE(stats_idx);
 
+	/*WR_ADDR_CFG*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + stats_base + 0x8);
+	/*WR_IRQ_FRAMEDROP_PATTERN*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + stats_base + 0x10);
+	/*WR_IRQ_SUBSAMPLE_PATTERN*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + stats_base + 0x14);
 }
 
 static void msm_vfe40_stats_cfg_ub(struct vfe_device *vfe_dev)
 {
+	int i;
+	uint32_t ub_offset = VFE40_UB_SIZE;
+	uint32_t ub_size[VFE40_NUM_STATS_TYPE] = {
+		64, /*MSM_ISP_STATS_BE*/
+		64, /*MSM_ISP_STATS_BG*/
+		64, /*MSM_ISP_STATS_BF*/
+		16, /*MSM_ISP_STATS_AWB*/
+		8,  /*MSM_ISP_STATS_RS*/
+		16, /*MSM_ISP_STATS_CS*/
+		16, /*MSM_ISP_STATS_IHIST*/
+		16, /*MSM_ISP_STATS_BHIST*/
+	};
+
+	for (i = 0; i < VFE40_NUM_STATS_TYPE; i++) {
+		ub_offset -= ub_size[i];
+		msm_camera_io_w(VFE40_BURST_LEN << 30 |
+			ub_offset << 16 | (ub_size[i] - 1),
+			vfe_dev->vfe_base + VFE40_STATS_BASE(i) + 0xC);
+	}
 }
 
-static void msm_vfe40_stats_enable(struct vfe_device *vfe_dev,
+static void msm_vfe40_stats_enable_module(struct vfe_device *vfe_dev,
 	uint32_t stats_mask, uint8_t enable)
 {
+	int i;
+	uint32_t module_cfg, module_cfg_mask = 0;
 
+	for (i = 0; i < VFE40_NUM_STATS_TYPE; i++) {
+		if ((stats_mask >> i) & 0x1) {
+			switch (i) {
+			case 0:
+			case 1:
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+				module_cfg_mask |= 1 << (5 + i);
+				break;
+			case 6:
+				module_cfg_mask |= 1 << 15;
+				break;
+			case 7:
+				module_cfg_mask |= 1 << 18;
+				break;
+			default:
+				pr_err("%s: Invalid stats mask\n", __func__);
+				return;
+			}
+		}
+	}
+
+	module_cfg = msm_camera_io_r(vfe_dev->vfe_base + 0x18);
+	if (enable)
+		module_cfg |= module_cfg_mask;
+	else
+		module_cfg &= ~module_cfg_mask;
+	msm_camera_io_w(module_cfg, vfe_dev->vfe_base + 0x18);
 }
 
 static void msm_vfe40_stats_update_ping_pong_addr(
-	struct vfe_device *vfe_dev,
-	enum msm_isp_stats_type stats_type,
-	uint32_t pingpong_status,
-	unsigned long paddr)
+	struct vfe_device *vfe_dev, struct msm_vfe_stats_stream *stream_info,
+	uint32_t pingpong_status, unsigned long paddr)
 {
+	int stats_idx = STATS_IDX(stream_info->stream_handle);
+	msm_camera_io_w(paddr, vfe_dev->vfe_base +
+		VFE40_STATS_PING_PONG_BASE(stats_idx, pingpong_status));
 }
 
 static uint32_t msm_vfe40_stats_get_wm_mask(
@@ -976,7 +1136,7 @@
 static uint32_t msm_vfe40_stats_get_comp_mask(
 	uint32_t irq_status0, uint32_t irq_status1)
 {
-	return (irq_status0 >> 29) & 0x2;
+	return (irq_status0 >> 29) & 0x3;
 }
 
 static uint32_t msm_vfe40_stats_get_frame_id(
@@ -985,55 +1145,6 @@
 	return vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
 }
 
-static uint32_t msm_vfe40_stats_get_active_pingpong_idx(
-	uint32_t pingpong_status,
-	enum msm_isp_stats_type stats_type)
-{
-	int pingpong_bit = 0;
-	switch (stats_type) {
-	case MSM_ISP_STATS_AWB:
-		if (pingpong_status & (1 << 11))
-			pingpong_bit = 1; /* pong is active */
-			break;
-	case MSM_ISP_STATS_RS:
-		if (pingpong_status & (1 << 12))
-			pingpong_bit = 1; /* pong is active */
-			break;
-	case MSM_ISP_STATS_CS:
-		if (pingpong_status & (1 << 13))
-			pingpong_bit = 1; /* pong is active */
-			break;
-	case MSM_ISP_STATS_IHIST:
-		if (pingpong_status & (1 << 14))
-			pingpong_bit = 1; /* pong is active */
-			break;
-	case MSM_ISP_STATS_BG:
-		if (pingpong_status & (1 << 9))
-			pingpong_bit = 1; /* pong is active */
-			break;
-	case MSM_ISP_STATS_BF:
-		if (pingpong_status & (1 << 10))
-			pingpong_bit = 1; /* pong is active */
-			break;
-	case MSM_ISP_STATS_BE:
-		if (pingpong_status & (1 << 8))
-			pingpong_bit = 1; /* pong is active */
-			break;
-	case MSM_ISP_STATS_BHIST:
-		if (pingpong_status & (1 << 15))
-			pingpong_bit = 1; /* pong is active */
-			break;
-	case MSM_ISP_STATS_SKIN:
-	case MSM_ISP_STATS_AEC:
-	case MSM_ISP_STATS_AF:
-	default:
-		pr_err("%s: not supported stats type = %d\n",
-			__func__, stats_type);
-		return -EINVAL;
-	}
-	return pingpong_bit;
-}
-
 static int msm_vfe40_get_platform_data(struct vfe_device *vfe_dev)
 {
 	int rc = 0;
@@ -1072,11 +1183,11 @@
 	}
 
 	if (vfe_dev->pdev->id == 0)
-		vfe_dev->iommu_ctx = msm_iommu_get_ctx("vfe0");
+		vfe_dev->iommu_ctx[0] = msm_iommu_get_ctx("vfe0");
 	else if (vfe_dev->pdev->id == 1)
-		vfe_dev->iommu_ctx = msm_iommu_get_ctx("vfe1");
-	if (!vfe_dev->iommu_ctx) {
-		pr_err("%s: no irq resource?\n", __func__);
+		vfe_dev->iommu_ctx[0] = msm_iommu_get_ctx("vfe1");
+	if (!vfe_dev->iommu_ctx[0]) {
+		pr_err("%s: cannot get iommu_ctx\n", __func__);
 		rc = -ENODEV;
 		goto vfe_no_resource;
 	}
@@ -1085,12 +1196,29 @@
 	return rc;
 }
 
-struct msm_vfe_axi_hardware_info msm_vfe40_axi_hw_info = {
-	.num_wm = 7,
+static void msm_vfe40_get_error_mask(
+	uint32_t *error_mask0, uint32_t *error_mask1)
+{
+	*error_mask0 = 0x00000000;
+	*error_mask1 = 0x00FFFEFF;
+}
+
+static struct msm_vfe_axi_hardware_info msm_vfe40_axi_hw_info = {
+	.num_wm = 4,
 	.num_comp_mask = 4,
 	.num_rdi = 3,
 	.num_rdi_master = 3,
 	.min_wm_ub = 64,
+};
+
+static struct msm_vfe_stats_hardware_info msm_vfe40_stats_hw_info = {
+	.stats_capability_mask =
+		1 << MSM_ISP_STATS_BE | 1 << MSM_ISP_STATS_BF |
+		1 << MSM_ISP_STATS_BG | 1 << MSM_ISP_STATS_BHIST |
+		1 << MSM_ISP_STATS_AWB | 1 << MSM_ISP_STATS_IHIST |
+		1 << MSM_ISP_STATS_RS | 1 << MSM_ISP_STATS_CS,
+	.stats_ping_pong_offset = VFE40_STATS_PING_PONG_OFFSET,
+	.num_stats_type = VFE40_NUM_STATS_TYPE,
 	.num_stats_comp_mask = 2,
 };
 
@@ -1110,6 +1238,7 @@
 };
 
 struct msm_vfe_hardware_info vfe40_hw_info = {
+	.num_iommu_ctx = 1,
 	.vfe_ops = {
 		.irq_ops = {
 			.read_irq_status = msm_vfe40_read_irq_status,
@@ -1117,7 +1246,6 @@
 			.process_reset_irq = msm_vfe40_process_reset_irq,
 			.process_halt_irq = msm_vfe40_process_halt_irq,
 			.process_reset_irq = msm_vfe40_process_reset_irq,
-			.process_error_irq = msm_vfe40_process_error_irq,
 			.process_reg_update = msm_vfe40_process_reg_update,
 			.process_axi_irq = msm_isp_process_axi_irq,
 			.process_stats_irq = msm_isp_process_stats_irq,
@@ -1125,6 +1253,7 @@
 		.axi_ops = {
 			.reload_wm = msm_vfe40_axi_reload_wm,
 			.enable_wm = msm_vfe40_axi_enable_wm,
+			.cfg_io_format = msm_vfe40_cfg_io_format,
 			.cfg_comp_mask = msm_vfe40_axi_cfg_comp_mask,
 			.clear_comp_mask = msm_vfe40_axi_clear_comp_mask,
 			.cfg_wm_irq_mask = msm_vfe40_axi_cfg_wm_irq_mask,
@@ -1145,7 +1274,6 @@
 			.halt = msm_vfe40_axi_halt,
 		},
 		.core_ops = {
-			.epoch_irq = msm_vfe40_epoch_irq_enb,
 			.reg_update = msm_vfe40_reg_update,
 			.cfg_camif = msm_vfe40_cfg_camif,
 			.update_camif_state = msm_vfe40_update_camif_state,
@@ -1154,27 +1282,28 @@
 			.init_hw_reg = msm_vfe40_init_hardware_reg,
 			.release_hw = msm_vfe40_release_hardware,
 			.get_platform_data = msm_vfe40_get_platform_data,
+			.get_error_mask = msm_vfe40_get_error_mask,
+			.process_error_status = msm_vfe40_process_error_status,
 		},
 		.stats_ops = {
+			.get_stats_idx = msm_vfe40_get_stats_idx,
 			.cfg_comp_mask = msm_vfe40_stats_cfg_comp_mask,
-			.clear_comp_mask = msm_vfe40_stats_clear_comp_mask,
 			.cfg_wm_irq_mask = msm_vfe40_stats_cfg_wm_irq_mask,
 			.clear_wm_irq_mask = msm_vfe40_stats_clear_wm_irq_mask,
 			.cfg_wm_reg = msm_vfe40_stats_cfg_wm_reg,
 			.clear_wm_reg = msm_vfe40_stats_clear_wm_reg,
 			.cfg_ub = msm_vfe40_stats_cfg_ub,
-			.stats_enable = msm_vfe40_stats_enable,
+			.enable_module = msm_vfe40_stats_enable_module,
 			.update_ping_pong_addr =
 				msm_vfe40_stats_update_ping_pong_addr,
 			.get_comp_mask = msm_vfe40_stats_get_comp_mask,
 			.get_wm_mask = msm_vfe40_stats_get_wm_mask,
 			.get_frame_id = msm_vfe40_stats_get_frame_id,
 			.get_pingpong_status = msm_vfe40_get_pingpong_status,
-			.get_active_pingpong_idx =
-				msm_vfe40_stats_get_active_pingpong_idx,
 		},
 	},
 	.axi_hw_info = &msm_vfe40_axi_hw_info,
+	.stats_hw_info = &msm_vfe40_stats_hw_info,
 	.subdev_ops = &msm_vfe40_subdev_ops,
 	.subdev_internal_ops = &msm_vfe40_internal_ops,
 };
diff --git a/drivers/media/video/msmb/isp/msm_isp40.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.h
similarity index 100%
rename from drivers/media/video/msmb/isp/msm_isp40.h
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp40.h
diff --git a/drivers/media/video/msmb/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
similarity index 91%
rename from drivers/media/video/msmb/isp/msm_isp_axi_util.c
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 7e62071..606ee89 100644
--- a/drivers/media/video/msmb/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -29,27 +29,30 @@
 		return rc;
 	}
 
-	axi_data->stream_info[i].session_id = stream_cfg_cmd->session_id;
-	axi_data->stream_info[i].stream_id = stream_cfg_cmd->stream_id;
-	axi_data->stream_info[i].buf_divert = stream_cfg_cmd->buf_divert;
-	axi_data->stream_info[i].state = INACTIVE;
-
 	if ((axi_data->stream_handle_cnt << 8) == 0)
 		axi_data->stream_handle_cnt++;
 
 	stream_cfg_cmd->axi_stream_handle =
 		(++axi_data->stream_handle_cnt) << 8 | i;
 
+	axi_data->stream_info[i].session_id = stream_cfg_cmd->session_id;
+	axi_data->stream_info[i].stream_id = stream_cfg_cmd->stream_id;
+	axi_data->stream_info[i].buf_divert = stream_cfg_cmd->buf_divert;
+	axi_data->stream_info[i].state = INACTIVE;
+	axi_data->stream_info[i].stream_handle =
+		stream_cfg_cmd->axi_stream_handle;
 	return 0;
 }
 
 void msm_isp_axi_destroy_stream(
 	struct msm_vfe_axi_shared_data *axi_data, int stream_idx)
 {
-	if (axi_data->stream_info[stream_idx].state != AVALIABLE)
+	if (axi_data->stream_info[stream_idx].state != AVALIABLE) {
 		axi_data->stream_info[stream_idx].state = AVALIABLE;
-	else
+		axi_data->stream_info[stream_idx].stream_handle = 0;
+	} else {
 		pr_err("%s: stream does not exist\n", __func__);
+	}
 }
 
 int msm_isp_validate_axi_request(struct msm_vfe_axi_shared_data *axi_data,
@@ -116,6 +119,7 @@
 		return rc;
 	}
 
+	stream_info->stream_src = stream_cfg_cmd->stream_src;
 	return 0;
 }
 
@@ -388,8 +392,9 @@
 	}
 }
 
-void msm_isp_new_frame_notify(struct vfe_device *vfe_dev,
-	enum msm_vfe_input_src frame_src) {
+void msm_isp_sof_notify(struct vfe_device *vfe_dev,
+	enum msm_vfe_input_src frame_src, struct timeval *tv) {
+	struct msm_isp_event_data sof_event;
 	switch (frame_src) {
 	case VFE_PIX_0:
 		ISP_DBG("%s: PIX0 frame id: %lu\n", __func__,
@@ -408,7 +413,12 @@
 			__func__, frame_src);
 		break;
 	}
+
+	sof_event.frame_id = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
+	sof_event.timestamp = *tv;
+	msm_isp_send_event(vfe_dev, ISP_EVENT_SOF, &sof_event);
 }
+
 void msm_isp_calculate_framedrop(
 	struct msm_vfe_axi_shared_data *axi_data,
 	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
@@ -417,38 +427,31 @@
 		&axi_data->stream_info[
 		(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	uint32_t framedrop_period = 1;
-
 	switch (stream_cfg_cmd->frame_skip_pattern) {
 	case NO_SKIP:
-		stream_info->framedrop_pattern = VFE_NO_DROP;
-		framedrop_period = 1;
-		break;
 	case EVERY_2FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_2FRAME;
-		framedrop_period = 2;
-		break;
+	case EVERY_3FRAME:
 	case EVERY_4FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_4FRAME;
-		framedrop_period = 4;
-		break;
+	case EVERY_5FRAME:
+	case EVERY_6FRAME:
+	case EVERY_7FRAME:
 	case EVERY_8FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_8FRAME;
-		framedrop_period = 8;
+		framedrop_period = stream_cfg_cmd->frame_skip_pattern + 1;
 		break;
 	case EVERY_16FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_16FRAME;
 		framedrop_period = 16;
 		break;
 	case EVERY_32FRAME:
-		stream_info->framedrop_pattern = VFE_DROP_EVERY_32FRAME;
 		framedrop_period = 32;
 		break;
 	default:
-		stream_info->framedrop_pattern = VFE_NO_DROP;
 		framedrop_period = 1;
 		break;
 	}
 
+	stream_info->framedrop_pattern = 0x1;
+	stream_info->framedrop_period = framedrop_period - 1;
+
 	if (stream_cfg_cmd->init_frame_drop < framedrop_period) {
 		stream_info->framedrop_pattern <<=
 			stream_cfg_cmd->init_frame_drop;
@@ -461,6 +464,8 @@
 
 	if (stream_cfg_cmd->burst_count > 0) {
 		stream_info->stream_type = BURST_STREAM;
+		stream_info->num_burst_capture =
+			stream_cfg_cmd->burst_count;
 		stream_info->burst_frame_count =
 		stream_cfg_cmd->init_frame_drop +
 			(stream_cfg_cmd->burst_count - 1) *
@@ -468,6 +473,7 @@
 	} else {
 		stream_info->stream_type = CONTINUOUS_STREAM;
 		stream_info->burst_frame_count = 0;
+		stream_info->num_burst_capture = 0;
 	}
 }
 
@@ -501,6 +507,11 @@
 		&vfe_dev->axi_data.
 			stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 
+	if (stream_cfg_cmd->stream_src == CAMIF_RAW ||
+		stream_cfg_cmd->stream_src == IDEAL_RAW)
+			vfe_dev->hw_info->vfe_ops.axi_ops.
+				cfg_io_format(vfe_dev, stream_cfg_cmd);
+
 	msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);
 	vfe_dev->hw_info->vfe_ops.axi_ops.cfg_framedrop(vfe_dev, stream_info);
 
@@ -637,34 +648,32 @@
 		complete(&vfe_dev->stream_config_complete);
 	}
 }
-#define VFE_PING_FLAG 0xFFFFFFFF
-#define VFE_PONG_FLAG 0x0
 
 int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
 	struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
 	struct timeval *tv)
 {
 	int i, rc = -1;
-	struct msm_isp_buffer *buf;
+	struct msm_isp_buffer *buf = NULL;
 	struct msm_isp_event_data buf_event;
 	uint32_t pingpong_bit = 0;
 	uint32_t bufq_handle = stream_info->bufq_handle;
+	uint32_t stream_idx = stream_info->stream_handle & 0xFF;
 
 	pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1);
 	rc = vfe_dev->buf_mgr->ops->get_buf(
 		vfe_dev->buf_mgr, bufq_handle, &buf);
 	if (rc < 0) {
 		if (stream_info->stream_type == BURST_STREAM &&
-				stream_info->burst_frame_count <= 1) {
+				stream_info->num_burst_capture <= 1) {
 			rc = 0;
 			if (pingpong_bit)
 				buf = stream_info->buf[0];
 			else
 				buf = stream_info->buf[1];
 		} else {
-			pr_err("%s: No free buffer, stream_type = %d, burst_cnt = %d\n",
-				__func__, stream_info->stream_type,
-				stream_info->burst_frame_count);
+			vfe_dev->error_info.
+				stream_framedrop_count[stream_idx]++;
 			return rc;
 		}
 	}
@@ -688,6 +697,11 @@
 
 	if (stream_info->buf[pingpong_bit] && tv) {
 		if (stream_info->buf_divert) {
+			vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
+				stream_info->buf[pingpong_bit]->bufq_handle,
+				stream_info->buf[pingpong_bit]->buf_idx,
+				tv, stream_info->frame_id);
+
 			buf_event.frame_id = stream_info->frame_id;
 			buf_event.timestamp = *tv;
 			buf_event.u.buf_done.session_id =
@@ -827,7 +841,7 @@
 
 	if (camif_update == DISABLE_CAMIF)
 		vfe_dev->hw_info->vfe_ops.core_ops.
-			update_camif_state(vfe_dev, DISABLE_CAMIF_IMMEDIATELY);
+			update_camif_state(vfe_dev, DISABLE_CAMIF);
 
 	/*
 	* Stream start either immediately or at reg update
@@ -906,6 +920,38 @@
 	return rc;
 }
 
+int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream_update_cmd *update_cmd = arg;
+	stream_info = &axi_data->stream_info[
+			(update_cmd->stream_handle & 0xFF)];
+	if (stream_info->state != ACTIVE && stream_info->state != INACTIVE) {
+		pr_err("%s: Invalid stream state\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (update_cmd->update_type) {
+	case ENABLE_STREAM_BUF_DIVERT:
+		stream_info->buf_divert = 1;
+		break;
+	case DISABLE_STREAM_BUF_DIVERT:
+		stream_info->buf_divert = 0;
+		vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr,
+				stream_info->bufq_handle,
+				MSM_ISP_BUFFER_FLUSH_DIVERTED);
+		break;
+	case UPDATE_STREAM_FRAMEDROP_PATTERN:
+		break;
+	default:
+		pr_err("%s: Invalid update type\n", __func__);
+		return -EINVAL;
+	}
+	return rc;
+}
+
 void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1,
 	struct timeval *tv)
@@ -917,7 +963,6 @@
 	struct msm_vfe_axi_composite_info *comp_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 
-	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
 	comp_mask = vfe_dev->hw_info->vfe_ops.axi_ops.
 		get_comp_mask(irq_status0, irq_status1);
 	wm_mask = vfe_dev->hw_info->vfe_ops.axi_ops.
@@ -925,6 +970,7 @@
 	if (!(comp_mask || wm_mask))
 		return;
 
+	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
 	pingpong_status =
 		vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status(vfe_dev);
 
diff --git a/drivers/media/video/msmb/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
similarity index 92%
rename from drivers/media/video/msmb/isp/msm_isp_axi_util.h
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index 4847c06..0c64c19 100644
--- a/drivers/media/video/msmb/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -44,6 +44,7 @@
 int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg);
 int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg);
 int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg);
 
 void msm_isp_axi_stream_enable_cfg(struct vfe_device *vfe_dev,
 	struct msm_vfe_axi_stream *stream_info,
@@ -57,8 +58,8 @@
 
 void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev);
 void msm_isp_update_framedrop_count(struct vfe_device *vfe_dev);
-void msm_isp_new_frame_notify(struct vfe_device *vfe_dev,
-	enum msm_vfe_input_src frame_src);
+void msm_isp_sof_notify(struct vfe_device *vfe_dev,
+	enum msm_vfe_input_src frame_src, struct timeval *tv);
 void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1,
 	struct timeval *tv);
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
new file mode 100644
index 0000000..bf348d0
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -0,0 +1,348 @@
+/* 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/io.h>
+#include <media/v4l2-subdev.h>
+#include "msm_isp_util.h"
+#include "msm_isp_stats_util.h"
+
+static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info, uint32_t pingpong_status,
+	struct msm_isp_buffer **done_buf)
+{
+	int rc = -1;
+	struct msm_isp_buffer *buf;
+	uint32_t pingpong_bit = 0;
+	uint32_t bufq_handle = stream_info->bufq_handle;
+	uint32_t stats_pingpong_offset =
+		STATS_IDX(stream_info->stream_handle) +
+		vfe_dev->hw_info->stats_hw_info->stats_ping_pong_offset;
+
+	pingpong_bit = (~(pingpong_status >> stats_pingpong_offset) & 0x1);
+	rc = vfe_dev->buf_mgr->ops->get_buf(
+		vfe_dev->buf_mgr, bufq_handle, &buf);
+	if (rc < 0) {
+		vfe_dev->error_info.stats_framedrop_count[
+			STATS_IDX(stream_info->stream_handle)]++;
+		return rc;
+	}
+
+	if (buf->num_planes != 1) {
+		pr_err("%s: Invalid buffer\n", __func__);
+		rc = -EINVAL;
+		goto buf_error;
+	}
+
+	vfe_dev->hw_info->vfe_ops.stats_ops.update_ping_pong_addr(
+		vfe_dev, stream_info,
+		pingpong_status, buf->mapped_info[0].paddr);
+
+	if (stream_info->buf[pingpong_bit] && done_buf)
+		*done_buf = stream_info->buf[pingpong_bit];
+
+	stream_info->buf[pingpong_bit] = buf;
+	return 0;
+buf_error:
+	vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
+		buf->bufq_handle, buf->buf_idx);
+	return rc;
+}
+
+void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1,
+	struct timeval *tv)
+{
+	int i;
+	struct msm_isp_event_data buf_event;
+	struct msm_isp_stats_event *stats_event = &buf_event.u.stats;
+	struct msm_isp_buffer *done_buf;
+	struct msm_vfe_stats_stream *stream_info = NULL;
+	uint32_t pingpong_status;
+	uint32_t stats_comp_mask = 0, stats_irq_mask = 0;
+	stats_comp_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
+		get_comp_mask(irq_status0, irq_status1);
+	stats_irq_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
+		get_wm_mask(irq_status0, irq_status1);
+	if (!(stats_comp_mask || stats_irq_mask))
+		return;
+	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
+
+	if (vfe_dev->stats_data.stats_pipeline_policy == STATS_COMP_ALL) {
+		if (!stats_comp_mask)
+			return;
+		stats_irq_mask = 0xFFFFFFFF;
+	}
+
+	memset(&buf_event, 0, sizeof(struct msm_isp_event_data));
+	pingpong_status = vfe_dev->hw_info->
+		vfe_ops.stats_ops.get_pingpong_status(vfe_dev);
+
+	for (i = 0; i < vfe_dev->hw_info->stats_hw_info->num_stats_type; i++) {
+		if (!(stats_irq_mask & (1 << i)))
+			continue;
+		stream_info = &vfe_dev->stats_data.stream_info[i];
+		done_buf = NULL;
+		msm_isp_stats_cfg_ping_pong_address(vfe_dev,
+			stream_info, pingpong_status, &done_buf);
+		if (done_buf) {
+			stats_event->stats_mask |= 1 << stream_info->stats_type;
+			stats_event->stats_buf_idxs[stream_info->stats_type] =
+				done_buf->buf_idx;
+			vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
+				done_buf->bufq_handle, done_buf->buf_idx,
+				tv, 0);
+		}
+	}
+
+	if (stats_event->stats_mask) {
+		buf_event.timestamp = *tv;
+		msm_isp_send_event(vfe_dev, ISP_EVENT_STATS_NOTIFY, &buf_event);
+	}
+}
+
+int msm_isp_stats_create_stream(struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream_request_cmd *stream_req_cmd)
+{
+	int rc = -1;
+	struct msm_vfe_stats_stream *stream_info = NULL;
+	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+	uint32_t stats_idx;
+
+	if (!(vfe_dev->hw_info->stats_hw_info->stats_capability_mask &
+		(1 << stream_req_cmd->stats_type))) {
+		pr_err("%s: Stats type not supported\n", __func__);
+		return rc;
+	}
+
+	stats_idx = vfe_dev->hw_info->vfe_ops.stats_ops.
+		get_stats_idx(stream_req_cmd->stats_type);
+
+	stream_info = &stats_data->stream_info[stats_idx];
+	if (stream_info->state != STATS_AVALIABLE) {
+		pr_err("%s: Stats already requested\n", __func__);
+		return rc;
+	}
+
+	if (stats_data->stats_pipeline_policy != STATS_COMP_ALL) {
+		if (stream_req_cmd->framedrop_pattern >= MAX_SKIP) {
+			pr_err("%s: Invalid framedrop pattern\n", __func__);
+			return rc;
+		}
+
+		if (stream_req_cmd->irq_subsample_pattern >= MAX_SKIP) {
+			pr_err("%s: Invalid irq subsample pattern\n", __func__);
+			return rc;
+		}
+	} else {
+		if (stats_data->comp_framedrop_pattern >= MAX_SKIP) {
+			pr_err("%s: Invalid comp framedrop pattern\n",
+				__func__);
+			return rc;
+		}
+
+		if (stats_data->comp_irq_subsample_pattern >= MAX_SKIP) {
+			pr_err("%s: Invalid comp irq subsample pattern\n",
+				__func__);
+			return rc;
+		}
+		stream_req_cmd->framedrop_pattern =
+			vfe_dev->stats_data.comp_framedrop_pattern;
+		stream_req_cmd->irq_subsample_pattern =
+			vfe_dev->stats_data.comp_irq_subsample_pattern;
+	}
+
+	stream_info->session_id = stream_req_cmd->session_id;
+	stream_info->stream_id = stream_req_cmd->stream_id;
+	stream_info->stats_type = stream_req_cmd->stats_type;
+	stream_info->framedrop_pattern = stream_req_cmd->framedrop_pattern;
+	stream_info->irq_subsample_pattern =
+		stream_req_cmd->irq_subsample_pattern;
+	stream_info->state = STATS_INACTIVE;
+
+	if ((vfe_dev->stats_data.stream_handle_cnt << 8) == 0)
+		vfe_dev->stats_data.stream_handle_cnt++;
+
+	stream_req_cmd->stream_handle =
+		(++vfe_dev->stats_data.stream_handle_cnt) << 8 | stats_idx;
+
+	stream_info->stream_handle = stream_req_cmd->stream_handle;
+	return 0;
+}
+
+int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0;
+	struct msm_vfe_stats_stream_request_cmd *stream_req_cmd = arg;
+	struct msm_vfe_stats_stream *stream_info = NULL;
+	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+	uint32_t stats_idx;
+
+	rc = msm_isp_stats_create_stream(vfe_dev, stream_req_cmd);
+	if (rc < 0) {
+		pr_err("%s: create stream failed\n", __func__);
+		return rc;
+	}
+
+	stats_idx = STATS_IDX(stream_req_cmd->stream_handle);
+	stream_info = &stats_data->stream_info[stats_idx];
+
+	switch (stream_info->framedrop_pattern) {
+	case NO_SKIP:
+		stream_info->framedrop_pattern = VFE_NO_DROP;
+		break;
+	case EVERY_2FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_2FRAME;
+		break;
+	case EVERY_4FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_4FRAME;
+		break;
+	case EVERY_8FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_8FRAME;
+		break;
+	case EVERY_16FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_16FRAME;
+		break;
+	case EVERY_32FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_32FRAME;
+		break;
+	default:
+		stream_info->framedrop_pattern = VFE_NO_DROP;
+		break;
+	}
+
+	if (stats_data->stats_pipeline_policy == STATS_COMP_NONE)
+		vfe_dev->hw_info->vfe_ops.stats_ops.
+			cfg_wm_irq_mask(vfe_dev, stream_info);
+
+	vfe_dev->hw_info->vfe_ops.stats_ops.cfg_wm_reg(vfe_dev, stream_info);
+	return rc;
+}
+
+int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = -1;
+	struct msm_vfe_stats_stream_cfg_cmd stream_cfg_cmd;
+	struct msm_vfe_stats_stream_release_cmd *stream_release_cmd = arg;
+	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+	int stats_idx = STATS_IDX(stream_release_cmd->stream_handle);
+	struct msm_vfe_stats_stream *stream_info =
+		&stats_data->stream_info[stats_idx];
+
+	if (stream_info->state == STATS_AVALIABLE) {
+		pr_err("%s: stream already release\n", __func__);
+		return rc;
+	} else if (stream_info->state != STATS_INACTIVE) {
+		stream_cfg_cmd.enable = 0;
+		stream_cfg_cmd.num_streams = 1;
+		stream_cfg_cmd.stream_handle[0] =
+			stream_release_cmd->stream_handle;
+		rc = msm_isp_cfg_stats_stream(vfe_dev, &stream_cfg_cmd);
+	}
+
+	if (stats_data->stats_pipeline_policy == STATS_COMP_NONE)
+		vfe_dev->hw_info->vfe_ops.stats_ops.
+			clear_wm_irq_mask(vfe_dev, stream_info);
+
+	vfe_dev->hw_info->vfe_ops.stats_ops.clear_wm_reg(vfe_dev, stream_info);
+	memset(stream_info, 0, sizeof(struct msm_vfe_stats_stream));
+	return 0;
+}
+
+int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int i, rc = 0;
+	struct msm_vfe_stats_stream_cfg_cmd *stream_cfg_cmd = arg;
+	struct msm_vfe_stats_stream *stream_info;
+	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+	int idx;
+	uint32_t stats_mask = 0;
+
+	if (stats_data->num_active_stream == 0)
+		vfe_dev->hw_info->vfe_ops.stats_ops.cfg_ub(vfe_dev);
+
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
+		stream_info = &stats_data->stream_info[idx];
+		if (stream_info->stream_handle !=
+				stream_cfg_cmd->stream_handle[i]) {
+			pr_err("%s: Invalid stream handle: 0x%x received\n",
+				__func__, stream_cfg_cmd->stream_handle[i]);
+			continue;
+		}
+
+		if (stream_cfg_cmd->enable) {
+			stream_info->bufq_handle =
+				vfe_dev->buf_mgr->ops->get_bufq_handle(
+				vfe_dev->buf_mgr, stream_info->session_id,
+				stream_info->stream_id);
+				if (stream_info->bufq_handle == 0) {
+					pr_err("%s: no buf configured for stream: 0x%x\n",
+						__func__,
+						stream_info->stream_handle);
+					return -EINVAL;
+				}
+
+			msm_isp_stats_cfg_ping_pong_address(vfe_dev,
+				stream_info, VFE_PING_FLAG, NULL);
+			msm_isp_stats_cfg_ping_pong_address(vfe_dev,
+				stream_info, VFE_PONG_FLAG, NULL);
+			stream_info->state = STATS_START_PENDING;
+			stats_data->num_active_stream++;
+		} else {
+			stream_info->state = STATS_STOP_PENDING;
+			stats_data->num_active_stream--;
+		}
+		stats_mask |= 1 << idx;
+	}
+	vfe_dev->hw_info->vfe_ops.stats_ops.
+		enable_module(vfe_dev, stats_mask, stream_cfg_cmd->enable);
+	return rc;
+}
+
+int msm_isp_cfg_stats_comp_policy(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = -1;
+	struct msm_vfe_stats_comp_policy_cfg *policy_cfg_cmd = arg;
+	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+
+	if (stats_data->num_active_stream != 0) {
+		pr_err("%s: Cannot update policy when there are active streams\n",
+			   __func__);
+		return rc;
+	}
+
+	if (policy_cfg_cmd->stats_pipeline_policy >= MAX_STATS_POLICY) {
+		pr_err("%s: Invalid stats composite policy\n", __func__);
+		return rc;
+	}
+
+	if (policy_cfg_cmd->comp_framedrop_pattern >= MAX_SKIP) {
+		pr_err("%s: Invalid comp framedrop pattern\n", __func__);
+		return rc;
+	}
+
+	if (policy_cfg_cmd->comp_irq_subsample_pattern >= MAX_SKIP) {
+		pr_err("%s: Invalid comp irq subsample pattern\n", __func__);
+		return rc;
+	}
+
+	stats_data->stats_pipeline_policy =
+		policy_cfg_cmd->stats_pipeline_policy;
+	stats_data->comp_framedrop_pattern =
+		policy_cfg_cmd->comp_framedrop_pattern;
+	stats_data->comp_irq_subsample_pattern =
+		policy_cfg_cmd->comp_irq_subsample_pattern;
+
+	vfe_dev->hw_info->vfe_ops.stats_ops.cfg_comp_mask(vfe_dev);
+
+	return 0;
+}
+
diff --git a/drivers/media/video/msmb/isp/msm_isp_stats_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.h
similarity index 89%
rename from drivers/media/video/msmb/isp/msm_isp_stats_util.h
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.h
index 4feb653..2f51b7b 100644
--- a/drivers/media/video/msmb/isp/msm_isp_stats_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.h
@@ -13,6 +13,7 @@
 #define __MSM_ISP_STATS_UTIL_H__
 
 #include "msm_isp.h"
+#define STATS_IDX(idx) (idx & 0xFF)
 
 void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1,
@@ -20,4 +21,5 @@
 int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg);
 int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg);
 int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_cfg_stats_comp_policy(struct vfe_device *vfe_dev, void *arg);
 #endif /* __MSM_ISP_STATS_UTIL_H__ */
diff --git a/drivers/media/video/msmb/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
similarity index 62%
rename from drivers/media/video/msmb/isp/msm_isp_util.c
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index ee3e50e..ab8dc95 100644
--- a/drivers/media/video/msmb/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -142,6 +142,12 @@
 	case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
 		msm_isp_cfg_stats_stream(vfe_dev, arg);
 		break;
+	case VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY:
+		msm_isp_cfg_stats_comp_policy(vfe_dev, arg);
+		break;
+	case VIDIOC_MSM_ISP_UPDATE_STREAM:
+		msm_isp_update_axi_stream(vfe_dev, arg);
+		break;
 	}
 
 	mutex_unlock(&vfe_dev->mutex);
@@ -149,58 +155,132 @@
 }
 
 static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
-	struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd, uint32_t *cfg_data)
+	struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd,
+	uint32_t *cfg_data, uint32_t cmd_len)
 {
 	switch (reg_cfg_cmd->cmd_type) {
 	case VFE_WRITE: {
 		if (resource_size(vfe_dev->vfe_mem) <
-				(reg_cfg_cmd->reg_offset + reg_cfg_cmd->len)) {
+			(reg_cfg_cmd->u.rw_info.reg_offset +
+			reg_cfg_cmd->u.rw_info.len)) {
 			pr_err("%s: Invalid length\n", __func__);
 			return -EINVAL;
 		}
 		msm_camera_io_memcpy(vfe_dev->vfe_base +
-			reg_cfg_cmd->reg_offset,
-		cfg_data + reg_cfg_cmd->cmd_data/4, reg_cfg_cmd->len);
+			reg_cfg_cmd->u.rw_info.reg_offset,
+			cfg_data + reg_cfg_cmd->u.rw_info.cmd_data_offset/4,
+			reg_cfg_cmd->u.rw_info.len);
 		break;
 	}
 	case VFE_WRITE_MB: {
-		uint32_t *data_ptr = cfg_data + reg_cfg_cmd->cmd_data/4;
+		uint32_t *data_ptr = cfg_data +
+			reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
 		msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base +
-			reg_cfg_cmd->reg_offset);
+			reg_cfg_cmd->u.rw_info.reg_offset);
 		break;
 	}
-	case VFE_WRITE_MASK: {
+	case VFE_CFG_MASK: {
 		uint32_t temp;
 		temp = msm_camera_io_r(vfe_dev->vfe_base +
-			reg_cfg_cmd->reg_offset);
-		temp |= reg_cfg_cmd->cmd_data;
+			reg_cfg_cmd->u.mask_info.reg_offset);
+		temp &= ~reg_cfg_cmd->u.mask_info.mask;
+		temp |= reg_cfg_cmd->u.mask_info.val;
 		msm_camera_io_w(temp, vfe_dev->vfe_base +
-			reg_cfg_cmd->reg_offset);
+			reg_cfg_cmd->u.mask_info.reg_offset);
 		break;
 	}
-	case VFE_CLEAR_MASK: {
-		uint32_t temp;
-		temp = msm_camera_io_r(vfe_dev->vfe_base +
-			reg_cfg_cmd->reg_offset);
-		temp &= ~reg_cfg_cmd->cmd_data;
-		msm_camera_io_w(temp, vfe_dev->vfe_base +
-			reg_cfg_cmd->reg_offset);
-		break;
-	}
-	case VFE_WRITE_AUTO_INCREMENT: {
+	case VFE_WRITE_DMI_16BIT:
+	case VFE_WRITE_DMI_32BIT:
+	case VFE_WRITE_DMI_64BIT: {
 		int i;
-		uint32_t *data_ptr = cfg_data + reg_cfg_cmd->cmd_data/4;
-		for (i = 0; i < reg_cfg_cmd->len/4; i++)
-			msm_camera_io_w(*data_ptr++,
-				vfe_dev->vfe_base + reg_cfg_cmd->reg_offset);
+		uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL;
+		uint32_t hi_val, lo_val, lo_val1;
+		if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) {
+			if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset +
+				reg_cfg_cmd->u.dmi_info.len > cmd_len) {
+				pr_err("Invalid Hi Table out of bounds\n");
+				return -EINVAL;
+			}
+			hi_tbl_ptr = cfg_data +
+				reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4;
+		}
+
+		if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset +
+			reg_cfg_cmd->u.dmi_info.len > cmd_len) {
+			pr_err("Invalid Lo Table out of bounds\n");
+			return -EINVAL;
+		}
+		lo_tbl_ptr = cfg_data +
+			reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4;
+
+		for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) {
+			lo_val = *lo_tbl_ptr++;
+			if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_16BIT) {
+				lo_val1 = lo_val & 0x0000FFFF;
+				lo_val = (lo_val & 0xFFFF0000)>>16;
+				msm_camera_io_w(lo_val1, vfe_dev->vfe_base +
+								0x091C);
+			} else if (reg_cfg_cmd->cmd_type ==
+					VFE_WRITE_DMI_64BIT) {
+				hi_val = *hi_tbl_ptr++;
+				msm_camera_io_w(hi_val, vfe_dev->vfe_base +
+					   0x0918);
+			}
+			msm_camera_io_w(lo_val, vfe_dev->vfe_base +
+							0x091C);
+		}
+		break;
+	}
+	case VFE_READ_DMI_16BIT:
+	case VFE_READ_DMI_32BIT:
+	case VFE_READ_DMI_64BIT: {
+		int i;
+		uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL;
+		uint32_t hi_val, lo_val, lo_val1;
+		if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) {
+			if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset +
+				reg_cfg_cmd->u.dmi_info.len > cmd_len) {
+				pr_err("Invalid Hi Table out of bounds\n");
+				return -EINVAL;
+			}
+			hi_tbl_ptr = cfg_data +
+				reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4;
+		}
+
+		if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset +
+			reg_cfg_cmd->u.dmi_info.len > cmd_len) {
+			pr_err("Invalid Lo Table out of bounds\n");
+			return -EINVAL;
+		}
+		lo_tbl_ptr = cfg_data +
+			reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4;
+
+		for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) {
+			if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) {
+				hi_val = msm_camera_io_r(vfe_dev->vfe_base +
+								0x0918);
+				*hi_tbl_ptr++ = hi_val;
+			}
+
+			lo_val = msm_camera_io_r(vfe_dev->vfe_base +
+							0x091C);
+
+			if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_16BIT) {
+				lo_val1 = msm_camera_io_r(vfe_dev->vfe_base +
+								0x091C);
+				lo_val |= lo_val1 << 16;
+			}
+			*lo_tbl_ptr++ = lo_val;
+		}
 		break;
 	}
 	case VFE_READ: {
 		int i;
-		uint32_t *data_ptr = cfg_data + reg_cfg_cmd->cmd_data/4;
-		for (i = 0; i < reg_cfg_cmd->len/4; i++)
-			*data_ptr++ = msm_camera_io_r(
-				vfe_dev->vfe_base + reg_cfg_cmd->reg_offset++);
+		uint32_t *data_ptr = cfg_data +
+			reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
+		for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++)
+			*data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base +
+				reg_cfg_cmd->u.rw_info.reg_offset++);
 		break;
 	}
 	}
@@ -244,7 +324,8 @@
 	}
 
 	for (i = 0; i < proc_cmd->num_cfg; i++)
-		msm_isp_send_hw_cmd(vfe_dev, &reg_cfg_cmd[i], cfg_data);
+		msm_isp_send_hw_cmd(vfe_dev, &reg_cfg_cmd[i],
+			cfg_data, proc_cmd->cmd_len);
 
 	if (copy_to_user(proc_cmd->cfg_data,
 			cfg_data, proc_cmd->cmd_len)) {
@@ -311,16 +392,104 @@
 	return val;
 }
 
+int msm_isp_get_bit_per_pixel(uint32_t output_format)
+{
+	switch (output_format) {
+	case V4L2_PIX_FMT_SBGGR8:
+	case V4L2_PIX_FMT_SGBRG8:
+	case V4L2_PIX_FMT_SGRBG8:
+	case V4L2_PIX_FMT_SRGGB8:
+		return 8;
+	case V4L2_PIX_FMT_SBGGR10:
+	case V4L2_PIX_FMT_SGBRG10:
+	case V4L2_PIX_FMT_SGRBG10:
+	case V4L2_PIX_FMT_SRGGB10:
+		return 10;
+	case V4L2_PIX_FMT_SBGGR12:
+	case V4L2_PIX_FMT_SGBRG12:
+	case V4L2_PIX_FMT_SGRBG12:
+	case V4L2_PIX_FMT_SRGGB12:
+		return 12;
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		return 8;
+		/*TD: Add more image format*/
+	default:
+		pr_err("%s: Invalid output format\n", __func__);
+		break;
+	}
+	return -EINVAL;
+}
+
+void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev)
+{
+	struct msm_vfe_error_info *error_info = &vfe_dev->error_info;
+	error_info->info_dump_frame_count++;
+	if (error_info->info_dump_frame_count == 0)
+		error_info->info_dump_frame_count++;
+}
+
+void msm_isp_process_error_info(struct vfe_device *vfe_dev)
+{
+	int i;
+	struct msm_vfe_error_info *error_info = &vfe_dev->error_info;
+	if (error_info->error_count == 1 ||
+		!(error_info->info_dump_frame_count % 100)) {
+		vfe_dev->hw_info->vfe_ops.core_ops.
+			process_error_status(vfe_dev);
+		error_info->error_mask0 = 0;
+		error_info->error_mask1 = 0;
+		error_info->camif_status = 0;
+		error_info->violation_status = 0;
+		for (i = 0; i < MAX_NUM_STREAM; i++) {
+			if (error_info->stream_framedrop_count[i] != 0) {
+				pr_err("%s: Stream[%d]: dropped %d frames\n",
+					__func__, i,
+					error_info->stream_framedrop_count[i]);
+				error_info->stream_framedrop_count[i] = 0;
+			}
+		}
+		for (i = 0; i < MSM_ISP_STATS_MAX; i++) {
+			if (error_info->stats_framedrop_count[i] != 0) {
+				pr_err("%s: Stats stream[%d]: dropped %d frames\n",
+					__func__, i,
+					error_info->stats_framedrop_count[i]);
+				error_info->stats_framedrop_count[i] = 0;
+			}
+		}
+	}
+}
+
+static inline void msm_isp_update_error_info(struct vfe_device *vfe_dev,
+	uint32_t error_mask0, uint32_t error_mask1)
+{
+	vfe_dev->error_info.error_mask0 |= error_mask0;
+	vfe_dev->error_info.error_mask1 |= error_mask1;
+	vfe_dev->error_info.error_count++;
+}
+
 irqreturn_t msm_isp_process_irq(int irq_num, void *data)
 {
 	unsigned long flags;
 	struct msm_vfe_tasklet_queue_cmd *queue_cmd;
 	struct vfe_device *vfe_dev = (struct vfe_device *) data;
 	uint32_t irq_status0, irq_status1;
+	uint32_t error_mask0, error_mask1;
 
 	vfe_dev->hw_info->vfe_ops.irq_ops.
 		read_irq_status(vfe_dev, &irq_status0, &irq_status1);
-	if ((irq_status0 == 0) && (irq_status1 == 0)) {
+	vfe_dev->hw_info->vfe_ops.core_ops.
+		get_error_mask(&error_mask0, &error_mask1);
+	error_mask0 &= irq_status0;
+	error_mask1 &= irq_status1;
+	irq_status0 &= ~error_mask0;
+	irq_status1 &= ~error_mask1;
+	if ((error_mask0 != 0) || (error_mask1 != 0))
+		msm_isp_update_error_info(vfe_dev, error_mask0, error_mask1);
+
+	if ((irq_status0 == 0) && (irq_status1 == 0) &&
+		(!((error_mask0 != 0) || (error_mask1 != 0)) &&
+		 vfe_dev->error_info.error_count == 1)) {
 		ISP_DBG("%s: irq_status0 & 1 are both 0!\n", __func__);
 		return IRQ_HANDLED;
 	}
@@ -376,14 +545,14 @@
 		irq_ops->process_halt_irq(vfe_dev,
 			irq_status0, irq_status1);
 		irq_ops->process_camif_irq(vfe_dev,
-			irq_status0, irq_status1);
-		irq_ops->process_error_irq(vfe_dev,
-			irq_status0, irq_status1);
+			irq_status0, irq_status1, &tv);
 		irq_ops->process_axi_irq(vfe_dev,
 			irq_status0, irq_status1, &tv);
 		irq_ops->process_stats_irq(vfe_dev,
 			irq_status0, irq_status1, &tv);
-		irq_ops->process_reg_update(vfe_dev, irq_status0, irq_status1);
+		irq_ops->process_reg_update(vfe_dev,
+			irq_status0, irq_status1, &tv);
+		msm_isp_process_error_info(vfe_dev);
 	}
 }
 
@@ -396,6 +565,7 @@
 
 int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
+	uint32_t i;
 	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
 	long rc;
 	ISP_DBG("%s\n", __func__);
@@ -421,10 +591,15 @@
 	}
 	vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
 
-	vfe_dev->buf_mgr->ops->attach_ctx(vfe_dev->buf_mgr, vfe_dev->iommu_ctx);
+	for (i = 0; i < vfe_dev->hw_info->num_iommu_ctx; i++)
+		vfe_dev->buf_mgr->ops->attach_ctx(vfe_dev->buf_mgr,
+			vfe_dev->iommu_ctx[i]);
 	vfe_dev->buf_mgr->ops->buf_mgr_init(vfe_dev->buf_mgr, "msm_isp", 14);
 
 	memset(&vfe_dev->axi_data, 0, sizeof(struct msm_vfe_axi_shared_data));
+	memset(&vfe_dev->stats_data, 0,
+		sizeof(struct msm_vfe_stats_shared_data));
+	memset(&vfe_dev->error_info, 0, sizeof(vfe_dev->error_info));
 	vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
 
 	ISP_DBG("%s: HW Version: 0x%x\n",
@@ -438,6 +613,7 @@
 
 int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
+	int i;
 	long rc;
 	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
 	ISP_DBG("%s\n", __func__);
@@ -453,7 +629,11 @@
 		pr_err("%s: halt timeout\n", __func__);
 
 	vfe_dev->buf_mgr->ops->buf_mgr_deinit(vfe_dev->buf_mgr);
-	vfe_dev->buf_mgr->ops->detach_ctx(vfe_dev->buf_mgr, vfe_dev->iommu_ctx);
+
+	for (i = vfe_dev->hw_info->num_iommu_ctx - 1; i >= 0; i--)
+		vfe_dev->buf_mgr->ops->detach_ctx(vfe_dev->buf_mgr,
+			vfe_dev->iommu_ctx[i]);
+
 	vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
 
 	vfe_dev->vfe_open_cnt--;
diff --git a/drivers/media/video/msmb/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
similarity index 90%
rename from drivers/media/video/msmb/isp/msm_isp_util.h
rename to drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index 729c8b5..6c2a88c 100644
--- a/drivers/media/video/msmb/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -35,10 +35,12 @@
 	uint32_t type, struct msm_isp_event_data *event_data);
 int msm_isp_cal_word_per_line(uint32_t output_format,
 	uint32_t pixel_per_line);
+int msm_isp_get_bit_per_pixel(uint32_t output_format);
 irqreturn_t msm_isp_process_irq(int irq_num, void *data);
 void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
 void msm_isp_do_tasklet(unsigned long data);
-
+void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev);
+void msm_isp_process_error_info(struct vfe_device *vfe_dev);
 int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
 int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
 long msm_isp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/Makefile b/drivers/media/platform/msm/camera_v2/ispif/Makefile
new file mode 100644
index 0000000..443911f
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/ispif/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_MSM_CSID) += msm_ispif.o
diff --git a/drivers/media/video/msmb/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
similarity index 71%
rename from drivers/media/video/msmb/ispif/msm_ispif.c
rename to drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index ffb9263..50e685a 100644
--- a/drivers/media/video/msmb/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -22,19 +22,22 @@
 
 #include "msm_ispif.h"
 #include "msm.h"
-#include "msm_ispif_hwreg.h"
 #include "msm_sd.h"
 #include "msm_camera_io_util.h"
 
+#ifdef CONFIG_MSM_ISPIF_V1
+#include "msm_ispif_hwreg_v1.h"
+#else
+#include "msm_ispif_hwreg_v2.h"
+#endif
+
 #define V4L2_IDENT_ISPIF                      50001
 #define MSM_ISPIF_DRV_NAME                    "msm_ispif"
-#define DUMP_BUFF_SIZE_128                    128
 
-#define ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY  0x01
 #define ISPIF_INTF_CMD_DISABLE_FRAME_BOUNDARY 0x00
+#define ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY  0x01
 #define ISPIF_INTF_CMD_DISABLE_IMMEDIATELY    0x02
 
-#define CONFIG_MSMB_CAMERA_DEBUG
 #undef CDBG
 #ifdef CONFIG_MSMB_CAMERA_DEBUG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
@@ -42,43 +45,18 @@
 #define CDBG(fmt, args...) do { } while (0)
 #endif
 
-static void msm_ispif_io_dump(void __iomem *addr, int size)
-{
-	char line_str[DUMP_BUFF_SIZE_128], *p_str;
-	int i;
-	u32 *p = (u32 *) addr;
-	u32 data;
-
-
-	CDBG("%s: %p %d\n", __func__, 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 = readl_relaxed(p++);
-		snprintf(p_str, 12, "%08x ", data);
-		p_str += 9;
-		if ((i + 1) % 4 == 0) {
-			CDBG("%s\n", line_str);
-			line_str[0] = '\0';
-			p_str = line_str;
-		}
-	}
-	if (line_str[0] != '\0')
-		CDBG("%s\n", line_str);
-}
-
 static void msm_ispif_io_dump_reg(struct ispif_device *ispif)
 {
-	int size;
-
 	if (!ispif->enb_dump_reg)
 		return;
-	size = 0x250;
-	msm_ispif_io_dump(ispif->base+0x100, size);
+	msm_camera_io_dump(ispif->base, 0x250);
+}
+
+static inline int msm_ispif_is_intf_valid(uint32_t csid_version,
+	uint8_t intf_type)
+{
+	return (csid_version <= CSID_VERSION_V2 && intf_type != VFE0) ?
+		false : true;
 }
 
 static int msm_ispif_intf_reset(struct ispif_device *ispif,
@@ -87,31 +65,26 @@
 
 	int i, rc = 0;
 	enum msm_ispif_intftype intf_type;
-	uint32_t data = (0x1 << STROBED_RST_EN);
+	uint32_t data = STROBED_RST_EN;
 
 	for (i = 0; i < params->num; i++) {
 		intf_type = params->entries[i].intftype;
 		ispif->sof_count[params->vfe_intf].sof_cnt[intf_type] = 0;
 		switch (intf_type) {
 		case PIX0:
-			data |= (0x1 << PIX_0_VFE_RST_STB) |
-				(0x1 << PIX_0_CSID_RST_STB);
+			data |= (PIX_0_VFE_RST_STB | PIX_0_CSID_RST_STB);
 			break;
 		case RDI0:
-			data |= (0x1 << RDI_0_VFE_RST_STB) |
-				(0x1 << RDI_0_CSID_RST_STB);
+			data |= (RDI_0_VFE_RST_STB | RDI_0_CSID_RST_STB);
 			break;
 		case PIX1:
-			data |= (0x1 << PIX_1_VFE_RST_STB) |
-				(0x1 << PIX_1_CSID_RST_STB);
+			data |= (PIX_1_VFE_RST_STB | PIX_1_CSID_RST_STB);
 			break;
 		case RDI1:
-			data |= (0x1 << RDI_1_VFE_RST_STB) |
-				(0x1 << RDI_1_CSID_RST_STB);
+			data |= (RDI_1_VFE_RST_STB | RDI_1_CSID_RST_STB);
 			break;
 		case RDI2:
-			data |= (0x1 << RDI_2_VFE_RST_STB) |
-				(0x1 << RDI_2_CSID_RST_STB);
+			data |= (RDI_2_VFE_RST_STB | RDI_2_CSID_RST_STB);
 			break;
 		default:
 			rc = -EINVAL;
@@ -139,14 +112,19 @@
 static int msm_ispif_reset(struct ispif_device *ispif)
 {
 	int rc = 0;
-	unsigned long jiffes = msecs_to_jiffies(500);
 	long lrc = 0;
+	unsigned long jiffes = msecs_to_jiffies(500);
 
-	memset(ispif->sof_count,  0,  sizeof(ispif->sof_count));
+	BUG_ON(!ispif);
+
+	memset(ispif->sof_count, 0, sizeof(ispif->sof_count));
+
 	msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR);
-	if (ispif->csid_version == CSID_VERSION_V3)
+
+	if (ispif->csid_version >= CSID_VERSION_V3)
 		msm_camera_io_w_mb(ISPIF_RST_CMD_1_MASK, ispif->base +
 			ISPIF_RST_CMD_1_ADDR);
+
 	CDBG("%s: Sending reset\n", __func__);
 	lrc = wait_for_completion_interruptible_timeout(
 		&ispif->reset_complete, jiffes);
@@ -155,6 +133,7 @@
 		rc = -EIO;
 	}
 	CDBG("%s: reset returned\n", __func__);
+
 	return rc;
 }
 
@@ -171,133 +150,132 @@
 	uint8_t intftype, uint8_t csid, uint8_t vfe_intf)
 {
 	int rc = 0;
-	uint32_t data = 0;
+	uint32_t data;
+
+	BUG_ON(!ispif);
+
+	if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+		pr_err("%s: invalid interface type\n", __func__);
+		return;
+	}
 
 	if (ispif->csid_version <= CSID_VERSION_V2) {
 		if (ispif->ispif_clk[intftype] == NULL) {
 			CDBG("%s: ispif NULL clk\n", __func__);
 			return;
 		}
+
 		rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
-		if (rc < 0)
+		if (rc) {
 			pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
-		return;
+			return;
+		}
 	}
+
 	data = msm_camera_io_r(ispif->base + ISPIF_INPUT_SEL_ADDR +
 		(0x200 * vfe_intf));
 	switch (intftype) {
 	case PIX0:
-		data &= ~(0x3);        /* clear old setting */
-		data |= csid;          /* add new setting */
+		data &= ~(BIT(1) | BIT(0));
+		data |= csid;
 		break;
 	case RDI0:
-		data &= ~(0x3 << 4);   /* clear old setting */
-		data |= (csid << 4);   /* add new setting */
+		data &= ~(BIT(5) | BIT(4));
+		data |= (csid << 4);
 		break;
 	case PIX1:
-		data &= ~(0x3 << 8);   /* clear old setting */
-		data |= (csid << 8);   /* add new setting */
+		data &= ~(BIT(9) | BIT(8));
+		data |= (csid << 8);
 		break;
 	case RDI1:
-		data &= ~(0x3 << 12);  /* clear old setting */
-		data |= (csid << 12);  /* add new setting */
+		data &= ~(BIT(13) | BIT(12));
+		data |= (csid << 12);
 		break;
 	case RDI2:
-		data &= ~(0x3 << 20);  /* clear old setting */
-		data |= (csid << 20);  /* add new setting */
+		data &= ~(BIT(21) | BIT(20));
+		data |= (csid << 20);
 		break;
 	}
-	if (data) {
+	if (data)
 		msm_camera_io_w_mb(data, ispif->base + ISPIF_INPUT_SEL_ADDR +
 			(0x200 * vfe_intf));
-	}
 }
 
 static void msm_ispif_enable_intf_cids(struct ispif_device *ispif,
-	uint8_t intftype, uint16_t cid_mask,
-	uint8_t vfe_intf, uint8_t enable)
+	uint8_t intftype, uint16_t cid_mask, uint8_t vfe_intf, uint8_t enable)
 {
-	uint32_t data = 0;
+	uint32_t intf_addr, data;
+
+	BUG_ON(!ispif);
+
+	if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+		pr_err("%s: invalid interface type\n", __func__);
+		return;
+	}
 
 	switch (intftype) {
 	case PIX0:
-		data = msm_camera_io_r(ispif->base +
-		ISPIF_PIX_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
-		if (enable)
-			data |= cid_mask;  /* add new config */
-		else
-			data &= ~cid_mask;  /* remove CID bit */
-		msm_camera_io_w_mb(data, ispif->base +
-		ISPIF_PIX_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		intf_addr = ISPIF_PIX_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
 		break;
 	case RDI0:
-		data = msm_camera_io_r(ispif->base +
-		ISPIF_RDI_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
-		if (enable)
-			data |= cid_mask;  /* add new config */
-		else
-			data &= ~cid_mask;  /* remove CID bit */
-		msm_camera_io_w_mb(data, ispif->base +
-			ISPIF_RDI_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		intf_addr = ISPIF_RDI_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
 		break;
 	case PIX1:
-		data = msm_camera_io_r(ispif->base +
-		ISPIF_PIX_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
-		if (enable)
-			data |= cid_mask;  /* add new config */
-		else
-			data &= ~cid_mask;  /* remove CID bit */
-		msm_camera_io_w_mb(data, ispif->base +
-			ISPIF_PIX_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		intf_addr = ISPIF_PIX_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
 		break;
 	case RDI1:
-		data = msm_camera_io_r(ispif->base +
-			ISPIF_RDI_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
-		if (enable)
-			data |= cid_mask;  /* add new config */
-		else
-			data &= ~cid_mask;  /* remove CID bit */
-		msm_camera_io_w_mb(data, ispif->base +
-			ISPIF_RDI_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		intf_addr = ISPIF_RDI_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
 		break;
 	case RDI2:
-		data = msm_camera_io_r(ispif->base +
-			ISPIF_RDI_2_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
-		if (enable)
-			data |= cid_mask;  /* add new config */
-		else
-			data &= ~cid_mask;  /* remove CID bit */
-		msm_camera_io_w_mb(data, ispif->base +
-			ISPIF_RDI_2_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		intf_addr = ISPIF_RDI_2_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
 		break;
+	default:
+		pr_err("%s: invalid intftype=%d\n", __func__, intftype);
+		BUG_ON(1);
+		return;
 	}
+
+	data = msm_camera_io_r(ispif->base + intf_addr);
+	if (enable)
+		data |= cid_mask;
+	else
+		data &= ~cid_mask;
+	msm_camera_io_w_mb(data, ispif->base + intf_addr);
 }
 
-static int32_t msm_ispif_validate_intf_status(struct ispif_device *ispif,
+static int msm_ispif_validate_intf_status(struct ispif_device *ispif,
 	uint8_t intftype, uint8_t vfe_intf)
 {
-	int32_t rc = 0;
+	int rc = 0;
 	uint32_t data = 0;
+
+	BUG_ON(!ispif);
+
+	if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+		pr_err("%s: invalid interface type\n", __func__);
+		return -EINVAL;
+	}
+
 	switch (intftype) {
 	case PIX0:
 		data = msm_camera_io_r(ispif->base +
-		ISPIF_PIX_0_STATUS_ADDR + (0x200 * vfe_intf));
+			ISPIF_PIX_0_STATUS_ADDR + (0x200 * vfe_intf));
 		break;
 	case RDI0:
 		data = msm_camera_io_r(ispif->base +
-		ISPIF_RDI_0_STATUS_ADDR + (0x200 * vfe_intf));
+			ISPIF_RDI_0_STATUS_ADDR + (0x200 * vfe_intf));
 		break;
 	case PIX1:
 		data = msm_camera_io_r(ispif->base +
-		ISPIF_PIX_1_STATUS_ADDR + (0x200 * vfe_intf));
+			ISPIF_PIX_1_STATUS_ADDR + (0x200 * vfe_intf));
 		break;
 	case RDI1:
 		data = msm_camera_io_r(ispif->base +
-		ISPIF_RDI_1_STATUS_ADDR + (0x200 * vfe_intf));
+			ISPIF_RDI_1_STATUS_ADDR + (0x200 * vfe_intf));
 		break;
 	case RDI2:
 		data = msm_camera_io_r(ispif->base +
-		ISPIF_RDI_2_STATUS_ADDR + (0x200 * vfe_intf));
+			ISPIF_RDI_2_STATUS_ADDR + (0x200 * vfe_intf));
 		break;
 	}
 	if ((data & 0xf) != 0xf)
@@ -311,8 +289,11 @@
 	int i;
 	uint16_t cids_mask = 0;
 
+	BUG_ON(!entry);
+
 	for (i = 0; i < entry->num_cids; i++)
 		cids_mask |= (1 << entry->cids[i]);
+
 	return cids_mask;
 }
 
@@ -320,33 +301,46 @@
 	struct msm_ispif_param_data *params)
 {
 	int rc = 0, i = 0;
-	enum msm_ispif_intftype intftype;
-	enum msm_ispif_vfe_intf vfe_intf = params->vfe_intf;
 	uint16_t cid_mask;
+	enum msm_ispif_intftype intftype;
+	enum msm_ispif_vfe_intf vfe_intf;
 
-	msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_ADDR);
-	msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_1_ADDR);
-	msm_camera_io_w_mb(0x00000000, ispif->base + ISPIF_IRQ_MASK_2_ADDR);
+	BUG_ON(!ispif);
+	BUG_ON(!params);
+
+	vfe_intf = params->vfe_intf;
+	if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+		pr_err("%s: invalid interface type\n", __func__);
+		return -EINVAL;
+	}
+
+	msm_camera_io_w(0x0, ispif->base + ISPIF_IRQ_MASK_ADDR);
+	msm_camera_io_w(0x0, ispif->base + ISPIF_IRQ_MASK_1_ADDR);
+	msm_camera_io_w_mb(0x0, ispif->base + ISPIF_IRQ_MASK_2_ADDR);
+
 	for (i = 0; i < params->num; i++) {
 		intftype = params->entries[i].intftype;
+
 		vfe_intf = params->vfe_intf;
+
 		CDBG("%s intftype %x, vfe_intf %d, csid %d\n", __func__,
-		intftype, vfe_intf, params->entries[i].csid);
-		if ((intftype >= INTF_MAX) ||
-				(ispif->csid_version <= CSID_VERSION_V2 &&
-				vfe_intf > VFE0) ||
-				(ispif->csid_version == CSID_VERSION_V3 &&
-				vfe_intf >= VFE_MAX)) {
+			intftype, vfe_intf, params->entries[i].csid);
+
+		if ((intftype >= INTF_MAX) || (vfe_intf >= VFE_MAX) ||
+			(ispif->csid_version <= CSID_VERSION_V2 &&
+			(vfe_intf > VFE0))) {
 			pr_err("%s: VFEID %d and CSID version %d mismatch\n",
 				__func__, vfe_intf, ispif->csid_version);
 			return -EINVAL;
 		}
+
 		rc = msm_ispif_validate_intf_status(ispif, intftype, vfe_intf);
-		if (rc < 0) {
+		if (rc) {
 			pr_err("%s:validate_intf_status failed, rc = %d\n",
 				__func__, rc);
 			return rc;
 		}
+
 		msm_ispif_sel_csid_core(ispif, intftype,
 			params->entries[i].csid, vfe_intf);
 		cid_mask = msm_ispif_get_cids_mask_from_cfg(
@@ -375,19 +369,27 @@
 
 	msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
 		ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+
 	return rc;
 }
 
-static void msm_ispif_intf_cmd(struct ispif_device *ispif,
-	uint32_t cmd_bits,
+static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint32_t cmd_bits,
 	struct msm_ispif_param_data *params)
 {
-	uint8_t vc = 0;
+	uint8_t vc;
 	int i, k;
 	enum msm_ispif_intftype intf_type;
 	enum msm_ispif_cid cid;
 	enum msm_ispif_vfe_intf vfe_intf = params->vfe_intf;
 
+	BUG_ON(!ispif);
+	BUG_ON(!params);
+
+	if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+		pr_err("%s: invalid interface type\n", __func__);
+		return;
+	}
+
 	for (i = 0; i < params->num; i++) {
 		intf_type = params->entries[i].intftype;
 		for (k = 0; k < params->entries[i].num_cids; k++) {
@@ -397,15 +399,16 @@
 				/* zero out two bits */
 				ispif->applied_intf_cmd[vfe_intf].intf_cmd1 &=
 					~(0x3 << (vc * 2 + 8));
+				/* set cmd bits */
 				ispif->applied_intf_cmd[vfe_intf].intf_cmd1 |=
-				(cmd_bits << (vc * 2 + 8)); /* set cmd bits */
+					(cmd_bits << (vc * 2 + 8));
 			} else {
 				/* zero 2 bits */
 				ispif->applied_intf_cmd[vfe_intf].intf_cmd &=
 					~(0x3 << (vc * 2 + vfe_intf * 8));
 				/* set cmd bits */
 				ispif->applied_intf_cmd[vfe_intf].intf_cmd |=
-				(cmd_bits << (vc * 2 + vfe_intf * 8));
+					(cmd_bits << (vc * 2 + vfe_intf * 8));
 			}
 		}
 	}
@@ -428,6 +431,9 @@
 	int i, rc = 0;
 	uint16_t cid_mask = 0;
 
+	BUG_ON(!ispif);
+	BUG_ON(!params);
+
 	msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_DISABLE_IMMEDIATELY, params);
 
 	/* after stop the interface we need to unmask the CID enable bits */
@@ -435,7 +441,7 @@
 		cid_mask = msm_ispif_get_cids_mask_from_cfg(
 			&params->entries[i]);
 		msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
-		cid_mask, params->vfe_intf, 0);
+			cid_mask, params->vfe_intf, 0);
 	}
 	return rc;
 }
@@ -443,9 +449,15 @@
 static int msm_ispif_start_frame_boundary(struct ispif_device *ispif,
 	struct msm_ispif_param_data *params)
 {
-	int rc = 0;
+	int rc;
 
 	rc = msm_ispif_intf_reset(ispif, params);
+	if (rc) {
+		pr_err("%s: msm_ispif_intf_reset failed. rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
 	msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY, params);
 	return rc;
 }
@@ -455,55 +467,58 @@
 {
 	int i, rc = 0;
 	uint16_t cid_mask = 0;
+	uint32_t intf_addr;
+
+	BUG_ON(!ispif);
+	BUG_ON(!params);
+
+	if (!msm_ispif_is_intf_valid(ispif->csid_version, params->vfe_intf)) {
+		pr_err("%s: invalid interface type\n", __func__);
+		return -EINVAL;
+	}
 
 	msm_ispif_intf_cmd(ispif,
 		ISPIF_INTF_CMD_DISABLE_FRAME_BOUNDARY, params);
+
 	for (i = 0; i < params->num; i++) {
 		cid_mask =
-			msm_ispif_get_cids_mask_from_cfg(
-				&params->entries[i]);
+			msm_ispif_get_cids_mask_from_cfg(&params->entries[i]);
+
 		switch (params->entries[i].intftype) {
 		case PIX0:
-			while ((msm_camera_io_r(ispif->base +
-				ISPIF_PIX_0_STATUS_ADDR +
-				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
-				CDBG("Wait for pix0 Idle\n");
-			}
+			intf_addr = ISPIF_PIX_0_STATUS_ADDR +
+				(0x200 * params->vfe_intf);
 			break;
 		case RDI0:
-			while ((msm_camera_io_r(ispif->base +
-				ISPIF_RDI_0_STATUS_ADDR +
-				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
-				CDBG("Wait for rdi0 Idle\n");
-			}
+			intf_addr = ISPIF_RDI_0_STATUS_ADDR +
+				(0x200 * params->vfe_intf);
 			break;
 		case PIX1:
-			while ((msm_camera_io_r(ispif->base +
-				ISPIF_PIX_1_STATUS_ADDR +
-				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
-				CDBG("Wait for pix1 Idle\n");
-			}
+			intf_addr = ISPIF_PIX_1_STATUS_ADDR +
+				(0x200 * params->vfe_intf);
 			break;
 		case RDI1:
-			while ((msm_camera_io_r(ispif->base +
-				ISPIF_RDI_1_STATUS_ADDR +
-				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
-				CDBG("Wait for rdi1 Idle\n");
-			}
+			intf_addr = ISPIF_RDI_1_STATUS_ADDR +
+				(0x200 * params->vfe_intf);
 			break;
 		case RDI2:
-			while ((msm_camera_io_r(ispif->base +
-				ISPIF_RDI_2_STATUS_ADDR +
-				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
-				CDBG("Wait for rdi2 Idle\n");
-			}
+			intf_addr = ISPIF_RDI_2_STATUS_ADDR +
+				(0x200 * params->vfe_intf);
 			break;
 		default:
-			break;
+			pr_err("%s: invalid intftype=%d\n", __func__,
+				params->entries[i].intftype);
+			return -EPERM;
 		}
+
+		/* todo_bug_fix? very bad. use readl_poll_timeout */
+		while ((msm_camera_io_r(ispif->base + intf_addr) & 0xF) != 0xF)
+			CDBG("%s: Wait for %d Idle\n", __func__,
+				params->entries[i].intftype);
+
 		/* disable CIDs in CID_MASK register */
 		msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
-		cid_mask, params->vfe_intf, 0);
+			cid_mask, params->vfe_intf, 0);
 	}
 	return rc;
 }
@@ -511,6 +526,9 @@
 static void ispif_process_irq(struct ispif_device *ispif,
 	struct ispif_irq_status *out, enum msm_ispif_vfe_intf vfe_id)
 {
+	BUG_ON(!ispif);
+	BUG_ON(!out);
+
 	if (out[vfe_id].ispifIrqStatus0 &
 			ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
 		ispif->sof_count[vfe_id].sof_cnt[PIX0]++;
@@ -527,7 +545,6 @@
 			ISPIF_IRQ_STATUS_RDI2_SOF_MASK) {
 		ispif->sof_count[vfe_id].sof_cnt[RDI2]++;
 	}
-	return;
 }
 
 static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
@@ -535,74 +552,71 @@
 {
 	struct ispif_device *ispif = (struct ispif_device *)data;
 
+	BUG_ON(!ispif);
+	BUG_ON(!out);
+
 	out[VFE0].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
 		ISPIF_IRQ_STATUS_ADDR);
-	out[VFE0].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
-		ISPIF_IRQ_STATUS_1_ADDR);
-	out[VFE0].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
-		ISPIF_IRQ_STATUS_2_ADDR);
 	msm_camera_io_w(out[VFE0].ispifIrqStatus0,
 		ispif->base + ISPIF_IRQ_CLEAR_ADDR);
+
+	out[VFE0].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
+		ISPIF_IRQ_STATUS_1_ADDR);
 	msm_camera_io_w(out[VFE0].ispifIrqStatus1,
 		ispif->base + ISPIF_IRQ_CLEAR_1_ADDR);
+
+	out[VFE0].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
+		ISPIF_IRQ_STATUS_2_ADDR);
 	msm_camera_io_w_mb(out[VFE0].ispifIrqStatus2,
 		ispif->base + ISPIF_IRQ_CLEAR_2_ADDR);
 
 	if (out[VFE0].ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
-		if (out[VFE0].ispifIrqStatus0 & (0x1 <<
-				RESET_DONE_IRQ))
+		if (out[VFE0].ispifIrqStatus0 & RESET_DONE_IRQ)
 			complete(&ispif->reset_complete);
-		if (out[VFE0].ispifIrqStatus0 & (0x1 <<
-				PIX_INTF_0_OVERFLOW_IRQ))
+
+		if (out[VFE0].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ)
 			pr_err("%s: VFE0 pix0 overflow.\n", __func__);
-		if (out[VFE0].ispifIrqStatus0 & (0x1 <<
-				RAW_INTF_0_OVERFLOW_IRQ))
+
+		if (out[VFE0].ispifIrqStatus0 & RAW_INTF_0_OVERFLOW_IRQ)
 			pr_err("%s: VFE0 rdi0 overflow.\n", __func__);
-		if (out[VFE0].ispifIrqStatus1 & (0x1 <<
-				RAW_INTF_1_OVERFLOW_IRQ))
+
+		if (out[VFE0].ispifIrqStatus1 & RAW_INTF_1_OVERFLOW_IRQ)
 			pr_err("%s: VFE0 rdi1 overflow.\n", __func__);
-		if (out[VFE0].ispifIrqStatus2 & (0x1 <<
-				RAW_INTF_2_OVERFLOW_IRQ))
+
+		if (out[VFE0].ispifIrqStatus2 & RAW_INTF_2_OVERFLOW_IRQ)
 			pr_err("%s: VFE0 rdi2 overflow.\n", __func__);
-		if ((out[VFE0].ispifIrqStatus0 &
-			ISPIF_IRQ_STATUS_SOF_MASK) ||
-				(out[VFE0].ispifIrqStatus1 &
-					ISPIF_IRQ_STATUS_SOF_MASK) ||
-				(out[VFE0].ispifIrqStatus2 &
-					ISPIF_IRQ_STATUS_RDI2_SOF_MASK))
-			ispif_process_irq(ispif, out, VFE0);
+
+		ispif_process_irq(ispif, out, VFE0);
 	}
-	if (ispif->csid_version == CSID_VERSION_V3) {
+	if (ispif->csid_version >= CSID_VERSION_V3) {
 		out[VFE1].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
 			ISPIF_IRQ_STATUS_ADDR + 0x200);
 		msm_camera_io_w(out[VFE1].ispifIrqStatus0,
 			ispif->base + ISPIF_IRQ_CLEAR_ADDR + 0x200);
+
 		out[VFE1].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
 			ISPIF_IRQ_STATUS_1_ADDR + 0x200);
 		msm_camera_io_w(out[VFE1].ispifIrqStatus1,
-			ispif->base + ISPIF_IRQ_CLEAR_1_ADDR + 0x200);
+
+				ispif->base + ISPIF_IRQ_CLEAR_1_ADDR + 0x200);
 		out[VFE1].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
 			ISPIF_IRQ_STATUS_2_ADDR + 0x200);
 		msm_camera_io_w_mb(out[VFE1].ispifIrqStatus2,
 			ispif->base + ISPIF_IRQ_CLEAR_2_ADDR + 0x200);
-		if (out[VFE1].ispifIrqStatus0 & (0x1 <<
-				PIX_INTF_0_OVERFLOW_IRQ))
+
+		if (out[VFE1].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ)
 			pr_err("%s: VFE1 pix0 overflow.\n", __func__);
-		if (out[VFE1].ispifIrqStatus0 & (0x1 <<
-				RAW_INTF_0_OVERFLOW_IRQ))
+
+		if (out[VFE1].ispifIrqStatus0 & RAW_INTF_0_OVERFLOW_IRQ)
 			pr_err("%s: VFE1 rdi0 overflow.\n", __func__);
-		if (out[VFE1].ispifIrqStatus1 & (0x1 <<
-				RAW_INTF_1_OVERFLOW_IRQ))
+
+		if (out[VFE1].ispifIrqStatus1 & RAW_INTF_1_OVERFLOW_IRQ)
 			pr_err("%s: VFE1 rdi1 overflow.\n", __func__);
-		if (out[VFE1].ispifIrqStatus2 & (0x1 <<
-				RAW_INTF_2_OVERFLOW_IRQ))
+
+		if (out[VFE1].ispifIrqStatus2 & RAW_INTF_2_OVERFLOW_IRQ)
 			pr_err("%s: VFE1 rdi2 overflow.\n", __func__);
-		if ((out[VFE1].ispifIrqStatus0 & ISPIF_IRQ_STATUS_SOF_MASK) ||
-				(out[VFE1].ispifIrqStatus1 &
-					ISPIF_IRQ_STATUS_SOF_MASK) ||
-				(out[VFE1].ispifIrqStatus2 &
-					ISPIF_IRQ_STATUS_RDI2_SOF_MASK))
-			ispif_process_irq(ispif, out, VFE1);
+
+		ispif_process_irq(ispif, out, VFE1);
 	}
 	msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
 		ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
@@ -635,10 +649,12 @@
 {
 	int rc = 0;
 
+	BUG_ON(!ispif);
+
 	if (ispif->ispif_state == ISPIF_POWER_UP) {
-		CDBG("%s: ispif already initted state = %d\n", __func__,
-		ispif->ispif_state);
-		rc = -EAGAIN;
+		pr_err("%s: ispif already initted state = %d\n", __func__,
+			ispif->ispif_state);
+		rc = -EPERM;
 		return rc;
 	}
 
@@ -653,7 +669,7 @@
 	if (ispif->csid_version < CSID_VERSION_V2) {
 		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
 			ispif->ispif_clk, 2, 1);
-		if (rc < 0) {
+		if (rc) {
 			pr_err("%s: cannot enable clock, error = %d\n",
 				__func__, rc);
 			goto end;
@@ -661,19 +677,23 @@
 	} else if (ispif->csid_version == CSID_VERSION_V2) {
 		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
 			ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 1);
-		if (rc < 0) {
+		if (rc) {
+			pr_err("%s: cannot enable clock, error = %d\n",
+				__func__, rc);
+			goto end;
+		}
+	} else if (ispif->csid_version >= CSID_VERSION_V3) {
+		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), 1);
+		if (rc) {
 			pr_err("%s: cannot enable clock, error = %d\n",
 				__func__, rc);
 			goto end;
 		}
 	} else {
-		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
-			ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), 1);
-		if (rc < 0) {
-			pr_err("%s: cannot enable clock, error = %d\n",
-				__func__, rc);
-			goto end;
-		}
+		pr_err("%s: unsupported version=%d\n", __func__,
+			ispif->csid_version);
+		goto end;
 	}
 	ispif->base = ioremap(ispif->mem->start,
 		resource_size(ispif->mem));
@@ -684,11 +704,13 @@
 	}
 	rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
 		IRQF_TRIGGER_RISING, "ispif", ispif);
-	init_completion(&ispif->reset_complete);
-	if (rc < 0) {
+	if (rc) {
 		pr_err("%s: request_irq error = %d\n", __func__, rc);
 		goto error_irq;
 	}
+
+	init_completion(&ispif->reset_complete);
+
 	rc = msm_ispif_reset(ispif);
 	if (rc == 0) {
 		ispif->ispif_state = ISPIF_POWER_UP;
@@ -705,6 +727,9 @@
 	} else if (ispif->csid_version == CSID_VERSION_V2) {
 		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
 		ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
+	} else if (ispif->csid_version >= CSID_VERSION_V3) {
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), 0);
 	}
 end:
 	return rc;
@@ -712,59 +737,51 @@
 
 static void msm_ispif_release(struct ispif_device *ispif)
 {
+	BUG_ON(!ispif);
+
 	if (ispif->ispif_state != ISPIF_POWER_UP) {
 		pr_err("%s: ispif invalid state %d\n", __func__,
-		ispif->ispif_state);
+			ispif->ispif_state);
 		return;
 	}
+
 	/* make sure no streaming going on */
 	msm_ispif_reset(ispif);
+
 	free_irq(ispif->irq->start, ispif);
+
 	iounmap(ispif->base);
+
 	if (ispif->csid_version < CSID_VERSION_V2) {
 		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
 		ispif->ispif_clk, 2, 0);
 	} else if (ispif->csid_version == CSID_VERSION_V2) {
 		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
 			ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
+	} else if (ispif->csid_version >= CSID_VERSION_V3) {
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), 0);
 	}
 	ispif->ispif_state = ISPIF_POWER_DOWN;
 }
 
-static int msm_ispif_clk_enable(struct ispif_device *ispif,
-	uint32_t csid_version, int enable)
-{
-	int rc = 0;
-
-	if (csid_version != CSID_VERSION_V3)
-		goto end;
-	rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
-		ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), enable);
-	if (rc < 0)
-		pr_err("%s: cannot enable clock, error = %d\n", __func__, rc);
-end:
-	return rc;
-}
-
 static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
 {
 	long rc = 0;
 	struct ispif_cfg_data *pcdata = (struct ispif_cfg_data *)arg;
 	struct ispif_device *ispif =
 		(struct ispif_device *)v4l2_get_subdevdata(sd);
+
+	BUG_ON(!sd);
+	BUG_ON(!pcdata);
+
 	mutex_lock(&ispif->mutex);
+
 	switch (pcdata->cfg_type) {
-	case ISPIF_CLK_ENABLE:
-		rc = msm_ispif_clk_enable(ispif, pcdata->csid_version, 1);
-		break;
-	case ISPIF_CLK_DISABLE:
-		rc = msm_ispif_clk_enable(ispif, pcdata->csid_version, 0);
-		break;
 	case ISPIF_ENABLE_REG_DUMP:
 		ispif->enb_dump_reg = pcdata->reg_dump; /* save dump config */
 		break;
 	case ISPIF_INIT:
-		/* need to move back to CDBG */
 		rc = msm_ispif_init(ispif, pcdata->csid_version);
 		msm_ispif_io_dump_reg(ispif);
 		break;
@@ -788,6 +805,8 @@
 		msm_ispif_release(ispif);
 		break;
 	default:
+		pr_err("%s: invalid cfg_type\n", __func__);
+		rc = -EINVAL;
 		break;
 	}
 	mutex_unlock(&ispif->mutex);
@@ -809,7 +828,6 @@
 static int ispif_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
 	struct ispif_device *ispif = v4l2_get_subdevdata(sd);
-	int rc = 0;
 
 	mutex_lock(&ispif->mutex);
 	if (ispif->open_cnt > 0) {
@@ -820,18 +838,22 @@
 	ispif->open_cnt++;
 end:
 	mutex_unlock(&ispif->mutex);
-	return rc;
+	return 0;
 }
 
 static int ispif_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-	struct ispif_device *ispif = v4l2_get_subdevdata(sd);
 	int rc = 0;
+	struct ispif_device *ispif = v4l2_get_subdevdata(sd);
 
-	CDBG("%s\n", __func__);
+	if (!ispif) {
+		pr_err("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
 	mutex_lock(&ispif->mutex);
 	if (ispif->open_cnt == 0) {
-		pr_err("Invalid close\n");
+		pr_err("%s: Invalid close\n", __func__);
 		rc = -ENODEV;
 		goto end;
 	}
@@ -856,12 +878,12 @@
 	.open = ispif_open_node,
 	.close = ispif_close_node,
 };
+
 static int __devinit ispif_probe(struct platform_device *pdev)
 {
-	int rc = 0;
+	int rc;
 	struct ispif_device *ispif;
 
-	CDBG("%s\n", __func__);
 	ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
 	if (!ispif) {
 		pr_err("%s: no enough memory\n", __func__);
@@ -873,20 +895,22 @@
 	ispif->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
 	snprintf(ispif->msm_sd.sd.name,
-		ARRAY_SIZE(ispif->msm_sd.sd.name), "msm_ispif");
+		ARRAY_SIZE(ispif->msm_sd.sd.name), MSM_ISPIF_DRV_NAME);
 	v4l2_set_subdevdata(&ispif->msm_sd.sd, ispif);
+
 	platform_set_drvdata(pdev, &ispif->msm_sd.sd);
 	mutex_init(&ispif->mutex);
-	ispif->pdev = pdev;
+
 	media_entity_init(&ispif->msm_sd.sd.entity, 0, NULL, 0);
 	ispif->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
 	ispif->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ISPIF;
 	ispif->msm_sd.sd.entity.name = pdev->name;
 	rc = msm_sd_register(&ispif->msm_sd);
-	if (rc != 0) {
+	if (rc) {
 		pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
-		goto error;
+		goto error_sd_register;
 	}
+
 	if (pdev->dev.of_node)
 		of_property_read_u32((&pdev->dev)->of_node,
 		"cell-index", &pdev->id);
@@ -912,12 +936,16 @@
 		rc = -EBUSY;
 		goto error;
 	}
+
 	ispif->pdev = pdev;
 	ispif->ispif_state = ISPIF_POWER_DOWN;
 	ispif->open_cnt = 0;
+
 	return 0;
 
 error:
+	msm_sd_unregister(&ispif->msm_sd);
+error_sd_register:
 	mutex_destroy(&ispif->mutex);
 	kfree(ispif);
 	return rc;
diff --git a/drivers/media/video/msmb/ispif/msm_ispif.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
similarity index 100%
rename from drivers/media/video/msmb/ispif/msm_ispif.h
rename to drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
new file mode 100644
index 0000000..cdbebea
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
@@ -0,0 +1,94 @@
+/* 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_ISPIF_HWREG_V1_H__
+#define __MSM_ISPIF_HWREG_V1_H__
+
+/* common registers */
+#define ISPIF_RST_CMD_ADDR                  0x0000
+#define ISPIF_RST_CMD_1_ADDR                0x0000 /* undefined */
+#define ISPIF_INTF_CMD_ADDR                 0x0004
+#define ISPIF_INTF_CMD_1_ADDR               0x0030
+#define ISPIF_CTRL_ADDR                     0x0008
+#define ISPIF_INPUT_SEL_ADDR                0x000C
+#define ISPIF_PIX_0_INTF_CID_MASK_ADDR      0x0010
+#define ISPIF_RDI_0_INTF_CID_MASK_ADDR      0x0014
+#define ISPIF_PIX_1_INTF_CID_MASK_ADDR      0x0038
+#define ISPIF_RDI_1_INTF_CID_MASK_ADDR      0x003C
+#define ISPIF_RDI_2_INTF_CID_MASK_ADDR      0x0044
+#define ISPIF_PIX_0_STATUS_ADDR             0x0024
+#define ISPIF_RDI_0_STATUS_ADDR             0x0028
+#define ISPIF_PIX_1_STATUS_ADDR             0x0060
+#define ISPIF_RDI_1_STATUS_ADDR             0x0064
+#define ISPIF_RDI_2_STATUS_ADDR             0x006C
+#define ISPIF_IRQ_MASK_ADDR                 0x0100
+#define ISPIF_IRQ_CLEAR_ADDR                0x0104
+#define ISPIF_IRQ_STATUS_ADDR               0x0108
+#define ISPIF_IRQ_MASK_1_ADDR               0x010C
+#define ISPIF_IRQ_CLEAR_1_ADDR              0x0110
+#define ISPIF_IRQ_STATUS_1_ADDR             0x0114
+#define ISPIF_IRQ_MASK_2_ADDR               0x0118
+#define ISPIF_IRQ_CLEAR_2_ADDR              0x011C
+#define ISPIF_IRQ_STATUS_2_ADDR             0x0120
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR     0x0124
+
+/*ISPIF RESET BITS*/
+#define VFE_CLK_DOMAIN_RST                 BIT(31)
+#define RDI_CLK_DOMAIN_RST                 BIT(30)
+#define PIX_CLK_DOMAIN_RST                 BIT(29)
+#define AHB_CLK_DOMAIN_RST                 BIT(28)
+#define RDI_1_CLK_DOMAIN_RST               BIT(27)
+#define PIX_1_CLK_DOMAIN_RST               BIT(26)
+#define RDI_2_CLK_DOMAIN_RST               BIT(25)
+#define RDI_2_MISR_RST_STB                 BIT(20)
+#define RDI_2_VFE_RST_STB                  BIT(19)
+#define RDI_2_CSID_RST_STB                 BIT(18)
+#define RDI_1_MISR_RST_STB                 BIT(14)
+#define RDI_1_VFE_RST_STB                  BIT(13)
+#define RDI_1_CSID_RST_STB                 BIT(12)
+#define PIX_1_VFE_RST_STB                  BIT(10)
+#define PIX_1_CSID_RST_STB                 BIT(9)
+#define RDI_0_MISR_RST_STB                 BIT(8)
+#define RDI_0_VFE_RST_STB                  BIT(7)
+#define RDI_0_CSID_RST_STB                 BIT(6)
+#define PIX_0_MISR_RST_STB                 BIT(5)
+#define PIX_0_VFE_RST_STB                  BIT(4)
+#define PIX_0_CSID_RST_STB                 BIT(3)
+#define SW_REG_RST_STB                     BIT(2)
+#define MISC_LOGIC_RST_STB                 BIT(1)
+#define STROBED_RST_EN                     BIT(0)
+
+#define ISPIF_RST_CMD_MASK              0xFE1C77FF
+#define ISPIF_RST_CMD_1_MASK            0xFFFFFFFF /* undefined */
+
+/* irq_mask_0 */
+#define PIX_INTF_0_OVERFLOW_IRQ            BIT(12)
+#define RAW_INTF_0_OVERFLOW_IRQ            BIT(25)
+#define RESET_DONE_IRQ                     BIT(27)
+/* irq_mask_1 */
+#define PIX_INTF_1_OVERFLOW_IRQ            BIT(12)
+#define RAW_INTF_1_OVERFLOW_IRQ            BIT(25)
+/* irq_mask_2 */
+#define RAW_INTF_2_OVERFLOW_IRQ            BIT(12)
+
+#define ISPIF_IRQ_STATUS_MASK           0x0A493249
+#define ISPIF_IRQ_STATUS_1_MASK         0x02493249
+#define ISPIF_IRQ_STATUS_2_MASK         0x00001249
+
+#define ISPIF_IRQ_STATUS_PIX_SOF_MASK     0x000249
+#define ISPIF_IRQ_STATUS_RDI0_SOF_MASK    0x492000
+#define ISPIF_IRQ_STATUS_RDI1_SOF_MASK    0x492000
+#define ISPIF_IRQ_STATUS_RDI2_SOF_MASK    0x000249
+
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD        0x000001
+
+#endif /* __MSM_ISPIF_HWREG_V1_H__ */
diff --git a/drivers/media/video/msmb/ispif/msm_ispif_hwreg.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
similarity index 61%
rename from drivers/media/video/msmb/ispif/msm_ispif_hwreg.h
rename to drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
index 16575ae..37b19f5 100644
--- a/drivers/media/video/msmb/ispif/msm_ispif_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
@@ -10,17 +10,15 @@
  * GNU General Public License for more details.
  */
 
-#ifndef MSM_ISPIF_HWREG_H
-#define MSM_ISPIF_HWREG_H
+#ifndef __MSM_ISPIF_HWREG_V2_H__
+#define __MSM_ISPIF_HWREG_V2_H__
 
-
-/* ISPIF registers */
-
-#define ISPIF_RST_CMD_ADDR                        0x08
-#define ISPIF_RST_CMD_1_ADDR                      0x0C
+/* common registers */
+#define ISPIF_RST_CMD_ADDR                       0x008
+#define ISPIF_RST_CMD_1_ADDR                     0x00C
 #define ISPIF_INTF_CMD_ADDR                      0x248
 #define ISPIF_INTF_CMD_1_ADDR                    0x24C
-#define ISPIF_CTRL_ADDR                           0x08
+#define ISPIF_CTRL_ADDR                          0x008
 #define ISPIF_INPUT_SEL_ADDR                     0x244
 #define ISPIF_PIX_0_INTF_CID_MASK_ADDR           0x254
 #define ISPIF_RDI_0_INTF_CID_MASK_ADDR           0x264
@@ -41,7 +39,7 @@
 #define ISPIF_IRQ_MASK_2_ADDR                    0x210
 #define ISPIF_IRQ_CLEAR_2_ADDR                   0x238
 #define ISPIF_IRQ_STATUS_2_ADDR                  0x224
-#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR           0x1C
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR          0x01C
 
 /* new */
 #define ISPIF_VFE_m_CTRL_0_ADDR                  0x200
@@ -56,36 +54,35 @@
 #define ISPIF_VFE_m_IRQ_CLEAR_2                  0x238
 
 /*ISPIF RESET BITS*/
-
-#define VFE_CLK_DOMAIN_RST                       31
-#define RDI_CLK_DOMAIN_RST                       26
-#define RDI_1_CLK_DOMAIN_RST                     27
-#define RDI_2_CLK_DOMAIN_RST                     28
-#define PIX_CLK_DOMAIN_RST                       29
-#define PIX_1_CLK_DOMAIN_RST                     30
-#define AHB_CLK_DOMAIN_RST                       25
-#define RDI_2_VFE_RST_STB                        12
-#define RDI_2_CSID_RST_STB                       11
-#define RDI_1_VFE_RST_STB                        10
-#define RDI_1_CSID_RST_STB                       9
-#define RDI_0_VFE_RST_STB                        8
-#define RDI_0_CSID_RST_STB                       7
-#define PIX_1_VFE_RST_STB                        6
-#define PIX_1_CSID_RST_STB                       5
-#define PIX_0_VFE_RST_STB                        4
-#define PIX_0_CSID_RST_STB                       3
-#define SW_REG_RST_STB                           2
-#define MISC_LOGIC_RST_STB                       1
-#define STROBED_RST_EN                           0
+#define VFE_CLK_DOMAIN_RST                       BIT(31)
+#define PIX_1_CLK_DOMAIN_RST                     BIT(30)
+#define PIX_CLK_DOMAIN_RST                       BIT(29)
+#define RDI_2_CLK_DOMAIN_RST                     BIT(28)
+#define RDI_1_CLK_DOMAIN_RST                     BIT(27)
+#define RDI_CLK_DOMAIN_RST                       BIT(26)
+#define AHB_CLK_DOMAIN_RST                       BIT(25)
+#define RDI_2_VFE_RST_STB                        BIT(12)
+#define RDI_2_CSID_RST_STB                       BIT(11)
+#define RDI_1_VFE_RST_STB                        BIT(10)
+#define RDI_1_CSID_RST_STB                       BIT(9)
+#define RDI_0_VFE_RST_STB                        BIT(8)
+#define RDI_0_CSID_RST_STB                       BIT(7)
+#define PIX_1_VFE_RST_STB                        BIT(6)
+#define PIX_1_CSID_RST_STB                       BIT(5)
+#define PIX_0_VFE_RST_STB                        BIT(4)
+#define PIX_0_CSID_RST_STB                       BIT(3)
+#define SW_REG_RST_STB                           BIT(2)
+#define MISC_LOGIC_RST_STB                       BIT(1)
+#define STROBED_RST_EN                           BIT(0)
 
 #define ISPIF_RST_CMD_MASK                       0xFE0F1FFF
 #define ISPIF_RST_CMD_1_MASK                     0xFC0F1FF9
 
-#define PIX_INTF_0_OVERFLOW_IRQ                  12
-#define RAW_INTF_0_OVERFLOW_IRQ                  25
-#define RAW_INTF_1_OVERFLOW_IRQ                  25
-#define RAW_INTF_2_OVERFLOW_IRQ                  12
-#define RESET_DONE_IRQ                           27
+#define PIX_INTF_0_OVERFLOW_IRQ                  BIT(12)
+#define RAW_INTF_0_OVERFLOW_IRQ                  BIT(25)
+#define RAW_INTF_1_OVERFLOW_IRQ                  BIT(25)
+#define RAW_INTF_2_OVERFLOW_IRQ                  BIT(12)
+#define RESET_DONE_IRQ                           BIT(27)
 
 #define ISPIF_IRQ_STATUS_MASK                    0x0A493249
 #define ISPIF_IRQ_STATUS_1_MASK                  0x02493249
@@ -96,7 +93,6 @@
 #define ISPIF_IRQ_STATUS_RDI1_SOF_MASK           0x492000
 #define ISPIF_IRQ_STATUS_RDI2_SOF_MASK           0x249
 
-#define ISPIF_IRQ_STATUS_SOF_MASK                0x492249
 #define ISPIF_IRQ_GLOBAL_CLEAR_CMD               0x1
 
-#endif
+#endif /* __MSM_ISPIF_HWREG_V2_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/Makefile b/drivers/media/platform/msm/camera_v2/jpeg_10/Makefile
new file mode 100644
index 0000000..1d3871b
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/Makefile
@@ -0,0 +1,5 @@
+GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/jpeg_10
+
+obj-$(CONFIG_MSMB_JPEG) += msm_jpeg_dev.o msm_jpeg_sync.o msm_jpeg_core.o msm_jpeg_hw.o msm_jpeg_platform.o
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
similarity index 100%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_common.h
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_core.c
similarity index 100%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_core.c
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_core.c
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_core.h
similarity index 100%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_core.h
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_core.h
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
similarity index 98%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
index 3e6e0d5..8b96227 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,7 +26,6 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
 
-#include "msm.h"
 #include "msm_jpeg_sync.h"
 #include "msm_jpeg_common.h"
 
@@ -274,7 +273,7 @@
 	.probe	= __msm_jpeg_probe,
 	.remove = __msm_jpeg_remove,
 	.driver = {
-		.name = MSM_JPEG_DRV_NAME,
+		.name = "msm_jpeg",
 		.owner = THIS_MODULE,
 		.of_match_table = msm_jpeg_dt_match,
 	},
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
similarity index 100%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.h
similarity index 100%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.h
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw_reg.h
similarity index 98%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw_reg.h
index 31286dd..f970c79 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw_reg.h
@@ -113,6 +113,8 @@
 #define JPEG_DECODE_PRED_C_STATE          (JPEG_REG_BASE + 0x00000264)
 #define JPEG_DECODE_RSM_STATE             (JPEG_REG_BASE + 0x00000268)
 
+#define JPEG_HW_VERSION                   (JPEG_REG_BASE + 0x00000000)
+
 #define VBIF_BASE_ADDRESS                      0xFDA60000
 #define VBIF_REGION_SIZE                       0xC30
 #define JPEG_VBIF_CLKON                        0x4
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
similarity index 77%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index 38a0ffb..0eb0a23 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,8 @@
 #include <linux/android_pmem.h>
 #include <mach/camera.h>
 #include <mach/iommu_domains.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
 
 #include "msm_jpeg_platform.h"
 #include "msm_jpeg_sync.h"
@@ -29,13 +31,9 @@
 void msm_jpeg_platform_p2v(struct msm_jpeg_device *pgmn_dev, struct file  *file,
 	struct ion_handle **ionhandle, int domain_num)
 {
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_unmap_iommu(pgmn_dev->jpeg_client, *ionhandle, domain_num, 0);
 	ion_free(pgmn_dev->jpeg_client, *ionhandle);
 	*ionhandle = NULL;
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(file);
-#endif
 }
 
 uint32_t msm_jpeg_platform_v2p(struct msm_jpeg_device *pgmn_dev, int fd,
@@ -44,26 +42,17 @@
 	unsigned long paddr;
 	unsigned long size;
 	int rc;
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	*ionhandle = ion_import_dma_buf(pgmn_dev->jpeg_client, fd);
 	if (IS_ERR_OR_NULL(*ionhandle))
 		return 0;
 
 	rc = ion_map_iommu(pgmn_dev->jpeg_client, *ionhandle, domain_num, 0,
-		SZ_4K, 0, &paddr, (unsigned long *)&size, 0,
-0); JPEG_DBG("%s:%d] addr 0x%x size %ld", __func__, __LINE__,
-							(uint32_t)paddr, size);
+		SZ_4K, 0, &paddr, (unsigned long *)&size, 0, 0);
+	JPEG_DBG("%s:%d] addr 0x%x size %ld", __func__, __LINE__,
+		(uint32_t)paddr, size);
 
-#elif CONFIG_ANDROID_PMEM
-	unsigned long kvstart;
-	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
-#else
-	rc = 0;
-	paddr = 0;
-	size = 0;
-#endif
 	if (rc < 0) {
-		JPEG_PR_ERR("%s: get_pmem_file fd %d error %d\n", __func__, fd,
+		JPEG_PR_ERR("%s: ion_map_iommu fd %d error %d\n", __func__, fd,
 			rc);
 		goto error1;
 	}
@@ -76,9 +65,7 @@
 
 	return paddr;
 error1:
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_free(pgmn_dev->jpeg_client, *ionhandle);
-#endif
 	return 0;
 }
 
@@ -90,7 +77,8 @@
 	{"camss_top_ahb_clk", -1},
 };
 
-static void set_vbif_params(void *jpeg_vbif_base)
+static void set_vbif_params(struct msm_jpeg_device *pgmn_dev,
+	 void *jpeg_vbif_base)
 {
 	writel_relaxed(0x1,
 		jpeg_vbif_base + JPEG_VBIF_CLKON);
@@ -122,14 +110,53 @@
 		jpeg_vbif_base + JPEG_VBIF_OUT_AXI_AOOO);
 	/*FE and WE QOS configuration need to be set when
 	QOS RR arbitration is enabled*/
-	writel_relaxed(0x00000001,
-		jpeg_vbif_base + JPEG_VBIF_ROUND_ROBIN_QOS_ARB);
+	if (pgmn_dev->hw_version == JPEG_8974_V2)
+		writel_relaxed(0x00000003,
+				jpeg_vbif_base + JPEG_VBIF_ROUND_ROBIN_QOS_ARB);
+	else
+		writel_relaxed(0x00000001,
+				jpeg_vbif_base + JPEG_VBIF_ROUND_ROBIN_QOS_ARB);
+
 	writel_relaxed(0x22222222,
 		jpeg_vbif_base + JPEG_VBIF_OUT_AXI_AMEMTYPE_CONF0);
 	writel_relaxed(0x2222,
 		jpeg_vbif_base + JPEG_VBIF_OUT_AXI_AMEMTYPE_CONF1);
 }
 
+static struct msm_bus_vectors msm_jpeg_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_JPEG,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors msm_jpeg_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_JPEG,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 1027648000,
+		.ib  = 1105920000,
+	},
+};
+
+static struct msm_bus_paths msm_jpeg_bus_client_config[] = {
+	{
+		ARRAY_SIZE(msm_jpeg_init_vectors),
+		msm_jpeg_init_vectors,
+	},
+	{
+		ARRAY_SIZE(msm_jpeg_vectors),
+		msm_jpeg_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata msm_jpeg_bus_client_pdata = {
+	msm_jpeg_bus_client_config,
+	ARRAY_SIZE(msm_jpeg_bus_client_config),
+	.name = "msm_jpeg",
+};
 
 int msm_jpeg_platform_init(struct platform_device *pdev,
 	struct resource **mem,
@@ -161,6 +188,16 @@
 	JPEG_DBG("%s base address: 0x%x, jpeg irq number: %d\n", __func__,
 		jpeg_mem->start, jpeg_irq);
 
+	pgmn_dev->jpeg_bus_client =
+		msm_bus_scale_register_client(&msm_jpeg_bus_client_pdata);
+	if (!pgmn_dev->jpeg_bus_client) {
+		JPEG_PR_ERR("%s: Registration Failed!\n", __func__);
+		pgmn_dev->jpeg_bus_client = 0;
+		return -EINVAL;
+	}
+	msm_bus_scale_client_update_request(
+		pgmn_dev->jpeg_bus_client, 1);
+
 	jpeg_io = request_mem_region(jpeg_mem->start,
 		resource_size(jpeg_mem), pdev->name);
 	if (!jpeg_io) {
@@ -172,32 +209,38 @@
 	if (!jpeg_base) {
 		rc = -ENOMEM;
 		JPEG_PR_ERR("%s: ioremap failed\n", __func__);
-		goto fail1;
+		goto fail_remap;
 	}
 
-	pgmn_dev->jpeg_vbif = ioremap(VBIF_BASE_ADDRESS, VBIF_REGION_SIZE);
-	if (!pgmn_dev->jpeg_vbif) {
-		rc = -ENOMEM;
-		JPEG_PR_ERR("%s:%d] ioremap failed\n", __func__, __LINE__);
-		goto fail1;
-	}
-	JPEG_DBG("%s:%d] jpeg_vbif 0x%x", __func__, __LINE__,
-		(uint32_t)pgmn_dev->jpeg_vbif);
-
 	pgmn_dev->jpeg_fs = regulator_get(&pgmn_dev->pdev->dev, "vdd");
 	rc = regulator_enable(pgmn_dev->jpeg_fs);
 	if (rc) {
 		JPEG_PR_ERR("%s:%d]jpeg regulator get failed\n",
-				__func__, __LINE__); }
+				__func__, __LINE__);
+		goto fail_fs;
+	}
 
-	pgmn_dev->hw_version = JPEG_8974;
 	rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_8x_clk_info,
 	 pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_8x_clk_info), 1);
 	if (rc < 0) {
 		JPEG_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
-		goto fail2;
+		goto fail_clk;
 	}
 
+	pgmn_dev->hw_version = readl_relaxed(jpeg_base +
+		JPEG_HW_VERSION);
+	JPEG_DBG_HIGH("%s:%d] jpeg HW version 0x%x", __func__, __LINE__,
+		pgmn_dev->hw_version);
+
+	pgmn_dev->jpeg_vbif = ioremap(VBIF_BASE_ADDRESS, VBIF_REGION_SIZE);
+	if (!pgmn_dev->jpeg_vbif) {
+		rc = -ENOMEM;
+		JPEG_PR_ERR("%s:%d] ioremap failed\n", __func__, __LINE__);
+		goto fail_vbif;
+	}
+	JPEG_DBG("%s:%d] jpeg_vbif 0x%x", __func__, __LINE__,
+		(uint32_t)pgmn_dev->jpeg_vbif);
+
 #ifdef CONFIG_MSM_IOMMU
 	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
 		rc = iommu_attach_device(pgmn_dev->domain,
@@ -205,44 +248,33 @@
 		if (rc < 0) {
 			rc = -ENODEV;
 			JPEG_PR_ERR("%s: Device attach failed\n", __func__);
-			goto fail;
+			goto fail_iommu;
 		}
 		JPEG_DBG("%s:%d] dom 0x%x ctx 0x%x", __func__, __LINE__,
 					(uint32_t)pgmn_dev->domain,
 					(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
 	}
 #endif
-	set_vbif_params(pgmn_dev->jpeg_vbif);
+	set_vbif_params(pgmn_dev, pgmn_dev->jpeg_vbif);
 
 	rc = request_irq(jpeg_irq, handler, IRQF_TRIGGER_RISING, "jpeg",
 		context);
 	if (rc) {
 		JPEG_PR_ERR("%s: request_irq failed, %d\n", __func__,
 			jpeg_irq);
-		goto fail3;
+		goto fail_request_irq;
 	}
 
 	*mem  = jpeg_mem;
 	*base = jpeg_base;
 	*irq  = jpeg_irq;
 
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	pgmn_dev->jpeg_client = msm_ion_client_create(-1, "camera/jpeg");
-#endif
 	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
 
 	return rc;
 
-fail3:
-	msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_8x_clk_info,
-	pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_8x_clk_info), 0);
-
-	regulator_put(pgmn_dev->jpeg_fs);
-	regulator_disable(pgmn_dev->jpeg_fs);
-	pgmn_dev->jpeg_fs = NULL;
-fail2:
-	iounmap(jpeg_base);
-fail1:
+fail_request_irq:
 #ifdef CONFIG_MSM_IOMMU
 	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
 		JPEG_PR_ERR("%s:%d] dom 0x%x ctx 0x%x", __func__, __LINE__,
@@ -252,7 +284,23 @@
 					pgmn_dev->iommu_ctx_arr[i]);
 	}
 #endif
-fail:
+
+fail_iommu:
+	iounmap(pgmn_dev->jpeg_vbif);
+
+fail_vbif:
+	msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_8x_clk_info,
+	pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_8x_clk_info), 0);
+
+fail_clk:
+	regulator_put(pgmn_dev->jpeg_fs);
+	regulator_disable(pgmn_dev->jpeg_fs);
+	pgmn_dev->jpeg_fs = NULL;
+
+fail_fs:
+	iounmap(jpeg_base);
+
+fail_remap:
 	release_mem_region(jpeg_mem->start, resource_size(jpeg_mem));
 	JPEG_DBG("%s:%d] fail\n", __func__, __LINE__);
 	return rc;
@@ -276,6 +324,7 @@
 	}
 #endif
 
+	msm_bus_scale_unregister_client(pgmn_dev->jpeg_bus_client);
 	msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_8x_clk_info,
 	pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_8x_clk_info), 0);
 	JPEG_DBG("%s:%d] clock disbale done", __func__, __LINE__);
@@ -288,9 +337,7 @@
 	iounmap(pgmn_dev->jpeg_vbif);
 	iounmap(base);
 	release_mem_region(mem->start, resource_size(mem));
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_client_destroy(pgmn_dev->jpeg_client);
-#endif
 	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
 	return result;
 }
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
similarity index 100%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
similarity index 99%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
index a7a9d70..15b4b25 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -864,7 +864,7 @@
 	}
 	return rc;
 }
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+
 static int camera_register_domain(void)
 {
 	struct msm_iova_partition camera_fw_partition = {
@@ -880,7 +880,6 @@
 	};
 	return msm_register_domain(&camera_fw_layout);
 }
-#endif
 
 int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev)
 {
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
similarity index 93%
rename from drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
rename to drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
index 1ac4838..be889cd 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -23,10 +23,8 @@
 #include <media/v4l2-subdev.h>
 #include "msm_jpeg_hw.h"
 
-#define JPEG_7X 0x1
-#define JPEG_8X60 (0x1 << 1)
-#define JPEG_8960 (0x1 << 2)
-#define JPEG_8974 0x1
+#define JPEG_8974_V1 0x10000000
+#define JPEG_8974_V2 0x10010000
 
 struct msm_jpeg_q {
 	char const	*name;
@@ -99,6 +97,7 @@
 	spinlock_t reset_lock;
 	wait_queue_head_t reset_wait;
 	uint32_t res_size;
+	uint32_t jpeg_bus_client;
 };
 
 int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev);
diff --git a/drivers/media/video/msmb/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
similarity index 100%
rename from drivers/media/video/msmb/msm.c
rename to drivers/media/platform/msm/camera_v2/msm.c
diff --git a/drivers/media/video/msmb/msm.h b/drivers/media/platform/msm/camera_v2/msm.h
similarity index 100%
rename from drivers/media/video/msmb/msm.h
rename to drivers/media/platform/msm/camera_v2/msm.h
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/Makefile b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/Makefile
new file mode 100644
index 0000000..8832457
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/Makefile
@@ -0,0 +1,2 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+obj-$(CONFIG_MSMB_CAMERA) += msm_generic_buf_mgr.o
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
new file mode 100644
index 0000000..7cae19f
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -0,0 +1,133 @@
+/* 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 "msm_generic_buf_mgr.h"
+
+struct msm_buf_mngr_device *msm_buf_mngr_dev;
+
+static int msm_buf_mngr_get_buf(struct msm_buf_mngr_device *buf_mngr_dev,
+	struct msm_buf_mngr_info *buf_info)
+{
+	struct vb2_buffer *vb2_buf = NULL;
+	vb2_buf = buf_mngr_dev->vb2_ops.get_buf(buf_info->session_id,
+		buf_info->stream_id);
+	buf_mngr_dev->bufs.vb2_buf = vb2_buf;
+	list_add_tail(&buf_mngr_dev->bufs.list, &buf_mngr_dev->bufs.list);
+	buf_info->index = vb2_buf->v4l2_buf.index;
+	return 0;
+}
+
+static int msm_buf_mngr_buf_done(struct msm_buf_mngr_device *buf_mngr_dev,
+	struct msm_buf_mngr_info *buf_info)
+{
+	struct vb2_buffer *vb2_buf = NULL;
+	list_for_each_entry(vb2_buf, &buf_mngr_dev->bufs.list, queued_entry) {
+		if (vb2_buf->v4l2_buf.index == buf_info->index) {
+			buf_mngr_dev->vb2_ops.put_buf(vb2_buf);
+			break;
+		}
+	}
+	return 0;
+}
+
+static int msm_buf_mngr_put_buf(struct msm_buf_mngr_device *buf_mngr_dev,
+	struct msm_buf_mngr_info *buf_info)
+{
+	struct vb2_buffer *vb2_buf = NULL;
+	list_for_each_entry(vb2_buf, &buf_mngr_dev->bufs.list, queued_entry) {
+		if (vb2_buf->v4l2_buf.index == buf_info->index) {
+			buf_mngr_dev->vb2_ops.buf_done(vb2_buf);
+			break;
+		}
+	}
+	return 0;
+}
+
+static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	struct msm_buf_mngr_device *buf_mngr_dev = v4l2_get_subdevdata(sd);
+
+	void __user *argp = (void __user *)arg;
+	switch (cmd) {
+	case VIDIOC_MSM_BUF_MNGR_GET_BUF:
+		msm_buf_mngr_get_buf(buf_mngr_dev, argp);
+		break;
+	case VIDIOC_MSM_BUF_MNGR_BUF_DONE:
+		msm_buf_mngr_buf_done(buf_mngr_dev, argp);
+		break;
+	case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
+		msm_buf_mngr_put_buf(buf_mngr_dev, argp);
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static struct v4l2_subdev_core_ops msm_buf_mngr_subdev_core_ops = {
+	.ioctl = msm_buf_mngr_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_buf_mngr_subdev_ops = {
+	.core = &msm_buf_mngr_subdev_core_ops,
+};
+
+static const struct of_device_id msm_buf_mngr_dt_match[] = {
+	{.compatible = "qcom,msm_buf_mngr"},
+};
+
+static int __init msm_buf_mngr_init(void)
+{
+	int rc = 0;
+
+	msm_buf_mngr_dev = kzalloc(sizeof(*msm_buf_mngr_dev),
+		GFP_KERNEL);
+	if (WARN_ON(!msm_buf_mngr_dev)) {
+		pr_err("%s: not enough memory", __func__);
+		return -ENOMEM;
+	}
+	/* Sub-dev */
+	v4l2_subdev_init(&msm_buf_mngr_dev->subdev.sd,
+		&msm_buf_mngr_subdev_ops);
+	snprintf(msm_buf_mngr_dev->subdev.sd.name,
+		ARRAY_SIZE(msm_buf_mngr_dev->subdev.sd.name), "msm_buf_mngr");
+	msm_buf_mngr_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	v4l2_set_subdevdata(&msm_buf_mngr_dev->subdev.sd, msm_buf_mngr_dev);
+
+	media_entity_init(&msm_buf_mngr_dev->subdev.sd.entity, 0, NULL, 0);
+	msm_buf_mngr_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	msm_buf_mngr_dev->subdev.sd.entity.group_id =
+		MSM_CAMERA_SUBDEV_BUF_MNGR;
+	rc = msm_sd_register(&msm_buf_mngr_dev->subdev);
+	if (rc != 0) {
+		pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
+		goto end;
+	}
+
+	v4l2_subdev_notify(&msm_buf_mngr_dev->subdev.sd, MSM_SD_NOTIFY_REQ_CB,
+	  &msm_buf_mngr_dev->vb2_ops);
+
+end:
+	return rc;
+}
+
+static void __exit msm_buf_mngr_exit(void)
+{
+	kfree(msm_buf_mngr_dev);
+}
+
+module_init(msm_buf_mngr_init);
+module_exit(msm_buf_mngr_exit);
+MODULE_DESCRIPTION("MSM Buffer Manager");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
new file mode 100644
index 0000000..35368fd
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
@@ -0,0 +1,38 @@
+/* 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_BUF_GENERIC_MNGR_H__
+#define __MSM_BUF_GENERIC_MNGR_H__
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msmb_camera.h>
+#include <media/msmb_generic_buf_mgr.h>
+
+#include "msm.h"
+#include "msm_sd.h"
+
+struct msm_get_bufs {
+	struct list_head list;
+	struct vb2_buffer *vb2_buf;
+};
+
+struct msm_buf_mngr_device {
+	struct msm_sd_subdev subdev;
+	struct msm_sd_req_vb2_q vb2_ops;
+	struct msm_get_bufs bufs;
+};
+
+#endif
diff --git a/drivers/media/video/msmb/msm_sd.h b/drivers/media/platform/msm/camera_v2/msm_sd.h
similarity index 100%
rename from drivers/media/video/msmb/msm_sd.h
rename to drivers/media/platform/msm/camera_v2/msm_sd.h
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/Makefile b/drivers/media/platform/msm/camera_v2/msm_vb2/Makefile
new file mode 100644
index 0000000..2673bdd
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/msm_vb2
+obj-$(CONFIG_MSMB_CAMERA) += msm_vb2.o
diff --git a/drivers/media/video/msmb/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
similarity index 100%
rename from drivers/media/video/msmb/msm_vb2/msm_vb2.c
rename to drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
diff --git a/drivers/media/video/msmb/msm_vb2/msm_vb2.h b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
similarity index 100%
rename from drivers/media/video/msmb/msm_vb2/msm_vb2.h
rename to drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
new file mode 100644
index 0000000..d0b6c62
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -0,0 +1,10 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/msm_vb2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
+obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/
+obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
+obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
+obj-$(CONFIG_OV2720) += ov2720.o
+obj-$(CONFIG_MT9M114) += mt9m114.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/Makefile b/drivers/media/platform/msm/camera_v2/sensor/actuator/Makefile
new file mode 100644
index 0000000..c0d607f
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/Makefile
@@ -0,0 +1,4 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
+obj-$(CONFIG_MSMB_CAMERA) += msm_actuator.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
new file mode 100644
index 0000000..e939c2b
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -0,0 +1,858 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include "msm_sd.h"
+#include "msm_actuator.h"
+#include "msm_cci.h"
+
+DEFINE_MSM_MUTEX(msm_actuator_mutex);
+
+/*#define MSM_ACUTUATOR_DEBUG*/
+#undef CDBG
+#ifdef MSM_ACUTUATOR_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+static struct msm_actuator_ctrl_t msm_actuator_t;
+static struct msm_actuator msm_vcm_actuator_table;
+static struct msm_actuator msm_piezo_actuator_table;
+
+static struct msm_actuator *actuators[] = {
+	&msm_vcm_actuator_table,
+	&msm_piezo_actuator_table,
+};
+
+static int32_t msm_actuator_piezo_set_default_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_move_params_t *move_params)
+{
+	int32_t rc = 0;
+	CDBG("Enter\n");
+
+	if (a_ctrl->curr_step_pos != 0) {
+		a_ctrl->i2c_tbl_index = 0;
+		a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
+			a_ctrl->initial_code, 0, 0);
+		a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
+			a_ctrl->initial_code, 0, 0);
+		rc = a_ctrl->i2c_client.i2c_func_tbl->
+			i2c_write_table_w_microdelay(
+			&a_ctrl->i2c_client, a_ctrl->i2c_reg_tbl,
+			a_ctrl->i2c_tbl_index, a_ctrl->i2c_data_type);
+		if (rc < 0) {
+			pr_err("%s: i2c write error:%d\n",
+				__func__, rc);
+			return rc;
+		}
+		a_ctrl->i2c_tbl_index = 0;
+		a_ctrl->curr_step_pos = 0;
+	}
+	CDBG("Exit\n");
+	return rc;
+}
+
+static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl,
+	int16_t next_lens_position, uint32_t hw_params, uint16_t delay)
+{
+	struct msm_actuator_reg_params_t *write_arr = a_ctrl->reg_tbl;
+	uint32_t hw_dword = hw_params;
+	uint16_t i2c_byte1 = 0, i2c_byte2 = 0;
+	uint16_t value = 0;
+	uint32_t size = a_ctrl->reg_tbl_size, i = 0;
+	struct msm_camera_i2c_reg_tbl *i2c_tbl = a_ctrl->i2c_reg_tbl;
+	CDBG("Enter\n");
+	for (i = 0; i < size; i++) {
+		if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) {
+			value = (next_lens_position <<
+				write_arr[i].data_shift) |
+				((hw_dword & write_arr[i].hw_mask) >>
+				write_arr[i].hw_shift);
+
+			if (write_arr[i].reg_addr != 0xFFFF) {
+				i2c_byte1 = write_arr[i].reg_addr;
+				i2c_byte2 = value;
+				if (size != (i+1)) {
+					i2c_byte2 = value & 0xFF;
+					CDBG("byte1:0x%x, byte2:0x%x\n",
+						i2c_byte1, i2c_byte2);
+					i2c_tbl[a_ctrl->i2c_tbl_index].
+						reg_addr = i2c_byte1;
+					i2c_tbl[a_ctrl->i2c_tbl_index].
+						reg_data = i2c_byte2;
+					i2c_tbl[a_ctrl->i2c_tbl_index].
+						delay = 0;
+					a_ctrl->i2c_tbl_index++;
+					i++;
+					i2c_byte1 = write_arr[i].reg_addr;
+					i2c_byte2 = (value & 0xFF00) >> 8;
+				}
+			} else {
+				i2c_byte1 = (value & 0xFF00) >> 8;
+				i2c_byte2 = value & 0xFF;
+			}
+		} else {
+			i2c_byte1 = write_arr[i].reg_addr;
+			i2c_byte2 = (hw_dword & write_arr[i].hw_mask) >>
+				write_arr[i].hw_shift;
+		}
+		CDBG("i2c_byte1:0x%x, i2c_byte2:0x%x\n", i2c_byte1, i2c_byte2);
+		i2c_tbl[a_ctrl->i2c_tbl_index].reg_addr = i2c_byte1;
+		i2c_tbl[a_ctrl->i2c_tbl_index].reg_data = i2c_byte2;
+		i2c_tbl[a_ctrl->i2c_tbl_index].delay = delay;
+		a_ctrl->i2c_tbl_index++;
+	}
+	CDBG("Exit\n");
+}
+
+static int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
+	uint16_t size, enum msm_actuator_data_type type,
+	struct reg_settings_t *settings)
+{
+	int32_t rc = -EFAULT;
+	int32_t i = 0;
+	CDBG("Enter\n");
+
+	for (i = 0; i < size; i++) {
+		switch (type) {
+		case MSM_ACTUATOR_BYTE_DATA:
+			rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write(
+				&a_ctrl->i2c_client,
+				settings[i].reg_addr,
+				settings[i].reg_data, MSM_CAMERA_I2C_BYTE_DATA);
+			break;
+		case MSM_ACTUATOR_WORD_DATA:
+			rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write(
+				&a_ctrl->i2c_client,
+				settings[i].reg_addr,
+				settings[i].reg_data, MSM_CAMERA_I2C_WORD_DATA);
+			break;
+		default:
+			pr_err("Unsupport data type: %d\n", type);
+			break;
+		}
+		if (rc < 0)
+			break;
+	}
+
+	a_ctrl->curr_step_pos = 0;
+	CDBG("Exit\n");
+	return rc;
+}
+
+static void msm_actuator_write_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	uint16_t curr_lens_pos,
+	struct damping_params_t *damping_params,
+	int8_t sign_direction,
+	int16_t code_boundary)
+{
+	int16_t next_lens_pos = 0;
+	uint16_t damping_code_step = 0;
+	uint16_t wait_time = 0;
+	CDBG("Enter\n");
+
+	damping_code_step = damping_params->damping_step;
+	wait_time = damping_params->damping_delay;
+
+	/* Write code based on damping_code_step in a loop */
+	for (next_lens_pos =
+		curr_lens_pos + (sign_direction * damping_code_step);
+		(sign_direction * next_lens_pos) <=
+			(sign_direction * code_boundary);
+		next_lens_pos =
+			(next_lens_pos +
+				(sign_direction * damping_code_step))) {
+		a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
+			next_lens_pos, damping_params->hw_params, wait_time);
+		curr_lens_pos = next_lens_pos;
+	}
+
+	if (curr_lens_pos != code_boundary) {
+		a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
+			code_boundary, damping_params->hw_params, wait_time);
+	}
+	CDBG("Exit\n");
+}
+
+static int32_t msm_actuator_piezo_move_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_move_params_t *move_params)
+{
+	int32_t dest_step_position = move_params->dest_step_pos;
+	int32_t rc = 0;
+	int32_t num_steps = move_params->num_steps;
+	CDBG("Enter\n");
+
+	if (num_steps == 0)
+		return rc;
+
+	a_ctrl->i2c_tbl_index = 0;
+	a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
+		(num_steps *
+		a_ctrl->region_params[0].code_per_step),
+		move_params->ringing_params[0].hw_params, 0);
+
+	rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write_table_w_microdelay(
+		&a_ctrl->i2c_client,
+		a_ctrl->i2c_reg_tbl, a_ctrl->i2c_tbl_index,
+		a_ctrl->i2c_data_type);
+	if (rc < 0) {
+		pr_err("i2c write error:%d\n", rc);
+		return rc;
+	}
+	a_ctrl->i2c_tbl_index = 0;
+	a_ctrl->curr_step_pos = dest_step_position;
+	CDBG("Exit\n");
+	return rc;
+}
+
+static int32_t msm_actuator_move_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_move_params_t *move_params)
+{
+	int32_t rc = 0;
+	int8_t sign_dir = move_params->sign_dir;
+	uint16_t step_boundary = 0;
+	uint16_t target_step_pos = 0;
+	uint16_t target_lens_pos = 0;
+	int16_t dest_step_pos = move_params->dest_step_pos;
+	uint16_t curr_lens_pos = 0;
+	int dir = move_params->dir;
+	int32_t num_steps = move_params->num_steps;
+
+	CDBG("called, dir %d, num_steps %d\n", dir, num_steps);
+
+	if (dest_step_pos == a_ctrl->curr_step_pos)
+		return rc;
+
+	curr_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos];
+	a_ctrl->i2c_tbl_index = 0;
+	CDBG("curr_step_pos =%d dest_step_pos =%d curr_lens_pos=%d\n",
+		a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos);
+
+	while (a_ctrl->curr_step_pos != dest_step_pos) {
+		step_boundary =
+			a_ctrl->region_params[a_ctrl->curr_region_index].
+			step_bound[dir];
+		if ((dest_step_pos * sign_dir) <=
+			(step_boundary * sign_dir)) {
+
+			target_step_pos = dest_step_pos;
+			target_lens_pos =
+				a_ctrl->step_position_table[target_step_pos];
+			a_ctrl->func_tbl->actuator_write_focus(a_ctrl,
+					curr_lens_pos,
+					&(move_params->
+						ringing_params[a_ctrl->
+						curr_region_index]),
+					sign_dir,
+					target_lens_pos);
+			curr_lens_pos = target_lens_pos;
+
+		} else {
+			target_step_pos = step_boundary;
+			target_lens_pos =
+				a_ctrl->step_position_table[target_step_pos];
+			a_ctrl->func_tbl->actuator_write_focus(a_ctrl,
+					curr_lens_pos,
+					&(move_params->ringing_params[a_ctrl->
+						curr_region_index]),
+					sign_dir,
+					target_lens_pos);
+			curr_lens_pos = target_lens_pos;
+
+			a_ctrl->curr_region_index += sign_dir;
+		}
+		a_ctrl->curr_step_pos = target_step_pos;
+	}
+
+	rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write_table_w_microdelay(
+		&a_ctrl->i2c_client,
+		a_ctrl->i2c_reg_tbl, a_ctrl->i2c_tbl_index,
+		a_ctrl->i2c_data_type);
+	if (rc < 0) {
+		pr_err("i2c write error:%d\n", rc);
+		return rc;
+	}
+	a_ctrl->i2c_tbl_index = 0;
+	CDBG("Exit\n");
+
+	return rc;
+}
+
+static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_set_info_t *set_info)
+{
+	int16_t code_per_step = 0;
+	int16_t cur_code = 0;
+	int16_t step_index = 0, region_index = 0;
+	uint16_t step_boundary = 0;
+	uint32_t max_code_size = 1;
+	uint16_t data_size = set_info->actuator_params.data_size;
+	CDBG("Enter\n");
+
+	for (; data_size > 0; data_size--)
+		max_code_size *= 2;
+
+	kfree(a_ctrl->step_position_table);
+	a_ctrl->step_position_table = NULL;
+
+	/* Fill step position table */
+	a_ctrl->step_position_table =
+		kmalloc(sizeof(uint16_t) *
+		(set_info->af_tuning_params.total_steps + 1), GFP_KERNEL);
+
+	if (a_ctrl->step_position_table == NULL)
+		return -ENOMEM;
+
+	cur_code = set_info->af_tuning_params.initial_code;
+	a_ctrl->step_position_table[step_index++] = cur_code;
+	for (region_index = 0;
+		region_index < a_ctrl->region_size;
+		region_index++) {
+		code_per_step =
+			a_ctrl->region_params[region_index].code_per_step;
+		step_boundary =
+			a_ctrl->region_params[region_index].
+			step_bound[MOVE_NEAR];
+		for (; step_index <= step_boundary;
+			step_index++) {
+			cur_code += code_per_step;
+			if (cur_code < max_code_size)
+				a_ctrl->step_position_table[step_index] =
+					cur_code;
+			else {
+				for (; step_index <
+					set_info->af_tuning_params.total_steps;
+					step_index++)
+					a_ctrl->
+						step_position_table[
+						step_index] =
+						max_code_size;
+			}
+		}
+	}
+	CDBG("Exit\n");
+	return 0;
+}
+
+static int32_t msm_actuator_set_default_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_move_params_t *move_params)
+{
+	int32_t rc = 0;
+	CDBG("Enter\n");
+
+	if (a_ctrl->curr_step_pos != 0)
+		rc = a_ctrl->func_tbl->actuator_move_focus(a_ctrl, move_params);
+	CDBG("Exit\n");
+	return rc;
+}
+
+static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
+{
+	int32_t rc = 0;
+	CDBG("Enter\n");
+	if (a_ctrl->vcm_enable) {
+		rc = gpio_direction_output(a_ctrl->vcm_pwd, 0);
+		if (!rc)
+			gpio_free(a_ctrl->vcm_pwd);
+	}
+
+	kfree(a_ctrl->step_position_table);
+	a_ctrl->step_position_table = NULL;
+	kfree(a_ctrl->i2c_reg_tbl);
+	a_ctrl->i2c_reg_tbl = NULL;
+	a_ctrl->i2c_tbl_index = 0;
+	CDBG("Exit\n");
+	return rc;
+}
+
+static int32_t msm_actuator_init(struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_set_info_t *set_info) {
+	struct reg_settings_t *init_settings = NULL;
+	int32_t rc = -EFAULT;
+	uint16_t i = 0;
+	struct msm_camera_cci_client *cci_client = NULL;
+	CDBG("Enter\n");
+
+	for (i = 0; i < ARRAY_SIZE(actuators); i++) {
+		if (set_info->actuator_params.act_type ==
+			actuators[i]->act_type) {
+			a_ctrl->func_tbl = &actuators[i]->func_tbl;
+			rc = 0;
+		}
+	}
+
+	if (rc < 0) {
+		pr_err("Actuator function table not found\n");
+		return rc;
+	}
+
+	a_ctrl->region_size = set_info->af_tuning_params.region_size;
+	if (a_ctrl->region_size > MAX_ACTUATOR_REGION) {
+		pr_err("MAX_ACTUATOR_REGION is exceeded.\n");
+		return -EFAULT;
+	}
+	a_ctrl->pwd_step = set_info->af_tuning_params.pwd_step;
+	a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
+
+	if (copy_from_user(&a_ctrl->region_params,
+		(void *)set_info->af_tuning_params.region_params,
+		a_ctrl->region_size * sizeof(struct region_params_t)))
+		return -EFAULT;
+
+	if (a_ctrl->act_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		cci_client = a_ctrl->i2c_client.cci_client;
+		cci_client->sid =
+			set_info->actuator_params.i2c_addr >> 1;
+		cci_client->retries = 3;
+		cci_client->id_map = 0;
+		cci_client->cci_i2c_master = a_ctrl->cci_master;
+	} else {
+		a_ctrl->i2c_client.client->addr =
+			set_info->actuator_params.i2c_addr;
+	}
+
+	a_ctrl->i2c_data_type = set_info->actuator_params.i2c_data_type;
+	a_ctrl->i2c_client.addr_type = set_info->actuator_params.i2c_addr_type;
+	a_ctrl->reg_tbl_size = set_info->actuator_params.reg_tbl_size;
+	if (a_ctrl->reg_tbl_size > MAX_ACTUATOR_REG_TBL_SIZE) {
+		pr_err("MAX_ACTUATOR_REG_TBL_SIZE is exceeded.\n");
+		return -EFAULT;
+	}
+
+	a_ctrl->i2c_reg_tbl =
+		kmalloc(sizeof(struct msm_camera_i2c_reg_tbl) *
+		(set_info->af_tuning_params.total_steps + 1), GFP_KERNEL);
+	if (!a_ctrl->i2c_reg_tbl) {
+		pr_err("kmalloc fail\n");
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(&a_ctrl->reg_tbl,
+		(void *)set_info->actuator_params.reg_tbl_params,
+		a_ctrl->reg_tbl_size *
+		sizeof(struct msm_actuator_reg_params_t))) {
+		kfree(a_ctrl->i2c_reg_tbl);
+		return -EFAULT;
+	}
+
+	if (set_info->actuator_params.init_setting_size) {
+		if (a_ctrl->func_tbl->actuator_init_focus) {
+			init_settings = kmalloc(sizeof(struct reg_settings_t) *
+				(set_info->actuator_params.init_setting_size),
+				GFP_KERNEL);
+			if (init_settings == NULL) {
+				kfree(a_ctrl->i2c_reg_tbl);
+				pr_err("Error allocating memory for init_settings\n");
+				return -EFAULT;
+			}
+			if (copy_from_user(init_settings,
+				(void *)set_info->actuator_params.init_settings,
+				set_info->actuator_params.init_setting_size *
+				sizeof(struct reg_settings_t))) {
+				kfree(init_settings);
+				kfree(a_ctrl->i2c_reg_tbl);
+				pr_err("Error copying init_settings\n");
+				return -EFAULT;
+			}
+			rc = a_ctrl->func_tbl->actuator_init_focus(a_ctrl,
+				set_info->actuator_params.init_setting_size,
+				a_ctrl->i2c_data_type,
+				init_settings);
+			kfree(init_settings);
+			if (rc < 0) {
+				kfree(a_ctrl->i2c_reg_tbl);
+				pr_err("Error actuator_init_focus\n");
+				return -EFAULT;
+			}
+		}
+	}
+
+	a_ctrl->initial_code = set_info->af_tuning_params.initial_code;
+	if (a_ctrl->func_tbl->actuator_init_step_table)
+		rc = a_ctrl->func_tbl->
+			actuator_init_step_table(a_ctrl, set_info);
+
+	a_ctrl->curr_step_pos = 0;
+	a_ctrl->curr_region_index = 0;
+	CDBG("Exit\n");
+
+	return rc;
+}
+
+static int32_t msm_actuator_config(struct msm_actuator_ctrl_t *a_ctrl,
+	void __user *argp)
+{
+	struct msm_actuator_cfg_data *cdata =
+		(struct msm_actuator_cfg_data *)argp;
+	int32_t rc = 0;
+	mutex_lock(a_ctrl->actuator_mutex);
+	CDBG("Enter\n");
+	CDBG("%s type %d\n", __func__, cdata->cfgtype);
+	switch (cdata->cfgtype) {
+	case CFG_GET_ACTUATOR_INFO:
+		cdata->is_af_supported = 1;
+		cdata->cfg.cam_name = a_ctrl->cam_name;
+		break;
+
+	case CFG_SET_ACTUATOR_INFO:
+		rc = msm_actuator_init(a_ctrl, &cdata->cfg.set_info);
+		if (rc < 0)
+			pr_err("init table failed %d\n", rc);
+		break;
+
+	case CFG_SET_DEFAULT_FOCUS:
+		rc = a_ctrl->func_tbl->actuator_set_default_focus(a_ctrl,
+			&cdata->cfg.move);
+		if (rc < 0)
+			pr_err("move focus failed %d\n", rc);
+		break;
+
+	case CFG_MOVE_FOCUS:
+		rc = a_ctrl->func_tbl->actuator_move_focus(a_ctrl,
+			&cdata->cfg.move);
+		if (rc < 0)
+			pr_err("move focus failed %d\n", rc);
+		break;
+
+	default:
+		break;
+	}
+	mutex_unlock(a_ctrl->actuator_mutex);
+	CDBG("Exit\n");
+	return rc;
+}
+
+static int32_t msm_actuator_get_subdev_id(struct msm_actuator_ctrl_t *a_ctrl,
+	void *arg)
+{
+	uint32_t *subdev_id = (uint32_t *)arg;
+	CDBG("Enter\n");
+	if (!subdev_id) {
+		pr_err("failed\n");
+		return -EINVAL;
+	}
+	*subdev_id = a_ctrl->pdev->id;
+	CDBG("subdev_id %d\n", *subdev_id);
+	CDBG("Exit\n");
+	return 0;
+}
+
+static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = {
+	.i2c_read = msm_camera_cci_i2c_read,
+	.i2c_read_seq = msm_camera_cci_i2c_read_seq,
+	.i2c_write = msm_camera_cci_i2c_write,
+	.i2c_write_table = msm_camera_cci_i2c_write_table,
+	.i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table,
+	.i2c_write_table_w_microdelay =
+		msm_camera_cci_i2c_write_table_w_microdelay,
+	.i2c_util = msm_sensor_cci_i2c_util,
+};
+
+static struct msm_camera_i2c_fn_t msm_sensor_qup_func_tbl = {
+	.i2c_read = msm_camera_qup_i2c_read,
+	.i2c_read_seq = msm_camera_qup_i2c_read_seq,
+	.i2c_write = msm_camera_qup_i2c_write,
+	.i2c_write_table = msm_camera_qup_i2c_write_table,
+	.i2c_write_seq_table = msm_camera_qup_i2c_write_seq_table,
+	.i2c_write_table_w_microdelay =
+		msm_camera_qup_i2c_write_table_w_microdelay,
+};
+
+static int msm_actuator_open(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh) {
+	int rc = 0;
+	struct msm_actuator_ctrl_t *a_ctrl =  v4l2_get_subdevdata(sd);
+	CDBG("Enter\n");
+	if (!a_ctrl) {
+		pr_err("failed\n");
+		return -EINVAL;
+	}
+	if (a_ctrl->act_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+			&a_ctrl->i2c_client, MSM_CCI_INIT);
+		if (rc < 0)
+			pr_err("cci_init failed\n");
+	}
+	CDBG("Exit\n");
+	return rc;
+}
+
+static int msm_actuator_close(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh) {
+	int rc = 0;
+	struct msm_actuator_ctrl_t *a_ctrl =  v4l2_get_subdevdata(sd);
+	CDBG("Enter\n");
+	if (!a_ctrl) {
+		pr_err("failed\n");
+		return -EINVAL;
+	}
+	if (a_ctrl->act_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+			&a_ctrl->i2c_client, MSM_CCI_RELEASE);
+		if (rc < 0)
+			pr_err("cci_init failed\n");
+	}
+	CDBG("Exit\n");
+	return rc;
+}
+
+static const struct v4l2_subdev_internal_ops msm_actuator_internal_ops = {
+	.open = msm_actuator_open,
+	.close = msm_actuator_close,
+};
+
+static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int rc = 0;
+	struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+	CDBG("Enter\n");
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("i2c_check_functionality failed\n");
+		goto probe_failure;
+	}
+
+	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
+	CDBG("client = %x\n", (unsigned int) client);
+	act_ctrl_t->i2c_client.client = client;
+	/* Set device type as I2C */
+	act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
+	act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
+
+	/* Assign name for sub device */
+	snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
+		"%s", act_ctrl_t->i2c_driver->driver.name);
+
+	/* Initialize sub device */
+	v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
+		act_ctrl_t->i2c_client.client,
+		act_ctrl_t->act_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
+	act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+	act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
+	act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+	msm_sd_register(&act_ctrl_t->msm_sd);
+	CDBG("succeeded\n");
+	CDBG("Exit\n");
+
+probe_failure:
+	return rc;
+}
+
+static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	struct msm_camera_cci_client *cci_client = NULL;
+	CDBG("Enter\n");
+
+	if (!pdev->dev.of_node) {
+		pr_err("of_node NULL\n");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
+		&pdev->id);
+	CDBG("cell-index %d, rc %d\n", pdev->id, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
+		&msm_actuator_t.cci_master);
+	CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t.cci_master, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	msm_actuator_t.cam_name = pdev->id;
+
+	/* Set platform device handle */
+	msm_actuator_t.pdev = pdev;
+	/* Set device type as platform device */
+	msm_actuator_t.act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+	msm_actuator_t.i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
+	msm_actuator_t.i2c_client.cci_client = kzalloc(sizeof(
+		struct msm_camera_cci_client), GFP_KERNEL);
+	if (!msm_actuator_t.i2c_client.cci_client) {
+		pr_err("failed no memory\n");
+		return -ENOMEM;
+	}
+
+	cci_client = msm_actuator_t.i2c_client.cci_client;
+	cci_client->cci_subdev = msm_cci_get_subdev();
+	v4l2_subdev_init(&msm_actuator_t.msm_sd.sd,
+		msm_actuator_t.act_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&msm_actuator_t.msm_sd.sd, &msm_actuator_t);
+	msm_actuator_t.msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+	msm_actuator_t.msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(msm_actuator_t.msm_sd.sd.name,
+		ARRAY_SIZE(msm_actuator_t.msm_sd.sd.name), "msm_actuator");
+	media_entity_init(&msm_actuator_t.msm_sd.sd.entity, 0, NULL, 0);
+	msm_actuator_t.msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	msm_actuator_t.msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+	msm_sd_register(&msm_actuator_t.msm_sd);
+	CDBG("Exit\n");
+	return rc;
+}
+
+static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
+{
+	int rc = 0;
+	CDBG("%s called\n", __func__);
+
+	CDBG("vcm info: %x %x\n", a_ctrl->vcm_pwd,
+		a_ctrl->vcm_enable);
+	if (a_ctrl->vcm_enable) {
+		rc = gpio_request(a_ctrl->vcm_pwd, "msm_actuator");
+		if (!rc) {
+			CDBG("Enable VCM PWD\n");
+			gpio_direction_output(a_ctrl->vcm_pwd, 1);
+		}
+	}
+	CDBG("Exit\n");
+	return rc;
+}
+
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+	{"msm_actuator", (kernel_ulong_t)&msm_actuator_t},
+	{ }
+};
+
+static struct i2c_driver msm_actuator_i2c_driver = {
+	.id_table = msm_actuator_i2c_id,
+	.probe  = msm_actuator_i2c_probe,
+	.remove = __exit_p(msm_actuator_i2c_remove),
+	.driver = {
+		.name = "msm_actuator",
+	},
+};
+
+static const struct of_device_id msm_actuator_dt_match[] = {
+	{.compatible = "qcom,actuator", .data = &msm_actuator_t},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
+
+static struct platform_driver msm_actuator_platform_driver = {
+	.driver = {
+		.name = "qcom,actuator",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_actuator_dt_match,
+	},
+};
+
+static int __init msm_actuator_init_module(void)
+{
+	int32_t rc = 0;
+	CDBG("Enter\n");
+	rc = platform_driver_probe(msm_actuator_t.pdriver,
+		msm_actuator_platform_probe);
+	if (!rc)
+		return rc;
+	CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(msm_actuator_t.i2c_driver);
+}
+
+static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
+	void __user *argp = (void __user *)arg;
+	CDBG("Enter\n");
+	CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
+	switch (cmd) {
+	case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+		return msm_actuator_get_subdev_id(a_ctrl, argp);
+	case VIDIOC_MSM_ACTUATOR_CFG:
+		return msm_actuator_config(a_ctrl, argp);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
+{
+	int rc = 0;
+	struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
+	CDBG("Enter\n");
+	mutex_lock(a_ctrl->actuator_mutex);
+	if (on)
+		rc = msm_actuator_power_up(a_ctrl);
+	else
+		rc = msm_actuator_power_down(a_ctrl);
+	mutex_unlock(a_ctrl->actuator_mutex);
+	CDBG("Exit\n");
+	return rc;
+}
+
+static struct v4l2_subdev_core_ops msm_actuator_subdev_core_ops = {
+	.ioctl = msm_actuator_subdev_ioctl,
+	.s_power = msm_actuator_power,
+};
+
+static struct v4l2_subdev_ops msm_actuator_subdev_ops = {
+	.core = &msm_actuator_subdev_core_ops,
+};
+
+static struct msm_actuator_ctrl_t msm_actuator_t = {
+	.i2c_driver = &msm_actuator_i2c_driver,
+	.pdriver = &msm_actuator_platform_driver,
+	.act_v4l2_subdev_ops = &msm_actuator_subdev_ops,
+
+	.curr_step_pos = 0,
+	.curr_region_index = 0,
+	.actuator_mutex = &msm_actuator_mutex,
+
+};
+
+static struct msm_actuator msm_vcm_actuator_table = {
+	.act_type = ACTUATOR_VCM,
+	.func_tbl = {
+		.actuator_init_step_table = msm_actuator_init_step_table,
+		.actuator_move_focus = msm_actuator_move_focus,
+		.actuator_write_focus = msm_actuator_write_focus,
+		.actuator_set_default_focus = msm_actuator_set_default_focus,
+		.actuator_init_focus = msm_actuator_init_focus,
+		.actuator_parse_i2c_params = msm_actuator_parse_i2c_params,
+	},
+};
+
+static struct msm_actuator msm_piezo_actuator_table = {
+	.act_type = ACTUATOR_PIEZO,
+	.func_tbl = {
+		.actuator_init_step_table = NULL,
+		.actuator_move_focus = msm_actuator_piezo_move_focus,
+		.actuator_write_focus = NULL,
+		.actuator_set_default_focus =
+			msm_actuator_piezo_set_default_focus,
+		.actuator_init_focus = msm_actuator_init_focus,
+		.actuator_parse_i2c_params = msm_actuator_parse_i2c_params,
+	},
+};
+
+module_init(msm_actuator_init_module);
+MODULE_DESCRIPTION("MSM ACTUATOR");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
new file mode 100644
index 0000000..c616307
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef MSM_ACTUATOR_H
+#define MSM_ACTUATOR_H
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <mach/camera2.h>
+#include <media/v4l2-subdev.h>
+#include <media/msmb_camera.h>
+#include "msm_camera_i2c.h"
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+	static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+struct msm_actuator_ctrl_t;
+
+struct msm_actuator_func_tbl {
+	int32_t (*actuator_i2c_write_b_af)(struct msm_actuator_ctrl_t *,
+			uint8_t,
+			uint8_t);
+	int32_t (*actuator_init_step_table)(struct msm_actuator_ctrl_t *,
+		struct msm_actuator_set_info_t *);
+	int32_t (*actuator_init_focus)(struct msm_actuator_ctrl_t *,
+		uint16_t, enum msm_actuator_data_type, struct reg_settings_t *);
+	int32_t (*actuator_set_default_focus) (struct msm_actuator_ctrl_t *,
+			struct msm_actuator_move_params_t *);
+	int32_t (*actuator_move_focus) (struct msm_actuator_ctrl_t *,
+			struct msm_actuator_move_params_t *);
+	void (*actuator_parse_i2c_params)(struct msm_actuator_ctrl_t *,
+			int16_t, uint32_t, uint16_t);
+	void (*actuator_write_focus)(struct msm_actuator_ctrl_t *,
+			uint16_t,
+			struct damping_params_t *,
+			int8_t,
+			int16_t);
+};
+
+struct msm_actuator {
+	enum actuator_type act_type;
+	struct msm_actuator_func_tbl func_tbl;
+};
+
+struct msm_actuator_ctrl_t {
+	struct i2c_driver *i2c_driver;
+	struct platform_driver *pdriver;
+	struct platform_device *pdev;
+	struct msm_camera_i2c_client i2c_client;
+	enum msm_camera_device_type_t act_device_type;
+	struct msm_sd_subdev msm_sd;
+	enum af_camera_name cam_name;
+	struct mutex *actuator_mutex;
+	struct msm_actuator_func_tbl *func_tbl;
+	enum msm_actuator_data_type i2c_data_type;
+	struct v4l2_subdev sdev;
+	struct v4l2_subdev_ops *act_v4l2_subdev_ops;
+
+	int16_t curr_step_pos;
+	uint16_t curr_region_index;
+	uint16_t *step_position_table;
+	struct region_params_t region_params[MAX_ACTUATOR_REGION];
+	uint16_t reg_tbl_size;
+	struct msm_actuator_reg_params_t reg_tbl[MAX_ACTUATOR_REG_TBL_SIZE];
+	uint16_t region_size;
+	void *user_data;
+	uint32_t vcm_pwd;
+	uint32_t vcm_enable;
+	uint32_t total_steps;
+	uint16_t pwd_step;
+	uint16_t initial_code;
+	struct msm_camera_i2c_reg_tbl *i2c_reg_tbl;
+	uint16_t i2c_tbl_index;
+	enum cci_i2c_master_t cci_master;
+};
+
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/Makefile b/drivers/media/platform/msm/camera_v2/sensor/cci/Makefile
new file mode 100644
index 0000000..d3aa498
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/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_MSM_CCI) += msm_cci.o
diff --git a/drivers/media/video/msmb/sensor/cci/msm_cam_cci_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
similarity index 97%
rename from drivers/media/video/msmb/sensor/cci/msm_cam_cci_hwreg.h
rename to drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
index 19cff3b..642df76 100644
--- a/drivers/media/video/msmb/sensor/cci/msm_cam_cci_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
@@ -29,8 +29,7 @@
 #define CCI_I2C_M0_READ_BUF_LEVEL_ADDR                              0x0000011C
 #define CCI_HALT_REQ_ADDR                                           0x00000034
 #define CCI_M0_HALT_REQ_RMSK                                               0x1
-#define CCI_M1_HALT_REQ_RMSK                                              0x01
-#define CCI_HALT_REQ_ADDR                                           0x00000034
+#define CCI_M1_HALT_REQ_RMSK                                               0x2
 #define CCI_I2C_M1_SCL_CTL_ADDR                                     0x00000200
 #define CCI_I2C_M1_SDA_CTL_0_ADDR                                   0x00000204
 #define CCI_I2C_M1_SDA_CTL_1_ADDR                                   0x00000208
diff --git a/drivers/media/video/msmb/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
similarity index 97%
rename from drivers/media/video/msmb/sensor/cci/msm_cci.c
rename to drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index b1c9a40..12ac4cb 100644
--- a/drivers/media/video/msmb/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -32,7 +32,6 @@
 /* TODO move this somewhere else */
 #define MSM_CCI_DRV_NAME "msm_cci"
 
-#define CONFIG_MSMB_CAMERA_DEBUG
 #undef CDBG
 #ifdef CONFIG_MSMB_CAMERA_DEBUG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
@@ -101,6 +100,20 @@
 	return 0;
 }
 
+static void msm_cci_flush_queue(struct cci_device *cci_dev,
+	enum cci_i2c_master_t master)
+{
+	uint32_t rc = 0;
+
+	msm_camera_io_w(1 << master, cci_dev->base + CCI_HALT_REQ_ADDR);
+	rc = wait_for_completion_interruptible_timeout(
+		&cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT);
+	if (rc <= 0)
+		pr_err("%s: wait_for_completion_interruptible_timeout %d\n",
+			__func__, __LINE__);
+	return;
+}
+
 static int32_t msm_cci_validate_queue(struct cci_device *cci_dev,
 	uint32_t len,
 	enum cci_i2c_master_t master,
@@ -139,6 +152,7 @@
 				 __func__, __LINE__);
 			if (rc == 0)
 				rc = -ETIMEDOUT;
+			msm_cci_flush_queue(cci_dev, master);
 			return rc;
 		}
 		rc = cci_dev->cci_master_info[master].status;
@@ -318,7 +332,8 @@
 			 __func__, __LINE__);
 		if (rc == 0)
 			rc = -ETIMEDOUT;
-		return rc;
+		msm_cci_flush_queue(cci_dev, master);
+		goto ERROR;
 	} else {
 		rc = 0;
 	}
@@ -421,8 +436,7 @@
 
 	val = 1 << ((master * 2) + queue);
 	CDBG("%s:%d CCI_QUEUE_START_ADDR\n", __func__, __LINE__);
-	msm_camera_io_w(val, cci_dev->base + CCI_QUEUE_START_ADDR +
-		master*0x200 + queue * 0x100);
+	msm_camera_io_w(val, cci_dev->base + CCI_QUEUE_START_ADDR);
 
 	CDBG("%s:%d E wait_for_completion_interruptible\n",
 		__func__, __LINE__);
@@ -433,7 +447,8 @@
 			 __func__, __LINE__);
 		if (rc == 0)
 			rc = -ETIMEDOUT;
-		return rc;
+		msm_cci_flush_queue(cci_dev, master);
+		goto ERROR;
 	} else {
 		rc = 0;
 	}
diff --git a/drivers/media/video/msmb/sensor/cci/msm_cci.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
similarity index 98%
rename from drivers/media/video/msmb/sensor/cci/msm_cci.h
rename to drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
index 527a8db..f9e40f1 100644
--- a/drivers/media/video/msmb/sensor/cci/msm_cci.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.h
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <media/v4l2-subdev.h>
 #include <media/msm_cam_sensor.h>
+#include <mach/camera2.h>
 #include "msm_sd.h"
 
 #define NUM_MASTERS 2
@@ -26,11 +27,6 @@
 #define TRUE  1
 #define FALSE 0
 
-enum cci_i2c_master_t {
-	MASTER_0,
-	MASTER_1,
-};
-
 enum cci_i2c_queue_t {
 	QUEUE_0,
 	QUEUE_1,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/Makefile b/drivers/media/platform/msm/camera_v2/sensor/csid/Makefile
new file mode 100644
index 0000000..572e722
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/Makefile
@@ -0,0 +1,8 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
+  ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/csid/include/csi2.0
+else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
+  ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/csid/include/csi3.0
+endif
+obj-$(CONFIG_MSM_CSID) += msm_csid.o
diff --git a/drivers/media/video/msmb/sensor/csid/include/csi2.0/msm_csid_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csid/include/csi2.0/msm_csid_hwreg.h
similarity index 100%
rename from drivers/media/video/msmb/sensor/csid/include/csi2.0/msm_csid_hwreg.h
rename to drivers/media/platform/msm/camera_v2/sensor/csid/include/csi2.0/msm_csid_hwreg.h
diff --git a/drivers/media/video/msmb/sensor/csid/include/csi3.0/msm_csid_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csid/include/csi3.0/msm_csid_hwreg.h
similarity index 100%
rename from drivers/media/video/msmb/sensor/csid/include/csi3.0/msm_csid_hwreg.h
rename to drivers/media/platform/msm/camera_v2/sensor/csid/include/csi3.0/msm_csid_hwreg.h
diff --git a/drivers/media/video/msmb/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
similarity index 98%
rename from drivers/media/video/msmb/sensor/csid/msm_csid.c
rename to drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index 5889f20..2999a23 100644
--- a/drivers/media/video/msmb/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -29,7 +29,6 @@
 #define TRUE   1
 #define FALSE  0
 
-#define CONFIG_MSMB_CAMERA_DEBUG
 #undef CDBG
 #ifdef CONFIG_MSMB_CAMERA_DEBUG
 #define CDBG(fmt, args...) pr_err(fmt, ##args)
@@ -314,7 +313,7 @@
 			goto clk_enable_failed;
 		}
 		CDBG("%s:%d called\n", __func__, __LINE__);
-	} else if (CSID_VERSION == CSID_VERSION_V3) {
+	} else if (CSID_VERSION >= CSID_VERSION_V3) {
 		CDBG("%s:%d called\n", __func__, __LINE__);
 		rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
 			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
@@ -378,7 +377,7 @@
 	return rc;
 
 clk_enable_failed:
-	if (CSID_VERSION == CSID_VERSION_V3) {
+	if (CSID_VERSION >= CSID_VERSION_V3) {
 		msm_cam_clk_enable(&csid_dev->pdev->dev,
 			csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
 			csid_8974_clk_info[0].num_clk_info, 0);
@@ -388,7 +387,7 @@
 		msm_camera_enable_vreg(&csid_dev->pdev->dev,
 			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
 			NULL, 0, &csid_dev->csi_vdd, 0);
-	} else if (CSID_VERSION == CSID_VERSION_V3) {
+	} else if (CSID_VERSION >= CSID_VERSION_V3) {
 		msm_camera_enable_vreg(&csid_dev->pdev->dev,
 			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
 			NULL, 0, &csid_dev->csi_vdd, 0);
@@ -398,7 +397,7 @@
 		msm_camera_config_vreg(&csid_dev->pdev->dev,
 			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
 			NULL, 0, &csid_dev->csi_vdd, 0);
-	} else if (CSID_VERSION == CSID_VERSION_V3) {
+	} else if (CSID_VERSION >= CSID_VERSION_V3) {
 		msm_camera_config_vreg(&csid_dev->pdev->dev,
 			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
 			NULL, 0, &csid_dev->csi_vdd, 0);
@@ -437,7 +436,7 @@
 		msm_camera_config_vreg(&csid_dev->pdev->dev,
 			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
 			NULL, 0, &csid_dev->csi_vdd, 0);
-	} else if (csid_dev->hw_version == CSID_VERSION_V3) {
+	} else if (csid_dev->hw_version >= CSID_VERSION_V3) {
 		core_id = csid_dev->pdev->id;
 		if (core_id)
 			msm_cam_clk_enable(&csid_dev->pdev->dev,
diff --git a/drivers/media/video/msmb/sensor/csid/msm_csid.h b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h
similarity index 100%
rename from drivers/media/video/msmb/sensor/csid/msm_csid.h
rename to drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.h
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/Makefile b/drivers/media/platform/msm/camera_v2/sensor/csiphy/Makefile
new file mode 100644
index 0000000..eab1f6f
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/Makefile
@@ -0,0 +1,8 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
+  ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0
+else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
+  ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi3.0
+endif
+obj-$(CONFIG_MSM_CSIPHY) += msm_csiphy.o
diff --git a/drivers/media/video/msmb/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
similarity index 100%
rename from drivers/media/video/msmb/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
rename to drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
diff --git a/drivers/media/video/msmb/sensor/csiphy/include/csi3.0/msm_csiphy_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi3.0/msm_csiphy_hwreg.h
similarity index 100%
rename from drivers/media/video/msmb/sensor/csiphy/include/csi3.0/msm_csiphy_hwreg.h
rename to drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi3.0/msm_csiphy_hwreg.h
diff --git a/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
similarity index 97%
rename from drivers/media/video/msmb/sensor/csiphy/msm_csiphy.c
rename to drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index cc29ed4..df3ee60 100644
--- a/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -27,7 +27,6 @@
 #define CSIPHY_VERSION_V3                        0x10
 #define MSM_CSIPHY_DRV_NAME                      "msm_csiphy"
 
-#define CONFIG_MSMB_CAMERA_DEBUG
 #undef CDBG
 #ifdef CONFIG_MSMB_CAMERA_DEBUG
 #define CDBG(fmt, args...) pr_err(fmt, ##args)
@@ -67,7 +66,7 @@
 	msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
 	msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
 
-	if (csiphy_dev->hw_version != CSIPHY_VERSION_V3) {
+	if (csiphy_dev->hw_version < CSIPHY_VERSION_V3) {
 		val = 0x3;
 		msm_camera_io_w((lane_mask << 2) | val,
 				csiphybase + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
@@ -199,7 +198,7 @@
 	}
 	CDBG("%s:%d called\n", __func__, __LINE__);
 
-	if (CSIPHY_VERSION != CSIPHY_VERSION_V3) {
+	if (CSIPHY_VERSION < CSIPHY_VERSION_V3) {
 		CDBG("%s:%d called\n", __func__, __LINE__);
 		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
@@ -270,7 +269,7 @@
 	}
 	CDBG("%s:%d called\n", __func__, __LINE__);
 
-	if (CSIPHY_VERSION != CSIPHY_VERSION_V3) {
+	if (CSIPHY_VERSION < CSIPHY_VERSION_V3) {
 		CDBG("%s:%d called\n", __func__, __LINE__);
 		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
@@ -330,7 +329,7 @@
 		csi_lane_params->csi_lane_assign,
 		csi_lane_params->csi_lane_mask);
 
-	if (csiphy_dev->hw_version != CSIPHY_VERSION_V3) {
+	if (csiphy_dev->hw_version < CSIPHY_VERSION_V3) {
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] = 0;
 		for (i = 0; i < 4; i++)
 			msm_camera_io_w(0x0, csiphy_dev->base +
@@ -360,7 +359,7 @@
 
 	disable_irq(csiphy_dev->irq->start);
 
-	if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+	if (CSIPHY_VERSION < CSIPHY_VERSION_V3)
 		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
 			ARRAY_SIZE(csiphy_8960_clk_info), 0);
@@ -399,7 +398,7 @@
 		csi_lane_params->csi_lane_assign,
 		csi_lane_params->csi_lane_mask);
 
-	if (csiphy_dev->hw_version != CSIPHY_VERSION_V3) {
+	if (csiphy_dev->hw_version < CSIPHY_VERSION_V3) {
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] = 0;
 		for (i = 0; i < 4; i++)
 			msm_camera_io_w(0x0, csiphy_dev->base +
@@ -427,7 +426,7 @@
 	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_LNCK_CFG2_ADDR);
 	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
 
-	if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+	if (CSIPHY_VERSION < CSIPHY_VERSION_V3)
 		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
 			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
 			ARRAY_SIZE(csiphy_8960_clk_info), 0);
diff --git a/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
similarity index 100%
rename from drivers/media/video/msmb/sensor/csiphy/msm_csiphy.h
rename to drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c
new file mode 100644
index 0000000..ba2c87d
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c
@@ -0,0 +1,88 @@
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include "msm_led_flash.h"
+
+/*#define CONFIG_MSMB_CAMERA_DEBUG*/
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+static long msm_led_flash_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	struct msm_led_flash_ctrl_t *fctrl = NULL;
+	int32_t rc = 0;
+	void __user *argp = (void __user *)arg;
+	if (!sd) {
+		pr_err("sd NULL\n");
+		return -EINVAL;
+	}
+	fctrl = v4l2_get_subdevdata(sd);
+	if (!fctrl) {
+		pr_err("fctrl NULL\n");
+		return -EINVAL;
+	}
+	switch (cmd) {
+	case VIDIOC_MSM_FLASH_LED_DATA_CFG:
+		rc = fctrl->func_tbl->flash_led_config(fctrl, argp);
+		return 0;
+	default:
+		pr_err("invalid cmd %d\n", cmd);
+		return -ENOIOCTLCMD;
+	}
+}
+
+static struct v4l2_subdev_core_ops msm_flash_subdev_core_ops = {
+	.ioctl = msm_led_flash_subdev_ioctl,
+};
+
+static struct v4l2_subdev_ops msm_flash_subdev_ops = {
+	.core = &msm_flash_subdev_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops msm_flash_internal_ops;
+
+int32_t msm_led_flash_create_v4lsubdev(struct platform_device *pdev, void *data)
+{
+	struct msm_led_flash_ctrl_t *fctrl =
+		(struct msm_led_flash_ctrl_t *)data;
+	CDBG("Enter\n");
+
+	if (!fctrl) {
+		pr_err("fctrl NULL\n");
+		return -EINVAL;
+	}
+
+	/* Initialize sub device */
+	v4l2_subdev_init(&fctrl->msm_sd.sd, &msm_flash_subdev_ops);
+	v4l2_set_subdevdata(&fctrl->msm_sd.sd, fctrl);
+
+	fctrl->pdev = pdev;
+	fctrl->msm_sd.sd.internal_ops = &msm_flash_internal_ops;
+	fctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(fctrl->msm_sd.sd.name, ARRAY_SIZE(fctrl->msm_sd.sd.name),
+		"msm_flash");
+	media_entity_init(&fctrl->msm_sd.sd.entity, 0, NULL, 0);
+	fctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	fctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_LED_FLASH;
+	msm_sd_register(&fctrl->msm_sd);
+
+	CDBG("probe success\n");
+	return 0;
+}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h
new file mode 100644
index 0000000..76c58d2
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h
@@ -0,0 +1,49 @@
+/* Copyright (c) 2009-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_LED_FLASH_H
+#define MSM_LED_FLASH_H
+
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_cam_sensor.h>
+#include "msm_sd.h"
+
+#define MAX_LED_TRIGGERS 2
+
+struct msm_led_flash_ctrl_t;
+
+struct msm_flash_fn_t {
+	int32_t (*flash_led_config)(struct msm_led_flash_ctrl_t *, void *);
+	int32_t (*flash_led_init)(struct msm_led_flash_ctrl_t *);
+	int32_t (*flash_led_release)(struct msm_led_flash_ctrl_t *);
+	int32_t (*flash_led_off)(struct msm_led_flash_ctrl_t *);
+	int32_t (*flash_led_low)(struct msm_led_flash_ctrl_t *);
+	int32_t (*flash_led_high)(struct msm_led_flash_ctrl_t *);
+};
+
+struct msm_led_flash_ctrl_t {
+	struct msm_camera_i2c_client *flash_i2c_client;
+	struct msm_sd_subdev msm_sd;
+	struct platform_device *pdev;
+	struct msm_flash_fn_t *func_tbl;
+	const char *led_trigger_name[MAX_LED_TRIGGERS];
+	struct led_trigger *led_trigger[MAX_LED_TRIGGERS];
+	uint32_t max_current[MAX_LED_TRIGGERS];
+	void *data;
+};
+
+int32_t msm_led_flash_create_v4lsubdev(struct platform_device *pdev,
+	void *data);
+
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
new file mode 100644
index 0000000..9d8981f
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
@@ -0,0 +1,170 @@
+/* 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) "%s:%d " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include "msm_led_flash.h"
+
+#define FLASH_NAME "camera-led-flash"
+
+/*#define CONFIG_MSMB_CAMERA_DEBUG*/
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+static struct msm_led_flash_ctrl_t fctrl;
+
+static int32_t msm_led_trigger_config(struct msm_led_flash_ctrl_t *fctrl,
+	void *data)
+{
+	int rc = 0;
+	struct msm_camera_led_cfg_t *cfg = (struct msm_camera_led_cfg_t *)data;
+	CDBG("called led_state %d\n", cfg->cfgtype);
+
+	if (!fctrl->led_trigger[0]) {
+		pr_err("failed\n");
+		return -EINVAL;
+	}
+	switch (cfg->cfgtype) {
+	case MSM_CAMERA_LED_OFF:
+		led_trigger_event(fctrl->led_trigger[0], 0);
+		break;
+
+	case MSM_CAMERA_LED_LOW:
+		led_trigger_event(fctrl->led_trigger[0],
+			fctrl->max_current[0] / 2);
+		break;
+
+	case MSM_CAMERA_LED_HIGH:
+		led_trigger_event(fctrl->led_trigger[0], fctrl->max_current[0]);
+		break;
+
+	case MSM_CAMERA_LED_INIT:
+	case MSM_CAMERA_LED_RELEASE:
+		led_trigger_event(fctrl->led_trigger[0], 0);
+		break;
+
+	default:
+		rc = -EFAULT;
+		break;
+	}
+	CDBG("flash_set_led_state: return %d\n", rc);
+	return rc;
+}
+
+static const struct of_device_id msm_led_trigger_dt_match[] = {
+	{.compatible = "qcom,camera-led-flash"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_led_trigger_dt_match);
+
+static struct platform_driver msm_led_trigger_driver = {
+	.driver = {
+		.name = FLASH_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = msm_led_trigger_dt_match,
+	},
+};
+
+static int32_t msm_led_trigger_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0, i = 0;
+	struct device_node *of_node = pdev->dev.of_node;
+	struct device_node *flash_src_node = NULL;
+	uint32_t count = 0;
+
+	CDBG("called\n");
+
+	if (!of_node) {
+		pr_err("of_node NULL\n");
+		return -EINVAL;
+	}
+
+	fctrl.pdev = pdev;
+
+	rc = of_property_read_u32(of_node, "cell-index", &pdev->id);
+	if (rc < 0) {
+		pr_err("failed\n");
+		return -EINVAL;
+	}
+	CDBG("pdev id %d\n", pdev->id);
+
+	if (of_get_property(of_node, "qcom,flash-source", &count)) {
+		count /= sizeof(uint32_t);
+		CDBG("count %d\n", count);
+		if (count > MAX_LED_TRIGGERS) {
+			pr_err("failed\n");
+			return -EINVAL;
+		}
+		for (i = 0; i < count; i++) {
+			flash_src_node = of_parse_phandle(of_node,
+				"qcom,flash-source", i);
+			if (!flash_src_node) {
+				pr_err("flash_src_node NULL\n");
+				continue;
+			}
+
+			rc = of_property_read_string(flash_src_node,
+				"linux,default-trigger",
+				&fctrl.led_trigger_name[i]);
+			if (rc < 0) {
+				pr_err("failed\n");
+				of_node_put(flash_src_node);
+				continue;
+			}
+
+			CDBG("default trigger %s\n", fctrl.led_trigger_name[i]);
+
+			rc = of_property_read_u32(flash_src_node,
+				"qcom,max-current", &fctrl.max_current[i]);
+			if (rc < 0) {
+				pr_err("failed rc %d\n", rc);
+				of_node_put(flash_src_node);
+				continue;
+			}
+
+			of_node_put(flash_src_node);
+
+			CDBG("max_current[%d] %d\n", i, fctrl.max_current[i]);
+
+			led_trigger_register_simple(fctrl.led_trigger_name[i],
+				&fctrl.led_trigger[i]);
+		}
+	}
+	rc = msm_led_flash_create_v4lsubdev(pdev, &fctrl);
+	return rc;
+}
+
+static int __init msm_led_trigger_add_driver(void)
+{
+	CDBG("called\n");
+	return platform_driver_probe(&msm_led_trigger_driver,
+		msm_led_trigger_probe);
+}
+
+static struct msm_flash_fn_t msm_led_trigger_func_tbl = {
+	.flash_led_config = msm_led_trigger_config,
+};
+
+static struct msm_led_flash_ctrl_t fctrl = {
+	.func_tbl = &msm_led_trigger_func_tbl,
+};
+
+module_init(msm_led_trigger_add_driver);
+MODULE_DESCRIPTION("LED TRIGGER FLASH");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/Makefile b/drivers/media/platform/msm/camera_v2/sensor/io/Makefile
new file mode 100644
index 0000000..f71b09d
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
+obj-$(CONFIG_MSMB_CAMERA)   += msm_camera_io_util.o msm_camera_cci_i2c.o msm_camera_qup_i2c.o msm_camera_i2c_mux.o
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
similarity index 61%
rename from drivers/media/video/msmb/sensor/io/msm_camera_cci_i2c.c
rename to drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index b07bb36..b07f04f 100644
--- a/drivers/media/video/msmb/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -14,7 +14,6 @@
 #include "msm_camera_i2c.h"
 #include "msm_cci.h"
 
-#define CONFIG_MSMB_CAMERA_DEBUG
 #undef CDBG
 #ifdef CONFIG_MSMB_CAMERA_DEBUG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
@@ -24,6 +23,9 @@
 #define S_I2C_DBG(fmt, args...) do { } while (0)
 #endif
 
+#define I2C_COMPARE_MATCH 0
+#define I2C_COMPARE_MISMATCH 1
+#define I2C_POLL_MAX_ITERATION 20
 
 int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
 	uint16_t addr, uint16_t *data,
@@ -143,12 +145,16 @@
 
 	S_I2C_DBG("%s reg addr = 0x%x num bytes: %d\n",
 			  __func__, addr, num_byte);
+	memset(reg_conf_tbl, 0,
+		num_byte * sizeof(struct msm_camera_i2c_reg_conf));
 	reg_conf_tbl[0].reg_addr = addr;
 	for (i = 0; i < num_byte; i++)
 		reg_conf_tbl[i].reg_data = data[i];
 	cci_ctrl.cmd = MSM_CCI_I2C_WRITE;
 	cci_ctrl.cci_info = client->cci_client;
 	cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = reg_conf_tbl;
+	cci_ctrl.cfg.cci_i2c_write_cfg.data_type = MSM_CAMERA_I2C_BYTE_DATA;
+	cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
 	cci_ctrl.cfg.cci_i2c_write_cfg.size = num_byte;
 	rc = v4l2_subdev_call(client->cci_client->cci_subdev,
 			core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
@@ -265,6 +271,210 @@
 	return rc;
 }
 
+static int32_t msm_camera_cci_i2c_compare(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t data,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc;
+	uint16_t reg_data = 0;
+	int data_len = 0;
+	switch (data_type) {
+	case MSM_CAMERA_I2C_BYTE_DATA:
+	case MSM_CAMERA_I2C_WORD_DATA:
+		data_len = data_type;
+		break;
+	case MSM_CAMERA_I2C_SET_BYTE_MASK:
+	case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
+		data_len = MSM_CAMERA_I2C_BYTE_DATA;
+		break;
+	case MSM_CAMERA_I2C_SET_WORD_MASK:
+	case MSM_CAMERA_I2C_UNSET_WORD_MASK:
+		data_len = MSM_CAMERA_I2C_WORD_DATA;
+		break;
+	default:
+		pr_err("%s: Unsupport data type: %d\n", __func__, data_type);
+		break;
+	}
+
+	rc = msm_camera_cci_i2c_read(client, addr, &reg_data, data_len);
+	if (rc < 0)
+		return rc;
+
+	rc = I2C_COMPARE_MISMATCH;
+	switch (data_type) {
+	case MSM_CAMERA_I2C_BYTE_DATA:
+	case MSM_CAMERA_I2C_WORD_DATA:
+		if (data == reg_data)
+			rc = I2C_COMPARE_MATCH;
+		break;
+	case MSM_CAMERA_I2C_SET_BYTE_MASK:
+	case MSM_CAMERA_I2C_SET_WORD_MASK:
+		if ((reg_data & data) == data)
+			rc = I2C_COMPARE_MATCH;
+		break;
+	case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
+	case MSM_CAMERA_I2C_UNSET_WORD_MASK:
+		if (!(reg_data & data))
+			rc = I2C_COMPARE_MATCH;
+		break;
+	default:
+		pr_err("%s: Unsupport data type: %d\n", __func__, data_type);
+		break;
+	}
+
+	S_I2C_DBG("%s: Register and data match result %d\n", __func__,
+		rc);
+	return rc;
+}
+
+static int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t data,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc;
+	int i;
+	S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
+		__func__, addr, data, data_type);
+
+	for (i = 0; i < I2C_POLL_MAX_ITERATION; i++) {
+		rc = msm_camera_cci_i2c_compare(client,
+			addr, data, data_type);
+		if (rc == 0 || rc < 0)
+			break;
+		usleep_range(10000, 11000);
+	}
+	return rc;
+}
+
+static int32_t msm_camera_cci_i2c_set_mask(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t mask,
+	enum msm_camera_i2c_data_type data_type, uint16_t set_mask)
+{
+	int32_t rc;
+	uint16_t reg_data;
+
+	rc = msm_camera_cci_i2c_read(client, addr, &reg_data, data_type);
+	if (rc < 0) {
+		S_I2C_DBG("%s read fail\n", __func__);
+		return rc;
+	}
+	S_I2C_DBG("%s addr: 0x%x data: 0x%x setmask: 0x%x\n",
+			__func__, addr, reg_data, mask);
+
+	if (set_mask)
+		reg_data |= mask;
+	else
+		reg_data &= ~mask;
+	S_I2C_DBG("%s write: 0x%x\n", __func__, reg_data);
+
+	rc = msm_camera_cci_i2c_write(client, addr, reg_data, data_type);
+	if (rc < 0)
+		S_I2C_DBG("%s write fail\n", __func__);
+
+	return rc;
+}
+
+static int32_t msm_camera_cci_i2c_set_write_mask_data(
+	struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t data, int16_t mask,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc;
+	uint16_t reg_data;
+	CDBG("%s\n", __func__);
+	if (mask == -1)
+		return 0;
+	if (mask == 0) {
+		rc = msm_camera_cci_i2c_write(client, addr, data, data_type);
+	} else {
+		rc = msm_camera_cci_i2c_read(client, addr, &reg_data,
+			data_type);
+		if (rc < 0) {
+			CDBG("%s read fail\n", __func__);
+			return rc;
+		}
+		reg_data &= ~mask;
+		reg_data |= (data & mask);
+		rc = msm_camera_cci_i2c_write(client, addr, reg_data,
+			data_type);
+		if (rc < 0)
+			CDBG("%s write fail\n", __func__);
+	}
+	return rc;
+}
+
+int32_t msm_camera_cci_i2c_write_conf_tbl(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int i;
+	int32_t rc = -EFAULT;
+	for (i = 0; i < size; i++) {
+		enum msm_camera_i2c_data_type dt;
+		if (reg_conf_tbl->cmd_type == MSM_CAMERA_I2C_CMD_POLL) {
+			rc = msm_camera_cci_i2c_poll(client,
+				reg_conf_tbl->reg_addr,
+				reg_conf_tbl->reg_data,
+				reg_conf_tbl->dt);
+		} else {
+			if (reg_conf_tbl->dt == 0)
+				dt = data_type;
+			else
+				dt = reg_conf_tbl->dt;
+			switch (dt) {
+			case MSM_CAMERA_I2C_BYTE_DATA:
+			case MSM_CAMERA_I2C_WORD_DATA:
+				rc = msm_camera_cci_i2c_write(
+					client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data, dt);
+				break;
+			case MSM_CAMERA_I2C_SET_BYTE_MASK:
+				rc = msm_camera_cci_i2c_set_mask(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					MSM_CAMERA_I2C_BYTE_DATA, 1);
+				break;
+			case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
+				rc = msm_camera_cci_i2c_set_mask(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					MSM_CAMERA_I2C_BYTE_DATA, 0);
+				break;
+			case MSM_CAMERA_I2C_SET_WORD_MASK:
+				rc = msm_camera_cci_i2c_set_mask(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					MSM_CAMERA_I2C_WORD_DATA, 1);
+				break;
+			case MSM_CAMERA_I2C_UNSET_WORD_MASK:
+				rc = msm_camera_cci_i2c_set_mask(client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					MSM_CAMERA_I2C_WORD_DATA, 0);
+				break;
+			case MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA:
+				rc = msm_camera_cci_i2c_set_write_mask_data(
+					client,
+					reg_conf_tbl->reg_addr,
+					reg_conf_tbl->reg_data,
+					reg_conf_tbl->mask,
+					MSM_CAMERA_I2C_BYTE_DATA);
+				break;
+			default:
+				pr_err("%s: Unsupport data type: %d\n",
+					__func__, dt);
+				break;
+			}
+		}
+		if (rc < 0)
+			break;
+		reg_conf_tbl++;
+	}
+	return rc;
+}
+
 int32_t msm_sensor_cci_i2c_util(struct msm_camera_i2c_client *client,
 	uint16_t cci_cmd)
 {
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_i2c.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
similarity index 91%
rename from drivers/media/video/msmb/sensor/io/msm_camera_i2c.h
rename to drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
index aa38e62..26f1c4f 100644
--- a/drivers/media/video/msmb/sensor/io/msm_camera_i2c.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
@@ -48,6 +48,9 @@
 		struct msm_camera_i2c_reg_tbl *, uint16_t,
 		enum msm_camera_i2c_data_type);
 	int32_t (*i2c_util)(struct msm_camera_i2c_client *, uint16_t);
+	int32_t (*i2c_write_conf_tbl)(struct msm_camera_i2c_client *client,
+		struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
+		enum msm_camera_i2c_data_type data_type);
 };
 
 int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
@@ -77,6 +80,11 @@
 	struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
 	enum msm_camera_i2c_data_type data_type);
 
+int32_t msm_camera_cci_i2c_write_conf_tbl(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
+	enum msm_camera_i2c_data_type data_type);
+
 int32_t msm_sensor_cci_i2c_util(struct msm_camera_i2c_client *client,
 	uint16_t cci_cmd);
 
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c_mux.c
similarity index 100%
rename from drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.c
rename to drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c_mux.c
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c_mux.h
similarity index 100%
rename from drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.h
rename to drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c_mux.h
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
similarity index 99%
rename from drivers/media/video/msmb/sensor/io/msm_camera_io_util.c
rename to drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
index 0f41a68..7dbbc03 100644
--- a/drivers/media/video/msmb/sensor/io/msm_camera_io_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
@@ -23,7 +23,6 @@
 
 #define BUFF_SIZE_128 128
 
-#define CONFIG_MSMB_CAMERA_DEBUG
 #undef CDBG
 #ifdef CONFIG_MSMB_CAMERA_DEBUG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_io_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h
similarity index 100%
rename from drivers/media/video/msmb/sensor/io/msm_camera_io_util.h
rename to drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_qup_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
similarity index 99%
rename from drivers/media/video/msmb/sensor/io/msm_camera_qup_i2c.c
rename to drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
index d2cfbff..55f27e0 100644
--- a/drivers/media/video/msmb/sensor/io/msm_camera_qup_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
@@ -13,7 +13,6 @@
 #include <mach/camera2.h>
 #include "msm_camera_i2c.h"
 
-#define CONFIG_MSMB_CAMERA_DEBUG
 #undef CDBG
 #ifdef CONFIG_MSMB_CAMERA_DEBUG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
diff --git a/drivers/media/video/msmb/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
similarity index 96%
rename from drivers/media/video/msmb/sensor/msm_sensor.c
rename to drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 78c3207..9062a9c 100644
--- a/drivers/media/video/msmb/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -50,6 +50,7 @@
 	int32_t rc = 0, i = 0;
 	uint32_t val = 0, count = 0;
 	uint32_t *val_array = NULL;
+	struct device_node *src_node = NULL;
 
 	sensordata->sensor_info = kzalloc(sizeof(struct msm_sensor_info_t),
 		GFP_KERNEL);
@@ -60,17 +61,21 @@
 	for (i = 0; i < SUB_MODULE_MAX; i++)
 		sensordata->sensor_info->subdev_id[i] = -1;
 
-	if (of_property_read_bool(of_node, "qcom,actuator-sd-index") ==
-		true) {
-		rc = of_property_read_u32(of_node, "qcom,actuator-sd-index",
-			&val);
-		CDBG("%s qcom,actuator-sd-index %d, rc %d\n", __func__, val,
-			rc);
+	src_node = of_parse_phandle(of_node, "qcom,actuator-src", 0);
+	if (!src_node) {
+		CDBG("%s:%d src_node NULL\n", __func__, __LINE__);
+	} else {
+		rc = of_property_read_u32(src_node, "cell-index", &val);
+		CDBG("%s qcom,actuator cell index %d, rc %d\n", __func__,
+			val, rc);
 		if (rc < 0) {
-			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
-			return rc;
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR;
 		}
-		sensordata->sensor_info->subdev_id[SUB_MODULE_ACTUATOR] = val;
+		sensordata->sensor_info->
+			subdev_id[SUB_MODULE_ACTUATOR] = val;
+		of_node_put(src_node);
+		src_node = NULL;
 	}
 
 	if (of_property_read_bool(of_node, "qcom,eeprom-sd-index") ==
@@ -80,7 +85,7 @@
 		CDBG("%s qcom,eeprom-sd-index %d, rc %d\n", __func__, val, rc);
 		if (rc < 0) {
 			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
-			return rc;
+			goto ERROR;
 		}
 		sensordata->sensor_info->subdev_id[SUB_MODULE_EEPROM] = val;
 	}
@@ -93,7 +98,7 @@
 			rc);
 		if (rc < 0) {
 			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
-			return rc;
+			goto ERROR;
 		}
 		sensordata->sensor_info->subdev_id[SUB_MODULE_LED_FLASH] = val;
 	}
@@ -106,7 +111,7 @@
 			val, rc);
 		if (rc < 0) {
 			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
-			return rc;
+			goto ERROR;
 		}
 		sensordata->sensor_info->subdev_id[SUB_MODULE_STROBE_FLASH] =
 			val;
@@ -117,12 +122,13 @@
 		if (count > 2) {
 			pr_err("%s qcom,csiphy-sd-index count %d > 2\n",
 				__func__, count);
-			return -EINVAL;
+			goto ERROR;
 		}
 		val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
 		if (!val_array) {
 			pr_err("%s failed %d\n", __func__, __LINE__);
-			return -ENOMEM;
+			rc = -ENOMEM;
+			goto ERROR;
 		}
 
 		rc = of_property_read_u32_array(of_node, "qcom,csiphy-sd-index",
@@ -130,7 +136,7 @@
 		if (rc < 0) {
 			pr_err("%s failed %d\n", __func__, __LINE__);
 			kfree(val_array);
-			return rc;
+			goto ERROR;
 		}
 		for (i = 0; i < count; i++) {
 			sensordata->sensor_info->subdev_id
@@ -142,7 +148,8 @@
 	} else {
 		pr_err("%s:%d qcom,csiphy-sd-index not present\n", __func__,
 			__LINE__);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto ERROR;
 	}
 
 	if (of_get_property(of_node, "qcom,csid-sd-index", &count)) {
@@ -150,12 +157,14 @@
 		if (count > 2) {
 			pr_err("%s qcom,csid-sd-index count %d > 2\n",
 				__func__, count);
-			return -EINVAL;
+			rc = -EINVAL;
+			goto ERROR;
 		}
 		val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
 		if (!val_array) {
 			pr_err("%s failed %d\n", __func__, __LINE__);
-			return -ENOMEM;
+			rc = -ENOMEM;
+			goto ERROR;
 		}
 
 		rc = of_property_read_u32_array(of_node, "qcom,csid-sd-index",
@@ -163,7 +172,7 @@
 		if (rc < 0) {
 			pr_err("%s failed %d\n", __func__, __LINE__);
 			kfree(val_array);
-			return rc;
+			goto ERROR;
 		}
 		for (i = 0; i < count; i++) {
 			sensordata->sensor_info->subdev_id
@@ -175,9 +184,14 @@
 	} else {
 		pr_err("%s:%d qcom,csid-sd-index not present\n", __func__,
 			__LINE__);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto ERROR;
 	}
 	return rc;
+ERROR:
+	kfree(sensordata->sensor_info);
+	sensordata->sensor_info = NULL;
+	return rc;
 }
 
 static int32_t msm_sensor_get_dt_csi_data(struct device_node *of_node,
@@ -640,6 +654,16 @@
 		rc = 0;
 	}
 
+	rc = of_property_read_u32(of_node, "qcom,cci-master",
+		&s_ctrl->cci_i2c_master);
+	CDBG("%s qcom,cci-master %d, rc %d\n", __func__, s_ctrl->cci_i2c_master,
+		rc);
+	if (rc < 0) {
+		/* Set default master 0 */
+		s_ctrl->cci_i2c_master = MASTER_0;
+		rc = 0;
+	}
+
 	rc = msm_sensor_get_sub_module_index(of_node, sensordata);
 	if (rc < 0) {
 		pr_err("%s failed %d\n", __func__, __LINE__);
@@ -878,7 +902,7 @@
 		}
 	}
 
-	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
+	if (s_ctrl->sensor_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
 		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_util(
 			s_ctrl->sensor_i2c_client, MSM_CCI_INIT);
 		if (rc < 0) {
@@ -900,7 +924,7 @@
 	return 0;
 power_up_failed:
 	pr_err("%s:%d failed\n", __func__, __LINE__);
-	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
+	if (s_ctrl->sensor_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
 		s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_util(
 			s_ctrl->sensor_i2c_client, MSM_CCI_RELEASE);
 	}
@@ -960,7 +984,7 @@
 	CDBG("%s:%d\n", __func__, __LINE__);
 	power_setting_array = &s_ctrl->power_setting_array;
 
-	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
+	if (s_ctrl->sensor_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
 		s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_util(
 			s_ctrl->sensor_i2c_client, MSM_CCI_RELEASE);
 	}
@@ -1370,6 +1394,7 @@
 	.i2c_write_table_w_microdelay =
 		msm_camera_cci_i2c_write_table_w_microdelay,
 	.i2c_util = msm_sensor_cci_i2c_util,
+	.i2c_write_conf_tbl = msm_camera_cci_i2c_write_conf_tbl,
 };
 
 static struct msm_camera_i2c_fn_t msm_sensor_qup_func_tbl = {
@@ -1400,7 +1425,7 @@
 			return rc;
 		}
 	}
-	s_ctrl->sensor_device_type = MSM_SENSOR_PLATFORM_DEVICE;
+	s_ctrl->sensor_device_type = MSM_CAMERA_PLATFORM_DEVICE;
 	s_ctrl->sensor_i2c_client->cci_client = kzalloc(sizeof(
 		struct msm_camera_cci_client), GFP_KERNEL);
 	if (!s_ctrl->sensor_i2c_client->cci_client) {
@@ -1410,7 +1435,7 @@
 	/* TODO: get CCI subdev */
 	cci_client = s_ctrl->sensor_i2c_client->cci_client;
 	cci_client->cci_subdev = msm_cci_get_subdev();
-	cci_client->cci_i2c_master = MASTER_0;
+	cci_client->cci_i2c_master = s_ctrl->cci_i2c_master;
 	cci_client->sid =
 		s_ctrl->sensordata->slave_info->sensor_slave_addr >> 1;
 	cci_client->retries = 3;
@@ -1479,7 +1504,7 @@
 		return -EINVAL;
 	}
 
-	s_ctrl->sensor_device_type = MSM_SENSOR_I2C_DEVICE;
+	s_ctrl->sensor_device_type = MSM_CAMERA_I2C_DEVICE;
 	s_ctrl->sensordata = client->dev.platform_data;
 	if (s_ctrl->sensordata == NULL) {
 		pr_err("%s %s NULL sensor data\n", __func__, client->name);
diff --git a/drivers/media/video/msmb/sensor/msm_sensor.h b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
similarity index 96%
rename from drivers/media/video/msmb/sensor/msm_sensor.h
rename to drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
index 20a2b14..6c36e47d 100644
--- a/drivers/media/video/msmb/sensor/msm_sensor.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
@@ -47,7 +47,8 @@
 
 struct msm_sensor_ctrl_t {
 	struct platform_device *pdev;
-	enum msm_sensor_device_type_t sensor_device_type;
+	enum msm_camera_device_type_t sensor_device_type;
+	enum cci_i2c_master_t cci_i2c_master;
 	struct msm_camera_sensor_board_info *sensordata;
 	struct msm_sensor_power_setting_array power_setting_array;
 	struct mutex *msm_sensor_mutex;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
new file mode 100644
index 0000000..9911a59
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
@@ -0,0 +1,1452 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "msm_sensor.h"
+#include "msm_cci.h"
+#include "msm_camera_io_util.h"
+#define MT9M114_SENSOR_NAME "mt9m114"
+#define PLATFORM_DRIVER_NAME "msm_camera_mt9m114"
+#define mt9m114_obj mt9m114_##obj
+
+/*#define CONFIG_MSMB_CAMERA_DEBUG*/
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+/* Sysctl registers */
+#define MT9M114_COMMAND_REGISTER                0x0080
+#define MT9M114_COMMAND_REGISTER_APPLY_PATCH    (1 << 0)
+#define MT9M114_COMMAND_REGISTER_SET_STATE      (1 << 1)
+#define MT9M114_COMMAND_REGISTER_REFRESH        (1 << 2)
+#define MT9M114_COMMAND_REGISTER_WAIT_FOR_EVENT (1 << 3)
+#define MT9M114_COMMAND_REGISTER_OK             (1 << 15)
+
+DEFINE_MSM_MUTEX(mt9m114_mut);
+static struct msm_sensor_ctrl_t mt9m114_s_ctrl;
+
+static struct msm_sensor_power_setting mt9m114_power_setting[] = {
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VIO,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VDIG,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VANA,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 1,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 30,
+	},
+	{
+		.seq_type = SENSOR_CLK,
+		.seq_val = SENSOR_CAM_MCLK,
+		.config_val = 0,
+		.delay = 100,
+	},
+	{
+		.seq_type = SENSOR_I2C_MUX,
+		.seq_val = 0,
+		.config_val = 0,
+		.delay = 0,
+	},
+};
+
+static struct msm_camera_i2c_reg_conf mt9m114_720p_settings[] = {
+	{0xdc00, 0x50, MSM_CAMERA_I2C_BYTE_DATA, MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_SET_STATE,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{MT9M114_COMMAND_REGISTER, (MT9M114_COMMAND_REGISTER_OK |
+		MT9M114_COMMAND_REGISTER_SET_STATE), MSM_CAMERA_I2C_WORD_DATA,
+		MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_SET_STATE,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{0xDC01, 0x52, MSM_CAMERA_I2C_BYTE_DATA, MSM_CAMERA_I2C_CMD_POLL},
+
+	{0x098E, 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC800, 0x007C,},/*y_addr_start = 124*/
+	{0xC802, 0x0004,},/*x_addr_start = 4*/
+	{0xC804, 0x0353,},/*y_addr_end = 851*/
+	{0xC806, 0x050B,},/*x_addr_end = 1291*/
+	{0xC808, 0x02DC,},/*pixclk = 48000000*/
+	{0xC80A, 0x6C00,},/*pixclk = 48000000*/
+	{0xC80C, 0x0001,},/*row_speed = 1*/
+	{0xC80E, 0x00DB,},/*fine_integ_time_min = 219*/
+	{0xC810, 0x05BD,},/*fine_integ_time_max = 1469*/
+	{0xC812, 0x03E8,},/*frame_length_lines = 1000*/
+	{0xC814, 0x0640,},/*line_length_pck = 1600*/
+	{0xC816, 0x0060,},/*fine_correction = 96*/
+	{0xC818, 0x02D3,},/*cpipe_last_row = 723*/
+	{0xC826, 0x0020,},/*reg_0_data = 32*/
+	{0xC834, 0x0000,},/*sensor_control_read_mode = 0*/
+	{0xC854, 0x0000,},/*crop_window_xoffset = 0*/
+	{0xC856, 0x0000,},/*crop_window_yoffset = 0*/
+	{0xC858, 0x0500,},/*crop_window_width = 1280*/
+	{0xC85A, 0x02D0,},/*crop_window_height = 720*/
+	{0xC85C, 0x03, MSM_CAMERA_I2C_BYTE_DATA},  /*crop_cropmode = 3*/
+	{0xC868, 0x0500,},/*output_width = 1280*/
+	{0xC86A, 0x02D0,},/*output_height = 720*/
+	{0xC878, 0x00, MSM_CAMERA_I2C_BYTE_DATA},  /*aet_aemode = 0*/
+	{0xC88C, 0x1E00,},/*aet_max_frame_rate = 7680*/
+	{0xC88E, 0x1E00,},/*aet_min_frame_rate = 7680*/
+	{0xC914, 0x0000,},/*stat_awb_window_xstart = 0*/
+	{0xC916, 0x0000,},/*stat_awb_window_ystart = 0*/
+	{0xC918, 0x04FF,},/*stat_awb_window_xend = 1279*/
+	{0xC91A, 0x02CF,},/*stat_awb_window_yend = 719*/
+	{0xC91C, 0x0000,},/*stat_ae_window_xstart = 0*/
+	{0xC91E, 0x0000,},/*stat_ae_window_ystart = 0*/
+	{0xC920, 0x00FF,},/*stat_ae_window_xend = 255*/
+	{0xC922, 0x008F,},/*stat_ae_window_yend = 143*/
+};
+
+static struct msm_camera_i2c_reg_conf mt9m114_recommend_settings[] = {
+	{0x301A, 0x0200, MSM_CAMERA_I2C_SET_WORD_MASK},
+	{0x098E, 0, MSM_CAMERA_I2C_BYTE_DATA},
+	/*cam_sysctl_pll_enable = 1*/
+	{0xC97E, 0x01, MSM_CAMERA_I2C_BYTE_DATA},
+	/*cam_sysctl_pll_divider_m_n = 288*/
+	{0xC980, 0x0120,},
+	/*cam_sysctl_pll_divider_p = 1792*/
+	{0xC982, 0x0700,},
+	/*output_control = 32769*/
+	{0xC984, 0x8001,},
+	/*mipi_timing_t_hs_zero = 3840*/
+	{0xC988, 0x0F00,},
+	/*mipi_timing_t_hs_exit_hs_trail = 2823*/
+	{0xC98A, 0x0B07,},
+	/*mipi_timing_t_clk_post_clk_pre = 3329*/
+	{0xC98C, 0x0D01,},
+	/*mipi_timing_t_clk_trail_clk_zero = 1821*/
+	{0xC98E, 0x071D,},
+	/*mipi_timing_t_lpx = 6*/
+	{0xC990, 0x0006,},
+	/*mipi_timing_init_timing = 2572*/
+	{0xC992, 0x0A0C,},
+	{0xC800, 0x007C,},/*y_addr_start = 124*/
+	{0xC802, 0x0004,},/*x_addr_start = 4*/
+	{0xC804, 0x0353,},/*y_addr_end = 851*/
+	{0xC806, 0x050B,},/*x_addr_end = 1291*/
+	{0xC808, 0x02DC,},/*pixclk = 48000000*/
+	{0xC80A, 0x6C00,},/*pixclk = 48000000*/
+	{0xC80C, 0x0001,},/*row_speed = 1*/
+	{0xC80E, 0x00DB,},/*fine_integ_time_min = 219*/
+	{0xC810, 0x05BD,},/*fine_integ_time_max = 1469*/
+	{0xC812, 0x03E8,},/*frame_length_lines = 1000*/
+	{0xC814, 0x0640,},/*line_length_pck = 1600*/
+	{0xC816, 0x0060,},/*fine_correction = 96*/
+	{0xC818, 0x02D3,},/*cpipe_last_row = 723*/
+	{0xC826, 0x0020,},/*reg_0_data = 32*/
+	{0xC834, 0x0000,},/*sensor_control_read_mode = 0*/
+	{0xC854, 0x0000,},/*crop_window_xoffset = 0*/
+	{0xC856, 0x0000,},/*crop_window_yoffset = 0*/
+	{0xC858, 0x0500,},/*crop_window_width = 1280*/
+	{0xC85A, 0x02D0,},/*crop_window_height = 720*/
+	{0xC85C, 0x03, MSM_CAMERA_I2C_BYTE_DATA},  /*crop_cropmode = 3*/
+	{0xC868, 0x0500,},/*output_width = 1280*/
+	{0xC86A, 0x02D0,},/*output_height = 720*/
+	{0xC878, 0x00, MSM_CAMERA_I2C_BYTE_DATA},  /*aet_aemode = 0*/
+	{0xC88C, 0x1E00,},/*aet_max_frame_rate = 7680*/
+	{0xC88E, 0x1E00,},/*aet_min_frame_rate = 7680*/
+	{0xC914, 0x0000,},/*stat_awb_window_xstart = 0*/
+	{0xC916, 0x0000,},/*stat_awb_window_ystart = 0*/
+	{0xC918, 0x04FF,},/*stat_awb_window_xend = 1279*/
+	{0xC91A, 0x02CF,},/*stat_awb_window_yend = 719*/
+	{0xC91C, 0x0000,},/*stat_ae_window_xstart = 0*/
+	{0xC91E, 0x0000,},/*stat_ae_window_ystart = 0*/
+	{0xC920, 0x00FF,},/*stat_ae_window_xend = 255*/
+	{0xC922, 0x008F,},/*stat_ae_window_yend = 143*/
+
+	/*Sensor optimization*/
+	{0x316A, 0x8270,},
+	{0x316C, 0x8270,},
+	{0x3ED0, 0x2305,},
+	{0x3ED2, 0x77CF,},
+	{0x316E, 0x8202,},
+	{0x3180, 0x87FF,},
+	{0x30D4, 0x6080,},
+	{0xA802, 0x0008,},/*AE_TRACK_MODE*/
+	{0x3E14, 0xFF39,},
+	{0x0982, 0x0001,},/*ACCESS_CTL_STAT*/
+	{0x098A, 0x5000,},/*PHYSICAL_ADDRESS_ACCESS*/
+	{0xD000, 0x70CF,},
+	{0xD002, 0xFFFF,},
+	{0xD004, 0xC5D4,},
+	{0xD006, 0x903A,},
+	{0xD008, 0x2144,},
+	{0xD00A, 0x0C00,},
+	{0xD00C, 0x2186,},
+	{0xD00E, 0x0FF3,},
+	{0xD010, 0xB844,},
+	{0xD012, 0xB948,},
+	{0xD014, 0xE082,},
+	{0xD016, 0x20CC,},
+	{0xD018, 0x80E2,},
+	{0xD01A, 0x21CC,},
+	{0xD01C, 0x80A2,},
+	{0xD01E, 0x21CC,},
+	{0xD020, 0x80E2,},
+	{0xD022, 0xF404,},
+	{0xD024, 0xD801,},
+	{0xD026, 0xF003,},
+	{0xD028, 0xD800,},
+	{0xD02A, 0x7EE0,},
+	{0xD02C, 0xC0F1,},
+	{0xD02E, 0x08BA,},
+	{0xD030, 0x0600,},
+	{0xD032, 0xC1A1,},
+	{0xD034, 0x76CF,},
+	{0xD036, 0xFFFF,},
+	{0xD038, 0xC130,},
+	{0xD03A, 0x6E04,},
+	{0xD03C, 0xC040,},
+	{0xD03E, 0x71CF,},
+	{0xD040, 0xFFFF,},
+	{0xD042, 0xC790,},
+	{0xD044, 0x8103,},
+	{0xD046, 0x77CF,},
+	{0xD048, 0xFFFF,},
+	{0xD04A, 0xC7C0,},
+	{0xD04C, 0xE001,},
+	{0xD04E, 0xA103,},
+	{0xD050, 0xD800,},
+	{0xD052, 0x0C6A,},
+	{0xD054, 0x04E0,},
+	{0xD056, 0xB89E,},
+	{0xD058, 0x7508,},
+	{0xD05A, 0x8E1C,},
+	{0xD05C, 0x0809,},
+	{0xD05E, 0x0191,},
+	{0xD060, 0xD801,},
+	{0xD062, 0xAE1D,},
+	{0xD064, 0xE580,},
+	{0xD066, 0x20CA,},
+	{0xD068, 0x0022,},
+	{0xD06A, 0x20CF,},
+	{0xD06C, 0x0522,},
+	{0xD06E, 0x0C5C,},
+	{0xD070, 0x04E2,},
+	{0xD072, 0x21CA,},
+	{0xD074, 0x0062,},
+	{0xD076, 0xE580,},
+	{0xD078, 0xD901,},
+	{0xD07A, 0x79C0,},
+	{0xD07C, 0xD800,},
+	{0xD07E, 0x0BE6,},
+	{0xD080, 0x04E0,},
+	{0xD082, 0xB89E,},
+	{0xD084, 0x70CF,},
+	{0xD086, 0xFFFF,},
+	{0xD088, 0xC8D4,},
+	{0xD08A, 0x9002,},
+	{0xD08C, 0x0857,},
+	{0xD08E, 0x025E,},
+	{0xD090, 0xFFDC,},
+	{0xD092, 0xE080,},
+	{0xD094, 0x25CC,},
+	{0xD096, 0x9022,},
+	{0xD098, 0xF225,},
+	{0xD09A, 0x1700,},
+	{0xD09C, 0x108A,},
+	{0xD09E, 0x73CF,},
+	{0xD0A0, 0xFF00,},
+	{0xD0A2, 0x3174,},
+	{0xD0A4, 0x9307,},
+	{0xD0A6, 0x2A04,},
+	{0xD0A8, 0x103E,},
+	{0xD0AA, 0x9328,},
+	{0xD0AC, 0x2942,},
+	{0xD0AE, 0x7140,},
+	{0xD0B0, 0x2A04,},
+	{0xD0B2, 0x107E,},
+	{0xD0B4, 0x9349,},
+	{0xD0B6, 0x2942,},
+	{0xD0B8, 0x7141,},
+	{0xD0BA, 0x2A04,},
+	{0xD0BC, 0x10BE,},
+	{0xD0BE, 0x934A,},
+	{0xD0C0, 0x2942,},
+	{0xD0C2, 0x714B,},
+	{0xD0C4, 0x2A04,},
+	{0xD0C6, 0x10BE,},
+	{0xD0C8, 0x130C,},
+	{0xD0CA, 0x010A,},
+	{0xD0CC, 0x2942,},
+	{0xD0CE, 0x7142,},
+	{0xD0D0, 0x2250,},
+	{0xD0D2, 0x13CA,},
+	{0xD0D4, 0x1B0C,},
+	{0xD0D6, 0x0284,},
+	{0xD0D8, 0xB307,},
+	{0xD0DA, 0xB328,},
+	{0xD0DC, 0x1B12,},
+	{0xD0DE, 0x02C4,},
+	{0xD0E0, 0xB34A,},
+	{0xD0E2, 0xED88,},
+	{0xD0E4, 0x71CF,},
+	{0xD0E6, 0xFF00,},
+	{0xD0E8, 0x3174,},
+	{0xD0EA, 0x9106,},
+	{0xD0EC, 0xB88F,},
+	{0xD0EE, 0xB106,},
+	{0xD0F0, 0x210A,},
+	{0xD0F2, 0x8340,},
+	{0xD0F4, 0xC000,},
+	{0xD0F6, 0x21CA,},
+	{0xD0F8, 0x0062,},
+	{0xD0FA, 0x20F0,},
+	{0xD0FC, 0x0040,},
+	{0xD0FE, 0x0B02,},
+	{0xD100, 0x0320,},
+	{0xD102, 0xD901,},
+	{0xD104, 0x07F1,},
+	{0xD106, 0x05E0,},
+	{0xD108, 0xC0A1,},
+	{0xD10A, 0x78E0,},
+	{0xD10C, 0xC0F1,},
+	{0xD10E, 0x71CF,},
+	{0xD110, 0xFFFF,},
+	{0xD112, 0xC7C0,},
+	{0xD114, 0xD840,},
+	{0xD116, 0xA900,},
+	{0xD118, 0x71CF,},
+	{0xD11A, 0xFFFF,},
+	{0xD11C, 0xD02C,},
+	{0xD11E, 0xD81E,},
+	{0xD120, 0x0A5A,},
+	{0xD122, 0x04E0,},
+	{0xD124, 0xDA00,},
+	{0xD126, 0xD800,},
+	{0xD128, 0xC0D1,},
+	{0xD12A, 0x7EE0,},
+	{0x098E, 0x0000,},
+
+	{0x0982, 0x0001,},
+	{0x098A, 0x5C10,},
+	{0xDC10, 0xC0F1,},
+	{0xDC12, 0x0CDA,},
+	{0xDC14, 0x0580,},
+	{0xDC16, 0x76CF,},
+	{0xDC18, 0xFF00,},
+	{0xDC1A, 0x2184,},
+	{0xDC1C, 0x9624,},
+	{0xDC1E, 0x218C,},
+	{0xDC20, 0x8FC3,},
+	{0xDC22, 0x75CF,},
+	{0xDC24, 0xFFFF,},
+	{0xDC26, 0xE058,},
+	{0xDC28, 0xF686,},
+	{0xDC2A, 0x1550,},
+	{0xDC2C, 0x1080,},
+	{0xDC2E, 0xE001,},
+	{0xDC30, 0x1D50,},
+	{0xDC32, 0x1002,},
+	{0xDC34, 0x1552,},
+	{0xDC36, 0x1100,},
+	{0xDC38, 0x6038,},
+	{0xDC3A, 0x1D52,},
+	{0xDC3C, 0x1004,},
+	{0xDC3E, 0x1540,},
+	{0xDC40, 0x1080,},
+	{0xDC42, 0x081B,},
+	{0xDC44, 0x00D1,},
+	{0xDC46, 0x8512,},
+	{0xDC48, 0x1000,},
+	{0xDC4A, 0x00C0,},
+	{0xDC4C, 0x7822,},
+	{0xDC4E, 0x2089,},
+	{0xDC50, 0x0FC1,},
+	{0xDC52, 0x2008,},
+	{0xDC54, 0x0F81,},
+	{0xDC56, 0xFFFF,},
+	{0xDC58, 0xFF80,},
+	{0xDC5A, 0x8512,},
+	{0xDC5C, 0x1801,},
+	{0xDC5E, 0x0052,},
+	{0xDC60, 0xA512,},
+	{0xDC62, 0x1544,},
+	{0xDC64, 0x1080,},
+	{0xDC66, 0xB861,},
+	{0xDC68, 0x262F,},
+	{0xDC6A, 0xF007,},
+	{0xDC6C, 0x1D44,},
+	{0xDC6E, 0x1002,},
+	{0xDC70, 0x20CA,},
+	{0xDC72, 0x0021,},
+	{0xDC74, 0x20CF,},
+	{0xDC76, 0x04E1,},
+	{0xDC78, 0x0850,},
+	{0xDC7A, 0x04A1,},
+	{0xDC7C, 0x21CA,},
+	{0xDC7E, 0x0021,},
+	{0xDC80, 0x1542,},
+	{0xDC82, 0x1140,},
+	{0xDC84, 0x8D2C,},
+	{0xDC86, 0x6038,},
+	{0xDC88, 0x1D42,},
+	{0xDC8A, 0x1004,},
+	{0xDC8C, 0x1542,},
+	{0xDC8E, 0x1140,},
+	{0xDC90, 0xB601,},
+	{0xDC92, 0x046D,},
+	{0xDC94, 0x0580,},
+	{0xDC96, 0x78E0,},
+	{0xDC98, 0xD800,},
+	{0xDC9A, 0xB893,},
+	{0xDC9C, 0x002D,},
+	{0xDC9E, 0x04A0,},
+	{0xDCA0, 0xD900,},
+	{0xDCA2, 0x78E0,},
+	{0xDCA4, 0x72CF,},
+	{0xDCA6, 0xFFFF,},
+	{0xDCA8, 0xE058,},
+	{0xDCAA, 0x2240,},
+	{0xDCAC, 0x0340,},
+	{0xDCAE, 0xA212,},
+	{0xDCB0, 0x208A,},
+	{0xDCB2, 0x0FFF,},
+	{0xDCB4, 0x1A42,},
+	{0xDCB6, 0x0004,},
+	{0xDCB8, 0xD830,},
+	{0xDCBA, 0x1A44,},
+	{0xDCBC, 0x0002,},
+	{0xDCBE, 0xD800,},
+	{0xDCC0, 0x1A50,},
+	{0xDCC2, 0x0002,},
+	{0xDCC4, 0x1A52,},
+	{0xDCC6, 0x0004,},
+	{0xDCC8, 0x1242,},
+	{0xDCCA, 0x0140,},
+	{0xDCCC, 0x8A2C,},
+	{0xDCCE, 0x6038,},
+	{0xDCD0, 0x1A42,},
+	{0xDCD2, 0x0004,},
+	{0xDCD4, 0x1242,},
+	{0xDCD6, 0x0141,},
+	{0xDCD8, 0x70CF,},
+	{0xDCDA, 0xFF00,},
+	{0xDCDC, 0x2184,},
+	{0xDCDE, 0xB021,},
+	{0xDCE0, 0xD800,},
+	{0xDCE2, 0xB893,},
+	{0xDCE4, 0x07E5,},
+	{0xDCE6, 0x0460,},
+	{0xDCE8, 0xD901,},
+	{0xDCEA, 0x78E0,},
+	{0xDCEC, 0xC0F1,},
+	{0xDCEE, 0x0BFA,},
+	{0xDCF0, 0x05A0,},
+	{0xDCF2, 0x216F,},
+	{0xDCF4, 0x0043,},
+	{0xDCF6, 0xC1A4,},
+	{0xDCF8, 0x220A,},
+	{0xDCFA, 0x1F80,},
+	{0xDCFC, 0xFFFF,},
+	{0xDCFE, 0xE058,},
+	{0xDD00, 0x2240,},
+	{0xDD02, 0x134F,},
+	{0xDD04, 0x1A48,},
+	{0xDD06, 0x13C0,},
+	{0xDD08, 0x1248,},
+	{0xDD0A, 0x1002,},
+	{0xDD0C, 0x70CF,},
+	{0xDD0E, 0x7FFF,},
+	{0xDD10, 0xFFFF,},
+	{0xDD12, 0xE230,},
+	{0xDD14, 0xC240,},
+	{0xDD16, 0xDA00,},
+	{0xDD18, 0xF00C,},
+	{0xDD1A, 0x1248,},
+	{0xDD1C, 0x1003,},
+	{0xDD1E, 0x1301,},
+	{0xDD20, 0x04CB,},
+	{0xDD22, 0x7261,},
+	{0xDD24, 0x2108,},
+	{0xDD26, 0x0081,},
+	{0xDD28, 0x2009,},
+	{0xDD2A, 0x0080,},
+	{0xDD2C, 0x1A48,},
+	{0xDD2E, 0x10C0,},
+	{0xDD30, 0x1248,},
+	{0xDD32, 0x100B,},
+	{0xDD34, 0xC300,},
+	{0xDD36, 0x0BE7,},
+	{0xDD38, 0x90C4,},
+	{0xDD3A, 0x2102,},
+	{0xDD3C, 0x0003,},
+	{0xDD3E, 0x238C,},
+	{0xDD40, 0x8FC3,},
+	{0xDD42, 0xF6C7,},
+	{0xDD44, 0xDAFF,},
+	{0xDD46, 0x1A05,},
+	{0xDD48, 0x1082,},
+	{0xDD4A, 0xC241,},
+	{0xDD4C, 0xF005,},
+	{0xDD4E, 0x7A6F,},
+	{0xDD50, 0xC241,},
+	{0xDD52, 0x1A05,},
+	{0xDD54, 0x10C2,},
+	{0xDD56, 0x2000,},
+	{0xDD58, 0x8040,},
+	{0xDD5A, 0xDA00,},
+	{0xDD5C, 0x20C0,},
+	{0xDD5E, 0x0064,},
+	{0xDD60, 0x781C,},
+	{0xDD62, 0xC042,},
+	{0xDD64, 0x1C0E,},
+	{0xDD66, 0x3082,},
+	{0xDD68, 0x1A48,},
+	{0xDD6A, 0x13C0,},
+	{0xDD6C, 0x7548,},
+	{0xDD6E, 0x7348,},
+	{0xDD70, 0x7148,},
+	{0xDD72, 0x7648,},
+	{0xDD74, 0xF002,},
+	{0xDD76, 0x7608,},
+	{0xDD78, 0x1248,},
+	{0xDD7A, 0x1000,},
+	{0xDD7C, 0x1400,},
+	{0xDD7E, 0x300B,},
+	{0xDD80, 0x084D,},
+	{0xDD82, 0x02C5,},
+	{0xDD84, 0x1248,},
+	{0xDD86, 0x1000,},
+	{0xDD88, 0xE101,},
+	{0xDD8A, 0x1001,},
+	{0xDD8C, 0x04CB,},
+	{0xDD8E, 0x1A48,},
+	{0xDD90, 0x1000,},
+	{0xDD92, 0x7361,},
+	{0xDD94, 0x1408,},
+	{0xDD96, 0x300B,},
+	{0xDD98, 0x2302,},
+	{0xDD9A, 0x02C0,},
+	{0xDD9C, 0x780D,},
+	{0xDD9E, 0x2607,},
+	{0xDDA0, 0x903E,},
+	{0xDDA2, 0x07D6,},
+	{0xDDA4, 0xFFE3,},
+	{0xDDA6, 0x792F,},
+	{0xDDA8, 0x09CF,},
+	{0xDDAA, 0x8152,},
+	{0xDDAC, 0x1248,},
+	{0xDDAE, 0x100E,},
+	{0xDDB0, 0x2400,},
+	{0xDDB2, 0x334B,},
+	{0xDDB4, 0xE501,},
+	{0xDDB6, 0x7EE2,},
+	{0xDDB8, 0x0DBF,},
+	{0xDDBA, 0x90F2,},
+	{0xDDBC, 0x1B0C,},
+	{0xDDBE, 0x1382,},
+	{0xDDC0, 0xC123,},
+	{0xDDC2, 0x140E,},
+	{0xDDC4, 0x3080,},
+	{0xDDC6, 0x7822,},
+	{0xDDC8, 0x1A07,},
+	{0xDDCA, 0x1002,},
+	{0xDDCC, 0x124C,},
+	{0xDDCE, 0x1000,},
+	{0xDDD0, 0x120B,},
+	{0xDDD2, 0x1081,},
+	{0xDDD4, 0x1207,},
+	{0xDDD6, 0x1083,},
+	{0xDDD8, 0x2142,},
+	{0xDDDA, 0x004B,},
+	{0xDDDC, 0x781B,},
+	{0xDDDE, 0x0B21,},
+	{0xDDE0, 0x02E2,},
+	{0xDDE2, 0x1A4C,},
+	{0xDDE4, 0x1000,},
+	{0xDDE6, 0xE101,},
+	{0xDDE8, 0x0915,},
+	{0xDDEA, 0x00C2,},
+	{0xDDEC, 0xC101,},
+	{0xDDEE, 0x1204,},
+	{0xDDF0, 0x1083,},
+	{0xDDF2, 0x090D,},
+	{0xDDF4, 0x00C2,},
+	{0xDDF6, 0xE001,},
+	{0xDDF8, 0x1A4C,},
+	{0xDDFA, 0x1000,},
+	{0xDDFC, 0x1A06,},
+	{0xDDFE, 0x1002,},
+	{0xDE00, 0x234A,},
+	{0xDE02, 0x1000,},
+	{0xDE04, 0x7169,},
+	{0xDE06, 0xF008,},
+	{0xDE08, 0x2053,},
+	{0xDE0A, 0x0003,},
+	{0xDE0C, 0x6179,},
+	{0xDE0E, 0x781C,},
+	{0xDE10, 0x2340,},
+	{0xDE12, 0x104B,},
+	{0xDE14, 0x1203,},
+	{0xDE16, 0x1083,},
+	{0xDE18, 0x0BF1,},
+	{0xDE1A, 0x90C2,},
+	{0xDE1C, 0x1202,},
+	{0xDE1E, 0x1080,},
+	{0xDE20, 0x091D,},
+	{0xDE22, 0x0004,},
+	{0xDE24, 0x70CF,},
+	{0xDE26, 0xFFFF,},
+	{0xDE28, 0xC644,},
+	{0xDE2A, 0x881B,},
+	{0xDE2C, 0xE0B2,},
+	{0xDE2E, 0xD83C,},
+	{0xDE30, 0x20CA,},
+	{0xDE32, 0x0CA2,},
+	{0xDE34, 0x1A01,},
+	{0xDE36, 0x1002,},
+	{0xDE38, 0x1A4C,},
+	{0xDE3A, 0x1080,},
+	{0xDE3C, 0x02B9,},
+	{0xDE3E, 0x05A0,},
+	{0xDE40, 0xC0A4,},
+	{0xDE42, 0x78E0,},
+	{0xDE44, 0xC0F1,},
+	{0xDE46, 0xFF95,},
+	{0xDE48, 0xD800,},
+	{0xDE4A, 0x71CF,},
+	{0xDE4C, 0xFF00,},
+	{0xDE4E, 0x1FE0,},
+	{0xDE50, 0x19D0,},
+	{0xDE52, 0x001C,},
+	{0xDE54, 0x19D1,},
+	{0xDE56, 0x001C,},
+	{0xDE58, 0x70CF,},
+	{0xDE5A, 0xFFFF,},
+	{0xDE5C, 0xE058,},
+	{0xDE5E, 0x901F,},
+	{0xDE60, 0xB861,},
+	{0xDE62, 0x19D2,},
+	{0xDE64, 0x001C,},
+	{0xDE66, 0xC0D1,},
+	{0xDE68, 0x7EE0,},
+	{0xDE6A, 0x78E0,},
+	{0xDE6C, 0xC0F1,},
+	{0xDE6E, 0x0A7A,},
+	{0xDE70, 0x0580,},
+	{0xDE72, 0x70CF,},
+	{0xDE74, 0xFFFF,},
+	{0xDE76, 0xC5D4,},
+	{0xDE78, 0x9041,},
+	{0xDE7A, 0x9023,},
+	{0xDE7C, 0x75CF,},
+	{0xDE7E, 0xFFFF,},
+	{0xDE80, 0xE058,},
+	{0xDE82, 0x7942,},
+	{0xDE84, 0xB967,},
+	{0xDE86, 0x7F30,},
+	{0xDE88, 0xB53F,},
+	{0xDE8A, 0x71CF,},
+	{0xDE8C, 0xFFFF,},
+	{0xDE8E, 0xC84C,},
+	{0xDE90, 0x91D3,},
+	{0xDE92, 0x108B,},
+	{0xDE94, 0x0081,},
+	{0xDE96, 0x2615,},
+	{0xDE98, 0x1380,},
+	{0xDE9A, 0x090F,},
+	{0xDE9C, 0x0C91,},
+	{0xDE9E, 0x0A8E,},
+	{0xDEA0, 0x05A0,},
+	{0xDEA2, 0xD906,},
+	{0xDEA4, 0x7E10,},
+	{0xDEA6, 0x2615,},
+	{0xDEA8, 0x1380,},
+	{0xDEAA, 0x0A82,},
+	{0xDEAC, 0x05A0,},
+	{0xDEAE, 0xD960,},
+	{0xDEB0, 0x790F,},
+	{0xDEB2, 0x090D,},
+	{0xDEB4, 0x0133,},
+	{0xDEB6, 0xAD0C,},
+	{0xDEB8, 0xD904,},
+	{0xDEBA, 0xAD2C,},
+	{0xDEBC, 0x79EC,},
+	{0xDEBE, 0x2941,},
+	{0xDEC0, 0x7402,},
+	{0xDEC2, 0x71CF,},
+	{0xDEC4, 0xFF00,},
+	{0xDEC6, 0x2184,},
+	{0xDEC8, 0xB142,},
+	{0xDECA, 0x1906,},
+	{0xDECC, 0x0E44,},
+	{0xDECE, 0xFFDE,},
+	{0xDED0, 0x70C9,},
+	{0xDED2, 0x0A5A,},
+	{0xDED4, 0x05A0,},
+	{0xDED6, 0x8D2C,},
+	{0xDED8, 0xAD0B,},
+	{0xDEDA, 0xD800,},
+	{0xDEDC, 0xAD01,},
+	{0xDEDE, 0x0219,},
+	{0xDEE0, 0x05A0,},
+	{0xDEE2, 0xA513,},
+	{0xDEE4, 0xC0F1,},
+	{0xDEE6, 0x71CF,},
+	{0xDEE8, 0xFFFF,},
+	{0xDEEA, 0xC644,},
+	{0xDEEC, 0xA91B,},
+	{0xDEEE, 0xD902,},
+	{0xDEF0, 0x70CF,},
+	{0xDEF2, 0xFFFF,},
+	{0xDEF4, 0xC84C,},
+	{0xDEF6, 0x093E,},
+	{0xDEF8, 0x03A0,},
+	{0xDEFA, 0xA826,},
+	{0xDEFC, 0xFFDC,},
+	{0xDEFE, 0xF1B5,},
+	{0xDF00, 0xC0F1,},
+	{0xDF02, 0x09EA,},
+	{0xDF04, 0x0580,},
+	{0xDF06, 0x75CF,},
+	{0xDF08, 0xFFFF,},
+	{0xDF0A, 0xE058,},
+	{0xDF0C, 0x1540,},
+	{0xDF0E, 0x1080,},
+	{0xDF10, 0x08A7,},
+	{0xDF12, 0x0010,},
+	{0xDF14, 0x8D00,},
+	{0xDF16, 0x0813,},
+	{0xDF18, 0x009E,},
+	{0xDF1A, 0x1540,},
+	{0xDF1C, 0x1081,},
+	{0xDF1E, 0xE181,},
+	{0xDF20, 0x20CA,},
+	{0xDF22, 0x00A1,},
+	{0xDF24, 0xF24B,},
+	{0xDF26, 0x1540,},
+	{0xDF28, 0x1081,},
+	{0xDF2A, 0x090F,},
+	{0xDF2C, 0x0050,},
+	{0xDF2E, 0x1540,},
+	{0xDF30, 0x1081,},
+	{0xDF32, 0x0927,},
+	{0xDF34, 0x0091,},
+	{0xDF36, 0x1550,},
+	{0xDF38, 0x1081,},
+	{0xDF3A, 0xDE00,},
+	{0xDF3C, 0xAD2A,},
+	{0xDF3E, 0x1D50,},
+	{0xDF40, 0x1382,},
+	{0xDF42, 0x1552,},
+	{0xDF44, 0x1101,},
+	{0xDF46, 0x1D52,},
+	{0xDF48, 0x1384,},
+	{0xDF4A, 0xB524,},
+	{0xDF4C, 0x082D,},
+	{0xDF4E, 0x015F,},
+	{0xDF50, 0xFF55,},
+	{0xDF52, 0xD803,},
+	{0xDF54, 0xF033,},
+	{0xDF56, 0x1540,},
+	{0xDF58, 0x1081,},
+	{0xDF5A, 0x0967,},
+	{0xDF5C, 0x00D1,},
+	{0xDF5E, 0x1550,},
+	{0xDF60, 0x1081,},
+	{0xDF62, 0xDE00,},
+	{0xDF64, 0xAD2A,},
+	{0xDF66, 0x1D50,},
+	{0xDF68, 0x1382,},
+	{0xDF6A, 0x1552,},
+	{0xDF6C, 0x1101,},
+	{0xDF6E, 0x1D52,},
+	{0xDF70, 0x1384,},
+	{0xDF72, 0xB524,},
+	{0xDF74, 0x0811,},
+	{0xDF76, 0x019E,},
+	{0xDF78, 0xB8A0,},
+	{0xDF7A, 0xAD00,},
+	{0xDF7C, 0xFF47,},
+	{0xDF7E, 0x1D40,},
+	{0xDF80, 0x1382,},
+	{0xDF82, 0xF01F,},
+	{0xDF84, 0xFF5A,},
+	{0xDF86, 0x8D01,},
+	{0xDF88, 0x8D40,},
+	{0xDF8A, 0xE812,},
+	{0xDF8C, 0x71CF,},
+	{0xDF8E, 0xFFFF,},
+	{0xDF90, 0xC644,},
+	{0xDF92, 0x893B,},
+	{0xDF94, 0x7030,},
+	{0xDF96, 0x22D1,},
+	{0xDF98, 0x8062,},
+	{0xDF9A, 0xF20A,},
+	{0xDF9C, 0x0A0F,},
+	{0xDF9E, 0x009E,},
+	{0xDFA0, 0x71CF,},
+	{0xDFA2, 0xFFFF,},
+	{0xDFA4, 0xC84C,},
+	{0xDFA6, 0x893B,},
+	{0xDFA8, 0xE902,},
+	{0xDFAA, 0xFFCF,},
+	{0xDFAC, 0x8D00,},
+	{0xDFAE, 0xB8E7,},
+	{0xDFB0, 0x26CA,},
+	{0xDFB2, 0x1022,},
+	{0xDFB4, 0xF5E2,},
+	{0xDFB6, 0xFF3C,},
+	{0xDFB8, 0xD801,},
+	{0xDFBA, 0x1D40,},
+	{0xDFBC, 0x1002,},
+	{0xDFBE, 0x0141,},
+	{0xDFC0, 0x0580,},
+	{0xDFC2, 0x78E0,},
+	{0xDFC4, 0xC0F1,},
+	{0xDFC6, 0xC5E1,},
+	{0xDFC8, 0xFF34,},
+	{0xDFCA, 0xDD00,},
+	{0xDFCC, 0x70CF,},
+	{0xDFCE, 0xFFFF,},
+	{0xDFD0, 0xE090,},
+	{0xDFD2, 0xA8A8,},
+	{0xDFD4, 0xD800,},
+	{0xDFD6, 0xB893,},
+	{0xDFD8, 0x0C8A,},
+	{0xDFDA, 0x0460,},
+	{0xDFDC, 0xD901,},
+	{0xDFDE, 0x71CF,},
+	{0xDFE0, 0xFFFF,},
+	{0xDFE2, 0xDC10,},
+	{0xDFE4, 0xD813,},
+	{0xDFE6, 0x0B96,},
+	{0xDFE8, 0x0460,},
+	{0xDFEA, 0x72A9,},
+	{0xDFEC, 0x0119,},
+	{0xDFEE, 0x0580,},
+	{0xDFF0, 0xC0F1,},
+	{0xDFF2, 0x71CF,},
+	{0xDFF4, 0x0000,},
+	{0xDFF6, 0x5BAE,},
+	{0xDFF8, 0x7940,},
+	{0xDFFA, 0xFF9D,},
+	{0xDFFC, 0xF135,},
+	{0xDFFE, 0x78E0,},
+	{0xE000, 0xC0F1,},
+	{0xE002, 0x70CF,},
+	{0xE004, 0x0000,},
+	{0xE006, 0x5CBA,},
+	{0xE008, 0x7840,},
+	{0xE00A, 0x70CF,},
+	{0xE00C, 0xFFFF,},
+	{0xE00E, 0xE058,},
+	{0xE010, 0x8800,},
+	{0xE012, 0x0815,},
+	{0xE014, 0x001E,},
+	{0xE016, 0x70CF,},
+	{0xE018, 0xFFFF,},
+	{0xE01A, 0xC84C,},
+	{0xE01C, 0x881A,},
+	{0xE01E, 0xE080,},
+	{0xE020, 0x0EE0,},
+	{0xE022, 0xFFC1,},
+	{0xE024, 0xF121,},
+	{0xE026, 0x78E0,},
+	{0xE028, 0xC0F1,},
+	{0xE02A, 0xD900,},
+	{0xE02C, 0xF009,},
+	{0xE02E, 0x70CF,},
+	{0xE030, 0xFFFF,},
+	{0xE032, 0xE0AC,},
+	{0xE034, 0x7835,},
+	{0xE036, 0x8041,},
+	{0xE038, 0x8000,},
+	{0xE03A, 0xE102,},
+	{0xE03C, 0xA040,},
+	{0xE03E, 0x09F3,},
+	{0xE040, 0x8114,},
+	{0xE042, 0x71CF,},
+	{0xE044, 0xFFFF,},
+	{0xE046, 0xE058,},
+	{0xE048, 0x70CF,},
+	{0xE04A, 0xFFFF,},
+	{0xE04C, 0xC594,},
+	{0xE04E, 0xB030,},
+	{0xE050, 0xFFDD,},
+	{0xE052, 0xD800,},
+	{0xE054, 0xF109,},
+	{0xE056, 0x0000,},
+	{0xE058, 0x0300,},
+	{0xE05A, 0x0204,},
+	{0xE05C, 0x0700,},
+	{0xE05E, 0x0000,},
+	{0xE060, 0x0000,},
+	{0xE062, 0x0000,},
+	{0xE064, 0x0000,},
+	{0xE066, 0x0000,},
+	{0xE068, 0x0000,},
+	{0xE06A, 0x0000,},
+	{0xE06C, 0x0000,},
+	{0xE06E, 0x0000,},
+	{0xE070, 0x0000,},
+	{0xE072, 0x0000,},
+	{0xE074, 0x0000,},
+	{0xE076, 0x0000,},
+	{0xE078, 0x0000,},
+	{0xE07A, 0x0000,},
+	{0xE07C, 0x0000,},
+	{0xE07E, 0x0000,},
+	{0xE080, 0x0000,},
+	{0xE082, 0x0000,},
+	{0xE084, 0x0000,},
+	{0xE086, 0x0000,},
+	{0xE088, 0x0000,},
+	{0xE08A, 0x0000,},
+	{0xE08C, 0x0000,},
+	{0xE08E, 0x0000,},
+	{0xE090, 0x0000,},
+	{0xE092, 0x0000,},
+	{0xE094, 0x0000,},
+	{0xE096, 0x0000,},
+	{0xE098, 0x0000,},
+	{0xE09A, 0x0000,},
+	{0xE09C, 0x0000,},
+	{0xE09E, 0x0000,},
+	{0xE0A0, 0x0000,},
+	{0xE0A2, 0x0000,},
+	{0xE0A4, 0x0000,},
+	{0xE0A6, 0x0000,},
+	{0xE0A8, 0x0000,},
+	{0xE0AA, 0x0000,},
+	{0xE0AC, 0xFFFF,},
+	{0xE0AE, 0xCB68,},
+	{0xE0B0, 0xFFFF,},
+	{0xE0B2, 0xDFF0,},
+	{0xE0B4, 0xFFFF,},
+	{0xE0B6, 0xCB6C,},
+	{0xE0B8, 0xFFFF,},
+	{0xE0BA, 0xE000,},
+	{0x098E, 0x0000,},
+
+	/*MIPI setting for SOC1040*/
+	{0x3C5A, 0x0009,},
+	{0x3C44, 0x0080,},/*MIPI_CUSTOM_SHORT_PKT*/
+
+	/*[Tuning_settings]*/
+
+	/*[CCM]*/
+	{0xC892, 0x0267,},/*CAM_AWB_CCM_L_0*/
+	{0xC894, 0xFF1A,},/*CAM_AWB_CCM_L_1*/
+	{0xC896, 0xFFB3,},/*CAM_AWB_CCM_L_2*/
+	{0xC898, 0xFF80,},/*CAM_AWB_CCM_L_3*/
+	{0xC89A, 0x0166,},/*CAM_AWB_CCM_L_4*/
+	{0xC89C, 0x0003,},/*CAM_AWB_CCM_L_5*/
+	{0xC89E, 0xFF9A,},/*CAM_AWB_CCM_L_6*/
+	{0xC8A0, 0xFEB4,},/*CAM_AWB_CCM_L_7*/
+	{0xC8A2, 0x024D,},/*CAM_AWB_CCM_L_8*/
+	{0xC8A4, 0x01BF,},/*CAM_AWB_CCM_M_0*/
+	{0xC8A6, 0xFF01,},/*CAM_AWB_CCM_M_1*/
+	{0xC8A8, 0xFFF3,},/*CAM_AWB_CCM_M_2*/
+	{0xC8AA, 0xFF75,},/*CAM_AWB_CCM_M_3*/
+	{0xC8AC, 0x0198,},/*CAM_AWB_CCM_M_4*/
+	{0xC8AE, 0xFFFD,},/*CAM_AWB_CCM_M_5*/
+	{0xC8B0, 0xFF9A,},/*CAM_AWB_CCM_M_6*/
+	{0xC8B2, 0xFEE7,},/*CAM_AWB_CCM_M_7*/
+	{0xC8B4, 0x02A8,},/*CAM_AWB_CCM_M_8*/
+	{0xC8B6, 0x01D9,},/*CAM_AWB_CCM_R_0*/
+	{0xC8B8, 0xFF26,},/*CAM_AWB_CCM_R_1*/
+	{0xC8BA, 0xFFF3,},/*CAM_AWB_CCM_R_2*/
+	{0xC8BC, 0xFFB3,},/*CAM_AWB_CCM_R_3*/
+	{0xC8BE, 0x0132,},/*CAM_AWB_CCM_R_4*/
+	{0xC8C0, 0xFFE8,},/*CAM_AWB_CCM_R_5*/
+	{0xC8C2, 0xFFDA,},/*CAM_AWB_CCM_R_6*/
+	{0xC8C4, 0xFECD,},/*CAM_AWB_CCM_R_7*/
+	{0xC8C6, 0x02C2,},/*CAM_AWB_CCM_R_8*/
+	{0xC8C8, 0x0075,},/*CAM_AWB_CCM_L_RG_GAIN*/
+	{0xC8CA, 0x011C,},/*CAM_AWB_CCM_L_BG_GAIN*/
+	{0xC8CC, 0x009A,},/*CAM_AWB_CCM_M_RG_GAIN*/
+	{0xC8CE, 0x0105,},/*CAM_AWB_CCM_M_BG_GAIN*/
+	{0xC8D0, 0x00A4,},/*CAM_AWB_CCM_R_RG_GAIN*/
+	{0xC8D2, 0x00AC,},/*CAM_AWB_CCM_R_BG_GAIN*/
+	{0xC8D4, 0x0A8C,},/*CAM_AWB_CCM_L_CTEMP*/
+	{0xC8D6, 0x0F0A,},/*CAM_AWB_CCM_M_CTEMP*/
+	{0xC8D8, 0x1964,},/*CAM_AWB_CCM_R_CTEMP*/
+
+	/*[AWB]*/
+	{0xC914, 0x0000,},/*CAM_STAT_AWB_CLIP_WINDOW_XSTART*/
+	{0xC916, 0x0000,},/*CAM_STAT_AWB_CLIP_WINDOW_YSTART*/
+	{0xC918, 0x04FF,},/*CAM_STAT_AWB_CLIP_WINDOW_XEND*/
+	{0xC91A, 0x02CF,},/*CAM_STAT_AWB_CLIP_WINDOW_YEND*/
+	{0xC904, 0x0033,},/*CAM_AWB_AWB_XSHIFT_PRE_ADJ*/
+	{0xC906, 0x0040,},/*CAM_AWB_AWB_YSHIFT_PRE_ADJ*/
+	{0xC8F2, 0x03, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_AWB_XSCALE*/
+	{0xC8F3, 0x02, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_AWB_YSCALE*/
+	{0xC906, 0x003C,},/*CAM_AWB_AWB_YSHIFT_PRE_ADJ*/
+	{0xC8F4, 0x0000,},/*CAM_AWB_AWB_WEIGHTS_0*/
+	{0xC8F6, 0x0000,},/*CAM_AWB_AWB_WEIGHTS_1*/
+	{0xC8F8, 0x0000,},/*CAM_AWB_AWB_WEIGHTS_2*/
+	{0xC8FA, 0xE724,},/*CAM_AWB_AWB_WEIGHTS_3*/
+	{0xC8FC, 0x1583,},/*CAM_AWB_AWB_WEIGHTS_4*/
+	{0xC8FE, 0x2045,},/*CAM_AWB_AWB_WEIGHTS_5*/
+	{0xC900, 0x03FF,},/*CAM_AWB_AWB_WEIGHTS_6*/
+	{0xC902, 0x007C,},/*CAM_AWB_AWB_WEIGHTS_7*/
+	{0xC90C, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_R_L*/
+	{0xC90D, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_G_L*/
+	{0xC90E, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_B_L*/
+	{0xC90F, 0x88, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_R_R*/
+	{0xC910, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_G_R*/
+	{0xC911, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AWB_K_B_R*/
+
+	/*[Step7-CPIPE_Preference]*/
+	{0xC926, 0x0020,},/*CAM_LL_START_BRIGHTNESS*/
+	{0xC928, 0x009A,},/*CAM_LL_STOP_BRIGHTNESS*/
+	{0xC946, 0x0070,},/*CAM_LL_START_GAIN_METRIC*/
+	{0xC948, 0x00F3,},/*CAM_LL_STOP_GAIN_METRIC*/
+	{0xC952, 0x0020,},/*CAM_LL_START_TARGET_LUMA_BM*/
+	{0xC954, 0x009A,},/*CAM_LL_STOP_TARGET_LUMA_BM*/
+	{0xC92A, 0x80, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_SATURATION*/
+	{0xC92B, 0x4B, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_END_SATURATION*/
+	{0xC92C, 0x00, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_DESATURATION*/
+	{0xC92D, 0xFF, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_END_DESATURATION*/
+	{0xC92E, 0x3C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_DEMOSAIC*/
+	{0xC92F, 0x02, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_AP_GAIN*/
+	{0xC930, 0x06, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_AP_THRESH*/
+	{0xC931, 0x64, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_DEMOSAIC*/
+	{0xC932, 0x01, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_AP_GAIN*/
+	{0xC933, 0x0C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_AP_THRESH*/
+	{0xC934, 0x3C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_NR_RED*/
+	{0xC935, 0x3C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_NR_GREEN*/
+	{0xC936, 0x3C, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_NR_BLUE*/
+	{0xC937, 0x0F, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_NR_THRESH*/
+	{0xC938, 0x64, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_NR_RED*/
+	{0xC939, 0x64, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_NR_GREEN*/
+	{0xC93A, 0x64, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_NR_BLUE*/
+	{0xC93B, 0x32, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_NR_THRESH*/
+	{0xC93C, 0x0020,},/*CAM_LL_START_CONTRAST_BM*/
+	{0xC93E, 0x009A,},/*CAM_LL_STOP_CONTRAST_BM*/
+	{0xC940, 0x00DC,},/*CAM_LL_GAMMA*/
+	/*CAM_LL_START_CONTRAST_GRADIENT*/
+	{0xC942, 0x38, MSM_CAMERA_I2C_BYTE_DATA},
+	/*CAM_LL_STOP_CONTRAST_GRADIENT*/
+	{0xC943, 0x30, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC944, 0x50, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_START_CONTRAST_LUMA*/
+	{0xC945, 0x19, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_STOP_CONTRAST_LUMA*/
+	{0xC94A, 0x0230,},/*CAM_LL_START_FADE_TO_BLACK_LUMA*/
+	{0xC94C, 0x0010,},/*CAM_LL_STOP_FADE_TO_BLACK_LUMA*/
+	{0xC94E, 0x01CD,},/*CAM_LL_CLUSTER_DC_TH_BM*/
+	{0xC950, 0x05, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_CLUSTER_DC_GATE*/
+	{0xC951, 0x40, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_LL_SUMMING_SENSITIVITY*/
+	/*CAM_AET_TARGET_AVERAGE_LUMA_DARK*/
+	{0xC87B, 0x1B, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC878, 0x0E, MSM_CAMERA_I2C_BYTE_DATA},/*CAM_AET_AEMODE*/
+	{0xC890, 0x0080,},/*CAM_AET_TARGET_GAIN*/
+	{0xC886, 0x0100,},/*CAM_AET_AE_MAX_VIRT_AGAIN*/
+	{0xC87C, 0x005A,},/*CAM_AET_BLACK_CLIPPING_TARGET*/
+	{0xB42A, 0x05, MSM_CAMERA_I2C_BYTE_DATA},/*CCM_DELTA_GAIN*/
+	/*AE_TRACK_AE_TRACKING_DAMPENING*/
+	{0xA80A, 0x20, MSM_CAMERA_I2C_BYTE_DATA},
+	{0x3C44, 0x0080,},
+	{0x3C40, 0x0004, MSM_CAMERA_I2C_UNSET_WORD_MASK},
+	{0xA802, 0x08, MSM_CAMERA_I2C_SET_BYTE_MASK},
+	{0xC908, 0x01, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC879, 0x01, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC909, 0x01, MSM_CAMERA_I2C_UNSET_BYTE_MASK},
+	{0xA80A, 0x18, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xA80B, 0x18, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xAC16, 0x18, MSM_CAMERA_I2C_BYTE_DATA},
+	{0xC878, 0x08, MSM_CAMERA_I2C_SET_BYTE_MASK},
+	{0xBC02, 0x08, MSM_CAMERA_I2C_UNSET_BYTE_MASK},
+};
+
+static struct v4l2_subdev_info mt9m114_subdev_info[] = {
+	{
+		.code   = V4L2_MBUS_FMT_YUYV8_2X8,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.fmt    = 1,
+		.order    = 0,
+	},
+};
+
+static struct msm_camera_i2c_reg_conf mt9m114_config_change_settings[] = {
+	{0xdc00, 0x28, MSM_CAMERA_I2C_BYTE_DATA, MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_SET_STATE,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{MT9M114_COMMAND_REGISTER, (MT9M114_COMMAND_REGISTER_OK |
+		MT9M114_COMMAND_REGISTER_SET_STATE), MSM_CAMERA_I2C_WORD_DATA,
+		MSM_CAMERA_I2C_CMD_WRITE},
+	{MT9M114_COMMAND_REGISTER, MT9M114_COMMAND_REGISTER_SET_STATE,
+		MSM_CAMERA_I2C_UNSET_WORD_MASK, MSM_CAMERA_I2C_CMD_POLL},
+	{0xDC01, 0x31, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static const struct i2c_device_id mt9m114_i2c_id[] = {
+	{MT9M114_SENSOR_NAME, (kernel_ulong_t)&mt9m114_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver mt9m114_i2c_driver = {
+	.id_table = mt9m114_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = MT9M114_SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client mt9m114_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id mt9m114_dt_match[] = {
+	{.compatible = "qcom,mt9m114", .data = &mt9m114_s_ctrl},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, mt9m114_dt_match);
+
+static struct platform_driver mt9m114_platform_driver = {
+	.driver = {
+		.name = "qcom,mt9m114",
+		.owner = THIS_MODULE,
+		.of_match_table = mt9m114_dt_match,
+	},
+};
+
+static int32_t mt9m114_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc;
+	const struct of_device_id *match;
+	match = of_match_device(mt9m114_dt_match, &pdev->dev);
+	rc = msm_sensor_platform_probe(pdev, match->data);
+	return rc;
+}
+
+static int __init mt9m114_init_module(void)
+{
+	int32_t rc;
+	pr_info("%s:%d\n", __func__, __LINE__);
+	rc = platform_driver_probe(&mt9m114_platform_driver,
+		mt9m114_platform_probe);
+	if (!rc)
+		return rc;
+	pr_err("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&mt9m114_i2c_driver);
+}
+
+static void __exit mt9m114_exit_module(void)
+{
+	pr_info("%s:%d\n", __func__, __LINE__);
+	if (mt9m114_s_ctrl.pdev) {
+		msm_sensor_free_sensor_data(&mt9m114_s_ctrl);
+		platform_driver_unregister(&mt9m114_platform_driver);
+	} else
+		i2c_del_driver(&mt9m114_i2c_driver);
+	return;
+}
+
+int32_t mt9m114_sensor_config(struct msm_sensor_ctrl_t *s_ctrl,
+	void __user *argp)
+{
+	struct sensorb_cfg_data *cdata = (struct sensorb_cfg_data *)argp;
+	long rc = 0;
+	int32_t i = 0;
+	mutex_lock(s_ctrl->msm_sensor_mutex);
+	CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__,
+		s_ctrl->sensordata->sensor_name, cdata->cfgtype);
+	switch (cdata->cfgtype) {
+	case CFG_GET_SENSOR_INFO:
+		memcpy(cdata->cfg.sensor_info.sensor_name,
+			s_ctrl->sensordata->sensor_name,
+			sizeof(cdata->cfg.sensor_info.sensor_name));
+		cdata->cfg.sensor_info.session_id =
+			s_ctrl->sensordata->sensor_info->session_id;
+		for (i = 0; i < SUB_MODULE_MAX; i++)
+			cdata->cfg.sensor_info.subdev_id[i] =
+				s_ctrl->sensordata->sensor_info->subdev_id[i];
+		CDBG("%s:%d sensor name %s\n", __func__, __LINE__,
+			cdata->cfg.sensor_info.sensor_name);
+		CDBG("%s:%d session id %d\n", __func__, __LINE__,
+			cdata->cfg.sensor_info.session_id);
+		for (i = 0; i < SUB_MODULE_MAX; i++)
+			CDBG("%s:%d subdev_id[%d] %d\n", __func__, __LINE__, i,
+				cdata->cfg.sensor_info.subdev_id[i]);
+
+		break;
+	case CFG_SET_INIT_SETTING:
+		/* 1. Write Recommend settings */
+		/* 2. Write change settings */
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->
+			i2c_write_conf_tbl(
+			s_ctrl->sensor_i2c_client, mt9m114_recommend_settings,
+			ARRAY_SIZE(mt9m114_recommend_settings),
+			MSM_CAMERA_I2C_WORD_DATA);
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->
+			i2c_write_conf_tbl(
+			s_ctrl->sensor_i2c_client,
+			mt9m114_config_change_settings,
+			ARRAY_SIZE(mt9m114_config_change_settings),
+			MSM_CAMERA_I2C_WORD_DATA);
+		break;
+	case CFG_SET_RESOLUTION:
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->
+			i2c_write_conf_tbl(
+			s_ctrl->sensor_i2c_client, mt9m114_720p_settings,
+			ARRAY_SIZE(mt9m114_720p_settings),
+			MSM_CAMERA_I2C_WORD_DATA);
+		break;
+	case CFG_SET_STOP_STREAM:
+		break;
+	case CFG_SET_START_STREAM:
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->
+			i2c_write_conf_tbl(
+			s_ctrl->sensor_i2c_client,
+			mt9m114_config_change_settings,
+			ARRAY_SIZE(mt9m114_config_change_settings),
+			MSM_CAMERA_I2C_WORD_DATA);
+		break;
+	case CFG_GET_SENSOR_INIT_PARAMS:
+		cdata->cfg.sensor_init_params =
+			*s_ctrl->sensordata->sensor_init_params;
+		CDBG("%s:%d init params mode %d pos %d mount %d\n", __func__,
+			__LINE__,
+			cdata->cfg.sensor_init_params.modes_supported,
+			cdata->cfg.sensor_init_params.position,
+			cdata->cfg.sensor_init_params.sensor_mount_angle);
+		break;
+	case CFG_SET_SLAVE_INFO: {
+		struct msm_camera_sensor_slave_info sensor_slave_info;
+		struct msm_sensor_power_setting_array *power_setting_array;
+		int slave_index = 0;
+		if (copy_from_user(&sensor_slave_info,
+		    (void *)cdata->cfg.setting,
+		    sizeof(struct msm_camera_sensor_slave_info))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		/* Update sensor slave address */
+		if (sensor_slave_info.slave_addr) {
+			s_ctrl->sensor_i2c_client->cci_client->sid =
+				sensor_slave_info.slave_addr >> 1;
+		}
+
+		/* Update sensor address type */
+		s_ctrl->sensor_i2c_client->addr_type =
+			sensor_slave_info.addr_type;
+
+		/* Update power up / down sequence */
+		s_ctrl->power_setting_array =
+			sensor_slave_info.power_setting_array;
+		power_setting_array = &s_ctrl->power_setting_array;
+		power_setting_array->power_setting = kzalloc(
+			power_setting_array->size *
+			sizeof(struct msm_sensor_power_setting), GFP_KERNEL);
+		if (!power_setting_array->power_setting) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(power_setting_array->power_setting,
+		    (void *)sensor_slave_info.power_setting_array.power_setting,
+		    power_setting_array->size *
+		    sizeof(struct msm_sensor_power_setting))) {
+			kfree(power_setting_array->power_setting);
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		s_ctrl->free_power_setting = true;
+		CDBG("%s sensor id %x\n", __func__,
+			sensor_slave_info.slave_addr);
+		CDBG("%s sensor addr type %d\n", __func__,
+			sensor_slave_info.addr_type);
+		CDBG("%s sensor reg %x\n", __func__,
+			sensor_slave_info.sensor_id_info.sensor_id_reg_addr);
+		CDBG("%s sensor id %x\n", __func__,
+			sensor_slave_info.sensor_id_info.sensor_id);
+		for (slave_index = 0; slave_index <
+			power_setting_array->size; slave_index++) {
+			CDBG("%s i %d power setting %d %d %ld %d\n", __func__,
+				slave_index,
+				power_setting_array->power_setting[slave_index].
+				seq_type,
+				power_setting_array->power_setting[slave_index].
+				seq_val,
+				power_setting_array->power_setting[slave_index].
+				config_val,
+				power_setting_array->power_setting[slave_index].
+				delay);
+		}
+		kfree(power_setting_array->power_setting);
+		break;
+	}
+	case CFG_WRITE_I2C_ARRAY: {
+		struct msm_camera_i2c_reg_setting conf_array;
+		struct msm_camera_i2c_reg_array *reg_setting = NULL;
+
+		if (copy_from_user(&conf_array,
+			(void *)cdata->cfg.setting,
+			sizeof(struct msm_camera_i2c_reg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		reg_setting = kzalloc(conf_array.size *
+			(sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL);
+		if (!reg_setting) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(reg_setting, (void *)conf_array.reg_setting,
+			conf_array.size *
+			sizeof(struct msm_camera_i2c_reg_array))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(reg_setting);
+			rc = -EFAULT;
+			break;
+		}
+
+		conf_array.reg_setting = reg_setting;
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table(
+			s_ctrl->sensor_i2c_client, &conf_array);
+		kfree(reg_setting);
+		break;
+	}
+	case CFG_WRITE_I2C_SEQ_ARRAY: {
+		struct msm_camera_i2c_seq_reg_setting conf_array;
+		struct msm_camera_i2c_seq_reg_array *reg_setting = NULL;
+
+		if (copy_from_user(&conf_array,
+			(void *)cdata->cfg.setting,
+			sizeof(struct msm_camera_i2c_seq_reg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		reg_setting = kzalloc(conf_array.size *
+			(sizeof(struct msm_camera_i2c_seq_reg_array)),
+			GFP_KERNEL);
+		if (!reg_setting) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(reg_setting, (void *)conf_array.reg_setting,
+			conf_array.size *
+			sizeof(struct msm_camera_i2c_seq_reg_array))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(reg_setting);
+			rc = -EFAULT;
+			break;
+		}
+
+		conf_array.reg_setting = reg_setting;
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->
+			i2c_write_seq_table(s_ctrl->sensor_i2c_client,
+			&conf_array);
+		kfree(reg_setting);
+		break;
+	}
+
+	case CFG_POWER_UP:
+		if (s_ctrl->func_tbl->sensor_power_up)
+			rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+		else
+			rc = -EFAULT;
+		break;
+
+	case CFG_POWER_DOWN:
+		if (s_ctrl->func_tbl->sensor_power_down)
+			rc = s_ctrl->func_tbl->sensor_power_down(
+				s_ctrl);
+		else
+			rc = -EFAULT;
+		break;
+
+	case CFG_SET_STOP_STREAM_SETTING: {
+		struct msm_camera_i2c_reg_setting *stop_setting =
+			&s_ctrl->stop_setting;
+		struct msm_camera_i2c_reg_array *reg_setting = NULL;
+		if (copy_from_user(stop_setting, (void *)cdata->cfg.setting,
+		    sizeof(struct msm_camera_i2c_reg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		reg_setting = stop_setting->reg_setting;
+		stop_setting->reg_setting = kzalloc(stop_setting->size *
+			(sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL);
+		if (!stop_setting->reg_setting) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(stop_setting->reg_setting,
+		    (void *)reg_setting, stop_setting->size *
+		    sizeof(struct msm_camera_i2c_reg_array))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(stop_setting->reg_setting);
+			stop_setting->reg_setting = NULL;
+			stop_setting->size = 0;
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	default:
+		rc = -EFAULT;
+		break;
+	}
+
+	mutex_unlock(s_ctrl->msm_sensor_mutex);
+
+	return rc;
+}
+
+static struct msm_sensor_fn_t mt9m114_sensor_func_tbl = {
+	.sensor_config = mt9m114_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+	.sensor_match_id = msm_sensor_match_id,
+};
+
+static struct msm_sensor_ctrl_t mt9m114_s_ctrl = {
+	.sensor_i2c_client = &mt9m114_sensor_i2c_client,
+	.power_setting_array.power_setting = mt9m114_power_setting,
+	.power_setting_array.size = ARRAY_SIZE(mt9m114_power_setting),
+	.msm_sensor_mutex = &mt9m114_mut,
+	.sensor_v4l2_subdev_info = mt9m114_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(mt9m114_subdev_info),
+	.func_tbl = &mt9m114_sensor_func_tbl,
+};
+
+module_init(mt9m114_init_module);
+module_exit(mt9m114_exit_module);
+MODULE_DESCRIPTION("Aptina 1.26MP YUV sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov2720.c b/drivers/media/platform/msm/camera_v2/sensor/ov2720.c
new file mode 100644
index 0000000..d790c65
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov2720.c
@@ -0,0 +1,149 @@
+/* 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.
+ *
+ */
+#include "msm_sensor.h"
+#define OV2720_SENSOR_NAME "ov2720"
+DEFINE_MSM_MUTEX(ov2720_mut);
+
+static struct msm_sensor_ctrl_t ov2720_s_ctrl;
+
+static struct msm_sensor_power_setting ov2720_power_setting[] = {
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VIO,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VANA,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VDIG,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 1,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 30,
+	},
+	{
+		.seq_type = SENSOR_CLK,
+		.seq_val = SENSOR_CAM_MCLK,
+		.config_val = 0,
+		.delay = 1,
+	},
+	{
+		.seq_type = SENSOR_I2C_MUX,
+		.seq_val = 0,
+		.config_val = 0,
+		.delay = 0,
+	},
+};
+
+static struct v4l2_subdev_info ov2720_subdev_info[] = {
+	{
+		.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.fmt    = 1,
+		.order    = 0,
+	},
+};
+
+static const struct i2c_device_id ov2720_i2c_id[] = {
+	{OV2720_SENSOR_NAME, (kernel_ulong_t)&ov2720_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver ov2720_i2c_driver = {
+	.id_table = ov2720_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = OV2720_SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client ov2720_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id ov2720_dt_match[] = {
+	{.compatible = "qcom,ov2720", .data = &ov2720_s_ctrl},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, ov2720_dt_match);
+
+static struct platform_driver ov2720_platform_driver = {
+	.driver = {
+		.name = "qcom,ov2720",
+		.owner = THIS_MODULE,
+		.of_match_table = ov2720_dt_match,
+	},
+};
+
+static int32_t ov2720_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	const struct of_device_id *match;
+	match = of_match_device(ov2720_dt_match, &pdev->dev);
+	rc = msm_sensor_platform_probe(pdev, match->data);
+	return rc;
+}
+
+static int __init ov2720_init_module(void)
+{
+	int32_t rc = 0;
+	pr_info("%s:%d\n", __func__, __LINE__);
+	rc = platform_driver_probe(&ov2720_platform_driver,
+		ov2720_platform_probe);
+	if (!rc)
+		return rc;
+	pr_err("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&ov2720_i2c_driver);
+}
+
+static void __exit ov2720_exit_module(void)
+{
+	pr_info("%s:%d\n", __func__, __LINE__);
+	if (ov2720_s_ctrl.pdev) {
+		msm_sensor_free_sensor_data(&ov2720_s_ctrl);
+		platform_driver_unregister(&ov2720_platform_driver);
+	} else
+		i2c_del_driver(&ov2720_i2c_driver);
+	return;
+}
+
+static struct msm_sensor_ctrl_t ov2720_s_ctrl = {
+	.sensor_i2c_client = &ov2720_sensor_i2c_client,
+	.power_setting_array.power_setting = ov2720_power_setting,
+	.power_setting_array.size = ARRAY_SIZE(ov2720_power_setting),
+	.msm_sensor_mutex = &ov2720_mut,
+	.sensor_v4l2_subdev_info = ov2720_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov2720_subdev_info),
+};
+
+module_init(ov2720_init_module);
+module_exit(ov2720_exit_module);
+MODULE_DESCRIPTION("ov2720");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msmb/sensor/s5k3l1yx.c b/drivers/media/platform/msm/camera_v2/sensor/s5k3l1yx.c
similarity index 100%
rename from drivers/media/video/msmb/sensor/s5k3l1yx.c
rename to drivers/media/platform/msm/camera_v2/sensor/s5k3l1yx.c
diff --git a/drivers/media/dvb/mpq/Kconfig b/drivers/media/platform/msm/dvb/Kconfig
similarity index 67%
rename from drivers/media/dvb/mpq/Kconfig
rename to drivers/media/platform/msm/dvb/Kconfig
index 766312c..e3eb391 100644
--- a/drivers/media/dvb/mpq/Kconfig
+++ b/drivers/media/platform/msm/dvb/Kconfig
@@ -7,6 +7,5 @@
 	  Support for Qualcomm MPQ based DVB adapter.
 	  Say Y or M if you own such a device and want to use it.
 
-source "drivers/media/dvb/mpq/demux/Kconfig"
-source "drivers/media/dvb/mpq/video/Kconfig"
-
+source "drivers/media/platform/msm/dvb/demux/Kconfig"
+source "drivers/media/platform/msm/dvb/video/Kconfig"
diff --git a/drivers/media/dvb/mpq/Makefile b/drivers/media/platform/msm/dvb/Makefile
similarity index 100%
rename from drivers/media/dvb/mpq/Makefile
rename to drivers/media/platform/msm/dvb/Makefile
diff --git a/drivers/media/dvb/mpq/adapter/Makefile b/drivers/media/platform/msm/dvb/adapter/Makefile
similarity index 70%
rename from drivers/media/dvb/mpq/adapter/Makefile
rename to drivers/media/platform/msm/dvb/adapter/Makefile
index ed664da..dcf7cdb 100644
--- a/drivers/media/dvb/mpq/adapter/Makefile
+++ b/drivers/media/platform/msm/dvb/adapter/Makefile
@@ -1,6 +1,6 @@
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/dvb/mpq/include/
+EXTRA_CFLAGS += -Idrivers/media/platform/msm/dvb/include/
 
 obj-$(CONFIG_DVB_MPQ) += mpq-adapter.o
 
diff --git a/drivers/media/dvb/mpq/adapter/mpq_adapter.c b/drivers/media/platform/msm/dvb/adapter/mpq_adapter.c
similarity index 100%
rename from drivers/media/dvb/mpq/adapter/mpq_adapter.c
rename to drivers/media/platform/msm/dvb/adapter/mpq_adapter.c
diff --git a/drivers/media/dvb/mpq/adapter/mpq_stream_buffer.c b/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c
similarity index 100%
rename from drivers/media/dvb/mpq/adapter/mpq_stream_buffer.c
rename to drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c
diff --git a/drivers/media/dvb/mpq/demux/Kconfig b/drivers/media/platform/msm/dvb/demux/Kconfig
similarity index 100%
rename from drivers/media/dvb/mpq/demux/Kconfig
rename to drivers/media/platform/msm/dvb/demux/Kconfig
diff --git a/drivers/media/dvb/mpq/demux/Makefile b/drivers/media/platform/msm/dvb/demux/Makefile
similarity index 88%
rename from drivers/media/dvb/mpq/demux/Makefile
rename to drivers/media/platform/msm/dvb/demux/Makefile
index 9f4a03e..e164a21 100644
--- a/drivers/media/dvb/mpq/demux/Makefile
+++ b/drivers/media/platform/msm/dvb/demux/Makefile
@@ -1,6 +1,6 @@
 
 ccflags-y += -Idrivers/media/dvb/dvb-core/
-ccflags-y += -Idrivers/media/dvb/mpq/include/
+ccflags-y += -Idrivers/media/platform/msm/dvb/include/
 ccflags-y += -Idrivers/misc/
 
 obj-$(CONFIG_DVB_MPQ_DEMUX) += mpq-dmx-hw-plugin.o
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
similarity index 98%
rename from drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
rename to drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index c7c617f..2c9a0b8 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -25,6 +25,8 @@
 
 #define MAX_PES_LENGTH	(SZ_64K)
 
+#define MAX_TS_PACKETS_FOR_SDMX_PROCESS	(500)
+
 /*
  * PES header length field is 8 bits so PES header length after this field
  * can be up to 256 bytes.
@@ -87,6 +89,11 @@
 static int mpq_bypass_sdmx = 1;
 module_param(mpq_bypass_sdmx, int, S_IRUGO | S_IWUSR);
 
+/* Max number of TS packets allowed as input for a single sdmx process */
+static int mpq_sdmx_proc_limit = MAX_TS_PACKETS_FOR_SDMX_PROCESS;
+module_param(mpq_sdmx_proc_limit, int, S_IRUGO | S_IWUSR);
+
+
 /**
  * Maximum allowed framing pattern size
  */
@@ -4339,7 +4346,7 @@
 	}
 }
 
-int mpq_sdmx_process(struct mpq_demux *mpq_demux,
+static int mpq_sdmx_process_buffer(struct mpq_demux *mpq_demux,
 	struct sdmx_buff_descr *input,
 	u32 fill_count,
 	u32 read_offset)
@@ -4435,6 +4442,41 @@
 
 	return bytes_read;
 }
+
+int mpq_sdmx_process(struct mpq_demux *mpq_demux,
+	struct sdmx_buff_descr *input,
+	u32 fill_count,
+	u32 read_offset)
+{
+	int ret;
+	int todo;
+	int total_bytes_read = 0;
+	int limit = mpq_sdmx_proc_limit * mpq_demux->demux.ts_packet_size;
+
+	do {
+		todo = fill_count > limit ? limit : fill_count;
+		ret = mpq_sdmx_process_buffer(mpq_demux, input, todo,
+			read_offset);
+		if (ret > 0) {
+			total_bytes_read += ret;
+			fill_count -= ret;
+			read_offset += ret;
+			if (read_offset >= input->size)
+				read_offset -= input->size;
+		} else if (ret == 0) {
+			/* Not enough data to read (less than 1 TS packet) */
+			break;
+		} else {
+			/* Some error occurred */
+			MPQ_DVB_ERR_PRINT(
+				"%s: mpq_sdmx_process_buffer failed, returned %d\n",
+				__func__, ret);
+			break;
+		}
+	} while (fill_count > 0);
+
+	return total_bytes_read;
+}
 EXPORT_SYMBOL(mpq_sdmx_process);
 
 static int mpq_sdmx_write(struct mpq_demux *mpq_demux,
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
similarity index 100%
rename from drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
rename to drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
similarity index 100%
rename from drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
rename to drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
similarity index 100%
rename from drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
rename to drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
similarity index 100%
rename from drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v2.c
rename to drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
diff --git a/drivers/media/dvb/mpq/demux/mpq_sdmx.c b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c
similarity index 100%
rename from drivers/media/dvb/mpq/demux/mpq_sdmx.c
rename to drivers/media/platform/msm/dvb/demux/mpq_sdmx.c
diff --git a/drivers/media/dvb/mpq/demux/mpq_sdmx.h b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
similarity index 100%
rename from drivers/media/dvb/mpq/demux/mpq_sdmx.h
rename to drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
diff --git a/drivers/media/dvb/mpq/include/mpq_adapter.h b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
similarity index 100%
rename from drivers/media/dvb/mpq/include/mpq_adapter.h
rename to drivers/media/platform/msm/dvb/include/mpq_adapter.h
diff --git a/drivers/media/dvb/mpq/include/mpq_dvb_debug.h b/drivers/media/platform/msm/dvb/include/mpq_dvb_debug.h
similarity index 100%
rename from drivers/media/dvb/mpq/include/mpq_dvb_debug.h
rename to drivers/media/platform/msm/dvb/include/mpq_dvb_debug.h
diff --git a/drivers/media/dvb/mpq/include/mpq_stream_buffer.h b/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h
similarity index 100%
rename from drivers/media/dvb/mpq/include/mpq_stream_buffer.h
rename to drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h
diff --git a/drivers/media/dvb/mpq/video/Kconfig b/drivers/media/platform/msm/dvb/video/Kconfig
similarity index 100%
rename from drivers/media/dvb/mpq/video/Kconfig
rename to drivers/media/platform/msm/dvb/video/Kconfig
diff --git a/drivers/media/dvb/mpq/video/Makefile b/drivers/media/platform/msm/dvb/video/Makefile
similarity index 62%
rename from drivers/media/dvb/mpq/video/Makefile
rename to drivers/media/platform/msm/dvb/video/Makefile
index 38c1091..7a5ecf4 100644
--- a/drivers/media/dvb/mpq/video/Makefile
+++ b/drivers/media/platform/msm/dvb/video/Makefile
@@ -1,5 +1,5 @@
 
 ccflags-y += -Idrivers/media/dvb/dvb-core/
-ccflags-y += -Idrivers/media/dvb/mpq/include/
+ccflags-y += -Idrivers/media/platform/msm/dvb/include/
 
 obj-$(CONFIG_DVB_MPQ_VIDEO) += mpq_dvb_video.o
diff --git a/drivers/media/dvb/mpq/video/mpq_dvb_video.c b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
similarity index 100%
rename from drivers/media/dvb/mpq/video/mpq_dvb_video.c
rename to drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
diff --git a/drivers/media/dvb/mpq/video/mpq_dvb_video_internal.h b/drivers/media/platform/msm/dvb/video/mpq_dvb_video_internal.h
similarity index 100%
rename from drivers/media/dvb/mpq/video/mpq_dvb_video_internal.h
rename to drivers/media/platform/msm/dvb/video/mpq_dvb_video_internal.h
diff --git a/drivers/media/platform/msm/vcap/Kconfig b/drivers/media/platform/msm/vcap/Kconfig
new file mode 100644
index 0000000..2bdcfbd
--- /dev/null
+++ b/drivers/media/platform/msm/vcap/Kconfig
@@ -0,0 +1,7 @@
+config MSM_VCAP
+	tristate "Qualcomm MSM VCAP"
+	depends on VIDEO_DEV && VIDEO_V4L2
+	default y
+	---help---
+		Enables VCAP driver. This device allows for video capture and
+		video processing using the v4l2 api
diff --git a/drivers/media/platform/msm/vcap/Makefile b/drivers/media/platform/msm/vcap/Makefile
new file mode 100644
index 0000000..b9c6e4c
--- /dev/null
+++ b/drivers/media/platform/msm/vcap/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MSM_VCAP) += vcap_v4l2.o
+obj-$(CONFIG_MSM_VCAP) += vcap_vc.o
+obj-$(CONFIG_MSM_VCAP) += vcap_vp.o
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/platform/msm/vcap/vcap_v4l2.c
similarity index 100%
rename from drivers/media/video/vcap_v4l2.c
rename to drivers/media/platform/msm/vcap/vcap_v4l2.c
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/platform/msm/vcap/vcap_vc.c
similarity index 100%
rename from drivers/media/video/vcap_vc.c
rename to drivers/media/platform/msm/vcap/vcap_vc.c
diff --git a/drivers/media/video/vcap_vc.h b/drivers/media/platform/msm/vcap/vcap_vc.h
similarity index 100%
rename from drivers/media/video/vcap_vc.h
rename to drivers/media/platform/msm/vcap/vcap_vc.h
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/platform/msm/vcap/vcap_vp.c
similarity index 100%
rename from drivers/media/video/vcap_vp.c
rename to drivers/media/platform/msm/vcap/vcap_vp.c
diff --git a/drivers/media/video/vcap_vp.h b/drivers/media/platform/msm/vcap/vcap_vp.h
similarity index 100%
rename from drivers/media/video/vcap_vp.h
rename to drivers/media/platform/msm/vcap/vcap_vp.h
diff --git a/drivers/media/platform/msm/vidc/Kconfig b/drivers/media/platform/msm/vidc/Kconfig
new file mode 100644
index 0000000..3fc2b9e
--- /dev/null
+++ b/drivers/media/platform/msm/vidc/Kconfig
@@ -0,0 +1,7 @@
+#
+# VIDEO CORE
+#
+
+menuconfig MSM_VIDC_V4L2
+	bool "Qualcomm MSM V4L2 based video driver"
+		depends on (ARCH_MSM8974 || ARCH_MSM8610) && VIDEO_V4L2
diff --git a/drivers/media/video/msm_vidc/Makefile b/drivers/media/platform/msm/vidc/Makefile
similarity index 94%
rename from drivers/media/video/msm_vidc/Makefile
rename to drivers/media/platform/msm/vidc/Makefile
index da829cc..6977165 100644
--- a/drivers/media/video/msm_vidc/Makefile
+++ b/drivers/media/platform/msm/vidc/Makefile
@@ -9,3 +9,4 @@
 				hfi_response_handler.o \
 				hfi_packetization.o \
 				vidc_hfi.o \
+				q6_hfi.o \
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
similarity index 98%
rename from drivers/media/video/msm_vidc/hfi_packetization.c
rename to drivers/media/platform/msm/vidc/hfi_packetization.c
index 06e230d..44e23ed 100644
--- a/drivers/media/video/msm_vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -215,8 +215,8 @@
 	case HAL_EXTRADATA_NUM_CONCEALED_MB:
 		ret = HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB;
 		break;
-	case HAL_EXTRADATA_INDEX:
-		ret = HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG;
+	case HAL_EXTRADATA_ASPECT_RATIO:
+		ret = HFI_PROPERTY_PARAM_INDEX_EXTRADATA;
 		break;
 	default:
 		dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
@@ -795,7 +795,7 @@
 		hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
 		hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
 		hfi->layer_id = ((struct hal_bitrate *)pdata)->layer_id;
-		pkt->size += sizeof(u32) * 2;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_bitrate);
 		break;
 	}
 	case HAL_PARAM_PROFILE_LEVEL_CURRENT:
@@ -1056,7 +1056,10 @@
 			(struct hfi_index_extradata_config *)
 			&pkt->rg_property_data[1];
 		hfi->enable = extra->enable;
-		index = get_hfi_extradata_index(extra->index);
+		if (extra->index == HAL_EXTRADATA_ASPECT_RATIO)
+			index = EXTRADATA_ASPECT_RATIO;
+		else
+			index = get_hfi_extradata_index(extra->index);
 		if (index)
 			hfi->index_extra_data_id = index;
 		else {
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.h b/drivers/media/platform/msm/vidc/hfi_packetization.h
similarity index 100%
rename from drivers/media/video/msm_vidc/hfi_packetization.h
rename to drivers/media/platform/msm/vidc/hfi_packetization.h
diff --git a/drivers/media/video/msm_vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
similarity index 99%
rename from drivers/media/video/msm_vidc/hfi_response_handler.c
rename to drivers/media/platform/msm/vidc/hfi_response_handler.c
index cedd789..f6a9949 100644
--- a/drivers/media/video/msm_vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -828,7 +828,7 @@
 		struct vidc_hal_msg_pkt_hdr *msg_hdr)
 {
 	if (!callback || !msg_hdr || msg_hdr->size <
-		HFI_MIN_PKT_SIZE) {
+		VIDC_IFACEQ_MIN_PKT_SIZE) {
 		dprintk(VIDC_ERR, "hal_process_msg_packet:bad"
 			"packet/packet size: %d", msg_hdr->size);
 		return;
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
similarity index 100%
rename from drivers/media/video/msm_vidc/msm_smem.c
rename to drivers/media/platform/msm/vidc/msm_smem.c
diff --git a/drivers/media/video/msm_vidc/msm_smem.h b/drivers/media/platform/msm/vidc/msm_smem.h
similarity index 100%
rename from drivers/media/video/msm_vidc/msm_smem.h
rename to drivers/media/platform/msm/vidc/msm_smem.h
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
similarity index 72%
rename from drivers/media/video/msm_vidc/msm_v4l2_vidc.c
rename to drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 4f39357..47eccfa 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -15,13 +15,13 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/ioctl.h>
-#include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/debugfs.h>
 #include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <mach/board.h>
 #include <mach/iommu.h>
 #include <mach/iommu_domains.h>
 #include <media/msm_vidc.h>
@@ -30,6 +30,7 @@
 #include "vidc_hfi_api.h"
 #include "msm_smem.h"
 #include "vidc_hfi_api.h"
+#include "msm_vidc_resources.h"
 
 #define BASE_DEVICE_NUMBER 32
 
@@ -406,11 +407,11 @@
 				&& (!EXTRADATA_IDX(b->length)
 					|| (i != EXTRADATA_IDX(b->length)))) {
 			smem_flags |= SMEM_SECURE;
-			domain = hdev->get_domain(hdev->hfi_device_data,
-						CP_MAP);
+			domain = call_hfi_op(hdev, get_domain,
+					hdev->hfi_device_data, CP_MAP);
 		} else
-			domain = hdev->get_domain(hdev->hfi_device_data,
-						NS_MAP);
+			domain = call_hfi_op(hdev, get_domain,
+					hdev->hfi_device_data, NS_MAP);
 
 		if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 			smem_flags |= SMEM_INPUT;
@@ -671,30 +672,335 @@
 {
 }
 
-static int msm_vidc_get_hfi(struct platform_device *pdev,
-			struct msm_vidc_core *core)
+static size_t get_u32_array_num_elements(struct platform_device *pdev,
+					char *name)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int len;
+	size_t num_elements = 0;
+	if (!of_get_property(np, name, &len)) {
+		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
+			name);
+		goto fail_read;
+	}
+
+	num_elements = len / sizeof(u32);
+	if (num_elements <= 0) {
+		dprintk(VIDC_ERR, "%s not specified in device tree\n",
+			name);
+		goto fail_read;
+	}
+	return num_elements / 2;
+
+fail_read:
+	return 0;
+}
+
+static int read_hfi_type(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	int rc = 0;
 	const char *hfi_name = NULL;
 
-	rc = of_property_read_string(np, "hfi", &hfi_name);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to read hfi from device tree\n");
-		goto err_hfi_read;
-	}
-
-	if (!strcmp(hfi_name, "venus"))
-		core->hfi_type = VIDC_HFI_VENUS;
-	else if (!strcmp(hfi_name, "q6"))
-		core->hfi_type = VIDC_HFI_Q6;
-
-	dprintk(VIDC_INFO, "hfi_type = %d\n", core->hfi_type);
+	if (np) {
+		rc = of_property_read_string(np, "qcom,hfi", &hfi_name);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Failed to read hfi from device tree\n");
+			goto err_hfi_read;
+		}
+		if (!strcmp(hfi_name, "venus"))
+			rc = VIDC_HFI_VENUS;
+		else if (!strcmp(hfi_name, "q6"))
+			rc = VIDC_HFI_Q6;
+		else
+			rc = -EINVAL;
+	} else
+		rc = VIDC_HFI_Q6;
 
 err_hfi_read:
 	return rc;
 }
 
+static inline void msm_vidc_free_freq_table(
+		struct msm_vidc_platform_resources *res)
+{
+	kfree(res->load_freq_tbl);
+	res->load_freq_tbl = NULL;
+}
+
+static inline void msm_vidc_free_iommu_maps(
+		struct msm_vidc_platform_resources *res)
+{
+	kfree(res->iommu_maps);
+	res->iommu_maps = NULL;
+}
+
+static inline void msm_vidc_free_reg_table(
+			struct msm_vidc_platform_resources *res)
+{
+	kfree(res->reg_set.reg_tbl);
+	res->reg_set.reg_tbl = NULL;
+}
+
+static int msm_vidc_load_freq_table(struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+	int num_elements = 0;
+	struct platform_device *pdev = res->pdev;
+
+	num_elements = get_u32_array_num_elements(pdev, "qcom,load-freq-tbl");
+	if (num_elements == 0) {
+		dprintk(VIDC_ERR, "no elements in frequency table\n");
+		return rc;
+	}
+
+	res->load_freq_tbl = kzalloc(num_elements * sizeof(*res->load_freq_tbl),
+			GFP_KERNEL);
+	if (!res->load_freq_tbl) {
+		dprintk(VIDC_ERR,
+				"%s Failed to alloc load_freq_tbl\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32_array(pdev->dev.of_node,
+		"qcom,load-freq-tbl", (u32 *)res->load_freq_tbl,
+		num_elements * 2)) {
+		dprintk(VIDC_ERR, "Failed to read frequency table\n");
+		msm_vidc_free_freq_table(res);
+		return -EINVAL;
+	}
+
+	res->load_freq_tbl_size = num_elements;
+	return rc;
+}
+
+static int msm_vidc_load_iommu_maps(struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+	int num_elements = 0;
+	int i;
+	struct platform_device *pdev = res->pdev;
+	char *names[MAX_MAP] = {
+		[CP_MAP] = "qcom,vidc-cp-map",
+		[NS_MAP] = "qcom,vidc-ns-map",
+	};
+	char *contexts[MAX_MAP] = {
+		[CP_MAP] = "venus_cp",
+		[NS_MAP] = "venus_ns",
+	};
+
+
+	res->iommu_maps = kzalloc(MAX_MAP * sizeof(*res->iommu_maps),
+			GFP_KERNEL);
+	if (!res->iommu_maps) {
+		dprintk(VIDC_ERR, "%s Failed to alloc iommu_maps\n", __func__);
+		return -ENOMEM;
+	}
+
+	res->iommu_maps_size = MAX_MAP;
+	for (i = 0; i < MAX_MAP; i++) {
+		num_elements = get_u32_array_num_elements(pdev, names[i]);
+		if (num_elements == 0) {
+			dprintk(VIDC_ERR,
+				"no elements in iommu map :%s\n", names[i]);
+			goto error;
+		}
+		memcpy(&res->iommu_maps[i].name, names[i],
+				strlen(names[i]));
+		memcpy(&res->iommu_maps[i].ctx, contexts[i],
+				strlen(contexts[i]));
+
+		if (of_property_read_u32_array(pdev->dev.of_node, names[i],
+			res->iommu_maps[i].addr_range, num_elements * 2)) {
+			dprintk(VIDC_ERR, "Failed to read iommu map :%s\n",
+					names[i]);
+			rc = -EINVAL;
+			goto error;
+		}
+	}
+	return rc;
+error:
+	msm_vidc_free_iommu_maps(res);
+	return rc;
+}
+
+static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res)
+{
+	struct reg_set *reg_set;
+	struct platform_device *pdev = res->pdev;
+	int i;
+	int rc = 0;
+
+	reg_set = &res->reg_set;
+	reg_set->count = get_u32_array_num_elements(pdev, "qcom,reg-presets");
+	if (reg_set->count == 0) {
+		dprintk(VIDC_DBG, "no elements in reg set\n");
+		return rc;
+	}
+
+	reg_set->reg_tbl = kzalloc(reg_set->count *
+			sizeof(*(reg_set->reg_tbl)), GFP_KERNEL);
+	if (!reg_set->reg_tbl) {
+		dprintk(VIDC_ERR, "%s Failed to alloc temp\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,reg-presets",
+		(u32 *)reg_set->reg_tbl, reg_set->count * 2)) {
+		dprintk(VIDC_ERR, "Failed to read register table\n");
+		msm_vidc_free_reg_table(res);
+		return -EINVAL;
+	}
+	for (i = 0; i < reg_set->count; i++) {
+		dprintk(VIDC_DBG,
+			"reg = %x, value = %x\n",
+			reg_set->reg_tbl[i].reg,
+			reg_set->reg_tbl[i].value
+		);
+	}
+	return rc;
+}
+
+static int read_platform_resources_from_dt(
+		struct msm_vidc_platform_resources *res)
+{
+	struct platform_device *pdev = res->pdev;
+	struct resource *kres = NULL;
+	int rc = 0;
+
+	if (!pdev->dev.of_node) {
+		dprintk(VIDC_ERR, "DT node not found\n");
+		return -ENOENT;
+	}
+
+	res->fw_base_addr = 0x0;
+
+	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res->register_base = kres ? kres->start : -1;
+	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
+
+	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	res->irq = kres ? kres->start : -1;
+
+	rc = msm_vidc_load_freq_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load freq table: %d\n", rc);
+		goto err_load_freq_table;
+	}
+	rc = msm_vidc_load_iommu_maps(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load iommu maps: %d\n", rc);
+		goto err_load_iommu_maps;
+	}
+	rc = msm_vidc_load_reg_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load reg table: %d\n", rc);
+		goto err_load_reg_table;
+	}
+	return rc;
+
+err_load_reg_table:
+	msm_vidc_free_iommu_maps(res);
+err_load_iommu_maps:
+	msm_vidc_free_freq_table(res);
+err_load_freq_table:
+	return rc;
+}
+
+static int read_platform_resources_from_board(
+		struct msm_vidc_platform_resources *res)
+{
+	struct resource *kres = NULL;
+	struct platform_device *pdev = res->pdev;
+	struct msm_vidc_v4l2_platform_data *pdata = pdev->dev.platform_data;
+	int64_t start, size;
+	int c = 0, rc = 0;
+
+	if (!pdata) {
+		dprintk(VIDC_ERR, "Platform data not found\n");
+		return -ENOENT;
+	}
+
+	res->fw_base_addr = 0x0;
+
+	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res->register_base = kres ? kres->start : -1;
+	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
+
+	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	res->irq = kres ? kres->start : -1;
+
+	res->load_freq_tbl = kzalloc(pdata->num_load_table *
+			sizeof(*res->load_freq_tbl), GFP_KERNEL);
+
+	if (!res->load_freq_tbl) {
+		dprintk(VIDC_ERR, "%s Failed to alloc load_freq_tbl\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	res->load_freq_tbl_size = pdata->num_load_table;
+	for (c = 0; c > pdata->num_load_table; ++c) {
+		res->load_freq_tbl[c].load = pdata->load_table[c][0];
+		res->load_freq_tbl[c].freq = pdata->load_table[c][1];
+	}
+
+	res->iommu_maps = kzalloc(MAX_MAP *
+			sizeof(*res->iommu_maps), GFP_KERNEL);
+	if (!res->iommu_maps) {
+		dprintk(VIDC_ERR, "%s Failed to alloc iommu_maps\n",
+				__func__);
+		kfree(res->load_freq_tbl);
+		return -ENOMEM;
+	}
+
+	res->iommu_maps_size = MAX_MAP;
+
+	start = pdata->iommu_table[MSM_VIDC_V4L2_IOMMU_MAP_CP][0];
+	size = pdata->iommu_table[MSM_VIDC_V4L2_IOMMU_MAP_CP][1];
+	res->iommu_maps[CP_MAP] = (struct msm_vidc_iommu_info) {
+		.addr_range = {(u32) start, (u32) size},
+			.name = "qcom,vidc-cp-map",
+			.ctx = "venus_cp",
+	};
+
+	start = pdata->iommu_table[MSM_VIDC_V4L2_IOMMU_MAP_NS][0];
+	size = pdata->iommu_table[MSM_VIDC_V4L2_IOMMU_MAP_NS][1];
+	res->iommu_maps[NS_MAP] = (struct msm_vidc_iommu_info) {
+		.addr_range = {(u32) start, (u32) size},
+			.name = "qcom,vidc-ns-map",
+			.ctx = "venus_ns",
+	};
+	return rc;
+}
+
+static int read_platform_resources(struct msm_vidc_core *core,
+		struct platform_device *pdev)
+{
+	if (!core || !pdev) {
+		dprintk(VIDC_ERR, "%s: Invalid params %p %p\n",
+			__func__, core, pdev);
+		return -EINVAL;
+	}
+	core->hfi_type = read_hfi_type(pdev);
+	if (core->hfi_type < 0) {
+		dprintk(VIDC_ERR, "Failed to identify core type\n");
+		return core->hfi_type;
+	}
+
+	core->resources.pdev = pdev;
+	if (pdev->dev.of_node) {
+		/* Target supports DT, parse from it */
+		return read_platform_resources_from_dt(&core->resources);
+	} else {
+		/* Legacy board file usage */
+		return read_platform_resources_from_board(
+				&core->resources);
+	}
+}
 static int msm_vidc_initialize_core(struct platform_device *pdev,
 				struct msm_vidc_core *core)
 {
@@ -702,10 +1008,15 @@
 	int rc = 0;
 	if (!core)
 		return -EINVAL;
+	rc = read_platform_resources(core, pdev);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to get platform resources\n");
+		return rc;
+	}
 
 	INIT_LIST_HEAD(&core->instances);
 	mutex_init(&core->sync_lock);
-	spin_lock_init(&core->lock);
+	mutex_init(&core->lock);
 
 	core->state = VIDC_CORE_UNINIT;
 	for (i = SYS_MSG_INDEX(SYS_MSG_START);
@@ -713,11 +1024,6 @@
 		init_completion(&core->completions[i]);
 	}
 
-	rc = msm_vidc_get_hfi(pdev, core);
-	if (rc)
-		dprintk(VIDC_ERR,
-			"Failed to read Host-Firmware Interface rc: %d\n", rc);
-
 	return rc;
 }
 
@@ -725,7 +1031,6 @@
 {
 	int rc = 0;
 	struct msm_vidc_core *core;
-	unsigned long flags;
 	core = kzalloc(sizeof(*core), GFP_KERNEL);
 	if (!core || !vidc_driver) {
 		dprintk(VIDC_ERR,
@@ -770,15 +1075,14 @@
 	video_set_drvdata(&core->vdev[MSM_VIDC_ENCODER].vdev, core);
 
 	core->device = vidc_hfi_initialize(core->hfi_type, core->id,
-				pdev, &handle_cmd_response);
+				&core->resources, &handle_cmd_response);
 	if (!core->device) {
 		dprintk(VIDC_ERR, "Failed to create HFI device\n");
 		goto err_cores_exceeded;
 	}
-
-	spin_lock_irqsave(&vidc_driver->lock, flags);
+	mutex_lock(&vidc_driver->lock);
 	if (vidc_driver->num_cores  + 1 > MSM_VIDC_CORES_MAX) {
-		spin_unlock_irqrestore(&vidc_driver->lock, flags);
+		mutex_unlock(&vidc_driver->lock);
 		dprintk(VIDC_ERR, "Maximum cores already exist, core_no = %d\n",
 				vidc_driver->num_cores);
 		goto err_cores_exceeded;
@@ -786,7 +1090,7 @@
 
 	core->id = vidc_driver->num_cores++;
 	list_add_tail(&core->list, &vidc_driver->cores);
-	spin_unlock_irqrestore(&vidc_driver->lock, flags);
+	mutex_unlock(&vidc_driver->lock);
 	core->debugfs_root = msm_vidc_debugfs_init_core(
 		core, vidc_driver->debugfs_root);
 	pdev->dev.platform_data = core;
@@ -825,6 +1129,9 @@
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
 	v4l2_device_unregister(&core->v4l2_dev);
 
+	msm_vidc_free_freq_table(&core->resources);
+	msm_vidc_free_iommu_maps(&core->resources);
+	msm_vidc_free_reg_table(&core->resources);
 	kfree(core);
 	return rc;
 }
@@ -838,7 +1145,7 @@
 	.probe = msm_vidc_probe,
 	.remove = msm_vidc_remove,
 	.driver = {
-		.name = "msm_vidc",
+		.name = "msm_vidc_v4l2",
 		.owner = THIS_MODULE,
 		.of_match_table = msm_vidc_dt_match,
 	},
@@ -856,7 +1163,7 @@
 	}
 
 	INIT_LIST_HEAD(&vidc_driver->cores);
-	spin_lock_init(&vidc_driver->lock);
+	mutex_init(&vidc_driver->lock);
 	vidc_driver->debugfs_root = debugfs_create_dir("msm_vidc", NULL);
 	if (!vidc_driver->debugfs_root)
 		dprintk(VIDC_ERR,
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
similarity index 98%
rename from drivers/media/video/msm_vidc/msm_vdec.c
rename to drivers/media/platform/msm/vidc/msm_vdec.c
index b10787c..ae98afb 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -423,8 +423,8 @@
 				buffer_info.extradata_addr = 0;
 				buffer_info.extradata_size = 0;
 			}
-			rc = hdev->session_set_buffers(
-				(void *)inst->session, &buffer_info);
+			rc = call_hfi_op(hdev, session_set_buffers,
+					(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
 				"vidc_hal_session_set_buffers failed");
@@ -501,8 +501,8 @@
 			else
 				buffer_info.extradata_addr = 0;
 			buffer_info.response_required = false;
-			rc = hdev->session_release_buffers(
-					(void *)inst->session, &buffer_info);
+			rc = call_hfi_op(hdev, session_release_buffers,
+				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
 				"vidc_hal_session_release_buffers failed");
@@ -627,7 +627,8 @@
 		} else {
 			switch (fmt->fourcc) {
 			case V4L2_PIX_FMT_NV12:
-				hdev->get_stride_scanline(COLOR_FMT_NV12,
+				call_hfi_op(hdev, get_stride_scanline,
+					COLOR_FMT_NV12,
 					inst->prop.width, inst->prop.height,
 					&stride, &scanlines);
 				break;
@@ -848,7 +849,6 @@
 {
 	int i, rc = 0;
 	struct msm_vidc_inst *inst;
-	unsigned long flags;
 	struct hal_buffer_requirements *bufreq;
 	int extra_idx = 0;
 	struct hfi_device *hdev;
@@ -892,7 +892,7 @@
 				"Failed to get buffer requirements: %d\n", rc);
 			break;
 		}
-		spin_lock_irqsave(&inst->lock, flags);
+		mutex_lock(&inst->lock);
 		if (*num_buffers && *num_buffers >
 			inst->buff_req.buffer[HAL_BUFFER_OUTPUT].
 				buffer_count_actual) {
@@ -902,8 +902,8 @@
 
 			new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
 			new_buf_count.buffer_count_actual = *num_buffers;
-			rc = hdev->session_set_property(inst->session,
-					property_id, &new_buf_count);
+			rc = call_hfi_op(hdev, session_set_property,
+				inst->session, property_id, &new_buf_count);
 
 		}
 		bufreq = &inst->buff_req.buffer[HAL_BUFFER_OUTPUT];
@@ -911,7 +911,7 @@
 			*num_buffers =  bufreq->buffer_count_actual;
 		else
 			bufreq->buffer_count_actual = *num_buffers ;
-		spin_unlock_irqrestore(&inst->lock, flags);
+		mutex_unlock(&inst->lock);
 		dprintk(VIDC_DBG, "count =  %d, size = %d, alignment = %d\n",
 				inst->buff_req.buffer[1].buffer_count_actual,
 				inst->buff_req.buffer[1].buffer_size,
@@ -1224,9 +1224,8 @@
 			property_id,
 			msm_vdec_ctrls[control_idx].id,
 			control.value);
-			rc = hdev->session_set_property((void *)
-				inst->session, property_id,
-					pdata);
+			rc = call_hfi_op(hdev, session_set_property, (void *)
+				inst->session, property_id, pdata);
 	}
 
 	return rc;
diff --git a/drivers/media/video/msm_vidc/msm_vdec.h b/drivers/media/platform/msm/vidc/msm_vdec.h
similarity index 100%
rename from drivers/media/video/msm_vidc/msm_vdec.h
rename to drivers/media/platform/msm/vidc/msm_vdec.h
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
similarity index 98%
rename from drivers/media/video/msm_vidc/msm_venc.c
rename to drivers/media/platform/msm/vidc/msm_venc.c
index 05d3570..12469a5 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -124,6 +124,7 @@
 		.step = 1,
 		.menu_skip_mask = 0,
 		.qmenu = NULL,
+		.cluster = 0,
 	},
 	{
 		.id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
@@ -399,7 +400,6 @@
 		(1 << V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) |
 		(1 << V4L2_MPEG_VIDEO_MULTI_SLICE_GOB)
 		),
-		.qmenu = NULL,
 		.cluster = MSM_VENC_CTRL_CLUSTER_SLICING,
 	},
 	{
@@ -408,7 +408,7 @@
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.minimum = MIN_SLICE_BYTE_SIZE,
 		.maximum = MAX_SLICE_BYTE_SIZE,
-		.default_value = 0,
+		.default_value = MIN_SLICE_BYTE_SIZE,
 		.step = 1,
 		.menu_skip_mask = 0,
 		.qmenu = NULL,
@@ -420,7 +420,7 @@
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.minimum = 1,
 		.maximum = MAX_SLICE_MB_SIZE,
-		.default_value = 0,
+		.default_value = 1,
 		.step = 1,
 		.menu_skip_mask = 0,
 		.qmenu = NULL,
@@ -543,7 +543,6 @@
 		(1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
 		(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME)
 		),
-		.qmenu = NULL,
 		.cluster = 0,
 	}
 };
@@ -628,7 +627,6 @@
 	struct msm_vidc_inst *inst;
 	struct hal_buffer_count_actual new_buf_count;
 	enum hal_property property_id;
-	unsigned long flags;
 	struct hfi_device *hdev;
 	if (!q || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
@@ -666,15 +664,15 @@
 			break;
 		}
 		*num_planes = 1;
-		spin_lock_irqsave(&inst->lock, flags);
+		mutex_lock(&inst->lock);
 		*num_buffers = inst->buff_req.buffer[0].buffer_count_actual =
 			max(*num_buffers, inst->buff_req.buffer[0].
 				buffer_count_actual);
-		spin_unlock_irqrestore(&inst->lock, flags);
+		mutex_unlock(&inst->lock);
 		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
 		new_buf_count.buffer_type = HAL_BUFFER_INPUT;
 		new_buf_count.buffer_count_actual = *num_buffers;
-		rc = hdev->session_set_property(inst->session,
+		rc = call_hfi_op(hdev, session_set_property, inst->session,
 					property_id, &new_buf_count);
 		dprintk(VIDC_DBG, "size = %d, alignment = %d, count = %d\n",
 				inst->buff_req.buffer[0].buffer_size,
@@ -1446,8 +1444,8 @@
 		dprintk(VIDC_DBG, "Control: HAL property=%d,ctrl_value=%d\n",
 				property_id,
 				ctrl->val);
-		rc = hdev->session_set_property((void *)inst->session,
-				property_id, pdata);
+		rc = call_hfi_op(hdev, session_set_property,
+				(void *)inst->session, property_id, pdata);
 	}
 
 	return rc;
@@ -1646,8 +1644,9 @@
 		frame_rate.frame_rate = inst->prop.fps * (0x1<<16);
 		frame_rate.buffer_type = HAL_BUFFER_OUTPUT;
 		pdata = &frame_rate;
-		rc = hdev->session_set_property((void *)inst->session,
-				property_id, pdata);
+		rc = call_hfi_op(hdev, session_set_property,
+				(void *)inst->session, property_id, pdata);
+
 		if (rc) {
 			dprintk(VIDC_WARN,
 				"Failed to set frame rate %d\n", rc);
@@ -1695,16 +1694,16 @@
 		frame_sz.height = inst->prop.height;
 		dprintk(VIDC_DBG, "width = %d, height = %d\n",
 				frame_sz.width, frame_sz.height);
-		rc = hdev->session_set_property((void *)inst->session,
-				HAL_PARAM_FRAME_SIZE, &frame_sz);
+		rc = call_hfi_op(hdev, session_set_property, (void *)
+			inst->session, HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
 			dprintk(VIDC_ERR,
 				"Failed to set framesize for Output port\n");
 			goto exit;
 		}
 		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
-		rc = hdev->session_set_property((void *)inst->session,
-				HAL_PARAM_FRAME_SIZE, &frame_sz);
+		rc = call_hfi_op(hdev, session_set_property, (void *)
+			inst->session, HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
 			dprintk(VIDC_ERR,
 				"Failed to set hal property for framesize\n");
@@ -1834,7 +1833,7 @@
 				b->m.planes[i].m.userptr;
 			buffer_info.extradata_size = 0;
 			buffer_info.extradata_addr = 0;
-			rc = hdev->session_set_buffers(
+			rc = call_hfi_op(hdev, session_set_buffers,
 				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
@@ -1888,7 +1887,7 @@
 			buffer_info.extradata_size = 0;
 			buffer_info.extradata_addr = 0;
 			buffer_info.response_required = false;
-			rc = hdev->session_release_buffers(
+			rc = call_hfi_op(hdev, session_release_buffers,
 				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
@@ -2047,7 +2046,11 @@
 					msm_venc_ctrls[idx].default_value);
 			}
 		}
-
+		if (!ctrl) {
+			dprintk(VIDC_ERR,
+			"Failed to get ctrl for: idx: %d, %d\n",
+			idx, msm_venc_ctrls[idx].id);
+		}
 		msm_venc_ctrls[idx].priv = ctrl;
 	}
 	ret_val = inst->ctrl_handler.error;
@@ -2068,7 +2071,6 @@
 					idx);
 			continue;
 		}
-
 		v4l2_ctrl_cluster(cluster_size, cluster);
 
 		temp = kzalloc(sizeof(*temp), GFP_KERNEL);
diff --git a/drivers/media/video/msm_vidc/msm_venc.h b/drivers/media/platform/msm/vidc/msm_venc.h
similarity index 100%
rename from drivers/media/video/msm_vidc/msm_venc.h
rename to drivers/media/platform/msm/vidc/msm_venc.h
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
similarity index 95%
rename from drivers/media/video/msm_vidc/msm_vidc.c
rename to drivers/media/platform/msm/vidc/msm_vidc.c
index 73c9860..042900e 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -93,7 +93,7 @@
 
 	hdev = inst->core->device;
 
-	return hdev->iommu_get_map(hdev->hfi_device_data, maps);
+	return call_hfi_op(hdev, iommu_get_map, hdev->hfi_device_data, maps);
 }
 
 int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
@@ -395,7 +395,6 @@
 {
 	struct msm_vidc_inst *inst = NULL;
 	struct msm_vidc_core *core = NULL;
-	unsigned long flags;
 	int rc = 0;
 	int i = 0;
 	if (core_id >= MSM_VIDC_CORES_MAX ||
@@ -423,7 +422,7 @@
 	mutex_init(&inst->sync_lock);
 	mutex_init(&inst->bufq[CAPTURE_PORT].lock);
 	mutex_init(&inst->bufq[OUTPUT_PORT].lock);
-	spin_lock_init(&inst->lock);
+	mutex_init(&inst->lock);
 	inst->session_type = session_type;
 	INIT_LIST_HEAD(&inst->pendingq);
 	INIT_LIST_HEAD(&inst->internalbufs);
@@ -475,9 +474,9 @@
 
 	setup_event_queue(inst, &core->vdev[core_id].vdev);
 
-	spin_lock_irqsave(&core->lock, flags);
+	mutex_lock(&core->lock);
 	list_add_tail(&inst->list, &core->instances);
-	spin_unlock_irqrestore(&core->lock, flags);
+	mutex_unlock(&core->lock);
 	return inst;
 fail_init:
 	msm_smem_delete_client(inst->mem_client);
@@ -490,12 +489,11 @@
 
 static void cleanup_instance(struct msm_vidc_inst *inst)
 {
-	unsigned long flags;
 	struct list_head *ptr, *next;
 	struct vb2_buf_entry *entry;
 	struct internal_buf *buf;
 	if (inst) {
-		spin_lock_irqsave(&inst->lock, flags);
+		mutex_lock(&inst->lock);
 		if (!list_empty(&inst->pendingq)) {
 			list_for_each_safe(ptr, next, &inst->pendingq) {
 				entry = list_entry(ptr, struct vb2_buf_entry,
@@ -509,10 +507,10 @@
 				buf = list_entry(ptr, struct internal_buf,
 						list);
 				list_del(&buf->list);
-				spin_unlock_irqrestore(&inst->lock, flags);
+				mutex_unlock(&inst->lock);
 				msm_smem_free(inst->mem_client, buf->handle);
 				kfree(buf);
-				spin_lock_irqsave(&inst->lock, flags);
+				mutex_lock(&inst->lock);
 			}
 		}
 		if (!list_empty(&inst->persistbufs)) {
@@ -520,18 +518,18 @@
 				buf = list_entry(ptr, struct internal_buf,
 						list);
 				list_del(&buf->list);
-				spin_unlock_irqrestore(&inst->lock, flags);
+				mutex_unlock(&inst->lock);
 				msm_smem_free(inst->mem_client, buf->handle);
 				kfree(buf);
-				spin_lock_irqsave(&inst->lock, flags);
+				mutex_lock(&inst->lock);
 			}
 		}
 		if (inst->extradata_handle) {
-			spin_unlock_irqrestore(&inst->lock, flags);
+			mutex_unlock(&inst->lock);
 			msm_smem_free(inst->mem_client, inst->extradata_handle);
-			spin_lock_irqsave(&inst->lock, flags);
+			mutex_lock(&inst->lock);
 		}
-		spin_unlock_irqrestore(&inst->lock, flags);
+		mutex_unlock(&inst->lock);
 		msm_smem_delete_client(inst->mem_client);
 		debugfs_remove_recursive(inst->debugfs_root);
 	}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
similarity index 92%
rename from drivers/media/video/msm_vidc/msm_vidc_common.c
rename to drivers/media/platform/msm/vidc/msm_vidc_common.c
index 7e8732a..3c012e7 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -48,25 +48,29 @@
 
 #define TIME_DIFF_THRESHOLD 200
 
+/*Load is in Macroblocks (MBs) per sec. This value is calculated
+ * based on one 4k video instance @ 24 fps plus one 1080p video
+ * instance @ 30fps. 1 MB = 16 X 16 pixels*/
+#define MAX_LOAD 1074240
+
 static int msm_comm_get_load(struct msm_vidc_core *core,
 	enum session_type type)
 {
 	struct msm_vidc_inst *inst = NULL;
 	int num_mbs_per_sec = 0;
-	unsigned long flags;
 	if (!core) {
 		dprintk(VIDC_ERR, "Invalid args: %p\n", core);
 		return -EINVAL;
 	}
 	list_for_each_entry(inst, &core->instances, list) {
-		spin_lock_irqsave(&inst->lock, flags);
+		mutex_lock(&inst->lock);
 		if (inst->session_type == type &&
 			inst->state >= MSM_VIDC_OPEN_DONE &&
 			inst->state < MSM_VIDC_STOP_DONE) {
 			num_mbs_per_sec += NUM_MBS_PER_SEC(inst->prop.height,
 					inst->prop.width, inst->prop.fps);
 		}
-		spin_unlock_irqrestore(&inst->lock, flags);
+		mutex_unlock(&inst->lock);
 	}
 	return num_mbs_per_sec;
 }
@@ -91,7 +95,8 @@
 
 	load = msm_comm_get_load(core, type);
 
-	rc = hdev->scale_bus(hdev->hfi_device_data, load, type, mtype);
+	rc = call_hfi_op(hdev, scale_bus, hdev->hfi_device_data,
+					 load, type, mtype);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
 
@@ -112,16 +117,16 @@
 
 	for (i = 0; i < MSM_VIDC_MAX_DEVICES; i++) {
 		if ((mtype & DDR_MEM) &&
-			hdev->scale_bus(hdev->hfi_device_data, 0, i, DDR_MEM)) {
+			call_hfi_op(hdev, unvote_bus, hdev->hfi_device_data,
+				i, DDR_MEM))
 			dprintk(VIDC_WARN,
 				"Failed to unvote for DDR accesses\n");
-		}
+
 		if ((mtype & OCMEM_MEM) &&
-			hdev->scale_bus(hdev->hfi_device_data, 0, i,
-					OCMEM_MEM)) {
+			call_hfi_op(hdev, unvote_bus, hdev->hfi_device_data,
+				i, OCMEM_MEM))
 			dprintk(VIDC_WARN,
 				"Failed to unvote for OCMEM accesses\n");
-		}
 	}
 }
 
@@ -129,19 +134,18 @@
 {
 	struct msm_vidc_core *core;
 	int found = 0;
-	unsigned long flags;
 	if (core_id > MSM_VIDC_CORES_MAX) {
 		dprintk(VIDC_ERR, "Core id = %d is greater than max = %d\n",
 			core_id, MSM_VIDC_CORES_MAX);
 		return NULL;
 	}
-	spin_lock_irqsave(&vidc_driver->lock, flags);
+	mutex_lock(&vidc_driver->lock);
 	list_for_each_entry(core, &vidc_driver->cores, list) {
 		if (core && core->id == core_id)
 			found = 1;
 			break;
 	}
-	spin_unlock_irqrestore(&vidc_driver->lock, flags);
+	mutex_unlock(&vidc_driver->lock);
 	if (found)
 		return core;
 	return NULL;
@@ -287,12 +291,11 @@
 static void change_inst_state(struct msm_vidc_inst *inst,
 	enum instance_state state)
 {
-	unsigned long flags;
-	spin_lock_irqsave(&inst->lock, flags);
+	mutex_lock(&inst->lock);
 	dprintk(VIDC_DBG, "Moved inst: %p from state: %d to state: %d\n",
 		   inst, inst->state, state);
 	inst->state = state;
-	spin_unlock_irqrestore(&inst->lock, flags);
+	mutex_unlock(&inst->lock);
 }
 
 static int signal_session_msg_receipt(enum command_response cmd,
@@ -403,7 +406,6 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
-	unsigned long flags;
 	int i;
 	if (!response || !response->data) {
 		dprintk(VIDC_ERR,
@@ -411,10 +413,10 @@
 		return;
 	}
 	inst = (struct msm_vidc_inst *)response->session_id;
-	spin_lock_irqsave(&inst->lock, flags);
+	mutex_lock(&inst->lock);
 	memcpy(&inst->buff_req, response->data,
 			sizeof(struct buffer_requirements));
-	spin_unlock_irqrestore(&inst->lock, flags);
+	mutex_unlock(&inst->lock);
 	for (i = 0; i < 8; i++) {
 		dprintk(VIDC_DBG,
 			"buffer type: %d, count : %d, size: %d\n",
@@ -523,14 +525,13 @@
 	struct msm_vidc_inst *inst = NULL ;
 	struct msm_vidc_core *core = NULL;
 	struct v4l2_event dqevent;
-	unsigned long flags;
 	if (response) {
 		core = get_vidc_core(response->device_id);
 		dprintk(VIDC_WARN, "SYS_ERROR received for core %p\n", core);
 		if (core) {
-			spin_lock_irqsave(&core->lock, flags);
+			mutex_lock(&core->lock);
 			core->state = VIDC_CORE_INVALID;
-			spin_unlock_irqrestore(&core->lock, flags);
+			mutex_unlock(&core->lock);
 			dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
 			dqevent.id = 0;
 			list_for_each_entry(inst, &core->instances,
@@ -538,9 +539,9 @@
 				v4l2_event_queue_fh(&inst->event_handler,
 						&dqevent);
 
-				spin_lock_irqsave(&inst->lock, flags);
+				mutex_lock(&inst->lock);
 				inst->state = MSM_VIDC_CORE_INVALID;
-				spin_unlock_irqrestore(&inst->lock, flags);
+				mutex_unlock(&inst->lock);
 
 				wake_up(&inst->kernel_event_queue);
 			}
@@ -560,7 +561,6 @@
 	struct msm_vidc_inst *inst;
 	struct msm_vidc_core *core = NULL;
 	struct v4l2_event dqevent;
-	unsigned long flags;
 	dprintk(VIDC_ERR, "Venus Subsystem crashed\n");
 	core = get_vidc_core(response->device_id);
 	if (!core) {
@@ -568,18 +568,18 @@
 		return;
 	}
 	subsystem_crashed("venus");
-	spin_lock_irqsave(&core->lock, flags);
+	mutex_lock(&core->lock);
 	core->state = VIDC_CORE_INVALID;
-	spin_unlock_irqrestore(&core->lock, flags);
+	mutex_unlock(&core->lock);
 	dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
 	dqevent.id = 0;
 	list_for_each_entry(inst, &core->instances, list) {
 		if (inst) {
 			v4l2_event_queue_fh(&inst->event_handler, &dqevent);
-			spin_lock_irqsave(&inst->lock, flags);
+			mutex_lock(&inst->lock);
 			inst->state = MSM_VIDC_CORE_INVALID;
 			inst->session = NULL;
-			spin_unlock_irqrestore(&inst->lock, flags);
+			mutex_unlock(&inst->lock);
 		}
 	}
 }
@@ -663,7 +663,7 @@
 	if (inst->session_type == MSM_VIDC_ENCODER)
 		goto exit;
 	if (cur_time_stamp >= LLONG_MAX) {
-		dprintk(VIDC_WARN,
+		dprintk(VIDC_DBG,
 			"Clock scaling failed : Timestamp invalid\n");
 		goto exit;
 	}
@@ -819,8 +819,13 @@
 	fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
 	vb = get_vb_from_device_addr(&inst->bufq[CAPTURE_PORT],
 		(u32)fill_buf_done->packet_buffer1);
-	if (vb)
-		vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
+	if (!vb) {
+		dprintk(VIDC_ERR,
+				"Failed to find video buffer for seq_hdr_done");
+		return;
+	}
+
+	vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
 
 	vb->v4l2_buf.flags = V4L2_QCOM_BUF_FLAG_CODECCONFIG;
 
@@ -916,7 +921,8 @@
 	num_mbs_per_sec += msm_comm_get_load(core, MSM_VIDC_DECODER);
 
 	dprintk(VIDC_INFO, "num_mbs_per_sec = %d\n", num_mbs_per_sec);
-	rc = hdev->scale_clocks(hdev->hfi_device_data, num_mbs_per_sec);
+	rc = call_hfi_op(hdev, scale_clocks,
+		hdev->hfi_device_data, num_mbs_per_sec);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);
 	return rc;
@@ -942,7 +948,7 @@
 		dprintk(VIDC_WARN,
 				"Failed to scale DDR bus. Performance might be impacted\n");
 	}
-	if (hdev->is_ocmem_present(hdev->hfi_device_data)) {
+	if (call_hfi_op(hdev, is_ocmem_present, hdev->hfi_device_data)) {
 		if (msm_comm_scale_bus(core, inst->session_type,
 					OCMEM_MEM))
 			dprintk(VIDC_WARN,
@@ -979,7 +985,7 @@
 	init_completion(
 		&core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)]);
 
-	rc = hdev->unset_ocmem(hdev->hfi_device_data);
+	rc = call_hfi_op(hdev, unset_ocmem, hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
 		goto release_ocmem_failed;
@@ -998,7 +1004,6 @@
 static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_core *core = inst->core;
-	unsigned long flags;
 	int rc = 0;
 	mutex_lock(&core->sync_lock);
 	if (core->state >= VIDC_CORE_INIT_DONE) {
@@ -1015,9 +1020,9 @@
 		rc = -EIO;
 		goto exit;
 	} else {
-		spin_lock_irqsave(&core->lock, flags);
+		mutex_lock(&core->lock);
 		core->state = VIDC_CORE_INIT_DONE;
-		spin_unlock_irqrestore(&core->lock, flags);
+		mutex_unlock(&core->lock);
 	}
 	dprintk(VIDC_DBG, "SYS_INIT_DONE!!!\n");
 core_already_inited:
@@ -1032,7 +1037,6 @@
 {
 	int rc = 0;
 	struct msm_vidc_core *core = inst->core;
-	unsigned long flags;
 	struct hfi_device *hdev;
 
 	if (!core || !core->device)
@@ -1052,7 +1056,7 @@
 		goto fail_scale_bus;
 	}
 
-	rc = hdev->load_fw(hdev->hfi_device_data);
+	rc = call_hfi_op(hdev, load_fw, hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to load video firmware\n");
 		goto fail_load_fw;
@@ -1064,20 +1068,20 @@
 	}
 
 	init_completion(&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)]);
-	rc = hdev->core_init(hdev->hfi_device_data);
+	rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init core, id = %d\n", core->id);
 		goto fail_core_init;
 	}
-	spin_lock_irqsave(&core->lock, flags);
+	mutex_lock(&core->lock);
 	core->state = VIDC_CORE_INIT;
-	spin_unlock_irqrestore(&core->lock, flags);
+	mutex_unlock(&core->lock);
 core_already_inited:
 	change_inst_state(inst, MSM_VIDC_CORE_INIT);
 	mutex_unlock(&core->sync_lock);
 	return rc;
 fail_core_init:
-	hdev->unload_fw(hdev->hfi_device_data);
+	call_hfi_op(hdev, unload_fw, hdev->hfi_device_data);
 fail_load_fw:
 	msm_comm_unvote_buses(core, DDR_MEM);
 fail_scale_bus:
@@ -1090,7 +1094,6 @@
 	int rc = 0;
 	struct msm_vidc_core *core;
 	struct hfi_device *hdev;
-	unsigned long flags;
 
 	if (!inst || !inst->core || !inst->core->device) {
 		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1110,18 +1113,18 @@
 	if (list_empty(&core->instances)) {
 		if (inst->state != MSM_VIDC_CORE_INVALID)
 			msm_comm_unset_ocmem(core);
-		hdev->free_ocmem(hdev->hfi_device_data);
+		call_hfi_op(hdev, free_ocmem, hdev->hfi_device_data);
 		dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
-		rc = hdev->core_release(hdev->hfi_device_data);
+		rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data);
 		if (rc) {
 			dprintk(VIDC_ERR, "Failed to release core, id = %d\n",
 							core->id);
 			goto exit;
 		}
-		spin_lock_irqsave(&core->lock, flags);
+		mutex_lock(&core->lock);
 		core->state = VIDC_CORE_UNINIT;
-		spin_unlock_irqrestore(&core->lock, flags);
-		hdev->unload_fw(hdev->hfi_device_data);
+		call_hfi_op(hdev, unload_fw, hdev->hfi_device_data);
+		mutex_unlock(&core->lock);
 		msm_comm_unvote_buses(core, DDR_MEM|OCMEM_MEM);
 	}
 core_already_uninited:
@@ -1227,9 +1230,9 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_INIT_DONE)]);
-	inst->session = hdev->session_init(hdev->hfi_device_data, (u32) inst,
-					get_hal_domain(inst->session_type),
-					get_hal_codec_type(fourcc));
+	inst->session = call_hfi_op(hdev, session_init, hdev->hfi_device_data,
+			(u32) inst, get_hal_domain(inst->session_type),
+			get_hal_codec_type(fourcc));
 	if (!inst->session) {
 		dprintk(VIDC_ERR,
 			"Failed to call session init for: %d, %d, %d, %d\n",
@@ -1249,11 +1252,19 @@
 	int rc = 0;
 	u32 ocmem_sz = 0;
 	struct hfi_device *hdev;
+	int num_mbs_per_sec = 0;
 
 	if (!inst || !inst->core || !inst->core->device) {
 		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
 		return -EINVAL;
 	}
+	num_mbs_per_sec = msm_comm_get_load(inst->core, MSM_VIDC_DECODER);
+	num_mbs_per_sec += msm_comm_get_load(inst->core, MSM_VIDC_ENCODER);
+	if (num_mbs_per_sec > MAX_LOAD) {
+		dprintk(VIDC_ERR, "HW is overloaded, needed:%d max: %d\n",
+			num_mbs_per_sec, MAX_LOAD);
+		return -ENOMEM;
+	}
 	hdev = inst->core->device;
 
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
@@ -1265,7 +1276,8 @@
 	rc = msm_comm_scale_bus(inst->core, inst->session_type, OCMEM_MEM);
 	if (!rc) {
 		mutex_lock(&inst->core->sync_lock);
-		rc = hdev->alloc_ocmem(hdev->hfi_device_data, ocmem_sz);
+		rc = call_hfi_op(hdev, alloc_ocmem, hdev->hfi_device_data,
+				ocmem_sz);
 		mutex_unlock(&inst->core->sync_lock);
 		if (rc) {
 			dprintk(VIDC_WARN,
@@ -1276,7 +1288,7 @@
 		dprintk(VIDC_WARN,
 		"Failed to vote for OCMEM BW. Performance will be impacted\n");
 	}
-	rc = hdev->session_load_res((void *) inst->session);
+	rc = call_hfi_op(hdev, session_load_res, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send load resources\n");
@@ -1307,7 +1319,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_START_DONE)]);
-	rc = hdev->session_start((void *) inst->session);
+	rc = call_hfi_op(hdev, session_start, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send start\n");
@@ -1338,7 +1350,7 @@
 	dprintk(VIDC_DBG, "Send Stop to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_STOP_DONE)]);
-	rc = hdev->session_stop((void *) inst->session);
+	rc = call_hfi_op(hdev, session_stop, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to send stop\n");
 		goto exit;
@@ -1369,7 +1381,7 @@
 		"Send release res to hal\n");
 	init_completion(
 	&inst->completions[SESSION_MSG_INDEX(SESSION_RELEASE_RESOURCE_DONE)]);
-	rc = hdev->session_release_res((void *) inst->session);
+	rc = call_hfi_op(hdev, session_release_res, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send release resources\n");
@@ -1401,7 +1413,7 @@
 		"Send session close to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_END_DONE)]);
-	rc = hdev->session_end((void *) inst->session);
+	rc = call_hfi_op(hdev, session_end, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send close\n");
@@ -1608,11 +1620,14 @@
 				dprintk(VIDC_DBG,
 					"Received CODECCONFIG on output cap\n");
 			}
+			if (vb->v4l2_buf.flags &
+				V4L2_QCOM_BUF_TIMESTAMP_INVALID)
+				frame_data.timestamp = LLONG_MAX;
 			dprintk(VIDC_DBG,
 				"Sending etb to hal: Alloc: %d :filled: %d\n",
 				frame_data.alloc_len, frame_data.filled_len);
-			rc = hdev->session_etb((void *) inst->session,
-					&frame_data);
+			rc = call_hfi_op(hdev, session_etb, (void *)
+					inst->session, &frame_data);
 			if (!rc)
 				msm_vidc_debugfs_update(inst,
 					MSM_VIDC_DEBUGFS_EVENT_ETB);
@@ -1641,16 +1656,16 @@
 				seq_hdr.seq_hdr = (u8 *) vb->v4l2_planes[0].
 					m.userptr;
 				seq_hdr.seq_hdr_len = vb->v4l2_planes[0].length;
-				rc = hdev->session_get_seq_hdr((void *)
-						inst->session, &seq_hdr);
+				rc = call_hfi_op(hdev, session_get_seq_hdr,
+					(void *) inst->session, &seq_hdr);
 				if (!rc) {
 					inst->vb2_seq_hdr = vb;
 					dprintk(VIDC_DBG, "Seq_hdr: %p\n",
 						inst->vb2_seq_hdr);
 				}
 			} else {
-				rc = hdev->session_ftb((void *)
-					inst->session, &frame_data);
+				rc = call_hfi_op(hdev, session_ftb,
+					(void *) inst->session, &frame_data);
 			if (!rc)
 				msm_vidc_debugfs_update(inst,
 					MSM_VIDC_DEBUGFS_EVENT_FTB);
@@ -1689,7 +1704,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)]);
-	rc = hdev->session_get_buf_req((void *) inst->session);
+	rc = call_hfi_op(hdev, session_get_buf_req, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to get property\n");
 		goto exit;
@@ -1715,7 +1730,6 @@
 	struct internal_buf *buf;
 	struct vidc_buffer_addr_info buffer_info;
 	int rc = 0;
-	unsigned long flags;
 	struct msm_vidc_core *core;
 	struct hfi_device *hdev;
 	if (!inst) {
@@ -1734,7 +1748,7 @@
 		dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev);
 		return -EINVAL;
 	}
-	spin_lock_irqsave(&inst->lock, flags);
+	mutex_lock(&inst->lock);
 	if (!list_empty(&inst->internalbufs)) {
 		list_for_each_safe(ptr, next, &inst->internalbufs) {
 			buf = list_entry(ptr, struct internal_buf,
@@ -1750,27 +1764,26 @@
 				init_completion(
 				   &inst->completions[SESSION_MSG_INDEX
 				   (SESSION_RELEASE_BUFFER_DONE)]);
-				rc = hdev->session_release_buffers(
-						(void *) inst->session,
-							&buffer_info);
+				rc = call_hfi_op(hdev, session_release_buffers,
+					(void *)inst->session, &buffer_info);
 				if (rc)
 					dprintk(VIDC_WARN,
 						"Rel scrtch buf fail:0x%x, %d",
 						buffer_info.align_device_addr,
 						buffer_info.buffer_size);
-				spin_unlock_irqrestore(&inst->lock, flags);
+				mutex_unlock(&inst->lock);
 				rc = wait_for_sess_signal_receipt(inst,
 					SESSION_RELEASE_BUFFER_DONE);
-				spin_lock_irqsave(&inst->lock, flags);
+				mutex_lock(&inst->lock);
 			}
 			list_del(&buf->list);
-			spin_unlock_irqrestore(&inst->lock, flags);
+			mutex_unlock(&inst->lock);
 			msm_smem_free(inst->mem_client, buf->handle);
 			kfree(buf);
-			spin_lock_irqsave(&inst->lock, flags);
+			mutex_lock(&inst->lock);
 		}
 	}
-	spin_unlock_irqrestore(&inst->lock, flags);
+	mutex_unlock(&inst->lock);
 	return rc;
 }
 
@@ -1781,7 +1794,6 @@
 	struct internal_buf *buf;
 	struct vidc_buffer_addr_info buffer_info;
 	int rc = 0;
-	unsigned long flags;
 	struct msm_vidc_core *core;
 	struct hfi_device *hdev;
 	if (!inst) {
@@ -1800,7 +1812,7 @@
 		dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev);
 		return -EINVAL;
 	}
-	spin_lock_irqsave(&inst->lock, flags);
+	mutex_lock(&inst->lock);
 	if (!list_empty(&inst->persistbufs)) {
 		list_for_each_safe(ptr, next, &inst->persistbufs) {
 			buf = list_entry(ptr, struct internal_buf,
@@ -1816,27 +1828,26 @@
 				init_completion(
 				   &inst->completions[SESSION_MSG_INDEX
 				   (SESSION_RELEASE_BUFFER_DONE)]);
-				rc = hdev->session_release_buffers(
-						(void *) inst->session,
-							&buffer_info);
+				rc = call_hfi_op(hdev, session_release_buffers,
+					(void *)inst->session, &buffer_info);
 				if (rc)
 					dprintk(VIDC_WARN,
 						"Rel prst buf fail:0x%x, %d",
 						buffer_info.align_device_addr,
 						buffer_info.buffer_size);
-				spin_unlock_irqrestore(&inst->lock, flags);
+				mutex_unlock(&inst->lock);
 				rc = wait_for_sess_signal_receipt(inst,
 					SESSION_RELEASE_BUFFER_DONE);
-				spin_lock_irqsave(&inst->lock, flags);
+				mutex_lock(&inst->lock);
 			}
 			list_del(&buf->list);
-			spin_unlock_irqrestore(&inst->lock, flags);
+			mutex_unlock(&inst->lock);
 			msm_smem_free(inst->mem_client, buf->handle);
 			kfree(buf);
-			spin_lock_irqsave(&inst->lock, flags);
+			mutex_lock(&inst->lock);
 		}
 	}
-	spin_unlock_irqrestore(&inst->lock, flags);
+	mutex_unlock(&inst->lock);
 	return rc;
 }
 
@@ -1862,7 +1873,7 @@
 		rc = -EAGAIN;
 		goto exit;
 	}
-	rc = hdev->session_set_property((void *)inst->session,
+	rc = call_hfi_op(hdev, session_set_property, (void *)inst->session,
 			ptype, pdata);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to set hal property for framesize\n");
@@ -1877,7 +1888,6 @@
 	struct msm_smem *handle;
 	struct internal_buf *binfo;
 	struct vidc_buffer_addr_info buffer_info;
-	unsigned long flags;
 	int domain;
 	unsigned long smem_flags = 0;
 	struct hal_buffer_requirements *scratch_buf;
@@ -1900,10 +1910,12 @@
 	if (msm_comm_release_scratch_buffers(inst))
 		dprintk(VIDC_WARN, "Failed to release scratch buffers\n");
 	if (inst->mode == VIDC_SECURE) {
-		domain = hdev->get_domain(hdev->hfi_device_data, CP_MAP);
+		domain = call_hfi_op(hdev, get_domain,
+				hdev->hfi_device_data, CP_MAP);
 		smem_flags |= SMEM_SECURE;
 	} else
-		domain = hdev->get_domain(hdev->hfi_device_data, NS_MAP);
+		domain = call_hfi_op(hdev, get_domain,
+				hdev->hfi_device_data, NS_MAP);
 
 	if (scratch_buf->buffer_size) {
 		for (i = 0; i < scratch_buf->buffer_count_actual;
@@ -1930,16 +1942,16 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			dprintk(VIDC_DBG, "Scratch buffer address: %x",
 					buffer_info.align_device_addr);
-			rc = hdev->session_set_buffers(
-					(void *) inst->session,	&buffer_info);
+			rc = call_hfi_op(hdev, session_set_buffers,
+				(void *) inst->session, &buffer_info);
 			if (rc) {
 				dprintk(VIDC_ERR,
 					"vidc_hal_session_set_buffers failed");
 				goto fail_set_buffers;
 			}
-			spin_lock_irqsave(&inst->lock, flags);
+			mutex_lock(&inst->lock);
 			list_add_tail(&binfo->list, &inst->internalbufs);
-			spin_unlock_irqrestore(&inst->lock, flags);
+			mutex_unlock(&inst->lock);
 		}
 	}
 	return rc;
@@ -1984,10 +1996,12 @@
 	}
 
 	if (inst->mode == VIDC_SECURE) {
-		domain = hdev->get_domain(hdev->hfi_device_data, CP_MAP);
+		domain = call_hfi_op(hdev, get_domain,
+				hdev->hfi_device_data, CP_MAP);
 		flags |= SMEM_SECURE;
 	} else
-		domain = hdev->get_domain(hdev->hfi_device_data, NS_MAP);
+		domain = call_hfi_op(hdev, get_domain,
+				hdev->hfi_device_data, NS_MAP);
 
 	if (persist_buf->buffer_size) {
 		for (i = 0;	i <	persist_buf->buffer_count_actual; i++) {
@@ -2013,16 +2027,16 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			dprintk(VIDC_DBG, "Persist buffer address: %x",
 					buffer_info.align_device_addr);
-			rc = hdev->session_set_buffers(
-				(void *) inst->session, &buffer_info);
+			rc = call_hfi_op(hdev, session_set_buffers,
+					(void *) inst->session, &buffer_info);
 			if (rc) {
 				dprintk(VIDC_ERR,
 					"vidc_hal_session_set_buffers failed");
 				goto fail_set_buffers;
 			}
-			spin_lock_irqsave(&inst->lock, flags);
+			mutex_lock(&inst->lock);
 			list_add_tail(&binfo->list, &inst->persistbufs);
-			spin_unlock_irqrestore(&inst->lock, flags);
+			mutex_unlock(&inst->lock);
 		}
 	}
 	return rc;
@@ -2130,7 +2144,7 @@
 			dprintk(VIDC_WARN,
 			"FLUSH BUG: Pending q not empty! It should be empty\n");
 		}
-		rc = hdev->session_flush(inst->session,
+		rc = call_hfi_op(hdev, session_flush, inst->session,
 				HAL_FLUSH_OUTPUT);
 	} else {
 		if (!list_empty(&inst->pendingq)) {
@@ -2151,7 +2165,7 @@
 				kfree(temp);
 			}
 		}
-		rc = hdev->session_flush(inst->session,
+		rc = call_hfi_op(hdev, session_flush, inst->session,
 				HAL_FLUSH_ALL);
 	}
 	mutex_unlock(&inst->sync_lock);
@@ -2209,6 +2223,9 @@
 	case V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER:
 		ret = HAL_EXTRADATA_METADATA_FILLER;
 		break;
+	case V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO:
+		ret = HAL_EXTRADATA_ASPECT_RATIO;
+		break;
 	default:
 		dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
 		break;
@@ -2227,6 +2244,7 @@
 	}
 	hdev = core->device;
 	if (core->state == VIDC_CORE_INIT_DONE)
-		rc = hdev->core_trigger_ssr(hdev->hfi_device_data, type);
+		rc = call_hfi_op(hdev, core_trigger_ssr,
+				hdev->hfi_device_data, type);
 	return rc;
 }
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
similarity index 100%
rename from drivers/media/video/msm_vidc/msm_vidc_common.h
rename to drivers/media/platform/msm/vidc/msm_vidc_common.h
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
similarity index 96%
rename from drivers/media/video/msm_vidc/msm_vidc_debug.c
rename to drivers/media/platform/msm/vidc/msm_vidc_debug.c
index 0a2075d..b713d8b 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -67,13 +67,17 @@
 	write_str(&dbg_buf, "===============================\n");
 	write_str(&dbg_buf, "state: %d\n", core->state);
 	write_str(&dbg_buf, "base addr: 0x%x\n",
-		hdev->get_fw_info(hdev->hfi_device_data, FW_BASE_ADDRESS));
+		call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data,
+					FW_BASE_ADDRESS));
 	write_str(&dbg_buf, "register_base: 0x%x\n",
-		hdev->get_fw_info(hdev->hfi_device_data, FW_REGISTER_BASE));
+		call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data,
+					FW_REGISTER_BASE));
 	write_str(&dbg_buf, "register_size: %u\n",
-		hdev->get_fw_info(hdev->hfi_device_data, FW_REGISTER_SIZE));
+		call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data,
+					FW_REGISTER_SIZE));
 	write_str(&dbg_buf, "irq: %u\n",
-		hdev->get_fw_info(hdev->hfi_device_data, FW_IRQ));
+		call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data,
+					FW_IRQ));
 	for (i = SYS_MSG_START; i < SYS_MSG_END; i++) {
 		write_str(&dbg_buf, "completions[%d]: %s\n", i,
 			completion_done(&core->completions[SYS_MSG_INDEX(i)]) ?
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
similarity index 100%
rename from drivers/media/video/msm_vidc/msm_vidc_debug.h
rename to drivers/media/platform/msm/vidc/msm_vidc_debug.h
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
similarity index 97%
rename from drivers/media/video/msm_vidc/msm_vidc_internal.h
rename to drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 16bf753..c03a4c4 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -15,7 +15,6 @@
 #define _MSM_VIDC_INTERNAL_H_
 
 #include <linux/list.h>
-#include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/completion.h>
 #include <linux/wait.h>
@@ -106,7 +105,7 @@
 };
 
 struct msm_vidc_drv {
-	spinlock_t lock;
+	struct mutex lock;
 	struct list_head cores;
 	int num_cores;
 	struct dentry *debugfs_root;
@@ -168,22 +167,22 @@
 
 struct msm_vidc_core {
 	struct list_head list;
-	struct mutex sync_lock;
+	struct mutex sync_lock, lock;
 	int id;
 	void *device;
 	struct msm_video_device vdev[MSM_VIDC_MAX_DEVICES];
 	struct v4l2_device v4l2_dev;
-	spinlock_t lock;
 	struct list_head instances;
 	struct dentry *debugfs_root;
 	enum vidc_core_state state;
 	struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
 	enum msm_vidc_hfi_type hfi_type;
+	struct msm_vidc_platform_resources resources;
 };
 
 struct msm_vidc_inst {
 	struct list_head list;
-	struct mutex sync_lock;
+	struct mutex sync_lock, lock;
 	struct msm_vidc_core *core;
 	int session_type;
 	void *session;
@@ -191,7 +190,6 @@
 	int state;
 	const struct msm_vidc_format *fmts[MAX_PORT_NUM];
 	struct buf_queue bufq[MAX_PORT_NUM];
-	spinlock_t lock;
 	struct list_head pendingq;
 	struct list_head internalbufs;
 	struct list_head persistbufs;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
new file mode 100644
index 0000000..ca8af9c
--- /dev/null
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -0,0 +1,49 @@
+/* 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_VIDC_RESOURCES_H__
+#define __MSM_VIDC_RESOURCES_H__
+
+#include <linux/platform_device.h>
+#include <media/msm_vidc.h>
+
+struct load_freq_table {
+	u32 load;
+	u32 freq;
+};
+
+struct reg_value_pair {
+	u32 reg;
+	u32 value;
+};
+
+struct reg_set {
+	struct reg_value_pair *reg_tbl;
+	int count;
+};
+
+struct msm_vidc_platform_resources {
+	uint32_t fw_base_addr;
+	uint32_t register_base;
+	uint32_t register_size;
+	uint32_t irq;
+	struct load_freq_table *load_freq_tbl;
+	uint32_t load_freq_tbl_size;
+	struct msm_vidc_iommu_info *iommu_maps;
+	uint32_t iommu_maps_size;
+	struct reg_set reg_set;
+	struct platform_device *pdev;
+};
+
+#endif
+
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
new file mode 100644
index 0000000..25cc239
--- /dev/null
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -0,0 +1,1258 @@
+/* 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/slab.h>
+#include <mach/qdsp6v2/apr.h>
+#include <mach/subsystem_restart.h>
+#include "hfi_packetization.h"
+#include "msm_vidc_debug.h"
+#include "q6_hfi.h"
+#include "vidc_hfi_api.h"
+
+
+static int write_queue(void *info, u8 *packet)
+{
+	u32 packet_size_in_words, new_write_idx;
+	struct q6_iface_q_info *qinfo;
+	u32 empty_space, read_idx;
+	u32 *write_ptr;
+
+	if (!info || !packet) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+
+	qinfo = (struct q6_iface_q_info *) info;
+
+	packet_size_in_words = (*(u32 *)packet) >> 2;
+
+	if (packet_size_in_words == 0) {
+		dprintk(VIDC_ERR, "Zero packet size");
+		return -ENODATA;
+	}
+
+	read_idx = qinfo->read_idx;
+
+	empty_space = (qinfo->write_idx >=  read_idx) ?
+		(qinfo->q_size - (qinfo->write_idx -  read_idx)) :
+		(read_idx - qinfo->write_idx);
+	if (empty_space <= packet_size_in_words) {
+		dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)",
+					  empty_space, packet_size_in_words);
+		return -ENOTEMPTY;
+	}
+
+	new_write_idx = (qinfo->write_idx + packet_size_in_words);
+	write_ptr = (u32 *)(qinfo->buffer + (qinfo->write_idx << 2));
+	if (new_write_idx < qinfo->q_size) {
+		memcpy(write_ptr, packet, packet_size_in_words << 2);
+	} else {
+		new_write_idx -= qinfo->q_size;
+		memcpy(write_ptr, packet, (packet_size_in_words -
+			new_write_idx) << 2);
+		memcpy((void *)qinfo->buffer,
+			packet + ((packet_size_in_words - new_write_idx) << 2),
+			new_write_idx  << 2);
+	}
+	qinfo->write_idx = new_write_idx;
+	return 0;
+}
+
+static int read_queue(void *info, u8 *packet)
+{
+	u32 packet_size_in_words, new_read_idx;
+	u32 *read_ptr;
+	struct q6_iface_q_info *qinfo;
+
+	if (!info || !packet) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+
+	qinfo = (struct q6_iface_q_info *) info;
+
+	if (qinfo->read_idx == qinfo->write_idx)
+		return -EPERM;
+
+	read_ptr = (u32 *)(qinfo->buffer + (qinfo->read_idx << 2));
+	packet_size_in_words = (*read_ptr) >> 2;
+	if (packet_size_in_words == 0) {
+		dprintk(VIDC_ERR, "Zero packet size");
+		return -ENODATA;
+	}
+
+	new_read_idx = qinfo->read_idx + packet_size_in_words;
+	if (new_read_idx < qinfo->q_size) {
+		memcpy(packet, read_ptr,
+			packet_size_in_words << 2);
+	} else {
+		new_read_idx -= qinfo->q_size;
+		memcpy(packet, read_ptr,
+			(packet_size_in_words - new_read_idx) << 2);
+		memcpy(packet + ((packet_size_in_words -
+			new_read_idx) << 2),
+			(u8 *)qinfo->buffer,
+			new_read_idx << 2);
+	}
+
+	qinfo->read_idx = new_read_idx;
+	return 0;
+}
+
+static int q6_hfi_iface_eventq_write(struct q6_hfi_device *device, void *pkt)
+{
+	struct q6_iface_q_info *q_info;
+	int rc = 0;
+	unsigned long flags = 0;
+
+	if (!device || !pkt) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+
+	q_info = &device->event_queue;
+	if (!q_info->buffer) {
+		dprintk(VIDC_ERR, "cannot write to shared Q");
+		rc = -ENODATA;
+		goto err_q_write;
+	}
+
+	spin_lock_irqsave(&q_info->lock, flags);
+	rc = write_queue(q_info, (u8 *)pkt);
+	if (rc)
+		dprintk(VIDC_ERR, "q6_hfi_iface_eventq_write: queue_full");
+
+	spin_unlock_irqrestore(&q_info->lock, flags);
+err_q_write:
+	return rc;
+}
+
+static int q6_hfi_iface_eventq_read(struct q6_hfi_device *device, void *pkt)
+{
+	int rc = 0;
+	struct q6_iface_q_info *q_info;
+	unsigned long flags = 0;
+
+	if (!pkt) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+
+	q_info = &device->event_queue;
+
+	if (!q_info->buffer) {
+		dprintk(VIDC_ERR, "cannot read from shared Q");
+		rc = -ENODATA;
+		goto read_error;
+	}
+
+	spin_lock_irqsave(&q_info->lock, flags);
+	rc = read_queue(q_info, (u8 *)pkt);
+	if (rc) {
+		dprintk(VIDC_INFO, "q6_hfi_iface_eventq_read:queue_empty");
+		rc = -ENODATA;
+	}
+	spin_unlock_irqrestore(&q_info->lock, flags);
+
+read_error:
+	return rc;
+}
+
+static void q6_hfi_core_work_handler(struct work_struct *work)
+{
+	int rc = 0;
+	struct q6_hfi_device *device = container_of(
+		work, struct q6_hfi_device, vidc_worker);
+	u8 packet[VIDC_IFACEQ_MED_PKT_SIZE];
+
+	/* need to consume all the messages from the firmware */
+	do {
+		rc = q6_hfi_iface_eventq_read(device, packet);
+		if (!rc)
+			hfi_process_msg_packet(device->callback,
+				device->device_id,
+				(struct vidc_hal_msg_pkt_hdr *) packet);
+	} while (!rc);
+
+	if (rc != -ENODATA)
+		dprintk(VIDC_ERR, "Failed to read from event queue");
+}
+
+static int q6_hfi_register_iommu_domains(struct q6_hfi_device *device)
+{
+	(void)device;
+
+	dprintk(VIDC_ERR, "Not implemented: %s", __func__);
+
+	return 0;
+}
+
+static int q6_hfi_init_resources(struct q6_hfi_device *device)
+{
+	int rc = 0;
+
+	rc = q6_hfi_register_iommu_domains(device);
+	if (rc)
+		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
+
+	return rc;
+}
+
+static void *q6_hfi_add_device(u32 device_id,
+			hfi_cmd_response_callback callback)
+{
+	struct q6_hfi_device *hdevice = NULL;
+
+	if (device_id || !callback) {
+		dprintk(VIDC_ERR, "Invalid Paramters");
+		return NULL;
+	}
+
+	hdevice = (struct q6_hfi_device *)
+			kzalloc(sizeof(struct q6_hfi_device), GFP_KERNEL);
+	if (!hdevice) {
+		dprintk(VIDC_ERR, "failed to allocate new device");
+		goto err_alloc;
+	}
+
+	INIT_LIST_HEAD(&hal_ctxt.dev_head);
+	INIT_LIST_HEAD(&hdevice->list);
+	hdevice->device_id = device_id;
+	hdevice->callback = callback;
+
+	INIT_WORK(&hdevice->vidc_worker, q6_hfi_core_work_handler);
+	hdevice->vidc_workq = create_singlethread_workqueue(
+		"msm_vidc_workerq");
+	if (!hdevice->vidc_workq) {
+		dprintk(VIDC_ERR, ": create workq failed\n");
+		goto error_createq;
+	}
+
+	list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
+	hal_ctxt.dev_count++;
+
+	return (void *) hdevice;
+error_createq:
+	kfree(hdevice);
+err_alloc:
+	return NULL;
+}
+
+static void *q6_hfi_get_device(u32 device_id,
+				hfi_cmd_response_callback callback)
+{
+	struct q6_hfi_device *device;
+	int rc = 0;
+
+	if (!callback) {
+		dprintk(VIDC_ERR, "%s Invalid params:  %p\n",
+			__func__, callback);
+		return NULL;
+	}
+
+	device = q6_hfi_add_device(device_id, &handle_cmd_response);
+	if (!device) {
+		dprintk(VIDC_ERR, "Failed to create HFI device\n");
+		return NULL;
+	}
+
+	rc = q6_hfi_init_resources(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
+		goto err_fail_init_res;
+	}
+	return device;
+
+err_fail_init_res:
+	q6_hfi_delete_device(device);
+	return NULL;
+}
+
+void q6_hfi_delete_device(void *device)
+{
+	struct q6_hfi_device *close, *dev;
+
+	if (device) {
+		dev = (struct q6_hfi_device *) device;
+		list_for_each_entry(close, &hal_ctxt.dev_head, list) {
+				hal_ctxt.dev_count--;
+				list_del(&close->list);
+				destroy_workqueue(close->vidc_workq);
+				kfree(close);
+		}
+
+	}
+}
+
+static inline void q6_hfi_add_apr_hdr(struct q6_hfi_device *dev,
+			struct apr_hdr *hdr, u32 pkt_size, u32 opcode)
+{
+	hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(sizeof(struct apr_hdr)),
+				APR_PKT_VER);
+
+	hdr->src_svc = ((struct apr_svc *)dev->apr)->id;
+	hdr->src_domain = APR_DOMAIN_APPS;
+	hdr->dest_svc = APR_SVC_VIDC;
+	hdr->src_port = 0;
+	hdr->dest_port = 0;
+	hdr->pkt_size  = pkt_size;
+	hdr->token = 0;
+	hdr->opcode = opcode;
+}
+
+static int q6_hfi_apr_callback(struct apr_client_data *data, void *priv)
+{
+	struct q6_hfi_device *device = priv;
+	int rc = 0;
+
+	if (!data || !device || !data->payload_size) {
+		dprintk(VIDC_ERR, "%s - Invalid arguments", __func__);
+		return -EINVAL;
+	}
+
+	dprintk(VIDC_DBG, "%s opcode = %u payload size = %u", __func__,
+				data->opcode, data->payload_size);
+
+	rc = q6_hfi_iface_eventq_write(device, data->payload);
+	if (rc) {
+		dprintk(VIDC_ERR, "%s failed to write to event queue",
+				__func__);
+		return rc;
+	}
+	queue_work(device->vidc_workq, &device->vidc_worker);
+	return 0;
+}
+
+static void q6_release_event_queue(struct q6_hfi_device *device)
+{
+	kfree(device->event_queue.buffer);
+	device->event_queue.buffer = NULL;
+	device->event_queue.q_size = 0;
+	device->event_queue.read_idx = 0;
+	device->event_queue.write_idx = 0;
+}
+
+static int q6_init_event_queue(struct q6_hfi_device *dev)
+{
+	struct q6_iface_q_info *iface_q;
+
+	if (!dev) {
+		dprintk(VIDC_ERR, "Invalid device");
+		return -EINVAL;
+	}
+
+	iface_q = &dev->event_queue;
+	iface_q->buffer = kzalloc(Q6_IFACEQ_QUEUE_SIZE, GFP_KERNEL);
+	if (!iface_q->buffer) {
+		dprintk(VIDC_ERR, "iface_q alloc failed");
+		q6_release_event_queue(dev);
+		return -ENOMEM;
+	} else {
+		iface_q->q_size = Q6_IFACEQ_QUEUE_SIZE / 4;
+		iface_q->read_idx = 0;
+		iface_q->write_idx = 0;
+		spin_lock_init(&iface_q->lock);
+	}
+	return 0;
+}
+
+static int q6_hfi_core_init(void *device)
+{
+	struct q6_apr_cmd_sys_init_packet apr;
+	int rc = 0;
+	struct q6_hfi_device *dev = device;
+
+	if (!dev) {
+		dprintk(VIDC_ERR, "%s: invalid argument\n", __func__);
+		return -ENODEV;
+	}
+
+	INIT_LIST_HEAD(&dev->sess_head);
+
+	if (!dev->event_queue.buffer) {
+		rc = q6_init_event_queue(dev);
+		if (rc) {
+			dprintk(VIDC_ERR, "q6_init_event_queue failed");
+			goto err_core_init;
+		}
+	} else {
+		dprintk(VIDC_ERR, "queue buffer exists");
+		rc = -EEXIST;
+		goto err_core_init;
+	}
+
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr), HFI_CMD_SYS_INIT);
+
+	rc = create_pkt_cmd_sys_init(&apr.pkt, HFI_ARCH_OX_OFFSET);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to create sys init pkt");
+		goto err_core_init;
+	}
+
+	rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
+	if (rc != apr.hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+err_core_init:
+	return rc;
+}
+
+static int q6_hfi_core_release(void *device)
+{
+	struct q6_hfi_device *dev = device;
+
+	if (!dev) {
+		dprintk(VIDC_ERR, "%s: invalid argument\n", __func__);
+		return -ENODEV;
+	}
+	q6_release_event_queue(dev);
+
+	dprintk(VIDC_DBG, "HAL exited\n");
+	return 0;
+}
+
+static int q6_hfi_core_pc_prep(void *device)
+{
+	(void) device;
+
+	/* Q6 does not support core_pc_prep*/
+	return 0;
+}
+
+static int q6_hfi_core_ping(void *device)
+{
+	(void) device;
+
+	/* Q6 does not support cmd_sys_ping */
+	return 0;
+}
+
+static void *q6_hfi_session_init(void *device, u32 session_id,
+	enum hal_domain session_type, enum hal_video_codec codec_type)
+{
+	struct q6_apr_cmd_sys_session_init_packet apr;
+	struct hal_session *new_session;
+	struct q6_hfi_device *dev = device;
+	int rc = 0;
+
+	if (!dev) {
+		dprintk(VIDC_ERR, "%s: invalid argument\n", __func__);
+		return NULL;
+	}
+
+	new_session = (struct hal_session *)
+		kzalloc(sizeof(struct hal_session), GFP_KERNEL);
+	new_session->session_id = (u32) session_id;
+	if (session_type == 1)
+		new_session->is_decoder = 0;
+	else if (session_type == 2)
+		new_session->is_decoder = 1;
+	new_session->device = dev;
+
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
+				   HFI_CMD_SYS_SESSION_INIT);
+
+	if (create_pkt_cmd_sys_session_init(&apr.pkt, (u32)new_session,
+					session_type, codec_type)) {
+		dprintk(VIDC_ERR, "session_init: failed to create packet");
+		goto err_session_init;
+	}
+
+	rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
+	if (rc != apr.hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+		goto err_session_init;
+	}
+	list_add_tail(&new_session->list, &dev->sess_head);
+	return new_session;
+
+err_session_init:
+	kfree(new_session);
+	return NULL;
+}
+
+static int q6_hal_send_session_cmd(void *sess,
+	 int pkt_type)
+{
+	struct q6_apr_session_cmd_pkt apr;
+	int rc = 0;
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !session->device) {
+		dprintk(VIDC_ERR, "%s: invalid arguments\n", __func__);
+		return -EINVAL;
+	}
+	dev = session->device;
+
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr), pkt_type);
+
+	rc = create_pkt_cmd_session_cmd(&apr.pkt, pkt_type, (u32)session);
+	if (rc) {
+		dprintk(VIDC_ERR, "send session cmd: create pkt failed");
+		goto err_create_pkt;
+	}
+
+	rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
+	if (rc != apr.hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_end(void *session)
+{
+	return q6_hal_send_session_cmd(session,
+		HFI_CMD_SYS_SESSION_END);
+}
+
+static int q6_hfi_session_abort(void *session)
+{
+	return q6_hal_send_session_cmd(session,
+		HFI_CMD_SYS_SESSION_ABORT);
+}
+
+static int q6_hfi_session_set_buffers(void *sess,
+	struct vidc_buffer_addr_info *buffer_info)
+{
+	struct q6_apr_cmd_session_set_buffers_packet *apr;
+	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+	int rc = 0;
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !buffer_info || !session->device) {
+		dprintk(VIDC_ERR, "%s: invalid arguments\n", __func__);
+		return -EINVAL;
+	}
+	dev = session->device;
+
+	if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
+		return 0;
+	apr = (struct q6_apr_cmd_session_set_buffers_packet *)packet;
+
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE,
+			HFI_CMD_SESSION_SET_BUFFERS);
+
+	rc = create_pkt_cmd_session_set_buffers(&apr->pkt,
+			(u32)session, buffer_info);
+	if (rc) {
+		dprintk(VIDC_ERR, "set buffers: failed to create packet");
+		goto err_create_pkt;
+	}
+
+	dprintk(VIDC_INFO, "set buffers: 0x%x", buffer_info->buffer_type);
+	rc = apr_send_pkt(dev->apr, (uint32_t *)apr);
+	if (rc != apr->hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_release_buffers(void *sess,
+	struct vidc_buffer_addr_info *buffer_info)
+{
+	struct q6_apr_cmd_session_release_buffer_packet *apr;
+	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+	int rc = 0;
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !buffer_info || !session->device) {
+		dprintk(VIDC_ERR, "%s: invalid arguments\n", __func__);
+		return -EINVAL;
+	}
+
+	dev = session->device;
+
+	if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
+		return 0;
+
+	apr = (struct q6_apr_cmd_session_release_buffer_packet *) packet;
+
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE,
+					   HFI_CMD_SESSION_RELEASE_BUFFERS);
+
+	rc = create_pkt_cmd_session_release_buffers(&apr->pkt,
+					(u32)session, buffer_info);
+	if (rc) {
+		dprintk(VIDC_ERR, "release buffers: failed to create packet");
+		goto err_create_pkt;
+	}
+
+	dprintk(VIDC_INFO, "Release buffers: 0x%x", buffer_info->buffer_type);
+	rc = apr_send_pkt(dev->apr, (uint32_t *)apr);
+
+	if (rc != apr->hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_load_res(void *sess)
+{
+	return q6_hal_send_session_cmd(sess,
+		HFI_CMD_SESSION_LOAD_RESOURCES);
+}
+
+static int q6_hfi_session_release_res(void *sess)
+{
+	return q6_hal_send_session_cmd(sess,
+		HFI_CMD_SESSION_RELEASE_RESOURCES);
+}
+
+static int q6_hfi_session_start(void *sess)
+{
+	return q6_hal_send_session_cmd(sess,
+		HFI_CMD_SESSION_START);
+}
+
+static int q6_hfi_session_stop(void *sess)
+{
+	return q6_hal_send_session_cmd(sess,
+		HFI_CMD_SESSION_STOP);
+}
+
+static int q6_hfi_session_suspend(void *sess)
+{
+	return q6_hal_send_session_cmd(sess,
+		HFI_CMD_SESSION_SUSPEND);
+}
+
+static int q6_hfi_session_resume(void *sess)
+{
+	return q6_hal_send_session_cmd(sess,
+		HFI_CMD_SESSION_RESUME);
+}
+
+static int q6_hfi_session_etb(void *sess,
+			struct vidc_frame_data *input_frame)
+{
+	int rc = 0;
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !input_frame || !session->device) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+
+	dev = session->device;
+
+	if (session->is_decoder) {
+		struct q6_apr_cmd_session_empty_buffer_compressed_packet apr;
+		q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
+					   HFI_CMD_SESSION_EMPTY_BUFFER);
+
+		rc = create_pkt_cmd_session_etb_decoder(&apr.pkt,
+					(u32)session, input_frame);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Session etb decoder: failed to create pkt");
+			goto err_create_pkt;
+		}
+		dprintk(VIDC_DBG, "Q DECODER INPUT BUFFER");
+		dprintk(VIDC_DBG, "addr = 0x%x ts = %lld",
+			input_frame->device_addr, input_frame->timestamp);
+		rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
+		if (rc != apr.hdr.pkt_size) {
+			dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+					__func__, rc);
+			rc = -EBADE;
+		} else
+			rc = 0;
+	} else {
+		struct
+		q6_apr_cmd_session_empty_buffer_uncompressed_plane0_packet apr;
+		q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
+				   HFI_CMD_SESSION_EMPTY_BUFFER);
+
+		rc =  create_pkt_cmd_session_etb_encoder(&apr.pkt,
+					(u32)session, input_frame);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Session etb encoder: failed to create pkt");
+			goto err_create_pkt;
+		}
+		dprintk(VIDC_DBG, "Q ENCODER INPUT BUFFER");
+		rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
+		if (rc != apr.hdr.pkt_size) {
+			dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+					__func__, rc);
+			rc = -EBADE;
+		} else
+			rc = 0;
+	}
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_ftb(void *sess,
+	struct vidc_frame_data *output_frame)
+{
+	struct q6_apr_cmd_session_fill_buffer_packet apr;
+	int rc = 0;
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !output_frame || !session->device) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	dev = session->device;
+
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
+				   HFI_CMD_SESSION_FILL_BUFFER);
+
+	rc = create_pkt_cmd_session_ftb(&apr.pkt, (u32)session, output_frame);
+	if (rc) {
+		dprintk(VIDC_ERR, "Session ftb: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	dprintk(VIDC_INFO, "Q OUTPUT BUFFER");
+	rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
+	if (rc != apr.hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_parse_seq_hdr(void *sess,
+	struct vidc_seq_hdr *seq_hdr)
+{
+	struct q6_apr_cmd_session_parse_sequence_header_packet *apr;
+	int rc = 0;
+	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !seq_hdr || !session->device) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	dev = session->device;
+
+	apr = (struct q6_apr_cmd_session_parse_sequence_header_packet *) packet;
+
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_SMALL_PKT_SIZE,
+			   HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER);
+
+	rc = create_pkt_cmd_session_parse_seq_header(&apr->pkt,
+					(u32)session, seq_hdr);
+	if (rc) {
+		dprintk(VIDC_ERR,
+			"Session parse seq hdr: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	rc = apr_send_pkt(dev->apr, (uint32_t *)apr);
+	if (rc != apr->hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_get_seq_hdr(void *sess,
+	struct vidc_seq_hdr *seq_hdr)
+{
+	struct q6_apr_cmd_session_get_sequence_header_packet *apr;
+	int rc = 0;
+	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !seq_hdr || !session->device) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	dev = session->device;
+
+	apr = (struct q6_apr_cmd_session_get_sequence_header_packet *) packet;
+
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_SMALL_PKT_SIZE,
+				   HFI_CMD_SESSION_GET_SEQUENCE_HEADER);
+
+	rc = create_pkt_cmd_session_get_seq_hdr(&apr->pkt, (u32)session,
+						seq_hdr);
+	if (rc) {
+		dprintk(VIDC_ERR, "Session get seq hdr: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	rc = apr_send_pkt(dev->apr, (uint32_t *)apr);
+	if (rc != apr->hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_get_buf_req(void *sess)
+{
+	struct q6_apr_cmd_session_get_property_packet apr;
+	int rc = 0;
+	struct hal_session *session = sess;
+
+	struct q6_hfi_device *dev;
+
+	if (!session || !session->device) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	dev = session->device;
+
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
+				   HFI_CMD_SESSION_GET_PROPERTY);
+
+	rc = create_pkt_cmd_session_get_buf_req(&apr.pkt, (u32)session);
+	if (rc) {
+		dprintk(VIDC_ERR, "Session get buf req: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
+	if (rc != apr.hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_flush(void *sess, enum hal_flush flush_mode)
+{
+	struct q6_apr_cmd_session_flush_packet apr;
+	int rc = 0;
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !session->device) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	dev = session->device;
+
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
+				   HFI_CMD_SESSION_FLUSH);
+
+	rc = create_pkt_cmd_session_flush(&apr.pkt, (u32)session, flush_mode);
+	if (rc) {
+		dprintk(VIDC_ERR, "Session flush: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	rc = apr_send_pkt(dev->apr, (uint32_t *)&apr);
+	if (rc != apr.hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_set_property(void *sess,
+	enum hal_property ptype, void *pdata)
+{
+	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+	struct q6_apr_cmd_session_set_property_packet *apr =
+		(struct q6_apr_cmd_session_set_property_packet *) &packet;
+	struct hal_session *session = sess;
+	int rc = 0;
+	struct q6_hfi_device *dev;
+
+	if (!session || !pdata || !session->device) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	dev = session->device;
+	dprintk(VIDC_DBG, "in set_prop,with prop id: 0x%x", ptype);
+
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE,
+				 HFI_CMD_SESSION_SET_PROPERTY);
+
+	rc = create_pkt_cmd_session_set_property(&apr->pkt,
+				(u32)session, ptype, pdata);
+	if (rc) {
+		dprintk(VIDC_ERR, "set property: failed to create packet");
+		goto err_create_pkt;
+	}
+
+	rc = apr_send_pkt(dev->apr, (uint32_t *)apr);
+	if (rc != apr->hdr.pkt_size) {
+		dprintk(VIDC_ERR, "%s: apr_send_pkt failed rc: %d",
+				__func__, rc);
+		rc = -EBADE;
+	} else
+		rc = 0;
+
+err_create_pkt:
+	return rc;
+}
+
+static int q6_hfi_session_get_property(void *sess,
+	enum hal_property ptype, void *pdata)
+{
+	struct hal_session *session = sess;
+	struct q6_hfi_device *dev;
+
+	if (!session || !pdata || !session->device) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	dev = session->device;
+
+	dprintk(VIDC_DBG, "IN func: , with property id: %d", ptype);
+
+	switch (ptype) {
+	case HAL_CONFIG_FRAME_RATE:
+		break;
+	case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
+		break;
+	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
+		break;
+	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
+		break;
+	case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
+		break;
+	case HAL_PARAM_FRAME_SIZE:
+		break;
+	case HAL_CONFIG_REALTIME:
+		break;
+	case HAL_PARAM_BUFFER_COUNT_ACTUAL:
+		break;
+	case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
+		break;
+	case HAL_PARAM_VDEC_OUTPUT_ORDER:
+		break;
+	case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
+		break;
+	case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
+		break;
+	case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
+		break;
+	case HAL_PARAM_VDEC_MULTI_STREAM:
+		break;
+	case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
+		break;
+	case HAL_PARAM_DIVX_FORMAT:
+		break;
+	case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
+		break;
+	case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
+		break;
+	case HAL_CONFIG_VDEC_MB_ERROR_MAP:
+		break;
+	case HAL_CONFIG_VENC_REQUEST_IFRAME:
+		break;
+	case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
+		break;
+	case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
+		break;
+	case HAL_CONFIG_VENC_TARGET_BITRATE:
+		break;
+	case HAL_PARAM_PROFILE_LEVEL_CURRENT:
+		break;
+	case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
+		break;
+	case HAL_PARAM_VENC_RATE_CONTROL:
+		break;
+	case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
+		break;
+	case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
+		break;
+	case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
+		break;
+	case HAL_PARAM_VENC_SESSION_QP:
+		break;
+	case HAL_CONFIG_VENC_INTRA_PERIOD:
+		break;
+	case HAL_CONFIG_VENC_IDR_PERIOD:
+		break;
+	case HAL_CONFIG_VPE_OPERATIONS:
+		break;
+	case HAL_PARAM_VENC_INTRA_REFRESH:
+		break;
+	case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
+		break;
+	case HAL_CONFIG_VPE_DEINTERLACE:
+		break;
+	case HAL_SYS_DEBUG_CONFIG:
+		break;
+	/*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
+	case HAL_CONFIG_BUFFER_REQUIREMENTS:
+	case HAL_CONFIG_PRIORITY:
+	case HAL_CONFIG_BATCH_INFO:
+	case HAL_PARAM_METADATA_PASS_THROUGH:
+	case HAL_SYS_IDLE_INDICATOR:
+	case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
+	case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
+	case HAL_PARAM_CHROMA_SITE:
+	case HAL_PARAM_PROPERTIES_SUPPORTED:
+	case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
+	case HAL_PARAM_CAPABILITY_SUPPORTED:
+	case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
+	case HAL_PARAM_MULTI_VIEW_FORMAT:
+	case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
+	case HAL_PARAM_CODEC_SUPPORTED:
+	case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
+	case HAL_PARAM_VDEC_MB_QUANTIZATION:
+	case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
+	case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
+	case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
+	case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
+
+	case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
+	case HAL_CONFIG_VDEC_MULTI_STREAM:
+	case HAL_PARAM_VENC_MULTI_SLICE_INFO:
+	case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
+	case HAL_PARAM_VENC_LOW_LATENCY:
+	default:
+		dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
+		break;
+	}
+	return 0;
+}
+
+static int q6_hfi_scale_clocks(void *dev, int load)
+{
+	(void)dev;
+	(void)load;
+
+	/* Q6 does not support clocks scaling */
+	return 0;
+}
+
+static int q6_hfi_scale_bus(void *dev, int load,
+			enum session_type type, enum mem_type mtype)
+{
+	(void)dev;
+	(void)load;
+	(void)type;
+	(void)mtype;
+
+	/* Q6 does not support bus scaling */
+	return 0;
+
+}
+
+static int q6_hfi_unset_ocmem(void *dev)
+{
+	(void)dev;
+
+	/* Q6 does not support ocmem */
+	return -EINVAL;
+}
+
+static int q6_hfi_alloc_ocmem(void *dev, unsigned long size)
+{
+	(void)dev;
+	(void)size;
+
+	/* Q6 does not support ocmem */
+	return 0;
+}
+
+static int q6_hfi_free_ocmem(void *dev)
+{
+	(void)dev;
+
+	/* Q6 does not support ocmem */
+	return 0;
+}
+
+static int q6_hfi_is_ocmem_present(void *dev)
+{
+	(void)dev;
+
+	/* Q6 does not support ocmem */
+	return 0;
+}
+
+static int q6_hfi_get_domain(void *dev, enum msm_vidc_io_maps iomap)
+{
+	(void)dev;
+	(void)iomap;
+
+	dprintk(VIDC_ERR, "Not implemented: %s", __func__);
+
+	return 0;
+}
+
+static int q6_hfi_iommu_get_map(void *dev,
+			struct msm_vidc_iommu_info maps[MAX_MAP])
+{
+	(void)dev;
+	(void)maps;
+
+	dprintk(VIDC_ERR, "Not implemented: %s", __func__);
+
+	return 0;
+}
+
+static int q6_hfi_iommu_attach(void *dev)
+{
+	(void)dev;
+
+	dprintk(VIDC_ERR, "Not implemented: %s", __func__);
+
+	return 0;
+}
+
+static int q6_hfi_load_fw(void *dev)
+{
+	int rc = 0;
+	struct q6_hfi_device *device = dev;
+
+	if (!device)
+		return -EINVAL;
+
+	/*Set Q6 to loaded state*/
+	apr_set_q6_state(APR_SUBSYS_LOADED);
+
+	device->apr = apr_register("ADSP", "VIDC",
+				(apr_fn)q6_hfi_apr_callback,
+				0xFFFFFFFF,
+				device);
+
+	if (device->apr == NULL) {
+		dprintk(VIDC_ERR, "Failed to register with QDSP6");
+		rc = -EINVAL;
+		goto fail_apr_register;
+	}
+
+	rc = q6_hfi_iommu_attach(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to attach iommu");
+		goto fail_iommu_attach;
+	}
+
+	return rc;
+
+fail_iommu_attach:
+	apr_deregister(device->apr);
+fail_apr_register:
+	subsystem_put(device->resources.fw.cookie);
+	device->resources.fw.cookie = NULL;
+	return rc;
+}
+
+static void q6_hfi_unload_fw(void *hfi_device_data)
+{
+	struct q6_hfi_device *device = hfi_device_data;
+
+	if (!device)
+		return;
+	if (device->apr)
+		apr_deregister(device->apr);
+}
+
+static int q6_hfi_get_fw_info(void *dev, enum fw_info info)
+{
+	(void)dev;
+	(void)info;
+
+	return 0;
+}
+
+static void q6_init_hfi_callbacks(struct hfi_device *hdev)
+{
+	hdev->core_init = q6_hfi_core_init;
+	hdev->core_release = q6_hfi_core_release;
+	hdev->core_pc_prep = q6_hfi_core_pc_prep;
+	hdev->core_ping = q6_hfi_core_ping;
+	hdev->session_init = q6_hfi_session_init;
+	hdev->session_end = q6_hfi_session_end;
+	hdev->session_abort = q6_hfi_session_abort;
+	hdev->session_set_buffers = q6_hfi_session_set_buffers;
+	hdev->session_release_buffers = q6_hfi_session_release_buffers;
+	hdev->session_load_res = q6_hfi_session_load_res;
+	hdev->session_release_res = q6_hfi_session_release_res;
+	hdev->session_start = q6_hfi_session_start;
+	hdev->session_stop = q6_hfi_session_stop;
+	hdev->session_suspend = q6_hfi_session_suspend;
+	hdev->session_resume = q6_hfi_session_resume;
+	hdev->session_etb = q6_hfi_session_etb;
+	hdev->session_ftb = q6_hfi_session_ftb;
+	hdev->session_parse_seq_hdr = q6_hfi_session_parse_seq_hdr;
+	hdev->session_get_seq_hdr = q6_hfi_session_get_seq_hdr;
+	hdev->session_get_buf_req = q6_hfi_session_get_buf_req;
+	hdev->session_flush = q6_hfi_session_flush;
+	hdev->session_set_property = q6_hfi_session_set_property;
+	hdev->session_get_property = q6_hfi_session_get_property;
+	hdev->scale_clocks = q6_hfi_scale_clocks;
+	hdev->scale_bus = q6_hfi_scale_bus;
+	hdev->unset_ocmem = q6_hfi_unset_ocmem;
+	hdev->alloc_ocmem = q6_hfi_alloc_ocmem;
+	hdev->free_ocmem = q6_hfi_free_ocmem;
+	hdev->is_ocmem_present = q6_hfi_is_ocmem_present;
+	hdev->get_domain = q6_hfi_get_domain;
+	hdev->iommu_get_map = q6_hfi_iommu_get_map;
+	hdev->load_fw = q6_hfi_load_fw;
+	hdev->unload_fw = q6_hfi_unload_fw;
+	hdev->get_fw_info = q6_hfi_get_fw_info;
+}
+
+
+int q6_hfi_initialize(struct hfi_device *hdev, u32 device_id,
+		hfi_cmd_response_callback callback)
+{
+	int rc = 0;
+
+	if (!hdev || !callback) {
+		dprintk(VIDC_ERR, "Invalid params: %p %p\n", hdev, callback);
+		rc = -EINVAL;
+		goto err_hfi_init;
+	}
+	hdev->hfi_device_data = q6_hfi_get_device(device_id, callback);
+
+	q6_init_hfi_callbacks(hdev);
+
+err_hfi_init:
+	return rc;
+}
+
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.h b/drivers/media/platform/msm/vidc/q6_hfi.h
new file mode 100644
index 0000000..551eb04
--- /dev/null
+++ b/drivers/media/platform/msm/vidc/q6_hfi.h
@@ -0,0 +1,116 @@
+/* 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 __Q6_HFI_H__
+#define __Q6_HFI_H__
+
+#include "vidc_hfi.h"
+#include "vidc_hfi_helper.h"
+#include <mach/qdsp6v2/apr.h>
+
+#define Q6_IFACEQ_QUEUE_SIZE (8 * 1024)
+
+struct q6_resources {
+	struct msm_vidc_fw fw;
+};
+
+struct q6_iface_q_info {
+	spinlock_t lock;
+	u32 q_size;
+	u32 read_idx;
+	u32 write_idx;
+	u8 *buffer;
+};
+
+struct q6_hfi_device {
+	struct list_head list;
+	struct list_head sess_head;
+	struct q6_iface_q_info event_queue;
+	struct workqueue_struct *vidc_workq;
+	struct work_struct vidc_worker;
+	u32 device_id;
+	msm_vidc_callback callback;
+	struct q6_resources resources;
+	void *apr;
+};
+
+struct q6_apr_cmd_sys_init_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_sys_init_packet pkt;
+};
+
+struct q6_apr_cmd_sys_session_init_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_sys_session_init_packet pkt;
+};
+
+struct q6_apr_session_cmd_pkt {
+	struct apr_hdr hdr;
+	struct vidc_hal_session_cmd_pkt pkt;
+};
+
+struct q6_apr_cmd_session_set_buffers_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_set_buffers_packet pkt;
+};
+
+struct q6_apr_cmd_session_release_buffer_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_release_buffer_packet pkt;
+};
+
+struct q6_apr_cmd_session_empty_buffer_compressed_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_empty_buffer_compressed_packet pkt;
+};
+
+struct q6_apr_cmd_session_empty_buffer_uncompressed_plane0_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet pkt;
+};
+
+struct q6_apr_cmd_session_fill_buffer_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_fill_buffer_packet pkt;
+};
+
+struct q6_apr_cmd_session_parse_sequence_header_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_parse_sequence_header_packet pkt;
+};
+
+struct q6_apr_cmd_session_get_sequence_header_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_get_sequence_header_packet pkt;
+};
+
+struct q6_apr_cmd_session_get_property_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_get_property_packet pkt;
+};
+
+struct q6_apr_cmd_session_flush_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_flush_packet pkt;
+};
+
+struct q6_apr_cmd_session_set_property_packet {
+	struct apr_hdr hdr;
+	struct hfi_cmd_session_set_property_packet pkt;
+};
+
+int q6_hfi_initialize(struct hfi_device *hdev, u32 device_id,
+		hfi_cmd_response_callback callback);
+
+void q6_hfi_delete_device(void *device);
+
+#endif /*#ifndef  __Q6_HFI_H__ */
diff --git a/drivers/media/video/msm_vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
similarity index 93%
rename from drivers/media/video/msm_vidc/venus_hfi.c
rename to drivers/media/platform/msm/vidc/venus_hfi.c
index 5168b7a..7deef37 100644
--- a/drivers/media/video/msm_vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -827,7 +827,7 @@
 		return -EINVAL;
 	}
 
-	spin_lock(&device->write_lock);
+	mutex_lock(&device->write_lock);
 	q_info = &device->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
 	if (!q_info) {
 		dprintk(VIDC_ERR, "cannot write to shared Q's");
@@ -845,7 +845,7 @@
 		dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full");
 	}
 err_q_write:
-	spin_unlock(&device->write_lock);
+	mutex_unlock(&device->write_lock);
 	return result;
 }
 
@@ -859,7 +859,7 @@
 		dprintk(VIDC_ERR, "Invalid Params");
 		return -EINVAL;
 	}
-	spin_lock(&device->read_lock);
+	mutex_lock(&device->read_lock);
 	if (device->iface_queues[VIDC_IFACEQ_MSGQ_IDX].
 		q_array.align_virtual_addr == 0) {
 		dprintk(VIDC_ERR, "cannot read from shared MSG Q's");
@@ -880,7 +880,7 @@
 		rc = -ENODATA;
 	}
 read_error:
-	spin_unlock(&device->read_lock);
+	mutex_unlock(&device->read_lock);
 	return rc;
 }
 
@@ -894,7 +894,7 @@
 		dprintk(VIDC_ERR, "Invalid Params");
 		return -EINVAL;
 	}
-	spin_lock(&device->read_lock);
+	mutex_lock(&device->read_lock);
 	if (device->iface_queues[VIDC_IFACEQ_DBGQ_IDX].
 		q_array.align_virtual_addr == 0) {
 		dprintk(VIDC_ERR, "cannot read from shared DBG Q's");
@@ -914,7 +914,7 @@
 		rc = -ENODATA;
 	}
 dbg_error:
-	spin_unlock(&device->read_lock);
+	mutex_unlock(&device->read_lock);
 	return rc;
 }
 
@@ -1179,47 +1179,23 @@
 	return rc;
 }
 
-static void venus_hfi_set_vbif_registers(struct venus_hfi_device *device)
+static void venus_hfi_set_registers(struct venus_hfi_device *device)
 {
-	/*Disable Dynamic clock gating for Venus VBIF*/
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-				   VIDC_VENUS_VBIF_CLK_ON, 1, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00001FFF, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_OUT_AXI_AOOO, 0x1FFF1FFF, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_RD_LIM_CONF0, 0x10101001, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_RD_LIM_CONF1, 0x10101010, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_RD_LIM_CONF2, 0x10101010, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_RD_LIM_CONF3, 0x00000010, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_WR_LIM_CONF0, 0x1010100f, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_WR_LIM_CONF1, 0x10101010, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_WR_LIM_CONF2, 0x10101010, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_WR_LIM_CONF3, 0x00000010, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_OUT_RD_LIM_CONF0, 0x00001010, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_OUT_WR_LIM_CONF0, 0x00001010, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_ARB_CTL, 0x00000030, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS_VBIF_DDR_OUT_MAX_BURST, 0x00000707, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS_VBIF_OCMEM_OUT_MAX_BURST, 0x00000707, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000001, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY, 0x5555556, 0);
-	venus_hfi_write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL, 0, 0);
+	struct reg_set *reg_set;
+	int i;
+
+	if (!device->res) {
+		dprintk(VIDC_ERR,
+			"device resources null, cannot set registers\n");
+		return;
+	}
+
+	reg_set = &device->res->reg_set;
+	for (i = 0; i < reg_set->count; i++) {
+		venus_hfi_write_register(device->hal_data->register_base_addr,
+				reg_set->reg_tbl[i].reg,
+				reg_set->reg_tbl[i].value, 0);
+	}
 }
 
 static int venus_hfi_sys_set_debug(struct venus_hfi_device *device, int debug)
@@ -1259,9 +1235,9 @@
 	dev->intr_status = 0;
 	enable_irq(dev->hal_data->irq);
 	INIT_LIST_HEAD(&dev->sess_head);
-	spin_lock_init(&dev->read_lock);
-	spin_lock_init(&dev->write_lock);
-	venus_hfi_set_vbif_registers(dev);
+	mutex_init(&dev->read_lock);
+	mutex_init(&dev->write_lock);
+	venus_hfi_set_registers(dev);
 
 	if (!dev->hal_client) {
 		dev->hal_client = msm_smem_new_client(SMEM_ION);
@@ -2130,30 +2106,16 @@
 }
 
 static int venus_hfi_init_regs_and_interrupts(
-		struct venus_hfi_device *device, struct platform_device *pdev)
+		struct venus_hfi_device *device,
+		struct msm_vidc_platform_resources *res)
 {
 	struct hal_data *hal = NULL;
 	int rc = 0;
-	struct resource *res;
 
-	device->base_addr = 0x0;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dprintk(VIDC_ERR, "Failed to get IORESOURCE_MEM\n");
-		rc = -ENODEV;
-		goto err_core_init;
-	}
-	device->register_base = res->start;
-	device->register_size = resource_size(res);
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dprintk(VIDC_ERR, "Failed to get IORESOURCE_IRQ\n");
-		rc = -ENODEV;
-		goto err_core_init;
-	}
-	device->irq = res->start;
+	device->base_addr = res->fw_base_addr;
+	device->register_base = res->register_base;
+	device->register_size = res->register_size;
+	device->irq = res->irq;
 
 	rc = venus_hfi_check_core_registered(hal_ctxt, device->base_addr,
 			device->register_base, device->register_size,
@@ -2200,48 +2162,14 @@
 
 }
 
-static size_t read_u32_array(struct platform_device *pdev,
-		char *name, u32 *arr, size_t size)
-{
-	int len;
-	size_t sz = 0;
-	struct device_node *np = pdev->dev.of_node;
-	if (!of_get_property(np, name, &len)) {
-		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
-			name);
-		goto fail_read;
-	}
-	sz = len / sizeof(u32);
-	if (sz <= 0) {
-		dprintk(VIDC_ERR, "%s not specified in device tree\n",
-			name);
-		goto fail_read;
-	}
-	if (sz > size) {
-		dprintk(VIDC_ERR, "Not enough memory to store %s values\n",
-			name);
-		goto fail_read;
-	}
-	if (of_property_read_u32_array(np, name, arr, sz)) {
-		dprintk(VIDC_ERR,
-			"error while reading %s from device tree\n",
-			name);
-		goto fail_read;
-	}
-	return sz;
-fail_read:
-	sz = 0;
-	return sz;
-}
-
-static inline int venus_hfi_init_clocks(struct platform_device *pdev,
+static inline int venus_hfi_init_clocks(struct msm_vidc_platform_resources *res,
 		struct venus_hfi_device *device)
 {
 	struct venus_core_clock *cl;
 	int i;
 	int rc = 0;
 	struct venus_core_clock *clock;
-	if (!device) {
+	if (!res || !device) {
 		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
 		return -EINVAL;
 	}
@@ -2255,10 +2183,10 @@
 	strlcpy(clock[VCODEC_OCMEM_CLK].name, "mem_clk",
 		sizeof(clock[VCODEC_OCMEM_CLK].name));
 
-	clock[VCODEC_CLK].count = read_u32_array(pdev,
-		"load-freq-tbl", (u32 *)clock[VCODEC_CLK].load_freq_tbl,
-		(sizeof(clock[VCODEC_CLK].load_freq_tbl)/sizeof(u32)));
-	clock[VCODEC_CLK].count /= 2;
+	clock[VCODEC_CLK].count = res->load_freq_tbl_size;
+	memcpy((void *)clock[VCODEC_CLK].load_freq_tbl, res->load_freq_tbl,
+		clock[VCODEC_CLK].count * sizeof(*res->load_freq_tbl));
+
 	dprintk(VIDC_DBG, "count = %d\n", clock[VCODEC_CLK].count);
 	if (!clock[VCODEC_CLK].count) {
 		dprintk(VIDC_ERR, "Failed to read clock frequency\n");
@@ -2275,7 +2203,7 @@
 	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
 		cl = &device->resources.clock[i];
 		if (!cl->clk) {
-			cl->clk = devm_clk_get(&pdev->dev, cl->name);
+			cl->clk = devm_clk_get(&res->pdev->dev, cl->name);
 			if (IS_ERR_OR_NULL(cl->clk)) {
 				dprintk(VIDC_ERR,
 					"Failed to get clock: %s\n", cl->name);
@@ -2382,9 +2310,8 @@
 }
 
 static int venus_hfi_register_iommu_domains(struct venus_hfi_device *device,
-					struct platform_device *pdev)
+					struct msm_vidc_platform_resources *res)
 {
-	size_t len;
 	struct msm_iova_partition partition[2];
 	struct msm_iova_layout layout;
 	int rc = 0;
@@ -2406,15 +2333,9 @@
 			sizeof(io_map[NS_MAP].ctx));
 
 	for (i = 0; i < MAX_MAP; i++) {
-		len = read_u32_array(pdev, io_map[i].name,
-				io_map[i].addr_range,
-				(sizeof(io_map[i].addr_range)/sizeof(u32)));
-		if (!len) {
-			dprintk(VIDC_ERR,
-				"Error in reading cp address range\n");
-			rc = -EINVAL;
-			break;
-		}
+		memcpy(io_map[i].addr_range, &res->iommu_maps[i].addr_range,
+				sizeof(u32) * 2);
+
 		partition[0].start = io_map[i].addr_range[0];
 		if (i == NS_MAP) {
 			partition[0].size =
@@ -2572,6 +2493,37 @@
 	return rc;
 }
 
+static int venus_hfi_unvote_bus(void *dev,
+				enum session_type type, enum mem_type mtype)
+{
+	int rc = 0;
+	u32 handle = 0;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
+
+	if (mtype & DDR_MEM)
+		handle = device->resources.bus_info.ddr_handle[type];
+	if (mtype & OCMEM_MEM)
+		handle = device->resources.bus_info.ocmem_handle[type];
+
+	if (handle) {
+		rc = msm_bus_scale_client_update_request(
+				handle, 0);
+		if (rc)
+			dprintk(VIDC_ERR, "Failed to unvote bus: %d\n", rc);
+	} else {
+		dprintk(VIDC_ERR, "Failed to unvote bus, mtype: %d\n",
+				mtype);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
 static int venus_hfi_set_ocmem(void *dev, struct ocmem_buf *ocmem)
 {
 	struct vidc_resource_hdr rhdr;
@@ -2673,7 +2625,7 @@
 	ocmem_buffer = device->resources.ocmem.buf;
 	if (!ocmem_buffer ||
 		ocmem_buffer->len < size) {
-		ocmem_buffer = ocmem_allocate_nb(OCMEM_VIDEO, size);
+		ocmem_buffer = ocmem_allocate(OCMEM_VIDEO, size);
 		if (IS_ERR_OR_NULL(ocmem_buffer)) {
 			dprintk(VIDC_ERR,
 				"ocmem_allocate_nb failed: %d\n",
@@ -2736,11 +2688,12 @@
 
 
 static int venus_hfi_init_resources(struct venus_hfi_device *device,
-				struct platform_device *pdev)
+				struct msm_vidc_platform_resources *res)
 {
 	int rc = 0;
 
-	rc = venus_hfi_init_clocks(pdev, device);
+	device->res = res;
+	rc = venus_hfi_init_clocks(res, device);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init clocks\n");
 		rc = -ENODEV;
@@ -2753,7 +2706,7 @@
 		goto err_init_bus;
 	}
 
-	rc = venus_hfi_register_iommu_domains(device, pdev);
+	rc = venus_hfi_register_iommu_domains(device, res);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
 		goto err_register_iommu_domain;
@@ -3003,13 +2956,14 @@
 	return 0;
 }
 
-static void *venus_hfi_add_device(u32 device_id, struct platform_device *pdev,
-		void (*callback) (enum command_response cmd, void *data))
+static void *venus_hfi_add_device(u32 device_id,
+			struct msm_vidc_platform_resources *res,
+			hfi_cmd_response_callback callback)
 {
 	struct venus_hfi_device *hdevice = NULL;
 	int rc = 0;
 
-	if (device_id || !pdev || !callback) {
+	if (device_id || !res || !callback) {
 		dprintk(VIDC_ERR, "Invalid Paramters");
 		return NULL;
 	}
@@ -3023,7 +2977,7 @@
 		goto err_alloc;
 	}
 
-	rc = venus_hfi_init_regs_and_interrupts(hdevice, pdev);
+	rc = venus_hfi_init_regs_and_interrupts(hdevice, res);
 	if (rc)
 		goto err_init_regs;
 
@@ -3053,24 +3007,24 @@
 }
 
 static void *venus_hfi_get_device(u32 device_id,
-				struct platform_device *pdev,
+				struct msm_vidc_platform_resources *res,
 				hfi_cmd_response_callback callback)
 {
 	struct venus_hfi_device *device;
 	int rc = 0;
 
-	if (!pdev || !callback) {
-		dprintk(VIDC_ERR, "Invalid params: %p %p\n", pdev, callback);
+	if (!res || !callback) {
+		dprintk(VIDC_ERR, "Invalid params: %p %p\n", res, callback);
 		return NULL;
 	}
 
-	device = venus_hfi_add_device(device_id, pdev, &handle_cmd_response);
+	device = venus_hfi_add_device(device_id, res, &handle_cmd_response);
 	if (!device) {
 		dprintk(VIDC_ERR, "Failed to create HFI device\n");
 		return NULL;
 	}
 
-	rc = venus_hfi_init_resources(device, pdev);
+	rc = venus_hfi_init_resources(device, res);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
 		goto err_fail_init_res;
@@ -3132,6 +3086,7 @@
 	hdev->session_get_property = venus_hfi_session_get_property;
 	hdev->scale_clocks = venus_hfi_scale_clocks;
 	hdev->scale_bus = venus_hfi_scale_bus;
+	hdev->unvote_bus = venus_hfi_unvote_bus;
 	hdev->unset_ocmem = venus_hfi_unset_ocmem;
 	hdev->alloc_ocmem = venus_hfi_alloc_ocmem;
 	hdev->free_ocmem = venus_hfi_free_ocmem;
@@ -3145,16 +3100,18 @@
 }
 
 int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
-	struct platform_device *pdev, hfi_cmd_response_callback callback)
+		struct msm_vidc_platform_resources *res,
+		hfi_cmd_response_callback callback)
 {
 	int rc = 0;
 
-	if (!hdev || !callback) {
-		dprintk(VIDC_ERR, "Invalid params: %p %p\n", pdev, callback);
+	if (!hdev || !res || !callback) {
+		dprintk(VIDC_ERR, "Invalid params: %p %p %p\n",
+			hdev, res, callback);
 		rc = -EINVAL;
 		goto err_venus_hfi_init;
 	}
-	hdev->hfi_device_data = venus_hfi_get_device(device_id, pdev, callback);
+	hdev->hfi_device_data = venus_hfi_get_device(device_id, res, callback);
 
 	venus_init_hfi_callbacks(hdev);
 
diff --git a/drivers/media/video/msm_vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
similarity index 91%
rename from drivers/media/video/msm_vidc/venus_hfi.h
rename to drivers/media/platform/msm/vidc/venus_hfi.h
index 8770ace..58314dd 100644
--- a/drivers/media/video/msm_vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -26,6 +26,7 @@
 #include "vidc_hfi_helper.h"
 #include "vidc_hfi_api.h"
 #include "vidc_hfi.h"
+#include "msm_vidc_resources.h"
 
 #define HFI_MASK_QHDR_TX_TYPE			0xFF000000
 #define HFI_MASK_QHDR_RX_TYPE			0x00FF0000
@@ -42,12 +43,6 @@
 #define VIDC_IFACEQ_CMDQ_IDX				0
 #define VIDC_IFACEQ_MSGQ_IDX				1
 #define VIDC_IFACEQ_DBGQ_IDX				2
-
-#define VIDC_IFACEQ_MAX_PKT_SIZE			1024
-#define VIDC_IFACEQ_MED_PKT_SIZE			768
-#define VIDC_IFACEQ_MIN_PKT_SIZE			8
-#define VIDC_IFACEQ_VAR_SMALL_PKT_SIZE		100
-#define VIDC_IFACEQ_VAR_LARGE_PKT_SIZE		512
 #define VIDC_IFACEQ_MAX_BUF_COUNT			50
 #define VIDC_IFACE_MAX_PARALLEL_CLNTS		16
 #define VIDC_IFACEQ_DFLT_QHDR				0x01010000
@@ -149,15 +144,6 @@
 	VCODEC_MAX_CLKS
 };
 
-struct load_freq_table {
-	u32 load;
-	u32 freq;
-};
-
-struct msm_vidc_fw {
-	void *cookie;
-};
-
 struct venus_core_clock {
 	char name[VIDC_MAX_NAME_LENGTH];
 	struct clk *clk;
@@ -189,8 +175,8 @@
 	struct list_head sess_head;
 	u32 intr_status;
 	u32 device_id;
-	spinlock_t read_lock;
-	spinlock_t write_lock;
+	struct mutex read_lock;
+	struct mutex write_lock;
 	msm_vidc_callback callback;
 	struct vidc_mem_addr iface_q_table;
 	struct vidc_mem_addr qdss;
@@ -207,9 +193,11 @@
 	u32 register_size;
 	u32 irq;
 	struct venus_resources resources;
+	struct msm_vidc_platform_resources *res;
 };
 
 void venus_hfi_delete_device(void *device);
 int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
-	struct platform_device *pdev, hfi_cmd_response_callback callback);
+		struct msm_vidc_platform_resources *res,
+		hfi_cmd_response_callback callback);
 #endif
diff --git a/drivers/media/video/msm_vidc/vidc_hfi.c b/drivers/media/platform/msm/vidc/vidc_hfi.c
similarity index 81%
rename from drivers/media/video/msm_vidc/vidc_hfi.c
rename to drivers/media/platform/msm/vidc/vidc_hfi.c
index f09d3d5..e8131dd 100644
--- a/drivers/media/video/msm_vidc/vidc_hfi.c
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.c
@@ -14,14 +14,16 @@
 #include "msm_vidc_debug.h"
 #include "vidc_hfi_api.h"
 #include "venus_hfi.h"
+#include "q6_hfi.h"
 
 struct hal_device_data hal_ctxt;
 
 void *vidc_hfi_initialize(enum msm_vidc_hfi_type hfi_type, u32 device_id,
-			struct platform_device *pdev,
+			struct msm_vidc_platform_resources *res,
 			hfi_cmd_response_callback callback)
 {
 	struct hfi_device *hdev = NULL;
+	int rc = 0;
 	hdev = (struct hfi_device *)
 			kzalloc(sizeof(struct hfi_device), GFP_KERNEL);
 	if (!hdev) {
@@ -31,14 +33,24 @@
 
 	switch (hfi_type) {
 	case VIDC_HFI_VENUS:
-		venus_hfi_initialize(hdev, device_id, pdev, callback);
+		rc = venus_hfi_initialize(hdev, device_id, res, callback);
 		break;
 
 	case VIDC_HFI_Q6:
+		rc = q6_hfi_initialize(hdev, device_id, callback);
+		break;
+
 	default:
 		dprintk(VIDC_ERR, "Unsupported host-firmware interface\n");
 		goto err_hfi_init;
 	}
+
+	if (rc) {
+		dprintk(VIDC_ERR, "%s device init failed rc = %d",
+				__func__, rc);
+		goto err_hfi_init;
+	}
+
 	return hdev;
 
 err_hfi_init:
@@ -60,6 +72,9 @@
 		break;
 
 	case VIDC_HFI_Q6:
+		q6_hfi_delete_device(hdev->hfi_device_data);
+		break;
+
 	default:
 		dprintk(VIDC_ERR, "Unsupported host-firmware interface\n");
 	}
diff --git a/drivers/media/video/msm_vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
similarity index 98%
rename from drivers/media/video/msm_vidc/vidc_hfi.h
rename to drivers/media/platform/msm/vidc/vidc_hfi.h
index c82f665..f565d3b 100644
--- a/drivers/media/video/msm_vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -354,7 +354,12 @@
 #define  HFI_MSG_SESSION_RELEASE_BUFFERS_DONE			\
 	(HFI_MSG_SESSION_OX_START + 0xC)
 
-#define HFI_MIN_PKT_SIZE			8
+#define VIDC_IFACEQ_MAX_PKT_SIZE                        1024
+#define VIDC_IFACEQ_MED_PKT_SIZE                        768
+#define VIDC_IFACEQ_MIN_PKT_SIZE                        8
+#define VIDC_IFACEQ_VAR_SMALL_PKT_SIZE          100
+#define VIDC_IFACEQ_VAR_LARGE_PKT_SIZE          512
+
 
 struct hfi_cmd_sys_session_abort_packet {
 	u32 size;
@@ -819,6 +824,10 @@
 	int dev_count;
 };
 
+struct msm_vidc_fw {
+	void *cookie;
+};
+
 extern struct hal_device_data hal_ctxt;
 
 void hfi_process_msg_packet(msm_vidc_callback callback,
diff --git a/drivers/media/video/msm_vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
similarity index 98%
rename from drivers/media/video/msm_vidc/vidc_hfi_api.h
rename to drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 5428267..d06ea51 100644
--- a/drivers/media/video/msm_vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/types.h>
 #include <media/msm_vidc.h>
+#include "msm_vidc_resources.h"
 
 #define CONTAINS(__a, __sz, __t) ({\
 	int __rc = __t >= __a && \
@@ -92,6 +93,7 @@
 	HAL_EXTRADATA_INDEX,
 	HAL_EXTRADATA_NUM_CONCEALED_MB,
 	HAL_EXTRADATA_METADATA_FILLER,
+	HAL_EXTRADATA_ASPECT_RATIO,
 };
 
 enum hal_property {
@@ -1007,6 +1009,9 @@
 	FW_INFO_MAX,
 };
 
+#define call_hfi_op(q, op, args...)			\
+	(((q)->op) ? ((q)->op(args)) : 0)
+
 struct hfi_device {
 	void *hfi_device_data;
 
@@ -1047,6 +1052,8 @@
 	int (*scale_clocks)(void *dev, int load);
 	int (*scale_bus)(void *dev, int load,
 			enum session_type type, enum mem_type mtype);
+	int (*unvote_bus)(void *dev, enum session_type type,
+		enum mem_type mtype);
 	int (*unset_ocmem)(void *dev);
 	int (*alloc_ocmem)(void *dev, unsigned long size);
 	int (*free_ocmem)(void *dev);
@@ -1066,7 +1073,7 @@
 typedef void (*msm_vidc_callback) (u32 response, void *callback);
 
 void *vidc_hfi_initialize(enum msm_vidc_hfi_type hfi_type, u32 device_id,
-			struct platform_device *pdev,
+			struct msm_vidc_platform_resources *res,
 			hfi_cmd_response_callback callback);
 void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type,
 			struct hfi_device *hdev);
diff --git a/drivers/media/video/msm_vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
similarity index 100%
rename from drivers/media/video/msm_vidc/vidc_hfi_helper.h
rename to drivers/media/platform/msm/vidc/vidc_hfi_helper.h
diff --git a/drivers/media/video/msm_vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
similarity index 100%
rename from drivers/media/video/msm_vidc/vidc_hfi_io.h
rename to drivers/media/platform/msm/vidc/vidc_hfi_io.h
diff --git a/drivers/media/video/msm_wfd/Kconfig b/drivers/media/platform/msm/wfd/Kconfig
similarity index 100%
rename from drivers/media/video/msm_wfd/Kconfig
rename to drivers/media/platform/msm/wfd/Kconfig
diff --git a/drivers/media/video/msm_wfd/Makefile b/drivers/media/platform/msm/wfd/Makefile
similarity index 100%
rename from drivers/media/video/msm_wfd/Makefile
rename to drivers/media/platform/msm/wfd/Makefile
diff --git a/drivers/media/video/msm_wfd/enc-mfc-subdev.c b/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
similarity index 100%
rename from drivers/media/video/msm_wfd/enc-mfc-subdev.c
rename to drivers/media/platform/msm/wfd/enc-mfc-subdev.c
diff --git a/drivers/media/video/msm_wfd/enc-subdev.h b/drivers/media/platform/msm/wfd/enc-subdev.h
similarity index 100%
rename from drivers/media/video/msm_wfd/enc-subdev.h
rename to drivers/media/platform/msm/wfd/enc-subdev.h
diff --git a/drivers/media/video/msm_wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
similarity index 100%
rename from drivers/media/video/msm_wfd/enc-venus-subdev.c
rename to drivers/media/platform/msm/wfd/enc-venus-subdev.c
diff --git a/drivers/media/video/msm_wfd/mdp-4-subdev.c b/drivers/media/platform/msm/wfd/mdp-4-subdev.c
similarity index 100%
rename from drivers/media/video/msm_wfd/mdp-4-subdev.c
rename to drivers/media/platform/msm/wfd/mdp-4-subdev.c
diff --git a/drivers/media/video/msm_wfd/mdp-5-subdev.c b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
similarity index 100%
rename from drivers/media/video/msm_wfd/mdp-5-subdev.c
rename to drivers/media/platform/msm/wfd/mdp-5-subdev.c
diff --git a/drivers/media/video/msm_wfd/mdp-dummy-subdev.c b/drivers/media/platform/msm/wfd/mdp-dummy-subdev.c
similarity index 100%
rename from drivers/media/video/msm_wfd/mdp-dummy-subdev.c
rename to drivers/media/platform/msm/wfd/mdp-dummy-subdev.c
diff --git a/drivers/media/video/msm_wfd/mdp-subdev.h b/drivers/media/platform/msm/wfd/mdp-subdev.h
similarity index 100%
rename from drivers/media/video/msm_wfd/mdp-subdev.h
rename to drivers/media/platform/msm/wfd/mdp-subdev.h
diff --git a/drivers/media/video/msm_wfd/vsg-subdev.c b/drivers/media/platform/msm/wfd/vsg-subdev.c
similarity index 100%
rename from drivers/media/video/msm_wfd/vsg-subdev.c
rename to drivers/media/platform/msm/wfd/vsg-subdev.c
diff --git a/drivers/media/video/msm_wfd/vsg-subdev.h b/drivers/media/platform/msm/wfd/vsg-subdev.h
similarity index 100%
rename from drivers/media/video/msm_wfd/vsg-subdev.h
rename to drivers/media/platform/msm/wfd/vsg-subdev.h
diff --git a/drivers/media/video/msm_wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
similarity index 100%
rename from drivers/media/video/msm_wfd/wfd-ioctl.c
rename to drivers/media/platform/msm/wfd/wfd-ioctl.c
diff --git a/drivers/media/video/msm_wfd/wfd-util.c b/drivers/media/platform/msm/wfd/wfd-util.c
similarity index 96%
rename from drivers/media/video/msm_wfd/wfd-util.c
rename to drivers/media/platform/msm/wfd/wfd-util.c
index e69a839..965c873 100644
--- a/drivers/media/video/msm_wfd/wfd-util.c
+++ b/drivers/media/platform/msm/wfd/wfd-util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -55,6 +55,7 @@
 
 	memset(stats, 0, sizeof(*stats));
 	INIT_LIST_HEAD(&stats->enc_queue);
+	mutex_init(&stats->mutex);
 
 	snprintf(device_str, sizeof(device_str), "%d", device);
 	stats->d_parent = debugfs_create_dir(device_str, wfd_debugfs_root);
@@ -128,6 +129,8 @@
 int wfd_stats_update(struct wfd_stats *stats, enum wfd_stats_event event)
 {
 	int rc = 0;
+
+	mutex_lock(&stats->mutex);
 	switch (event) {
 	case WFD_STAT_EVENT_CLIENT_QUEUE:
 		stats->v4l2_buf_count++;
@@ -192,6 +195,7 @@
 	default:
 		rc = -ENOTSUPP;
 	}
+	mutex_unlock(&stats->mutex);
 
 	return rc;
 }
diff --git a/drivers/media/video/msm_wfd/wfd-util.h b/drivers/media/platform/msm/wfd/wfd-util.h
similarity index 90%
rename from drivers/media/video/msm_wfd/wfd-util.h
rename to drivers/media/platform/msm/wfd/wfd-util.h
index e5db846..a04e16a 100644
--- a/drivers/media/video/msm_wfd/wfd-util.h
+++ b/drivers/media/platform/msm/wfd/wfd-util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,8 +12,9 @@
  */
 
 #include <linux/debugfs.h>
-#include <linux/list.h>
 #include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
 
 #ifndef _WFD_UTIL_H_
 #define _WFD_UTIL_H_
@@ -23,8 +24,8 @@
 #define WFD_TAG "wfd: "
 #define WFD_MSG_INFO(fmt...) pr_info(WFD_TAG fmt)
 #define WFD_MSG_WARN(fmt...) pr_warning(WFD_TAG fmt)
-#define WFD_MSG_ERR(fmt...) pr_err(KERN_ERR WFD_TAG fmt)
-#define WFD_MSG_CRIT(fmt...) pr_crit(KERN_CRIT WFD_TAG fmt)
+#define WFD_MSG_ERR(fmt...) pr_err(WFD_TAG fmt)
+#define WFD_MSG_CRIT(fmt...) pr_crit(WFD_TAG fmt)
 #define WFD_MSG_DBG(fmt...) pr_debug(WFD_TAG fmt)
 
 
@@ -34,6 +35,8 @@
 };
 
 struct wfd_stats {
+	struct mutex mutex;
+
 	/* Output Buffers */
 	uint32_t v4l2_buf_count;
 
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 830ba81..a722a79 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -639,14 +639,6 @@
 	  Say Y here if you want to test video apps or debug V4L devices.
 	  In doubt, say N.
 
-config MSM_VCAP
-	tristate "Qualcomm MSM VCAP"
-	depends on VIDEO_DEV && VIDEO_V4L2
-	default y
-	---help---
-		Enables VCAP driver. This device allows for video capture and
-		video processing using the v4l2 api
-
 #
 # USB Multimedia device configuration
 #
@@ -1174,49 +1166,7 @@
 
 source "drivers/media/video/s5p-tv/Kconfig"
 
-#
-# MSM camera configuration
-#
 
-comment "Qualcomm MSM Camera And Video"
-
-menuconfig MSM_CAMERA
-	bool "Qualcomm MSM camera and video capture support"
-	depends on ARCH_MSM && VIDEO_V4L2 && I2C
-	default y
-	help
-	  Say Y here to enable selecting the video adapters for
-	  Qualcomm msm camera and video encoding
-
-config MSM_CAMERA_DEBUG
-	bool "Qualcomm MSM camera debugging with printk"
-	depends on MSM_CAMERA
-	default n
-	help
-	  Enable printk() debug for msm camera
-
-if MSM_CAMERA
-source "drivers/media/video/msm/Kconfig"
-endif # MSM_CAMERA
-
-menuconfig MSMB_CAMERA
-	bool "Qualcomm MSM camera and video capture 2.0 support"
-	depends on ARCH_MSM && VIDEO_V4L2 && I2C
-	---help---
-	  Say Y here to enable selecting the video adapters for
-	  Qualcomm msm camera and video capture 2.0, enabling this
-	  adds support for the camera driver stack including sensor, isp
-	  and postprocessing drivers.
-
-config MSMB_CAMERA_DEBUG
-	bool "Qualcomm MSM camera 2.0 debugging with printk"
-	depends on MSMB_CAMERA
-	---help---
-	  Enable printk() debug for msm camera 2.0
-
-if MSMB_CAMERA
-source "drivers/media/video/msmb/Kconfig"
-endif # MSMB_CAMERA
 
 endif # V4L_PLATFORM_DRIVERS
 endif # VIDEO_CAPTURE_DRIVERS
@@ -1280,6 +1230,3 @@
 	    conversion.
 
 endif # V4L_MEM2MEM_DRIVERS
-
-source "drivers/media/video/msm_vidc/Kconfig"
-source "drivers/media/video/msm_wfd/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index e732773..1807467 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -170,9 +170,6 @@
 obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
 
-obj-$(CONFIG_MSM_VCAP) += vcap_v4l2.o
-obj-$(CONFIG_MSM_VCAP) += vcap_vc.o
-obj-$(CONFIG_MSM_VCAP) += vcap_vp.o
 obj-$(CONFIG_VIDEO_AK881X)		+= ak881x.o
 
 obj-$(CONFIG_VIDEO_OMAP2)		+= omap2cam.o
@@ -212,11 +209,7 @@
 
 obj-y	+= davinci/
 
-obj-$(CONFIG_MSM_CAMERA) += msm/
-obj-$(CONFIG_MSMB_CAMERA) += msmb/
 obj-$(CONFIG_ARCH_OMAP)	+= omap/
-obj-$(CONFIG_MSM_VIDC_V4L2) += msm_vidc/
-obj-$(CONFIG_MSM_WFD) += msm_wfd/
 
 ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
 ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
diff --git a/drivers/media/video/msm/actuators/Makefile b/drivers/media/video/msm/actuators/Makefile
deleted file mode 100644
index 70a3a19..0000000
--- a/drivers/media/video/msm/actuators/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-EXTRA_CFLAGS += -Idrivers/media/video/msm
-EXTRA_CFLAGS += -Idrivers/media/video/msm/io
-obj-$(CONFIG_MSM_ACTUATOR) += msm_actuator.o
diff --git a/drivers/media/video/msm/cci/Makefile b/drivers/media/video/msm/cci/Makefile
deleted file mode 100644
index 195a1b2..0000000
--- a/drivers/media/video/msm/cci/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-ccflags-y += -Idrivers/media/video/msm -Idrivers/media/video/msm/server
-obj-$(CONFIG_MSM_CCI) += msm_cci.o
diff --git a/drivers/media/video/msm/cpp/Makefile b/drivers/media/video/msm/cpp/Makefile
deleted file mode 100644
index b4f1fdf..0000000
--- a/drivers/media/video/msm/cpp/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-ccflags-y += -Idrivers/media/video/msm
-ccflags-y += -Idrivers/media/video/msm/io
-obj-$(CONFIG_MSM_CPP) += msm_cpp.o
-
diff --git a/drivers/media/video/msm/jpeg_10/Makefile b/drivers/media/video/msm/jpeg_10/Makefile
deleted file mode 100644
index d99d1a4..0000000
--- a/drivers/media/video/msm/jpeg_10/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-ccflags-y += -Idrivers/media/video/msm
-obj-$(CONFIG_MSM_JPEG) += msm_jpeg_dev.o msm_jpeg_sync.o msm_jpeg_core.o msm_jpeg_hw.o msm_jpeg_platform.o
diff --git a/drivers/media/video/msm/server/Makefile b/drivers/media/video/msm/server/Makefile
deleted file mode 100644
index 55abeed..0000000
--- a/drivers/media/video/msm/server/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-
-ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
-  EXTRA_CFLAGS += -Idrivers/media/video/msm
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/io
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
-  EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
-  obj-$(CONFIG_MSM_CAMERA)   += msm_cam_server.o
-endif
diff --git a/drivers/media/video/msm_vidc/Kconfig b/drivers/media/video/msm_vidc/Kconfig
deleted file mode 100644
index 6428180..0000000
--- a/drivers/media/video/msm_vidc/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# VIDEO CORE
-#
-
-menuconfig MSM_VIDC_V4L2
-	bool "Qualcomm MSM Video Core Driver"
-		depends on ARCH_MSM8974 && VIDEO_V4L2
-		default y
diff --git a/drivers/media/video/msmb/Makefile b/drivers/media/video/msmb/Makefile
deleted file mode 100644
index 3986128..0000000
--- a/drivers/media/video/msmb/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb
-ccflags-y += -Idrivers/media/video/msmb/sensor
-ccflags-y += -Idrivers/media/video/msmb/codecs
-ccflags-y += -Idrivers/media/video/msmb/isps
-ccflags-y += -Idrivers/media/video/msmb/pps
-ccflags-y += -Idrivers/media/video/msmb/msm_vb2
-ccflags-y += -Idrivers/media/video/msmb/camera
-
-obj-$(CONFIG_MSMB_CAMERA) += msm.o
-obj-$(CONFIG_MSMB_CAMERA) += camera/
-obj-$(CONFIG_MSMB_CAMERA) += msm_vb2/
-obj-$(CONFIG_MSMB_CAMERA) += sensor/
-obj-$(CONFIG_MSMB_CAMERA) += isp/
-obj-$(CONFIG_MSMB_CAMERA) += ispif/
diff --git a/drivers/media/video/msmb/camera/Makefile b/drivers/media/video/msmb/camera/Makefile
deleted file mode 100644
index 89ff167..0000000
--- a/drivers/media/video/msmb/camera/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb
-ccflags-y += -Idrivers/media/video/msmb/msm_vb2
-obj-$(CONFIG_MSMB_CAMERA) += camera.o
diff --git a/drivers/media/video/msmb/isp/Makefile b/drivers/media/video/msmb/isp/Makefile
deleted file mode 100644
index e517798..0000000
--- a/drivers/media/video/msmb/isp/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb
-ccflags-y += -Idrivers/media/video/msmb/sensor/io
-obj-$(CONFIG_MSMB_CAMERA) += msm_isp.o msm_buf_mgr.o msm_isp_util.o msm_isp_axi_util.o msm_isp_stats_util.o
-obj-$(CONFIG_MSMB_CAMERA) += msm_isp40.o
diff --git a/drivers/media/video/msmb/isp/msm_isp_stats_util.c b/drivers/media/video/msmb/isp/msm_isp_stats_util.c
deleted file mode 100644
index 86a4a3d..0000000
--- a/drivers/media/video/msmb/isp/msm_isp_stats_util.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/io.h>
-#include <media/v4l2-subdev.h>
-#include "msm_isp_util.h"
-#include "msm_isp_stats_util.h"
-#define VFE_PING_ACTIVE_FLAG 0xFFFFFFFF
-#define VFE_PONG_ACTIVE_FLAG 0x0
-
-int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
-	struct msm_vfe_stats_stream *stream_info, uint32_t pingpong_status,
-	struct msm_isp_buffer *out_buf)
-{
-	int rc = -1;
-	struct msm_isp_buffer *buf;
-	int active_bit = 0;
-	int buf_idx;
-	uint32_t bufq_handle = stream_info->bufq_handle;
-
-	out_buf = NULL;
-	active_bit = vfe_dev->hw_info->vfe_ops.stats_ops.
-		get_active_pingpong_idx(pingpong_status,
-			stream_info->stats_type);
-	buf_idx = active_bit^0x1;
-
-	rc = vfe_dev->buf_mgr->ops->get_buf(
-		vfe_dev->buf_mgr, bufq_handle, &buf);
-	if (rc < 0) {
-		pr_err("%s: No free buffer, stats_type = %d\n",
-			__func__, stream_info->stats_type);
-		return rc;
-	}
-	vfe_dev->hw_info->vfe_ops.stats_ops.update_ping_pong_addr(
-		vfe_dev, stream_info->stats_type,
-		pingpong_status, buf->mapped_info[buf_idx].paddr);
-
-	if (stream_info->buf[buf_idx])
-		out_buf = stream_info->buf[buf_idx];
-	stream_info->buf[buf_idx] = buf;
-	return 0;
-}
-
-void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
-	uint32_t irq_status0, uint32_t irq_status1,
-	struct timeval *tv)
-{
-	uint32_t frame_id;
-	uint32_t stats_comp_mask = 0, stats_mask = 0;
-	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
-	stats_comp_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
-		get_comp_mask(irq_status0, irq_status1);
-	stats_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
-		get_wm_mask(irq_status0, irq_status1);
-	if (!(stats_comp_mask || stats_mask))
-		return;
-	frame_id = vfe_dev->hw_info->vfe_ops.stats_ops.get_frame_id(vfe_dev);
-	/* TD: process comp/non comp stats */
-}
-
-static int msm_isp_stats_reserve_comp_mask(
-	struct vfe_device *vfe_dev,
-	struct msm_vfe_stats_shared_data *stats_data,
-	struct msm_vfe_stats_stream *stream_info)
-{
-	int i;
-	uint8_t num_stats_comp;
-	int8_t comp_idx = -1;
-	if (stream_info->comp_flag == 0)
-		return 0;
-
-	num_stats_comp = vfe_dev->axi_data.hw_info->num_stats_comp_mask;
-	for (i = 0; i < num_stats_comp; i++) {
-		if (!stats_data->composite_info[i].stats_mask == 0 &&
-				comp_idx < 0)
-			comp_idx = i;
-		if (stats_data->composite_info[i].comp_flag ==
-				stream_info->comp_flag) {
-			comp_idx = i;
-			break;
-		}
-	}
-	if (comp_idx < 0) {
-		pr_err("%s: no more stats comp idx\n", __func__);
-		return -EACCES;
-	}
-	stats_data->composite_info[comp_idx].stats_mask |=
-		(1 << stream_info->stats_type);
-	if (stats_data->composite_info[comp_idx].comp_flag == 0)
-		stats_data->composite_info[comp_idx].comp_flag =
-			stream_info->comp_flag;
-	stream_info->comp_idx = comp_idx;
-	return 0;
-}
-
-static int msm_isp_stats_unreserve_comp_mask(
-	struct vfe_device *vfe_dev,
-	struct msm_vfe_stats_shared_data *stats_data,
-	struct msm_vfe_stats_stream *stream_info)
-{
-	uint8_t comp_idx = stream_info->comp_idx;
-
-	if (stream_info->comp_flag == 0)
-		return 0;
-	stats_data->composite_info[comp_idx].stats_mask &=
-		~(1 << stream_info->stats_type);
-	if (stats_data->composite_info[comp_idx].stats_mask == 0)
-		memset(&stats_data->composite_info[comp_idx], 0,
-			sizeof(struct msm_vfe_stats_composite_info));
-	return 0;
-}
-
-int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg)
-{
-	int rc = 0;
-	struct msm_vfe_stats_stream_request_cmd *stream_cfg_cmd = arg;
-	struct msm_vfe_stats_stream *stream_info = NULL;
-	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
-
-	if (stream_cfg_cmd->stats_type < MSM_ISP_STATS_AEC ||
-			stream_cfg_cmd->stats_type >= MSM_ISP_STATS_MAX) {
-		pr_err("%s: invalid stats type %d received\n",
-		__func__, stream_cfg_cmd->stats_type);
-		return -EINVAL;
-	}
-	stream_info = &stats_data->stream_info[stream_cfg_cmd->stats_type];
-	if (stream_info->stream_handle != 0) {
-		pr_err("%s: stats type %d has been used already\n",
-			__func__, stream_cfg_cmd->stats_type);
-			return -EBUSY;
-	}
-
-	stats_data->stream_handle_cnt++;
-	if (stats_data->stream_handle_cnt == 0)
-		stats_data->stream_handle_cnt++;
-	stream_info->stream_handle =
-		stats_data->stream_handle_cnt << 16 |
-			stream_cfg_cmd->stats_type;
-	stream_info->enable = 0;
-	stream_info->stats_type = stream_cfg_cmd->stats_type;
-	stream_info->comp_flag = stream_cfg_cmd->comp_flag;
-	stream_info->session_id = stream_cfg_cmd->session_id;
-	stream_info->stream_id = stream_cfg_cmd->stream_id;
-	stream_info->framedrop_pattern = stream_cfg_cmd->framedrop_pattern;
-	stream_cfg_cmd->stream_handle =	stream_info->stream_handle;
-	msm_isp_stats_reserve_comp_mask(vfe_dev, stats_data, stream_info);
-	if (stream_info->comp_flag)
-		vfe_dev->hw_info->vfe_ops.stats_ops.
-			cfg_comp_mask(vfe_dev, stream_info);
-	else
-		vfe_dev->hw_info->vfe_ops.stats_ops.
-			cfg_wm_irq_mask(vfe_dev, stream_info);
-	vfe_dev->hw_info->vfe_ops.stats_ops.
-		cfg_wm_reg(vfe_dev, stream_info);
-	return rc;
-}
-
-int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg)
-{
-	int rc = 0;
-	struct msm_vfe_stats_stream_release_cmd *stream_release_cmd = arg;
-	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
-	struct msm_vfe_stats_stream *stream_info =
-		&stats_data->stream_info[
-		(stream_release_cmd->stream_handle & 0xFF)];
-
-	if (stream_info == NULL ||
-			stream_info->stream_handle !=
-				stream_release_cmd->stream_handle) {
-		pr_err("%s: handle mismatch(0x%x, 0x%x\n",
-			__func__, stream_info->stream_handle,
-			stream_release_cmd->stream_handle);
-		rc = -EINVAL;
-	}
-	if (stream_info->enable) {
-		struct msm_vfe_stats_stream_cfg_cmd stop_cmd;
-		memset(&stop_cmd, 0, sizeof(stop_cmd));
-		stop_cmd.num_streams = 1;
-		stop_cmd.stream_handle[0] = stream_release_cmd->stream_handle;
-		stop_cmd.enable = 0;
-		rc = msm_isp_cfg_stats_stream(vfe_dev, (void *)&stop_cmd);
-		if (rc < 0) {
-			pr_err("%s: cannot stop stats type %d\n",
-				__func__, stream_info->stats_type);
-			return -EPERM;
-		}
-	}
-	if (stream_info->bufq_handle) {
-		vfe_dev->buf_mgr->ops->release_buf(vfe_dev->buf_mgr,
-			stream_info->bufq_handle);
-		stream_info->bufq_handle = 0;
-	}
-	vfe_dev->hw_info->vfe_ops.stats_ops.
-		clear_wm_reg(vfe_dev, stream_info);
-	if (stream_info->comp_flag) {
-		msm_isp_stats_unreserve_comp_mask(vfe_dev,
-			stats_data, stream_info);
-		vfe_dev->hw_info->vfe_ops.stats_ops.
-		clear_comp_mask(vfe_dev, stream_info);
-	} else {
-		vfe_dev->hw_info->vfe_ops.stats_ops.
-		clear_wm_irq_mask(vfe_dev, stream_info);
-	}
-	vfe_dev->hw_info->vfe_ops.stats_ops.
-		clear_framedrop(vfe_dev, stream_info);
-	memset(stream_info, 0, sizeof(struct msm_vfe_stats_stream));
-	return rc;
-}
-
-int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg)
-{
-	int i, rc = 0;
-	uint32_t pingpong_status = 0;
-	struct msm_isp_buffer *buf = NULL;
-	struct msm_vfe_stats_stream_cfg_cmd *stream_cfg_cmd = arg;
-	struct msm_vfe_stats_stream *stream_info;
-	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
-	int idx;
-	uint32_t stats_mask = 0;
-	uint8_t enable = stream_cfg_cmd->enable;
-
-	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
-		idx = stream_cfg_cmd->stream_handle[i] & 0xF;
-		stream_info = &stats_data->stream_info[idx];
-		if (stream_info->stream_handle !=
-				stream_cfg_cmd->stream_handle[i]) {
-			pr_err("%s: invalid stream handle -0x%x received\n",
-				__func__, stream_cfg_cmd->stream_handle[i]);
-			continue;
-		}
-		if (enable) {
-			stream_info->bufq_handle =
-				vfe_dev->buf_mgr->ops->get_bufq_handle(
-				vfe_dev->buf_mgr, stream_info->session_id,
-				stream_info->stream_id);
-				if (stream_info->bufq_handle == 0) {
-					pr_err("%s: no buf configured for stats type = %d\n",
-						__func__,
-						stream_info->stats_type);
-					return -EINVAL;
-				}
-		}
-		/* config ping address */
-		pingpong_status = VFE_PONG_ACTIVE_FLAG;
-		stats_mask |= (1 << stream_info->stats_type);
-		msm_isp_stats_cfg_ping_pong_address(vfe_dev,
-			stream_info, pingpong_status, buf);
-		pingpong_status = VFE_PING_ACTIVE_FLAG;
-		msm_isp_stats_cfg_ping_pong_address(vfe_dev,
-			stream_info, pingpong_status, buf);
-	}
-	vfe_dev->hw_info->vfe_ops.stats_ops.
-		stats_enable(vfe_dev, stats_mask, enable);
-	return rc;
-}
diff --git a/drivers/media/video/msmb/ispif/Makefile b/drivers/media/video/msmb/ispif/Makefile
deleted file mode 100644
index 908cc28..0000000
--- a/drivers/media/video/msmb/ispif/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb
-ccflags-y += -Idrivers/media/video/msmb/sensor/io
-obj-$(CONFIG_MSM_CSID) += msm_ispif.o
diff --git a/drivers/media/video/msmb/msm_vb2/Makefile b/drivers/media/video/msmb/msm_vb2/Makefile
deleted file mode 100644
index 9f61289..0000000
--- a/drivers/media/video/msmb/msm_vb2/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb
-ccflags-y += -Idrivers/media/video/msmb/msm_vb2
-obj-$(CONFIG_MSMB_CAMERA) += msm_vb2.o
diff --git a/drivers/media/video/msmb/sensor/Makefile b/drivers/media/video/msmb/sensor/Makefile
deleted file mode 100644
index 5fa3f6e..0000000
--- a/drivers/media/video/msmb/sensor/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb
-ccflags-y += -Idrivers/media/video/msmb/msm_vb2
-ccflags-y += -Idrivers/media/video/msmb/camera
-ccflags-y += -Idrivers/media/video/msmb/sensor/io
-ccflags-y += -Idrivers/media/video/msmb/sensor/cci
-obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/
-obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
-obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
diff --git a/drivers/media/video/msmb/sensor/cci/Makefile b/drivers/media/video/msmb/sensor/cci/Makefile
deleted file mode 100644
index 8eef3fc..0000000
--- a/drivers/media/video/msmb/sensor/cci/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb/
-ccflags-y += -Idrivers/media/video/msmb/sensor/io
-obj-$(CONFIG_MSM_CCI) += msm_cci.o
diff --git a/drivers/media/video/msmb/sensor/csid/Makefile b/drivers/media/video/msmb/sensor/csid/Makefile
deleted file mode 100644
index 44d7726..0000000
--- a/drivers/media/video/msmb/sensor/csid/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb
-ccflags-y += -Idrivers/media/video/msmb/sensor/io
-ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
-  ccflags-y += -Idrivers/media/video/msmb/sensor/csid/include/csi2.0
-else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
-  ccflags-y += -Idrivers/media/video/msmb/sensor/csid/include/csi3.0
-endif
-obj-$(CONFIG_MSM_CSID) += msm_csid.o
diff --git a/drivers/media/video/msmb/sensor/csiphy/Makefile b/drivers/media/video/msmb/sensor/csiphy/Makefile
deleted file mode 100644
index 11e352c..0000000
--- a/drivers/media/video/msmb/sensor/csiphy/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb
-ccflags-y += -Idrivers/media/video/msmb/sensor/io
-ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
-  ccflags-y += -Idrivers/media/video/msmb/sensor/csiphy/include/csi2.0
-else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
-  ccflags-y += -Idrivers/media/video/msmb/sensor/csiphy/include/csi3.0
-endif
-obj-$(CONFIG_MSM_CSIPHY) += msm_csiphy.o
diff --git a/drivers/media/video/msmb/sensor/io/Makefile b/drivers/media/video/msmb/sensor/io/Makefile
deleted file mode 100644
index ec1faa5..0000000
--- a/drivers/media/video/msmb/sensor/io/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-ccflags-y += -Idrivers/media/video/msmb/
-ccflags-y += -Idrivers/media/video/msmb/sensor/cci
-obj-$(CONFIG_MSMB_CAMERA)   += msm_camera_io_util.o msm_camera_cci_i2c.o msm_camera_qup_i2c.o msm_camera_i2c_mux.o
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 8953475..a4cb12e 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -296,21 +296,37 @@
 	struct mfd_cell *dev;
 	int size;
 	int num_irqs;
+	int version; /* -1 to retrive version from chip version register */
+	enum wcd9xxx_slim_slave_addr_type slim_slave_type;
 } wcd9xxx_codecs[] = {
-	{{0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs),
-	 TABLA_NUM_IRQS},
-	{{0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs),
-	 TABLA_NUM_IRQS},
-	{{0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
-	 TAIKO_NUM_IRQS},
-	{{0x0, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
-	 TAPAN_NUM_IRQS},
-	{{0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
-	 SITAR_NUM_IRQS},
-	{{0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
-	 SITAR_NUM_IRQS},
-	{{0x2, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
-	 SITAR_NUM_IRQS},
+	{
+	 {0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs),
+	 TABLA_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+	},
+	{
+	 {0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs),
+	 TABLA_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+	},
+	{ /* wcd9320 version 1 */
+	 {0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
+	  TAIKO_NUM_IRQS, 1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
+	},
+	{
+	 {0x0, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
+	 TAPAN_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
+	},
+	{
+	 {0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
+	 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+	},
+	{
+	 {0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
+	 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+	},
+	{
+	 {0x2, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
+	 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+	},
 };
 
 static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
@@ -393,6 +409,10 @@
 			*wcd9xxx_dev = wcd9xxx_codecs[i].dev;
 			*wcd9xxx_dev_size = wcd9xxx_codecs[i].size;
 			*wcd9xxx_dev_num_irqs = wcd9xxx_codecs[i].num_irqs;
+			wcd9xxx->slim_slave_type =
+			    wcd9xxx_codecs[i].slim_slave_type;
+			if (wcd9xxx_codecs[i].version > -1)
+				wcd9xxx->version = wcd9xxx_codecs[i].version;
 			break;
 		}
 		i++;
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 546e252..0bce766 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,8 +14,6 @@
 #include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 
-#define WCD9XXX_CHIP_ID_TAIKO 0x00000201
-
 struct wcd9xxx_slim_sch {
 	u16 rx_port_ch_reg_base;
 	u16 port_tx_cfg_reg_base;
@@ -33,22 +31,15 @@
 
 static int wcd9xxx_configure_ports(struct wcd9xxx *wcd9xxx)
 {
-	int i;
-	u32 id;
-	for (i = 0; i < 4; i++)
-		((u8 *)&id)[i] = wcd9xxx_reg_read(wcd9xxx,
-						  WCD9XXX_A_CHIP_ID_BYTE_0 + i);
-	id = cpu_to_be32(id);
-	pr_debug("%s: chip id 0x%08x\n", __func__, id);
-	if (id != WCD9XXX_CHIP_ID_TAIKO) {
-		sh_ch.rx_port_ch_reg_base = 0x180 ;
+	if (wcd9xxx->slim_slave_type == WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA) {
+		sh_ch.rx_port_ch_reg_base = 0x180;
 		sh_ch.port_rx_cfg_reg_base = 0x040;
 		sh_ch.port_tx_cfg_reg_base = 0x040;
 	} else {
 		sh_ch.rx_port_ch_reg_base =
 			0x180 - (TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS * 4);
 		sh_ch.port_rx_cfg_reg_base =
-			0x040 - TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS ;
+			0x040 - TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS;
 		sh_ch.port_tx_cfg_reg_base = 0x050;
 	}
 
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index b11e30e..2910a37 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -42,6 +42,7 @@
 #include <mach/scm.h>
 #include <mach/subsystem_restart.h>
 #include <mach/socinfo.h>
+#include <mach/qseecomi.h>
 #include "qseecom_legacy.h"
 #include "qseecom_kernel.h"
 
@@ -60,114 +61,11 @@
 
 #define QSEECOM_MAX_SG_ENTRY	512
 
-enum qseecom_command_scm_resp_type {
-	QSEOS_APP_ID = 0xEE01,
-	QSEOS_LISTENER_ID
-};
-
-enum qseecom_qceos_cmd_id {
-	QSEOS_APP_START_COMMAND      = 0x01,
-	QSEOS_APP_SHUTDOWN_COMMAND,
-	QSEOS_APP_LOOKUP_COMMAND,
-	QSEOS_REGISTER_LISTENER,
-	QSEOS_DEREGISTER_LISTENER,
-	QSEOS_CLIENT_SEND_DATA_COMMAND,
-	QSEOS_LISTENER_DATA_RSP_COMMAND,
-	QSEOS_LOAD_EXTERNAL_ELF_COMMAND,
-	QSEOS_UNLOAD_EXTERNAL_ELF_COMMAND,
-	QSEOS_GET_APP_STATE_COMMAND,
-	QSEOS_LOAD_SERV_IMAGE_COMMAND,
-	QSEOS_UNLOAD_SERV_IMAGE_COMMAND,
-	QSEOS_APP_REGION_NOTIFICATION,
-	QSEOS_CMD_MAX     = 0xEFFFFFFF
-};
-
-enum qseecom_qceos_cmd_status {
-	QSEOS_RESULT_SUCCESS = 0,
-	QSEOS_RESULT_INCOMPLETE,
-	QSEOS_RESULT_FAILURE  = 0xFFFFFFFF
-};
-
 enum qseecom_clk_definitions {
 	CLK_DFAB = 0,
 	CLK_SFPB,
 };
 
-__packed  struct qsee_apps_region_info_ireq {
-	uint32_t qsee_cmd_id;
-	uint32_t addr;
-	uint32_t size;
-};
-
-__packed struct qseecom_check_app_ireq {
-	uint32_t qsee_cmd_id;
-	char     app_name[MAX_APP_NAME_SIZE];
-};
-
-__packed struct qseecom_load_app_ireq {
-	uint32_t qsee_cmd_id;
-	uint32_t mdt_len;		/* Length of the mdt file */
-	uint32_t img_len;		/* Length of .bxx and .mdt files */
-	uint32_t phy_addr;		/* phy addr of the start of image */
-	char     app_name[MAX_APP_NAME_SIZE];	/* application name*/
-};
-
-__packed struct qseecom_unload_app_ireq {
-	uint32_t qsee_cmd_id;
-	uint32_t  app_id;
-};
-
-__packed struct qseecom_load_lib_image_ireq {
-	uint32_t qsee_cmd_id;
-	uint32_t mdt_len;
-	uint32_t img_len;
-	uint32_t phy_addr;
-};
-
-__packed struct qseecom_unload_lib_image_ireq {
-	uint32_t qsee_cmd_id;
-};
-
-__packed struct qseecom_register_listener_ireq {
-	uint32_t qsee_cmd_id;
-	uint32_t listener_id;
-	void *sb_ptr;
-	uint32_t sb_len;
-};
-
-__packed struct qseecom_unregister_listener_ireq {
-	uint32_t qsee_cmd_id;
-	uint32_t  listener_id;
-};
-
-__packed struct qseecom_client_send_data_ireq {
-	uint32_t qsee_cmd_id;
-	uint32_t app_id;
-	void *req_ptr;
-	uint32_t req_len;
-	void *rsp_ptr;   /* First 4 bytes should always be the return status */
-	uint32_t rsp_len;
-};
-
-/* send_data resp */
-__packed struct qseecom_client_listener_data_irsp {
-	uint32_t qsee_cmd_id;
-	uint32_t listener_id;
-};
-
-/*
- * struct qseecom_command_scm_resp - qseecom response buffer
- * @cmd_status: value from enum tz_sched_cmd_status
- * @sb_in_rsp_addr: points to physical location of response
- *                buffer
- * @sb_in_rsp_len: length of command response
- */
-__packed struct qseecom_command_scm_resp {
-	uint32_t result;
-	enum qseecom_command_scm_resp_type resp_type;
-	unsigned int data;
-};
-
 static struct class *driver_class;
 static dev_t qseecom_device_no;
 static struct cdev qseecom_cdev;
@@ -586,6 +484,7 @@
 					struct qseecom_command_scm_resp *resp)
 {
 	int ret = 0;
+	int rc = 0;
 	uint32_t lstnr;
 	unsigned long flags;
 	struct qseecom_client_listener_data_irsp send_data_rsp;
@@ -624,8 +523,12 @@
 		if (data->abort) {
 			pr_err("Aborting listener service %d\n",
 				data->listener.id);
-			return -ENODEV;
+			rc = -ENODEV;
+			send_data_rsp.status  = QSEOS_RESULT_FAILURE;
+		} else {
+			send_data_rsp.status  = QSEOS_RESULT_SUCCESS;
 		}
+
 		qseecom.send_resp_flag = 0;
 		send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
 		send_data_rsp.listener_id  = lstnr ;
@@ -644,6 +547,9 @@
 			return -EINVAL;
 		}
 	}
+	if (rc)
+		return rc;
+
 	return ret;
 }
 
@@ -1455,7 +1361,7 @@
 	return ret;
 }
 
-static int qseecom_load_commonlib_image(void)
+static int qseecom_load_commonlib_image(struct qseecom_dev_handle *data)
 {
 	int32_t ret = 0;
 	uint32_t fw_size = 0;
@@ -1482,7 +1388,6 @@
 	ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
 				sizeof(struct qseecom_load_lib_image_ireq),
 							&resp, sizeof(resp));
-	kzfree(img_data);
 	if (ret) {
 		pr_err("scm_call to load failed : ret %d\n", ret);
 		ret = -EIO;
@@ -1495,6 +1400,12 @@
 						resp.result);
 			ret = -EINVAL;
 			break;
+		case  QSEOS_RESULT_INCOMPLETE:
+			ret = __qseecom_process_incomplete_cmd(data, &resp);
+			if (ret)
+				pr_err("process_incomplete_cmd failed err: %d\n",
+					ret);
+			break;
 		default:
 			pr_err("scm call return unknown response %d\n",
 						resp.result);
@@ -1502,6 +1413,7 @@
 			break;
 		}
 	}
+	kzfree(img_data);
 	return ret;
 }
 
@@ -1555,25 +1467,6 @@
 		return -EINVAL;
 	}
 
-	if (qseecom.qsee_version > QSEEE_VERSION_00) {
-		mutex_lock(&app_access_lock);
-		if (qseecom.commonlib_loaded == false) {
-			ret = qseecom_load_commonlib_image();
-			if (ret == 0)
-				qseecom.commonlib_loaded = true;
-		}
-		mutex_unlock(&app_access_lock);
-	}
-
-	if (ret)
-		return -EIO;
-
-	app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
-	memcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
-	ret = __qseecom_check_app_exists(app_ireq);
-	if (ret < 0)
-		return -EINVAL;
-
 	*handle = kzalloc(sizeof(struct qseecom_handle), GFP_KERNEL);
 	if (!(*handle)) {
 		pr_err("failed to allocate memory for kernel client handle\n");
@@ -1610,6 +1503,30 @@
 		return -EINVAL;
 	}
 
+	if (qseecom.qsee_version > QSEEE_VERSION_00) {
+		mutex_lock(&app_access_lock);
+		if (qseecom.commonlib_loaded == false) {
+			ret = qseecom_load_commonlib_image(data);
+			if (ret == 0)
+				qseecom.commonlib_loaded = true;
+		}
+		mutex_unlock(&app_access_lock);
+	}
+
+	if (ret) {
+		pr_err("Failed to loadd commonlib image\n");
+		kfree(data);
+		kfree(*handle);
+		*handle = NULL;
+		return -EIO;
+	}
+
+	app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+	memcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
+	ret = __qseecom_check_app_exists(app_ireq);
+	if (ret < 0)
+		return -EINVAL;
+
 	if (ret > 0) {
 		pr_warn("App id %d for [%s] app exists\n", ret,
 			(char *)app_ireq.app_name);
@@ -2251,7 +2168,7 @@
 		atomic_inc(&data->ioctl_count);
 		if (qseecom.qsee_version > QSEEE_VERSION_00) {
 			if (qseecom.commonlib_loaded == false) {
-				ret = qseecom_load_commonlib_image();
+				ret = qseecom_load_commonlib_image(data);
 				if (ret == 0)
 					qseecom.commonlib_loaded = true;
 			}
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 4708096..9ee19ab 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1725,6 +1725,20 @@
 	mmc_queue_bounce_pre(mqrq);
 }
 
+/**
+ * mmc_blk_disable_wr_packing() - disables packing mode
+ * @mq:	MMC queue.
+ *
+ */
+void mmc_blk_disable_wr_packing(struct mmc_queue *mq)
+{
+	if (mq) {
+		mq->wr_packing_enabled = false;
+		mq->num_of_potential_packed_wr_reqs = 0;
+	}
+}
+EXPORT_SYMBOL(mmc_blk_disable_wr_packing);
+
 static void mmc_blk_write_packing_control(struct mmc_queue *mq,
 					  struct request *req)
 {
@@ -1759,8 +1773,7 @@
 	data_dir = rq_data_dir(req);
 
 	if (data_dir == READ) {
-		mq->num_of_potential_packed_wr_reqs = 0;
-		mq->wr_packing_enabled = false;
+		mmc_blk_disable_wr_packing(mq);
 		return;
 	} else if (data_dir == WRITE) {
 		mq->num_of_potential_packed_wr_reqs++;
@@ -1840,6 +1853,9 @@
 			!IS_ALIGNED(blk_rq_sectors(cur), 8))
 		goto no_packed;
 
+	if (cur->cmd_flags & REQ_FUA)
+		goto no_packed;
+
 	max_blk_count = min(card->host->max_blk_count,
 			card->host->max_req_size >> 9);
 	if (unlikely(max_blk_count > 0xffff))
@@ -1879,6 +1895,12 @@
 			break;
 		}
 
+		if (next->cmd_flags & REQ_FUA) {
+			MMC_BLK_UPDATE_STOP_REASON(stats, FUA);
+			put_back = 1;
+			break;
+		}
+
 		if (rq_data_dir(cur) != rq_data_dir(next)) {
 			MMC_BLK_UPDATE_STOP_REASON(stats, WRONG_DATA_DIR);
 			put_back = 1;
@@ -2103,13 +2125,15 @@
 	mmc_blk_clear_packed(mq_rq);
 	return ret;
 }
-static void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq)
+static void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq,
+					unsigned int cmd_flags)
 {
 	struct request *prq;
 
 	while (!list_empty(&mq_rq->packed_list)) {
 		prq = list_entry_rq(mq_rq->packed_list.next);
 		list_del_init(&prq->queuelist);
+		prq->cmd_flags |= cmd_flags;
 		blk_end_request(prq, -EIO, blk_rq_bytes(prq));
 	}
 
@@ -2292,19 +2316,28 @@
 			ret = blk_end_request(req, -EIO,
 					blk_rq_cur_bytes(req));
 	} else {
-		mmc_blk_abort_packed_req(mq_rq);
+		mmc_blk_abort_packed_req(mq_rq, 0);
 	}
 
  start_new_req:
 	if (rqc) {
-		/*
-		 * If current request is packed, it needs to put back.
-		 */
-		if (mq->mqrq_cur->packed_cmd != MMC_PACKED_NONE)
-			mmc_blk_revert_packed_req(mq, mq->mqrq_cur);
+		if (mmc_card_removed(card)) {
+			if (mq_rq->packed_cmd == MMC_PACKED_NONE) {
+				rqc->cmd_flags |= REQ_QUIET;
+				blk_end_request_all(rqc, -EIO);
+			} else {
+				mmc_blk_abort_packed_req(mq_rq, REQ_QUIET);
+			}
+		} else {
+			/* If current request is packed, it needs to put back */
+			if (mq_rq->packed_cmd != MMC_PACKED_NONE)
+				mmc_blk_revert_packed_req(mq, mq->mqrq_cur);
 
-		mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
-		mmc_start_req(card->host, &mq->mqrq_cur->mmc_active, NULL);
+			mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
+			mmc_start_req(card->host,
+					&mq->mqrq_cur->mmc_active,
+					NULL);
+		}
 	}
 
 	return 0;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c1de8e8..a0a184d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -397,8 +397,21 @@
 	if (!card->ext_csd.bkops_en)
 		return;
 
-	mmc_claim_host(card->host);
+	if ((card->bkops_info.cancel_delayed_work) && !from_exception) {
+		pr_debug("%s: %s: cancel_delayed_work was set, exit\n",
+			 mmc_hostname(card->host), __func__);
+		card->bkops_info.cancel_delayed_work = false;
+		return;
+	}
 
+	/* In case of delayed bkops we might be in race with suspend. */
+	if (!mmc_try_claim_host(card->host))
+		return;
+
+	/*
+	 * Since the cancel_delayed_work can be changed while we are waiting
+	 * for the lock we will to re-check it
+	 */
 	if ((card->bkops_info.cancel_delayed_work) && !from_exception) {
 		pr_debug("%s: %s: cancel_delayed_work was set, exit\n",
 			 mmc_hostname(card->host), __func__);
@@ -595,6 +608,7 @@
 	mrq->host = host;
 	if (mmc_card_removed(host->card)) {
 		mrq->cmd->error = -ENOMEDIUM;
+		mmc_wait_data_done(mrq);
 		return -ENOMEDIUM;
 	}
 	mmc_start_request(host, mrq);
@@ -2580,6 +2594,30 @@
 	return;
 }
 
+static bool mmc_is_vaild_state_for_clk_scaling(struct mmc_host *host)
+{
+	struct mmc_card *card = host->card;
+	u32 status;
+	bool ret = false;
+
+	if (!card)
+		goto out;
+
+	if (mmc_send_status(card, &status)) {
+		pr_err("%s: Get card status fail\n", mmc_hostname(card->host));
+		goto out;
+	}
+
+	switch (R1_CURRENT_STATE(status)) {
+	case R1_STATE_TRAN:
+		ret = true;
+		break;
+	default:
+		break;
+	}
+out:
+	return ret;
+}
 
 /**
  * mmc_clk_scaling() - clock scaling decision algorithm
@@ -2652,6 +2690,10 @@
 			if (!from_wq)
 				cancel_delayed_work_sync(
 						&host->clk_scaling.work);
+
+			if (!mmc_is_vaild_state_for_clk_scaling(host))
+				goto bypass_scaling;
+
 			err = host->bus_ops->change_bus_speed(host, &freq);
 			if (!err)
 				host->clk_scaling.curr_freq = freq;
@@ -2673,6 +2715,7 @@
 	}
 
 	mmc_reset_clk_scale_stats(host);
+bypass_scaling:
 	host->clk_scaling.in_progress = false;
 out:
 	return;
@@ -3148,11 +3191,9 @@
 
 		if (!err) {
 			if (host->bus_ops->suspend) {
-				if (mmc_card_doing_bkops(host->card)) {
-					err = mmc_stop_bkops(host->card);
-					if (err)
-						goto stop_bkops_err;
-				}
+				err = mmc_stop_bkops(host->card);
+				if (err)
+					goto stop_bkops_err;
 				err = host->bus_ops->suspend(host);
 				MMC_UPDATE_BKOPS_STATS_SUSPEND(host->
 						card->bkops_info.bkops_stats);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 931ddb0..8b7e0bd 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -491,6 +491,13 @@
 			pack_stats->pack_stop_reason[RANDOM]);
 		strlcat(ubuf, temp_buf, cnt);
 	}
+	if (pack_stats->pack_stop_reason[FUA]) {
+		snprintf(temp_buf, TEMP_BUF_SIZE,
+			 "%s: %d times: fua request\n",
+			mmc_hostname(card->host),
+			pack_stats->pack_stop_reason[FUA]);
+		strlcat(ubuf, temp_buf, cnt);
+	}
 
 	spin_unlock(&pack_stats->lock);
 
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index a9f7819..0e6956f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -292,7 +292,7 @@
 	}
 
 	card->ext_csd.rev = ext_csd[EXT_CSD_REV];
-	if (card->ext_csd.rev > 6) {
+	if (card->ext_csd.rev > 7) {
 		printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n",
 			mmc_hostname(card->host), card->ext_csd.rev);
 		err = -EINVAL;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 2fedc97..de6db41 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -125,6 +125,9 @@
 	0xFFFFBBBB, 0xFFFF77FF, 0xFF7777FF, 0xEEDDBB77
 };
 
+static int disable_slots;
+module_param(disable_slots, int, 0);
+
 #if IRQ_DEBUG == 1
 static char *irq_status_bits[] = { "cmdcrcfail", "datcrcfail", "cmdtimeout",
 				   "dattimeout", "txunderrun", "rxoverrun",
@@ -4277,35 +4280,40 @@
 	if (!card || !mmc_card_sd(card))
 		return;
 
-	/*
-	 * Continuing on failing to disable regulator would lead to a panic
-	 * anyway, since the commands would fail and console would be flooded
-	 * with prints, eventually leading to a watchdog bark
-	 */
-	rc = msmsdcc_setup_vreg(host, false, false);
-	if (rc) {
-		pr_err("%s: %s disable regulator: failed: %d\n",
-		       mmc_hostname(mmc), __func__, rc);
-		BUG_ON(rc);
+	pr_debug("%s: Starting h/w reset\n", mmc_hostname(host->mmc));
+
+	if (host->plat->translate_vdd || host->plat->vreg_data) {
+
+		/* Disable the regulators */
+		if (host->plat->translate_vdd)
+			rc = host->plat->translate_vdd(mmc_dev(mmc), 0);
+		else if (host->plat->vreg_data)
+			rc = msmsdcc_setup_vreg(host, false, false);
+
+		if (rc) {
+			pr_err("%s: Failed to disable voltage regulator\n",
+				mmc_hostname(host->mmc));
+			BUG_ON(rc);
+		}
+
+		/* 10ms delay for supply to reach the desired voltage level */
+		usleep_range(10000, 12000);
+
+		/* Enable the regulators */
+		if (host->plat->translate_vdd)
+			rc = host->plat->translate_vdd(mmc_dev(mmc), 1);
+		else if (host->plat->vreg_data)
+			rc = msmsdcc_setup_vreg(host, true, false);
+
+		if (rc) {
+			pr_err("%s: Failed to enable voltage regulator\n",
+				mmc_hostname(host->mmc));
+			BUG_ON(rc);
+		}
+
+		/* 10ms delay for supply to reach the desired voltage level */
+		usleep_range(10000, 12000);
 	}
-
-	/* 10ms delay for the supply to reach the desired voltage level */
-	usleep_range(10000, 12000);
-
-	/*
-	 * Continuing on failing to enable regulator would lead to a panic
-	 * anyway, since the commands would fail and console would be flooded
-	 * with prints, eventually leading to a watchdog bark
-	 */
-	rc = msmsdcc_setup_vreg(host, true, false);
-	if (rc) {
-		pr_err("%s: %s enable regulator: failed: %d\n",
-		       mmc_hostname(mmc), __func__, rc);
-		BUG_ON(rc);
-	}
-
-	/* 10ms delay for the supply to reach the desired voltage level */
-	usleep_range(10000, 12000);
 }
 
 static const struct mmc_host_ops msmsdcc_ops = {
@@ -5772,6 +5780,11 @@
 		goto out;
 	}
 
+	if (disable_slots & (1 << (pdev->id - 1))) {
+		pr_info("%s: Slot %d disabled\n", __func__, pdev->id);
+		return -ENODEV;
+	}
+
 	if (pdev->id < 1 || pdev->id > 5)
 		return -EINVAL;
 
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 877120c..4eceb47 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -503,7 +503,7 @@
 				 MSMSDCC_DATA_PEND_FOR_CMD53 |
 				 MSMSDCC_TESTBUS_DEBUG;
 
-	if (step == 0x2b)
+	if ((step == 0x2b) || (step == 0x38))
 		host->hw_caps |= MSMSDCC_SW_RST_CFG_BROKEN;
 }
 
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5278324..5ccdd2a 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -295,7 +295,6 @@
 
 config WCNSS_CORE
 	tristate "Qualcomm WCNSS CORE driver"
-	depends on (ARCH_MSM8960 || ARCH_MSM8974)
 	select WIRELESS_EXT
 	select WEXT_PRIV
 	select WEXT_CORE
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 569f943..1064086 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -808,7 +808,7 @@
 	 *  Discover the hardware version number and the number of pipes
 	 *  supported by this BAM
 	 */
-	*num_pipes = bam_read_reg(base, NUM_PIPES);
+	*num_pipes = bam_read_reg_field(base, NUM_PIPES, BAM_NUM_PIPES);
 	*version = ver;
 
 	/* Check BAM version */
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 4a95780..adfebfa 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1037,18 +1037,10 @@
 		raw->last_good_ocv_uv = chip->last_ocv_uv;
 	}
 
-	/* fake a high OCV if we are just done charging */
+	/* stop faking 100% after an OCV event */
 	if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
 		chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
 		chip->cc_reading_at_100 = 0;
-	} else {
-		/*
-		 * force 100% ocv by selecting the highest voltage the
-		 * battery could ever reach
-		 */
-		raw->last_good_ocv_uv = chip->max_voltage_uv;
-		chip->last_ocv_uv = chip->max_voltage_uv;
-		chip->last_ocv_temp_decidegc = batt_temp_decidegc;
 	}
 	pr_debug("0p625 = %duV\n", chip->xoadc_v0625);
 	pr_debug("1p25 = %duV\n", chip->xoadc_v125);
@@ -2618,6 +2610,7 @@
 
 		the_chip->last_ocv_uv = the_chip->max_voltage_uv;
 		raw.last_good_ocv_uv = the_chip->max_voltage_uv;
+		the_chip->last_ocv_temp_decidegc = batt_temp;
 		/*
 		 * since we are treating this as an ocv event
 		 * forget the old cc value
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 7eb285b..63fb0a5 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -175,6 +175,7 @@
 	POWER_SUPPLY_ATTR(time_to_full_avg),
 	POWER_SUPPLY_ATTR(type),
 	POWER_SUPPLY_ATTR(scope),
+	POWER_SUPPLY_ATTR(system_temp_level),
 	/* Properties of type `const char *' */
 	POWER_SUPPLY_ATTR(model_name),
 	POWER_SUPPLY_ATTR(manufacturer),
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 63cab43..85a310a 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -117,10 +117,10 @@
 	int				charger_status;
 	bool				online;
 	/* platform data */
-	unsigned int			r_sense_mohm;
+	int				r_sense_uohm;
 	unsigned int			v_cutoff_uv;
-	unsigned int			max_voltage_uv;
-	unsigned int			r_conn_mohm;
+	int				max_voltage_uv;
+	int				r_conn_mohm;
 	int				shutdown_soc_valid_limit;
 	int				adjust_soc_low_threshold;
 	int				adjust_soc_high_threshold;
@@ -141,6 +141,7 @@
 	struct mutex			soc_invalidation_mutex;
 
 	bool				use_external_rsense;
+	bool				use_ocv_thresholds;
 
 	bool				ignore_shutdown_soc;
 	int				shutdown_soc_invalid;
@@ -150,11 +151,13 @@
 	int				low_soc_calc_threshold;
 	int				low_soc_calculate_soc_ms;
 	int				calculate_soc_ms;
+	struct wake_lock		soc_wake_lock;
 
 	uint16_t			ocv_reading_at_100;
 	int64_t				cc_reading_at_100;
 	uint16_t			prev_last_good_ocv_raw;
 	int				last_ocv_uv;
+	int				last_ocv_temp;
 	int				last_cc_uah;
 	unsigned long			tm_sec;
 	bool				first_time_calc_soc;
@@ -185,6 +188,10 @@
 	int				calculated_soc;
 	int				prev_voltage_based_soc;
 	bool				use_voltage_soc;
+
+	int				ocv_high_threshold_uv;
+	int				ocv_low_threshold_uv;
+	unsigned long			last_recalc_time;
 };
 
 static struct of_device_id qpnp_bms_match_table[] = {
@@ -299,7 +306,7 @@
 #define V_PER_BIT_DIV_FACTOR	1000
 #define VADC_INTRINSIC_OFFSET	0x6000
 
-static int vadc_reading_to_uv(unsigned int reading)
+static int vadc_reading_to_uv(int reading)
 {
 	if (reading <= VADC_INTRINSIC_OFFSET)
 		return 0;
@@ -311,8 +318,7 @@
 #define VADC_CALIB_UV		625000
 #define VBATT_MUL_FACTOR	3
 
-static int adjust_vbatt_reading(struct qpnp_bms_chip *chip,
-						unsigned int reading_uv)
+static int adjust_vbatt_reading(struct qpnp_bms_chip *chip, int reading_uv)
 {
 	s64 numerator, denominator;
 
@@ -334,6 +340,17 @@
 						* VBATT_MUL_FACTOR;
 }
 
+static int convert_vbatt_uv_to_raw(struct qpnp_bms_chip *chip,
+					int unadjusted_vbatt)
+{
+	int scaled_vbatt = unadjusted_vbatt / VBATT_MUL_FACTOR;
+
+	if (scaled_vbatt <= 0)
+		return VADC_INTRINSIC_OFFSET;
+	return ((scaled_vbatt * V_PER_BIT_DIV_FACTOR) / V_PER_BIT_MUL_FACTOR)
+						+ VADC_INTRINSIC_OFFSET;
+}
+
 static inline int convert_vbatt_raw_to_uv(struct qpnp_bms_chip *chip,
 					uint16_t reading)
 {
@@ -354,7 +371,7 @@
 					CC_READING_RESOLUTION_D);
 }
 
-#define QPNP_ADC_GAIN_NV				17857LL
+#define QPNP_ADC_GAIN_IDEAL				3291LL
 static s64 cc_adjust_for_gain(s64 uv, uint16_t gain)
 {
 	s64 result_uv;
@@ -365,10 +382,10 @@
 		return uv;
 	}
 	pr_debug("adjusting by factor: %lld/%hu = %lld%%\n",
-			QPNP_ADC_GAIN_NV, gain,
-			div_s64(QPNP_ADC_GAIN_NV * 100LL, (s64)gain));
+			QPNP_ADC_GAIN_IDEAL, gain,
+			div_s64(QPNP_ADC_GAIN_IDEAL * 100LL, (s64)gain));
 
-	result_uv = div_s64(uv * QPNP_ADC_GAIN_NV, (s64)gain);
+	result_uv = div_s64(uv * QPNP_ADC_GAIN_IDEAL, (s64)gain);
 	pr_debug("result_uv = %lld\n", result_uv);
 	return result_uv;
 }
@@ -380,7 +397,7 @@
 
 	qpnp_iadc_get_gain_and_offset(&calibration);
 	return cc_adjust_for_gain(cc_reading_to_uv(reading),
-			calibration.gain_raw);
+			calibration.gain_raw - calibration.offset_raw);
 }
 
 static int read_vsense_avg(struct qpnp_bms_chip *chip, int *result_uv)
@@ -404,7 +421,7 @@
 {
 	int vsense_uv = 0;
 
-	if (chip->r_sense_mohm == 0) {
+	if (chip->r_sense_uohm == 0) {
 		pr_err("r_sense is zero\n");
 		return -EINVAL;
 	}
@@ -417,7 +434,7 @@
 
 	pr_debug("vsense_uv=%duV\n", vsense_uv);
 	/* cast for signed division */
-	*result_ua = vsense_uv * 1000 / (int)chip->r_sense_mohm;
+	*result_ua = div_s64((vsense_uv * 1000000LL), (int)chip->r_sense_uohm);
 	pr_debug("ibat=%duA\n", *result_ua);
 	return 0;
 }
@@ -487,7 +504,8 @@
 }
 
 static void convert_and_store_ocv(struct qpnp_bms_chip *chip,
-				struct raw_soc_params *raw)
+				struct raw_soc_params *raw,
+				int batt_temp)
 {
 	int rc;
 
@@ -501,6 +519,7 @@
 	raw->last_good_ocv_uv = convert_vbatt_raw_to_uv(chip,
 					raw->last_good_ocv_raw);
 	chip->last_ocv_uv = raw->last_good_ocv_uv;
+	chip->last_ocv_temp = batt_temp;
 	pr_debug("last_good_ocv_uv = %d\n", raw->last_good_ocv_uv);
 }
 
@@ -532,14 +551,16 @@
 		pr_err("cc reenable failed: %d\n", rc);
 }
 
+#define OCV_RAW_UNINITIALIZED	0xFFFF
 static int read_soc_params_raw(struct qpnp_bms_chip *chip,
-				struct raw_soc_params *raw)
+				struct raw_soc_params *raw,
+				int batt_temp)
 {
 	int rc;
 
 	mutex_lock(&chip->bms_output_lock);
 
-	if (chip->prev_last_good_ocv_raw == 0) {
+	if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
 		/* software workaround for BMS 1.0
 		 * The coulomb counter does not reset upon PON, so reset it
 		 * manually upon probe. */
@@ -565,11 +586,11 @@
 	unlock_output_data(chip);
 	mutex_unlock(&chip->bms_output_lock);
 
-	if (chip->prev_last_good_ocv_raw == 0) {
-		convert_and_store_ocv(chip, raw);
+	if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
+		convert_and_store_ocv(chip, raw, batt_temp);
 		pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
 	} else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
-		convert_and_store_ocv(chip, raw);
+		convert_and_store_ocv(chip, raw, batt_temp);
 		/* forget the old cc value upon ocv */
 		chip->last_cc_uah = INT_MIN;
 	} else {
@@ -578,7 +599,7 @@
 
 	/* fake a high OCV if done charging */
 	if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
-		chip->ocv_reading_at_100 = 0;
+		chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
 		chip->cc_reading_at_100 = 0;
 	} else {
 		/*
@@ -587,6 +608,7 @@
 		 */
 		raw->last_good_ocv_uv = chip->max_voltage_uv;
 		chip->last_ocv_uv = chip->max_voltage_uv;
+		chip->last_ocv_temp = batt_temp;
 	}
 	pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
 			raw->last_good_ocv_raw, raw->last_good_ocv_uv);
@@ -626,13 +648,12 @@
 /* calculate remaining charge at the time of ocv */
 static int calculate_ocv_charge(struct qpnp_bms_chip *chip,
 						struct raw_soc_params *raw,
-						int fcc_uah,
-						int batt_temp)
+						int fcc_uah)
 {
 	int  ocv_uv, pc;
 
 	ocv_uv = raw->last_good_ocv_uv;
-	pc = calculate_pc(chip, ocv_uv, batt_temp);
+	pc = calculate_pc(chip, ocv_uv, chip->last_ocv_temp);
 	pr_debug("ocv_uv = %d pc = %d\n", ocv_uv, pc);
 	return (fcc_uah * pc) / 100;
 }
@@ -649,9 +670,9 @@
 #define SLEEP_CLK_HZ		32764
 #define SECONDS_PER_HOUR	3600
 
-static s64 cc_uv_to_nvh(s64 cc_uv)
+static s64 cc_uv_to_uvh(s64 cc_uv)
 {
-	return div_s64(cc_uv * CC_READING_TICKS * 1000,
+	return div_s64(cc_uv * CC_READING_TICKS,
 			SLEEP_CLK_HZ * SECONDS_PER_HOUR);
 }
 
@@ -667,7 +688,7 @@
  */
 static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc)
 {
-	int64_t cc_voltage_uv, cc_nvh, cc_uah;
+	int64_t cc_voltage_uv, cc_uvh, cc_uah;
 	struct qpnp_iadc_calib calibration;
 
 	qpnp_iadc_get_gain_and_offset(&calibration);
@@ -677,11 +698,13 @@
 					cc, chip->cc_reading_at_100,
 					cc_voltage_uv);
 	cc_voltage_uv = cc_to_uv(cc_voltage_uv);
-	cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv, calibration.gain_raw);
+	cc_voltage_uv = cc_adjust_for_gain(cc_voltage_uv,
+					calibration.gain_raw
+					- calibration.offset_raw);
 	pr_debug("cc_voltage_uv = %lld uv\n", cc_voltage_uv);
-	cc_nvh = cc_uv_to_nvh(cc_voltage_uv);
-	pr_debug("cc_nvh = %lld nano_volt_hour\n", cc_nvh);
-	cc_uah = div_s64(cc_nvh, chip->r_sense_mohm);
+	cc_uvh = cc_uv_to_uvh(cc_voltage_uv);
+	pr_debug("cc_uvh = %lld micro_volt_hour\n", cc_uvh);
+	cc_uah = div_s64(cc_uvh * 1000000LL, chip->r_sense_uohm);
 	/* cc_raw had 4 bits of extra precision.
 	   By now it should be within 32 bit range */
 	return (int)cc_uah;
@@ -842,7 +865,7 @@
 	return new_uuc_uah;
 }
 
-#define CHARGING_IAVG_MA 250
+#define MIN_IAVG_MA 250
 #define MIN_SECONDS_FOR_VALID_SAMPLE	20
 static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
 					struct soc_params *params,
@@ -871,8 +894,8 @@
 	 * if charging use a nominal avg current to keep
 	 * a reasonable UUC while charging
 	 */
-	if (uuc_iavg_ma < 0)
-		uuc_iavg_ma = CHARGING_IAVG_MA;
+	if (uuc_iavg_ma < MIN_IAVG_MA)
+		uuc_iavg_ma = MIN_IAVG_MA;
 	chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
 	chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
 	chip->iavg_num_samples++;
@@ -898,8 +921,8 @@
 	if (bms_reset)
 		return (params->fcc_uah * 3) / 100;
 
-	uuc_uah_iavg = calculate_termination_uuc(chip, params, uuc_iavg_ma,
-						batt_temp, &pc_unusable);
+	uuc_uah_iavg = calculate_termination_uuc(chip, params, batt_temp,
+						uuc_iavg_ma, &pc_unusable);
 	pr_debug("uuc_iavg_ma = %d uuc with iavg = %d\n",
 						uuc_iavg_ma, uuc_uah_iavg);
 
@@ -1022,8 +1045,7 @@
 	/* calculate remainging charge */
 	params->ocv_charge_uah = calculate_ocv_charge(
 						chip, raw,
-						params->fcc_uah,
-						batt_temp);
+						params->fcc_uah);
 	pr_debug("ocv_charge_uah = %uuAh\n", params->ocv_charge_uah);
 
 	/* calculate cc micro_volt_hour */
@@ -1111,7 +1133,7 @@
 
 	*vbat_uv = convert_vbatt_raw_to_uv(chip, vbat_raw);
 	vsense_uv = convert_vsense_to_uv(chip, vsense_raw);
-	*ibat_ua = vsense_uv * 1000 / (int)chip->r_sense_mohm;
+	*ibat_ua = div_s64(vsense_uv * 1000000LL, (int)chip->r_sense_uohm);
 
 	pr_debug("vsense_raw = 0x%x vbat_raw = 0x%x ibat_ua = %d vbat_uv = %d\n",
 			(uint16_t)vsense_raw, (uint16_t)vbat_raw,
@@ -1261,14 +1283,15 @@
 				int vbat_uv, int ibat_ua, int batt_temp)
 {
 	int chg_soc;
+	int batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
 
 	if (chip->soc_at_cv == -EINVAL) {
 		/* In constant current charging return the calc soc */
-		if (vbat_uv <= chip->max_voltage_uv)
+		if (batt_terminal_uv <= chip->max_voltage_uv)
 			pr_debug("CC CHG SOC %d\n", soc);
 
 		/* Note the CC to CV point */
-		if (vbat_uv >= chip->max_voltage_uv) {
+		if (batt_terminal_uv >= chip->max_voltage_uv) {
 			chip->soc_at_cv = soc;
 			chip->prev_chg_soc = soc;
 			chip->ibat_at_cv_ua = ibat_ua;
@@ -1287,14 +1310,15 @@
 	 * if voltage lessened (possibly because of a system load)
 	 * keep reporting the prev chg soc
 	 */
-	if (vbat_uv <= chip->max_voltage_uv) {
-		pr_debug("vbat %d < max = %d CC CHG SOC %d\n",
-			vbat_uv, chip->max_voltage_uv, chip->prev_chg_soc);
+	if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
+		pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
+			batt_terminal_uv,
+			chip->max_voltage_uv, chip->prev_chg_soc);
 		return chip->prev_chg_soc;
 	}
 
 	chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
-					100, -100000,
+					100, -1 * chip->chg_term_ua,
 					ibat_ua);
 	chg_soc = bound_soc(chg_soc);
 
@@ -1381,17 +1405,17 @@
 	n = min(200, max(1 , soc + soc_est + chip->last_soc_est));
 	chip->last_soc_est = soc_est;
 
-	pc = calculate_pc(chip, chip->last_ocv_uv, batt_temp);
+	pc = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
 	if (pc > 0) {
 		pc_new = calculate_pc(chip,
 				chip->last_ocv_uv - (++slope * 1000),
-				batt_temp);
+				chip->last_ocv_temp);
 		while (pc_new == pc) {
 			/* start taking 10mV steps */
 			slope = slope + 10;
 			pc_new = calculate_pc(chip,
 				chip->last_ocv_uv - (slope * 1000),
-				batt_temp);
+				chip->last_ocv_temp);
 		}
 	} else {
 		/*
@@ -1423,7 +1447,7 @@
 		chip->last_ocv_uv = chip->max_voltage_uv;
 
 	/* calculate the soc based on this new ocv */
-	pc_new = calculate_pc(chip, chip->last_ocv_uv, batt_temp);
+	pc_new = calculate_pc(chip, chip->last_ocv_uv, chip->last_ocv_temp);
 	rc_new_uah = (params->fcc_uah * pc_new) / 100;
 	soc_new = (rc_new_uah - params->cc_uah - params->uuc_uah)*100
 					/ (params->fcc_uah - params->uuc_uah);
@@ -1494,13 +1518,13 @@
 		pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
 						params.fcc_uah,
 						params.uuc_uah);
-		soc = 0;
-	} else {
-		soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
-					(params.fcc_uah
-						- params.uuc_uah));
+		new_calculated_soc = 0;
+		goto done_calculating;
 	}
 
+	soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
+				(params.fcc_uah - params.uuc_uah));
+
 	if (chip->first_time_calc_soc && soc < 0) {
 		/*
 		 * first time calcualtion and the pon ocv  is too low resulting
@@ -1574,6 +1598,7 @@
 		new_calculated_soc = clamp_soc_based_on_voltage(chip,
 						new_calculated_soc);
 
+done_calculating:
 	if (new_calculated_soc != chip->calculated_soc
 			&& chip->bms_psy.name != NULL) {
 		power_supply_changed(&chip->bms_psy);
@@ -1583,6 +1608,7 @@
 	chip->calculated_soc = new_calculated_soc;
 	pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
 	chip->first_time_calc_soc = 0;
+	get_current_time(&chip->last_recalc_time);
 	return chip->calculated_soc;
 }
 
@@ -1626,15 +1652,13 @@
 	return voltage_based_soc;
 }
 
-static void calculate_soc_work(struct work_struct *work)
+static int recalculate_soc(struct qpnp_bms_chip *chip)
 {
-	struct qpnp_bms_chip *chip = container_of(work,
-				struct qpnp_bms_chip,
-				calculate_soc_delayed_work.work);
 	int batt_temp, rc, soc;
 	struct qpnp_vadc_result result;
 	struct raw_soc_params raw;
 
+	wake_lock(&chip->soc_wake_lock);
 	if (chip->use_voltage_soc) {
 		soc = calculate_soc_from_voltage(chip);
 	} else {
@@ -1642,18 +1666,29 @@
 		if (rc) {
 			pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
 						LR_MUX1_BATT_THERM, rc);
-			return;
-		}
-		pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
-						result.physical,
-						result.measurement);
-		batt_temp = (int)result.physical;
+			soc = chip->calculated_soc;
+		} else {
+			pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
+							result.physical,
+							result.measurement);
+			batt_temp = (int)result.physical;
 
-		mutex_lock(&chip->last_ocv_uv_mutex);
-		read_soc_params_raw(chip, &raw);
-		soc = calculate_state_of_charge(chip, &raw, batt_temp);
-		mutex_unlock(&chip->last_ocv_uv_mutex);
+			mutex_lock(&chip->last_ocv_uv_mutex);
+			read_soc_params_raw(chip, &raw, batt_temp);
+			soc = calculate_state_of_charge(chip, &raw, batt_temp);
+			mutex_unlock(&chip->last_ocv_uv_mutex);
+		}
 	}
+	wake_unlock(&chip->soc_wake_lock);
+	return soc;
+}
+
+static void calculate_soc_work(struct work_struct *work)
+{
+	struct qpnp_bms_chip *chip = container_of(work,
+				struct qpnp_bms_chip,
+				calculate_soc_delayed_work.work);
+	int soc = recalculate_soc(chip);
 
 	if (soc < chip->low_soc_calc_threshold)
 		schedule_delayed_work(&chip->calculate_soc_delayed_work,
@@ -1949,6 +1984,43 @@
 	return 0;
 }
 
+#define OCV_USE_LIMIT_EN		BIT(7)
+static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
+					int low_voltage_threshold,
+					int high_voltage_threshold)
+{
+	uint16_t low_voltage_raw, high_voltage_raw;
+	int rc;
+
+	low_voltage_raw = convert_vbatt_uv_to_raw(chip,
+				low_voltage_threshold);
+	high_voltage_raw = convert_vbatt_uv_to_raw(chip,
+				high_voltage_threshold);
+	rc = qpnp_write_wrapper(chip, (u8 *)&low_voltage_raw,
+			chip->base + BMS1_OCV_USE_LOW_LIMIT_THR0, 2);
+	if (rc) {
+		pr_err("Failed to set ocv low voltage threshold: %d\n", rc);
+		return rc;
+	}
+	rc = qpnp_write_wrapper(chip, (u8 *)&high_voltage_raw,
+			chip->base + BMS1_OCV_USE_HIGH_LIMIT_THR0, 2);
+	if (rc) {
+		pr_err("Failed to set ocv high voltage threshold: %d\n", rc);
+		return rc;
+	}
+	rc = qpnp_masked_write(chip, BMS1_OCV_USE_LIMIT_CTL,
+				OCV_USE_LIMIT_EN, OCV_USE_LIMIT_EN);
+	if (rc) {
+		pr_err("Failed to enabled ocv voltage thresholds: %d\n", rc);
+		return rc;
+	}
+	pr_debug("ocv low threshold set to %d uv or 0x%x raw\n",
+				low_voltage_threshold, low_voltage_raw);
+	pr_debug("ocv high threshold set to %d uv or 0x%x raw\n",
+				high_voltage_threshold, high_voltage_raw);
+	return 0;
+}
+
 static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
 {
 	int rc;
@@ -2023,59 +2095,54 @@
 static int set_battery_data(struct qpnp_bms_chip *chip)
 {
 	int64_t battery_id;
+	struct bms_battery_data *batt_data;
 
-	if (chip->batt_type == BATT_DESAY)
-		goto desay;
-	else if (chip->batt_type == BATT_PALLADIUM)
-		goto palladium;
-
-	battery_id = read_battery_id(chip);
-	if (battery_id < 0) {
-		pr_err("cannot read battery id err = %lld\n", battery_id);
-		return battery_id;
-	}
-
-	if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX, battery_id)) {
-		goto palladium;
-	} else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
-				battery_id)) {
-		goto desay;
+	if (chip->batt_type == BATT_DESAY) {
+		batt_data = &desay_5200_data;
+	} else if (chip->batt_type == BATT_PALLADIUM) {
+		batt_data = &palladium_1500_data;
+	} else if (chip->batt_type == BATT_OEM) {
+		batt_data = &oem_batt_data;
 	} else {
-		pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
-				battery_id);
-		goto palladium;
+		battery_id = read_battery_id(chip);
+		if (battery_id < 0) {
+			pr_err("cannot read battery id err = %lld\n",
+							battery_id);
+			return battery_id;
+		}
+
+		if (is_between(PALLADIUM_ID_MIN, PALLADIUM_ID_MAX,
+							battery_id)) {
+			batt_data = &palladium_1500_data;
+		} else if (is_between(DESAY_5200_ID_MIN, DESAY_5200_ID_MAX,
+					battery_id)) {
+			batt_data = &desay_5200_data;
+		} else {
+			pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
+					battery_id);
+			batt_data = &palladium_1500_data;
+		}
 	}
 
-palladium:
-		chip->fcc = palladium_1500_data.fcc;
-		chip->fcc_temp_lut = palladium_1500_data.fcc_temp_lut;
-		chip->fcc_sf_lut = palladium_1500_data.fcc_sf_lut;
-		chip->pc_temp_ocv_lut = palladium_1500_data.pc_temp_ocv_lut;
-		chip->pc_sf_lut = palladium_1500_data.pc_sf_lut;
-		chip->rbatt_sf_lut = palladium_1500_data.rbatt_sf_lut;
-		chip->default_rbatt_mohm
-				= palladium_1500_data.default_rbatt_mohm;
-		goto check_lut;
-desay:
-		chip->fcc = desay_5200_data.fcc;
-		chip->fcc_temp_lut = desay_5200_data.fcc_temp_lut;
-		chip->pc_temp_ocv_lut = desay_5200_data.pc_temp_ocv_lut;
-		chip->pc_sf_lut = desay_5200_data.pc_sf_lut;
-		chip->rbatt_sf_lut = desay_5200_data.rbatt_sf_lut;
-		chip->default_rbatt_mohm = desay_5200_data.default_rbatt_mohm;
-		goto check_lut;
-check_lut:
-		if (chip->pc_temp_ocv_lut == NULL) {
-			pr_err("temp ocv lut table is NULL\n");
-			return -EINVAL;
-		}
-		return 0;
+	chip->fcc = batt_data->fcc;
+	chip->fcc_temp_lut = batt_data->fcc_temp_lut;
+	chip->fcc_sf_lut = batt_data->fcc_sf_lut;
+	chip->pc_temp_ocv_lut = batt_data->pc_temp_ocv_lut;
+	chip->pc_sf_lut = batt_data->pc_sf_lut;
+	chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
+	chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
+
+	if (chip->pc_temp_ocv_lut == NULL) {
+		pr_err("temp ocv lut table is NULL\n");
+		return -EINVAL;
+	}
+	return 0;
 }
 
 #define SPMI_PROP_READ(chip_prop, qpnp_spmi_property, retval)		\
 do {									\
 	retval = of_property_read_u32(chip->spmi->dev.of_node,		\
-				"qcom,bms-" qpnp_spmi_property,		\
+				"qcom," qpnp_spmi_property,		\
 					&chip->chip_prop);		\
 	if (retval) {							\
 		pr_err("Error reading " #qpnp_spmi_property		\
@@ -2088,7 +2155,7 @@
 {
 	int rc;
 
-	SPMI_PROP_READ(r_sense_mohm, "r-sense-mohm", rc);
+	SPMI_PROP_READ(r_sense_uohm, "r-sense-uohm", rc);
 	SPMI_PROP_READ(v_cutoff_uv, "v-cutoff-uv", rc);
 	SPMI_PROP_READ(max_voltage_uv, "max-voltage-uv", rc);
 	SPMI_PROP_READ(r_conn_mohm, "r-conn-mohm", rc);
@@ -2107,18 +2174,25 @@
 	SPMI_PROP_READ(calculate_soc_ms, "calculate-soc-ms", rc);
 	chip->use_external_rsense = of_property_read_bool(
 			chip->spmi->dev.of_node,
-			"qcom,bms-use-external-rsense");
+			"qcom,use-external-rsense");
 	chip->ignore_shutdown_soc = of_property_read_bool(
 			chip->spmi->dev.of_node,
-			"qcom,bms-ignore-shutdown-soc");
+			"qcom,ignore-shutdown-soc");
 	chip->use_voltage_soc = of_property_read_bool(chip->spmi->dev.of_node,
-			"qcom,bms-use-voltage-soc");
+			"qcom,use-voltage-soc");
+	chip->use_ocv_thresholds = of_property_read_bool(
+			chip->spmi->dev.of_node,
+			"qcom,use-ocv-thresholds");
+	SPMI_PROP_READ(ocv_high_threshold_uv,
+			"ocv-voltage-high-threshold-uv", rc);
+	SPMI_PROP_READ(ocv_low_threshold_uv,
+			"ocv-voltage-low-threshold-uv", rc);
 
 	if (chip->adjust_soc_low_threshold >= 45)
 		chip->adjust_soc_low_threshold = 45;
 
-	pr_debug("dts data: r_sense_mohm:%d, v_cutoff_uv:%d, max_v:%d\n",
-			chip->r_sense_mohm, chip->v_cutoff_uv,
+	pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
+			chip->r_sense_uohm, chip->v_cutoff_uv,
 			chip->max_voltage_uv);
 	pr_debug("r_conn:%d, shutdown_soc: %d, adjust_soc_low:%d\n",
 			chip->r_conn_mohm, chip->shutdown_soc_valid_limit,
@@ -2140,6 +2214,8 @@
 	chip->last_soc = -EINVAL;
 	chip->last_soc_est = -EINVAL;
 	chip->last_cc_uah = INT_MIN;
+	chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
+	chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
 	chip->first_time_calc_soc = 1;
 	chip->first_time_calc_uuc = 1;
 }
@@ -2272,9 +2348,9 @@
 								rc);
 			return rc;
 		}
-		chip->r_sense_mohm = rds_rsense_nohm/1000000;
-		pr_debug("rds_rsense = %d nOhm, saved as %d mOhm\n",
-					rds_rsense_nohm, chip->r_sense_mohm);
+		chip->r_sense_uohm = rds_rsense_nohm/1000;
+		pr_debug("rds_rsense = %d nOhm, saved as %d uOhm\n",
+					rds_rsense_nohm, chip->r_sense_uohm);
 	}
 	return 0;
 }
@@ -2336,6 +2412,17 @@
 		goto error_read;
 	}
 
+	if (chip->use_ocv_thresholds) {
+		rc = set_ocv_voltage_thresholds(chip,
+				chip->ocv_low_threshold_uv,
+				chip->ocv_high_threshold_uv);
+		if (rc) {
+			pr_err("Could not set ocv voltage thresholds: %d\n",
+					rc);
+			goto error_read;
+		}
+	}
+
 	rc = set_battery_data(chip);
 	if (rc) {
 		pr_err("Bad battery data %d\n", rc);
@@ -2348,6 +2435,8 @@
 	mutex_init(&chip->last_ocv_uv_mutex);
 	mutex_init(&chip->soc_invalidation_mutex);
 
+	wake_lock_init(&chip->soc_wake_lock, WAKE_LOCK_SUSPEND,
+			"qpnp_soc_lock");
 	INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
 			calculate_soc_work);
 
@@ -2380,12 +2469,13 @@
 	vbatt = 0;
 	get_battery_voltage(&vbatt);
 
-	pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_mohm = %u\n",
+	pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_uohm = %u\n",
 				get_prop_bms_capacity(chip),
-				vbatt, chip->last_ocv_uv, chip->r_sense_mohm);
+				vbatt, chip->last_ocv_uv, chip->r_sense_uohm);
 	return 0;
 
 unregister_dc:
+	wake_lock_destroy(&chip->soc_wake_lock);
 	power_supply_unregister(&chip->bms_psy);
 	dev_set_drvdata(&spmi->dev, NULL);
 error_resource:
@@ -2404,6 +2494,38 @@
 	return 0;
 }
 
+static int bms_resume(struct device *dev)
+{
+	int rc;
+	unsigned long soc_calc_period;
+	unsigned long time_since_last_recalc;
+	unsigned long tm_now_sec;
+	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
+
+	rc = get_current_time(&tm_now_sec);
+	if (rc) {
+		pr_err("Could not read current time: %d\n", rc);
+	} else if (tm_now_sec > chip->last_recalc_time) {
+		time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
+		pr_debug("Time since last recalc: %lu\n",
+				time_since_last_recalc);
+		if (chip->calculated_soc < chip->low_soc_calc_threshold)
+			soc_calc_period = chip->low_soc_calculate_soc_ms;
+		else
+			soc_calc_period = chip->calculate_soc_ms;
+
+		if (time_since_last_recalc >= soc_calc_period) {
+			chip->last_recalc_time = tm_now_sec;
+			recalculate_soc(chip);
+		}
+	}
+	return 0;
+}
+
+static const struct dev_pm_ops qpnp_bms_pm_ops = {
+	.resume		= bms_resume,
+};
+
 static struct spmi_driver qpnp_bms_driver = {
 	.probe		= qpnp_bms_probe,
 	.remove		= __devexit_p(qpnp_bms_remove),
@@ -2411,6 +2533,7 @@
 		.name		= QPNP_BMS_DEV_NAME,
 		.owner		= THIS_MODULE,
 		.of_match_table	= qpnp_bms_match_table,
+		.pm		= &qpnp_bms_pm_ops,
 	},
 };
 
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 32359e5..13ba50b 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -69,6 +69,7 @@
 #define CHGR_CHG_WDOG_DLY			0x63
 #define CHGR_CHG_WDOG_PET			0x64
 #define CHGR_CHG_WDOG_EN			0x65
+#define CHGR_IR_DROP_COMPEN			0x67
 #define CHGR_USB_IUSB_MAX			0x44
 #define CHGR_USB_USB_SUSP			0x47
 #define CHGR_USB_USB_OTG_CTL			0x48
@@ -80,6 +81,7 @@
 #define CHGR_BAT_IF_BATFET_CTRL1		0x90
 #define CHGR_MISC_BOOT_DONE			0x42
 #define CHGR_BUCK_COMPARATOR_OVRIDE_3		0xED
+#define CHGR_BUCK_BCK_VBAT_REG_MODE		0x74
 #define MISC_REVISION2				0x01
 #define USB_OVP_CTL				0x42
 #define SEC_ACCESS				0xD0
@@ -101,6 +103,7 @@
 #define CHGR_CHG_EN			BIT(7)
 #define CHGR_ON_BAT_FORCE_BIT		BIT(0)
 #define USB_VALID_DEB_20MS		0x03
+#define BUCK_VBAT_REG_NODE_SEL_BIT	BIT(0)
 
 /* Interrupt definitions */
 /* smbb_chg_interrupts */
@@ -170,6 +173,9 @@
  * @term_current:		the charging based term current
  * @safe_current:		battery safety current setting
  * @revision:			PMIC revision
+ * @thermal_levels		amount of thermal mitigation levels
+ * @thermal_mitigation		thermal mitigation level values
+ * @therm_lvl_sel		thermal mitigation level selection
  * @dc_psy			power supply to export information to userspace
  * @usb_psy			power supply to export information to userspace
  * @bms_psy			power supply to export information to userspace
@@ -205,6 +211,9 @@
 	unsigned int			term_current;
 	unsigned int			safe_current;
 	unsigned int			revision;
+	unsigned int			thermal_levels;
+	unsigned int			therm_lvl_sel;
+	unsigned int			*thermal_mitigation;
 	struct power_supply		dc_psy;
 	struct power_supply		*usb_psy;
 	struct power_supply		*bms_psy;
@@ -464,6 +473,7 @@
 {
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+	case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
 		return 1;
 	default:
 		break;
@@ -494,6 +504,29 @@
 			disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
 }
 
+static int
+qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
+{
+	int rc;
+
+	if (chip->charging_disabled && enable) {
+		pr_debug("Charging disabled\n");
+		return 0;
+	}
+
+	rc = qpnp_chg_charge_en(chip, enable);
+	if (rc) {
+		pr_err("Failed to control charging %d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_chg_force_run_on_batt(chip, !enable);
+	if (rc)
+		pr_err("Failed to control charging %d\n", rc);
+
+	return rc;
+}
+
 static
 int switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
 {
@@ -569,6 +602,7 @@
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
 };
 
 static char *pm_power_supplied_to[] = {
@@ -884,32 +918,13 @@
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
 		val->intval = !(chip->charging_disabled);
 		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int
-qpnp_batt_power_set_property(struct power_supply *psy,
-				  enum power_supply_property psp,
-				  const union power_supply_propval *val)
-{
-	struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
-								batt_psy);
-
-	switch (psp) {
-	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
-		chip->charging_disabled = !(val->intval);
-		qpnp_chg_charge_en(chip, !chip->charging_disabled);
-		qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
+	case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
+		val->intval = chip->therm_lvl_sel;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	power_supply_changed(&chip->batt_psy);
 	return 0;
 }
 
@@ -1066,6 +1081,60 @@
 		chip->chgr_base + CHGR_VDD_MAX, 1);
 }
 
+static void
+qpnp_chg_set_appropriate_battery_current(struct qpnp_chg_chip *chip)
+{
+	unsigned int chg_current = chip->max_bat_chg_current;
+
+	if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
+		chg_current = min(chg_current,
+			chip->thermal_mitigation[chip->therm_lvl_sel]);
+
+	pr_debug("setting %d mA\n", chg_current);
+	qpnp_chg_ibatmax_set(chip, chg_current);
+}
+
+static void
+qpnp_batt_system_temp_level_set(struct qpnp_chg_chip *chip, int lvl_sel)
+{
+	if (lvl_sel >= 0 && lvl_sel < chip->thermal_levels) {
+		chip->therm_lvl_sel = lvl_sel;
+		if (lvl_sel == (chip->thermal_levels - 1)) {
+			/* disable charging if highest value selected */
+			qpnp_chg_buck_control(chip, 0);
+		} else {
+			qpnp_chg_buck_control(chip, 1);
+			qpnp_chg_set_appropriate_battery_current(chip);
+		}
+	} else {
+		pr_err("Unsupported level selected %d\n", lvl_sel);
+	}
+}
+
+static int
+qpnp_batt_power_set_property(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  const union power_supply_propval *val)
+{
+	struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
+								batt_psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+		chip->charging_disabled = !(val->intval);
+		qpnp_chg_charge_en(chip, !chip->charging_disabled);
+		qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
+		break;
+	case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
+		qpnp_batt_system_temp_level_set(chip, val->intval);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	power_supply_changed(&chip->batt_psy);
+	return 0;
+}
 
 static void
 qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
@@ -1161,6 +1230,14 @@
 		enable_irq_wake(chip->chg_done_irq);
 		break;
 	case SMBB_BUCK_SUBTYPE:
+		rc = qpnp_chg_masked_write(chip,
+			chip->chgr_base + CHGR_BUCK_BCK_VBAT_REG_MODE,
+			BUCK_VBAT_REG_NODE_SEL_BIT,
+			BUCK_VBAT_REG_NODE_SEL_BIT, 1);
+		if (rc) {
+			pr_debug("failed to enable IR drop comp rc=%d\n", rc);
+			return rc;
+		}
 		break;
 	case SMBB_BAT_IF_SUBTYPE:
 		break;
@@ -1325,6 +1402,29 @@
 	chip->use_default_batt_values = of_property_read_bool(spmi->dev.of_node,
 					"qcom,chg-use-default-batt-values");
 
+	of_get_property(spmi->dev.of_node, "qcom,chg-thermal-mitigation",
+		&(chip->thermal_levels));
+
+	if (chip->thermal_levels > sizeof(int)) {
+		chip->thermal_mitigation = kzalloc(
+			chip->thermal_levels,
+			GFP_KERNEL);
+
+		if (chip->thermal_mitigation == NULL) {
+			pr_err("thermal mitigation kzalloc() failed.\n");
+			goto fail_chg_enable;
+		}
+
+		chip->thermal_levels /= sizeof(int);
+		rc = of_property_read_u32_array(spmi->dev.of_node,
+				"qcom,chg-thermal-mitigation",
+				chip->thermal_mitigation, chip->thermal_levels);
+		if (rc) {
+			pr_err("qcom,chg-thermal-mitigation missing in dt\n");
+			goto fail_chg_enable;
+		}
+	}
+
 	/* Disable charging when faking battery values */
 	if (chip->use_default_batt_values)
 		chip->charging_disabled = true;
@@ -1464,12 +1564,18 @@
 	qpnp_chg_charge_en(chip, !chip->charging_disabled);
 	qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
 
-	pr_info("Probe success !\n");
+	pr_info("success chg_dis = %d, usb = %d, dc = %d b_health = %d batt_present = %d\n",
+			chip->charging_disabled,
+			qpnp_chg_is_usb_chg_plugged_in(chip),
+			qpnp_chg_is_dc_chg_plugged_in(chip),
+			get_prop_batt_present(chip),
+			get_prop_batt_health(chip));
 	return 0;
 
 unregister_dc:
 	power_supply_unregister(&chip->dc_psy);
 fail_chg_enable:
+	kfree(chip->thermal_mitigation);
 	kfree(chip);
 	dev_set_drvdata(&spmi->dev, NULL);
 	return rc;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 5ba5c2a..508c2bb 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -467,7 +467,7 @@
 	return sdkp;
 }
 
-static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev)
+struct scsi_disk *scsi_disk_get_from_dev(struct device *dev)
 {
 	struct scsi_disk *sdkp;
 
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 8f27f9d..1756897 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -47,3 +47,12 @@
 	depends on PCI && SCSI
 	---help---
 	This is a generic driver which supports PCIe UFS Host controllers.
+
+config SCSI_UFS_TEST
+	tristate "Universal Flash Storage host controller driver unit-tests"
+	depends on SCSI_UFSHCD && IOSCHED_TEST
+	---help---
+	This adds UFS Host controller unit-test framework.
+	The UFS unit-tests register as a block device test utility to
+	the test-iosched and will be initiated when the test-iosched will
+	be chosen to be the active I/O scheduler.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index adf7895..489058d 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,2 +1,3 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFS_TEST) += ufs_test.o
diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c
new file mode 100644
index 0000000..03c58a4
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_test.c
@@ -0,0 +1,348 @@
+/* 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/module.h>
+#include <linux/blkdev.h>
+#include <linux/debugfs.h>
+#include <linux/test-iosched.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include <../sd.h>
+
+#define MODULE_NAME "ufs_test"
+
+#define TEST_MAX_BIOS_PER_REQ		120
+#define LARGE_PRIME_1	1103515367
+#define LARGE_PRIME_2	35757
+#define DEFAULT_NUM_OF_BIOS	2
+
+#define test_pr_debug(fmt, args...) pr_debug("%s: "fmt"\n", MODULE_NAME, args)
+#define test_pr_info(fmt, args...) pr_info("%s: "fmt"\n", MODULE_NAME, args)
+#define test_pr_err(fmt, args...) pr_err("%s: "fmt"\n", MODULE_NAME, args)
+
+enum ufs_test_testcases {
+	UFS_TEST_WRITE_READ_TEST,
+};
+
+struct ufs_test_debug {
+	struct dentry *write_read_test; /* basic test */
+	struct dentry *random_test_seed; /* parameters in utils */
+};
+
+struct ufs_test_data {
+	/* Data structure for debugfs dentrys */
+	struct ufs_test_debug debug;
+	/*
+	 * Data structure containing individual test information, including
+	 * self-defined specific data
+	 */
+	struct test_info test_info;
+	/* device test */
+	struct blk_dev_test_type bdt;
+	/* A wait queue for OPs to complete */
+	wait_queue_head_t wait_q;
+	/* a flag for read compleation */
+	bool read_completed;
+	/* a flag for write compleation */
+	bool write_completed;
+	/*
+	 * To determine the number of r/w bios. When seed = 0, random is
+	 * disabled and 2 BIOs are written.
+	 */
+	unsigned int random_test_seed;
+};
+
+static struct ufs_test_data *utd;
+
+static bool message_repeat;
+
+static char *ufs_test_get_test_case_str(struct test_data *td)
+{
+	if (!td) {
+		test_pr_err("%s: NULL td", __func__);
+		return NULL;
+	}
+
+	switch (td->test_info.testcase) {
+	case UFS_TEST_WRITE_READ_TEST:
+		return "UFS write read test";
+		break;
+	default:
+		return "Unknown test";
+	}
+}
+
+static unsigned int ufs_test_pseudo_random_seed(unsigned int *seed_number,
+		unsigned int min_val, unsigned int max_val)
+{
+	int ret = 0;
+
+	if (!seed_number)
+		return 0;
+
+	*seed_number = ((unsigned int) (((unsigned long) *seed_number
+			* (unsigned long) LARGE_PRIME_1) + LARGE_PRIME_2));
+	ret = (unsigned int) ((*seed_number) % max_val);
+
+	return (ret > min_val ? ret : min_val);
+}
+
+static void ufs_test_pseudo_rnd_size(unsigned int *seed,
+				unsigned int *num_of_bios)
+{
+	*num_of_bios = ufs_test_pseudo_random_seed(seed, 1,
+						TEST_MAX_BIOS_PER_REQ);
+	if (!(*num_of_bios))
+		*num_of_bios = DEFAULT_NUM_OF_BIOS;
+}
+
+static void ufs_test_write_read_test_end_io_fn(struct request *rq, int err)
+{
+	struct test_request *test_rq = (struct test_request *)rq->elv.priv[0];
+	BUG_ON(!test_rq);
+
+	test_rq->req_completed = 1;
+	test_rq->req_result = err;
+
+	test_pr_info("%s: request %d completed, err=%d",
+			__func__, test_rq->req_id, err);
+
+	utd->write_completed = true;
+	wake_up(&utd->wait_q);
+}
+
+static struct gendisk *ufs_test_get_rq_disk(void)
+{
+	struct request_queue *req_q = test_iosched_get_req_queue();
+	struct scsi_device *sd;
+	struct device *dev;
+	struct scsi_disk *sdkp;
+	struct gendisk *gd;
+
+	if (!req_q) {
+		test_pr_info("%s: Could not fetch request_queue", __func__);
+		gd = NULL;
+		goto exit;
+	}
+
+	sd = (struct scsi_device *)req_q->queuedata;
+
+	dev = &sd->sdev_gendev;
+	sdkp = scsi_disk_get_from_dev(dev);
+	if (!sdkp) {
+		test_pr_info("%s: Could not fatch scsi disk", __func__);
+		gd = NULL;
+		goto exit;
+	}
+
+	gd = sdkp->disk;
+exit:
+	return gd;
+}
+
+static int ufs_test_run_write_read_test(struct test_data *td)
+{
+	int ret = 0;
+	unsigned int start_sec;
+	unsigned int num_bios;
+	struct request_queue *q = td->req_q;
+
+
+	start_sec = td->start_sector + sizeof(int) * BIO_U32_SIZE
+			* td->num_of_write_bios;
+	if (utd->random_test_seed != 0)
+		ufs_test_pseudo_rnd_size(&utd->random_test_seed, &num_bios);
+	else
+		num_bios = DEFAULT_NUM_OF_BIOS;
+
+	/* Adding a write request */
+	test_pr_info("%s: Adding a write requests to Q, first req_id=%d",
+			__func__, td->wr_rd_next_req_id);
+
+	utd->write_completed = false;
+	ret = test_iosched_add_wr_rd_test_req(0, WRITE, start_sec,
+					num_bios, TEST_PATTERN_5A,
+					ufs_test_write_read_test_end_io_fn);
+
+	if (ret) {
+		test_pr_err("%s: failed to add a write request", __func__);
+		return ret;
+	}
+
+	/* waiting for the write request to finish */
+	blk_run_queue(q);
+	wait_event(utd->wait_q, utd->write_completed);
+
+	/* Adding a read request*/
+	test_pr_info("%s: Adding a read request to Q", __func__);
+
+	ret = test_iosched_add_wr_rd_test_req(0, READ, start_sec,
+			num_bios, TEST_PATTERN_5A, NULL);
+
+	if (ret) {
+		test_pr_err("%s: failed to add a read request", __func__);
+		return ret;
+	}
+
+	blk_run_queue(q);
+	return ret;
+}
+
+static
+int ufs_test_write_read_test_open_cb(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	message_repeat = 1;
+	test_pr_info("%s:UFS test initialized", __func__);
+	return 0;
+}
+
+static ssize_t ufs_test_write_read_test_write_cb(struct file *file,
+					const char __user *buf,
+					size_t count, loff_t *ppos)
+{
+	int ret = 0;
+	int i;
+	int number;
+
+	sscanf(buf, "%d", &number);
+
+	if (number <= 0)
+		number = 1;
+
+	test_pr_info("%s:the test will run for %d iterations.",
+			__func__, number);
+	memset(&utd->test_info, 0, sizeof(struct test_info));
+
+	/* Initializing test */
+	utd->test_info.data = utd;
+	utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str;
+	utd->test_info.testcase = UFS_TEST_WRITE_READ_TEST;
+	utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk;
+	utd->test_info.run_test_fn = ufs_test_run_write_read_test;
+
+	/* Running the test multiple times */
+	for (i = 0; i < number; ++i) {
+		ret = test_iosched_start_test(&utd->test_info);
+		if (ret) {
+			test_pr_err("%s: Test failed.", __func__);
+			return ret;
+		}
+	}
+
+	test_pr_info("%s: Completed all the ufs test iterations.", __func__);
+
+	return count;
+}
+
+static ssize_t ufs_test_write_read_test_read_cb(struct file *file,
+		char __user *buffer, size_t count, loff_t *offset)
+{
+	memset((void *) buffer, 0, count);
+
+	snprintf(buffer, count, "\nThis is a UFS write-read test for debug.\n");
+
+	if (message_repeat == 1) {
+		message_repeat = 0;
+		return strnlen(buffer, count);
+	} else
+		return 0;
+}
+
+const struct file_operations write_read_test_ops = {
+		.open = ufs_test_write_read_test_open_cb,
+		.write = ufs_test_write_read_test_write_cb,
+		.read = ufs_test_write_read_test_read_cb,
+};
+
+static void ufs_test_debugfs_cleanup(void)
+{
+	debugfs_remove(utd->debug.write_read_test);
+}
+
+static int ufs_test_debugfs_init(void)
+{
+	struct dentry *utils_root, *tests_root;
+
+	utils_root = test_iosched_get_debugfs_utils_root();
+	tests_root = test_iosched_get_debugfs_tests_root();
+
+	if (!utils_root || !tests_root) {
+		test_pr_err("%s: Failed to create debugfs root.", __func__);
+		return -EINVAL;
+	}
+
+	utd->debug.random_test_seed = debugfs_create_u32("random_test_seed",
+			S_IRUGO | S_IWUGO, utils_root, &utd->random_test_seed);
+
+	if (!utd->debug.random_test_seed) {
+		test_pr_err("%s: Could not create debugfs random_test_seed.",
+				__func__);
+		return -ENOMEM;
+	}
+
+	utd->debug.write_read_test = debugfs_create_file("write_read_test",
+					S_IRUGO | S_IWUGO, tests_root,
+					NULL, &write_read_test_ops);
+
+	if (!utd->debug.write_read_test) {
+		debugfs_remove(utd->debug.random_test_seed);
+		test_pr_err("%s: Could not create debugfs write_read_test.",
+				__func__);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void ufs_test_probe(void)
+{
+	ufs_test_debugfs_init();
+}
+
+static void ufs_test_remove(void)
+{
+	ufs_test_debugfs_cleanup();
+}
+
+int __init ufs_test_init(void)
+{
+	utd = kzalloc(sizeof(struct ufs_test_data), GFP_KERNEL);
+	if (!utd) {
+		test_pr_err("%s: failed to allocate ufs_test_data", __func__);
+		return -ENODEV;
+	}
+
+	init_waitqueue_head(&utd->wait_q);
+	utd->bdt.init_fn = ufs_test_probe;
+	utd->bdt.exit_fn = ufs_test_remove;
+	INIT_LIST_HEAD(&utd->bdt.list);
+	test_iosched_register(&utd->bdt);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ufs_test_init);
+
+static void __exit ufs_test_exit(void)
+{
+	test_iosched_unregister(&utd->bdt);
+	kfree(utd);
+}
+module_init(ufs_test_init)
+;
+module_exit(ufs_test_exit)
+;
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("UFC test");
+
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index eb741ef..10c69c3 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -224,6 +224,17 @@
 	u8 la = txn->la;
 	u8 wbuf[SLIM_RX_MSGQ_BUF_LEN];
 
+	if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
+			txn->mc != SLIM_USR_MC_REPORT_SATELLITE) {
+		/*
+		 * Counter-part of system-suspend when runtime-pm is not enabled
+		 * This way, resume can be left empty and device will be put in
+		 * active mode only if client requests anything on the bus
+		 * If the state was DOWN, SSR UP notification will take
+		 * care of putting the device in active state.
+		 */
+		ngd_slim_runtime_resume(dev->dev);
+	}
 	if (txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
 			SLIM_MSG_MC_RECONFIGURE_NOW)) {
 		if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED) {
@@ -1172,6 +1183,19 @@
 	if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
 		dev_dbg(dev, "system suspend");
 		ret = ngd_slim_runtime_suspend(dev);
+		/*
+		 * If runtime-PM still thinks it's active, then make sure its
+		 * status is in sync with HW status.
+		 * Since this suspend calls QMI api, it results in holding a
+		 * wakelock. That results in failure of first suspend.
+		 * Subsequent suspend should not call low-power transition
+		 * again since the HW is already in suspended state.
+		 */
+		if (!ret) {
+			pm_runtime_disable(dev);
+			pm_runtime_set_suspended(dev);
+			pm_runtime_enable(dev);
+		}
 	}
 	if (ret == -EBUSY) {
 		/*
@@ -1189,18 +1213,11 @@
 
 static int ngd_slim_resume(struct device *dev)
 {
-	/* If runtime_pm is enabled, this resume shouldn't do anything */
-	if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
-		int ret;
-		dev_dbg(dev, "system resume");
-		ret = ngd_slim_runtime_resume(dev);
-		if (!ret) {
-			pm_runtime_mark_last_busy(dev);
-			pm_request_autosuspend(dev);
-		}
-		return ret;
-
-	}
+	/*
+	 * Rely on runtime-PM to call resume in case it is enabled.
+	 * Even if it's not enabled, rely on 1st client transaction to do
+	 * clock/power on
+	 */
 	return 0;
 }
 #endif /* CONFIG_PM_SLEEP */
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index e5b3158..bec0399 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -233,6 +233,17 @@
 }
 EXPORT_SYMBOL_GPL(slim_driver_register);
 
+/*
+ * slim_driver_unregister: Undo effects of slim_driver_register
+ * @drv: Client driver to be unregistered
+ */
+void slim_driver_unregister(struct slim_driver *drv)
+{
+	if (drv)
+		driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(slim_driver_unregister);
+
 #define slim_ctrl_attr_gr NULL
 
 static void slim_ctrl_release(struct device *dev)
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index 8cb1036..d1d49ef 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -299,6 +299,7 @@
 {
 	struct q_irq_data *irq_d;
 	struct q_perip_data *per_d;
+	int rc;
 
 	irq_d = kzalloc(sizeof(struct q_irq_data), GFP_KERNEL);
 	if (!irq_d)
@@ -313,15 +314,26 @@
 	if (!per_d) {
 		per_d = kzalloc(sizeof(struct q_perip_data), GFP_KERNEL);
 		if (!per_d) {
-			kfree(irq_d);
-			return ERR_PTR(-ENOMEM);
+			rc = -ENOMEM;
+			goto alloc_fail;
 		}
-		radix_tree_insert(&chip_d->per_tree,
+		rc = radix_tree_preload(GFP_KERNEL);
+		if (rc)
+			goto alloc_fail;
+		rc = radix_tree_insert(&chip_d->per_tree,
 				  (hwirq & ~0x7), per_d);
+		if (rc)
+			goto alloc_fail;
+		radix_tree_preload_end();
 	}
 	irq_d->per_d = per_d;
 
 	return irq_d;
+
+alloc_fail:
+	kfree(per_d);
+	kfree(irq_d);
+	return ERR_PTR(rc);
 }
 
 static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
diff --git a/drivers/spmi/spmi-dbgfs.c b/drivers/spmi/spmi-dbgfs.c
index a23f945..b825ade 100644
--- a/drivers/spmi/spmi-dbgfs.c
+++ b/drivers/spmi/spmi-dbgfs.c
@@ -36,6 +36,7 @@
 #include <linux/debugfs.h>
 #include <linux/spmi.h>
 #include <linux/ctype.h>
+#include "spmi-dbgfs.h"
 
 #define ADDR_LEN	 6	/* 5 byte address + 1 space character */
 #define CHARS_PER_ITEM   3	/* Format is 'XX ' */
@@ -58,6 +59,7 @@
 struct spmi_ctrl_data {
 	u32 cnt;
 	u32 addr;
+	struct dentry *dir;
 	struct list_head node;
 	struct spmi_controller *ctrl;
 };
@@ -655,6 +657,7 @@
 	}
 
 	ctrl_data->cnt  = 1;
+	ctrl_data->dir  = dir;
 	ctrl_data->ctrl = ctrl;
 
 	file = debugfs_create_u32("count", DFS_MODE, dir, &ctrl_data->cnt);
@@ -693,6 +696,25 @@
 	return -ENOMEM;
 }
 
+/*
+ * spmi_dfs_create_file: creates a new file in the SPMI debugfs
+ * @returns valid dentry pointer on success or NULL
+ */
+struct dentry *spmi_dfs_create_file(struct spmi_controller *ctrl,
+					const char *name, void *data,
+					const struct file_operations *fops)
+{
+	struct spmi_ctrl_data *ctrl_data;
+
+	list_for_each_entry(ctrl_data, &dbgfs_data.ctrl, node) {
+		if (ctrl_data->ctrl == ctrl)
+			return debugfs_create_file(name,
+					DFS_MODE, ctrl_data->dir, data, fops);
+	}
+
+	return NULL;
+}
+
 static void __exit spmi_dfs_delete_all_ctrl(struct list_head *head)
 {
 	struct list_head *pos, *tmp;
diff --git a/drivers/spmi/spmi-dbgfs.h b/drivers/spmi/spmi-dbgfs.h
index 0baa4db..2a0d815 100644
--- a/drivers/spmi/spmi-dbgfs.h
+++ b/drivers/spmi/spmi-dbgfs.h
@@ -12,10 +12,16 @@
 #ifndef _SPMI_DBGFS_H
 #define _SPMI_DBGFS_H
 
+#include <linux/debugfs.h>
+
 #ifdef CONFIG_DEBUG_FS
 int spmi_dfs_add_controller(struct spmi_controller *ctrl);
 #else
-int spmi_dfs_add_controller(struct spmi_controller *ctrl) { return 0; }
+static int spmi_dfs_add_controller(struct spmi_controller *ctrl) { return 0; }
 #endif
 
+struct dentry *spmi_dfs_create_file(struct spmi_controller *ctrl,
+					const char *name, void *data,
+					const struct file_operations *fops);
+
 #endif /* _SPMI_DBGFS_H */
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index ffbb558..450db0b 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -23,7 +23,9 @@
 #include <linux/interrupt.h>
 #include <linux/of_spmi.h>
 #include <linux/module.h>
+#include <linux/seq_file.h>
 #include <mach/qpnp-int.h>
+#include "spmi-dbgfs.h"
 
 #define SPMI_PMIC_ARB_NAME		"spmi_pmic_arb"
 
@@ -46,6 +48,21 @@
 #define SPMI_PIC_IRQ_STATUS(N)		(0x0600 + (4 * (N)))
 #define SPMI_PIC_IRQ_CLEAR(N)		(0x0A00 + (4 * (N)))
 
+/* Mapping Table */
+#define SPMI_MAPPING_TABLE_REG(N)	(0x0B00 + (4 * (N)))
+#define SPMI_MAPPING_BIT_INDEX(X)	(((X) >> 18) & 0xF)
+#define SPMI_MAPPING_BIT_IS_0_FLAG(X)	(((X) >> 17) & 0x1)
+#define SPMI_MAPPING_BIT_IS_0_RESULT(X)	(((X) >> 9) & 0xFF)
+#define SPMI_MAPPING_BIT_IS_1_FLAG(X)	(((X) >> 8) & 0x1)
+#define SPMI_MAPPING_BIT_IS_1_RESULT(X)	(((X) >> 0) & 0xFF)
+
+#define SPMI_MAPPING_TABLE_LEN		255
+#define SPMI_MAPPING_TABLE_TREE_DEPTH	16	/* Maximum of 16-bits */
+
+/* Ownership Table */
+#define SPMI_OWNERSHIP_TABLE_REG(N)	(0x0700 + (4 * (N)))
+#define SPMI_OWNERSHIP_PERIPH2OWNER(X)	((X) & 0x7)
+
 /* Channel Status fields */
 enum pmic_arb_chnl_status {
 	PMIC_ARB_STATUS_DONE	= (1 << 0),
@@ -81,13 +98,8 @@
 #define PMIC_ARB_TIMEOUT_US		100
 #define PMIC_ARB_MAX_TRANS_BYTES	(8)
 
-#define PMIC_ARB_APID_MASK				0xFF
-#define PMIC_ARB_PPID_MASK				0xFFF
-/* extract PPID and APID from interrupt map in .dts config file format */
-#define PMIC_ARB_DEV_TRE_2_PPID(MAP_COMPRS_VAL)		\
-			((MAP_COMPRS_VAL) >> (20))
-#define PMIC_ARB_DEV_TRE_2_APID(MAP_COMPRS_VAL)		\
-			((MAP_COMPRS_VAL) &  PMIC_ARB_APID_MASK)
+#define PMIC_ARB_APID_MASK		0xFF
+#define PMIC_ARB_PPID_MASK		0xFFF
 
 /**
  * base - base address of the PMIC Arbiter core registers.
@@ -99,6 +111,7 @@
 	struct device		*slave;
 	void __iomem		*base;
 	void __iomem		*intr;
+	void __iomem		*cnfg;
 	int			pic_irq;
 	bool			allow_wakeup;
 	spinlock_t		lock;
@@ -107,6 +120,7 @@
 	u8			min_apid;
 	u8			max_apid;
 	u16			periph_id_map[PMIC_ARB_MAX_PERIPHS];
+	u32			mapping_table[SPMI_MAPPING_TABLE_LEN];
 };
 
 static u32 pmic_arb_read(struct spmi_pmic_arb_dev *dev, u32 offset)
@@ -317,17 +331,79 @@
 	return pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID;
 }
 
+static u32 search_mapping_table(struct spmi_pmic_arb_dev *pmic_arb, u16 ppid)
+{
+	u32 *mapping_table = pmic_arb->mapping_table;
+	u32 apid = PMIC_ARB_MAX_PERIPHS;
+	int index = 0;
+	u32 data;
+	int i;
+
+	for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
+		data = mapping_table[index];
+
+		if (ppid & (1 << SPMI_MAPPING_BIT_INDEX(data))) {
+			if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
+				index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
+			} else {
+				apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
+				break;
+			}
+		} else {
+			if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
+				index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
+			} else {
+				apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
+				break;
+			}
+		}
+	}
+
+	return apid;
+}
+
 /* PPID to APID */
 static uint32_t map_peripheral_id(struct spmi_pmic_arb_dev *pmic_arb, u16 ppid)
 {
-	int first = pmic_arb->min_apid;
-	int last = pmic_arb->max_apid;
-	int i;
+	u32 apid = search_mapping_table(pmic_arb, ppid);
+	u32 old_ppid;
+	u32 owner;
 
-	/* Search table for a matching PPID */
-	for (i = first; i <= last; ++i) {
-		if ((pmic_arb->periph_id_map[i] & PMIC_ARB_PPID_MASK) == ppid)
-			return i;
+	/* If the apid was found, add it to the lookup table */
+	if (apid < PMIC_ARB_MAX_PERIPHS) {
+		old_ppid = get_peripheral_id(pmic_arb, apid);
+
+		owner = SPMI_OWNERSHIP_PERIPH2OWNER(
+				readl_relaxed(pmic_arb->cnfg +
+					SPMI_OWNERSHIP_TABLE_REG(apid)));
+
+		/* Check ownership */
+		if (owner != pmic_arb->owner) {
+			dev_err(pmic_arb->dev, "PPID 0x%x incorrect owner %d\n",
+				ppid, owner);
+			return PMIC_ARB_MAX_PERIPHS;
+		}
+
+		/* Check if already mapped */
+		if (pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID) {
+			if (ppid != old_ppid) {
+				dev_err(pmic_arb->dev,
+					"PPID 0x%x: APID 0x%x already mapped\n",
+					ppid, apid);
+				return PMIC_ARB_MAX_PERIPHS;
+			}
+			return apid;
+		}
+
+		pmic_arb->periph_id_map[apid] = ppid | PMIC_ARB_PERIPH_ID_VALID;
+
+		if (apid > pmic_arb->max_apid)
+			pmic_arb->max_apid = apid;
+
+		if (apid < pmic_arb->min_apid)
+			pmic_arb->min_apid = apid;
+
+		return apid;
 	}
 
 	dev_err(pmic_arb->dev, "Unknown ppid 0x%x\n", ppid);
@@ -481,6 +557,37 @@
 	return 0;
 }
 
+static int pmic_arb_mapping_data_show(struct seq_file *file, void *unused)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = file->private;
+	int first = pmic_arb->min_apid;
+	int last = pmic_arb->max_apid;
+	int i;
+
+	for (i = first; i <= last; ++i) {
+		if (!is_apid_valid(pmic_arb, i))
+			continue;
+
+		seq_printf(file, "APID 0x%.2x = PPID 0x%.3x. Enabled:%d\n",
+			i, get_peripheral_id(pmic_arb, i),
+			readl_relaxed(pmic_arb->intr + SPMI_PIC_ACC_ENABLE(i)));
+	}
+
+	return 0;
+}
+
+static int pmic_arb_mapping_data_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pmic_arb_mapping_data_show, inode->i_private);
+}
+
+static const struct file_operations pmic_arb_dfs_fops = {
+	.open		= pmic_arb_mapping_data_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static int __devinit
 spmi_pmic_arb_get_property(struct platform_device *pdev, char *pname, u32 *prop)
 {
@@ -494,70 +601,6 @@
 	return ret;
 }
 
-static int __devinit spmi_pmic_arb_get_map_data(struct platform_device *pdev,
-					struct spmi_pmic_arb_dev *pmic_arb)
-{
-	int i;
-	int ret;
-	int map_size;
-	u32 *map_data;
-	const int map_width = sizeof(*map_data);
-	const struct device_node *of_node = pdev->dev.of_node;
-
-	/* Get size of the mapping table (in bytes) */
-	if (!of_get_property(of_node, "qcom,pmic-arb-ppid-map", &map_size)) {
-		dev_err(&pdev->dev, "missing ppid mapping table\n");
-		return -ENODEV;
-	}
-
-	/* Map size can't exceed the maximum number of peripherals */
-	if (map_size == 0 || map_size > map_width * PMIC_ARB_MAX_PERIPHS) {
-		dev_err(&pdev->dev, "map size of %d is not valid\n", map_size);
-		return -ENODEV;
-	}
-
-	map_data = kzalloc(map_size, GFP_KERNEL);
-	if (!map_data) {
-		dev_err(&pdev->dev, "can not allocate map data\n");
-		return -ENOMEM;
-	}
-
-	ret = of_property_read_u32_array(of_node,
-		"qcom,pmic-arb-ppid-map", map_data, map_size/sizeof(u32));
-	if (ret) {
-		dev_err(&pdev->dev, "invalid or missing property: ppid-map\n");
-		goto err;
-	};
-
-	pmic_arb->max_apid = 0;
-	pmic_arb->min_apid = PMIC_ARB_MAX_PERIPHS - 1;
-
-	/* Build the mapping table from the data */
-	for (i = 0; i < map_size/sizeof(u32);) {
-		u32 map_compressed_val = map_data[i++];
-		u32 ppid = PMIC_ARB_DEV_TRE_2_PPID(map_compressed_val) ;
-		u32 apid = PMIC_ARB_DEV_TRE_2_APID(map_compressed_val) ;
-
-		if (pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID)
-			dev_warn(&pdev->dev, "duplicate APID 0x%x\n", apid);
-
-		pmic_arb->periph_id_map[apid] = ppid | PMIC_ARB_PERIPH_ID_VALID;
-
-		if (apid > pmic_arb->max_apid)
-			pmic_arb->max_apid = apid;
-
-		if (apid < pmic_arb->min_apid)
-			pmic_arb->min_apid = apid;
-	}
-
-	pr_debug("%d value(s) mapped, min:%d, max:%d\n",
-		map_size/map_width, pmic_arb->min_apid, pmic_arb->max_apid);
-
-err:
-	kfree(map_data);
-	return ret;
-}
-
 static struct qpnp_local_int spmi_pmic_arb_intr_cb = {
 	.mask = pmic_arb_pic_disable,
 	.unmask = pmic_arb_pic_enable,
@@ -571,6 +614,7 @@
 	u32 cell_index;
 	u32 prop;
 	int ret = 0;
+	int i;
 
 	pr_debug("SPMI PMIC Arbiter\n");
 
@@ -581,7 +625,7 @@
 		return -ENOMEM;
 	}
 
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
 	if (!mem_res) {
 		dev_err(&pdev->dev, "missing base memory resource\n");
 		return -ENODEV;
@@ -594,7 +638,7 @@
 		return -ENOMEM;
 	}
 
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
 	if (!mem_res) {
 		dev_err(&pdev->dev, "missing mem resource (interrupts)\n");
 		return -ENODEV;
@@ -607,6 +651,23 @@
 		return -ENOMEM;
 	}
 
+	mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg");
+	if (!mem_res) {
+		dev_err(&pdev->dev, "missing mem resource (configuration)\n");
+		return -ENODEV;
+	}
+
+	pmic_arb->cnfg = devm_ioremap(&pdev->dev,
+					mem_res->start, resource_size(mem_res));
+	if (!pmic_arb->cnfg) {
+		dev_err(&pdev->dev, "ioremap of 'cnfg' failed\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pmic_arb->mapping_table); ++i)
+		pmic_arb->mapping_table[i] = readl_relaxed(
+				pmic_arb->cnfg + SPMI_MAPPING_TABLE_REG(i));
+
 	pmic_arb->pic_irq = platform_get_irq(pdev, 0);
 	if (!pmic_arb->pic_irq) {
 		dev_err(&pdev->dev, "missing IRQ resource\n");
@@ -625,10 +686,6 @@
 	if (ret)
 		return -ENODEV;
 
-	ret = spmi_pmic_arb_get_map_data(pdev, pmic_arb);
-	if (ret)
-		return ret;
-
 	ret = spmi_pmic_arb_get_property(pdev, "qcom,pmic-arb-ee", &prop);
 	if (ret)
 		return -ENODEV;
@@ -649,6 +706,9 @@
 		}
 	}
 
+	pmic_arb->max_apid = 0;
+	pmic_arb->min_apid = PMIC_ARB_MAX_PERIPHS - 1;
+
 	pmic_arb->dev = &pdev->dev;
 	platform_set_drvdata(pdev, pmic_arb);
 	spmi_set_ctrldata(&pmic_arb->controller, pmic_arb);
@@ -681,6 +741,11 @@
 	/* Register device(s) from the device tree */
 	of_spmi_register_devices(&pmic_arb->controller);
 
+	/* Add debugfs file for mapping data */
+	if (spmi_dfs_create_file(&pmic_arb->controller, "mapping",
+					pmic_arb, &pmic_arb_dfs_fops) == NULL)
+		dev_err(&pdev->dev, "error creating 'mapping' debugfs file\n");
+
 	pr_debug("PMIC Arb Version 0x%x\n",
 			pmic_arb_read(pmic_arb, PMIC_ARB_VERSION));
 
diff --git a/drivers/switch/switch_class.c b/drivers/switch/switch_class.c
index e05fc25..f9cf2b4 100644
--- a/drivers/switch/switch_class.c
+++ b/drivers/switch/switch_class.c
@@ -151,8 +151,8 @@
 {
 	device_remove_file(sdev->dev, &dev_attr_name);
 	device_remove_file(sdev->dev, &dev_attr_state);
-	device_destroy(switch_class, MKDEV(0, sdev->index));
 	dev_set_drvdata(sdev->dev, NULL);
+	device_destroy(switch_class, MKDEV(0, sdev->index));
 }
 EXPORT_SYMBOL_GPL(switch_dev_unregister);
 
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 1716598..c2e1731 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -83,7 +83,7 @@
 #define TSENS8_POINT1_MASK_BACKUP	0x3f
 #define TSENS9_POINT1_MASK		0x3f
 #define TSENS9_POINT1_MASK_BACKUP	0xfc0
-#define TSENS10_POINT1_MASK		0xfc00
+#define TSENS10_POINT1_MASK		0xfc0
 #define TSENS10_POINT1_MASK_BACKUP	0x3f000
 #define TSENS_CAL_SEL_0_1		0xc0000000
 #define TSENS_CAL_SEL_2			0x40000000
@@ -134,7 +134,7 @@
 #define TSENS1_POINT2_BACKUP_MASK	0x3f
 #define TSENS2_POINT2_MASK		0x3f
 #define TSENS2_POINT2_BACKUP_MASK	0xfc0
-#define TSENS3_POINT2_MASK		0xfc00
+#define TSENS3_POINT2_MASK		0xfc0
 #define TSENS3_POINT2_BACKUP_MASK	0x3f000
 #define TSENS4_POINT2_MASK		0x3f000
 #define TSENS4_POINT2_BACKUP_MASK	0xfc0000
@@ -143,8 +143,8 @@
 #define TSENS6_POINT2_MASK		0x3f000000
 #define TSENS6_POINT2_BACKUP_MASK	0x3f
 #define TSENS7_POINT2_MASK		0x3f
-#define TSENS7_POINT2_BACKUP_MASK	0xfc00
-#define TSENS8_POINT2_MASK		0xfc00
+#define TSENS7_POINT2_BACKUP_MASK	0xfc0
+#define TSENS8_POINT2_MASK		0xfc0
 #define TSENS8_POINT2_BACKUP_MASK	0x3f000
 #define TSENS9_POINT2_MASK		0x3f000
 #define TSENS9_POINT2_BACKUP_MASK	0xfc0000
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 4818941..17ae34f 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -867,10 +867,10 @@
 
 		if (status_low & QPNP_ADC_TM_LOW_THR_INT_EN_M1)
 			adc_tm->battery_param->threshold_notification(
-							ADC_TM_LOW_STATE);
+			ADC_TM_LOW_STATE, adc_tm->battery_param->btm_ctx);
 		else if (status_high & QPNP_ADC_TM_HIGH_THR_INT_EN_M1)
 			adc_tm->battery_param->threshold_notification(
-							ADC_TM_HIGH_STATE);
+			ADC_TM_HIGH_STATE, adc_tm->battery_param->btm_ctx);
 	}
 
 	return;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index fd866e1..4b6ba67 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -855,6 +855,7 @@
 	struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
 
 	mutex_lock(&msm_uport->clk_mutex);
+	msm_hs_write(uport, UARTDM_IMR_ADDR, 0);
 
 	/*
 	 * Disable Rx channel of UARTDM
@@ -947,7 +948,6 @@
 
 	uport->read_status_mask = (termios->c_cflag & CREAD);
 
-	msm_hs_write(uport, UARTDM_IMR_ADDR, 0);
 
 	/* Set Transmit software time out */
 	uart_update_timeout(uport, c_cflag, bps);
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 3e8f923..c9f4199 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -49,6 +49,7 @@
 #include <linux/wakelock.h>
 #include <mach/board.h>
 #include <mach/msm_serial_hs_lite.h>
+#include <mach/msm_bus.h>
 #include <asm/mach-types.h>
 #include "msm_serial_hs_hwreg.h"
 
@@ -89,6 +90,10 @@
 	enum uart_core_type	uart_type;
 	enum uart_func_mode	func_mode;
 	struct wake_lock	port_open_wake_lock;
+	int			clk_enable_count;
+	u32			bus_perf_client;
+	/* BLSP UART required BUS Scaling data */
+	struct msm_bus_scale_pdata *bus_scale_table;
 };
 
 #define UARTDM_VERSION_11_13	0
@@ -366,23 +371,40 @@
 
 	if (enable) {
 
+		msm_hsl_port->clk_enable_count++;
 		ret = clk_prepare_enable(msm_hsl_port->clk);
 		if (ret)
 			goto err;
 		if (msm_hsl_port->pclk) {
 			ret = clk_prepare_enable(msm_hsl_port->pclk);
-			if (ret) {
-				clk_disable_unprepare(msm_hsl_port->clk);
-				goto err;
-			}
+			if (ret)
+				goto err_clk_disable;
 		}
 	} else {
 
+		msm_hsl_port->clk_enable_count--;
 		clk_disable_unprepare(msm_hsl_port->clk);
 		if (msm_hsl_port->pclk)
 			clk_disable_unprepare(msm_hsl_port->pclk);
 	}
+
+	if (msm_hsl_port->bus_perf_client) {
+			pr_debug("Voting for bus scaling:%d\n",
+					!!msm_hsl_port->clk_enable_count);
+			ret = msm_bus_scale_client_update_request(
+				msm_hsl_port->bus_perf_client,
+				!!msm_hsl_port->clk_enable_count);
+			if (ret)
+				pr_err("Failed to request bus bw vector %d\n",
+					!!msm_hsl_port->clk_enable_count);
+	}
+
+	return ret;
+
+err_clk_disable:
+	clk_disable_unprepare(msm_hsl_port->clk);
 err:
+	msm_hsl_port->clk_enable_count--;
 	return ret;
 }
 static int msm_hsl_loopback_enable_set(void *data, u64 val)
@@ -1703,6 +1725,20 @@
 		 * UARTDM v14 Revision. Hence set uart_type as UART_BLSP.
 		 */
 		msm_hsl_port->uart_type = BLSP_HSUART;
+
+		msm_hsl_port->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+		if (!msm_hsl_port->bus_scale_table) {
+			pr_err("Bus scaling is disabled\n");
+		} else {
+			msm_hsl_port->bus_perf_client =
+				msm_bus_scale_register_client(
+					msm_hsl_port->bus_scale_table);
+			if (IS_ERR(&msm_hsl_port->bus_perf_client)) {
+				pr_err("Bus client register failed.\n");
+				ret = -EINVAL;
+				goto err;
+			}
+		}
 	}
 
 	gsbi_resource =	platform_get_resource_byname(pdev,
@@ -1767,6 +1803,8 @@
 	ret = uart_add_one_port(&msm_hsl_uart_driver, port);
 	if (msm_hsl_port->pclk)
 		clk_disable_unprepare(msm_hsl_port->pclk);
+
+err:
 	return ret;
 }
 
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index fb785f3..0011a1a 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -38,7 +38,6 @@
 
 #include <mach/rpm-regulator.h>
 #include <mach/rpm-regulator-smd.h>
-#include <mach/msm_xo.h>
 #include <mach/msm_bus.h>
 #include <mach/clk.h>
 
@@ -135,6 +134,8 @@
 #define HS_PHY_IRQ_STAT_REG	(QSCRATCH_REG_OFFSET + 0x24)
 #define CGCTL_REG		(QSCRATCH_REG_OFFSET + 0x28)
 #define SS_PHY_CTRL_REG		(QSCRATCH_REG_OFFSET + 0x30)
+#define SS_PHY_PARAM_CTRL_1	(QSCRATCH_REG_OFFSET + 0x34)
+#define SS_PHY_PARAM_CTRL_2	(QSCRATCH_REG_OFFSET + 0x38)
 #define SS_CR_PROTOCOL_DATA_IN_REG  (QSCRATCH_REG_OFFSET + 0x3C)
 #define SS_CR_PROTOCOL_DATA_OUT_REG (QSCRATCH_REG_OFFSET + 0x40)
 #define SS_CR_PROTOCOL_CAP_ADDR_REG (QSCRATCH_REG_OFFSET + 0x44)
@@ -158,7 +159,7 @@
 	u8 ep_num_mapping[DBM_MAX_EPS];
 	const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
 	struct list_head req_complete_list;
-	struct msm_xo_voter	*xo_handle;
+	struct clk		*xo_clk;
 	struct clk		*ref_clk;
 	struct clk		*core_clk;
 	struct clk		*iface_clk;
@@ -177,6 +178,7 @@
 	int			hsphy_init_seq;
 	bool			lpm_irq_seen;
 	struct delayed_work	resume_work;
+	struct work_struct	restart_usb_work;
 	struct wake_lock	wlock;
 	struct dwc3_charger	charger;
 	struct usb_phy		*otg_xceiv;
@@ -929,6 +931,50 @@
 }
 EXPORT_SYMBOL(msm_ep_unconfig);
 
+static void dwc3_restart_usb_work(struct work_struct *w)
+{
+	struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
+						restart_usb_work);
+
+	dev_dbg(mdwc->dev, "%s\n", __func__);
+
+	if (atomic_read(&mdwc->in_lpm) || !mdwc->otg_xceiv) {
+		dev_err(mdwc->dev, "%s failed!!!\n", __func__);
+		return;
+	}
+
+	if (!mdwc->ext_xceiv.bsv) {
+		dev_dbg(mdwc->dev, "%s bailing out in disconnect\n", __func__);
+		return;
+	}
+
+	/* Reset active USB connection */
+	mdwc->ext_xceiv.bsv = false;
+	queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
+	/* Make sure disconnect is processed before sending connect */
+	flush_delayed_work(&mdwc->resume_work);
+
+	mdwc->ext_xceiv.bsv = true;
+	queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
+}
+
+/**
+ * Reset USB peripheral connection
+ * Inform OTG for Vbus LOW followed by Vbus HIGH notification.
+ * This performs full hardware reset and re-initialization which
+ * might be required by some DBM client driver during uninit/cleanup.
+ */
+void msm_dwc3_restart_usb_session(void)
+{
+	struct dwc3_msm *mdwc = context;
+
+	dev_dbg(mdwc->dev, "%s\n", __func__);
+	queue_work(system_nrt_wq, &mdwc->restart_usb_work);
+
+	return;
+}
+EXPORT_SYMBOL(msm_dwc3_restart_usb_session);
+
 /**
  * msm_register_usb_ext_notification: register for event notification
  * @info: pointer to client usb_ext_notification structure. May be NULL.
@@ -1244,8 +1290,39 @@
 
 	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1010);
 	data &= ~0xFF0;
-	data |= 0x40;
+	data |= 0x20;
 	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1010, data);
+
+	/*
+	 * Fix RX Equalization setting as follows
+	 * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0
+	 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1
+	 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
+	 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
+	 */
+	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1006);
+	data &= ~(1 << 6);
+	data |= (1 << 7);
+	data &= ~(0x7 << 8);
+	data |= (0x3 << 8);
+	data |= (0x1 << 11);
+	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1006, data);
+
+	/*
+	 * Set EQ and TX launch amplitudes as follows
+	 * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22
+	 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
+	 * LANE0.TX_OVRD_DRV_LO.EN set to 1.
+	 */
+	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1002);
+	data &= ~0x3F80;
+	data |= (0x16 << 7);
+	data &= ~0x7F;
+	data |= (0x7F | (1 << 14));
+	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1002, data);
+
+	/* Set LOS_BIAS to 0x5 */
+	dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1, 0x07, 0x5);
 }
 
 static void dwc3_msm_block_reset(void)
@@ -1293,6 +1370,17 @@
 	dwc3_msm_write_readback(mdwc->base, CHARGING_DET_CTRL_REG, 0x3F, 0x34);
 }
 
+static bool dwc3_chg_det_check_linestate(struct dwc3_msm *mdwc)
+{
+	u32 chg_det;
+	bool ret = false;
+
+	chg_det = dwc3_msm_read_reg(mdwc->base, CHARGING_DET_OUTPUT_REG);
+	ret = chg_det & (3 << 8);
+
+	return ret;
+}
+
 static bool dwc3_chg_det_check_output(struct dwc3_msm *mdwc)
 {
 	u32 chg_det;
@@ -1358,9 +1446,10 @@
 static const char *chg_to_string(enum dwc3_chg_type chg_type)
 {
 	switch (chg_type) {
-	case USB_SDP_CHARGER:		return "USB_SDP_CHARGER";
-	case USB_DCP_CHARGER:		return "USB_DCP_CHARGER";
-	case USB_CDP_CHARGER:		return "USB_CDP_CHARGER";
+	case DWC3_SDP_CHARGER:		return "USB_SDP_CHARGER";
+	case DWC3_DCP_CHARGER:		return "USB_DCP_CHARGER";
+	case DWC3_CDP_CHARGER:		return "USB_CDP_CHARGER";
+	case DWC3_PROPRIETARY_CHARGER:	return "USB_PROPRIETARY_CHARGER";
 	default:			return "INVALID_CHARGER";
 	}
 }
@@ -1390,6 +1479,14 @@
 		tmout = ++mdwc->dcd_retries == DWC3_CHG_DCD_MAX_RETRIES;
 		if (is_dcd || tmout) {
 			dwc3_chg_disable_dcd(mdwc);
+			if (dwc3_chg_det_check_linestate(mdwc)) {
+				dev_dbg(mdwc->dev, "proprietary charger\n");
+				mdwc->charger.chg_type =
+						DWC3_PROPRIETARY_CHARGER;
+				mdwc->chg_state = USB_CHG_STATE_DETECTED;
+				delay = 0;
+				break;
+			}
 			dwc3_chg_enable_primary_det(mdwc);
 			delay = DWC3_CHG_PRIMARY_DET_TIME;
 			mdwc->chg_state = USB_CHG_STATE_DCD_DONE;
@@ -1404,7 +1501,7 @@
 			delay = DWC3_CHG_SECONDARY_DET_TIME;
 			mdwc->chg_state = USB_CHG_STATE_PRIMARY_DONE;
 		} else {
-			mdwc->charger.chg_type = USB_SDP_CHARGER;
+			mdwc->charger.chg_type = DWC3_SDP_CHARGER;
 			mdwc->chg_state = USB_CHG_STATE_DETECTED;
 			delay = 0;
 		}
@@ -1412,9 +1509,9 @@
 	case USB_CHG_STATE_PRIMARY_DONE:
 		vout = dwc3_chg_det_check_output(mdwc);
 		if (vout)
-			mdwc->charger.chg_type = USB_DCP_CHARGER;
+			mdwc->charger.chg_type = DWC3_DCP_CHARGER;
 		else
-			mdwc->charger.chg_type = USB_CDP_CHARGER;
+			mdwc->charger.chg_type = DWC3_CDP_CHARGER;
 		mdwc->chg_state = USB_CHG_STATE_SECONDARY_DONE;
 		/* fall through */
 	case USB_CHG_STATE_SECONDARY_DONE:
@@ -1503,7 +1600,6 @@
 		 * 1. Set suspend and sleep bits in GUSB2PHYCONFIG reg
 		 * 2. Clear interrupt latch register and enable BSV, ID HV intr
 		 * 3. Enable DP and DM HV interrupts in ALT_INTERRUPT_EN_REG
-		 * 4. Enable PHY retention
 		 */
 		dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0),
 			dwc3_msm_read_reg(mdwc->base, DWC3_GUSB2PHYCFG(0)) |
@@ -1512,8 +1608,7 @@
 		if (mdwc->otg_xceiv && (!mdwc->ext_xceiv.otg_capability))
 			dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG,
 							 0x18000, 0x18000);
-		dwc3_msm_write_reg(mdwc->base, ALT_INTERRUPT_EN_REG, 0x00A);
-		dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG, 0x2, 0x0);
+		dwc3_msm_write_reg(mdwc->base, ALT_INTERRUPT_EN_REG, 0xFC0);
 		udelay(5);
 	} else {
 		/* Sequence to put hardware in low power state:
@@ -1542,10 +1637,8 @@
 	clk_disable_unprepare(mdwc->iface_clk);
 
 	/* USB PHY no more requires TCXO */
-	ret = msm_xo_mode_vote(mdwc->xo_handle, MSM_XO_MODE_OFF);
-	if (ret)
-		dev_err(mdwc->dev, "%s failed to devote for TCXO buffer%d\n",
-						__func__, ret);
+	if (!host_bus_suspend)
+		clk_disable_unprepare(mdwc->xo_clk);
 
 	if (mdwc->bus_perf_client) {
 		ret = msm_bus_scale_client_update_request(
@@ -1560,7 +1653,8 @@
 
 	dwc3_ssusb_ldo_enable(0);
 	dwc3_ssusb_config_vddcx(0);
-	dwc3_hsusb_config_vddcx(0);
+	if (!host_bus_suspend)
+		dwc3_hsusb_config_vddcx(0);
 	wake_unlock(&mdwc->wlock);
 	atomic_set(&mdwc->in_lpm, 1);
 
@@ -1594,21 +1688,25 @@
 			dev_err(mdwc->dev, "Failed to vote for bus scaling\n");
 	}
 
-	/* Vote for TCXO while waking up USB HSPHY */
-	ret = msm_xo_mode_vote(mdwc->xo_handle, MSM_XO_MODE_ON);
-	if (ret)
-		dev_err(mdwc->dev, "%s failed to vote for TCXO buffer%d\n",
-						__func__, ret);
-
 	dcp = mdwc->charger.chg_type == DWC3_DCP_CHARGER;
 	host_bus_suspend = mdwc->host_mode == 1;
+
+	if (!host_bus_suspend) {
+		/* Vote for TCXO while waking up USB HSPHY */
+		ret = clk_prepare_enable(mdwc->xo_clk);
+		if (ret)
+			dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n",
+						__func__, ret);
+	}
+
 	if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
 							!host_bus_suspend)
 		dwc3_hsusb_ldo_enable(1);
 
 	dwc3_ssusb_ldo_enable(1);
 	dwc3_ssusb_config_vddcx(1);
-	dwc3_hsusb_config_vddcx(1);
+	if (!host_bus_suspend)
+		dwc3_hsusb_config_vddcx(1);
 	clk_prepare_enable(mdwc->ref_clk);
 	usleep_range(1000, 1200);
 
@@ -1626,8 +1724,9 @@
 		/* Disable DP and DM HV interrupt */
 		dwc3_msm_write_reg(mdwc->base, ALT_INTERRUPT_EN_REG, 0x000);
 
-		/* Disable Retention */
-		dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG, 0x2, 0x2);
+		/* Clear suspend bit in GUSB2PHYCONFIG register */
+		dwc3_msm_write_readback(mdwc->base, DWC3_GUSB2PHYCFG(0),
+								0x40, 0x0);
 	} else {
 		/* Disable HV interrupt */
 		if (mdwc->otg_xceiv && (!mdwc->ext_xceiv.otg_capability))
@@ -1852,16 +1951,8 @@
 		if (mdwc->otg_xceiv && !mdwc->ext_inuse &&
 		    (mdwc->ext_xceiv.otg_capability || !init)) {
 			mdwc->ext_xceiv.bsv = val->intval;
-			if (atomic_read(&mdwc->in_lpm)) {
-				dev_dbg(mdwc->dev,
-					"%s received in LPM\n", __func__);
-				queue_delayed_work(system_nrt_wq,
+			queue_delayed_work(system_nrt_wq,
 							&mdwc->resume_work, 0);
-			} else {
-				mdwc->ext_xceiv.notify_ext_events(
-							mdwc->otg_xceiv->otg,
-							DWC3_EVENT_XCEIV_STATE);
-			}
 
 			if (!init)
 				init = true;
@@ -2090,20 +2181,21 @@
 	INIT_LIST_HEAD(&msm->req_complete_list);
 	INIT_DELAYED_WORK(&msm->chg_work, dwc3_chg_detect_work);
 	INIT_DELAYED_WORK(&msm->resume_work, dwc3_resume_work);
+	INIT_WORK(&msm->restart_usb_work, dwc3_restart_usb_work);
 	INIT_DELAYED_WORK(&msm->init_adc_work, dwc3_init_adc_work);
 
-	msm->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, "usb");
-	if (IS_ERR(msm->xo_handle)) {
+	msm->xo_clk = clk_get(&pdev->dev, "xo");
+	if (IS_ERR(msm->xo_clk)) {
 		dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n",
 								__func__);
-		return PTR_ERR(msm->xo_handle);
+		return PTR_ERR(msm->xo_clk);
 	}
 
-	ret = msm_xo_mode_vote(msm->xo_handle, MSM_XO_MODE_ON);
+	ret = clk_prepare_enable(msm->xo_clk);
 	if (ret) {
 		dev_err(&pdev->dev, "%s failed to vote for TCXO buffer%d\n",
 						__func__, ret);
-		goto free_xo_handle;
+		goto put_xo;
 	}
 
 	/*
@@ -2114,7 +2206,7 @@
 	if (IS_ERR(msm->core_clk)) {
 		dev_err(&pdev->dev, "failed to get core_clk\n");
 		ret = PTR_ERR(msm->core_clk);
-		goto free_xo_handle;
+		goto disable_xo;
 	}
 	clk_set_rate(msm->core_clk, 125000000);
 	clk_prepare_enable(msm->core_clk);
@@ -2442,8 +2534,10 @@
 	clk_disable_unprepare(msm->iface_clk);
 disable_core_clk:
 	clk_disable_unprepare(msm->core_clk);
-free_xo_handle:
-	msm_xo_put(msm->xo_handle);
+disable_xo:
+	clk_disable_unprepare(msm->xo_clk);
+put_xo:
+	clk_put(msm->xo_clk);
 
 	return ret;
 }
@@ -2478,7 +2572,8 @@
 	clk_disable_unprepare(msm->sleep_clk);
 	clk_disable_unprepare(msm->hsphy_sleep_clk);
 	clk_disable_unprepare(msm->ref_clk);
-	msm_xo_put(msm->xo_handle);
+	clk_disable_unprepare(msm->xo_clk);
+	clk_put(msm->xo_clk);
 
 	return 0;
 }
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 4980337..01fad76 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -373,6 +373,10 @@
 	struct usb_phy *phy = dotg->otg.phy;
 	int ret = 0;
 
+	/* Flush processing any pending events before handling new ones */
+	if (init)
+		flush_work(&dotg->sm_work);
+
 	if (event == DWC3_EVENT_PHY_RESUME) {
 		if (!pm_runtime_status_suspended(phy->dev)) {
 			dev_warn(phy->dev, "PHY_RESUME event out of LPM!!!!\n");
@@ -394,6 +398,12 @@
 			}
 		}
 	} else if (event == DWC3_EVENT_XCEIV_STATE) {
+		if (pm_runtime_status_suspended(phy->dev)) {
+			dev_warn(phy->dev, "PHY_STATE event in LPM!!!!\n");
+			ret = pm_runtime_get(phy->dev);
+			if (ret < 0)
+				dev_warn(phy->dev, "pm_runtime_get failed!!\n");
+		}
 		if (ext_xceiv->id == DWC3_ID_FLOAT) {
 			dev_dbg(phy->dev, "XCVR: ID set\n");
 			set_bit(ID, &dotg->inputs);
@@ -472,7 +482,8 @@
 		power_supply_type = POWER_SUPPLY_TYPE_USB;
 	else if (dotg->charger->chg_type == DWC3_CDP_CHARGER)
 		power_supply_type = POWER_SUPPLY_TYPE_USB_CDP;
-	else if (dotg->charger->chg_type == DWC3_DCP_CHARGER)
+	else if (dotg->charger->chg_type == DWC3_DCP_CHARGER ||
+			dotg->charger->chg_type == DWC3_PROPRIETARY_CHARGER)
 		power_supply_type = POWER_SUPPLY_TYPE_USB_DCP;
 	else
 		power_supply_type = POWER_SUPPLY_TYPE_BATTERY;
@@ -675,6 +686,7 @@
 				/* Has charger been detected? If no detect it */
 				switch (charger->chg_type) {
 				case DWC3_DCP_CHARGER:
+				case DWC3_PROPRIETARY_CHARGER:
 					dev_dbg(phy->dev, "lpm, DCP charger\n");
 					dwc3_otg_set_power(phy,
 							DWC3_IDEV_CHG_MAX);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 07d6411..d3b1b4a 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -61,12 +61,15 @@
  * DWC3_DCP_CHARGER	Dedicated charger port (AC charger/ Wall charger).
  * DWC3_CDP_CHARGER	Charging downstream port. Enumeration can happen and
  *                      IDEV_CHG_MAX can be drawn irrespective of USB state.
+ * DWC3_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific
+ *                     voltages between 2.0-3.3v for identification.
  */
 enum dwc3_chg_type {
 	DWC3_INVALID_CHARGER = 0,
 	DWC3_SDP_CHARGER,
 	DWC3_DCP_CHARGER,
 	DWC3_CDP_CHARGER,
+	DWC3_PROPRIETARY_CHARGER,
 };
 
 struct dwc3_charger {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 0cce630..9fa1ab4 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -356,7 +356,16 @@
 		if (!(reg & DWC3_DEPCMD_CMDACT)) {
 			dev_vdbg(dwc->dev, "Command Complete --> %d\n",
 					DWC3_DEPCMD_STATUS(reg));
-			return 0;
+			/* SW issues START TRANSFER command to isochronous ep
+			 * with future frame interval. If future interval time
+			 * has already passed when core recieves command, core
+			 * will respond with an error(bit13 in Command complete
+			 * event. Hence return error in this case.
+			 */
+			if (reg & 0x2000)
+				return -EAGAIN;
+			else
+				return 0;
 		}
 
 		/*
@@ -769,9 +778,9 @@
 	dep->free_slot++;
 
 	/* Skip the LINK-TRB on ISOC */
-	if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
+	if (((dep->free_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
 			usb_endpoint_xfer_isoc(dep->endpoint.desc))
-		return;
+		dep->free_slot++;
 
 	if (!req->trb) {
 		dwc3_gadget_move_request_queued(req);
@@ -945,7 +954,7 @@
 		int start_new)
 {
 	struct dwc3_gadget_ep_cmd_params params;
-	struct dwc3_request		*req;
+	struct dwc3_request		*req, *req1, *n;
 	struct dwc3			*dwc = dep->dwc;
 	int				ret;
 	u32				cmd;
@@ -993,15 +1002,44 @@
 	if (ret < 0) {
 		dev_dbg(dwc->dev, "failed to send STARTTRANSFER command\n");
 
-		/*
-		 * FIXME we need to iterate over the list of requests
-		 * here and stop, unmap, free and del each of the linked
-		 * requests instead of what we do now.
-		 */
-		usb_gadget_unmap_request(&dwc->gadget, &req->request,
+		if ((ret == -EAGAIN) && start_new &&
+				usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+			/* If bit13 in Command complete event is set, software
+			 * must issue ENDTRANDFER command and wait for
+			 * Xfernotready event to queue the requests again.
+			 */
+			if (!dep->resource_index) {
+				dep->resource_index =
+					 dwc3_gadget_ep_get_transfer_index(dwc,
+								dep->number);
+				WARN_ON_ONCE(!dep->resource_index);
+			}
+			dwc3_stop_active_transfer(dwc, dep->number);
+			list_for_each_entry_safe_reverse(req1, n,
+						 &dep->req_queued, list) {
+				req1->trb = NULL;
+				dwc3_gadget_move_request_list_front(req1);
+				if (req->request.num_mapped_sgs)
+					dep->busy_slot +=
+						 req->request.num_mapped_sgs;
+				else
+					dep->busy_slot++;
+				if ((dep->busy_slot & DWC3_TRB_MASK) ==
+							DWC3_TRB_NUM - 1)
+					dep->busy_slot++;
+			}
+			return ret;
+		} else {
+			/*
+			 * FIXME we need to iterate over the list of requests
+			 * here and stop, unmap, free and del each of the linked
+			 * requests instead of what we do now.
+			 */
+			usb_gadget_unmap_request(&dwc->gadget, &req->request,
 				req->direction);
-		list_del(&req->list);
-		return ret;
+			list_del(&req->list);
+			return ret;
+		}
 	}
 
 	dep->flags |= DWC3_EP_BUSY;
@@ -1020,6 +1058,8 @@
 {
 	u32 uf;
 
+	dep->current_uf = cur_uf;
+
 	if (list_empty(&dep->request_list)) {
 		dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
 			dep->name);
@@ -1049,6 +1089,13 @@
 	struct dwc3		*dwc = dep->dwc;
 	int			ret;
 
+	if (req->request.status == -EINPROGRESS) {
+		ret = -EBUSY;
+		dev_err(dwc->dev, "%s: %p request already in queue",
+					dep->name, req);
+		return ret;
+	}
+
 	req->request.actual	= 0;
 	req->request.status	= -EINPROGRESS;
 	req->direction		= dep->direction;
@@ -1094,7 +1141,17 @@
 		 * notion of current microframe.
 		 */
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
-			dwc3_stop_active_transfer(dwc, dep->number);
+			/* If xfernotready event is recieved before issuing
+			 * START TRANSFER command, don't issue END TRANSFER.
+			 * Rather start queueing the requests by issuing START
+			 * TRANSFER command.
+			 */
+			if (list_empty(&dep->req_queued) && dep->resource_index)
+				dwc3_stop_active_transfer(dwc, dep->number);
+			else
+				__dwc3_gadget_start_isoc(dwc, dep,
+							dep->current_uf);
+			dep->flags &= ~DWC3_EP_PENDING_REQUEST;
 			return 0;
 		}
 
@@ -1120,16 +1177,6 @@
 					dep->name);
 	}
 
-	/*
-	 * 3. Missed ISOC Handling. We need to start isoc transfer on the saved
-	 * uframe number.
-	 */
-	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-		(dep->flags & DWC3_EP_MISSED_ISOC)) {
-			__dwc3_gadget_start_isoc(dwc, dep, dep->current_uf);
-			dep->flags &= ~DWC3_EP_MISSED_ISOC;
-	}
-
 	return 0;
 }
 
@@ -1847,14 +1894,29 @@
 				if (trb_status == DWC3_TRBSTS_MISSED_ISOC) {
 					dev_dbg(dwc->dev, "incomplete IN transfer %s\n",
 							dep->name);
-					dep->current_uf = event->parameters &
-						~(dep->interval - 1);
+					/*
+					 * If missed isoc occurred and there is
+					 * no request queued then issue END
+					 * TRANSFER, so that core generates
+					 * next xfernotready and we will issue
+					 * a fresh START TRANSFER.
+					 * If there are still queued request
+					 * then wait, do not issue either END
+					 * or UPDATE TRANSFER, just attach next
+					 * request in request_list during
+					 * giveback.If any future queued request
+					 * is successfully transferred then we
+					 * will issue UPDATE TRANSFER for all
+					 * request in the request_list.
+					 */
 					dep->flags |= DWC3_EP_MISSED_ISOC;
 				} else {
 					dev_err(dwc->dev, "incomplete IN transfer %s\n",
 							dep->name);
 					status = -ECONNRESET;
 				}
+			} else {
+				dep->flags &= ~DWC3_EP_MISSED_ISOC;
 			}
 		} else {
 			if (count && (event->status & DEPEVT_STATUS_SHORT))
@@ -1881,6 +1943,22 @@
 			break;
 	} while (1);
 
+	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+			list_empty(&dep->req_queued)) {
+		if (list_empty(&dep->request_list))
+			/*
+			 * If there is no entry in request list then do
+			 * not issue END TRANSFER now. Just set PENDING
+			 * flag, so that END TRANSFER is issued when an
+			 * entry is added into request list.
+			 */
+			dep->flags |= DWC3_EP_PENDING_REQUEST;
+		else
+			dwc3_stop_active_transfer(dwc, dep->number);
+		dep->flags &= ~DWC3_EP_MISSED_ISOC;
+		return 1;
+	}
+
 	if ((event->status & DEPEVT_STATUS_IOC) &&
 			(trb->ctrl & DWC3_TRB_CTRL_IOC))
 		return 0;
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index dc7a3c1..cd5492f 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -94,6 +94,14 @@
 	return list_first_entry(list, struct dwc3_request, list);
 }
 
+static inline void dwc3_gadget_move_request_list_front(struct dwc3_request *req)
+{
+	struct dwc3_ep		*dep = req->dep;
+
+	req->queued = false;
+	list_move(&req->list, &dep->request_list);
+}
+
 static inline void dwc3_gadget_move_request_queued(struct dwc3_request *req)
 {
 	struct dwc3_ep		*dep = req->dep;
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 0514aa8..245a972 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2512,6 +2512,8 @@
 	fsg->bulk_out_enabled = 1;
 	common->bulk_out_maxpacket = le16_to_cpu(fsg->bulk_in->desc->wMaxPacketSize);
 	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+	csw_hack_sent = 0;
+	write_error_after_csw_sent = 0;
 	fsg->common->new_fsg = fsg;
 	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
 	return USB_GADGET_DELAYED_STATUS;
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index b82edd9..3069bcb 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -410,6 +410,7 @@
 
 	clear_eps(f);
 	clear_desc(c->cdev->gadget, f);
+	msm_dwc3_restart_usb_session();
 }
 
 static void qdss_eps_disable(struct usb_function *f)
@@ -795,11 +796,13 @@
 	pr_debug("usb_qdss_close\n");
 
 	spin_lock_irqsave(&d_lock, flags);
-	/*free not used reqests*/
-	usb_qdss_free_req(ch);
 	usb_ep_dequeue(qdss->data, qdss->endless_req);
+	usb_ep_free_request(qdss->data, qdss->endless_req);
 	qdss->endless_req = NULL;
+	ch->app_conn = 0;
 	spin_unlock_irqrestore(&d_lock, flags);
+
+	msm_dwc3_restart_usb_session();
 }
 EXPORT_SYMBOL(usb_qdss_close);
 
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1a75bd7..24f3cb1 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -256,8 +256,11 @@
 		else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
 			/*clear RS bit before setting SUSP bit
 			* and wait for HCH to get set*/
-			if (ehci->susp_sof_bug)
+			if (ehci->susp_sof_bug) {
+				spin_unlock_irq(&ehci->lock);
 				ehci_halt(ehci);
+				spin_lock_irq(&ehci->lock);
+			}
 
 			t2 |= PORT_SUSPEND;
 			set_bit(port, &ehci->bus_suspended);
@@ -1268,7 +1271,9 @@
 							temp | PORT_SUSPEND,
 							sreg);
 				}
+				spin_unlock_irq(&ehci->lock);
 				ehci_halt(ehci);
+				spin_lock_irq(&ehci->lock);
 				temp = ehci_readl(ehci, status_reg);
 				temp |= selector << 16;
 				ehci_writel(ehci, temp, status_reg);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index d5321ff..67040e5 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -85,6 +85,8 @@
 	int			peripheral_status_irq;
 	int			wakeup_irq;
 	bool			wakeup_irq_enabled;
+	int			async_irq;
+	uint32_t		async_int_cnt;
 	atomic_t		pm_usage_cnt;
 	uint32_t		bus_perf_client;
 	uint32_t		wakeup_int_cnt;
@@ -820,9 +822,11 @@
 	atomic_set(&mehci->in_lpm, 1);
 	enable_irq(hcd->irq);
 
-	mehci->wakeup_irq_enabled = 1;
-	enable_irq_wake(mehci->wakeup_irq);
-	enable_irq(mehci->wakeup_irq);
+	if (mehci->wakeup_irq) {
+		mehci->wakeup_irq_enabled = 1;
+		enable_irq_wake(mehci->wakeup_irq);
+		enable_irq(mehci->wakeup_irq);
+	}
 
 	if (pdata && pdata->standalone_latency)
 		pm_qos_update_request(&mehci->pm_qos_req_dma,
@@ -856,13 +860,15 @@
 		pm_qos_update_request(&mehci->pm_qos_req_dma,
 			pdata->standalone_latency + 1);
 
-	spin_lock_irqsave(&mehci->wakeup_lock, flags);
-	if (mehci->wakeup_irq_enabled) {
-		disable_irq_wake(mehci->wakeup_irq);
-		disable_irq_nosync(mehci->wakeup_irq);
-		mehci->wakeup_irq_enabled = 0;
+	if (mehci->wakeup_irq) {
+		spin_lock_irqsave(&mehci->wakeup_lock, flags);
+		if (mehci->wakeup_irq_enabled) {
+			disable_irq_wake(mehci->wakeup_irq);
+			disable_irq_nosync(mehci->wakeup_irq);
+			mehci->wakeup_irq_enabled = 0;
+		}
+		spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
 	}
-	spin_unlock_irqrestore(&mehci->wakeup_lock, flags);
 
 	wake_lock(&mehci->wlock);
 
@@ -1412,20 +1418,28 @@
 	struct msm_hsic_hcd *mehci = data;
 	int ret;
 
-	mehci->wakeup_int_cnt++;
-	dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
-	dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
-			__func__, mehci->wakeup_int_cnt);
+	if (irq == mehci->async_irq) {
+		mehci->async_int_cnt++;
+		dbg_log_event(NULL, "Remote Wakeup (ASYNC) IRQ",
+							 mehci->async_int_cnt);
+	} else {
+		mehci->wakeup_int_cnt++;
+		dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
+	}
+	dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt %d cnt: %u, %u\n",
+		    __func__, irq, mehci->wakeup_int_cnt, mehci->async_int_cnt);
 
 	wake_lock(&mehci->wlock);
 
-	spin_lock(&mehci->wakeup_lock);
-	if (mehci->wakeup_irq_enabled) {
-		mehci->wakeup_irq_enabled = 0;
-		disable_irq_wake(irq);
-		disable_irq_nosync(irq);
+	if (mehci->wakeup_irq) {
+		spin_lock(&mehci->wakeup_lock);
+		if (mehci->wakeup_irq_enabled) {
+			mehci->wakeup_irq_enabled = 0;
+			disable_irq_wake(irq);
+			disable_irq_nosync(irq);
+		}
+		spin_unlock(&mehci->wakeup_lock);
 	}
-	spin_unlock(&mehci->wakeup_lock);
 
 	if (!atomic_read(&mehci->pm_usage_cnt)) {
 		ret = pm_runtime_get(mehci->dev);
@@ -1843,6 +1857,21 @@
 		}
 	}
 
+	mehci->async_irq = platform_get_irq_byname(pdev, "async_irq");
+	if (mehci->async_irq < 0) {
+		dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n");
+		mehci->async_irq = 0;
+	} else {
+		ret = request_irq(mehci->async_irq, msm_hsic_wakeup_irq,
+				IRQF_TRIGGER_RISING, "msm_hsic_async", mehci);
+		if (ret) {
+			dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n");
+			mehci->async_irq = 0;
+		} else {
+			enable_irq_wake(mehci->async_irq);
+		}
+	}
+
 	ret = ehci_hsic_msm_debugfs_init(mehci);
 	if (ret)
 		dev_dbg(&pdev->dev, "mode debugfs file is"
@@ -1904,6 +1933,9 @@
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
 	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
 
+	/* Remove the HCD prior to releasing our resources. */
+	usb_remove_hcd(hcd);
+
 	if (pdata && pdata->standalone_latency)
 		pm_qos_remove_request(&mehci->pm_qos_req_dma);
 
@@ -1916,6 +1948,10 @@
 		free_irq(mehci->wakeup_irq, mehci);
 	}
 
+	if (mehci->async_irq) {
+		disable_irq_wake(mehci->async_irq);
+		free_irq(mehci->async_irq, mehci);
+	}
 	/*
 	 * If the update request is called after unregister, the request will
 	 * fail. Results are undefined if unregister is called in the middle of
@@ -1933,7 +1969,6 @@
 
 	destroy_workqueue(ehci_wq);
 
-	usb_remove_hcd(hcd);
 	msm_hsic_config_gpios(mehci, 0);
 	msm_hsic_init_vddcx(mehci, 0);
 	msm_hsic_init_gdsc(mehci, 0);
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
index 5c87691..40e1eea 100644
--- a/drivers/usb/host/ehci-msm2.c
+++ b/drivers/usb/host/ehci-msm2.c
@@ -979,8 +979,10 @@
 	return 0;
 
 put_clocks:
-	clk_disable_unprepare(mhcd->iface_clk);
-	clk_disable_unprepare(mhcd->core_clk);
+	if (!atomic_read(&mhcd->in_lpm)) {
+		clk_disable_unprepare(mhcd->iface_clk);
+		clk_disable_unprepare(mhcd->core_clk);
+	}
 	clk_put(mhcd->core_clk);
 	if (!IS_ERR(mhcd->phy_sleep_clk)) {
 		clk_disable_unprepare(mhcd->phy_sleep_clk);
@@ -1230,7 +1232,6 @@
 		free_irq(mhcd->async_irq, mhcd);
 	}
 	device_init_wakeup(&pdev->dev, 0);
-	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
 	usb_remove_hcd(hcd);
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 78ece8d..717103d 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -485,6 +485,7 @@
 	struct xhci_bus_state *bus_state;
 	u16 link_state = 0;
 	u16 wake_mask = 0;
+	u16 test_mode = 0;
 
 	max_ports = xhci_get_ports(hcd, &port_array);
 	bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -628,6 +629,8 @@
 		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
 		break;
 	case SetPortFeature:
+		/* The MSB of wIndex is the TEST Mode */
+		test_mode = (wIndex & 0xff00) >> 8;
 		if (wValue == USB_PORT_FEAT_LINK_STATE)
 			link_state = (wIndex & 0xff00) >> 3;
 		if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
@@ -762,6 +765,23 @@
 
 			temp = xhci_readl(xhci, port_array[wIndex]);
 			break;
+		case USB_PORT_FEAT_TEST:
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					wIndex + 1);
+			if (test_mode && test_mode <= 5) {
+				/* unlock to execute stop endpoint commands */
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				xhci_stop_device(xhci, slot_id, 1);
+				spin_lock_irqsave(&xhci->lock, flags);
+				xhci_halt(xhci);
+
+				temp = xhci_readl(xhci, port_array[wIndex] + 1);
+				temp |= test_mode << 28;
+				xhci_writel(xhci, temp, port_array[wIndex] + 1);
+			} else {
+				goto error;
+			}
+			break;
 		default:
 			goto error;
 		}
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 1547691..1ee1c8e 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -1,5 +1,4 @@
-/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -31,6 +30,7 @@
 #define DRIVER_DESC	"USB host diag bridge driver"
 #define DRIVER_VERSION	"1.0"
 
+#define MAX_DIAG_BRIDGE_DEVS	2
 #define AUTOSUSP_DELAY_WITH_USB 1000
 
 struct diag_bridge {
@@ -52,12 +52,18 @@
 	unsigned		pending_reads;
 	unsigned		pending_writes;
 };
-struct diag_bridge *__dev;
+struct diag_bridge *__dev[MAX_DIAG_BRIDGE_DEVS];
 
-int diag_bridge_open(struct diag_bridge_ops *ops)
+int diag_bridge_open(int id, struct diag_bridge_ops *ops)
 {
-	struct diag_bridge	*dev = __dev;
+	struct diag_bridge	*dev;
 
+	if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID");
+		return -ENODEV;
+	}
+
+	dev = __dev[id];
 	if (!dev) {
 		pr_err("dev is null");
 		return -ENODEV;
@@ -86,16 +92,23 @@
 static void diag_bridge_delete(struct kref *kref)
 {
 	struct diag_bridge *dev = container_of(kref, struct diag_bridge, kref);
+	int id = dev->pdev->id;
 
 	usb_put_dev(dev->udev);
-	__dev = 0;
+	__dev[id] = 0;
 	kfree(dev);
 }
 
-void diag_bridge_close(void)
+void diag_bridge_close(int id)
 {
-	struct diag_bridge	*dev = __dev;
+	struct diag_bridge	*dev;
 
+	if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID");
+		return;
+	}
+
+	dev = __dev[id];
 	if (!dev) {
 		pr_err("dev is null");
 		return;
@@ -141,15 +154,21 @@
 	kref_put(&dev->kref, diag_bridge_delete);
 }
 
-int diag_bridge_read(char *data, int size)
+int diag_bridge_read(int id, char *data, int size)
 {
 	struct urb		*urb = NULL;
 	unsigned int		pipe;
-	struct diag_bridge	*dev = __dev;
+	struct diag_bridge	*dev;
 	int			ret;
 
+	if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID");
+		return -ENODEV;
+	}
+
 	pr_debug("reading %d bytes", size);
 
+	dev = __dev[id];
 	if (!dev) {
 		pr_err("device is disconnected");
 		return -ENODEV;
@@ -243,15 +262,21 @@
 	kref_put(&dev->kref, diag_bridge_delete);
 }
 
-int diag_bridge_write(char *data, int size)
+int diag_bridge_write(int id, char *data, int size)
 {
 	struct urb		*urb = NULL;
 	unsigned int		pipe;
-	struct diag_bridge	*dev = __dev;
+	struct diag_bridge	*dev;
 	int			ret;
 
+	if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID");
+		return -ENODEV;
+	}
+
 	pr_debug("writing %d bytes", size);
 
+	dev = __dev[id];
 	if (!dev) {
 		pr_err("device is disconnected");
 		return -ENODEV;
@@ -328,28 +353,30 @@
 static ssize_t diag_read_stats(struct file *file, char __user *ubuf,
 				size_t count, loff_t *ppos)
 {
-	struct diag_bridge	*dev = __dev;
 	char			*buf;
-	int			ret;
-
-	if (!dev)
-		return -ENODEV;
+	int			i, ret = 0;
 
 	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
-			"epin:%d, epout:%d\n"
-			"bytes to host: %lu\n"
-			"bytes to mdm: %lu\n"
-			"pending reads: %u\n"
-			"pending writes: %u\n"
-			"last error: %d\n",
-			dev->in_epAddr, dev->out_epAddr,
-			dev->bytes_to_host, dev->bytes_to_mdm,
-			dev->pending_reads, dev->pending_writes,
-			dev->err);
+	for (i = 0; i < MAX_DIAG_BRIDGE_DEVS; i++) {
+		struct diag_bridge *dev = __dev[i];
+		if (!dev)
+			continue;
+
+		ret += scnprintf(buf, DEBUG_BUF_SIZE,
+				"epin:%d, epout:%d\n"
+				"bytes to host: %lu\n"
+				"bytes to mdm: %lu\n"
+				"pending reads: %u\n"
+				"pending writes: %u\n"
+				"last error: %d\n",
+				dev->in_epAddr, dev->out_epAddr,
+				dev->bytes_to_host, dev->bytes_to_mdm,
+				dev->pending_reads, dev->pending_writes,
+				dev->err);
+	}
 
 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
 	kfree(buf);
@@ -359,11 +386,14 @@
 static ssize_t diag_reset_stats(struct file *file, const char __user *buf,
 				 size_t count, loff_t *ppos)
 {
-	struct diag_bridge	*dev = __dev;
+	int i;
 
-	if (dev) {
-		dev->bytes_to_host = dev->bytes_to_mdm = 0;
-		dev->pending_reads = dev->pending_writes = 0;
+	for (i = 0; i < MAX_DIAG_BRIDGE_DEVS; i++) {
+		struct diag_bridge *dev = __dev[i];
+		if (dev) {
+			dev->bytes_to_host = dev->bytes_to_mdm = 0;
+			dev->pending_reads = dev->pending_writes = 0;
+		}
 	}
 
 	return count;
@@ -407,8 +437,7 @@
 	struct diag_bridge		*dev;
 	struct usb_host_interface	*ifc_desc;
 	struct usb_endpoint_descriptor	*ep_desc;
-	int				i;
-	int				ret = -ENOMEM;
+	int				i, devid, ret = -ENOMEM;
 	__u8				ifc_num;
 
 	pr_debug("id:%lu", id->driver_info);
@@ -416,21 +445,31 @@
 	ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
 
 	/* is this interface supported ? */
-	if (ifc_num != id->driver_info)
+	if (ifc_num != (id->driver_info & 0xFF))
 		return -ENODEV;
 
+	devid = (id->driver_info >> 8) & 0xFF;
+	if (devid < 0 || devid >= MAX_DIAG_BRIDGE_DEVS)
+		return -ENODEV;
+
+	/* already probed? */
+	if (__dev[devid]) {
+		pr_err("Diag device already probed");
+		return -ENODEV;
+	}
+
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
 		pr_err("unable to allocate dev");
 		return -ENOMEM;
 	}
-	dev->pdev = platform_device_alloc("diag_bridge", -1);
+	dev->pdev = platform_device_alloc("diag_bridge", devid);
 	if (!dev->pdev) {
 		pr_err("unable to allocate platform device");
 		kfree(dev);
 		return -ENOMEM;
 	}
-	__dev = dev;
+	__dev[devid] = dev;
 
 	dev->udev = usb_get_dev(interface_to_usbdev(ifc));
 	dev->ifc = ifc;
@@ -518,17 +557,21 @@
 }
 
 #define VALID_INTERFACE_NUM	0
+#define DEV_ID(n)		((n)<<8)
+
 static const struct usb_device_id diag_bridge_ids[] = {
 	{ USB_DEVICE(0x5c6, 0x9001),
-	.driver_info = VALID_INTERFACE_NUM, },
+	.driver_info = VALID_INTERFACE_NUM | DEV_ID(0), },
 	{ USB_DEVICE(0x5c6, 0x9034),
-	.driver_info = VALID_INTERFACE_NUM, },
+	.driver_info = VALID_INTERFACE_NUM | DEV_ID(0), },
 	{ USB_DEVICE(0x5c6, 0x9048),
-	.driver_info = VALID_INTERFACE_NUM, },
+	.driver_info = VALID_INTERFACE_NUM | DEV_ID(0), },
 	{ USB_DEVICE(0x5c6, 0x904C),
-	.driver_info = VALID_INTERFACE_NUM, },
+	.driver_info = VALID_INTERFACE_NUM | DEV_ID(0), },
 	{ USB_DEVICE(0x5c6, 0x9075),
-	.driver_info = VALID_INTERFACE_NUM, },
+	.driver_info = VALID_INTERFACE_NUM | DEV_ID(0), },
+	{ USB_DEVICE(0x5c6, 0x9079),
+	.driver_info = VALID_INTERFACE_NUM | DEV_ID(1), },
 
 	{} /* terminating entry */
 };
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index a3b92ed..7aeca6e 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -244,6 +244,7 @@
 	VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p240_16_9),
 	VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i240_4_3),
 	VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i240_16_9),
+	VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x1024p60_5_4)
 };
 EXPORT_SYMBOL(hdmi_common_supported_video_mode_lut);
 
@@ -308,6 +309,7 @@
 	VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p240_16_9),
 	VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i240_4_3),
 	VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i240_16_9),
+	HDMI_SETTINGS_1280x1024p60_5_4
 };
 EXPORT_SYMBOL(hdmi_mhl_supported_video_mode_lut);
 
@@ -1075,6 +1077,8 @@
 	 89909, 119880, 148352, 119880, FALSE},
 	{HDMI_VFRMT_1280x720p120_16_9, 1280, 720, FALSE, 1650, 370, 750, 30,
 	 90000, 120000, 148500, 120000, FALSE},
+	{HDMI_VFRMT_1280x1024p60_5_4, 1280, 1024, FALSE, 1688, 408, 1066, 42,
+	 63981, 60020, 108000, 60000, FALSE},
 
 	/* All 1440 H Active */
 	{HDMI_VFRMT_1440x576i50_4_3, 1440, 576, TRUE,  1728, 288, 625, 24,
@@ -1569,7 +1573,8 @@
 	struct hdmi_disp_mode_list_type *disp_mode_list,
 	uint32 num_og_cea_blocks)
 {
-	uint8 len, offset, present_multi_3d, hdmi_vic_len, hdmi_3d_len;
+	uint8 len, offset, present_multi_3d, hdmi_vic_len;
+	int hdmi_3d_len;
 	uint16 structure_all, structure_mask;
 	const uint8 *vsd = num_og_cea_blocks ?
 		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
@@ -1693,7 +1698,7 @@
 	struct hdmi_disp_mode_list_type *disp_mode_list,
 	uint32 num_og_cea_blocks)
 {
-	uint8 i			= 0;
+	uint8 i			= 0, offset = 0, std_blk = 0;
 	uint32 video_format	= HDMI_VFRMT_640x480p60_4_3;
 	boolean has480p		= FALSE;
 	uint8 len;
@@ -1824,6 +1829,66 @@
 		}
 	}
 
+
+	/*
+	 * Check SD Timings if it contains 1280x1024@60Hz.
+	 * SD Timing can be max 8 with 2 byte in size.
+	 */
+	std_blk = 0;
+	offset  = 0;
+	while (std_blk < 8) {
+		if ((edid_blk0[0x26 + offset] == 0x81) &&
+			(edid_blk0[0x26 + offset + 1] == 0x80)) {
+			add_supported_video_format(disp_mode_list,
+					HDMI_VFRMT_1280x1024p60_5_4);
+			break;
+		} else {
+			offset += 2;
+		}
+		std_blk++;
+	}
+
+	/* check if the EDID revision is 4 (version 1.4) */
+	if (edid_blk0[0x13] == 4) {
+		uint8  start = 0x36;
+
+		i = 0;
+
+		/* Check each of 4 - 18 bytes descriptors */
+		while (i < 4) {
+			uint8  itrate   = start;
+			uint32 header_1 = 0;
+			uint8  header_2 = 0;
+
+			/*
+			 * First 5 bytes are header.
+			 * If they match 0x000000F700, it means its an
+			 * established Timing III descriptor.
+			 */
+			header_1 = edid_blk0[itrate++];
+			header_1 = header_1 << 8 | edid_blk0[itrate++];
+			header_1 = header_1 << 8 | edid_blk0[itrate++];
+			header_1 = header_1 << 8 | edid_blk0[itrate++];
+			header_2 = edid_blk0[itrate];
+
+			if (header_1 == 0x000000F7 &&
+			    header_2 == 0x00) {
+				itrate++; /* VESA DMT Standard Version (0x0A)*/
+				itrate++; /* First set of supported formats */
+				itrate++; /* Second set of supported formats */
+				/* BIT(1) indicates 1280x1024@60Hz */
+				if (edid_blk0[itrate] & 0x02) {
+					add_supported_video_format(
+						disp_mode_list,
+						HDMI_VFRMT_1280x1024p60_5_4);
+					break;
+				}
+			}
+			i++;
+			start += 0x12;
+		}
+	}
+
 	/* mandaroty 3d format */
 	if (external_common_state->present_3d) {
 		if (has60hz_mode) {
@@ -2053,7 +2118,7 @@
 
 bool hdmi_common_get_video_format_from_drv_data(struct msm_fb_data_type *mfd)
 {
-	uint32 format = HDMI_VFRMT_1920x1080p60_16_9;
+	uint32 format =  external_common_state->video_resolution;
 	struct fb_var_screeninfo *var = &mfd->fbi->var;
 	bool changed = TRUE;
 
@@ -2076,7 +2141,9 @@
 				: HDMI_VFRMT_720x576p50_16_9;
 			break;
 		case 1280:
-			if (mfd->var_frame_rate == 50000)
+			if (mfd->var_yres == 1024)
+				format = HDMI_VFRMT_1280x1024p60_5_4;
+			else if (mfd->var_frame_rate == 50000)
 				format = HDMI_VFRMT_1280x720p50_16_9;
 			else
 				format = HDMI_VFRMT_1280x720p60_16_9;
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index b27e4c8..d117898 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -109,9 +109,19 @@
 #define HDMI_VFRMT_1440x480i240_4_3	HDMI_VFRMT_720x480i240_4_3
 #define HDMI_VFRMT_720x480i240_16_9	58
 #define HDMI_VFRMT_1440x480i240_16_9	HDMI_VFRMT_720x480i240_16_9
-#define HDMI_VFRMT_MAX			59
 #define HDMI_VFRMT_FORCE_32BIT		0x7FFFFFFF
 
+/* Video Identification Codes from 65-127 are reserved for the future */
+#define HDMI_VFRMT_END			127
+
+/* VESA DMT TIMINGS */
+/* DMT ID: 23h, STD code: (81h, 80h), also a part of Established Timing III */
+#define HDMI_VFRMT_1280x1024p60_5_4	(HDMI_VFRMT_END + 1)
+#define DMT_VFRMT_END                   HDMI_VFRMT_1280x1024p60_5_4
+
+#define HDMI_VFRMT_MAX	                (DMT_VFRMT_END + 1)
+
+
 extern int ext_resolution;
 
 struct hdmi_disp_mode_timing_type {
@@ -185,6 +195,9 @@
 #define HDMI_SETTINGS_1920x1080p30_16_9					\
 	{HDMI_VFRMT_1920x1080p30_16_9,   1920,  88,   44,  148,  FALSE,	\
 	 1080, 4, 5, 36, FALSE, 74250, 30000, FALSE, TRUE}
+#define HDMI_SETTINGS_1280x1024p60_5_4					\
+	{HDMI_VFRMT_1280x1024p60_5_4,   1280,  48,  112,  248,  FALSE, \
+	 1024, 1, 3, 38, FALSE, 108000, 60000, FALSE, TRUE}
 
 /* A lookup table for all the supported display modes by the HDMI
  * hardware and driver.  Use HDMI_SETUP_LUT in the module init to
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 8dbeaa0..fa57992 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -647,6 +647,7 @@
 	HDMI_SETUP_LUT(1920x1080p24_16_9);
 	HDMI_SETUP_LUT(1920x1080p25_16_9);
 	HDMI_SETUP_LUT(1920x1080p30_16_9);
+	HDMI_SETUP_LUT(1280x1024p60_5_4);
 }
 
 #ifdef PORT_DEBUG
@@ -3618,36 +3619,35 @@
 	return 0;
 }
 
-
-static uint8 hdmi_msm_avi_iframe_lut[][16] = {
+static uint8 hdmi_msm_avi_iframe_lut[][17] = {
 /*	480p60	480i60	576p50	576i50	720p60	 720p50	1080p60	1080i60	1080p50
 	1080i50	1080p24	1080p30	1080p25	640x480p 480p60_16_9 576p50_4_3 */
 	{0x10,	0x10,	0x10,	0x10,	0x10,	 0x10,	0x10,	0x10,	0x10,
-	 0x10,	0x10,	0x10,	0x10,	0x10, 0x10, 0x10}, /*00*/
+	 0x10,	0x10,	0x10,	0x10,	0x10, 0x10, 0x10, 0x10}, /*00*/
 	{0x18,	0x18,	0x28,	0x28,	0x28,	 0x28,	0x28,	0x28,	0x28,
-	 0x28,	0x28,	0x28,	0x28,	0x18, 0x28, 0x18}, /*01*/
+	 0x28,	0x28,	0x28,	0x28,	0x18, 0x28, 0x18, 0x08}, /*01*/
 	{0x00,	0x04,	0x04,	0x04,	0x04,	 0x04,	0x04,	0x04,	0x04,
-	 0x04,	0x04,	0x04,	0x04,	0x88, 0x00, 0x04}, /*02*/
+	 0x04,	0x04,	0x04,	0x04,	0x88, 0x00, 0x04, 0x04}, /*02*/
 	{0x02,	0x06,	0x11,	0x15,	0x04,	 0x13,	0x10,	0x05,	0x1F,
-	 0x14,	0x20,	0x22,	0x21,	0x01, 0x03, 0x11}, /*03*/
+	 0x14,	0x20,	0x22,	0x21,	0x01, 0x03, 0x11, 0x00}, /*03*/
 	{0x00,	0x01,	0x00,	0x01,	0x00,	 0x00,	0x00,	0x00,	0x00,
-	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00}, /*04*/
+	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00, 0x00}, /*04*/
 	{0x00,	0x00,	0x00,	0x00,	0x00,	 0x00,	0x00,	0x00,	0x00,
-	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00}, /*05*/
+	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00, 0x00}, /*05*/
 	{0x00,	0x00,	0x00,	0x00,	0x00,	 0x00,	0x00,	0x00,	0x00,
-	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00}, /*06*/
+	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00, 0x00}, /*06*/
 	{0xE1,	0xE1,	0x41,	0x41,	0xD1,	 0xd1,	0x39,	0x39,	0x39,
-	 0x39,	0x39,	0x39,	0x39,	0xe1, 0xE1, 0x41}, /*07*/
+	 0x39,	0x39,	0x39,	0x39,	0xe1, 0xE1, 0x41, 0x01}, /*07*/
 	{0x01,	0x01,	0x02,	0x02,	0x02,	 0x02,	0x04,	0x04,	0x04,
-	 0x04,	0x04,	0x04,	0x04,	0x01, 0x01, 0x02}, /*08*/
+	 0x04,	0x04,	0x04,	0x04,	0x01, 0x01, 0x02, 0x04}, /*08*/
 	{0x00,	0x00,	0x00,	0x00,	0x00,	 0x00,	0x00,	0x00,	0x00,
-	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00}, /*09*/
+	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00, 0x00}, /*09*/
 	{0x00,	0x00,	0x00,	0x00,	0x00,	 0x00,	0x00,	0x00,	0x00,
-	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00}, /*10*/
+	 0x00,	0x00,	0x00,	0x00,	0x00, 0x00, 0x00, 0x00}, /*10*/
 	{0xD1,	0xD1,	0xD1,	0xD1,	0x01,	 0x01,	0x81,	0x81,	0x81,
-	 0x81,	0x81,	0x81,	0x81,	0x81, 0xD1, 0xD1}, /*11*/
+	 0x81,	0x81,	0x81,	0x81,	0x81, 0xD1, 0xD1, 0x01}, /*11*/
 	{0x02,	0x02,	0x02,	0x02,	0x05,	 0x05,	0x07,	0x07,	0x07,
-	 0x07,	0x07,	0x07,	0x07,	0x02, 0x02, 0x02}  /*12*/
+	 0x07,	0x07,	0x07,	0x07,	0x02, 0x02, 0x02, 0x05}  /*12*/
 };
 
 static void hdmi_msm_avi_info_frame(void)
@@ -3710,6 +3710,9 @@
 	case HDMI_VFRMT_720x576p50_4_3:
 		mode = 15;
 		break;
+	case HDMI_VFRMT_1280x1024p60_5_4:
+		mode = 16;
+		break;
 	default:
 		DEV_INFO("%s: mode %d not supported\n", __func__,
 			external_common_state->video_resolution);
@@ -4489,6 +4492,7 @@
 		cancel_work_sync(&hdmi_msm_state->hdcp_reauth_work);
 		cancel_work_sync(&hdmi_msm_state->hdcp_work);
 		del_timer_sync(&hdmi_msm_state->hdcp_timer);
+		hdmi_msm_state->reauth = FALSE;
 
 		hdcp_deauthenticate();
 	}
@@ -4539,10 +4543,26 @@
 			hdmi_msm_state->hdcp_enable ? "Enabled" : "Disabled");
 }
 
+static void hdmi_msm_update_panel_info(struct msm_fb_data_type *mfd)
+{
+	if (!mfd)
+		return;
+
+	if (hdmi_common_get_video_format_from_drv_data(mfd))
+		hdmi_common_init_panel_info(&mfd->panel_info);
+}
+
+static bool hdmi_msm_cable_connected(void)
+{
+	return hdmi_msm_state->hpd_initialized &&
+			external_common_state->hpd_state;
+}
+
 static int __devinit hdmi_msm_probe(struct platform_device *pdev)
 {
 	int rc;
 	struct platform_device *fb_dev;
+	struct msm_fb_data_type *mfd = NULL;
 
 	if (!hdmi_msm_state) {
 		pr_err("%s: hdmi_msm_state is NULL\n", __func__);
@@ -4664,6 +4684,10 @@
 	} else
 		DEV_ERR("Init FAILED: failed to add fb device\n");
 
+	mfd = platform_get_drvdata(fb_dev);
+	mfd->update_panel_info = hdmi_msm_update_panel_info;
+	mfd->is_panel_ready = hdmi_msm_cable_connected;
+
 	if (hdmi_prim_display) {
 		rc = hdmi_msm_hpd_on();
 		if (rc)
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index f461657..5070b03 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -51,6 +51,11 @@
 	int domain_idx;
 };
 
+struct mdss_hw_settings {
+	char __iomem *reg;
+	u32 val;
+};
+
 struct mdss_data_type {
 	u32 rev;
 	u32 mdp_rev;
@@ -78,16 +83,31 @@
 	u8 clk_ena;
 	u8 fs_ena;
 	u8 vsync_ena;
-	u8 eintf_ena;
 
-	u32 prim_ptype;
 	u32 res_init;
 	u32 bus_hdl;
 
 	u32 smp_mb_cnt;
 	u32 smp_mb_size;
-	u32 *pipe_type_map;
-	u32 *mixer_type_map;
+
+	struct mdss_hw_settings *hw_settings;
+
+	struct mdss_mdp_pipe *vig_pipes;
+	struct mdss_mdp_pipe *rgb_pipes;
+	struct mdss_mdp_pipe *dma_pipes;
+	u32 nvig_pipes;
+	u32 nrgb_pipes;
+	u32 ndma_pipes;
+	struct mdss_mdp_mixer *mixer_intf;
+	struct mdss_mdp_mixer *mixer_wb;
+	u32 nmixers_intf;
+	u32 nmixers_wb;
+	struct mdss_mdp_ctl *ctl_off;
+	u32 nctl;
+	struct mdss_mdp_dp_intf *dp_off;
+	u32 ndp;
+	void *video_intf;
+	u32 nintf;
 
 	struct ion_client *iclient;
 	int iommu_attached;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 18e88c8..54eaabb 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,8 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
 
@@ -24,47 +26,47 @@
 #include "mdss_panel.h"
 #include "mdss_dsi.h"
 
-static struct mdss_dsi_drv_pdata dsi_drv;
-
 static unsigned char *mdss_dsi_base;
 
-static int mdss_dsi_regulator_init(struct platform_device *pdev)
+static int mdss_dsi_regulator_init(struct platform_device *pdev,
+				   struct dsi_drv_cm_data *dsi_drv)
 {
 	int ret;
-	dsi_drv.vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
-	if (IS_ERR(dsi_drv.vdd_vreg)) {
+
+	dsi_drv->vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
+	if (IS_ERR(dsi_drv->vdd_vreg)) {
 		pr_err("could not get 8941_l22, rc = %ld\n",
-				PTR_ERR(dsi_drv.vdd_vreg));
+				PTR_ERR(dsi_drv->vdd_vreg));
 		return -ENODEV;
 	}
 
-	ret = regulator_set_voltage(dsi_drv.vdd_vreg, 3000000, 3000000);
+	ret = regulator_set_voltage(dsi_drv->vdd_vreg, 3000000, 3000000);
 	if (ret) {
 		pr_err("vdd_vreg->set_voltage failed, rc=%d\n", ret);
 		return -EINVAL;
 	}
 
-	dsi_drv.vdd_io_vreg = devm_regulator_get(&pdev->dev, "vdd_io");
-	if (IS_ERR(dsi_drv.vdd_io_vreg)) {
+	dsi_drv->vdd_io_vreg = devm_regulator_get(&pdev->dev, "vdd_io");
+	if (IS_ERR(dsi_drv->vdd_io_vreg)) {
 		pr_err("could not get 8941_l12, rc = %ld\n",
-				PTR_ERR(dsi_drv.vdd_io_vreg));
+				PTR_ERR(dsi_drv->vdd_io_vreg));
 		return -ENODEV;
 	}
 
-	ret = regulator_set_voltage(dsi_drv.vdd_io_vreg, 1800000, 1800000);
+	ret = regulator_set_voltage(dsi_drv->vdd_io_vreg, 1800000, 1800000);
 	if (ret) {
 		pr_err("vdd_io_vreg->set_voltage failed, rc=%d\n", ret);
 		return -EINVAL;
 	}
 
-	dsi_drv.dsi_vreg = devm_regulator_get(&pdev->dev, "vreg");
-	if (IS_ERR(dsi_drv.dsi_vreg)) {
+	dsi_drv->dsi_vreg = devm_regulator_get(&pdev->dev, "vreg");
+	if (IS_ERR(dsi_drv->dsi_vreg)) {
 		pr_err("could not get 8941_l2, rc = %ld\n",
-				PTR_ERR(dsi_drv.dsi_vreg));
+				PTR_ERR(dsi_drv->dsi_vreg));
 		return -ENODEV;
 	}
 
-	ret = regulator_set_voltage(dsi_drv.dsi_vreg, 1200000, 1200000);
+	ret = regulator_set_voltage(dsi_drv->dsi_vreg, 1200000, 1200000);
 	if (ret) {
 		pr_err("dsi_vreg->set_voltage failed, rc=%d\n", ret);
 		return -EINVAL;
@@ -73,34 +75,46 @@
 	return 0;
 }
 
-static int mdss_dsi_panel_power_on(int enable)
+static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata, int enable)
 {
 	int ret;
+	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);
 	pr_debug("%s: enable=%d\n", __func__, enable);
 
 	if (enable) {
-		ret = regulator_set_optimum_mode(dsi_drv.vdd_vreg, 100000);
+		ret = regulator_set_optimum_mode
+		  ((ctrl_pdata->shared_pdata).vdd_vreg, 100000);
 		if (ret < 0) {
 			pr_err("%s: vdd_vreg set regulator mode failed.\n",
 						       __func__);
 			return ret;
 		}
 
-		ret = regulator_set_optimum_mode(dsi_drv.vdd_io_vreg, 100000);
+		ret = regulator_set_optimum_mode
+		  ((ctrl_pdata->shared_pdata).vdd_io_vreg, 100000);
 		if (ret < 0) {
 			pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
 						       __func__);
 			return ret;
 		}
 
-		ret = regulator_set_optimum_mode(dsi_drv.dsi_vreg, 100000);
+		ret = regulator_set_optimum_mode
+		  ((ctrl_pdata->shared_pdata).dsi_vreg, 100000);
 		if (ret < 0) {
 			pr_err("%s: dsi_vreg set regulator mode failed.\n",
 						       __func__);
 			return ret;
 		}
 
-		ret = regulator_enable(dsi_drv.vdd_io_vreg);
+		ret = regulator_enable((ctrl_pdata->shared_pdata).vdd_io_vreg);
 		if (ret) {
 			pr_err("%s: Failed to enable regulator.\n", __func__);
 			return ret;
@@ -108,7 +122,7 @@
 		msleep(20);
 		wmb();
 
-		ret = regulator_enable(dsi_drv.vdd_vreg);
+		ret = regulator_enable((ctrl_pdata->shared_pdata).vdd_vreg);
 		if (ret) {
 			pr_err("%s: Failed to enable regulator.\n", __func__);
 			return ret;
@@ -116,50 +130,53 @@
 		msleep(20);
 		wmb();
 
-		ret = regulator_enable(dsi_drv.dsi_vreg);
+		ret = regulator_enable((ctrl_pdata->shared_pdata).dsi_vreg);
 		if (ret) {
 			pr_err("%s: Failed to enable regulator.\n", __func__);
 			return ret;
 		}
 
-		mdss_dsi_panel_reset(1);
+		mdss_dsi_panel_reset(pdata, 1);
 
 	} else {
 
-		mdss_dsi_panel_reset(0);
+		mdss_dsi_panel_reset(pdata, 0);
 
-		ret = regulator_disable(dsi_drv.vdd_vreg);
+		ret = regulator_disable((ctrl_pdata->shared_pdata).vdd_vreg);
 		if (ret) {
 			pr_err("%s: Failed to disable regulator.\n", __func__);
 			return ret;
 		}
 
-		ret = regulator_disable(dsi_drv.dsi_vreg);
+		ret = regulator_disable((ctrl_pdata->shared_pdata).dsi_vreg);
 		if (ret) {
 			pr_err("%s: Failed to disable regulator.\n", __func__);
 			return ret;
 		}
 
-		ret = regulator_disable(dsi_drv.vdd_io_vreg);
+		ret = regulator_disable((ctrl_pdata->shared_pdata).vdd_io_vreg);
 		if (ret) {
 			pr_err("%s: Failed to disable regulator.\n", __func__);
 			return ret;
 		}
 
-		ret = regulator_set_optimum_mode(dsi_drv.vdd_vreg, 100);
+		ret = regulator_set_optimum_mode
+		  ((ctrl_pdata->shared_pdata).vdd_vreg, 100);
 		if (ret < 0) {
 			pr_err("%s: vdd_vreg set regulator mode failed.\n",
 						       __func__);
 			return ret;
 		}
 
-		ret = regulator_set_optimum_mode(dsi_drv.vdd_io_vreg, 100);
+		ret = regulator_set_optimum_mode
+		  ((ctrl_pdata->shared_pdata).vdd_io_vreg, 100);
 		if (ret < 0) {
 			pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
 						       __func__);
 			return ret;
 		}
-		ret = regulator_set_optimum_mode(dsi_drv.dsi_vreg, 100);
+		ret = regulator_set_optimum_mode
+		  ((ctrl_pdata->shared_pdata).dsi_vreg, 100);
 		if (ret < 0) {
 			pr_err("%s: dsi_vreg set regulator mode failed.\n",
 						       __func__);
@@ -175,13 +192,13 @@
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 	int ret = 0;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	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);
 	pinfo = &pdata->panel_info;
 
 	mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
@@ -198,14 +215,22 @@
 static int mdss_dsi_off(struct mdss_panel_data *pdata)
 {
 	int ret = 0;
+	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);
 	mdss_dsi_clk_disable(pdata);
-	mdss_dsi_unprepare_clocks();
+	mdss_dsi_unprepare_clocks(ctrl_pdata);
 
 	/* disable DSI controller */
 	mdss_dsi_controller_cfg(0, pdata);
 
-	ret = mdss_dsi_panel_power_on(0);
+	ret = mdss_dsi_panel_power_on(pdata, 0);
 	if (ret) {
 		pr_err("%s: Panel power off failed\n", __func__);
 		return ret;
@@ -227,16 +252,16 @@
 	u32 dummy_xres, dummy_yres;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	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);
 	pinfo = &pdata->panel_info;
 
-	ret = mdss_dsi_panel_power_on(1);
+	ret = mdss_dsi_panel_power_on(pdata, 1);
 	if (ret) {
 		pr_err("%s: Panel power on failed\n", __func__);
 		return ret;
@@ -245,7 +270,7 @@
 	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
 	mdss_dsi_phy_init(pdata);
 
-	mdss_dsi_prepare_clocks();
+	mdss_dsi_prepare_clocks(ctrl_pdata);
 	mdss_dsi_clk_enable(pdata);
 
 	clk_rate = pdata->panel_info.clk_rate;
@@ -323,7 +348,7 @@
 
 	mdss_dsi_op_mode_config(mipi->mode, pdata);
 
-	pr_debug("%s-:\n", __func__);
+	pr_debug("%s-:End\n", __func__);
 	return ret;
 }
 
@@ -331,32 +356,84 @@
 				  int event, void *arg)
 {
 	int rc = 0;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	pr_debug("%s: event=%d\n", __func__, event);
+	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);
 	switch (event) {
 	case MDSS_EVENT_UNBLANK:
-		rc = mdss_dsi_on(pdata);
+		if (ctrl_pdata->on_cmds->ctrl_state == DSI_LP_MODE) {
+			rc = mdss_dsi_on(pdata);
+		} else {
+			pr_debug("%s:event=%d, Dsi On not called: ctrl_state: %d\n",
+				 __func__, event,
+				 ctrl_pdata->on_cmds->ctrl_state);
+			rc = -EINVAL;
+		}
 		break;
 	case MDSS_EVENT_BLANK:
-		rc = mdss_dsi_ctrl_unprepare(pdata);
+		if (ctrl_pdata->off_cmds->ctrl_state == DSI_HS_MODE) {
+			rc = mdss_dsi_ctrl_unprepare(pdata);
+		} else {
+			pr_debug("%s:event=%d,Unprepare not called.Ctrl_state: %d\n",
+				 __func__, event,
+				 ctrl_pdata->on_cmds->ctrl_state);
+			rc = -EINVAL;
+		}
 		break;
 	case MDSS_EVENT_TIMEGEN_OFF:
+		if (ctrl_pdata->off_cmds->ctrl_state == DSI_LP_MODE) {
+			pr_debug("%s:event=%d, calling unprepare: ctrl_state: %d\n",
+				 __func__, event,
+				 ctrl_pdata->on_cmds->ctrl_state);
+			rc = mdss_dsi_ctrl_unprepare(pdata);
+		}
 		rc = mdss_dsi_off(pdata);
 		break;
+	default:
+		pr_debug("%s: unhandled event=%d\n", __func__, event);
+		break;
 	}
 	return rc;
 }
 
-static int mdss_dsi_resource_initialized;
-
-static int __devinit mdss_dsi_probe(struct platform_device *pdev)
+static int __devinit mdss_dsi_ctrl_probe(struct platform_device *pdev)
 {
 	int rc = 0;
+	u32 index;
+
 	pr_debug("%s\n", __func__);
 
-	if (pdev->dev.of_node && !mdss_dsi_resource_initialized) {
+	if (pdev->dev.of_node) {
 		struct resource *mdss_dsi_mres;
-		pdev->id = 1;
+		const char *ctrl_name;
+
+		ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
+		if (!ctrl_name)
+			pr_info("%s:%d, DSI Ctrl name not specified\n",
+						__func__, __LINE__);
+		else
+			pr_info("%s: DSI Ctrl name = %s\n",
+				__func__, ctrl_name);
+
+		rc = of_property_read_u32(pdev->dev.of_node,
+					  "cell-index", &index);
+		if (rc) {
+			dev_err(&pdev->dev,
+				"%s: Cell-index not specified, rc=%d\n",
+							__func__, rc);
+			return rc;
+		}
+
+		if (index == 0)
+			pdev->id = 1;
+		else
+			pdev->id = 2;
+
 		mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 		if (!mdss_dsi_mres) {
 			pr_err("%s:%d unable to get the MDSS resources",
@@ -373,20 +450,6 @@
 			}
 		}
 
-		rc = mdss_dsi_regulator_init(pdev);
-		if (rc) {
-			dev_err(&pdev->dev,
-				"%s: failed to init regulator, rc=%d\n",
-							__func__, rc);
-			iounmap(mdss_dsi_base);
-			return rc;
-		}
-
-		if (mdss_dsi_clk_init(pdev)) {
-			iounmap(mdss_dsi_base);
-			return -EPERM;
-		}
-
 		rc = of_platform_populate(pdev->dev.of_node,
 					NULL, NULL, &pdev->dev);
 		if (rc) {
@@ -397,16 +460,13 @@
 			return rc;
 		}
 
-		mdss_dsi_resource_initialized = 1;
+		pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
 	}
 
-	if (!mdss_dsi_resource_initialized)
-		return -EPERM;
-
 	return 0;
 }
 
-static int __devexit mdss_dsi_remove(struct platform_device *pdev)
+static int __devexit mdss_dsi_ctrl_remove(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd;
 
@@ -417,6 +477,58 @@
 
 struct device dsi_dev;
 
+int mdss_dsi_retrieve_ctrl_resources(struct platform_device *pdev, int mode,
+			    unsigned char **ctrl_base)
+{
+	int rc = 0;
+	u32 index;
+	struct resource *mdss_dsi_mres;
+
+	rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &index);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: Cell-index not specified, rc=%d\n",
+						__func__, rc);
+		return rc;
+	}
+
+	if (index == 0) {
+		if (mode != DISPLAY_1) {
+			pr_err("%s:%d Panel->Ctrl mapping is wrong",
+				       __func__, __LINE__);
+			return -EPERM;
+		}
+	} else if (index == 1) {
+		if (mode != DISPLAY_2) {
+			pr_err("%s:%d Panel->Ctrl mapping is wrong",
+				       __func__, __LINE__);
+			return -EPERM;
+		}
+	} else {
+		pr_err("%s:%d Unknown Ctrl mapped to panel",
+			       __func__, __LINE__);
+		return -EPERM;
+	}
+
+	mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mdss_dsi_mres) {
+		pr_err("%s:%d unable to get the DSI ctrl resources",
+			       __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	*ctrl_base = ioremap(mdss_dsi_mres->start,
+		resource_size(mdss_dsi_mres));
+	if (!(*ctrl_base)) {
+		pr_err("%s:%d unable to remap dsi resources",
+			       __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+
 int dsi_panel_device_register(struct platform_device *pdev,
 			      struct mdss_panel_common_pdata *panel_data,
 			      char backlight_ctrl)
@@ -426,6 +538,10 @@
 	u8 lanes = 0, bpp;
 	u32 h_period, v_period, dsi_pclk_rate;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	struct device_node *dsi_ctrl_np = NULL;
+	struct platform_device *ctrl_pdev = NULL;
+	unsigned char *ctrl_addr;
+	bool broadcast;
 
 	h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
 			+ (panel_data->panel_info.lcdc.h_back_porch)
@@ -496,22 +612,107 @@
 	if (!ctrl_pdata)
 		return -ENOMEM;
 
+	dsi_ctrl_np = of_parse_phandle(pdev->dev.of_node,
+				       "qcom,dsi-ctrl-phandle", 0);
+	if (!dsi_ctrl_np) {
+		pr_err("%s: Dsi controller node not initialized\n", __func__);
+		devm_kfree(&pdev->dev, ctrl_pdata);
+		return -EPROBE_DEFER;
+	}
+
+	ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
+
+	rc = mdss_dsi_regulator_init(ctrl_pdev, &(ctrl_pdata->shared_pdata));
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: failed to init regulator, rc=%d\n",
+						__func__, rc);
+		devm_kfree(&pdev->dev, ctrl_pdata);
+		return rc;
+	}
+
+	broadcast = of_property_read_bool(pdev->dev.of_node,
+					  "qcom,mdss-pan-broadcast-mode");
+	if (broadcast)
+		ctrl_pdata->shared_pdata.broadcast_enable = 1;
+
+	ctrl_pdata->disp_en_gpio = of_get_named_gpio(pdev->dev.of_node,
+						     "qcom,enable-gpio", 0);
+	if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
+		pr_err("%s:%d, Disp_en gpio not specified\n",
+						__func__, __LINE__);
+	} else {
+		rc = gpio_request(ctrl_pdata->disp_en_gpio, "disp_enable");
+		if (rc) {
+			pr_err("request reset gpio failed, rc=%d\n",
+			       rc);
+			gpio_free(ctrl_pdata->disp_en_gpio);
+			return -ENODEV;
+		}
+		rc = gpio_direction_output(ctrl_pdata->disp_en_gpio, 1);
+		if (rc) {
+			pr_err("set_direction for disp_en gpio failed, rc=%d\n",
+			       rc);
+			gpio_free(ctrl_pdata->disp_en_gpio);
+			return -ENODEV;
+		}
+	}
+
+	ctrl_pdata->rst_gpio = of_get_named_gpio(pdev->dev.of_node,
+						 "qcom,rst-gpio", 0);
+	if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
+		pr_err("%s:%d, reset gpio not specified\n",
+						__func__, __LINE__);
+	} else {
+		rc = gpio_request(ctrl_pdata->rst_gpio, "disp_rst_n");
+		if (rc) {
+			pr_err("request reset gpio failed, rc=%d\n",
+				rc);
+			gpio_free(ctrl_pdata->rst_gpio);
+			gpio_free(ctrl_pdata->disp_en_gpio);
+			return -ENODEV;
+		}
+	}
+
+	if (mdss_dsi_clk_init(ctrl_pdev, ctrl_pdata)) {
+		pr_err("%s: unable to initialize Dsi ctrl clks\n", __func__);
+		devm_kfree(&pdev->dev, ctrl_pdata);
+		return -EPERM;
+	}
+
+	if (mdss_dsi_retrieve_ctrl_resources(ctrl_pdev,
+					     panel_data->panel_info.pdest,
+					     &ctrl_addr)) {
+		pr_err("%s: unable to get Dsi controller res\n", __func__);
+		devm_kfree(&pdev->dev, ctrl_pdata);
+		return -EPERM;
+	}
+
+	pr_debug("%s: ctrl base address: 0x%x\n", __func__, (int)ctrl_addr);
 	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;
+
 	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->ctrl_base) = mdss_dsi_base;
+	(ctrl_pdata->ctrl_base) = ctrl_addr;
 	(ctrl_pdata->bl_ctrl) = backlight_ctrl;
 	/*
 	 * register in mdp driver
 	 */
-	rc = mdss_register_panel(&(ctrl_pdata->panel_data));
+	rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
 	if (rc) {
 		dev_err(&pdev->dev, "unable to register MIPI DSI panel\n");
 		devm_kfree(&pdev->dev, ctrl_pdata);
+		if (ctrl_pdata->rst_gpio)
+			gpio_free(ctrl_pdata->rst_gpio);
+		if (ctrl_pdata->disp_en_gpio)
+			gpio_free(ctrl_pdata->disp_en_gpio);
 		return rc;
 	}
 
@@ -522,25 +723,25 @@
 	return 0;
 }
 
-static const struct of_device_id msm_mdss_dsi_dt_match[] = {
-	{.compatible = "qcom,msm-mdss-dsi"},
+static const struct of_device_id mdss_dsi_ctrl_dt_match[] = {
+	{.compatible = "qcom,mdss-dsi-ctrl"},
 	{}
 };
-MODULE_DEVICE_TABLE(of, msm_mdss_dsi_dt_match);
+MODULE_DEVICE_TABLE(of, mdss_dsi_ctrl_dt_match);
 
-static struct platform_driver mdss_dsi_driver = {
-	.probe = mdss_dsi_probe,
-	.remove = __devexit_p(mdss_dsi_remove),
+static struct platform_driver mdss_dsi_ctrl_driver = {
+	.probe = mdss_dsi_ctrl_probe,
+	.remove = __devexit_p(mdss_dsi_ctrl_remove),
 	.shutdown = NULL,
 	.driver = {
-		.name = "mdss_dsi",
-		.of_match_table = msm_mdss_dsi_dt_match,
+		.name = "mdss_dsi_ctrl",
+		.of_match_table = mdss_dsi_ctrl_dt_match,
 	},
 };
 
 static int mdss_dsi_register_driver(void)
 {
-	return platform_driver_register(&mdss_dsi_driver);
+	return platform_driver_register(&mdss_dsi_ctrl_driver);
 }
 
 static int __init mdss_dsi_driver_init(void)
@@ -562,7 +763,7 @@
 static void __exit mdss_dsi_driver_cleanup(void)
 {
 	iounmap(mdss_dsi_base);
-	platform_driver_unregister(&mdss_dsi_driver);
+	platform_driver_unregister(&mdss_dsi_ctrl_driver);
 }
 module_exit(mdss_dsi_driver_cleanup);
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index dab38bc..06c2952 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -83,6 +83,11 @@
 	UNKNOWN_CTRL,
 };
 
+enum dsi_ctrl_state {
+	DSI_LP_MODE,
+	DSI_HS_MODE,
+};
+
 #define DSI_NON_BURST_SYNCH_PULSE	0
 #define DSI_NON_BURST_SYNCH_EVENT	1
 #define DSI_BURST_MODE			2
@@ -244,17 +249,26 @@
 	void *data;
 };
 
+struct dsi_panel_cmds_list {
+	struct dsi_cmd_desc *buf;
+	char 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 mdss_dsi_drv_pdata {
+struct dsi_drv_cm_data {
 	struct regulator *vdd_vreg;
 	struct regulator *vdd_io_vreg;
 	struct regulator *dsi_vreg;
+	int broadcast_enable;
 };
 
 struct mdss_dsi_ctrl_pdata {
@@ -263,6 +277,15 @@
 	struct mdss_panel_data panel_data;
 	unsigned char *ctrl_base;
 	char bl_ctrl;
+	struct clk *byte_clk;
+	struct clk *esc_clk;
+	struct clk *pixel_clk;
+	int mdss_dsi_clk_on;
+	int rst_gpio;
+	int disp_en_gpio;
+	struct dsi_panel_cmds_list *on_cmds;
+	struct dsi_panel_cmds_list *off_cmds;
+	struct dsi_drv_cm_data shared_pdata;
 };
 
 int dsi_panel_device_register(struct platform_device *pdev,
@@ -292,7 +315,7 @@
 				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(void);
+void mdss_dsi_cmd_mdp_start(struct mdss_panel_data *pdata);
 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);
@@ -307,11 +330,12 @@
 void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata);
 int mdss_dsi_clk_div_config(u8 bpp, u8 lanes,
 			    u32 *expected_dsi_pclk);
-int mdss_dsi_clk_init(struct platform_device *pdev);
-void mdss_dsi_clk_deinit(struct device *dev);
-void mdss_dsi_prepare_clocks(void);
-void mdss_dsi_unprepare_clocks(void);
-void mdss_dsi_panel_reset(int enable);
+int mdss_dsi_clk_init(struct platform_device *pdev,
+		      struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+void mdss_dsi_clk_deinit(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+void mdss_dsi_prepare_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+void mdss_dsi_unprepare_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable);
 void mdss_dsi_phy_enable(unsigned char *ctrl_base, int on);
 void mdss_dsi_phy_init(struct mdss_panel_data *pdata);
 void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index a8fcffe..6f7023c 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -1,5 +1,4 @@
-
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -31,13 +30,20 @@
 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;
 
-struct mdss_hw mdss_dsi_hw = {
+struct mdss_hw mdss_dsi0_hw = {
 	.hw_ndx = MDSS_HW_DSI0,
 	.ptr = NULL,
 	.irq_handler = mdss_dsi_isr,
 };
 
+struct mdss_hw mdss_dsi1_hw = {
+	.hw_ndx = MDSS_HW_DSI1,
+	.ptr = NULL,
+	.irq_handler = mdss_dsi_isr,
+};
+
 void mdss_dsi_init(void)
 {
 	init_completion(&dsi_dma_comp);
@@ -47,12 +53,24 @@
 
 void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
-	mdss_dsi_hw.ptr = (void *)(ctrl_pdata);
+	if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1)
+		mdss_dsi0_hw.ptr = (void *)(ctrl_pdata);
+	else
+		mdss_dsi1_hw.ptr = (void *)(ctrl_pdata);
 }
 
-void mdss_dsi_enable_irq(void)
+void mdss_dsi_enable_irq(struct mdss_panel_data *pdata)
 {
 	unsigned long flags;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
 
 	spin_lock_irqsave(&dsi_irq_lock, flags);
 	if (dsi_irq_enabled) {
@@ -61,15 +79,28 @@
 		return;
 	}
 
-	mdss_enable_irq(&mdss_dsi_hw);
+	if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
+		mdss_enable_irq(&mdss_dsi0_hw);
+	else
+		mdss_enable_irq(&mdss_dsi1_hw);
+
 	dsi_irq_enabled = 1;
 	/* TO DO: Check whether MDSS IRQ is enabled */
 	spin_unlock_irqrestore(&dsi_irq_lock, flags);
 }
 
-void mdss_dsi_disable_irq(void)
+void mdss_dsi_disable_irq(struct mdss_panel_data *pdata)
 {
 	unsigned long flags;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
 
 	spin_lock_irqsave(&dsi_irq_lock, flags);
 	if (dsi_irq_enabled == 0) {
@@ -77,7 +108,11 @@
 		spin_unlock_irqrestore(&dsi_irq_lock, flags);
 		return;
 	}
-	mdss_disable_irq(&mdss_dsi_hw);
+	if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1)
+		mdss_disable_irq(&mdss_dsi0_hw);
+	else
+		mdss_disable_irq(&mdss_dsi1_hw);
+
 	dsi_irq_enabled = 0;
 	/* TO DO: Check whether MDSS IRQ is Disabled */
 	spin_unlock_irqrestore(&dsi_irq_lock, flags);
@@ -661,13 +696,14 @@
 	u32 data;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
 	}
 
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
 	pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
 
 	if (pinfo->mode == DSI_VIDEO_MODE) {
@@ -740,7 +776,17 @@
 
 	/* from frame buffer, low power mode */
 	/* DSI_COMMAND_MODE_DMA_CTRL */
-	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x3C, 0x14000000);
+	if (ctrl_pdata->shared_pdata.broadcast_enable)
+		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x94000000);
+	else
+		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x14000000);
+
+	if (ctrl_pdata->shared_pdata.broadcast_enable)
+		if (pdata->panel_info.pdest == DISPLAY_1) {
+			pr_debug("%s: Broadcast mode enabled.\n",
+				 __func__);
+			left_ctrl_pdata = ctrl_pdata;
+		}
 
 	data = 0;
 	if (pinfo->te_sel)
@@ -793,13 +839,14 @@
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 	u32 data;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
 	}
 
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
 	data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x3c);
 
 	if (mode == 0)
@@ -815,13 +862,13 @@
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 	u32 dsi_ctrl;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
 	}
 
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
 	dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
 	dsi_ctrl &= ~0x01;
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
@@ -848,13 +895,14 @@
 	u32 timeout_us = 16000;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
 	}
 
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
 	/* Check for CMD_MODE_DMA_BUSY */
 	if (readl_poll_timeout(((ctrl_pdata->ctrl_base) + 0x0008),
 			   status,
@@ -895,13 +943,21 @@
 	u32 dsi_ctrl, intr_ctrl;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
 	}
 
+	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) {
+			pr_debug("%s: Broadcast mode. 1st ctrl\n",
+				 __func__);
+			return;
+		}
+
 	dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
 	/*If Video enabled, Keep Video and Cmd mode ON */
 	if (dsi_ctrl & 0x02)
@@ -923,18 +979,27 @@
 
 	pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
 
+	if (ctrl_pdata->shared_pdata.broadcast_enable)
+		if ((pdata->panel_info.pdest == DISPLAY_2)
+		  && (left_ctrl_pdata != NULL)) {
+			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110,
+				  intr_ctrl); /* DSI_INTL_CTRL */
+			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+					dsi_ctrl);
+		}
+
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110,
 				intr_ctrl); /* DSI_INTL_CTRL */
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
 	wmb();
 }
 
-void mdss_dsi_cmd_mdp_start(void)
+void mdss_dsi_cmd_mdp_start(struct mdss_panel_data *pdata)
 {
 	unsigned long flag;
 
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	mdss_dsi_enable_irq();
+	mdss_dsi_enable_irq(pdata);
 	dsi_mdp_busy = true;
 	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
 }
@@ -946,13 +1011,14 @@
 	int timeout_us = 10000;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
 	}
 
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x098, 0x01);	/* trigger */
 	wmb();
 
@@ -1008,18 +1074,40 @@
 	unsigned long flag;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	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) {
+			pr_debug("%s: Broadcast mode. 1st ctrl\n",
+				 __func__);
+			return 0;
+		}
+
 	/* 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);
 	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
 	if (video_mode) {
@@ -1028,7 +1116,8 @@
 	}
 
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	mdss_dsi_enable_irq();
+	mdss_dsi_enable_irq(pdata);
+
 	dsi_mdp_busy = true;
 	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
 
@@ -1045,7 +1134,7 @@
 
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
 	dsi_mdp_busy = false;
-	mdss_dsi_disable_irq();
+	mdss_dsi_disable_irq(pdata);
 	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
 
 	if (video_mode)
@@ -1083,13 +1172,14 @@
 	char cmd;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	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)
 		rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
 
@@ -1116,7 +1206,7 @@
 	}
 
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	mdss_dsi_enable_irq();
+	mdss_dsi_enable_irq(pdata);
 	dsi_mdp_busy = true;
 	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
 
@@ -1153,7 +1243,7 @@
 
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
 	dsi_mdp_busy = false;
-	mdss_dsi_disable_irq();
+	mdss_dsi_disable_irq(pdata);
 	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
 
 	if (pdata->panel_info.mipi.no_max_pkt_size) {
@@ -1204,13 +1294,13 @@
 	unsigned long size, addr;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	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;
 
 	pr_debug("%s: ", __func__);
@@ -1242,10 +1332,23 @@
 
 	INIT_COMPLETION(dsi_dma_comp);
 
+	if (ctrl_pdata->shared_pdata.broadcast_enable)
+		if ((pdata->panel_info.pdest == DISPLAY_2)
+		  && (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);
 	wmb();
 
+	if (ctrl_pdata->shared_pdata.broadcast_enable)
+		if ((pdata->panel_info.pdest == DISPLAY_2)
+		  && (left_ctrl_pdata != NULL)) {
+			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x090, 0x01);
+		}
+
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x090, 0x01);	/* trigger */
 	wmb();
 
@@ -1267,13 +1370,13 @@
 	int i, off, cnt;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	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;
@@ -1383,6 +1486,15 @@
 	isr = MIPI_INP(dsi_base + 0x0110);/* DSI_INTR_CTRL */
 	MIPI_OUTP(dsi_base + 0x0110, isr);
 
+	if (ctrl_pdata->shared_pdata.broadcast_enable)
+		if ((ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_2)
+		    && (left_ctrl_pdata != NULL)) {
+			u32 isr0;
+			isr0 = MIPI_INP(left_ctrl_pdata->ctrl_base
+						+ 0x0110);/* DSI_INTR_CTRL */
+			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, isr0);
+		}
+
 	if (isr & DSI_INTR_ERROR)
 		mdss_dsi_error(dsi_base);
 
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index b3c3652..4c30d18 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,9 +13,8 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/gpio.h>
 #include <linux/qpnp/pin.h>
+#include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/leds.h>
@@ -27,46 +26,51 @@
 static struct dsi_buf dsi_panel_tx_buf;
 static struct dsi_buf dsi_panel_rx_buf;
 
-static struct dsi_cmd_desc *dsi_panel_on_cmds;
-static struct dsi_cmd_desc *dsi_panel_off_cmds;
-static int num_of_on_cmds;
-static int num_of_off_cmds;
-static char *on_cmds, *off_cmds;
-
 DEFINE_LED_TRIGGER(bl_led_trigger);
 
 static struct mdss_dsi_phy_ctrl phy_params;
 
-static int rst_gpio;
-static int disp_en;
-
-void mdss_dsi_panel_reset(int enable)
+void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
 {
-	if (!disp_en)
-		pr_debug("%s:%d, reset line not configured\n",
-			   __func__, __LINE__);
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	if (!rst_gpio)
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
+	if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
 		pr_debug("%s:%d, reset line not configured\n",
 			   __func__, __LINE__);
+		return;
+	}
+
+	if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
+		pr_debug("%s:%d, reset line not configured\n",
+			   __func__, __LINE__);
+		return;
+	}
 
 	pr_debug("%s: enable = %d\n", __func__, enable);
 
 	if (enable) {
-		gpio_set_value(rst_gpio, 1);
+		gpio_set_value((ctrl_pdata->rst_gpio), 1);
 		msleep(20);
 		wmb();
-		gpio_set_value(rst_gpio, 0);
+		gpio_set_value((ctrl_pdata->rst_gpio), 0);
 		udelay(200);
 		wmb();
-		gpio_set_value(rst_gpio, 1);
+		gpio_set_value((ctrl_pdata->rst_gpio), 1);
 		msleep(20);
 		wmb();
-		gpio_set_value(disp_en, 1);
+		gpio_set_value((ctrl_pdata->disp_en_gpio), 1);
 		wmb();
 	} else {
-		gpio_set_value(rst_gpio, 0);
-		gpio_set_value(disp_en, 0);
+		gpio_set_value((ctrl_pdata->rst_gpio), 0);
+		gpio_set_value((ctrl_pdata->disp_en_gpio), 0);
 	}
 }
 
@@ -75,13 +79,14 @@
 {
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-	if (!ctrl_pdata) {
+	if (pdata == NULL) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
 	}
 
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
 	if (ctrl_pdata->bl_ctrl) {
 		switch (ctrl_pdata->bl_ctrl) {
 		case BL_WLED:
@@ -100,15 +105,24 @@
 static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
 {
 	struct mipi_panel_info *mipi;
+	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);
 	mipi  = &pdata->panel_info.mipi;
 
 	pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
 		 mipi->mode);
 
 	if (mipi->mode == DSI_VIDEO_MODE) {
-		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_on_cmds,
-			num_of_on_cmds);
+		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
+				 ctrl_pdata->on_cmds->buf,
+				 ctrl_pdata->on_cmds->size);
 	} else {
 		pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
 		return -EINVAL;
@@ -120,14 +134,23 @@
 static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)
 {
 	struct mipi_panel_info *mipi;
+	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);
 	mipi  = &pdata->panel_info.mipi;
 
 	pr_debug("%s:%d, debug info\n", __func__, __LINE__);
 
 	if (mipi->mode == DSI_VIDEO_MODE) {
-		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_off_cmds,
-			num_of_off_cmds);
+		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
+				 ctrl_pdata->off_cmds->buf,
+				 ctrl_pdata->off_cmds->size);
 	} else {
 		pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
 		return -EINVAL;
@@ -145,7 +168,10 @@
 	int rc, i, len;
 	int cmd_plen, data_offset;
 	const char *data;
-	static const char *bl_ctrl_type;
+	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;
 
 	rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
 	if (rc) {
@@ -164,43 +190,6 @@
 			panel_data->panel_info.yres - res[1];
 	}
 
-	disp_en = of_get_named_gpio(np, "qcom,enable-gpio", 0);
-	if (!gpio_is_valid(disp_en)) {
-		pr_err("%s:%d, Disp_en gpio not specified\n",
-						__func__, __LINE__);
-		return -ENODEV;
-	}
-
-	rc = gpio_request(disp_en, "disp_enable");
-	if (rc) {
-		pr_err("request reset gpio failed, rc=%d\n",
-			rc);
-		gpio_free(disp_en);
-		return -ENODEV;
-	}
-	rc = gpio_direction_output(disp_en, 1);
-	if (rc) {
-		pr_err("set_direction for disp_en gpio failed, rc=%d\n",
-			rc);
-		gpio_free(disp_en);
-		return -ENODEV;
-	}
-
-	rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
-	if (!gpio_is_valid(rst_gpio)) {
-		pr_err("%s:%d, reset gpio not specified\n",
-						__func__, __LINE__);
-	} else {
-		rc = gpio_request(rst_gpio, "disp_rst_n");
-		if (rc) {
-			pr_err("request reset gpio failed, rc=%d\n",
-				rc);
-			gpio_free(rst_gpio);
-			gpio_free(disp_en);
-			return -ENODEV;
-		}
-	}
-
 	rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
 	if (rc) {
 		pr_err("%s:%d, panel bpp not specified\n",
@@ -209,6 +198,22 @@
 	}
 	panel_data->panel_info.bpp = (!rc ? tmp : 24);
 
+	pdest = of_get_property(pdev->dev.of_node,
+				"qcom,mdss-pan-dest", NULL);
+	if (strlen(pdest) != 9) {
+		pr_err("%s: Unknown pdest specified\n", __func__);
+		return -EINVAL;
+	}
+	if (!strncmp(pdest, "display_1", 9))
+		panel_data->panel_info.pdest = DISPLAY_1;
+	else if (!strncmp(pdest, "display_2", 9))
+		panel_data->panel_info.pdest = DISPLAY_2;
+	else {
+		pr_debug("%s: pdest not specified. Set Default\n",
+							__func__);
+		panel_data->panel_info.pdest = DISPLAY_1;
+	}
+
 	rc = of_property_read_u32_array(np,
 		"qcom,mdss-pan-porch-values", res, 6);
 	panel_data->panel_info.lcdc.h_back_porch = (!rc ? res[0] : 6);
@@ -224,7 +229,7 @@
 
 	bl_ctrl_type = of_get_property(pdev->dev.of_node,
 				  "qcom,mdss-pan-bl-ctrl", NULL);
-	if (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12)) {
+	if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12))) {
 		led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
 		pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
 		*bl_ctrl = BL_WLED;
@@ -278,6 +283,9 @@
 	panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
 	panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
 
+	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
+	panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
+
 	rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
 	panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
 	panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
@@ -380,22 +388,34 @@
 		goto error;
 	}
 
-	dsi_panel_on_cmds =
+	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 (!dsi_panel_on_cmds)
+	if (!(panel_data->dsi_panel_on_cmds)->buf)
 		return -ENOMEM;
 
 	data_offset = 0;
 	for (i = 0; i < num_of_on_cmds; i++) {
-		dsi_panel_on_cmds[i].dtype = on_cmds[data_offset++];
-		dsi_panel_on_cmds[i].last = on_cmds[data_offset++];
-		dsi_panel_on_cmds[i].vc = on_cmds[data_offset++];
-		dsi_panel_on_cmds[i].ack = on_cmds[data_offset++];
-		dsi_panel_on_cmds[i].wait = on_cmds[data_offset++];
-		dsi_panel_on_cmds[i].dlen = on_cmds[data_offset++];
-		dsi_panel_on_cmds[i].payload = &on_cmds[data_offset];
-		data_offset += (dsi_panel_on_cmds[i].dlen);
+		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) {
@@ -404,6 +424,23 @@
 		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__);
@@ -429,22 +466,34 @@
 		goto error;
 	}
 
-	dsi_panel_off_cmds = kzalloc(num_of_off_cmds
+	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 (!dsi_panel_off_cmds)
+	if (!(panel_data->dsi_panel_off_cmds)->buf)
 		return -ENOMEM;
 
 	data_offset = 0;
 	for (i = 0; i < num_of_off_cmds; i++) {
-		dsi_panel_off_cmds[i].dtype = off_cmds[data_offset++];
-		dsi_panel_off_cmds[i].last = off_cmds[data_offset++];
-		dsi_panel_off_cmds[i].vc = off_cmds[data_offset++];
-		dsi_panel_off_cmds[i].ack = off_cmds[data_offset++];
-		dsi_panel_off_cmds[i].wait = off_cmds[data_offset++];
-		dsi_panel_off_cmds[i].dlen = off_cmds[data_offset++];
-		dsi_panel_off_cmds[i].payload = &off_cmds[data_offset];
-		data_offset += (dsi_panel_off_cmds[i].dlen);
+		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) {
@@ -453,16 +502,31 @@
 		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;
+	}
+
 	return 0;
 error:
-	kfree(dsi_panel_on_cmds);
-	kfree(dsi_panel_off_cmds);
+	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);
-	if (rst_gpio)
-		gpio_free(rst_gpio);
-	if (disp_en)
-		gpio_free(disp_en);
 
 	return -EINVAL;
 }
@@ -474,11 +538,6 @@
 	static const char *panel_name;
 	char bl_ctrl = UNKNOWN_CTRL;
 
-	if (pdev->dev.parent == NULL) {
-		pr_err("%s: parent device missing\n", __func__);
-		return -ENODEV;
-	}
-
 	pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
 	if (!pdev->dev.of_node)
 		return -ENODEV;
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index 227619f..6986117 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -433,7 +433,7 @@
 	edp_drv->panel_data.event_handler = mdss_edp_event_handler;
 	edp_drv->panel_data.set_backlight = mdss_edp_set_backlight;
 
-	ret = mdss_register_panel(&edp_drv->panel_data);
+	ret = mdss_register_panel(edp_drv->pdev, &edp_drv->panel_data);
 	if (ret) {
 		dev_err(&(edp_drv->pdev->dev), "unable to register eDP\n");
 		return ret;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index a283e0a..00a8aa5 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -87,7 +87,8 @@
 
 static void mdss_fb_commit_wq_handler(struct work_struct *work);
 static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd);
-
+static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd,
+					int event, void *arg);
 void mdss_fb_no_update_notify_timer_cb(unsigned long data)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
@@ -232,7 +233,7 @@
 
 	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata)
-		return -ENODEV;
+		return -EPROBE_DEFER;
 
 	/*
 	 * alloc framebuffer info + par data
@@ -259,6 +260,8 @@
 	mfd->fb_imgType = MDP_RGBA_8888;
 
 	mfd->pdev = pdev;
+	if (pdata->next)
+		mfd->split_display = true;
 
 	mutex_init(&mfd->lock);
 
@@ -284,6 +287,7 @@
 	}
 
 	mdss_fb_create_sysfs(mfd);
+	mdss_fb_send_panel_event(mfd, MDSS_EVENT_FB_REGISTERED, fbi);
 
 	if (mfd->timeline == NULL) {
 		char timeline_name[16];
@@ -298,6 +302,10 @@
 		}
 	}
 
+	rc = mdss_mdp_overlay_init(mfd);
+	if (rc)
+		pr_err("unable to init overlay\n");
+
 	return 0;
 }
 
@@ -332,8 +340,8 @@
 	return 0;
 }
 
-static inline int mdss_fb_send_panel_event(
-	struct msm_fb_data_type *mfd, int e, void *arg)
+static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd,
+					int event, void *arg)
 {
 	struct mdss_panel_data *pdata;
 
@@ -343,10 +351,10 @@
 		return -ENODEV;
 	}
 
-	pr_debug("sending event=%d for fb%d\n", e, mfd->index);
+	pr_debug("sending event=%d for fb%d\n", event, mfd->index);
 
 	if (pdata->event_handler)
-		return pdata->event_handler(pdata, e, arg);
+		return pdata->event_handler(pdata, event, arg);
 
 	return 0;
 }
@@ -453,11 +461,18 @@
 	return result;
 }
 
+static const struct of_device_id mdss_fb_dt_match[] = {
+	{ .compatible = "qcom,mdss-fb",},
+	{}
+};
+EXPORT_COMPAT("qcom,mdss-fb");
+
 static struct platform_driver mdss_fb_driver = {
 	.probe = mdss_fb_probe,
 	.remove = mdss_fb_remove,
 	.driver = {
 		.name = "mdss_fb",
+		.of_match_table = mdss_fb_dt_match,
 	},
 };
 
@@ -872,13 +887,15 @@
 		return ret;
 	}
 
-	fix->type = panel_info->is_3d_panel;
-	fix->line_length = mdss_fb_line_length(mfd->index, panel_info->xres,
-					       bpp);
-
 	var->xres = panel_info->xres;
+	if (mfd->split_display)
+		var->xres *= 2;
+
+	fix->type = panel_info->is_3d_panel;
+	fix->line_length = mdss_fb_line_length(mfd->index, var->xres, bpp);
+
 	var->yres = panel_info->yres;
-	var->xres_virtual = panel_info->xres;
+	var->xres_virtual = var->xres;
 	var->yres_virtual = panel_info->yres * mfd->fb_page;
 	var->bits_per_pixel = bpp * 8;	/* FrameBuffer color depth */
 	var->upper_margin = panel_info->lcdc.v_back_porch;
@@ -899,7 +916,6 @@
 	fbi->flags = FBINFO_FLAG_DEFAULT;
 	fbi->pseudo_palette = mdss_fb_pseudo_palette;
 
-	panel_info->fbi = fbi;
 	mfd->ref_cnt = 0;
 	mfd->panel_power_on = false;
 
@@ -1035,15 +1051,20 @@
 	mfd->acq_fen_cnt = 0;
 }
 
-void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd)
+static void mdss_fb_signal_timeline_locked(struct msm_fb_data_type *mfd)
 {
-	mutex_lock(&mfd->sync_mutex);
 	if (mfd->timeline) {
 		sw_sync_timeline_inc(mfd->timeline, 1);
 		mfd->timeline_value++;
 	}
 	mfd->last_rel_fence = mfd->cur_rel_fence;
 	mfd->cur_rel_fence = 0;
+}
+
+void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd)
+{
+	mutex_lock(&mfd->sync_mutex);
+	mdss_fb_signal_timeline_locked(mfd);
 	mutex_unlock(&mfd->sync_mutex);
 }
 
@@ -1074,6 +1095,7 @@
 				__func__, ret, mfd->is_committing);
 		if (ret <= 0) {
 			mutex_lock(&mfd->sync_mutex);
+			mdss_fb_signal_timeline_locked(mfd);
 			mfd->is_committing = 0;
 			complete_all(&mfd->commit_comp);
 			mutex_unlock(&mfd->sync_mutex);
@@ -1722,44 +1744,73 @@
 }
 EXPORT_SYMBOL(msm_fb_get_writeback_fb);
 
-int mdss_register_panel(struct mdss_panel_data *pdata)
+static int mdss_fb_register_extra_panel(struct platform_device *pdev,
+	struct mdss_panel_data *pdata)
 {
-	struct platform_device *mdss_fb_dev = NULL;
-	struct msm_fb_data_type *mfd;
-	int rc;
+	struct mdss_panel_data *fb_pdata;
 
-	if (!mdss_res) {
-		pr_err("mdss mdp resources not initialized yet\n");
-		return -ENODEV;
-	}
-
-	mdss_fb_dev = platform_device_alloc("mdss_fb", pdata->panel_info.pdest);
-	if (!mdss_fb_dev) {
-		pr_err("unable to allocate mdss_fb device\n");
-		return -ENOMEM;
-	}
-
-	mdss_fb_dev->dev.platform_data = pdata;
-
-	rc = platform_device_add(mdss_fb_dev);
-	if (rc) {
-		platform_device_put(mdss_fb_dev);
-		pr_err("unable to probe mdss_fb device (%d)\n", rc);
-		return rc;
-	}
-
-	mfd = platform_get_drvdata(mdss_fb_dev);
-	if (!mfd)
-		return -ENODEV;
-	if (mfd->key != MFD_KEY)
+	fb_pdata = dev_get_platdata(&pdev->dev);
+	if (!fb_pdata) {
+		pr_err("framebuffer device %s contains invalid panel data\n",
+				dev_name(&pdev->dev));
 		return -EINVAL;
+	}
 
-	mfd->on_fnc = mdss_mdp_ctl_on;
-	mfd->off_fnc = mdss_mdp_ctl_off;
+	if (fb_pdata->next) {
+		pr_err("split panel already setup for framebuffer device %s\n",
+				dev_name(&pdev->dev));
+		return -EEXIST;
+	}
 
-	rc = mdss_mdp_overlay_init(mfd);
-	if (rc)
-		pr_err("unable to init overlay\n");
+	if ((fb_pdata->panel_info.type != MIPI_VIDEO_PANEL) ||
+			(pdata->panel_info.type != MIPI_VIDEO_PANEL)) {
+		pr_err("Split panel not supported for panel type %d\n",
+				pdata->panel_info.type);
+		return -EINVAL;
+	}
+
+	fb_pdata->next = pdata;
+
+	return 0;
+}
+
+int mdss_register_panel(struct platform_device *pdev,
+	struct mdss_panel_data *pdata)
+{
+	struct platform_device *fb_pdev, *mdss_pdev;
+	struct device_node *node;
+	int rc = 0;
+
+	if (!pdev || !pdev->dev.of_node) {
+		pr_err("Invalid device node\n");
+		return -ENODEV;
+	}
+
+	node = of_parse_phandle(pdev->dev.of_node, "qcom,mdss-fb-map", 0);
+	if (!node) {
+		pr_err("Unable to find fb node for device: %s\n",
+				pdev->name);
+		return -ENODEV;
+	}
+	mdss_pdev = of_find_device_by_node(node->parent);
+	if (!mdss_pdev) {
+		pr_err("Unable to find mdss for node: %s\n", node->full_name);
+		rc = -ENODEV;
+		goto mdss_notfound;
+	}
+
+	fb_pdev = of_find_device_by_node(node);
+	if (fb_pdev) {
+		rc = mdss_fb_register_extra_panel(fb_pdev, pdata);
+	} else {
+		pr_info("adding framebuffer device %s\n", dev_name(&pdev->dev));
+		fb_pdev = of_platform_device_create(node, NULL,
+				&mdss_pdev->dev);
+		fb_pdev->dev.platform_data = pdata;
+	}
+
+mdss_notfound:
+	of_node_put(node);
 
 	return rc;
 }
@@ -1801,4 +1852,4 @@
 	return 0;
 }
 
-module_init(mdss_fb_init);
+device_initcall_sync(mdss_fb_init);
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index a3b1ac3..193b6b7 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -60,6 +60,7 @@
 
 	struct panel_id panel;
 	struct mdss_panel_info *panel_info;
+	int split_display;
 
 	u32 dest;
 	struct fb_info *fbi;
@@ -109,6 +110,7 @@
 
 	u32 mdp_fb_page_protection;
 
+	struct mdss_data_type *mdata;
 	struct mdss_mdp_ctl *ctl;
 	struct mdss_mdp_wb *wb;
 	struct list_head overlay_list;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 6140b6a..b6dec99 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -34,7 +34,7 @@
 #define DRV_NAME "hdmi-tx"
 #define COMPATIBLE_NAME "qcom,hdmi-tx"
 
-#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_1920x1080p60_16_9
+#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3
 
 /* HDMI PHY/PLL bit field macros */
 #define SW_RESET BIT(2)
@@ -406,24 +406,23 @@
 	.attrs = hdmi_tx_fs_attrs,
 };
 
-static int hdmi_tx_sysfs_create(struct hdmi_tx_ctrl *hdmi_ctrl)
+static int hdmi_tx_sysfs_create(struct hdmi_tx_ctrl *hdmi_ctrl,
+	struct fb_info *fbi)
 {
 	int rc;
-	struct mdss_panel_info *pinfo = NULL;
 
-	if (!hdmi_ctrl) {
+	if (!hdmi_ctrl || !fbi) {
 		DEV_ERR("%s: invalid input\n", __func__);
 		return -ENODEV;
 	}
-	pinfo = &hdmi_ctrl->panel_data.panel_info;
 
-	rc = sysfs_create_group(&pinfo->fbi->dev->kobj,
+	rc = sysfs_create_group(&fbi->dev->kobj,
 		&hdmi_tx_fs_attrs_group);
 	if (rc) {
 		DEV_ERR("%s: failed, rc=%d\n", __func__, rc);
 		return rc;
 	}
-	hdmi_ctrl->kobj = &pinfo->fbi->dev->kobj;
+	hdmi_ctrl->kobj = &fbi->dev->kobj;
 	DEV_DBG("%s: sysfs group %p\n", __func__, hdmi_ctrl->kobj);
 
 	kobject_uevent(hdmi_ctrl->kobj, KOBJ_ADD);
@@ -1742,7 +1741,7 @@
 		rc = -EPERM;
 	}
 
-	return 0;
+	return rc;
 } /* hdmi_tx_audio_info_setup */
 
 static int hdmi_tx_get_audio_edid_blk(struct platform_device *pdev,
@@ -1983,15 +1982,15 @@
 
 	hdmi_tx_core_off(hdmi_ctrl);
 
-	mutex_lock(&hdmi_ctrl->mutex);
-	hdmi_ctrl->panel_power_on = false;
-	mutex_unlock(&hdmi_ctrl->mutex);
-
 	if (hdmi_ctrl->hpd_off_pending) {
 		hdmi_tx_hpd_off(hdmi_ctrl);
 		hdmi_ctrl->hpd_off_pending = false;
 	}
 
+	mutex_lock(&hdmi_ctrl->mutex);
+	hdmi_ctrl->panel_power_on = false;
+	mutex_unlock(&hdmi_ctrl->mutex);
+
 	DEV_INFO("%s: HDMI Core: OFF\n", __func__);
 } /* hdmi_tx_power_off_work */
 
@@ -2349,6 +2348,22 @@
 		event, hdmi_ctrl->panel_suspend, hdmi_ctrl->hpd_feature_on);
 
 	switch (event) {
+	case MDSS_EVENT_FB_REGISTERED:
+		rc = hdmi_tx_sysfs_create(hdmi_ctrl, arg);
+		if (rc) {
+			DEV_ERR("%s: hdmi_tx_sysfs_create failed.rc=%d\n",
+					__func__, rc);
+			return rc;
+		}
+		rc = hdmi_tx_init_features(hdmi_ctrl);
+		if (rc) {
+			DEV_ERR("%s: init_features failed.rc=%d\n",
+					__func__, rc);
+			hdmi_tx_sysfs_remove(hdmi_ctrl);
+			return rc;
+		}
+		break;
+
 	case MDSS_EVENT_CHECK_PARAMS:
 		new_vic = hdmi_tx_get_vic_from_panel_info(hdmi_ctrl,
 			(struct mdss_panel_info *)arg);
@@ -2369,6 +2384,10 @@
 		break;
 
 	case MDSS_EVENT_RESUME:
+		/* If a suspend is already underway, wait for it to finish */
+		if (hdmi_ctrl->panel_suspend && hdmi_ctrl->panel_power_on)
+			flush_work(&hdmi_ctrl->power_off_work);
+
 		if (hdmi_ctrl->hpd_feature_on) {
 			INIT_COMPLETION(hdmi_ctrl->hpd_done);
 
@@ -2475,7 +2494,7 @@
 		return rc;
 	}
 
-	rc = mdss_register_panel(&hdmi_ctrl->panel_data);
+	rc = mdss_register_panel(hdmi_ctrl->pdev, &hdmi_ctrl->panel_data);
 	if (rc) {
 		DEV_ERR("%s: FAILED: to register HDMI panel\n", __func__);
 		return rc;
@@ -3074,26 +3093,13 @@
 		goto failed_reg_panel;
 	}
 
-	rc = hdmi_tx_sysfs_create(hdmi_ctrl);
-	if (rc) {
-		DEV_ERR("%s: hdmi_tx_sysfs_create failed.rc=%d\n",
-			__func__, rc);
-		goto failed_reg_panel;
-	}
-
-	rc = hdmi_tx_init_features(hdmi_ctrl);
-	if (rc) {
-		DEV_ERR("%s: init_features failed.rc=%d\n", __func__, rc);
-		goto failed_init_features;
-	}
-
 	rc = of_platform_populate(of_node, NULL, NULL, &pdev->dev);
 	if (rc) {
-		DEV_ERR("%s: failed to add child devices, rc=%d\n",
+		DEV_ERR("%s: Failed to add child devices. rc=%d\n",
 			__func__, rc);
 		goto failed_init_features;
 	} else {
-		DEV_DBG("%s: added child devices.\n", __func__);
+		DEV_DBG("%s: Add child devices.\n", __func__);
 	}
 
 	return rc;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index cd836a0..31b80b1 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -57,25 +57,6 @@
 static DEFINE_MUTEX(mdp_clk_lock);
 static DEFINE_MUTEX(mdp_suspend_mutex);
 
-u32 mdss_mdp_pipe_type_map[MDSS_MDP_MAX_SSPP] = {
-	MDSS_MDP_PIPE_TYPE_VIG,
-	MDSS_MDP_PIPE_TYPE_VIG,
-	MDSS_MDP_PIPE_TYPE_VIG,
-	MDSS_MDP_PIPE_TYPE_RGB,
-	MDSS_MDP_PIPE_TYPE_RGB,
-	MDSS_MDP_PIPE_TYPE_RGB,
-	MDSS_MDP_PIPE_TYPE_DMA,
-	MDSS_MDP_PIPE_TYPE_DMA,
-};
-
-u32 mdss_mdp_mixer_type_map[MDSS_MDP_MAX_LAYERMIXER] = {
-	MDSS_MDP_MIXER_TYPE_INTF,
-	MDSS_MDP_MIXER_TYPE_INTF,
-	MDSS_MDP_MIXER_TYPE_INTF,
-	MDSS_MDP_MIXER_TYPE_WRITEBACK,
-	MDSS_MDP_MIXER_TYPE_WRITEBACK,
-};
-
 #define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)		\
 	{						\
 		.src = MSM_BUS_MASTER_MDP_PORT0,	\
@@ -131,6 +112,15 @@
 struct mdss_hw *mdss_irq_handlers[MDSS_MAX_HW_BLK];
 
 static int mdss_mdp_register_early_suspend(struct mdss_data_type *mdata);
+static int mdss_mdp_parse_dt(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_mixer(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_ctl(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_video_intf(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_handler(struct platform_device *pdev,
+				      char *prop_name, u32 *offsets, int len);
+static int mdss_mdp_parse_dt_prop_len(struct platform_device *pdev,
+				       char *prop_name);
 
 static inline int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr)
 {
@@ -788,20 +778,18 @@
 
 static int mdss_hw_init(struct mdss_data_type *mdata)
 {
-	char *base = mdata->vbif_base;
-
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-	/* Setup VBIF QoS settings*/
-	MDSS_MDP_REG_WRITE(0x2E0, 0x000000AA);
-	MDSS_MDP_REG_WRITE(0x2E4, 0x00000055);
-	writel_relaxed(0x00000001, base + 0x004);
-	writel_relaxed(0x00000707, base + 0x0D8);
-	writel_relaxed(0x00000030, base + 0x0F0);
-	writel_relaxed(0x00000001, base + 0x124);
-	writel_relaxed(0x00000FFF, base + 0x178);
-	writel_relaxed(0x0FFF0FFF, base + 0x17C);
-	writel_relaxed(0x22222222, base + 0x160);
-	writel_relaxed(0x00002222, base + 0x164);
+	mdata->rev = MDSS_MDP_REG_READ(MDSS_REG_HW_VERSION);
+	mdata->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
+
+	if (mdata->hw_settings) {
+		struct mdss_hw_settings *hws = mdata->hw_settings;
+
+		while (hws->reg) {
+			writel_relaxed(hws->val, hws->reg);
+			hws++;
+		}
+	}
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 	pr_debug("MDP hw init done\n");
 
@@ -812,6 +800,18 @@
 {
 	u32 rc = 0;
 
+	if (mdata->res_init) {
+		pr_err("mdss resources already initialized\n");
+		return -EPERM;
+	}
+
+	mdata->res_init = true;
+	mdata->timeout = HZ/20;
+	mdata->clk_ena = false;
+	mdata->irq_mask = MDSS_MDP_DEFAULT_INTR_MASK;
+	mdata->irq_ena = false;
+	mdata->suspend = false;
+
 	rc = mdss_mdp_irq_clk_setup(mdata);
 	if (rc)
 		return rc;
@@ -820,27 +820,12 @@
 	INIT_DELAYED_WORK(&mdata->clk_ctrl_worker,
 			  mdss_mdp_clk_ctrl_workqueue_handler);
 
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-	mdata->rev = MDSS_MDP_REG_READ(MDSS_REG_HW_VERSION);
-	mdata->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-
 	mdata->smp_mb_cnt = MDSS_MDP_SMP_MMB_BLOCKS;
 	mdata->smp_mb_size = MDSS_MDP_SMP_MMB_SIZE;
-	mdata->pipe_type_map = mdss_mdp_pipe_type_map;
-	mdata->mixer_type_map = mdss_mdp_mixer_type_map;
 
 	pr_info("mdss_revision=%x\n", mdata->rev);
 	pr_info("mdp_hw_revision=%x\n", mdata->mdp_rev);
 
-	mdata->res_init = true;
-	mdata->timeout = HZ/20;
-	mdata->clk_ena = false;
-	mdata->irq_mask = MDSS_MDP_DEFAULT_INTR_MASK;
-	mdata->suspend = false;
-	mdata->prim_ptype = NO_PANEL;
-	mdata->irq_ena = false;
-
 	mdata->iclient = msm_ion_client_create(-1, mdata->pdev->name);
 	if (IS_ERR_OR_NULL(mdata->iclient)) {
 		pr_err("msm_ion_client_create() return error (%p)\n",
@@ -927,6 +912,13 @@
 	}
 	mdata->irq = res->start;
 
+	/*populate hw iomem base info from device tree*/
+	rc = mdss_mdp_parse_dt(pdev);
+	if (rc) {
+		pr_err("unable to parse device tree\n");
+		goto probe_done;
+	}
+
 	rc = mdss_mdp_res_init(mdata);
 	if (rc) {
 		pr_err("unable to initialize mdss mdp resources\n");
@@ -962,10 +954,399 @@
 	return rc;
 }
 
+static void mdss_mdp_parse_dt_regs_array(const u32 *arr, char __iomem *hw_base,
+	struct mdss_hw_settings *hws, int count)
+{
+	u32 len, reg;
+	int i;
+
+	if (!arr)
+		return;
+
+	for (i = 0, len = count * 2; i < len; i += 2) {
+		reg = be32_to_cpu(arr[i]);
+		hws->reg = hw_base + reg;
+		hws->val = be32_to_cpu(arr[i + 1]);
+		pr_debug("reg: 0x%04x=0x%08x\n", reg, hws->val);
+		hws++;
+	}
+}
+
+int mdss_mdp_parse_dt_hw_settings(struct platform_device *pdev)
+{
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+	struct mdss_hw_settings *hws;
+	const u32 *vbif_arr, *mdp_arr;
+	int vbif_len, mdp_len;
+
+	vbif_arr = of_get_property(pdev->dev.of_node, "qcom,vbif-settings",
+			&vbif_len);
+	if (!vbif_arr || (mdp_len & 1)) {
+		pr_warn("MDSS VBIF settings not found\n");
+		vbif_len = 0;
+	}
+	vbif_len /= 2 * sizeof(u32);
+
+	mdp_arr = of_get_property(pdev->dev.of_node, "qcom,mdp-settings",
+			&mdp_len);
+	if (!mdp_arr || (mdp_len & 1)) {
+		pr_warn("MDSS MDP settings not found\n");
+		mdp_len = 0;
+	}
+	mdp_len /= 2 * sizeof(u32);
+
+	if ((mdp_len + vbif_len) == 0)
+		return 0;
+
+	hws = devm_kzalloc(&pdev->dev, sizeof(*hws) * (vbif_len + mdp_len + 1),
+			GFP_KERNEL);
+	if (!hws)
+		return -ENOMEM;
+
+	mdss_mdp_parse_dt_regs_array(vbif_arr, mdata->vbif_base, hws, vbif_len);
+	mdss_mdp_parse_dt_regs_array(mdp_arr, mdata->mdp_base,
+		hws + vbif_len, mdp_len);
+
+	mdata->hw_settings = hws;
+
+	return 0;
+}
+
+static int mdss_mdp_parse_dt(struct platform_device *pdev)
+{
+	int rc;
+
+	rc = mdss_mdp_parse_dt_hw_settings(pdev);
+	if (rc) {
+		pr_err("Error in device tree : hw settings\n");
+		return rc;
+	}
+
+	rc = mdss_mdp_parse_dt_pipe(pdev);
+	if (rc) {
+		pr_err("Error in device tree : pipes\n");
+		return rc;
+	}
+
+	rc = mdss_mdp_parse_dt_mixer(pdev);
+	if (rc) {
+		pr_err("Error in device tree : mixers\n");
+		return rc;
+	}
+
+	rc = mdss_mdp_parse_dt_ctl(pdev);
+	if (rc) {
+		pr_err("Error in device tree : ctl\n");
+		return rc;
+	}
+
+	rc = mdss_mdp_parse_dt_video_intf(pdev);
+	if (rc) {
+		pr_err("Error in device tree : ctl\n");
+		return rc;
+	}
+
+	return 0;
+}
+
+
+static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
+{
+	u32 npipes, off;
+	int rc = 0;
+	u32 nids = 0;
+	u32 *offsets = NULL, *ftch_id = NULL;
+
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+	mdata->nvig_pipes = mdss_mdp_parse_dt_prop_len(pdev,
+				"qcom,mdss-pipe-vig-off");
+	mdata->nrgb_pipes = mdss_mdp_parse_dt_prop_len(pdev,
+				"qcom,mdss-pipe-rgb-off");
+	mdata->ndma_pipes = mdss_mdp_parse_dt_prop_len(pdev,
+				"qcom,mdss-pipe-dma-off");
+
+	nids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-vig-fetch-id");
+	nids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-rgb-fetch-id");
+	nids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-dma-fetch-id");
+
+	npipes = mdata->nvig_pipes + mdata->nrgb_pipes + mdata->ndma_pipes;
+
+	if (npipes != nids) {
+		pr_err("device tree err: unequal number of pipes and smp ids");
+		return -EINVAL;
+	}
+
+	offsets = kzalloc(sizeof(u32) * npipes, GFP_KERNEL);
+	if (!offsets) {
+		pr_err("no mem assigned: kzalloc fail\n");
+		return -ENOMEM;
+	}
+
+	ftch_id = kzalloc(sizeof(u32) * nids, GFP_KERNEL);
+	if (!ftch_id) {
+		pr_err("no mem assigned: kzalloc fail\n");
+		rc = -ENOMEM;
+		goto ftch_alloc_fail;
+	}
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-fetch-id",
+		ftch_id, mdata->nvig_pipes);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-off",
+		offsets, mdata->nvig_pipes);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_pipe_addr_setup(mdata, offsets, ftch_id,
+		MDSS_MDP_PIPE_TYPE_VIG, MDSS_MDP_SSPP_VIG0, mdata->nvig_pipes);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-fetch-id",
+		ftch_id + mdata->nvig_pipes, mdata->nrgb_pipes);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-off",
+		offsets + mdata->nvig_pipes, mdata->nrgb_pipes);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_pipe_addr_setup(mdata, offsets + mdata->nvig_pipes,
+		ftch_id + mdata->nvig_pipes, MDSS_MDP_PIPE_TYPE_RGB,
+		MDSS_MDP_SSPP_RGB0, mdata->nrgb_pipes);
+	if (rc)
+		goto parse_done;
+
+	off = mdata->nvig_pipes + mdata->nrgb_pipes;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-fetch-id",
+		ftch_id + off, mdata->ndma_pipes);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-off",
+		offsets + off, mdata->ndma_pipes);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_pipe_addr_setup(mdata, offsets + off, ftch_id + off,
+		MDSS_MDP_PIPE_TYPE_DMA, MDSS_MDP_SSPP_DMA0, mdata->ndma_pipes);
+	if (rc)
+		goto parse_done;
+
+parse_done:
+	kfree(ftch_id);
+ftch_alloc_fail:
+	kfree(offsets);
+	return rc;
+}
+
+static int mdss_mdp_parse_dt_mixer(struct platform_device *pdev)
+{
+
+	u32 nmixers, ndspp;
+	int rc = 0;
+	u32 *mixer_offsets = NULL, *dspp_offsets = NULL;
+
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+	mdata->nmixers_intf = mdss_mdp_parse_dt_prop_len(pdev,
+				"qcom,mdss-mixer-intf-off");
+	mdata->nmixers_wb = mdss_mdp_parse_dt_prop_len(pdev,
+				"qcom,mdss-mixer-wb-off");
+	ndspp = mdss_mdp_parse_dt_prop_len(pdev,
+				"qcom,mdss-dspp-off");
+	nmixers = mdata->nmixers_intf + mdata->nmixers_wb;
+
+	if (mdata->nmixers_intf != ndspp) {
+		pr_err("device tree err: unequal no of dspp and intf mixers\n");
+		return -EINVAL;
+	}
+
+	mixer_offsets = kzalloc(sizeof(u32) * nmixers, GFP_KERNEL);
+	if (!mixer_offsets) {
+		pr_err("no mem assigned: kzalloc fail\n");
+		return -ENOMEM;
+	}
+
+	dspp_offsets = kzalloc(sizeof(u32) * ndspp, GFP_KERNEL);
+	if (!dspp_offsets) {
+		pr_err("no mem assigned: kzalloc fail\n");
+		rc = -ENOMEM;
+		goto dspp_alloc_fail;
+	}
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-mixer-intf-off",
+		mixer_offsets, mdata->nmixers_intf);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-mixer-wb-off",
+		mixer_offsets + mdata->nmixers_intf, mdata->nmixers_wb);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-dspp-off",
+		dspp_offsets, ndspp);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_mixer_addr_setup(mdata, mixer_offsets,
+			dspp_offsets, MDSS_MDP_MIXER_TYPE_INTF,
+			mdata->nmixers_intf);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_mixer_addr_setup(mdata, mixer_offsets +
+			mdata->nmixers_intf, NULL,
+			MDSS_MDP_MIXER_TYPE_WRITEBACK, mdata->nmixers_wb);
+	if (rc)
+		goto parse_done;
+
+parse_done:
+	kfree(dspp_offsets);
+dspp_alloc_fail:
+	kfree(mixer_offsets);
+
+	return rc;
+}
+
+static int mdss_mdp_parse_dt_ctl(struct platform_device *pdev)
+{
+	u32 nwb;
+	int rc = 0;
+	u32 *ctl_offsets = NULL, *wb_offsets = NULL;
+
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+	mdata->nctl = mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-ctl-off");
+	nwb =  mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-wb-off");
+
+	if (mdata->nctl != nwb) {
+		pr_err("device tree err: unequal number of ctl and wb\n");
+		rc = -EINVAL;
+		goto parse_done;
+	}
+
+	ctl_offsets = kzalloc(sizeof(u32) * mdata->nctl, GFP_KERNEL);
+	if (!ctl_offsets) {
+		pr_err("no more mem for ctl offsets\n");
+		return -ENOMEM;
+	}
+
+	wb_offsets = kzalloc(sizeof(u32) * nwb, GFP_KERNEL);
+	if (!wb_offsets) {
+		pr_err("no more mem for writeback offsets\n");
+		rc = -ENOMEM;
+		goto wb_alloc_fail;
+	}
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-ctl-off",
+		ctl_offsets, mdata->nctl);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-wb-off",
+		wb_offsets, nwb);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_ctl_addr_setup(mdata, ctl_offsets, wb_offsets,
+						 mdata->nctl);
+	if (rc)
+		goto parse_done;
+
+parse_done:
+	kfree(wb_offsets);
+wb_alloc_fail:
+	kfree(ctl_offsets);
+
+	return rc;
+}
+
+static int mdss_mdp_parse_dt_video_intf(struct platform_device *pdev)
+{
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+	u32 count;
+	u32 *offsets;
+	int rc;
+
+
+	count = mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-intf-off");
+	if (count == 0)
+		return -EINVAL;
+
+	offsets = kzalloc(sizeof(u32) * count, GFP_KERNEL);
+	if (!offsets) {
+		pr_err("no mem assigned for video intf\n");
+		return -ENOMEM;
+	}
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-intf-off",
+			offsets, count);
+	if (rc)
+		goto parse_fail;
+
+	rc = mdss_mdp_video_addr_setup(mdata, offsets, count);
+	if (rc)
+		pr_err("unable to setup video interfaces\n");
+
+parse_fail:
+	kfree(offsets);
+
+	return rc;
+}
+
+static int mdss_mdp_parse_dt_handler(struct platform_device *pdev,
+		char *prop_name, u32 *offsets, int len)
+{
+	int rc;
+	rc = of_property_read_u32_array(pdev->dev.of_node, prop_name,
+					offsets, len);
+	if (rc) {
+		pr_err("Error from prop %s : u32 array read\n", prop_name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mdss_mdp_parse_dt_prop_len(struct platform_device *pdev,
+				      char *prop_name)
+{
+	int len = 0;
+
+	of_find_property(pdev->dev.of_node, prop_name, &len);
+
+	if (len < 1) {
+		pr_err("Error from prop %s : spec error in device tree\n",
+		       prop_name);
+		return 0;
+	}
+
+	len = len/sizeof(u32);
+
+	return len;
+}
+
+struct mdss_data_type *mdss_mdp_get_mdata()
+{
+	return mdss_res;
+}
+
 static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
 {
 	mutex_lock(&mdp_suspend_mutex);
-	if (!mdata->suspend || mdata->eintf_ena || !mdata->fs) {
+	if (!mdata->suspend || !mdata->fs) {
 		mutex_unlock(&mdp_suspend_mutex);
 		return;
 	}
@@ -1128,7 +1509,6 @@
 	{}
 };
 MODULE_DEVICE_TABLE(of, mdss_mdp_dt_match);
-EXPORT_COMPAT("qcom,mdss_mdp");
 
 static struct platform_driver mdss_mdp_driver = {
 	.probe = mdss_mdp_probe,
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 40cca22..30b7695 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -112,6 +112,8 @@
 
 struct mdss_mdp_ctl {
 	u32 num;
+	char __iomem *base;
+	char __iomem *wb_base;
 	u32 ref_cnt;
 	int power_on;
 
@@ -131,6 +133,7 @@
 	u32 bus_ib_quota;
 	u32 clk_rate;
 
+	struct mdss_data_type *mdata;
 	struct msm_fb_data_type *mfd;
 	struct mdss_mdp_mixer *mixer_left;
 	struct mdss_mdp_mixer *mixer_right;
@@ -150,9 +153,10 @@
 struct mdss_mdp_mixer {
 	u32 num;
 	u32 ref_cnt;
+	char __iomem *base;
+	char __iomem *dspp_base;
 	u8 type;
 	u8 params_changed;
-
 	u16 width;
 	u16 height;
 	u8 cursor_enabled;
@@ -209,10 +213,31 @@
 	struct mdss_mdp_img_data p[MAX_PLANES];
 };
 
+struct pp_sts_type {
+	u32 pa_sts;
+	u32 pcc_sts;
+	u32 igc_sts;
+	u32 igc_tbl_idx;
+	u32 argc_sts;
+	u32 enhist_sts;
+	u32 dither_sts;
+	u32 gamut_sts;
+	u32 pgc_sts;
+	u32 sharp_sts;
+};
+
+struct mdss_pipe_pp_res {
+	u32 igc_c0_c1[IGC_LUT_ENTRIES];
+	u32 igc_c2[IGC_LUT_ENTRIES];
+	struct pp_sts_type pp_sts;
+};
+
 struct mdss_mdp_pipe {
 	u32 num;
 	u32 type;
 	u32 ndx;
+	char __iomem *base;
+	u32 ftch_id;
 	atomic_t ref_cnt;
 	u32 play_cnt;
 
@@ -248,6 +273,7 @@
 	struct list_head cleanup_list;
 
 	struct mdp_overlay_pp_params pp_cfg;
+	struct mdss_pipe_pp_res pp_res;
 };
 
 struct mdss_mdp_writeback_arg {
@@ -260,14 +286,12 @@
 static inline void mdss_mdp_ctl_write(struct mdss_mdp_ctl *ctl,
 				      u32 reg, u32 val)
 {
-	int offset = MDSS_MDP_REG_CTL_OFFSET(ctl->num);
-	MDSS_MDP_REG_WRITE(offset + reg, val);
+	writel_relaxed(val, ctl->base + reg);
 }
 
 static inline u32 mdss_mdp_ctl_read(struct mdss_mdp_ctl *ctl, u32 reg)
 {
-	int offset = MDSS_MDP_REG_CTL_OFFSET(ctl->num);
-	return MDSS_MDP_REG_READ(offset + reg);
+	return readl_relaxed(ctl->base + reg);
 }
 
 irqreturn_t mdss_mdp_isr(int irq, void *ptr);
@@ -284,15 +308,23 @@
 unsigned long mdss_mdp_get_clk_rate(u32 clk_idx);
 int mdss_mdp_vsync_clk_enable(int enable);
 void mdss_mdp_clk_ctrl(int enable, int isr);
+struct mdss_data_type *mdss_mdp_get_mdata(void);
 
 int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
 int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en);
+int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata,
+		u32 *offsets,  u32 count);
 int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl);
 
-int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd);
-int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd);
+struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
+				       struct msm_fb_data_type *mfd);
+int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
+		struct mdss_panel_data *pdata);
+int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg);
 
 struct mdss_mdp_mixer *mdss_mdp_wb_mixer_alloc(int rotator);
@@ -308,10 +340,17 @@
 int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
 				   struct mdp_csc_cfg *data);
 
-int mdss_mdp_pipe_pp_setup(struct mdss_mdp_pipe *pipe, u32 *op);
-int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
-int mdss_mdp_pcc_config(struct mdp_pcc_cfg_data *cfg_ptr, u32 *copyback);
+int mdss_mdp_pp_init(struct device *dev);
+void mdss_mdp_pp_term(struct device *dev);
+int mdss_mdp_pp_resume(u32 mixer_num);
 
+int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_pipe_pp_setup(struct mdss_mdp_pipe *pipe, u32 *op);
+int mdss_mdp_pipe_sspp_setup(struct mdss_mdp_pipe *pipe, u32 *op);
+void mdss_mdp_pipe_sspp_term(struct mdss_mdp_pipe *pipe);
+
+int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config, u32 *copyback);
+int mdss_mdp_pcc_config(struct mdp_pcc_cfg_data *cfg_ptr, u32 *copyback);
 int mdss_mdp_igc_lut_config(struct mdp_igc_lut_data *config, u32 *copyback);
 int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config, u32 *copyback);
 int mdss_mdp_hist_lut_config(struct mdp_hist_lut_data *config, u32 *copyback);
@@ -324,12 +363,19 @@
 		   struct mdp_histogram_data *hist, u32 *hist_data_addr);
 void mdss_mdp_hist_intr_done(u32 isr);
 
-
-struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum);
-struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(u32 type);
-struct mdss_mdp_pipe *mdss_mdp_pipe_get(u32 ndx);
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(struct mdss_mdp_mixer *mixer,
+					  u32 type);
+struct mdss_mdp_pipe *mdss_mdp_pipe_get(struct mdss_data_type *mdata, u32 ndx);
 int mdss_mdp_pipe_map(struct mdss_mdp_pipe *pipe);
 void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe);
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_dma(struct mdss_mdp_mixer *mixer);
+
+int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
+		u32 *ftch_y_id, u32 type, u32 num_base, u32 len);
+int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, u32 *mixer_offsets,
+		u32 *dspp_offsets, u32 type, u32 len);
+int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, u32 *ctl_offsets,
+		u32 *wb_offsets, u32 len);
 
 int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
 int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
@@ -347,9 +393,5 @@
 int mdss_mdp_wb_kickoff(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
 
-int mdss_mdp_pp_init(struct device *dev);
-void mdss_mdp_pp_term(struct device *dev);
-int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config, u32 *copyback);
-
 int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id);
 #endif /* MDSS_MDP_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 6030cbc..63a1aa4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -38,10 +38,14 @@
 #define MDSS_MDP_PERF_UPDATE_ALL -1
 
 static DEFINE_MUTEX(mdss_mdp_ctl_lock);
-static struct mdss_mdp_ctl mdss_mdp_ctl_list[MDSS_MDP_MAX_CTL];
-static struct mdss_mdp_mixer mdss_mdp_mixer_list[MDSS_MDP_MAX_LAYERMIXER];
 
-static int mdss_mdp_ctl_perf_commit(u32 flags)
+static inline void mdp_mixer_write(struct mdss_mdp_mixer *mixer,
+				   u32 reg, u32 val)
+{
+	writel_relaxed(val, mixer->base + reg);
+}
+
+static int mdss_mdp_ctl_perf_commit(struct mdss_data_type *mdata, u32 flags)
 {
 	struct mdss_mdp_ctl *ctl;
 	int cnum;
@@ -54,8 +58,8 @@
 	}
 
 	mutex_lock(&mdss_mdp_ctl_lock);
-	for (cnum = 0; cnum < MDSS_MDP_MAX_CTL; cnum++) {
-		ctl = &mdss_mdp_ctl_list[cnum];
+	for (cnum = 0; cnum < mdata->nctl; cnum++) {
+		ctl = mdata->ctl_off + cnum;
 		if (ctl->power_on) {
 			bus_ab_quota += ctl->bus_ab_quota;
 			bus_ib_quota += ctl->bus_ib_quota;
@@ -69,10 +73,6 @@
 		bus_ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR(bus_ib_quota);
 		bus_ib_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT;
 
-		if ((bus_ib_quota == 0) && (clk_rate > 0)) {
-			/* allocate min bw for panel cmds if mdp is active */
-			bus_ib_quota = SZ_16M;
-		}
 		mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
 	}
 	if (flags & MDSS_MDP_PERF_UPDATE_CLK) {
@@ -92,7 +92,7 @@
 	struct mdss_mdp_pipe *pipe;
 	const int fps = 60;
 	u32 quota, rate;
-	u32 v_total, v_active;
+	u32 v_total;
 	int i;
 	u32 max_clk_rate = 0, ab_total = 0, ib_total = 0;
 
@@ -103,7 +103,6 @@
 	if (mixer->rotator_mode) {
 		pipe = mixer->stage_pipe[0]; /* rotator pipe */
 		v_total = pipe->flags & MDP_ROT_90 ? pipe->dst.w : pipe->dst.h;
-		v_active = v_total;
 	} else {
 		int is_writeback = false;
 		if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
@@ -112,13 +111,11 @@
 			v_total = (pinfo->yres + pinfo->lcdc.v_back_porch +
 				   pinfo->lcdc.v_front_porch +
 				   pinfo->lcdc.v_pulse_width);
-			v_active = pinfo->yres;
 
 			if (pinfo->type == WRITEBACK_PANEL)
 				is_writeback = true;
 		} else {
 			v_total = mixer->height;
-			v_active = v_total;
 
 			is_writeback = true;
 		}
@@ -148,21 +145,19 @@
 		else
 			quota *= pipe->src_fmt->bpp;
 
-		if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
-			quota = (quota / v_active) * v_total;
-		else if (mixer->rotator_mode)
-			quota *= 2; /* bus read + write */
-
 		rate = pipe->dst.w;
-		if (pipe->src.h > pipe->dst.h) {
+		if (pipe->src.h > pipe->dst.h)
 			rate = (rate * pipe->src.h) / pipe->dst.h;
-			ib_quota = (quota / pipe->dst.h) * pipe->src.h;
-		} else {
-			ib_quota = quota;
-		}
+
 		rate *= v_total * fps;
-		if (mixer->rotator_mode)
+		if (mixer->rotator_mode) {
 			rate /= 4; /* block mode fetch at 4 pix/clk */
+			quota *= 2; /* bus read + write */
+			ib_quota = quota;
+		} else {
+			ib_quota = (quota / pipe->dst.h) * v_total;
+		}
+
 
 		pr_debug("mixer=%d pnum=%d clk_rate=%u bus ab=%u ib=%u\n",
 			 mixer->num, pipe->num, rate, quota, ib_quota);
@@ -205,6 +200,10 @@
 			max_clk_rate = clk_rate;
 	}
 
+	/* request minimum bandwidth for dsi commands */
+	if ((total_ib_quota == 0) && (ctl->intf_type == MDSS_INTF_DSI))
+		total_ib_quota = SZ_16M >> MDSS_MDP_BUS_FACTOR_SHIFT;
+
 	*flags = 0;
 
 	if (max_clk_rate != ctl->clk_rate) {
@@ -219,7 +218,7 @@
 	if ((total_ab_quota != ctl->bus_ab_quota) ||
 			(total_ib_quota != ctl->bus_ib_quota)) {
 		if (ret == MDSS_MDP_PERF_UPDATE_SKIP) {
-			if (total_ib_quota > ctl->bus_ib_quota)
+			if (total_ib_quota >= ctl->bus_ib_quota)
 				ret = MDSS_MDP_PERF_UPDATE_EARLY;
 			else
 				ret = MDSS_MDP_PERF_UPDATE_LATE;
@@ -232,22 +231,22 @@
 	return ret;
 }
 
-static struct mdss_mdp_ctl *mdss_mdp_ctl_alloc(void)
+static struct mdss_mdp_ctl *mdss_mdp_ctl_alloc(struct mdss_data_type *mdata)
 {
 	struct mdss_mdp_ctl *ctl = NULL;
 	int cnum;
 
 	mutex_lock(&mdss_mdp_ctl_lock);
-	for (cnum = 0; cnum < MDSS_MDP_MAX_CTL; cnum++) {
-		if (mdss_mdp_ctl_list[cnum].ref_cnt == 0) {
-			ctl = &mdss_mdp_ctl_list[cnum];
-			ctl->num = cnum;
+	for (cnum = 0; cnum < mdata->nctl; cnum++) {
+		ctl = mdata->ctl_off + cnum;
+		if (ctl->ref_cnt == 0) {
 			ctl->ref_cnt++;
+			ctl->mdata = mdata;
 			mutex_init(&ctl->lock);
-
 			pr_debug("alloc ctl_num=%d\n", ctl->num);
 			break;
 		}
+		ctl = NULL;
 	}
 	mutex_unlock(&mdss_mdp_ctl_lock);
 
@@ -267,31 +266,57 @@
 	}
 
 	mutex_lock(&mdss_mdp_ctl_lock);
-	if (--ctl->ref_cnt == 0)
-		memset(ctl, 0, sizeof(*ctl));
+	ctl->ref_cnt--;
 	mutex_unlock(&mdss_mdp_ctl_lock);
 
 	return 0;
 }
 
-static struct mdss_mdp_mixer *mdss_mdp_mixer_alloc(u32 type)
+static struct mdss_mdp_mixer *mdss_mdp_mixer_alloc(
+		struct mdss_mdp_ctl *ctl, u32 type)
 {
 	struct mdss_mdp_mixer *mixer = NULL;
-	int mnum;
+	u32 nmixers_intf;
+	u32 nmixers_wb;
+	u32 i;
+	u32 nmixers;
+	struct mdss_mdp_mixer *mixer_pool = NULL;
+
+	if (!ctl || !ctl->mdata)
+		return NULL;
 
 	mutex_lock(&mdss_mdp_ctl_lock);
-	for (mnum = 0; mnum < MDSS_MDP_MAX_LAYERMIXER; mnum++) {
-		if (type == mdss_res->mixer_type_map[mnum] &&
-		    mdss_mdp_mixer_list[mnum].ref_cnt == 0) {
-			mixer = &mdss_mdp_mixer_list[mnum];
-			mixer->num = mnum;
+	nmixers_intf = ctl->mdata->nmixers_intf;
+	nmixers_wb = ctl->mdata->nmixers_wb;
+
+	switch (type) {
+
+	case MDSS_MDP_MIXER_TYPE_INTF:
+		mixer_pool = ctl->mdata->mixer_intf;
+		nmixers = nmixers_intf;
+		break;
+
+	case MDSS_MDP_MIXER_TYPE_WRITEBACK:
+		mixer_pool = ctl->mdata->mixer_wb;
+		nmixers = nmixers_wb;
+		break;
+
+	default:
+		nmixers = 0;
+		pr_err("invalid pipe type %d\n", type);
+		break;
+	}
+
+	for (i = 0; i < nmixers; i++) {
+		mixer = mixer_pool + i;
+		if (mixer->ref_cnt == 0) {
 			mixer->ref_cnt++;
 			mixer->params_changed++;
-			mixer->type = type;
-
-			pr_debug("mixer_num=%d\n", mixer->num);
+			mixer->ctl = ctl;
+			pr_debug("alloc mixer num%d\n", mixer->num);
 			break;
 		}
+		mixer = NULL;
 	}
 	mutex_unlock(&mdss_mdp_ctl_lock);
 
@@ -311,8 +336,7 @@
 	}
 
 	mutex_lock(&mdss_mdp_ctl_lock);
-	if (--mixer->ref_cnt == 0)
-		memset(mixer, 0, sizeof(*mixer));
+	mixer->ref_cnt--;
 	mutex_unlock(&mdss_mdp_ctl_lock);
 
 	return 0;
@@ -323,23 +347,22 @@
 	struct mdss_mdp_ctl *ctl = NULL;
 	struct mdss_mdp_mixer *mixer = NULL;
 
-	ctl = mdss_mdp_ctl_alloc();
-
+	ctl = mdss_mdp_ctl_alloc(mdss_res);
 	if (!ctl)
 		return NULL;
 
-	mixer = mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_WRITEBACK);
+	mixer = mdss_mdp_mixer_alloc(ctl, MDSS_MDP_MIXER_TYPE_WRITEBACK);
 	if (!mixer)
 		goto error;
 
 	mixer->rotator_mode = rotator;
 
 	switch (mixer->num) {
-	case MDSS_MDP_LAYERMIXER3:
+	case MDSS_MDP_WB_LAYERMIXER0:
 		ctl->opmode = (rotator ? MDSS_MDP_CTL_OP_ROT0_MODE :
 			       MDSS_MDP_CTL_OP_WB0_MODE);
 		break;
-	case MDSS_MDP_LAYERMIXER4:
+	case MDSS_MDP_WB_LAYERMIXER1:
 		ctl->opmode = (rotator ? MDSS_MDP_CTL_OP_ROT1_MODE :
 			       MDSS_MDP_CTL_OP_WB1_MODE);
 		break;
@@ -349,7 +372,6 @@
 	}
 
 	ctl->mixer_left = mixer;
-	mixer->ctl = ctl;
 
 	ctl->start_fnc = mdss_mdp_writeback_start;
 	ctl->power_on = true;
@@ -381,46 +403,52 @@
 	mdss_mdp_mixer_free(mixer);
 	mdss_mdp_ctl_free(ctl);
 
-	mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
+	mdss_mdp_ctl_perf_commit(ctl->mdata, MDSS_MDP_PERF_UPDATE_ALL);
 
 	return 0;
 }
 
-static int mdss_mdp_ctl_init(struct msm_fb_data_type *mfd)
+static inline int mdss_mdp_set_split_ctl(struct mdss_mdp_ctl *ctl,
+		struct mdss_mdp_ctl *split_ctl)
 {
-	struct mdss_mdp_ctl *ctl;
-	struct mdss_panel_data *pdata;
+	if (!ctl || !split_ctl)
+		return -ENODEV;
+
+	/* setup split ctl mixer as right mixer of original ctl so that
+	 * original ctl can work the same way as dual pipe solution */
+	ctl->mixer_right = split_ctl->mixer_left;
+
+	return 0;
+}
+
+static inline struct mdss_mdp_ctl *mdss_mdp_get_split_ctl(
+		struct mdss_mdp_ctl *ctl)
+{
+	if (ctl && ctl->mixer_right && (ctl->mixer_right->ctl != ctl))
+		return ctl->mixer_right->ctl;
+
+	return NULL;
+}
+
+static int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_mdp_ctl *split_ctl;
 	u32 width, height;
-	int ret = 0;
 
-	if (!mfd)
-		return -ENODEV;
-
-	pdata = dev_get_platdata(&mfd->pdev->dev);
-	if (!pdata) {
-		pr_err("no panel connected for fb%d\n", mfd->index);
+	if (!ctl || !ctl->panel_data) {
+		pr_err("invalid ctl handle\n");
 		return -ENODEV;
 	}
 
-	width = pdata->panel_info.xres;
-	height = pdata->panel_info.yres;
+	split_ctl = mdss_mdp_get_split_ctl(ctl);
 
-	if (width > (2 * MAX_MIXER_WIDTH)) {
-		pr_err("unsupported resolution\n");
-		return -EINVAL;
-	}
+	width = ctl->panel_data->panel_info.xres;
+	height = ctl->panel_data->panel_info.yres;
 
-	if (!mfd->ctl) {
-		ctl = mdss_mdp_ctl_alloc();
-		if (!ctl) {
-			pr_err("unable to allocate ctl\n");
-			return -ENOMEM;
-		}
-		ctl->mfd = mfd;
-		mfd->ctl = ctl;
-		ctl->panel_data = pdata;
-	} else {
-		ctl = mfd->ctl;
+	if ((split_ctl && (width > MAX_MIXER_WIDTH)) ||
+			(width > (2 * MAX_MIXER_WIDTH))) {
+		pr_err("Unsupported panel resolution: %dx%d\n", width, height);
+		return -ENOTSUPP;
 	}
 
 	ctl->width = width;
@@ -428,11 +456,10 @@
 
 	if (!ctl->mixer_left) {
 		ctl->mixer_left =
-			mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+			mdss_mdp_mixer_alloc(ctl, MDSS_MDP_MIXER_TYPE_INTF);
 		if (!ctl->mixer_left) {
 			pr_err("unable to allocate layer mixer\n");
-			ret = -ENOMEM;
-			goto ctl_init_fail;
+			return -ENOMEM;
 		}
 	}
 
@@ -441,25 +468,55 @@
 
 	ctl->mixer_left->width = width;
 	ctl->mixer_left->height = height;
-	ctl->mixer_left->ctl = ctl;
+
+	if (split_ctl) {
+		pr_debug("split display detected\n");
+		return 0;
+	}
 
 	if (width < ctl->width) {
 		if (ctl->mixer_right == NULL) {
-			ctl->mixer_right =
-				mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+			ctl->mixer_right = mdss_mdp_mixer_alloc(ctl,
+					MDSS_MDP_MIXER_TYPE_INTF);
 			if (!ctl->mixer_right) {
 				pr_err("unable to allocate right mixer\n");
-				ret = -ENOMEM;
-				goto ctl_init_fail;
+				if (ctl->mixer_left)
+					mdss_mdp_mixer_free(ctl->mixer_left);
+				return -ENOMEM;
 			}
 		}
 		ctl->mixer_right->width = width;
 		ctl->mixer_right->height = height;
-		ctl->mixer_right->ctl = ctl;
 	} else if (ctl->mixer_right) {
 		mdss_mdp_mixer_free(ctl->mixer_right);
+		ctl->mixer_right = NULL;
 	}
 
+	if (ctl->mixer_right) {
+		ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+			       MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
+	} else {
+		ctl->opmode &= ~(MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+				  MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT);
+	}
+
+	return 0;
+}
+
+struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
+				       struct msm_fb_data_type *mfd)
+{
+	struct mdss_mdp_ctl *ctl;
+	int ret = 0;
+
+	ctl = mdss_mdp_ctl_alloc(mfd->mdata);
+	if (!ctl) {
+		pr_err("unable to allocate ctl\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	ctl->mfd = mfd;
+	ctl->panel_data = pdata;
+
 	switch (pdata->panel_info.type) {
 	case EDP_PANEL:
 		ctl->intf_num = MDSS_MDP_INTF0;
@@ -519,37 +576,117 @@
 		mdss_mdp_dither_config(&dither, NULL);
 	}
 
-	if (ctl->mixer_right) {
-		ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
-			       MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
-	}
-
+	return ctl;
 ctl_init_fail:
-	if (IS_ERR_VALUE(ret)) {
-		if (ctl->mixer_left)
-			mdss_mdp_mixer_free(ctl->mixer_left);
-		if (ctl->mixer_right)
-			mdss_mdp_mixer_free(ctl->mixer_right);
-		mdss_mdp_ctl_free(ctl);
-		mfd->ctl = NULL;
-	}
+	mdss_mdp_ctl_free(ctl);
 
-	return ret;
+	return ERR_PTR(ret);
 }
 
-static int mdss_mdp_ctl_destroy(struct msm_fb_data_type *mfd)
+int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
+		struct mdss_panel_data *pdata)
 {
-	struct mdss_mdp_ctl *ctl;
-	if (!mfd || !mfd->ctl)
+	struct mdss_mdp_ctl *sctl;
+	struct mdss_mdp_mixer *mixer;
+
+	if (!ctl || !pdata)
 		return -ENODEV;
 
-	ctl = mfd->ctl;
-	mfd->ctl = NULL;
+	if (pdata->panel_info.xres > MAX_MIXER_WIDTH) {
+		pr_err("Unsupported second panel resolution: %dx%d\n",
+				pdata->panel_info.xres, pdata->panel_info.yres);
+		return -ENOTSUPP;
+	}
 
-	if (ctl->mixer_left)
-		mdss_mdp_mixer_free(ctl->mixer_left);
-	if (ctl->mixer_right)
+	if (ctl->mixer_right) {
+		pr_err("right mixer already setup for ctl=%d\n", ctl->num);
+		return -EPERM;
+	}
+
+	sctl = mdss_mdp_ctl_init(pdata, ctl->mfd);
+	if (!sctl) {
+		pr_err("unable to setup split display\n");
+		return -ENODEV;
+	}
+
+	sctl->width = pdata->panel_info.xres;
+	sctl->height = pdata->panel_info.yres;
+
+	ctl->mixer_left = mdss_mdp_mixer_alloc(ctl, MDSS_MDP_MIXER_TYPE_INTF);
+	if (!ctl->mixer_left) {
+		pr_err("unable to allocate layer mixer\n");
+		mdss_mdp_ctl_destroy(sctl);
+		return -ENOMEM;
+	}
+
+	mixer = mdss_mdp_mixer_alloc(sctl, MDSS_MDP_MIXER_TYPE_INTF);
+	if (!mixer) {
+		pr_err("unable to allocate layer mixer\n");
+		mdss_mdp_ctl_destroy(sctl);
+		return -ENOMEM;
+	}
+
+	mixer->width = sctl->width;
+	mixer->height = sctl->height;
+	sctl->mixer_left = mixer;
+
+	return mdss_mdp_set_split_ctl(ctl, sctl);
+}
+
+static void mdss_mdp_ctl_split_display_enable(int enable,
+	struct mdss_mdp_ctl *main_ctl, struct mdss_mdp_ctl *slave_ctl)
+{
+	u32 upper = 0, lower = 0;
+
+	pr_debug("split main ctl=%d intf=%d slave ctl=%d intf=%d\n",
+			main_ctl->num, main_ctl->intf_num,
+			slave_ctl->num, slave_ctl->intf_num);
+	if (enable) {
+		if (main_ctl->opmode & MDSS_MDP_CTL_OP_CMD_MODE) {
+			upper |= BIT(1);
+			lower |= BIT(1);
+
+			/* interface controlling sw trigger */
+			if (main_ctl->intf_num == MDSS_MDP_INTF2)
+				upper |= BIT(4);
+			else
+				upper |= BIT(8);
+		} else { /* video mode */
+			if (main_ctl->intf_num == MDSS_MDP_INTF2)
+				lower |= BIT(4);
+			else
+				lower |= BIT(8);
+		}
+	}
+	MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTRL, upper);
+	MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTRL, lower);
+	MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SPLIT_DISPLAY_EN, enable);
+}
+
+
+int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_mdp_ctl *sctl;
+	int rc;
+
+	rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CLOSE, NULL);
+	WARN(rc, "unable to close panel for intf=%d\n", ctl->intf_num);
+
+	sctl = mdss_mdp_get_split_ctl(ctl);
+	if (sctl) {
+		pr_debug("destroying split display ctl=%d\n", sctl->num);
+		if (sctl->mixer_left)
+			mdss_mdp_mixer_free(sctl->mixer_left);
+		mdss_mdp_ctl_free(sctl);
+	} else if (ctl->mixer_right) {
 		mdss_mdp_mixer_free(ctl->mixer_right);
+		ctl->mixer_right = NULL;
+	}
+
+	if (ctl->mixer_left) {
+		mdss_mdp_mixer_free(ctl->mixer_left);
+		ctl->mixer_left = NULL;
+	}
 	mdss_mdp_ctl_free(ctl);
 
 	return 0;
@@ -558,6 +695,8 @@
 int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg)
 {
 	struct mdss_panel_data *pdata;
+	int rc = 0;
+
 	if (!ctl || !ctl->panel_data)
 		return -ENODEV;
 
@@ -565,51 +704,21 @@
 
 	pr_debug("sending ctl=%d event=%d\n", ctl->num, event);
 
-	if (pdata->event_handler)
-		return pdata->event_handler(pdata, event, arg);
+	do {
+		if (pdata->event_handler)
+			rc = pdata->event_handler(pdata, event, arg);
+		pdata = pdata->next;
+	} while (rc == 0 && pdata);
 
-	return 0;
+	return rc;
 }
 
-int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
+static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl)
 {
-	struct mdss_mdp_ctl *ctl;
 	struct mdss_mdp_mixer *mixer;
-	u32 outsize, temp, off;
+	u32 outsize, temp;
 	int ret = 0;
 
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (mdss_mdp_ctl_init(mfd)) {
-		pr_err("unable to initialize ctl\n");
-		return -ENODEV;
-	}
-
-	ctl = mfd->ctl;
-
-	if (ctl->power_on) {
-		WARN(1, "already on!\n");
-		return 0;
-	}
-
-	mutex_lock(&ctl->lock);
-
-	ctl->power_on = true;
-	ctl->bus_ab_quota = 0;
-	ctl->bus_ib_quota = 0;
-	ctl->clk_rate = 0;
-
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-	ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_RESET, NULL);
-	if (ret) {
-		pr_err("panel power on failed ctl=%d\n", ctl->num);
-		goto start_fail;
-	}
-
 	if (ctl->start_fnc)
 		ret = ctl->start_fnc(ctl);
 	else
@@ -618,70 +727,94 @@
 
 	if (ret) {
 		pr_err("unable to start intf\n");
-		goto start_fail;
+		return ret;
 	}
 
 	pr_debug("ctl_num=%d\n", ctl->num);
 
 	mixer = ctl->mixer_left;
+	mdss_mdp_pp_resume(mixer->num);
 	mixer->params_changed++;
 
 	temp = MDSS_MDP_REG_READ(MDSS_MDP_REG_DISP_INTF_SEL);
 	temp |= (ctl->intf_type << ((ctl->intf_num - MDSS_MDP_INTF0) * 8));
 	MDSS_MDP_REG_WRITE(MDSS_MDP_REG_DISP_INTF_SEL, temp);
 
-	if (ctl->intf_num != MDSS_MDP_NO_INTF) {
-		off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
-		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_PANEL_FORMAT,
-				   ctl->dst_format);
-	}
-
 	outsize = (mixer->height << 16) | mixer->width;
-	off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, outsize);
-
-	if (ctl->mixer_right) {
-		mixer = ctl->mixer_right;
-		mixer->params_changed++;
-		outsize = (mixer->height << 16) | mixer->width;
-		off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
-		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, outsize);
-		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
-	}
-
-start_fail:
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-	mutex_unlock(&ctl->lock);
-	if (ret)
-		mdss_mdp_ctl_destroy(mfd);
+	mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, outsize);
 
 	return ret;
 }
 
-int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd)
+int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl)
 {
-	struct mdss_mdp_ctl *ctl;
+	struct mdss_mdp_ctl *sctl;
 	int ret = 0;
 
-	if (!mfd)
-		return -ENODEV;
+	ret = mdss_mdp_ctl_setup(ctl);
+	if (ret)
+		return ret;
 
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (!mfd->ctl) {
-		pr_err("ctl not initialized\n");
-		return -ENODEV;
+	if (ctl->power_on) {
+		WARN(1, "already on!\n");
+		return 0;
 	}
 
-	ctl = mfd->ctl;
+	sctl = mdss_mdp_get_split_ctl(ctl);
+
+	mutex_lock(&ctl->lock);
+
+	ctl->power_on = true;
+	ctl->bus_ab_quota = 0;
+	ctl->bus_ib_quota = 0;
+	ctl->clk_rate = 0;
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_RESET, NULL);
+	if (ret) {
+		pr_err("panel power on failed ctl=%d\n", ctl->num);
+		return ret;
+	}
+
+	ret = mdss_mdp_ctl_start_sub(ctl);
+	if (ret == 0) {
+		if (sctl) { /* split display is available */
+			ret = mdss_mdp_ctl_start_sub(sctl);
+			if (!ret)
+				mdss_mdp_ctl_split_display_enable(1, ctl, sctl);
+		} else if (ctl->mixer_right) {
+			struct mdss_mdp_mixer *mixer = ctl->mixer_right;
+			u32 out, off;
+
+			mdss_mdp_pp_resume(mixer->num);
+			mixer->params_changed++;
+			out = (mixer->height << 16) | mixer->width;
+			off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
+			MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, out);
+			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
+		}
+	}
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	mutex_unlock(&ctl->lock);
+
+	return ret;
+}
+
+int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_mdp_ctl *sctl;
+	int ret = 0;
 
 	if (!ctl->power_on) {
 		WARN(1, "already off!\n");
 		return 0;
 	}
 
-	pr_debug("ctl_num=%d\n", mfd->ctl->num);
+	sctl = mdss_mdp_get_split_ctl(ctl);
+
+	pr_debug("ctl_num=%d\n", ctl->num);
 
 	mutex_lock(&ctl->lock);
 
@@ -692,6 +825,12 @@
 	else
 		pr_warn("no stop func for ctl=%d\n", ctl->num);
 
+	if (sctl && sctl->stop_fnc) {
+		ret = sctl->stop_fnc(sctl);
+
+		mdss_mdp_ctl_split_display_enable(0, ctl, sctl);
+	}
+
 	if (ret) {
 		pr_warn("error powering off intf ctl=%d\n", ctl->num);
 	} else {
@@ -706,19 +845,13 @@
 			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(
 					ctl->mixer_right->num), 0);
 		}
-		mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
+		mdss_mdp_ctl_perf_commit(ctl->mdata, MDSS_MDP_PERF_UPDATE_ALL);
 	}
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
 	mutex_unlock(&ctl->lock);
 
-	if (!ret && !mfd->ref_cnt) {
-		ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CLOSE, NULL);
-		WARN(ret, "unable to close intf %d\n", ctl->intf_num);
-		mdss_mdp_ctl_destroy(mfd);
-	}
-
 	return ret;
 }
 
@@ -755,8 +888,7 @@
 		}
 
 		blend_stage = stage - MDSS_MDP_STAGE_0;
-		off = MDSS_MDP_REG_LM_OFFSET(mixer->num) +
-		      MDSS_MDP_REG_LM_BLEND_OFFSET(blend_stage);
+		off = MDSS_MDP_REG_LM_BLEND_OFFSET(blend_stage);
 
 		if (pipe->is_fg) {
 			bgalpha = 0;
@@ -802,10 +934,10 @@
 
 		mixercfg |= stage << (3 * pipe->num);
 
-		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OP_MODE, blend_op);
-		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_BLEND_FG_ALPHA,
+		mdp_mixer_write(mixer, off + MDSS_MDP_REG_LM_OP_MODE, blend_op);
+		mdp_mixer_write(mixer, off + MDSS_MDP_REG_LM_BLEND_FG_ALPHA,
 				   pipe->alpha);
-		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_BLEND_BG_ALPHA,
+		mdp_mixer_write(mixer, off + MDSS_MDP_REG_LM_BLEND_BG_ALPHA,
 				   0xFF - pipe->alpha);
 	}
 
@@ -817,12 +949,82 @@
 	ctl->flush_bits |= BIT(6) << mixer->num;	/* LAYER_MIXER */
 
 	off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OP_MODE, blend_color_out);
+	mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OP_MODE, blend_color_out);
 	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(mixer->num), mixercfg);
 
 	return 0;
 }
 
+int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata,
+	 u32 *mixer_offsets, u32 *dspp_offsets, u32 type, u32 len)
+{
+	struct mdss_mdp_mixer *head;
+	u32 i;
+	int rc = 0;
+
+	head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_mixer) *
+			len, GFP_KERNEL);
+
+	if (!head) {
+		pr_err("unable to setup mixer type=%d :kzalloc fail\n",
+			type);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < len; i++) {
+		head[i].type = type;
+		head[i].base = mdata->mdp_base + mixer_offsets[i];
+		head[i].ref_cnt = 0;
+		head[i].num = i;
+		if (type == MDSS_MDP_MIXER_TYPE_INTF)
+			head[i].dspp_base = mdata->mdp_base + dspp_offsets[i];
+	}
+
+	switch (type) {
+
+	case MDSS_MDP_MIXER_TYPE_INTF:
+		mdata->mixer_intf = head;
+		break;
+
+	case MDSS_MDP_MIXER_TYPE_WRITEBACK:
+		mdata->mixer_wb = head;
+		break;
+
+	default:
+		pr_err("Invalid mixer type=%d\n", type);
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+
+int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata,
+	u32 *ctl_offsets, u32 *wb_offsets, u32 len)
+{
+	struct mdss_mdp_ctl *head;
+	u32 i;
+
+	head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_ctl) *
+			len, GFP_KERNEL);
+
+	if (!head) {
+		pr_err("unable to setup ctl and wb: kzalloc fail\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < len; i++) {
+		head[i].num = i;
+		head[i].base = (mdata->mdp_base) + ctl_offsets[i];
+		head[i].wb_base = (mdata->mdp_base) + wb_offsets[i];
+		head[i].ref_cnt = 0;
+	}
+
+	mdata->ctl_off = head;
+
+	return 0;
+}
+
 struct mdss_mdp_mixer *mdss_mdp_mixer_get(struct mdss_mdp_ctl *ctl, int mux)
 {
 	struct mdss_mdp_mixer *mixer = NULL;
@@ -942,6 +1144,7 @@
 
 int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
 {
+	struct mdss_mdp_ctl *sctl = NULL;
 	int mixer1_changed, mixer2_changed;
 	int ret = 0;
 	int perf_update = MDSS_MDP_PERF_UPDATE_SKIP;
@@ -963,6 +1166,8 @@
 		return 0;
 	}
 
+	sctl = mdss_mdp_get_split_ctl(ctl);
+
 	mixer1_changed = (ctl->mixer_left && ctl->mixer_left->params_changed);
 	mixer2_changed = (ctl->mixer_right && ctl->mixer_right->params_changed);
 
@@ -978,7 +1183,7 @@
 		}
 
 		if (perf_update == MDSS_MDP_PERF_UPDATE_EARLY)
-			mdss_mdp_ctl_perf_commit(update_flags);
+			mdss_mdp_ctl_perf_commit(ctl->mdata, update_flags);
 
 		if (mixer1_changed)
 			mdss_mdp_mixer_update(ctl->mixer_left);
@@ -987,11 +1192,22 @@
 
 		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, ctl->opmode);
 		ctl->flush_bits |= BIT(17);	/* CTL */
+
+		if (sctl) {
+			mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_TOP,
+					sctl->opmode);
+			sctl->flush_bits |= BIT(17);
+		}
 	}
 
 	/* postprocessing setup, including dspp */
 	mdss_mdp_pp_setup(ctl);
 	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
+	if (sctl) {
+		mdss_mdp_pp_setup(sctl);
+		mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH,
+			sctl->flush_bits);
+	}
 	wmb();
 	ctl->flush_bits = 0;
 
@@ -1003,7 +1219,7 @@
 	ctl->play_cnt++;
 
 	if (perf_update == MDSS_MDP_PERF_UPDATE_LATE)
-		mdss_mdp_ctl_perf_commit(update_flags);
+		mdss_mdp_ctl_perf_commit(ctl->mdata, update_flags);
 
 done:
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
@@ -1017,10 +1233,12 @@
 {
 	int i;
 	struct mdss_mdp_ctl *ctl;
+	struct mdss_data_type *mdata;
 	u32 mixer_cnt = 0;
 	mutex_lock(&mdss_mdp_ctl_lock);
-	for (i = 0; i < MDSS_MDP_MAX_CTL; i++) {
-		ctl = &mdss_mdp_ctl_list[i];
+	mdata = mdss_mdp_get_mdata();
+	for (i = 0; i < mdata->nctl; i++) {
+		ctl = mdata->ctl_off + i;
 		if ((ctl->power_on) && (ctl->mfd) &&
 			(ctl->mfd->index == fb_num)) {
 			if (ctl->mixer_left) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index d2b2eab..1c5c4b8 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -16,6 +16,14 @@
 
 #include <linux/bitops.h>
 
+#define IGC_LUT_ENTRIES	256
+#define GC_LUT_SEGMENTS	16
+#define ENHIST_LUT_ENTRIES 256
+#define HIST_V_SIZE	256
+
+#define MDSS_MDP_HW_REV_100		0x10000000
+#define MDSS_MDP_HW_REV_102		0x10020000
+
 #define MDSS_REG_HW_VERSION				0x0
 #define MDSS_REG_HW_INTR_STATUS				0x10
 
@@ -34,6 +42,10 @@
 #define MDSS_MDP_REG_HIST_INTR_STATUS			0x00120
 #define MDSS_MDP_REG_HIST_INTR_CLEAR			0x00124
 
+#define MDSS_MDP_REG_SPLIT_DISPLAY_EN			0x003F4
+#define MDSS_MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTRL	0x003F8
+#define MDSS_MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTRL	0x004F0
+
 #define MDSS_INTF_DSI	0x1
 #define MDSS_INTF_HDMI	0x3
 #define MDSS_INTF_LCDC	0x5
@@ -156,6 +168,9 @@
 #define MDSS_MDP_REG_SSPP_SRC_OP_MODE			0x038
 #define MDSS_MDP_OP_DEINTERLACE			BIT(22)
 #define MDSS_MDP_OP_DEINTERLACE_ODD		BIT(23)
+#define MDSS_MDP_OP_IGC_ROM_1			BIT(18)
+#define MDSS_MDP_OP_IGC_ROM_0			BIT(17)
+#define MDSS_MDP_OP_IGC_EN			BIT(16)
 #define MDSS_MDP_OP_FLIP_UD			BIT(14)
 #define MDSS_MDP_OP_FLIP_LR			BIT(13)
 #define MDSS_MDP_OP_BWC_EN			BIT(0)
@@ -185,6 +200,7 @@
 #define MDSS_MDP_REG_VIG_QSEED2_C03_INIT_PHASEY		0x224
 #define MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEX		0x228
 #define MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEY		0x22C
+#define MDSS_MDP_REG_VIG_QSEED2_SHARP			0x230
 #define MDSS_MDP_REG_VIG_PA_BASE			0x310
 
 #define MDSS_MDP_REG_SCALE_CONFIG			0x204
@@ -209,13 +225,17 @@
 #define MDSS_MDP_NUM_REG_MIXERS 3
 #define MDSS_MDP_NUM_WB_MIXERS 2
 
-enum mdss_mdp_mixer_index {
-	MDSS_MDP_LAYERMIXER0,
-	MDSS_MDP_LAYERMIXER1,
-	MDSS_MDP_LAYERMIXER2,
-	MDSS_MDP_LAYERMIXER3,
-	MDSS_MDP_LAYERMIXER4,
-	MDSS_MDP_MAX_LAYERMIXER
+enum mdss_mdp_mixer_intf_index {
+	MDSS_MDP_INTF_LAYERMIXER0,
+	MDSS_MDP_INTF_LAYERMIXER1,
+	MDSS_MDP_INTF_LAYERMIXER2,
+	MDSS_MDP_INTF_MAX_LAYERMIXER,
+};
+
+enum mdss_mdp_mixer_wb_index {
+	MDSS_MDP_WB_LAYERMIXER0,
+	MDSS_MDP_WB_LAYERMIXER1,
+	MDSS_MDP_WB_MAX_LAYERMIXER,
 };
 
 enum mdss_mdp_stage_index {
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index a6a6d59..1aea4e0 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -38,9 +38,10 @@
 	u32 hsync_skew;
 };
 
-#define MAX_SESSIONS 3
 struct mdss_mdp_video_ctx {
-	u32 pp_num;
+	u32 intf_num;
+	char __iomem *base;
+	u32 intf_type;
 	u8 ref_cnt;
 
 	u8 timegen_en;
@@ -51,9 +52,37 @@
 	mdp_vsync_handler_t vsync_handler;
 };
 
-struct mdss_mdp_video_ctx mdss_mdp_video_ctx_list[MAX_SESSIONS];
+static inline void mdp_video_write(struct mdss_mdp_video_ctx *ctx,
+				   u32 reg, u32 val)
+{
+	writel_relaxed(val, ctx->base + reg);
+}
 
-static int mdss_mdp_video_timegen_setup(struct mdss_mdp_ctl *ctl,
+int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata,
+				u32 *offsets,  u32 count)
+{
+	struct mdss_mdp_video_ctx *head;
+	u32 i;
+
+	head = devm_kzalloc(&mdata->pdev->dev,
+			sizeof(struct mdss_mdp_video_ctx) * count, GFP_KERNEL);
+	if (!head)
+		return -ENOMEM;
+
+	for (i = 0; i < count; i++) {
+		head[i].base = mdata->mdp_base + offsets[i];
+		pr_debug("adding Video Intf #%d offset=0x%x virt=%p\n", i,
+				offsets[i], head[i].base);
+		head[i].ref_cnt = 0;
+		head[i].intf_num = i + MDSS_MDP_INTF0;
+	}
+
+	mdata->video_intf = head;
+	mdata->nintf = count;
+	return 0;
+}
+
+static int mdss_mdp_video_timegen_setup(struct mdss_mdp_video_ctx *ctx,
 					struct intf_timing_params *p)
 {
 	u32 hsync_period, vsync_period;
@@ -61,9 +90,6 @@
 	u32 active_h_start, active_h_end, active_v_start, active_v_end;
 	u32 den_polarity, hsync_polarity, vsync_polarity;
 	u32 display_hctl, active_hctl, hsync_ctl, polarity_ctl;
-	int off;
-
-	off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
 
 	hsync_period = p->hsync_pulse_width + p->h_back_porch +
 			p->width + p->h_front_porch;
@@ -75,7 +101,7 @@
 	display_v_end = ((vsync_period - p->v_front_porch) * hsync_period) +
 			p->hsync_skew - 1;
 
-	if (ctl->intf_type == MDSS_INTF_EDP) {
+	if (ctx->intf_type == MDSS_INTF_EDP) {
 		display_v_start += p->hsync_pulse_width + p->h_back_porch;
 		display_v_end -= p->h_front_porch;
 	}
@@ -114,7 +140,7 @@
 	display_hctl = (hsync_end_x << 16) | hsync_start_x;
 
 	den_polarity = 0;
-	if (MDSS_INTF_HDMI ==  ctl->intf_type) {
+	if (MDSS_INTF_HDMI == ctx->intf_type) {
 		hsync_polarity = p->yres >= 720 ? 0 : 1;
 		vsync_polarity = p->yres >= 720 ? 0 : 1;
 	} else {
@@ -125,31 +151,25 @@
 		       (vsync_polarity << 1) | /* VSYNC Polarity */
 		       (hsync_polarity << 0);  /* HSYNC Polarity */
 
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_HSYNC_CTL, hsync_ctl);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0,
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_HSYNC_CTL, hsync_ctl);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0,
 			   vsync_period * hsync_period);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_VSYNC_PULSE_WIDTH_F0,
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PULSE_WIDTH_F0,
 			   p->vsync_pulse_width * hsync_period);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_DISPLAY_HCTL,
-			   display_hctl);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_DISPLAY_V_START_F0,
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_DISPLAY_HCTL, display_hctl);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_DISPLAY_V_START_F0,
 			   display_v_start);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_DISPLAY_V_END_F0,
-			   display_v_end);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_ACTIVE_HCTL, active_hctl);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_ACTIVE_V_START_F0,
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_DISPLAY_V_END_F0, display_v_end);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_ACTIVE_HCTL, active_hctl);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_ACTIVE_V_START_F0,
 			   active_v_start);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_ACTIVE_V_END_F0,
-			   active_v_end);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_ACTIVE_V_END_F0, active_v_end);
 
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_BORDER_COLOR,
-			   p->border_clr);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_UNDERFLOW_COLOR,
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_BORDER_COLOR, p->border_clr);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_UNDERFLOW_COLOR,
 			   p->underflow_clr);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_HSYNC_SKEW,
-			   p->hsync_skew);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_POLARITY_CTL,
-			   polarity_ctl);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_HSYNC_SKEW, p->hsync_skew);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_POLARITY_CTL, polarity_ctl);
 
 	return 0;
 }
@@ -198,7 +218,7 @@
 static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)
 {
 	struct mdss_mdp_video_ctx *ctx;
-	int rc, off;
+	int rc;
 
 	pr_debug("stop ctl=%d\n", ctl->num);
 
@@ -217,8 +237,7 @@
 		}
 		WARN(rc, "intf %d blank error (%d)\n", ctl->intf_num, rc);
 
-		off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
-		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
+		mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 		ctx->timegen_en = false;
 
@@ -230,10 +249,8 @@
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
 				   NULL, NULL);
-	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
-				   NULL, NULL);
 
-	memset(ctx, 0, sizeof(*ctx));
+	ctx->ref_cnt--;
 
 	return 0;
 }
@@ -276,15 +293,13 @@
 	video_vsync_irq_enable(ctl);
 
 	if (!ctx->timegen_en) {
-		int off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
-
 		rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_UNBLANK, NULL);
 		WARN(rc, "intf %d unblank error (%d)\n", ctl->intf_num, rc);
 
 		pr_debug("enabling timing gen for intf=%d\n", ctl->intf_num);
 
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
+		mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
 		wmb();
 	}
 
@@ -305,12 +320,14 @@
 
 int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl)
 {
+	struct mdss_data_type *mdata;
 	struct mdss_panel_info *pinfo;
 	struct mdss_mdp_video_ctx *ctx;
 	struct mdss_mdp_mixer *mixer;
 	struct intf_timing_params itp = {0};
 	int i;
 
+	mdata = ctl->mdata;
 	pinfo = &ctl->panel_data->panel_info;
 	mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
 
@@ -319,21 +336,24 @@
 		return -ENODEV;
 	}
 
+	i = ctl->intf_num - MDSS_MDP_INTF0;
+	if (i < mdata->nintf) {
+		ctx = ((struct mdss_mdp_video_ctx *) mdata->video_intf) + i;
+		if (ctx->ref_cnt) {
+			pr_err("Intf %d already in use\n", ctl->intf_num);
+			return -EBUSY;
+		}
+		pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base);
+		ctx->ref_cnt++;
+	} else {
+		pr_err("Invalid intf number: %d\n", ctl->intf_num);
+		return -EINVAL;
+	}
+
 	pr_debug("start ctl=%u\n", ctl->num);
 
-	for (i = 0; i < MAX_SESSIONS; i++) {
-		ctx = &mdss_mdp_video_ctx_list[i];
-		if (ctx->ref_cnt == 0) {
-			ctx->ref_cnt++;
-			break;
-		}
-	}
-	if (i == MAX_SESSIONS) {
-		pr_err("too many sessions\n");
-		return -ENOMEM;
-	}
 	ctl->priv_data = ctx;
-	ctx->pp_num = mixer->num;
+	ctx->intf_type = ctl->intf_type;
 	init_completion(&ctx->vsync_comp);
 	spin_lock_init(&ctx->vsync_lock);
 	atomic_set(&ctx->vsync_ref, 0);
@@ -356,10 +376,11 @@
 	itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width;
 	itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width;
 
-	if (mdss_mdp_video_timegen_setup(ctl, &itp)) {
+	if (mdss_mdp_video_timegen_setup(ctx, &itp)) {
 		pr_err("unable to get timing parameters\n");
 		return -EINVAL;
 	}
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_PANEL_FORMAT, ctl->dst_format);
 
 	ctl->stop_fnc = mdss_mdp_video_stop;
 	ctl->display_fnc = mdss_mdp_video_display;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 2c0ddda..97428cd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -27,6 +27,7 @@
 
 struct mdss_mdp_writeback_ctx {
 	u32 wb_num;
+	char __iomem *base;
 	u8 ref_cnt;
 	u8 type;
 
@@ -75,10 +76,16 @@
 	},
 };
 
+static inline void mdp_wb_write(struct mdss_mdp_writeback_ctx *ctx,
+				u32 reg, u32 val)
+{
+	writel_relaxed(val, ctx->base + reg);
+}
+
 static int mdss_mdp_writeback_addr_setup(struct mdss_mdp_writeback_ctx *ctx,
 					 struct mdss_mdp_data *data)
 {
-	int off, ret;
+	int ret;
 
 	if (!data)
 		return -EINVAL;
@@ -89,11 +96,10 @@
 	if (ret)
 		return ret;
 
-	off = MDSS_MDP_REG_WB_OFFSET(ctx->wb_num);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST0_ADDR, data->p[0].addr);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST1_ADDR, data->p[1].addr);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST2_ADDR, data->p[2].addr);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST3_ADDR, data->p[3].addr);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST0_ADDR, data->p[0].addr);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST1_ADDR, data->p[1].addr);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST2_ADDR, data->p[2].addr);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST3_ADDR, data->p[3].addr);
 
 	return 0;
 }
@@ -102,8 +108,8 @@
 {
 	struct mdss_mdp_format_params *fmt;
 	u32 dst_format, pattern, ystride0, ystride1, outsize, chroma_samp;
-	int off;
 	u32 opmode = ctx->opmode;
+	struct mdss_data_type *mdata;
 
 	pr_debug("wb_num=%d format=%d\n", ctx->wb_num, ctx->format);
 
@@ -157,8 +163,19 @@
 	}
 
 	if (fmt->fetch_planes != MDSS_MDP_PLANE_PLANAR) {
-		pattern = (fmt->element[3] << 24) | (fmt->element[2] << 15) |
-			(fmt->element[1] << 8) | (fmt->element[0] << 0);
+		mdata = mdss_mdp_get_mdata();
+		if (mdata && mdata->mdp_rev >= MDSS_MDP_HW_REV_102) {
+			pattern = (fmt->element[3] << 24) |
+				  (fmt->element[2] << 16) |
+				  (fmt->element[1] << 8)  |
+				  (fmt->element[0] << 0);
+		} else {
+			pattern = (fmt->element[3] << 24) |
+				  (fmt->element[2] << 15) |
+				  (fmt->element[1] << 8)  |
+				  (fmt->element[0] << 0);
+		}
+
 		dst_format |= (fmt->unpack_align_msb << 18) |
 			      (fmt->unpack_tight << 17) |
 			      ((fmt->unpack_count - 1) << 12) |
@@ -173,13 +190,12 @@
 		   (ctx->dst_planes.ystride[3] << 16);
 	outsize = (ctx->height << 16) | ctx->width;
 
-	off = MDSS_MDP_REG_WB_OFFSET(ctx->wb_num);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_FORMAT, dst_format);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_OP_MODE, opmode);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_PACK_PATTERN, pattern);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_YSTRIDE0, ystride0);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_DST_YSTRIDE1, ystride1);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_WB_OUT_SIZE, outsize);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_FORMAT, dst_format);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_OP_MODE, opmode);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_PACK_PATTERN, pattern);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_YSTRIDE0, ystride0);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_YSTRIDE1, ystride1);
+	mdp_wb_write(ctx, MDSS_MDP_REG_WB_OUT_SIZE, outsize);
 
 	return 0;
 }
@@ -352,6 +368,7 @@
 	}
 	ctl->priv_data = ctx;
 	ctx->wb_num = ctl->num;	/* wb num should match ctl num */
+	ctx->base = ctl->wb_base;
 	ctx->initialized = false;
 
 	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 3956228..283d3f0 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -39,7 +39,7 @@
 {
 	struct mdss_mdp_pipe *pipe;
 
-	pipe = mdss_mdp_pipe_get(req->id);
+	pipe = mdss_mdp_pipe_get(mfd->mdata, req->id);
 	if (IS_ERR_OR_NULL(pipe)) {
 		pr_err("invalid pipe ndx=%x\n", req->id);
 		return pipe ? PTR_ERR(pipe) : -ENODEV;
@@ -232,7 +232,7 @@
 	struct mdss_mdp_format_params *fmt;
 	struct mdss_mdp_pipe *pipe;
 	struct mdss_mdp_mixer *mixer = NULL;
-	u32 pipe_type, mixer_mux;
+	u32 pipe_type, mixer_mux, len;
 	int ret;
 
 	if (mfd == NULL || mfd->ctl == NULL)
@@ -280,12 +280,12 @@
 		else
 			pipe_type = MDSS_MDP_PIPE_TYPE_RGB;
 
-		pipe = mdss_mdp_pipe_alloc(pipe_type);
+		pipe = mdss_mdp_pipe_alloc(mixer, pipe_type);
 
 		/* VIG pipes can also support RGB format */
 		if (!pipe && pipe_type == MDSS_MDP_PIPE_TYPE_RGB) {
 			pipe_type = MDSS_MDP_PIPE_TYPE_VIG;
-			pipe = mdss_mdp_pipe_alloc(pipe_type);
+			pipe = mdss_mdp_pipe_alloc(mixer, pipe_type);
 		}
 
 		if (pipe == NULL) {
@@ -306,7 +306,7 @@
 		pipe->mfd = mfd;
 		pipe->play_cnt = 0;
 	} else {
-		pipe = mdss_mdp_pipe_get(req->id);
+		pipe = mdss_mdp_pipe_get(mfd->mdata, req->id);
 		if (IS_ERR_OR_NULL(pipe)) {
 			pr_err("invalid pipe ndx=%x\n", req->id);
 			return pipe ? PTR_ERR(pipe) : -ENODEV;
@@ -337,12 +337,25 @@
 	pipe->req_data = *req;
 
 	if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
-		if (pipe->num <= MDSS_MDP_SSPP_VIG2)
-			memcpy(&pipe->pp_cfg, &req->overlay_pp_cfg,
+		memcpy(&pipe->pp_cfg, &req->overlay_pp_cfg,
 					sizeof(struct mdp_overlay_pp_params));
-		else
-			pr_debug("%s: RGB Pipes don't support CSC/QSEED\n",
-								__func__);
+		len = pipe->pp_cfg.igc_cfg.len;
+		if ((pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_IGC_CFG) &&
+						(len == IGC_LUT_ENTRIES)) {
+			ret = copy_from_user(pipe->pp_res.igc_c0_c1,
+					pipe->pp_cfg.igc_cfg.c0_c1_data,
+					sizeof(uint32_t) * len);
+			if (ret)
+				return -ENOMEM;
+			ret = copy_from_user(pipe->pp_res.igc_c2,
+					pipe->pp_cfg.igc_cfg.c2_data,
+					sizeof(uint32_t) * len);
+			if (ret)
+				return -ENOMEM;
+			pipe->pp_cfg.igc_cfg.c0_c1_data =
+							pipe->pp_res.igc_c0_c1;
+			pipe->pp_cfg.igc_cfg.c2_data = pipe->pp_res.igc_c2;
+		}
 	}
 
 	if (pipe->flags & MDP_DEINTERLACE) {
@@ -505,7 +518,7 @@
 		pipe_ndx = BIT(i);
 		if (pipe_ndx & ndx) {
 			unset_ndx |= pipe_ndx;
-			pipe = mdss_mdp_pipe_get(pipe_ndx);
+			pipe = mdss_mdp_pipe_get(mfd->mdata, pipe_ndx);
 			if (IS_ERR_OR_NULL(pipe)) {
 				pr_warn("unknown pipe ndx=%x\n", pipe_ndx);
 				continue;
@@ -646,7 +659,7 @@
 	int ret;
 	u32 flags;
 
-	pipe = mdss_mdp_pipe_get(req->id);
+	pipe = mdss_mdp_pipe_get(mfd->mdata, req->id);
 	if (IS_ERR_OR_NULL(pipe)) {
 		pr_err("pipe ndx=%x doesn't exist\n", req->id);
 		return pipe ? PTR_ERR(pipe) : -ENODEV;
@@ -731,8 +744,7 @@
 
 	if (fb_ndx) {
 		pr_debug("unstaging framebuffer pipes %x\n", fb_ndx);
-		mdss_mdp_overlay_unset(mfd, fb_ndx);
-		mdss_mdp_overlay_kickoff(mfd->ctl);
+		mdss_mdp_overlay_release(mfd, fb_ndx);
 	}
 	return 0;
 }
@@ -863,7 +875,7 @@
 		return;
 	}
 
-	if (fbi->var.xres > MAX_MIXER_WIDTH) {
+	if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
 		ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
 						   MDSS_MDP_MIXER_MUX_RIGHT);
 		if (ret) {
@@ -883,7 +895,8 @@
 	}
 	mutex_unlock(&mfd->ov_lock);
 
-	if (fbi->var.activate & FB_ACTIVATE_VBL)
+	if ((fbi->var.activate & FB_ACTIVATE_VBL) ||
+	    (fbi->var.activate & FB_ACTIVATE_FORCE))
 		mdss_mdp_overlay_kickoff(mfd->ctl);
 }
 
@@ -971,9 +984,9 @@
 	ret = wait_for_completion_interruptible_timeout(&mfd->vsync_comp,
 			timeout);
 	if (ret <= 0) {
-		pr_warn("vsync wait on fb%d interrupted (%d)\n",
-			mfd->index, ret);
-		return -EBUSY;
+		pr_warn("Sending current time as vsync timestamp for fb%d\n",
+				mfd->index);
+		mfd->vsync_time = ktime_get();
 	}
 
 	spin_lock_irqsave(&mfd->vsync_lock, flags);
@@ -1244,9 +1257,47 @@
 {
 	int rc;
 
-	rc = mdss_mdp_ctl_on(mfd);
-	if (rc == 0)
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (!mfd->ctl) {
+		struct mdss_mdp_ctl *ctl;
+		struct mdss_panel_data *pdata;
+
+		pdata = dev_get_platdata(&mfd->pdev->dev);
+		if (!pdata) {
+			pr_err("no panel connected for fb%d\n", mfd->index);
+			return -ENODEV;
+		}
+
+		ctl = mdss_mdp_ctl_init(pdata, mfd);
+		if (IS_ERR_OR_NULL(ctl)) {
+			pr_err("Unable to initialize ctl for fb%d\n",
+				mfd->index);
+			return PTR_ERR(ctl);
+		}
+
+		if (mfd->split_display && pdata->next) {
+			/* enable split display */
+			rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next);
+			if (rc) {
+				mdss_mdp_ctl_destroy(ctl);
+				return rc;
+			}
+		}
+		mfd->ctl = ctl;
+	}
+
+	rc = mdss_mdp_ctl_start(mfd->ctl);
+	if (rc == 0) {
 		atomic_inc(&ov_active_panels);
+	} else {
+		mdss_mdp_ctl_destroy(mfd->ctl);
+		mfd->ctl = NULL;
+	}
 
 	return rc;
 }
@@ -1255,12 +1306,26 @@
 {
 	int rc;
 
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (!mfd->ctl) {
+		pr_err("ctl not initialized\n");
+		return -ENODEV;
+	}
+
 	mdss_mdp_overlay_release_all(mfd);
 
-	rc = mdss_mdp_ctl_off(mfd);
+	rc = mdss_mdp_ctl_stop(mfd->ctl);
 	if (rc == 0) {
-		if (!mfd->ref_cnt)
+		if (!mfd->ref_cnt) {
 			mfd->borderfill_enable = false;
+			mdss_mdp_ctl_destroy(mfd->ctl);
+			mfd->ctl = NULL;
+		}
 
 		if (atomic_dec_return(&ov_active_panels) == 0)
 			mdss_mdp_rotator_release_all();
@@ -1274,6 +1339,12 @@
 	struct device *dev = mfd->fbi->dev;
 	int rc;
 
+	mfd->mdata = dev_get_drvdata(mfd->pdev->dev.parent);
+	if (!mfd->mdata) {
+		pr_err("unable to initialize overlay for fb%d\n", mfd->index);
+		return -ENODEV;
+	}
+
 	mfd->on_fnc = mdss_mdp_overlay_on;
 	mfd->off_fnc = mdss_mdp_overlay_off;
 	mfd->hw_refresh = true;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 4ece15d..0a52561 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -25,8 +25,8 @@
 static DEFINE_MUTEX(mdss_mdp_smp_lock);
 static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
 
-static struct mdss_mdp_pipe mdss_mdp_pipe_list[MDSS_MDP_MAX_SSPP];
-
+static struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
+						  u32 ndx);
 static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
 
 static u32 mdss_mdp_smp_mmb_reserve(unsigned long *smp, size_t n)
@@ -119,42 +119,10 @@
 
 static int mdss_mdp_smp_alloc(struct mdss_mdp_pipe *pipe)
 {
-	u32 client_id;
 	int i;
-
-	switch (pipe->num) {
-	case MDSS_MDP_SSPP_VIG0:
-		client_id = MDSS_MDP_SMP_CLIENT_VIG0_FETCH_Y;
-		break;
-	case MDSS_MDP_SSPP_VIG1:
-		client_id = MDSS_MDP_SMP_CLIENT_VIG1_FETCH_Y;
-		break;
-	case MDSS_MDP_SSPP_VIG2:
-		client_id = MDSS_MDP_SMP_CLIENT_VIG2_FETCH_Y;
-		break;
-	case MDSS_MDP_SSPP_RGB0:
-		client_id = MDSS_MDP_SMP_CLIENT_RGB0_FETCH;
-		break;
-	case MDSS_MDP_SSPP_RGB1:
-		client_id = MDSS_MDP_SMP_CLIENT_RGB1_FETCH;
-		break;
-	case MDSS_MDP_SSPP_RGB2:
-		client_id = MDSS_MDP_SMP_CLIENT_RGB2_FETCH;
-		break;
-	case MDSS_MDP_SSPP_DMA0:
-		client_id = MDSS_MDP_SMP_CLIENT_DMA0_FETCH_Y;
-		break;
-	case MDSS_MDP_SSPP_DMA1:
-		client_id = MDSS_MDP_SMP_CLIENT_DMA1_FETCH_Y;
-		break;
-	default:
-		pr_err("no valid smp client for pnum=%d\n", pipe->num);
-		return -EINVAL;
-	}
-
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < pipe->src_planes.num_planes; i++)
-		mdss_mdp_smp_mmb_set(client_id + i, &pipe->smp[i]);
+		mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
 	mutex_unlock(&mdss_mdp_smp_lock);
 	return 0;
 }
@@ -179,84 +147,141 @@
 	return 0;
 }
 
-static struct mdss_mdp_pipe *mdss_mdp_pipe_init(u32 pnum)
+static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
+						u32 type)
 {
 	struct mdss_mdp_pipe *pipe;
+	struct mdss_data_type *mdata;
+	struct mdss_mdp_pipe *pipe_pool = NULL;
+	u32 npipes;
+	u32 i;
 
-	pipe = &mdss_mdp_pipe_list[pnum];
+	if (!mixer || !mixer->ctl || !mixer->ctl->mdata)
+		return NULL;
 
-	if (atomic_cmpxchg(&pipe->ref_cnt, 0, 1) == 0) {
-		pipe->num = pnum;
-		pipe->type = mdss_res->pipe_type_map[pnum];
-		pipe->ndx = BIT(pnum);
+	mdata = mixer->ctl->mdata;
 
-		pr_debug("ndx=%x pnum=%d\n", pipe->ndx, pipe->num);
+	switch (type) {
+	case MDSS_MDP_PIPE_TYPE_VIG:
+		pipe_pool = mdata->vig_pipes;
+		npipes = mdata->nvig_pipes;
+		break;
 
-		return pipe;
+	case MDSS_MDP_PIPE_TYPE_RGB:
+		pipe_pool = mdata->rgb_pipes;
+		npipes = mdata->nrgb_pipes;
+		break;
+
+	case MDSS_MDP_PIPE_TYPE_DMA:
+		pipe_pool = mdata->dma_pipes;
+		npipes = mdata->ndma_pipes;
+		break;
+
+	default:
+		npipes = 0;
+		pr_err("invalid pipe type %d\n", type);
+		break;
 	}
 
-	return NULL;
-}
-
-struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum)
-{
-	struct mdss_mdp_pipe *pipe = NULL;
-	mutex_lock(&mdss_mdp_sspp_lock);
-	if (mdss_res->pipe_type_map[pnum] != MDSS_MDP_PIPE_TYPE_UNUSED)
-		pipe = mdss_mdp_pipe_init(pnum);
-	mutex_unlock(&mdss_mdp_sspp_lock);
-	return pipe;
-}
-
-struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(u32 type)
-{
-	struct mdss_mdp_pipe *pipe = NULL;
-	int pnum;
-
-	mutex_lock(&mdss_mdp_sspp_lock);
-	for (pnum = 0; pnum < MDSS_MDP_MAX_SSPP; pnum++) {
-		if (type == mdss_res->pipe_type_map[pnum]) {
-			pipe = mdss_mdp_pipe_init(pnum);
-			if (pipe)
-				break;
+	for (i = 0; i < npipes; i++) {
+		pipe = pipe_pool + i;
+		if (atomic_cmpxchg(&pipe->ref_cnt, 0, 1) == 0) {
+			pipe->mixer = mixer;
+			break;
 		}
+		pipe = NULL;
 	}
-	mutex_unlock(&mdss_mdp_sspp_lock);
+
+	if (pipe)
+		pr_debug("type=%x   pnum=%d\n", pipe->type, pipe->num);
+	else
+		pr_err("no %d type pipes available\n", type);
 
 	return pipe;
 }
 
-struct mdss_mdp_pipe *mdss_mdp_pipe_get(u32 ndx)
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_dma(struct mdss_mdp_mixer *mixer)
 {
 	struct mdss_mdp_pipe *pipe = NULL;
-	int i;
+	struct mdss_data_type *mdata;
+	u32 pnum;
+
+	mutex_lock(&mdss_mdp_sspp_lock);
+	mdata = mixer->ctl->mdata;
+	pnum = mixer->num;
+
+	if (atomic_cmpxchg(&((mdata->dma_pipes[pnum]).ref_cnt), 0, 1) == 0) {
+		pipe = &mdata->dma_pipes[pnum];
+		pipe->mixer = mixer;
+
+	} else {
+		pr_err("DMA pnum%d\t not available\n", pnum);
+	}
+
+	mutex_unlock(&mdss_mdp_sspp_lock);
+	return pipe;
+}
+
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(struct mdss_mdp_mixer *mixer,
+						 u32 type)
+{
+	struct mdss_mdp_pipe *pipe;
+	mutex_lock(&mdss_mdp_sspp_lock);
+	pipe = mdss_mdp_pipe_init(mixer, type);
+	mutex_unlock(&mdss_mdp_sspp_lock);
+	return pipe;
+}
+
+struct mdss_mdp_pipe *mdss_mdp_pipe_get(struct mdss_data_type *mdata, u32 ndx)
+{
+	struct mdss_mdp_pipe *pipe = NULL;
 
 	if (!ndx)
 		return ERR_PTR(-EINVAL);
 
 	mutex_lock(&mdss_mdp_sspp_lock);
-	for (i = 0; i < MDSS_MDP_MAX_SSPP; i++) {
-		pipe = &mdss_mdp_pipe_list[i];
-		if (ndx == pipe->ndx) {
-			if (mdss_mdp_pipe_map(pipe))
-				pipe = ERR_PTR(-EACCES);
-			break;
-		}
-	}
+
+	pipe = mdss_mdp_pipe_search(mdata, ndx);
+	if (!pipe)
+		return ERR_PTR(-EINVAL);
+
+	if (mdss_mdp_pipe_map(pipe))
+		return ERR_PTR(-EACCES);
+
 	mutex_unlock(&mdss_mdp_sspp_lock);
 
-	if (i == MDSS_MDP_MAX_SSPP)
-		return ERR_PTR(-ENODEV);
-
 	return pipe;
 }
 
+static struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
+						  u32 ndx)
+{
+	u32 i;
+	for (i = 0; i < mdata->nvig_pipes; i++) {
+		if (mdata->vig_pipes[i].ndx == ndx)
+			return &mdata->vig_pipes[i];
+	}
+
+	for (i = 0; i < mdata->nrgb_pipes; i++) {
+		if (mdata->rgb_pipes[i].ndx == ndx)
+			return &mdata->rgb_pipes[i];
+	}
+
+	for (i = 0; i < mdata->ndma_pipes; i++) {
+		if (mdata->dma_pipes[i].ndx == ndx)
+			return &mdata->dma_pipes[i];
+	}
+
+	return NULL;
+}
+
 static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe)
 {
 	pr_debug("ndx=%x pnum=%d ref_cnt=%d\n", pipe->ndx, pipe->num,
 			atomic_read(&pipe->ref_cnt));
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	mdss_mdp_pipe_sspp_term(pipe);
 	mdss_mdp_smp_free(pipe);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
@@ -283,14 +308,12 @@
 static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
 				       u32 reg, u32 val)
 {
-	int offset = MDSS_MDP_REG_SSPP_OFFSET(pipe->num);
-	MDSS_MDP_REG_WRITE(offset + reg, val);
+	writel_relaxed(val, pipe->base + reg);
 }
 
 static inline u32 mdss_mdp_pipe_read(struct mdss_mdp_pipe *pipe, u32 reg)
 {
-	int offset = MDSS_MDP_REG_SSPP_OFFSET(pipe->num);
-	return MDSS_MDP_REG_READ(offset + reg);
+	return readl_relaxed(pipe->base + reg);
 }
 
 static int mdss_mdp_leading_zero(u32 num)
@@ -576,6 +599,8 @@
 		unpack = 0;
 	}
 
+	mdss_mdp_pipe_sspp_setup(pipe, &opmode);
+
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, src_format);
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN, unpack);
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_OP_MODE, opmode);
@@ -606,6 +631,53 @@
 	}
 }
 
+int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
+				u32 *ftch_id, u32 type, u32 num_base, u32 len)
+{
+	struct mdss_mdp_pipe *head;
+	u32 i;
+	int rc = 0;
+
+	head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_pipe) *
+			len, GFP_KERNEL);
+
+	if (!head) {
+		pr_err("unable to setup pipe type=%d :devm_kzalloc fail\n",
+			type);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < len; i++) {
+		head[i].type = type;
+		head[i].ftch_id  = ftch_id[i];
+		head[i].num = i + num_base;
+		head[i].ndx = BIT(i + num_base);
+		head[i].base = mdata->mdp_base + offsets[i];
+	}
+
+	switch (type) {
+
+	case MDSS_MDP_PIPE_TYPE_VIG:
+		mdata->vig_pipes = head;
+		break;
+
+	case MDSS_MDP_PIPE_TYPE_RGB:
+		mdata->rgb_pipes = head;
+		break;
+
+	case MDSS_MDP_PIPE_TYPE_DMA:
+		mdata->dma_pipes = head;
+		break;
+
+	default:
+		pr_err("Invalid pipe type=%d\n", type);
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+
 static int mdss_mdp_src_addr_setup(struct mdss_mdp_pipe *pipe,
 				   struct mdss_mdp_data *data)
 {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 242be60..ee48f31 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -78,11 +78,6 @@
 
 #define MDSS_BLOCK_DISP_NUM	(MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0)
 
-#define IGC_LUT_ENTRIES	256
-#define GC_LUT_SEGMENTS	16
-#define ENHIST_LUT_ENTRIES 256
-#define HIST_V_SIZE	256
-
 #define HIST_WAIT_TIMEOUT(frame) ((60 * HZ * (frame)) / 1000)
 /* hist collect state */
 enum {
@@ -122,18 +117,6 @@
 	GAMUT_T2_SIZE + GAMUT_T3_SIZE + GAMUT_T4_SIZE + \
 	GAMUT_T5_SIZE + GAMUT_T6_SIZE + GAMUT_T7_SIZE)
 
-struct pp_sts_type {
-	u32 pa_sts;
-	u32 pcc_sts;
-	u32 igc_sts;
-	u32 igc_tbl_idx;
-	u32 argc_sts;
-	u32 enhist_sts;
-	u32 dither_sts;
-	u32 gamut_sts;
-	u32 pgc_sts;
-};
-
 #define PP_FLAGS_DIRTY_PA	0x1
 #define PP_FLAGS_DIRTY_PCC	0x2
 #define PP_FLAGS_DIRTY_IGC	0x4
@@ -143,6 +126,7 @@
 #define PP_FLAGS_DIRTY_GAMUT	0x40
 #define PP_FLAGS_DIRTY_HIST_COL	0x80
 #define PP_FLAGS_DIRTY_PGC	0x100
+#define PP_FLAGS_DIRTY_SHARP	0x200
 
 #define PP_STS_ENABLE	0x1
 #define PP_STS_GAMUT_FIRST	0x2
@@ -295,7 +279,7 @@
 }
 
 static void pp_gamut_config(struct mdp_gamut_cfg_data *gamut_cfg,
-				u32 base, u32 *gamut_sts)
+				u32 base, struct pp_sts_type *pp_sts)
 {
 	u32 offset;
 	int i, j;
@@ -320,13 +304,13 @@
 			offset += 4;
 		}
 		if (gamut_cfg->gamut_first)
-			*gamut_sts |= PP_STS_GAMUT_FIRST;
+			pp_sts->gamut_sts |= PP_STS_GAMUT_FIRST;
 	}
 
 	if (gamut_cfg->flags & MDP_PP_OPS_DISABLE)
-		*gamut_sts &= ~PP_STS_ENABLE;
+		pp_sts->gamut_sts &= ~PP_STS_ENABLE;
 	else if (gamut_cfg->flags & MDP_PP_OPS_ENABLE)
-		*gamut_sts |= PP_STS_ENABLE;
+		pp_sts->gamut_sts |= PP_STS_ENABLE;
 }
 
 static void pp_pa_config(unsigned long flags, u32 base,
@@ -407,11 +391,33 @@
 	}
 }
 
+static void pp_sharp_config(unsigned long flags, u32 base,
+				struct pp_sts_type *pp_sts,
+				struct mdp_sharp_cfg *sharp_config)
+{
+	if (flags & PP_FLAGS_DIRTY_SHARP) {
+		if (sharp_config->flags & MDP_PP_OPS_WRITE) {
+			MDSS_MDP_REG_WRITE(base, sharp_config->strength);
+			base += 4;
+			MDSS_MDP_REG_WRITE(base, sharp_config->edge_thr);
+			base += 4;
+			MDSS_MDP_REG_WRITE(base, sharp_config->smooth_thr);
+			base += 4;
+			MDSS_MDP_REG_WRITE(base, sharp_config->noise_thr);
+		}
+		if (sharp_config->flags & MDP_PP_OPS_DISABLE)
+			pp_sts->sharp_sts &= ~PP_STS_ENABLE;
+		else if (sharp_config->flags & MDP_PP_OPS_ENABLE)
+			pp_sts->sharp_sts |= PP_STS_ENABLE;
+	}
+}
+
+
 static int pp_vig_pipe_setup(struct mdss_mdp_pipe *pipe, u32 *op)
 {
-	struct pp_sts_type pp_sts;
 	u32 opmode = 0, base = 0;
 	unsigned long flags = 0;
+	u32 upscaling = 1;
 
 	pr_debug("pnum=%x\n", pipe->num);
 
@@ -450,12 +456,33 @@
 			flags = PP_FLAGS_DIRTY_PA;
 			base = MDSS_MDP_REG_SSPP_OFFSET(pipe->num) +
 				MDSS_MDP_REG_VIG_PA_BASE;
-			pp_sts.pa_sts = 0;
-			pp_pa_config(flags, base, &pp_sts,
+			pp_pa_config(flags, base, &pipe->pp_res.pp_sts,
 					&pipe->pp_cfg.pa_cfg);
-			if (pp_sts.pa_sts & PP_STS_ENABLE)
+
+			if (pipe->pp_res.pp_sts.pa_sts & PP_STS_ENABLE)
 				opmode |= (1 << 4); /* PA_EN */
 		}
+
+		if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_SHARP_CFG) {
+			if ((pipe->dst.w < pipe->src.w) ||
+				(pipe->dst.h < pipe->src.h))
+				upscaling = 0;
+			if ((pipe->src_fmt->is_yuv) && upscaling) {
+				flags = PP_FLAGS_DIRTY_SHARP;
+				base = MDSS_MDP_REG_SSPP_OFFSET(pipe->num) +
+					MDSS_MDP_REG_VIG_QSEED2_SHARP;
+				pp_sharp_config(flags, base,
+					&pipe->pp_res.pp_sts,
+					&pipe->pp_cfg.sharp_cfg);
+
+				if (pipe->pp_res.pp_sts.sharp_sts &
+					PP_STS_ENABLE)
+					MDSS_MDP_REG_WRITE(
+					   MDSS_MDP_REG_SSPP_OFFSET(pipe->num) +
+					   MDSS_MDP_REG_VIG_QSEED2_CONFIG,
+					   1 << 0 | 1 << 1);
+			}
+		}
 	}
 
 	*op = opmode;
@@ -479,6 +506,56 @@
 	return ret;
 }
 
+void mdss_mdp_pipe_sspp_term(struct mdss_mdp_pipe *pipe)
+{
+	memset(&pipe->pp_cfg, 0, sizeof(struct mdp_overlay_pp_params));
+	memset(&pipe->pp_res, 0, sizeof(struct mdss_pipe_pp_res));
+}
+
+int mdss_mdp_pipe_sspp_setup(struct mdss_mdp_pipe *pipe, u32 *op)
+{
+	int ret = 0;
+	unsigned long flags = 0;
+	u32 pipe_base;
+	u32 pipe_num;
+
+	if (pipe == NULL)
+		return -EINVAL;
+
+	/*
+	 * TODO: should this function be responsible for masking multiple
+	 * pipes to be written in dual pipe case?
+	 * if so, requires rework of update_igc_lut
+	 */
+	switch (pipe->type) {
+	case MDSS_MDP_PIPE_TYPE_VIG:
+		pipe_base = MDSS_MDP_REG_IGC_VIG_BASE;
+		pipe_num = pipe->num - MDSS_MDP_SSPP_VIG0;
+		break;
+	case MDSS_MDP_PIPE_TYPE_RGB:
+		pipe_base = MDSS_MDP_REG_IGC_RGB_BASE;
+		pipe_num = pipe->num - MDSS_MDP_SSPP_RGB0;
+		break;
+	case MDSS_MDP_PIPE_TYPE_DMA:
+		pipe_base = MDSS_MDP_REG_IGC_DMA_BASE;
+		pipe_num = pipe->num - MDSS_MDP_SSPP_DMA0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_IGC_CFG) {
+		flags |= PP_FLAGS_DIRTY_IGC;
+		pp_igc_config(flags, pipe_base, &pipe->pp_res.pp_sts,
+					&pipe->pp_cfg.igc_cfg, pipe_num);
+	}
+
+	if (pipe->pp_res.pp_sts.igc_sts & PP_STS_ENABLE)
+		*op |= (1 << 16); /* IGC_LUT_EN */
+
+	return ret;
+}
+
 static int pp_mixer_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
 		struct mdss_mdp_mixer *mixer)
 {
@@ -634,8 +711,8 @@
 	if (pp_sts->dither_sts & PP_STS_ENABLE)
 		opmode |= (1 << 8); /* DITHER_EN */
 	if (flags & PP_FLAGS_DIRTY_GAMUT)
-		pp_gamut_config(&mdss_pp_res->gamut_disp_cfg[disp_num],
-					base, &pp_sts->gamut_sts);
+		pp_gamut_config(&mdss_pp_res->gamut_disp_cfg[disp_num], base,
+				pp_sts);
 	if (pp_sts->gamut_sts & PP_STS_ENABLE) {
 		opmode |= (1 << 23); /* GAMUT_EN */
 		if (pp_sts->gamut_sts & PP_STS_GAMUT_FIRST)
@@ -687,6 +764,83 @@
 	return 0;
 }
 
+/*
+ * Set dirty and write bits on features that were enabled so they will be
+ * reconfigured
+ */
+int mdss_mdp_pp_resume(u32 mixer_num)
+{
+	u32 flags = 0;
+	struct pp_sts_type pp_sts;
+
+	if (mixer_num >= MDSS_MDP_MAX_DSPP) {
+		pr_warn("invalid mixer_num");
+		return -EINVAL;
+	}
+
+	pp_sts = mdss_pp_res->pp_dspp_sts[mixer_num];
+
+	if (pp_sts.pa_sts & PP_STS_ENABLE) {
+		flags |= PP_FLAGS_DIRTY_PA;
+		if (!(mdss_pp_res->pa_disp_cfg[mixer_num].flags
+					& MDP_PP_OPS_DISABLE))
+			mdss_pp_res->pa_disp_cfg[mixer_num].flags |=
+				MDP_PP_OPS_WRITE;
+	}
+	if (pp_sts.pcc_sts & PP_STS_ENABLE) {
+		flags |= PP_FLAGS_DIRTY_PCC;
+		if (!(mdss_pp_res->pcc_disp_cfg[mixer_num].ops
+					& MDP_PP_OPS_DISABLE))
+			mdss_pp_res->pcc_disp_cfg[mixer_num].ops |=
+				MDP_PP_OPS_WRITE;
+	}
+	if (pp_sts.igc_sts & PP_STS_ENABLE) {
+		flags |= PP_FLAGS_DIRTY_IGC;
+		if (!(mdss_pp_res->igc_disp_cfg[mixer_num].ops
+					& MDP_PP_OPS_DISABLE))
+			mdss_pp_res->igc_disp_cfg[mixer_num].ops |=
+				MDP_PP_OPS_WRITE;
+	}
+	if (pp_sts.argc_sts & PP_STS_ENABLE) {
+		flags |= PP_FLAGS_DIRTY_ARGC;
+		if (!(mdss_pp_res->argc_disp_cfg[mixer_num].flags
+					& MDP_PP_OPS_DISABLE))
+			mdss_pp_res->argc_disp_cfg[mixer_num].flags |=
+				MDP_PP_OPS_WRITE;
+	}
+	if (pp_sts.enhist_sts & PP_STS_ENABLE) {
+		flags |= PP_FLAGS_DIRTY_ENHIST;
+		if (!(mdss_pp_res->enhist_disp_cfg[mixer_num].ops
+					& MDP_PP_OPS_DISABLE))
+			mdss_pp_res->enhist_disp_cfg[mixer_num].ops |=
+				MDP_PP_OPS_WRITE;
+	}
+	if (pp_sts.dither_sts & PP_STS_ENABLE) {
+		flags |= PP_FLAGS_DIRTY_DITHER;
+		if (!(mdss_pp_res->dither_disp_cfg[mixer_num].flags
+					& MDP_PP_OPS_DISABLE))
+			mdss_pp_res->dither_disp_cfg[mixer_num].flags |=
+				MDP_PP_OPS_WRITE;
+	}
+	if (pp_sts.gamut_sts & PP_STS_ENABLE) {
+		flags |= PP_FLAGS_DIRTY_GAMUT;
+		if (!(mdss_pp_res->gamut_disp_cfg[mixer_num].flags
+					& MDP_PP_OPS_DISABLE))
+			mdss_pp_res->gamut_disp_cfg[mixer_num].flags |=
+				MDP_PP_OPS_WRITE;
+	}
+	if (pp_sts.pgc_sts & PP_STS_ENABLE) {
+		flags |= PP_FLAGS_DIRTY_PGC;
+		if (!(mdss_pp_res->pgc_disp_cfg[mixer_num].flags
+					& MDP_PP_OPS_DISABLE))
+			mdss_pp_res->pgc_disp_cfg[mixer_num].flags |=
+				MDP_PP_OPS_WRITE;
+	}
+
+	mdss_pp_res->pp_disp_flags[mixer_num] = flags;
+	return 0;
+}
+
 int mdss_mdp_pp_init(struct device *dev)
 {
 	int ret = 0;
@@ -706,6 +860,7 @@
 		for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
 			data[i] = i;
 
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 		/* Initialize Histogram LUT for all DSPPs */
 		for (i = 0; i < MDSS_MDP_MAX_DSPP; i++) {
 			offset = MDSS_MDP_REG_DSPP_OFFSET(i) +
@@ -714,6 +869,7 @@
 			pp_update_hist_lut(offset,
 					&mdss_pp_res->enhist_disp_cfg[i]);
 		}
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 	}
 	mutex_unlock(&mdss_pp_mutex);
 	return ret;
@@ -731,7 +887,7 @@
 {
 	int i;
 	u32 mixer_cnt;
-	u32 mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+	u32 mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
 	mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
 
 	if (!mixer_cnt)
@@ -1443,7 +1599,7 @@
 	struct pp_hist_col_info *hist_info;
 	int i, ret = 0;
 	u32 disp_num, dspp_num = 0;
-	u32 mixer_cnt, mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+	u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
 	unsigned long flag;
 
 	if ((req->block < MDP_LOGICAL_BLOCK_DISP_0) ||
@@ -1511,7 +1667,7 @@
 	int i, ret = 0;
 	u32 dspp_num, disp_num, ctl_base, done_bit;
 	struct pp_hist_col_info *hist_info;
-	u32 mixer_cnt, mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+	u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
 	unsigned long flag;
 
 	if ((block < MDP_LOGICAL_BLOCK_DISP_0) ||
@@ -1570,7 +1726,7 @@
 	u32 timeout, v_base;
 	struct pp_hist_col_info *hist_info;
 	u32 dspp_num, disp_num, ctl_base;
-	u32 mixer_cnt, mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+	u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
 	unsigned long flag;
 
 	if ((hist->block < MDP_LOGICAL_BLOCK_DISP_0) ||
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index a151b38..8bff5cb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -70,28 +70,13 @@
 {
 	struct mdss_mdp_mixer *mixer;
 	struct mdss_mdp_pipe *pipe = NULL;
-	int pnum;
 
 	mixer = mdss_mdp_wb_mixer_alloc(1);
 	if (!mixer)
 		return NULL;
 
-	switch (mixer->num) {
-	case MDSS_MDP_LAYERMIXER3:
-		pnum = MDSS_MDP_SSPP_DMA0;
-		break;
-	case MDSS_MDP_LAYERMIXER4:
-		pnum = MDSS_MDP_SSPP_DMA1;
-		break;
-	default:
-		goto done;
-	}
+	pipe = mdss_mdp_pipe_alloc_dma(mixer);
 
-	pipe = mdss_mdp_pipe_alloc_pnum(pnum);
-
-	if (!IS_ERR_OR_NULL(pipe))
-		pipe->mixer = mixer;
-done:
 	if (!pipe)
 		mdss_mdp_wb_mixer_destroy(mixer);
 
@@ -185,7 +170,7 @@
 			   struct mdss_mdp_data *src_data,
 			   struct mdss_mdp_data *dst_data)
 {
-	struct mdss_mdp_pipe *rot_pipe;
+	struct mdss_mdp_pipe *rot_pipe = NULL;
 	struct mdss_mdp_ctl *ctl;
 	int ret, need_wait = false;
 
@@ -238,6 +223,9 @@
 	if (need_wait)
 		mdss_mdp_rotator_busy_wait(rot);
 
+	if (rot_pipe)
+		pr_debug("end of rotator pnum=%d enqueue\n", rot_pipe->num);
+
 	return ret;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 24701b2..40131eb 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -65,6 +65,7 @@
 	MDSS_EVENT_SUSPEND,
 	MDSS_EVENT_RESUME,
 	MDSS_EVENT_CHECK_PARAMS,
+	MDSS_EVENT_FB_REGISTERED,
 };
 
 /* panel info type */
@@ -186,7 +187,6 @@
 	struct lcdc_panel_info lcdc;
 	struct mipi_panel_info mipi;
 	struct lvds_panel_info lvds;
-	struct fb_info *fbi;
 };
 
 struct mdss_panel_data {
@@ -196,7 +196,10 @@
 
 	/* function entry chain */
 	int (*event_handler) (struct mdss_panel_data *pdata, int e, void *arg);
+
+	struct mdss_panel_data *next;
 };
 
-int mdss_register_panel(struct mdss_panel_data *pdata);
+int mdss_register_panel(struct platform_device *pdev,
+	struct mdss_panel_data *pdata);
 #endif /* MDSS_PANEL_H */
diff --git a/drivers/video/msm/mdss/mdss_wb.c b/drivers/video/msm/mdss/mdss_wb.c
index d1a11c8..1b398d3 100644
--- a/drivers/video/msm/mdss/mdss_wb.c
+++ b/drivers/video/msm/mdss/mdss_wb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -111,7 +111,7 @@
 	pdata->event_handler = mdss_wb_event_handler;
 	pdev->dev.platform_data = pdata;
 
-	rc = mdss_register_panel(pdata);
+	rc = mdss_register_panel(pdev, pdata);
 	if (rc) {
 		dev_err(&pdev->dev, "unable to register writeback panel\n");
 		return rc;
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index 94f6d2b..3d3fff9 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -67,12 +67,37 @@
 		mhl_ctrl = ctrl;
 }
 
+static int mhl_flag_scrpd_burst_req(struct mhl_tx_ctrl *mhl_ctrl,
+		struct msc_command_struct *req)
+{
+	int postpone_send = 0;
+
+	if ((req->command == MHL_SET_INT) &&
+	    (req->offset == MHL_RCHANGE_INT)) {
+		if (mhl_ctrl->scrpd_busy) {
+			/* reduce priority */
+			if (req->payload.data[0] == MHL_INT_REQ_WRT)
+				postpone_send = 1;
+		} else {
+			if (req->payload.data[0] == MHL_INT_REQ_WRT) {
+				mhl_ctrl->scrpd_busy = true;
+				mhl_ctrl->wr_burst_pending = true;
+			} else if (req->payload.data[0] == MHL_INT_GRT_WRT) {
+					mhl_ctrl->scrpd_busy = true;
+			}
+		}
+	}
+	return postpone_send;
+}
+
+
+
 void mhl_msc_send_work(struct work_struct *work)
 {
 	struct mhl_tx_ctrl *mhl_ctrl =
 		container_of(work, struct mhl_tx_ctrl, mhl_msc_send_work);
 	struct msc_cmd_envelope *cmd_env;
-	int ret;
+	int ret, postpone_send;
 	/*
 	 * Remove item from the queue
 	 * and schedule it
@@ -85,21 +110,39 @@
 		list_del(&cmd_env->msc_queue_envelope);
 		mutex_unlock(&msc_send_workqueue_mutex);
 
-		ret = mhl_send_msc_command(mhl_ctrl, &cmd_env->msc_cmd_msg);
-		if (ret == -EAGAIN) {
-			int retry = 2;
-			while (retry--) {
-				ret = mhl_send_msc_command(
-					mhl_ctrl,
-					&cmd_env->msc_cmd_msg);
-				if (ret != -EAGAIN)
-					break;
+		postpone_send = mhl_flag_scrpd_burst_req(
+			mhl_ctrl,
+			&cmd_env->msc_cmd_msg);
+		if (postpone_send) {
+			if (cmd_env->msc_cmd_msg.retry-- > 0) {
+				mutex_lock(&msc_send_workqueue_mutex);
+				list_add_tail(
+					&cmd_env->msc_queue_envelope,
+					&mhl_ctrl->list_cmd);
+				mutex_unlock(&msc_send_workqueue_mutex);
+			} else {
+				pr_err("%s: max scrpd retry out\n",
+				       __func__);
 			}
+		} else {
+			ret = mhl_send_msc_command(mhl_ctrl,
+						   &cmd_env->msc_cmd_msg);
+			if (ret == -EAGAIN) {
+				int retry = 2;
+				while (retry--) {
+					ret = mhl_send_msc_command(
+						mhl_ctrl,
+						&cmd_env->msc_cmd_msg);
+					if (ret != -EAGAIN)
+						break;
+				}
+			}
+			if (ret == -EAGAIN)
+				pr_err("%s: send_msc_command retry out!\n",
+				       __func__);
+			vfree(cmd_env);
 		}
-		if (ret == -EAGAIN)
-			pr_err("%s: send_msc_command retry out!\n", __func__);
 
-		vfree(cmd_env);
 		mutex_lock(&msc_send_workqueue_mutex);
 	}
 	mutex_unlock(&msc_send_workqueue_mutex);
@@ -179,20 +222,26 @@
 		case DEVCAP_OFFSET_INT_STAT_SIZE:
 			break;
 		}
-
+		break;
+	case MHL_WRITE_BURST:
+		mhl_msc_send_set_int(
+			mhl_ctrl,
+			MHL_RCHANGE_INT,
+			MHL_INT_DSCR_CHG,
+			MSC_PRIORITY_SEND);
 		break;
 	}
 	return 0;
 }
 
 int mhl_msc_send_set_int(struct mhl_tx_ctrl *mhl_ctrl,
-			 u8 offset, u8 mask)
+			 u8 offset, u8 mask, u8 prior)
 {
 	struct msc_command_struct req;
 	req.command = MHL_SET_INT;
 	req.offset = offset;
 	req.payload.data[0] = mask;
-	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+	return mhl_queue_msc_command(mhl_ctrl, &req, prior);
 }
 
 int mhl_msc_send_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
@@ -205,6 +254,27 @@
 	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
 }
 
+static int mhl_msc_write_burst(struct mhl_tx_ctrl *mhl_ctrl,
+	u8 offset, u8 *data, u8 length)
+{
+	struct msc_command_struct req;
+	if (!mhl_ctrl)
+		return -EFAULT;
+
+	if (!mhl_ctrl->wr_burst_pending)
+		return -EFAULT;
+
+	req.command = MHL_WRITE_BURST;
+	req.offset = offset;
+	req.length = length;
+	req.payload.burst_data = data;
+	mhl_queue_msc_command(mhl_ctrl, &req, MSC_PRIORITY_SEND);
+	mhl_ctrl->wr_burst_pending = false;
+	return 0;
+}
+
+
+
 int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
 			 u8 sub_cmd, u8 cmd_data)
 {
@@ -384,6 +454,7 @@
 int mhl_msc_recv_set_int(struct mhl_tx_ctrl *mhl_ctrl,
 			 u8 offset, u8 set_int)
 {
+	int prior;
 	if (offset >= 2)
 		return -EFAULT;
 
@@ -394,18 +465,36 @@
 			mhl_ctrl->devcap_state = 0;
 			mhl_msc_read_devcap_all(mhl_ctrl);
 		}
-		if (set_int & MHL_INT_DSCR_CHG)
+		if (set_int & MHL_INT_DSCR_CHG) {
+			/* peer's scratchpad reg changed */
 			pr_debug("%s: dscr chg\n", __func__);
+			mhl_read_scratchpad(mhl_ctrl);
+			mhl_ctrl->scrpd_busy = false;
+		}
 		if (set_int & MHL_INT_REQ_WRT) {
-			/* SET_INT: GRT_WRT */
+			/* SET_INT: REQ_WRT */
+			if (mhl_ctrl->scrpd_busy) {
+				prior = MSC_NORMAL_SEND;
+			} else {
+				prior = MSC_PRIORITY_SEND;
+				mhl_ctrl->scrpd_busy = true;
+			}
 			mhl_msc_send_set_int(
 				mhl_ctrl,
 				MHL_RCHANGE_INT,
-				MHL_INT_GRT_WRT);
+				MHL_INT_GRT_WRT,
+				prior);
 		}
-		if (set_int & MHL_INT_GRT_WRT)
+		if (set_int & MHL_INT_GRT_WRT) {
+			/* SET_INT: GRT_WRT */
 			pr_debug("%s: recvd req to permit/grant write",
 				 __func__);
+			mhl_msc_write_burst(
+				mhl_ctrl,
+				MHL_SCRATCHPAD_OFFSET,
+				mhl_ctrl->scrpd.data,
+				mhl_ctrl->scrpd.length);
+		}
 		break;
 	case 1:
 		if (set_int & MHL_INT_EDID_CHG) {
@@ -487,3 +576,53 @@
 	mhl_ctrl->path_en_state = value;
 	return 0;
 }
+
+static int mhl_request_write_burst(struct mhl_tx_ctrl *mhl_ctrl,
+				   u8 start_reg,
+				   u8 length, u8 *data)
+{
+	int rc = 0;
+
+	if (!(mhl_ctrl->devcap[DEVCAP_OFFSET_FEATURE_FLAG] &
+	      MHL_FEATURE_SP_SUPPORT)) {
+		pr_debug("MHL: SCRATCHPAD_NOT_SUPPORTED\n");
+		rc = -EFAULT;
+	} else {
+		if (mhl_ctrl->scrpd_busy) {
+			pr_debug("MHL: scratchpad_busy\n");
+			rc = -EBUSY;
+		} else {
+			int i, reg;
+			for (i = 0, reg = start_reg; (i < length) &&
+				     (reg < MHL_SCRATCHPAD_SIZE); i++, reg++)
+				mhl_ctrl->scrpd.data[reg] = data[i];
+			mhl_ctrl->scrpd.length = length;
+			mhl_ctrl->scrpd.offset = start_reg;
+			mhl_msc_send_set_int(
+				mhl_ctrl,
+				MHL_RCHANGE_INT,
+				MHL_INT_REQ_WRT,
+				MSC_PRIORITY_SEND);
+		}
+	}
+	return rc;
+}
+
+/* write scratchpad entry */
+int mhl_write_scratchpad(struct mhl_tx_ctrl *mhl_ctrl,
+			  u8 offset, u8 length, u8 *data)
+{
+	int rc;
+
+	if ((length < ADOPTER_ID_SIZE) ||
+	    (length > MAX_SCRATCHPAD_TRANSFER_SIZE) ||
+	    (offset > (MAX_SCRATCHPAD_TRANSFER_SIZE - ADOPTER_ID_SIZE)) ||
+	    ((offset + length) > MAX_SCRATCHPAD_TRANSFER_SIZE)) {
+		pr_debug("MHL: write_burst (0x%02x)\n", -EINVAL);
+		return  -EINVAL;
+	}
+
+	rc = mhl_request_write_burst(mhl_ctrl, offset, length, data);
+
+	return rc;
+}
diff --git a/drivers/video/msm/mdss/mhl_msc.h b/drivers/video/msm/mdss/mhl_msc.h
index 9a7b3d6..8a1fd39 100644
--- a/drivers/video/msm/mdss/mhl_msc.h
+++ b/drivers/video/msm/mdss/mhl_msc.h
@@ -29,14 +29,15 @@
 			 struct msc_command_struct *req);
 
 int mhl_msc_send_set_int(struct mhl_tx_ctrl *mhl_ctrl,
-			 u8 offset, u8 mask);
+			 u8 offset, u8 mask, u8 priority);
 
 int mhl_msc_send_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
 			    u8 offset, u8 value);
 int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
 			 u8 sub_cmd, u8 cmd_data);
 
-int mhl_msc_recv_set_int(struct mhl_tx_ctrl *mhl_ctrl, u8 offset, u8 set_int);
+int mhl_msc_recv_set_int(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 offset, u8 set_int);
 
 int mhl_msc_recv_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
 			    u8 offset, u8 value);
@@ -48,6 +49,7 @@
 /* Tx should implement these APIs */
 int mhl_send_msc_command(struct mhl_tx_ctrl *mhl_ctrl,
 			 struct msc_command_struct *req);
+void mhl_read_scratchpad(struct mhl_tx_ctrl *mhl_ctrl);
 void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state);
 void mhl_tmds_ctrl(struct mhl_tx_ctrl *ctrl, uint8_t on);
 /******************************************************************/
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 7baeef5..4d6af15 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -239,6 +239,7 @@
 	int i, rc = 0;
 	struct device_node *of_node = NULL;
 	struct dss_gpio *temp_gpio = NULL;
+	int dt_gpio;
 	i = 0;
 
 	if (!dev || !pdata) {
@@ -263,7 +264,13 @@
 		goto error;
 	}
 	/* RESET */
-	temp_gpio->gpio = of_get_named_gpio(of_node, "mhl-rst-gpio", 0);
+	dt_gpio = of_get_named_gpio(of_node, "mhl-rst-gpio", 0);
+	if (dt_gpio < 0) {
+		pr_err("%s: Can't get mhl-rst-gpio\n", __func__);
+		goto error;
+	}
+
+	temp_gpio->gpio = dt_gpio;
 	snprintf(temp_gpio->gpio_name, 32, "%s", "mhl-rst-gpio");
 	pr_debug("%s: rst gpio=[%d]\n", __func__,
 		 temp_gpio->gpio);
@@ -277,7 +284,13 @@
 		pr_err("%s: can't alloc %d gpio mem\n", __func__, i);
 		goto error;
 	}
-	temp_gpio->gpio = of_get_named_gpio(of_node, "mhl-pwr-gpio", 0);
+	dt_gpio = of_get_named_gpio(of_node, "mhl-pwr-gpio", 0);
+	if (dt_gpio < 0) {
+		pr_err("%s: Can't get mhl-pwr-gpio\n", __func__);
+		goto error;
+	}
+
+	temp_gpio->gpio = dt_gpio;
 	snprintf(temp_gpio->gpio_name, 32, "%s", "mhl-pwr-gpio");
 	pr_debug("%s: pmic gpio=[%d]\n", __func__,
 		 temp_gpio->gpio);
@@ -291,7 +304,13 @@
 		pr_err("%s: can't alloc %d gpio mem\n", __func__, i);
 		goto error;
 	}
-	temp_gpio->gpio = of_get_named_gpio(of_node, "mhl-intr-gpio", 0);
+	dt_gpio = of_get_named_gpio(of_node, "mhl-intr-gpio", 0);
+	if (dt_gpio < 0) {
+		pr_err("%s: Can't get mhl-intr-gpio\n", __func__);
+		goto error;
+	}
+
+	temp_gpio->gpio = dt_gpio;
 	snprintf(temp_gpio->gpio_name, 32, "%s", "mhl-intr-gpio");
 	pr_debug("%s: intr gpio=[%d]\n", __func__,
 		 temp_gpio->gpio);
@@ -308,8 +327,11 @@
 
 static int mhl_sii_reset_pin(struct mhl_tx_ctrl *mhl_ctrl, int on)
 {
-	gpio_set_value(mhl_ctrl->pdata->gpios[MHL_TX_RESET_GPIO]->gpio,
-		       on);
+	if (mhl_ctrl->pdata->gpios[MHL_TX_RESET_GPIO]) {
+		gpio_set_value(
+			mhl_ctrl->pdata->gpios[MHL_TX_RESET_GPIO]->gpio,
+			on);
+	}
 	return 0;
 }
 
@@ -780,7 +802,8 @@
 
 	mhl_msc_send_set_int(mhl_ctrl,
 			     MHL_RCHANGE_INT,
-			     MHL_INT_DCAP_CHG);
+			     MHL_INT_DCAP_CHG,
+			     MSC_PRIORITY_SEND);
 
 }
 
@@ -1079,7 +1102,8 @@
 		}
 		burst_data = req->payload.burst_data;
 		for (i = 0; i < req->length; i++, burst_data++)
-			MHL_SII_CBUS_WR(0xC0 + i, *burst_data);
+			MHL_SII_REG_NAME_WR(REG_CBUS_SCRATCHPAD_0 + i,
+				*burst_data);
 		break;
 	default:
 		pr_err("%s: unknown command! (%02x)\n",
@@ -1116,6 +1140,18 @@
 	return -EFAULT;
 }
 
+/* read scratchpad */
+void mhl_read_scratchpad(struct mhl_tx_ctrl *mhl_ctrl)
+{
+	struct i2c_client *client = mhl_ctrl->i2c_handle;
+	int i;
+
+	for (i = 0; i < MHL_SCRATCHPAD_SIZE; i++) {
+		mhl_ctrl->scrpd.data[i] = MHL_SII_REG_NAME_RD(
+			REG_CBUS_SCRATCHPAD_0 + i);
+	}
+}
+
 static void mhl_cbus_isr(struct mhl_tx_ctrl *mhl_ctrl)
 {
 	uint8_t regval;
@@ -1388,12 +1424,12 @@
 	static struct regulator *reg_8941_vdda;
 	int rc;
 
-	pr_debug("Inside %s\n", __func__);
+	pr_debug("%s\n", __func__);
 	if (!reg_8941_l24) {
 		reg_8941_l24 = regulator_get(&client->dev,
 			"avcc_18");
 		if (IS_ERR(reg_8941_l24)) {
-			pr_err("could not get reg_8038_l20, rc = %ld\n",
+			pr_err("could not get 8941 l24, rc = %ld\n",
 				PTR_ERR(reg_8941_l24));
 			return -ENODEV;
 		}
@@ -1404,7 +1440,7 @@
 		if (rc) {
 			pr_err("'%s' regulator config[%u] failed, rc=%d\n",
 			       "avcc_1.8V", enable, rc);
-			return rc;
+			goto l24_fail;
 		} else {
 			pr_debug("%s: vreg L24 %s\n",
 				 __func__, (enable ? "enabled" : "disabled"));
@@ -1417,7 +1453,7 @@
 		if (IS_ERR(reg_8941_l02)) {
 			pr_err("could not get reg_8941_l02, rc = %ld\n",
 				PTR_ERR(reg_8941_l02));
-			return -ENODEV;
+			goto l24_fail;
 		}
 		if (enable)
 			rc = regulator_enable(reg_8941_l02);
@@ -1426,7 +1462,7 @@
 		if (rc) {
 			pr_debug("'%s' regulator configure[%u] failed, rc=%d\n",
 				 "avcc_1.2V", enable, rc);
-			return rc;
+			goto l02_fail;
 		} else {
 			pr_debug("%s: vreg L02 %s\n",
 				 __func__, (enable ? "enabled" : "disabled"));
@@ -1437,9 +1473,9 @@
 		reg_8941_smps3a = regulator_get(&client->dev,
 			"smps3a");
 		if (IS_ERR(reg_8941_smps3a)) {
-			pr_err("could not get reg_8038_l20, rc = %ld\n",
+			pr_err("could not get vreg smps3a, rc = %ld\n",
 				PTR_ERR(reg_8941_smps3a));
-			return -ENODEV;
+			goto l02_fail;
 		}
 		if (enable)
 			rc = regulator_enable(reg_8941_smps3a);
@@ -1448,7 +1484,7 @@
 		if (rc) {
 			pr_err("'%s' regulator config[%u] failed, rc=%d\n",
 			       "SMPS3A", enable, rc);
-			return rc;
+			goto smps3a_fail;
 		} else {
 			pr_debug("%s: vreg SMPS3A %s\n",
 				 __func__, (enable ? "enabled" : "disabled"));
@@ -1459,9 +1495,9 @@
 		reg_8941_vdda = regulator_get(&client->dev,
 			"vdda");
 		if (IS_ERR(reg_8941_vdda)) {
-			pr_err("could not get reg_8038_l20, rc = %ld\n",
+			pr_err("could not get vreg vdda, rc = %ld\n",
 				PTR_ERR(reg_8941_vdda));
-			return -ENODEV;
+			goto smps3a_fail;
 		}
 		if (enable)
 			rc = regulator_enable(reg_8941_vdda);
@@ -1470,7 +1506,7 @@
 		if (rc) {
 			pr_err("'%s' regulator config[%u] failed, rc=%d\n",
 			       "VDDA", enable, rc);
-			return rc;
+			goto vdda_fail;
 		} else {
 			pr_debug("%s: vreg VDDA %s\n",
 				 __func__, (enable ? "enabled" : "disabled"));
@@ -1478,6 +1514,21 @@
 	}
 
 	return rc;
+
+vdda_fail:
+	regulator_disable(reg_8941_vdda);
+	regulator_put(reg_8941_vdda);
+smps3a_fail:
+	regulator_disable(reg_8941_smps3a);
+	regulator_put(reg_8941_smps3a);
+l02_fail:
+	regulator_disable(reg_8941_l02);
+	regulator_put(reg_8941_l02);
+l24_fail:
+	regulator_disable(reg_8941_l24);
+	regulator_put(reg_8941_l24);
+
+	return -EINVAL;
 }
 
 
@@ -1500,13 +1551,13 @@
 		if (ret < 0) {
 			pr_err("%s: set gpio MHL_PWR_EN dircn failed: %d\n",
 			       __func__, ret);
-			return ret;
+			goto vreg_config_failed;
 		}
 
 		ret = mhl_sii_reg_config(client, true);
 		if (ret) {
 			pr_err("%s: regulator enable failed\n", __func__);
-			return -EINVAL;
+			goto vreg_config_failed;
 		}
 		pr_debug("%s: mhl sii power on successful\n", __func__);
 	} else {
@@ -1516,6 +1567,9 @@
 	}
 	pr_debug("%s: successful\n", __func__);
 	return 0;
+vreg_config_failed:
+	gpio_free(pwr_gpio);
+	return -EINVAL;
 }
 
 /*
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 34f8bf9f..83e89c5 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,52 +28,53 @@
 
 static struct dsi_clk_desc dsi_pclk;
 
-static struct clk *dsi_byte_clk;
-static struct clk *dsi_esc_clk;
-static struct clk *dsi_pixel_clk;
-
-int mdss_dsi_clk_on;
-
-int mdss_dsi_clk_init(struct platform_device *pdev)
+int mdss_dsi_clk_init(struct platform_device *pdev,
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
-	struct device *dev = &pdev->dev;
+	struct device *dev = NULL;
 
-	dsi_byte_clk = clk_get(dev, "byte_clk");
-	if (IS_ERR(dsi_byte_clk)) {
+	if (!pdev) {
+		pr_err("%s: Invalid pdev\n", __func__);
+		goto mdss_dsi_clk_err;
+	}
+
+	dev = &pdev->dev;
+	ctrl_pdata->byte_clk = clk_get(dev, "byte_clk");
+	if (IS_ERR(ctrl_pdata->byte_clk)) {
 		pr_err("can't find dsi_byte_clk\n");
-		dsi_byte_clk = NULL;
+		ctrl_pdata->byte_clk = NULL;
 		goto mdss_dsi_clk_err;
 	}
 
-	dsi_pixel_clk = clk_get(dev, "pixel_clk");
-	if (IS_ERR(dsi_pixel_clk)) {
+	ctrl_pdata->pixel_clk = clk_get(dev, "pixel_clk");
+	if (IS_ERR(ctrl_pdata->pixel_clk)) {
 		pr_err("can't find dsi_pixel_clk\n");
-		dsi_pixel_clk = NULL;
+		ctrl_pdata->pixel_clk = NULL;
 		goto mdss_dsi_clk_err;
 	}
 
-	dsi_esc_clk = clk_get(dev, "core_clk");
-	if (IS_ERR(dsi_esc_clk)) {
+	ctrl_pdata->esc_clk = clk_get(dev, "core_clk");
+	if (IS_ERR(ctrl_pdata->esc_clk)) {
 		pr_err("can't find dsi_esc_clk\n");
-		dsi_esc_clk = NULL;
+		ctrl_pdata->esc_clk = NULL;
 		goto mdss_dsi_clk_err;
 	}
 
 	return 0;
 
 mdss_dsi_clk_err:
-	mdss_dsi_clk_deinit(dev);
+	mdss_dsi_clk_deinit(ctrl_pdata);
 	return -EPERM;
 }
 
-void mdss_dsi_clk_deinit(struct device *dev)
+void mdss_dsi_clk_deinit(struct mdss_dsi_ctrl_pdata  *ctrl_pdata)
 {
-	if (dsi_byte_clk)
-		clk_put(dsi_byte_clk);
-	if (dsi_esc_clk)
-		clk_put(dsi_esc_clk);
-	if (dsi_pixel_clk)
-		clk_put(dsi_pixel_clk);
+	if (ctrl_pdata->byte_clk)
+		clk_put(ctrl_pdata->byte_clk);
+	if (ctrl_pdata->esc_clk)
+		clk_put(ctrl_pdata->esc_clk);
+	if (ctrl_pdata->pixel_clk)
+		clk_put(ctrl_pdata->pixel_clk);
 }
 
 #define PREF_DIV_RATIO 27
@@ -155,58 +156,76 @@
 	return 0;
 }
 
-void mdss_dsi_prepare_clocks(void)
+void mdss_dsi_prepare_clocks(struct mdss_dsi_ctrl_pdata  *ctrl_pdata)
 {
-	clk_prepare(dsi_byte_clk);
-	clk_prepare(dsi_esc_clk);
-	clk_prepare(dsi_pixel_clk);
+	clk_prepare(ctrl_pdata->byte_clk);
+	clk_prepare(ctrl_pdata->esc_clk);
+	clk_prepare(ctrl_pdata->pixel_clk);
 }
 
-void mdss_dsi_unprepare_clocks(void)
+void mdss_dsi_unprepare_clocks(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
-	clk_unprepare(dsi_esc_clk);
-	clk_unprepare(dsi_pixel_clk);
-	clk_unprepare(dsi_byte_clk);
+	clk_unprepare(ctrl_pdata->esc_clk);
+	clk_unprepare(ctrl_pdata->pixel_clk);
+	clk_unprepare(ctrl_pdata->byte_clk);
 }
 
 void mdss_dsi_clk_enable(struct mdss_panel_data *pdata)
 {
-	if (mdss_dsi_clk_on) {
+	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;
+	}
+
+	if (ctrl_pdata->mdss_dsi_clk_on) {
 		pr_info("%s: mdss_dsi_clks already ON\n", __func__);
 		return;
 	}
 
-	if (clk_set_rate(dsi_esc_clk, 19200000) < 0)
+	if (clk_set_rate(ctrl_pdata->esc_clk, 19200000) < 0)
 		pr_err("%s: dsi_esc_clk - clk_set_rate failed\n",
 					__func__);
 
-	if (clk_set_rate(dsi_byte_clk, 53000000) < 0)
+	if (clk_set_rate(ctrl_pdata->byte_clk, 53000000) < 0)
 		pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
 					__func__);
 
-	if (clk_set_rate(dsi_pixel_clk, 70000000) < 0)
+	if (clk_set_rate(ctrl_pdata->pixel_clk, 70000000) < 0)
 		pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
 					__func__);
 
-	clk_enable(dsi_esc_clk);
-	clk_enable(dsi_byte_clk);
-	clk_enable(dsi_pixel_clk);
+	clk_enable(ctrl_pdata->esc_clk);
+	clk_enable(ctrl_pdata->byte_clk);
+	clk_enable(ctrl_pdata->pixel_clk);
 
-	mdss_dsi_clk_on = 1;
+	ctrl_pdata->mdss_dsi_clk_on = 1;
 }
 
 void mdss_dsi_clk_disable(struct mdss_panel_data *pdata)
 {
-	if (mdss_dsi_clk_on == 0) {
+	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;
+	}
+
+	if (ctrl_pdata->mdss_dsi_clk_on == 0) {
 		pr_info("%s: mdss_dsi_clks already OFF\n", __func__);
 		return;
 	}
 
-	clk_disable(dsi_pixel_clk);
-	clk_disable(dsi_byte_clk);
-	clk_disable(dsi_esc_clk);
+	clk_disable(ctrl_pdata->pixel_clk);
+	clk_disable(ctrl_pdata->byte_clk);
+	clk_disable(ctrl_pdata->esc_clk);
 
-	mdss_dsi_clk_on = 0;
+	ctrl_pdata->mdss_dsi_clk_on = 0;
 }
 
 void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base)
@@ -280,7 +299,13 @@
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, 0x07);
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, pd->strength[0]);
 
-	off = 0x0580;	/* phy regulator ctrl settings */
+	/* phy regulator ctrl settings. Both the DSI controller
+	   have one regulator */
+	if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
+		off = 0x0580;
+	else
+		off = 0x0580 - 0x600;
+
 	/* Regulator ctrl - CAL_PWD_CFG */
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 6), pd->regulator[6]);
 	/* Regulator ctrl - TEST */
@@ -331,7 +356,10 @@
 	wmb();
 
 	/* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */
-	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x01);
+	if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x01);
+	else
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x00);
 	wmb();
 
 	off = 0x04b4;	/* phy BIST ctrl 0 - 5 */
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 3841498..0715b0b 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1568,6 +1568,7 @@
 static int msm_fb_open(struct fb_info *info, int user)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	bool unblank = true;
 	int result;
 
 	result = pm_runtime_get_sync(info->dev);
@@ -1589,9 +1590,16 @@
 			pr_debug("%s:%d no mdp_set_dma_pan_info %d\n",
 				__func__, __LINE__, info->node);
 
-		if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
-			printk(KERN_ERR "msm_fb_open: can't turn on display!\n");
-			return -1;
+		if (mfd->is_panel_ready && !mfd->is_panel_ready())
+			unblank = false;
+
+		if (unblank) {
+			if (msm_fb_blank_sub(FB_BLANK_UNBLANK,
+				info, mfd->op_enable)) {
+				MSM_FB_ERR("%s: can't turn on display!\n",
+					__func__);
+				return -EPERM;
+			}
 		}
 	}
 
@@ -1747,8 +1755,6 @@
 
 static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
 	if (var->rotate != FB_ROTATE_UR)
 		return -EINVAL;
 	if (var->grayscale != info->var.grayscale)
@@ -1837,12 +1843,6 @@
 	if ((var->xres == 0) || (var->yres == 0))
 		return -EINVAL;
 
-	if ((var->xres > MAX(mfd->panel_info.xres,
-			     mfd->panel_info.mode2_xres)) ||
-		(var->yres > MAX(mfd->panel_info.yres,
-				 mfd->panel_info.mode2_yres)))
-		return -EINVAL;
-
 	if (var->xoffset > (var->xres_virtual - var->xres))
 		return -EINVAL;
 
@@ -1926,6 +1926,10 @@
 
 	if (blank) {
 		msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
+
+		if (mfd->update_panel_info)
+			mfd->update_panel_info(mfd);
+
 		msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
 	}
 
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index eb8d087..34cb1fc 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -138,6 +138,8 @@
 	int (*stop_histogram) (struct fb_info *info, uint32_t block);
 	void (*vsync_ctrl) (int enable);
 	void (*vsync_init) (int cndx);
+	void (*update_panel_info)(struct msm_fb_data_type *mfd);
+	bool (*is_panel_ready)(void);
 	void *vsync_show;
 	void *cursor_buf;
 	void *cursor_buf_phys;
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 9c49d17..2b4542a 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -135,7 +135,7 @@
 				 * throttling rules. Don't do it again. */
 
 	/* request only flags */
-	__REQ_SORTED,		/* elevator knows about this request */
+	__REQ_SORTED = __REQ_RAHEAD, /* elevator knows about this request */
 	__REQ_SOFTBARRIER,	/* may not be passed by ioscheduler */
 	__REQ_NOMERGE,		/* don't touch this for merging */
 	__REQ_STARTED,		/* drive already may have started this one */
@@ -151,6 +151,7 @@
 	__REQ_IO_STAT,		/* account I/O stat */
 	__REQ_MIXED_MERGE,	/* merge of different types, fail separately */
 	__REQ_SANITIZE,		/* sanitize */
+	__REQ_URGENT,		/* urgent request */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -163,6 +164,7 @@
 #define REQ_PRIO		(1 << __REQ_PRIO)
 #define REQ_DISCARD		(1 << __REQ_DISCARD)
 #define REQ_SANITIZE		(1 << __REQ_SANITIZE)
+#define REQ_URGENT		(1 << __REQ_URGENT)
 #define REQ_NOIDLE		(1 << __REQ_NOIDLE)
 
 #define REQ_FAILFAST_MASK \
diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h
index b156eba..3f35dd9 100644
--- a/include/linux/coresight-stm.h
+++ b/include/linux/coresight-stm.h
@@ -36,7 +36,7 @@
 #define stm_log(entity_id, data, size)					\
 	stm_log_inv_ts(entity_id, 0, data, size)
 
-#ifdef CONFIG_MSM_QDSS
+#ifdef CONFIG_CORESIGHT_STM
 extern int stm_trace(uint32_t options, uint8_t entity_id, uint8_t proto_id,
 		     const void *data, uint32_t size);
 #else
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index b167b44..cfc690e 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -151,7 +151,7 @@
 	const struct coresight_ops_source *source_ops;
 };
 
-#ifdef CONFIG_MSM_QDSS
+#ifdef CONFIG_CORESIGHT
 extern struct coresight_device *
 coresight_register(struct coresight_desc *desc);
 extern void coresight_unregister(struct coresight_device *csdev);
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 4bd8885..d3ee879 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -135,7 +135,7 @@
 #define MSG_SSID_9			5500
 #define MSG_SSID_9_LAST			5516
 #define MSG_SSID_10			6000
-#define MSG_SSID_10_LAST		6072
+#define MSG_SSID_10_LAST		6080
 #define MSG_SSID_11			6500
 #define MSG_SSID_11_LAST		6521
 #define MSG_SSID_12			7000
@@ -159,7 +159,7 @@
 #define MSG_SSID_21			10300
 #define MSG_SSID_21_LAST		10300
 #define MSG_SSID_22			10350
-#define MSG_SSID_22_LAST		10361
+#define MSG_SSID_22_LAST		10374
 #define MSG_SSID_23			0xC000
 #define MSG_SSID_23_LAST		0xC063
 
@@ -525,6 +525,14 @@
 	MSG_LVL_MED,
 	MSG_LVL_MED,
 	MSG_LVL_MED,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
 	MSG_LVL_LOW
 };
 
@@ -686,6 +694,19 @@
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
+	MSG_LVL_LOW,
 	MSG_LVL_LOW
 };
 
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index b903dfb..fe23993 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2010 Samsung Electronics Co.Ltd
  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -32,10 +32,8 @@
 /* Bootoader IDs */
 #define MXT_BOOTLOADER_ID_224		0x0A
 #define MXT_BOOTLOADER_ID_224E		0x06
-#define MXT_BOOTLOADER_ID_336S		0x1A
 #define MXT_BOOTLOADER_ID_1386		0x01
 #define MXT_BOOTLOADER_ID_1386E		0x10
-#define MXT_BOOTLOADER_ID_1664S		0x14
 
 /* Config data for a given maXTouch controller with a specific firmware */
 struct mxt_config_info {
@@ -77,7 +75,6 @@
 	int *key_codes;
 	bool need_calibration;
 	bool no_force_update;
-	u8 bl_addr;
 
 	u8(*read_chg) (void);
 	int (*init_hw) (bool);
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/mfd/pm8xxx/batterydata-lib.h
index afa1843..5ff1cfb 100644
--- a/include/linux/mfd/pm8xxx/batterydata-lib.h
+++ b/include/linux/mfd/pm8xxx/batterydata-lib.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -73,6 +73,7 @@
 	BATT_UNKNOWN = 0,
 	BATT_PALLADIUM,
 	BATT_DESAY,
+	BATT_OEM,
 };
 
 /**
@@ -106,6 +107,7 @@
 	defined(CONFIG_QPNP_BMS)
 extern struct bms_battery_data  palladium_1500_data;
 extern struct bms_battery_data  desay_5200_data;
+extern struct bms_battery_data  oem_batt_data;
 
 int interpolate_fcc(struct single_row_lut *fcc_temp_lut, int batt_temp);
 int interpolate_scalingfactor(struct sf_lut *sf_lut, int row_entry, int pc);
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 458f060..3ebf091 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -36,11 +36,14 @@
 #define SITAR_IS_1P1(ver) \
 	((ver == SITAR_VERSION_1P1) ? 1 : 0)
 
-
-#define TAIKO_VERSION_1_0	0
+#define TAIKO_VERSION_1_0	1
 #define TAIKO_IS_1_0(ver) \
 	((ver == TAIKO_VERSION_1_0) ? 1 : 0)
 
+enum wcd9xxx_slim_slave_addr_type {
+	WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA,
+	WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO,
+};
 
 enum {
 	/* INTR_REG 0 */
@@ -186,6 +189,8 @@
 	struct wcd9xxx_ch *rx_chs;
 	struct wcd9xxx_ch *tx_chs;
 	u32 mclk_rate;
+
+	enum wcd9xxx_slim_slave_addr_type slim_slave_type;
 };
 
 int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
index 12f7851..9c44e8b 100644
--- a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
@@ -162,6 +162,8 @@
 #define WCD9XXX_A_MICB_4_MBHC__POR		(0x01)
 #define WCD9XXX_A_MICB_CFILT_1_VAL		(0x129)
 #define WCD9XXX_A_MICB_CFILT_1_VAL__POR		(0x80)
+#define WCD9XXX_A_RX_HPH_L_STATUS		(0x1B3)
+#define WCD9XXX_A_RX_HPH_L_STATUS__POR		(0x00)
 #define WCD9XXX_A_MBHC_HPH			(0x1FE)
 #define WCD9XXX_A_MBHC_HPH__POR			(0x44)
 #define WCD9XXX_A_RX_HPH_CNP_WG_TIME		(0x1AD)
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index cb74b73..75e6546 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -36,6 +36,7 @@
 	u8 command;
 	u8 offset;
 	u8 length;
+	u8 retry;
 	union {
 		u8 data[16];
 		u8 *burst_data;
@@ -43,6 +44,13 @@
 	u8 retval;
 };
 
+struct scrpd_struct {
+	u8 offset;
+	u8 length;
+	u8 data[MHL_SCRATCHPAD_SIZE];
+};
+
+
 /* USB driver interface  */
 
 #if defined(CONFIG_FB_MSM_HDMI_MHL_8334)
@@ -143,6 +151,9 @@
 	struct workqueue_struct *msc_send_workqueue;
 	u16 *rcp_key_code_tbl;
 	size_t rcp_key_code_tbl_len;
+	struct scrpd_struct scrpd;
+	int scrpd_busy;
+	int wr_burst_pending;
 };
 
 int mhl_i2c_reg_read(struct i2c_client *client,
@@ -337,8 +348,8 @@
 #define REG_CBUS_WRITE_STAT_2           ((TX_PAGE_CBUS << 16) | 0x00B2)
 #define REG_CBUS_WRITE_STAT_3           ((TX_PAGE_CBUS << 16) | 0x00B3)
 
-#define GET_PAGE(x) (x >> 16)
-#define GET_OFF(x) (x & 0xffff)
+#define GET_PAGE(x) ((x) >> 16)
+#define GET_OFF(x) ((x) & 0xffff)
 
 
 #define MHL_SII_REG_NAME_RD(arg)\
diff --git a/include/linux/mhl_defs.h b/include/linux/mhl_defs.h
index f23be79..f9d1ce4 100644
--- a/include/linux/mhl_defs.h
+++ b/include/linux/mhl_defs.h
@@ -128,7 +128,11 @@
 
 /* This contains one nibble each - max offset */
 #define		MHL_INT_AND_STATUS_SIZE			0x33
+#define         MHL_SCRATCHPAD_OFFSET                   0x40
 #define		MHL_SCRATCHPAD_SIZE			16
+#define		MAX_SCRATCHPAD_TRANSFER_SIZE		64
+#define		ADOPTER_ID_SIZE				2
+
 /* manually define highest number */
 #define		MHL_MAX_BUFFER_SIZE			MHL_SCRATCHPAD_SIZE
 
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index b362d7a..d683856 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -199,6 +199,7 @@
 	THRESHOLD,
 	LARGE_SEC_ALIGN,
 	RANDOM,
+	FUA,
 	MAX_REASONS,
 };
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index f9e0627..cb8e4f3 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -260,15 +260,15 @@
 #define MMC_CAP2_DETECT_ON_ERR	(1 << 8)	/* On I/O err check card removal */
 #define MMC_CAP2_HC_ERASE_SZ	(1 << 9)	/* High-capacity erase size */
 
-#define MMC_CAP2_PACKED_RD	(1 << 10)	/* Allow packed read */
-#define MMC_CAP2_PACKED_WR	(1 << 11)	/* Allow packed write */
+#define MMC_CAP2_PACKED_RD	(1 << 12)	/* Allow packed read */
+#define MMC_CAP2_PACKED_WR	(1 << 13)	/* Allow packed write */
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR) /* Allow packed commands */
-#define MMC_CAP2_PACKED_WR_CONTROL (1 << 12) /* Allow write packing control */
+#define MMC_CAP2_PACKED_WR_CONTROL (1 << 14) /* Allow write packing control */
 
-#define MMC_CAP2_SANITIZE	(1 << 13)		/* Support Sanitize */
-#define MMC_CAP2_INIT_BKOPS	    (1 << 15)	/* Need to set BKOPS_EN */
-#define MMC_CAP2_CLK_SCALE	(1 << 16)	/* Allow dynamic clk scaling */
+#define MMC_CAP2_SANITIZE	(1 << 15)		/* Support Sanitize */
+#define MMC_CAP2_INIT_BKOPS	    (1 << 16)	/* Need to set BKOPS_EN */
+#define MMC_CAP2_CLK_SCALE	(1 << 17)	/* Allow dynamic clk scaling */
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
 	int			clk_requests;	/* internal reference counter */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 56eda83..72febbb 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -305,14 +305,24 @@
 	uint32_t *data;
 };
 
+struct mdp_sharp_cfg {
+	uint32_t flags;
+	uint32_t strength;
+	uint32_t edge_thr;
+	uint32_t smooth_thr;
+	uint32_t noise_thr;
+};
+
 struct mdp_qseed_cfg_data {
 	uint32_t block;
 	struct mdp_qseed_cfg qseed_data;
 };
 
-#define MDP_OVERLAY_PP_CSC_CFG      0x1
-#define MDP_OVERLAY_PP_QSEED_CFG    0x2
-#define MDP_OVERLAY_PP_PA_CFG      0x4
+#define MDP_OVERLAY_PP_CSC_CFG         0x1
+#define MDP_OVERLAY_PP_QSEED_CFG       0x2
+#define MDP_OVERLAY_PP_PA_CFG          0x4
+#define MDP_OVERLAY_PP_IGC_CFG         0x8
+#define MDP_OVERLAY_PP_SHARP_CFG       0x10
 
 #define MDP_CSC_FLAG_ENABLE	0x1
 #define MDP_CSC_FLAG_YUV_IN	0x2
@@ -341,11 +351,20 @@
 	uint32_t cont_adj;
 };
 
+struct mdp_igc_lut_data {
+	uint32_t block;
+	uint32_t len, ops;
+	uint32_t *c0_c1_data;
+	uint32_t *c2_data;
+};
+
 struct mdp_overlay_pp_params {
 	uint32_t config_ops;
 	struct mdp_csc_cfg csc_cfg;
 	struct mdp_qseed_cfg qseed_cfg[2];
 	struct mdp_pa_cfg pa_cfg;
+	struct mdp_igc_lut_data igc_cfg;
+	struct mdp_sharp_cfg sharp_cfg;
 };
 
 struct mdp_overlay {
@@ -462,13 +481,6 @@
 	mdp_lut_max,
 };
 
-struct mdp_igc_lut_data {
-	uint32_t block;
-	uint32_t len, ops;
-	uint32_t *c0_c1_data;
-	uint32_t *c2_data;
-};
-
 struct mdp_ar_gc_lut_data {
 	uint32_t x_start;
 	uint32_t slope;
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e0d9072..c6ee4f0 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -514,6 +514,12 @@
  *	of PMKSA caching dandidates.
  *
  * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ *	In addition, this can be used as an event to request userspace to take
+ *	actions on TDLS links (set up a new link or tear down an existing one).
+ *	In such events, %NL80211_ATTR_TDLS_OPERATION indicates the requested
+ *	operation, %NL80211_ATTR_MAC contains the peer MAC address, and
+ *	%NL80211_ATTR_REASON_CODE the reason code to be used (only with
+ *	%NL80211_TDLS_TEARDOWN).
  * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
  *
  * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 46724eb..6e30ca2 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -126,6 +126,7 @@
 	POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
 	POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */
 	POWER_SUPPLY_PROP_SCOPE,
+	POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
 	/* Properties of type `const char *' */
 	POWER_SUPPLY_PROP_MODEL_NAME,
 	POWER_SUPPLY_PROP_MANUFACTURER,
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 903cc3f..a3347c4 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -680,6 +680,7 @@
  * @state_request: Enable/disable the corresponding high and low temperature
  *		thresholds.
  * @timer_interval: Select polling rate from qpnp_adc_meas_timer_2 type.
+ * @btmid_ctx: A context of void type.
  * @threshold_notification: Notification callback once threshold are crossed.
  */
 struct qpnp_adc_tm_btm_param {
@@ -687,7 +688,9 @@
 	int32_t					low_temp;
 	enum qpnp_state_request			state_request;
 	enum qpnp_adc_meas_timer_2		timer_interval;
-	void	(*threshold_notification) (enum qpnp_tm_state state);
+	void					*btm_ctx;
+	void	(*threshold_notification) (enum qpnp_tm_state state,
+						void *ctx);
 };
 
 /**
diff --git a/include/linux/regulator/krait-regulator.h b/include/linux/regulator/krait-regulator.h
index 2d49046..836f9d6 100644
--- a/include/linux/regulator/krait-regulator.h
+++ b/include/linux/regulator/krait-regulator.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,22 @@
 #ifdef CONFIG_ARCH_MSM8974
 int __init krait_power_init(void);
 void secondary_cpu_hs_init(void *base_ptr);
+
+/**
+ * krait_power_mdd_enable - function to turn on/off MDD. Turning off MDD
+ *				turns off badngap reference for LDO. If
+ *				a core is running on a LDO, requests to
+ *				turn off MDD will not be honoured
+ * @on:	boolean to indicate whether to turn MDD on/off
+ *
+ * CONTEXT: Can be called in interrupt context, only when the core
+ *		is about to go to idle, this guarantees that there are no
+ *		frequency changes on that cpu happening. Note if going from off
+ *		to on mode there will be settling delays
+ *
+ * RETURNS: -EINVAL if MDD cannot be turned off
+ */
+int krait_power_mdd_enable(int cpu_num, bool on);
 #else
 static inline int __init krait_power_init(void)
 {
@@ -33,6 +49,10 @@
 }
 
 static inline void secondary_cpu_hs_init(void *base_ptr) {}
+static inline int krait_power_mdd_enable(int cpu_num, bool on)
+{
+	return -EINVAL;
+}
 #endif
 
 #endif
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index 803ff22..5c5b777 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -962,6 +962,12 @@
 extern int slim_driver_register(struct slim_driver *drv);
 
 /*
+ * slim_driver_unregister: Undo effects of slim_driver_register
+ * @drv: Client driver to be unregistered
+ */
+extern void slim_driver_unregister(struct slim_driver *drv);
+
+/*
  * slim_add_numbered_controller: Controller bring-up.
  * @ctrl: Controller to be registered.
  * A controller is registered with the framework using this API. ctrl->nr is the
diff --git a/include/linux/test-iosched.h b/include/linux/test-iosched.h
index 3690160..89d3b30 100644
--- a/include/linux/test-iosched.h
+++ b/include/linux/test-iosched.h
@@ -23,7 +23,7 @@
 /*
  * Patterns definitions for read/write requests data
  */
-#define TEST_PATTERN_SEQUENTIAL	-1
+#define TEST_PATTERN_SEQUENTIAL	0x12345678
 #define TEST_PATTERN_5A		0x5A5A5A5A
 #define TEST_PATTERN_FF		0xFFFFFFFF
 #define TEST_NO_PATTERN		0xDEADBEEF
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index c588420..b0b718f 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -523,8 +523,9 @@
 int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
 	u8 dst_pipe_idx);
 
-int msm_register_usb_ext_notification(struct usb_ext_notification *info);
+void msm_dwc3_restart_usb_session(void);
 
+int msm_register_usb_ext_notification(struct usb_ext_notification *info);
 #else
 static inline int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
 	u8 dst_pipe_idx)
@@ -542,6 +543,11 @@
 	return -ENODEV;
 }
 
+static inline void msm_dwc3_restart_usb_session(void)
+{
+	return;
+}
+
 static inline int msm_register_usb_ext_notification(
 					struct usb_ext_notification *info)
 {
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 9d38db32..2972dc0 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -696,6 +696,9 @@
 #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
 #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
 #define V4L2_BUF_FLAG_EOS		0x2000
+#define V4L2_QCOM_BUF_FLAG_CODECCONFIG  0x4000
+#define V4L2_QCOM_BUF_FLAG_EOSEQ  0x8000
+#define V4L2_QCOM_BUF_TIMESTAMP_INVALID 0x10000
 
 /*
  *	O V E R L A Y   P R E V I E W
@@ -2140,9 +2143,6 @@
 	};
 };
 
-#define V4L2_QCOM_BUF_FLAG_CODECCONFIG	0x4000
-#define V4L2_QCOM_BUF_FLAG_EOSEQ  0x8000
-
 /* Decoder commands */
 #define V4L2_DEC_CMD_START       (0)
 #define V4L2_DEC_CMD_STOP        (1)
diff --git a/include/media/Kbuild b/include/media/Kbuild
index 43cc3b9..060047f 100644
--- a/include/media/Kbuild
+++ b/include/media/Kbuild
@@ -13,3 +13,4 @@
 header-y += msm_cam_sensor.h
 header-y += msmb_isp.h
 header-y += msmb_ispif.h
+header-y += msmb_generic_buf_mgr.h
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index a96a067..4e1fb31 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -33,6 +33,17 @@
 
 #define MAX_SENSOR_NAME 32
 
+#define MAX_ACT_MOD_NAME_SIZE 32
+#define MAX_ACT_NAME_SIZE 32
+#define NUM_ACTUATOR_DIR 2
+#define MAX_ACTUATOR_SCENARIO 8
+#define MAX_ACTUATOR_REGION 5
+#define MAX_ACTUATOR_INIT_SET 12
+#define MAX_ACTUATOR_REG_TBL_SIZE 8
+
+#define MOVE_NEAR 0
+#define MOVE_FAR  1
+
 enum msm_camera_i2c_reg_addr_type {
 	MSM_CAMERA_I2C_BYTE_ADDR = 1,
 	MSM_CAMERA_I2C_WORD_ADDR,
@@ -281,6 +292,147 @@
 	CFG_SET_STOP_STREAM_SETTING,
 	CFG_GET_SENSOR_INFO,
 	CFG_GET_SENSOR_INIT_PARAMS,
+	CFG_SET_INIT_SETTING,
+	CFG_SET_RESOLUTION,
+	CFG_SET_STOP_STREAM,
+	CFG_SET_START_STREAM,
+};
+
+enum msm_actuator_cfg_type_t {
+	CFG_GET_ACTUATOR_INFO,
+	CFG_SET_ACTUATOR_INFO,
+	CFG_SET_DEFAULT_FOCUS,
+	CFG_MOVE_FOCUS,
+};
+
+enum actuator_type {
+	ACTUATOR_VCM,
+	ACTUATOR_PIEZO,
+};
+
+enum msm_actuator_data_type {
+	MSM_ACTUATOR_BYTE_DATA = 1,
+	MSM_ACTUATOR_WORD_DATA,
+};
+
+enum msm_actuator_addr_type {
+	MSM_ACTUATOR_BYTE_ADDR = 1,
+	MSM_ACTUATOR_WORD_ADDR,
+};
+
+struct reg_settings_t {
+	uint16_t reg_addr;
+	uint16_t reg_data;
+};
+
+struct region_params_t {
+	/* [0] = ForwardDirection Macro boundary
+	   [1] = ReverseDirection Inf boundary
+        */
+	uint16_t step_bound[2];
+	uint16_t code_per_step;
+};
+
+struct damping_params_t {
+	uint32_t damping_step;
+	uint32_t damping_delay;
+	uint32_t hw_params;
+};
+
+struct msm_actuator_move_params_t {
+	int8_t dir;
+	int8_t sign_dir;
+	int16_t dest_step_pos;
+	int32_t num_steps;
+	struct damping_params_t *ringing_params;
+};
+
+struct msm_actuator_tuning_params_t {
+	int16_t initial_code;
+	uint16_t pwd_step;
+	uint16_t region_size;
+	uint32_t total_steps;
+	struct region_params_t *region_params;
+};
+
+struct msm_actuator_params_t {
+	enum actuator_type act_type;
+	uint8_t reg_tbl_size;
+	uint16_t data_size;
+	uint16_t init_setting_size;
+	uint32_t i2c_addr;
+	enum msm_actuator_addr_type i2c_addr_type;
+	enum msm_actuator_data_type i2c_data_type;
+	struct msm_actuator_reg_params_t *reg_tbl_params;
+	struct reg_settings_t *init_settings;
+};
+
+struct msm_actuator_set_info_t {
+	struct msm_actuator_params_t actuator_params;
+	struct msm_actuator_tuning_params_t af_tuning_params;
+};
+
+struct msm_actuator_get_info_t {
+	uint32_t focal_length_num;
+	uint32_t focal_length_den;
+	uint32_t f_number_num;
+	uint32_t f_number_den;
+	uint32_t f_pix_num;
+	uint32_t f_pix_den;
+	uint32_t total_f_dist_num;
+	uint32_t total_f_dist_den;
+	uint32_t hor_view_angle_num;
+	uint32_t hor_view_angle_den;
+	uint32_t ver_view_angle_num;
+	uint32_t ver_view_angle_den;
+};
+
+enum af_camera_name {
+	ACTUATOR_MAIN_CAM_0,
+	ACTUATOR_MAIN_CAM_1,
+	ACTUATOR_MAIN_CAM_2,
+	ACTUATOR_MAIN_CAM_3,
+	ACTUATOR_MAIN_CAM_4,
+	ACTUATOR_MAIN_CAM_5,
+	ACTUATOR_WEB_CAM_0,
+	ACTUATOR_WEB_CAM_1,
+	ACTUATOR_WEB_CAM_2,
+};
+
+struct msm_actuator_cfg_data {
+	int cfgtype;
+	uint8_t is_af_supported;
+	union {
+		struct msm_actuator_move_params_t move;
+		struct msm_actuator_set_info_t set_info;
+		struct msm_actuator_get_info_t get_info;
+		enum af_camera_name cam_name;
+	} cfg;
+};
+
+enum msm_actuator_write_type {
+	MSM_ACTUATOR_WRITE_HW_DAMP,
+	MSM_ACTUATOR_WRITE_DAC,
+};
+
+struct msm_actuator_reg_params_t {
+	enum msm_actuator_write_type reg_write_type;
+	uint32_t hw_mask;
+	uint16_t reg_addr;
+	uint16_t hw_shift;
+	uint16_t data_shift;
+};
+
+enum msm_camera_led_config_t {
+	MSM_CAMERA_LED_OFF,
+	MSM_CAMERA_LED_LOW,
+	MSM_CAMERA_LED_HIGH,
+	MSM_CAMERA_LED_INIT,
+	MSM_CAMERA_LED_RELEASE,
+};
+
+struct msm_camera_led_cfg_t {
+	enum msm_camera_led_config_t cfgtype;
 };
 
 #define VIDIOC_MSM_SENSOR_CFG \
@@ -298,6 +450,12 @@
 #define VIDIOC_MSM_CSID_IO_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct csiphy_cfg_data)
 
+#define VIDIOC_MSM_ACTUATOR_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct msm_actuator_cfg_data)
+
+#define VIDIOC_MSM_FLASH_LED_DATA_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_camera_led_cfg_t)
+
 #define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
 
 #endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index 4261d34..fae1efa 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -67,8 +67,8 @@
 	unsigned int frame_rate;
 };
 struct msm_vidc_ts_payload {
-	unsigned int timestamp_hi;
 	unsigned int timestamp_lo;
+	unsigned int timestamp_hi;
 };
 struct msm_vidc_concealmb_payload {
 	unsigned int num_mbs;
@@ -76,6 +76,15 @@
 struct msm_vidc_recoverysei_payload {
 	unsigned int flags;
 };
+
+struct msm_vidc_aspect_ratio_payload {
+	unsigned int size;
+	unsigned int version;
+	unsigned int port_index;
+	unsigned int aspect_width;
+	unsigned int aspect_height;
+};
+
 struct msm_vidc_panscan_window {
 	unsigned int panscan_height_offset;
 	unsigned int panscan_width_offset;
@@ -100,6 +109,7 @@
 	EXTRADATA_MULTISLICE_INFO = 0x7F100000,
 	EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
 	EXTRADATA_INDEX = 0x7F100002,
+	EXTRADATA_ASPECT_RATIO = 0x7F100003,
 	EXTRADATA_METADATA_FILLER = 0x7FE00002,
 };
 enum msm_vidc_interlace_type {
diff --git a/include/media/msmb_camera.h b/include/media/msmb_camera.h
index 732f60b..123c86c 100644
--- a/include/media/msmb_camera.h
+++ b/include/media/msmb_camera.h
@@ -32,6 +32,7 @@
 #define MSM_CAMERA_SUBDEV_CCI          10
 #define MSM_CAMERA_SUBDEV_LED_FLASH    11
 #define MSM_CAMERA_SUBDEV_STROBE_FLASH 12
+#define MSM_CAMERA_SUBDEV_BUF_MNGR     13
 
 #define MSM_MAX_CAMERA_SENSORS  5
 
diff --git a/include/media/msmb_generic_buf_mgr.h b/include/media/msmb_generic_buf_mgr.h
new file mode 100644
index 0000000..8981a3f
--- /dev/null
+++ b/include/media/msmb_generic_buf_mgr.h
@@ -0,0 +1,19 @@
+#ifndef __MEDIA_MSMB_BUF_MNGR_H__
+#define __MEDIA_MSMB_BUF_MNGR_H__
+
+#define VIDIOC_MSM_BUF_MNGR_GET_BUF \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 33, struct msm_buf_mngr_info *)
+
+#define VIDIOC_MSM_BUF_MNGR_PUT_BUF \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 34, struct msm_buf_mngr_info *)
+
+#define VIDIOC_MSM_BUF_MNGR_BUF_DONE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 35, struct msm_buf_mngr_info *)
+
+struct msm_buf_mngr_info {
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t index;
+};
+
+#endif
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 4e92f70..c9d3f15 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -52,7 +52,11 @@
 enum msm_vfe_frame_skip_pattern {
 	NO_SKIP,
 	EVERY_2FRAME,
+	EVERY_3FRAME,
 	EVERY_4FRAME,
+	EVERY_5FRAME,
+	EVERY_6FRAME,
+	EVERY_7FRAME,
 	EVERY_8FRAME,
 	EVERY_16FRAME,
 	EVERY_32FRAME,
@@ -142,6 +146,24 @@
 	enum msm_vfe_axi_stream_cmd cmd;
 };
 
+enum msm_vfe_axi_stream_update_type {
+	ENABLE_STREAM_BUF_DIVERT,
+	DISABLE_STREAM_BUF_DIVERT,
+	UPDATE_STREAM_FRAMEDROP_PATTERN,
+};
+
+struct msm_vfe_axi_stream_update_cmd {
+	uint32_t stream_handle;
+	enum msm_vfe_axi_stream_update_type update_type;
+	enum msm_vfe_frame_skip_pattern skip_pattern;
+};
+
+enum msm_vfe_stats_pipeline_policy {
+	STATS_COMP_ALL,
+	STATS_COMP_NONE,
+	MAX_STATS_POLICY,
+};
+
 enum msm_isp_stats_type {
 	MSM_ISP_STATS_AEC,   /* legacy based AEC */
 	MSM_ISP_STATS_AF,    /* legacy based AF */
@@ -161,10 +183,12 @@
 	uint32_t session_id;
 	uint32_t stream_id;
 	enum msm_isp_stats_type stats_type;
-	uint8_t comp_flag;
 	uint32_t framedrop_pattern;
+	uint32_t irq_subsample_pattern;
 	uint32_t stream_handle;
+	uint8_t comp_flag;
 };
+
 struct msm_vfe_stats_stream_release_cmd {
 	uint32_t stream_handle;
 };
@@ -173,13 +197,24 @@
 	uint32_t stream_handle[MSM_ISP_STATS_MAX];
 	uint8_t enable;
 };
+
+struct msm_vfe_stats_comp_policy_cfg {
+	enum msm_vfe_stats_pipeline_policy stats_pipeline_policy;
+	uint32_t comp_framedrop_pattern;
+	uint32_t comp_irq_subsample_pattern;
+};
+
 enum msm_vfe_reg_cfg_type {
 	VFE_WRITE,
 	VFE_WRITE_MB,
 	VFE_READ,
-	VFE_WRITE_MASK,
-	VFE_CLEAR_MASK,
-	VFE_WRITE_AUTO_INCREMENT,
+	VFE_CFG_MASK,
+	VFE_WRITE_DMI_16BIT,
+	VFE_WRITE_DMI_32BIT,
+	VFE_WRITE_DMI_64BIT,
+	VFE_READ_DMI_16BIT,
+	VFE_READ_DMI_32BIT,
+	VFE_READ_DMI_64BIT,
 };
 
 struct msm_vfe_cfg_cmd2 {
@@ -189,10 +224,31 @@
 	void __user *cfg_cmd;
 };
 
-struct msm_vfe_reg_cfg_cmd {
+struct msm_vfe_reg_rw_info {
 	uint32_t reg_offset;
-	uint32_t cmd_data;
+	uint32_t cmd_data_offset;
 	uint32_t len;
+};
+
+struct msm_vfe_reg_mask_info {
+	uint32_t reg_offset;
+	uint32_t mask;
+	uint32_t val;
+};
+
+struct msm_vfe_reg_dmi_info {
+	uint32_t hi_tbl_offset; /*Optional*/
+	uint32_t lo_tbl_offset; /*Required*/
+	uint32_t len;
+};
+
+struct msm_vfe_reg_cfg_cmd {
+	union {
+		struct msm_vfe_reg_rw_info rw_info;
+		struct msm_vfe_reg_mask_info mask_info;
+		struct msm_vfe_reg_dmi_info dmi_info;
+	} u;
+
 	enum msm_vfe_reg_cfg_type cmd_type;
 };
 
@@ -208,6 +264,8 @@
 	int buf_idx;
 	/*Only used for prepare buffer*/
 	struct v4l2_buffer buffer;
+	/*Only used for diverted buffer*/
+	uint32_t dirty_buf;
 };
 
 struct msm_vfe_axi_src_state {
@@ -320,4 +378,11 @@
 	_IOWR('V', BASE_VIDIOC_PRIVATE+11, \
 	struct msm_vfe_stats_stream_release_cmd)
 
+#define VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+12,   \
+	      struct msm_vfe_stats_comp_policy_cfg)
+
+#define VIDIOC_MSM_ISP_UPDATE_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+13, struct msm_vfe_axi_stream_update_cmd)
+
 #endif /* __MSMB_ISP__ */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5c1daf3..5e32ff7 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3358,6 +3358,25 @@
 				 enum nl80211_channel_type channel_type);
 
 /*
+ * cfg80211_tdls_oper_request - request userspace to perform TDLS operation
+ * @dev: the device on which the operation is requested
+ * @peer: the MAC address of the peer device
+ * @oper: the requested TDLS operation (NL80211_TDLS_SETUP or
+ *	NL80211_TDLS_TEARDOWN)
+ * @reason_code: the reason code for teardown request
+ * @gfp: allocation flags
+ *
+ * This function is used to request userspace to perform TDLS operation that
+ * requires knowledge of keys, i.e., link setup or teardown when the AP
+ * connection uses encryption. This is optional mechanism for the driver to use
+ * if it can automatically determine when a TDLS link could be useful (e.g.,
+ * based on traffic and signal strength for a peer).
+ */
+void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
+				enum nl80211_tdls_operation oper,
+				u16 reason_code, gfp_t gfp);
+
+/*
  * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units)
  * @rate: given rate_info to calculate bitrate from
  *
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index f34a5a8..cc37cd8 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -562,4 +562,6 @@
 	return (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + ptr[3];
 }
 
+struct scsi_disk *scsi_disk_get_from_dev(struct device *dev);
+
 #endif /* _SCSI_SCSI_H */
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 552ed6a..506e877 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -75,6 +75,10 @@
 	IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX = 33,
 	IDX_AFE_PORT_ID_SECONDARY_MI2S_RX = 34,
 	IDX_AFE_PORT_ID_SECONDARY_MI2S_TX = 35,
+	IDX_AFE_PORT_ID_TERTIARY_MI2S_RX = 36,
+	IDX_AFE_PORT_ID_TERTIARY_MI2S_TX = 37,
+	IDX_AFE_PORT_ID_PRIMARY_MI2S_RX = 38,
+	IDX_AFE_PORT_ID_PRIMARY_MI2S_TX = 39,
 	AFE_MAX_PORTS
 };
 
@@ -110,6 +114,7 @@
 	/* idx:1 out port, 0: in port*/
 	struct afe_audio_port_data port[2];
 	wait_queue_head_t      cmd_wait;
+	uint32_t               mem_map_handle;
 };
 
 int afe_open(u16 port_id, union afe_port_config *afe_config, int rate);
@@ -121,7 +126,8 @@
 int afe_get_port_index(u16 port_id);
 int afe_start_pseudo_port(u16 port_id);
 int afe_stop_pseudo_port(u16 port_id);
-uint32_t afe_req_mmap_handle(void);
+uint32_t afe_req_mmap_handle(struct afe_audio_client *ac);
+int afe_memory_map(u32 dma_addr_p, u32 dma_buf_sz, struct afe_audio_client *ac);
 int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
 int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz);
 int afe_cmd_memory_unmap(u32 dma_addr_p);
diff --git a/include/uapi/media/msmb_generic_buf_mgr.h b/include/uapi/media/msmb_generic_buf_mgr.h
new file mode 100644
index 0000000..8368e26
--- /dev/null
+++ b/include/uapi/media/msmb_generic_buf_mgr.h
@@ -0,0 +1,19 @@
+#ifndef __UAPI_MEDIA_MSMB_BUF_MNGR_H__
+#define __UAPI_MEDIA_MSMB_BUF_MNGR_H__
+
+#define VIDIOC_MSM_BUF_MNGR_GET_BUF \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 33, struct msm_buf_mngr_info *)
+
+#define VIDIOC_MSM_BUF_MNGR_PUT_BUF \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 34, struct msm_buf_mngr_info *)
+
+#define VIDIOC_MSM_BUF_MNGR_BUF_DONE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 35, struct msm_buf_mngr_info *)
+
+struct msm_buf_mngr_info {
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t index;
+};
+
+#endif
diff --git a/kernel/arch/arm/configs/omap3_beagle_android_defconfig b/kernel/arch/arm/configs/omap3_beagle_android_defconfig
new file mode 100644
index 0000000..4fc62c4fa
--- /dev/null
+++ b/kernel/arch/arm/configs/omap3_beagle_android_defconfig
@@ -0,0 +1,2419 @@
+#
+# Automatically generated make config: don't edit
+# Linux/arm 2.6.37 Kernel Configuration
+# Mon Apr 16 13:58:06 2012
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_HAVE_GENERIC_HARDIRQS is not set
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_ASHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_S5PV310 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_TCC_926 is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_PLAT_SPEAR is not set
+
+#
+# TI OMAP Common Features
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2PLUS=y
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_SMARTREFLEX=y
+CONFIG_OMAP_SMARTREFLEX_CLASS3=y
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_IOMMU=y
+# CONFIG_OMAP_IOMMU_DEBUG is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_PM_NONE is not set
+CONFIG_OMAP_PM_NOOP=y
+
+#
+# TI OMAP2/3/4 Specific Features
+#
+CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_ARCH_TI81XX is not set
+CONFIG_ARCH_OMAP3430=y
+CONFIG_OMAP_PACKAGE_CBB=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_DEVKIT8000 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP3530_LV_SOM is not set
+# CONFIG_MACH_OMAP3_TORPEDO is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_FLASHBOARD is not set
+# CONFIG_MACH_OMAP3517EVM is not set
+# CONFIG_MACH_CRANEBOARD is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP3_TOUCHBOOK is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RM680 is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_ZOOM2 is not set
+# CONFIG_MACH_OMAP_ZOOM3 is not set
+# CONFIG_MACH_CM_T35 is not set
+# CONFIG_MACH_CM_T3517 is not set
+# CONFIG_MACH_IGEP0020 is not set
+# CONFIG_MACH_IGEP0030 is not set
+# CONFIG_MACH_SBC3530 is not set
+# CONFIG_MACH_OMAP_3630SDP is not set
+# CONFIG_OMAP3_EMU is not set
+CONFIG_OMAP3_PM_DISABLE_VT_SWITCH=y
+# CONFIG_OMAP3_SDRC_AC_TIMING is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_743622 is not set
+CONFIG_COMMON_CLKDEV=y
+# CONFIG_FIQ_DEBUGGER is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_NVS=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HAS_WAKELOCK=y
+CONFIG_HAS_EARLYSUSPEND=y
+CONFIG_WAKELOCK=y
+CONFIG_WAKELOCK_STAT=y
+CONFIG_USER_WAKELOCK=y
+CONFIG_EARLYSUSPEND=y
+# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set
+# CONFIG_CONSOLE_EARLYSUSPEND is not set
+CONFIG_FB_EARLYSUSPEND=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_OPS=y
+CONFIG_ARCH_HAS_OPP=y
+CONFIG_PM_OPP=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL is not set
+CONFIG_ANDROID_PARANOID_NETWORK=y
+CONFIG_NET_ACTIVITY_STATS=y
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+
+#
+# Some wireless drivers require a rate control algorithm
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+CONFIG_MTD_OOPS=y
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=y
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM63XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_SMSC911X_ARCH_HOOKS is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+CONFIG_NETDEV_1000=y
+CONFIG_TI_DAVINCI_EMAC=y
+CONFIG_TI_DAVINCI_MDIO=y
+CONFIG_TI_DAVINCI_CPDMA=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NETDEV_10000=y
+CONFIG_WLAN=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_BCM4329 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_WL12XX_PLATFORM_DATA=y
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
+CONFIG_USB_NET_SMSC95XX=y
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_WAN is not set
+
+#
+# CAIF transport drivers
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_KEYRESET is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_QT602240 is not set
+CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_TSC2004 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYCHORD is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+# CONFIG_INPUT_TWL4030_VIBRA is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_GPIO is not set
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVMEM=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX3107 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_OMAP=y
+CONFIG_SERIAL_OMAP_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TI81XX_HDMI is not set
+# CONFIG_DCC_TTY is not set
+# CONFIG_RAMOOPS is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_BASIC_MMIO is not set
+# CONFIG_GPIO_IT8761E is not set
+# CONFIG_GPIO_VX855 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+CONFIG_GPIO_TWL4030=y
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_BQ20Z75 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_CHARGER_ISP1704 is not set
+# CONFIG_CHARGER_TWL4030 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_TWL4030_WATCHDOG=y
+# CONFIG_MAX63XX_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_MFD_SUPPORT=y
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+CONFIG_TWL4030_CORE=y
+CONFIG_TWL4030_POWER=y
+CONFIG_TWL4030_SCRIPT=y
+CONFIG_TWL4030_CODEC=y
+# CONFIG_TWL6030_PWM is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC35892 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_TPS6586X is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_DUMMY=y
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_AD5398 is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_IR_CORE is not set
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA827X=y
+CONFIG_MEDIA_TUNER_TDA18271=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_CONTIG=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TDA9875 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# RDS decoders
+#
+# CONFIG_VIDEO_SAA6588 is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_ADV7180 is not set
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_MT9T001 is not set
+CONFIG_VIDEO_MT9V011=y
+# CONFIG_VIDEO_MT9V032 is not set
+CONFIG_VIDEO_MT9V113=y
+# CONFIG_VIDEO_MT9T111 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_SAA7110 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_SAA7191 is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_TVP7002 is not set
+# CONFIG_VIDEO_VPX3220 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+# CONFIG_VIDEO_THS7303 is not set
+# CONFIG_VIDEO_ADV7343 is not set
+# CONFIG_VIDEO_AK881X is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+# CONFIG_VIDEO_VPSS_SYSTEM is not set
+# CONFIG_VIDEO_VPFE_CAPTURE is not set
+CONFIG_VIDEO_OMAP2_VOUT=y
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SR030PC30 is not set
+CONFIG_VIDEO_OMAP3=y
+CONFIG_VIDEO_OMAP3_DEBUG=y
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+# CONFIG_USB_GSPCA is not set
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_TMIO is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_VRAM=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=4
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
+CONFIG_OMAP2_DSS_DPI=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+CONFIG_OMAP2_VENC_OUT_TYPE_SVIDEO=y
+# CONFIG_OMAP2_VENC_OUT_TYPE_COMPOSITE is not set
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+CONFIG_FB_OMAP2_NUM_FBS=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
+# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
+CONFIG_PANEL_SHARP_LS037V7DW01=y
+# CONFIG_PANEL_SHARP_LQ043T1DG01 is not set
+# CONFIG_PANEL_SAMSUNG_LMS700KF23 is not set
+# CONFIG_PANEL_TAAL is not set
+# CONFIG_PANEL_TOPPOLY_TDO35S is not set
+# CONFIG_PANEL_TPO_TD043MTEA1 is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+# CONFIG_LCD_S6E63M0 is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=m
+# CONFIG_BACKLIGHT_ADP8860 is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SND_SOC_WL1271BT is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_3M_PCT is not set
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX_FF is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CANDO is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EGALAX is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MOSART is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_QUANTA is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_ROCCAT_KONE is not set
+# CONFIG_HID_ROCCAT_PYRA is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_STANTUM is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+
+#
+# Platform Glue Layer
+#
+# CONFIG_USB_MUSB_TUSB6010_GLUE is not set
+CONFIG_USB_MUSB_OMAP2PLUS_GLUE=y
+# CONFIG_USB_MUSB_AM35X_GLUE is not set
+# CONFIG_USB_MUSB_DAVINCI is not set
+# CONFIG_USB_MUSB_DA8XX is not set
+# CONFIG_USB_MUSB_TUSB6010 is not set
+CONFIG_USB_MUSB_OMAP2PLUS=y
+# CONFIG_USB_MUSB_AM35X is not set
+# CONFIG_USB_MUSB_TI81XX is not set
+# CONFIG_USB_MUSB_BLACKFIN is not set
+# CONFIG_USB_MUSB_UX500 is not set
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA_HW=y
+# CONFIG_USB_TI_CPPI_DMA_HW is not set
+# CONFIG_USB_TI_CPPI41_DMA_HW is not set
+CONFIG_USB_INVENTRA_DMA=y
+CONFIG_MUSB_USE_SYSTEM_DMA_WORKAROUND=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_TI_CPPI41_DMA is not set
+# CONFIG_USB_TUSB_OMAP_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_UAS is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_ANDROID=y
+# CONFIG_USB_ANDROID_ACM is not set
+CONFIG_USB_ANDROID_ADB=y
+CONFIG_USB_ANDROID_MASS_STORAGE=y
+# CONFIG_USB_ANDROID_MTP is not set
+# CONFIG_USB_ANDROID_RNDIS is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_EMBEDDED_SDIO is not set
+# CONFIG_MMC_PARANOID_SD_INIT is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_SWITCH=y
+# CONFIG_SWITCH_GPIO is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+CONFIG_RTC_INTF_ALARM=y
+CONFIG_RTC_INTF_ALARM_DEV=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_ECHO is not set
+# CONFIG_BRCM80211 is not set
+# CONFIG_RT2870 is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_R8712U is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE=128
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE=16
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE=8
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_OUTPUT=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+# CONFIG_POHMELFS is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_VT6656 is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_IIO is not set
+# CONFIG_ZRAM is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_FB_SM7XX is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_ADIS16255 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_EASYCAP is not set
+# CONFIG_TIDSPBRIDGE is not set
+# CONFIG_WESTBRIDGE is not set
+CONFIG_WESTBRIDGE_HAL_SELECTED=y
+CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y
+# CONFIG_MACH_NO_WESTBRIDGE is not set
+# CONFIG_ATH6K_LEGACY is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_YAFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFS_USE_LEGACY_DNS=y
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+CONFIG_BKL=y
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_STACKTRACE=y
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_LKDTM is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_KPROBE_EVENT=y
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_STRICT_DEVMEM is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_IMA is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set
+# CONFIG_CRYPTO_DEV_OMAP_AES is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/kernel/arch/arm/configs/panda_defconfig b/kernel/arch/arm/configs/panda_defconfig
new file mode 100644
index 0000000..4c5e56c
--- /dev/null
+++ b/kernel/arch/arm/configs/panda_defconfig
@@ -0,0 +1,331 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_ASHMEM=y
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_OMAP=y
+CONFIG_OMAP_RESET_CLOCKS=y
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_MACH_OMAP_4430SDP is not set
+CONFIG_ARM_THUMBEE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_SMP_ON_UP is not set
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_CMDLINE="console=ttyO2,115200n8 mem=1G androidboot.console=ttyO2"
+CONFIG_CMDLINE_EXTEND=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_OMAP_SMARTREFLEX=y
+CONFIG_OMAP_SMARTREFLEX_CLASS1P5=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=y
+CONFIG_WAKELOCK=y
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_PHONET=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_WILINK=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_ONENAND=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+# CONFIG_ANDROID_PMEM is not set
+CONFIG_KERNEL_DEBUGGER_CORE=y
+CONFIG_UID_STAT=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_IFB=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_PPP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_HW_RANDOM=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_TWL4030=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_HWMON is not set
+CONFIG_TWL6030_PWM=y
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_PVR_SGX=y
+CONFIG_PVR_NEED_PVR_DPF=y
+CONFIG_PVR_NEED_PVR_ASSERT=y
+CONFIG_PVR_USSE_EDM_STATUS_DEBUG=y
+CONFIG_FB=y
+CONFIG_OMAP2_DSS=y
+# CONFIG_OMAP2_DSS_VENC is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_NUM_FBS=2
+CONFIG_OMAP2_VRAM_SIZE=16
+CONFIG_PANEL_GENERIC_DPI=y
+CONFIG_DISPLAY_SUPPORT=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
+CONFIG_USB_MUSB_PERIPHERAL=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_KEYSPAN=y
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_G_ANDROID=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRC_CCITT=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_SDP4430=y
+CONFIG_SND_OMAP_SOC_OMAP4_HDMI=y
+CONFIG_OMAP_HSI=y
+CONFIG_OMAP_HSI_DEVICE=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+CONFIG_LIB80211=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+CONFIG_USB_ZD1201=y
+CONFIG_WL12XX_MENU=y
+CONFIG_WL12XX=y
+CONFIG_WL12XX_SDIO=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_OMAP_TEMP_SENSOR=y
+CONFIG_OMAP_DIE_TEMP_SENSOR=y
+CONFIG_TI_ST=y
+CONFIG_KEYBOARD_GPIO=y
diff --git a/kernel/arch/arm/mach-omap2/board-omap3beagle.c b/kernel/arch/arm/mach-omap2/board-omap3beagle.c
new file mode 100644
index 0000000..b3d1b81
--- /dev/null
+++ b/kernel/arch/arm/mach-omap2/board-omap3beagle.c
@@ -0,0 +1,1038 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3beagle.c
+ *
+ * Copyright (C) 2008 Texas Instruments
+ *
+ * Modified from mach-omap2/board-3430sdp.c
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
+
+#include <linux/usb/android_composite.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/display.h>
+#include <plat/gpmc.h>
+#include <plat/nand.h>
+#include <plat/usb.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "timer-gp.h"
+#include "board-flash.h"
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4
+#include <linux/input/synaptics_dsx.h>
+
+#define TM_SAMPLE1	(1)	// 2D only
+#define TM_SAMPLE2	(2)	// 2D + 0D x 2
+#define TM_SAMPLE3	(3)	// 2D + 0D x 4
+#define SYNAPTICS_MODULE TM_SAMPLE1
+#endif
+
+#define NAND_BLOCK_SIZE		SZ_128K
+
+#ifdef CONFIG_USB_ANDROID
+#define GOOGLE_VENDOR_ID		0x18d1
+#define GOOGLE_PRODUCT_ID		0x9018
+#define GOOGLE_ADB_PRODUCT_ID		0x9015
+#endif
+
+/* 	Synaptics Thin Driver	*/
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4
+static int synaptics_gpio_setup(unsigned gpio, bool configure)
+{
+	int retval=0;
+	if (configure)
+	{
+		retval = gpio_request(gpio, "rmi4_attn");
+		if (retval) {
+			pr_err("%s: Failed to get attn gpio %d. Code: %d.",
+			       __func__, gpio, retval);
+			return retval;
+		}
+		omap_mux_init_signal("sdmmc2_clk.gpio_130", OMAP_PIN_INPUT_PULLUP);
+
+		retval = gpio_direction_input(gpio);
+		if (retval) {
+			pr_err("%s: Failed to setup attn gpio %d. Code: %d.",
+			       __func__, gpio, retval);
+			gpio_free(gpio);
+		}
+	} else {
+		pr_warn("%s: No way to deconfigure gpio %d.",
+		       __func__, gpio);
+	}
+
+	return retval;
+}
+
+ #if (SYNAPTICS_MODULE == TM_SAMPLE1)
+#define TM_SAMPLE1_ADDR 0x20
+#define TM_SAMPLE1_ATTN 130
+
+static unsigned char TM_SAMPLE1_f1a_button_codes[] = {};
+
+static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE1_capacitance_button_map = {
+	.nbuttons = ARRAY_SIZE(TM_SAMPLE1_f1a_button_codes),
+	.map = TM_SAMPLE1_f1a_button_codes,
+};
+
+static struct synaptics_rmi4_platform_data rmi4_platformdata = {
+	.irq_flags = IRQF_TRIGGER_FALLING,
+	.irq_gpio = TM_SAMPLE1_ATTN,
+ 	.gpio_config = synaptics_gpio_setup,
+	.capacitance_button_map = &TM_SAMPLE1_capacitance_button_map,
+};
+
+static struct i2c_board_info bus2_i2c_devices[] = {
+ 	{
+ 		I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE1_ADDR),
+ 		.platform_data = &rmi4_platformdata,
+     	},	
+};
+
+#elif (SYNAPTICS_MODULE == TM_SAMPLE2)
+#define TM_SAMPLE2_ADDR 0x20
+#define TM_SAMPLE2_ATTN 130
+
+static unsigned char TM_SAMPLE2_f1a_button_codes[] = {KEY_MENU, KEY_BACK};
+
+static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE2_capacitance_button_map = {
+	.nbuttons = ARRAY_SIZE(TM_SAMPLE2_f1a_button_codes),
+	.map = TM_SAMPLE2_f1a_button_codes,
+};
+
+static struct synaptics_rmi4_platform_data rmi4_platformdata = {
+	.irq_flags = IRQF_TRIGGER_FALLING,
+	.irq_gpio = TM_SAMPLE2_ATTN,
+ 	.gpio_config = synaptics_gpio_setup,
+ 	.capacitance_button_map = &TM_SAMPLE2_capacitance_button_map,
+};
+
+static struct i2c_board_info bus2_i2c_devices[] = {
+ 	{
+ 		I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE2_ADDR),
+ 		.platform_data = &rmi4_platformdata,
+     	},
+};
+
+#elif (SYNAPTICS_MODULE == TM_SAMPLE3)
+#define TM_SAMPLE3_ADDR	0x20
+#define TM_SAMPLE3_ATTN	130
+
+static unsigned char TM_SAMPLE3_f1a_button_codes[] = {KEY_MENU, KEY_HOME,KEY_BACK,KEY_SEARCH};
+
+static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE3_capacitance_button_map = {
+	.nbuttons = ARRAY_SIZE(TM_SAMPLE3_f1a_button_codes),
+	.map = TM_SAMPLE3_f1a_button_codes,
+};
+
+static struct synaptics_rmi4_platform_data rmi4_platformdata = {
+	.irq_flags = IRQF_TRIGGER_FALLING,
+	.irq_gpio = TM_SAMPLE3_ATTN,
+	.gpio_config = synaptics_gpio_setup,
+	.capacitance_button_map = &TM_SAMPLE3_capacitance_button_map,
+};
+
+static struct i2c_board_info bus2_i2c_devices[] = {
+     {
+         I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE3_ADDR),
+         .platform_data = &rmi4_platformdata,
+     },
+};
+#endif
+
+void __init i2c_device_setup(void)
+{
+	pr_info(">>>>I2C device setup.");
+	if (ARRAY_SIZE(bus2_i2c_devices)) {
+		i2c_register_board_info(2, bus2_i2c_devices,
+					ARRAY_SIZE(bus2_i2c_devices));
+    }
+}
+
+/* End of Synaptics change for beagle board */
+
+static char *usb_functions_adb[] = {
+	"adb",
+};
+
+static char *usb_functions_mass_storage[] = {
+	"usb_mass_storage",
+};
+static char *usb_functions_ums_adb[] = {
+	"usb_mass_storage",
+	"adb",
+};
+
+static char *usb_functions_all[] = {
+	"adb", "usb_mass_storage",
+};
+
+static struct android_usb_product usb_products[] = {
+	{
+		.product_id	= GOOGLE_PRODUCT_ID,
+		.num_functions	= ARRAY_SIZE(usb_functions_adb),
+		.functions	= usb_functions_adb,
+	},
+	{
+		.product_id	= GOOGLE_PRODUCT_ID,
+		.num_functions	= ARRAY_SIZE(usb_functions_mass_storage),
+		.functions	= usb_functions_mass_storage,
+	},
+	{
+		.product_id	= GOOGLE_PRODUCT_ID,
+		.num_functions	= ARRAY_SIZE(usb_functions_ums_adb),
+		.functions	= usb_functions_ums_adb,
+	},
+};
+
+static struct usb_mass_storage_platform_data mass_storage_pdata = {
+	.nluns		= 1,
+	.vendor		= "rowboat",
+	.product	= "rowboat gadget",
+	.release	= 0x100,
+};
+
+static struct platform_device usb_mass_storage_device = {
+	.name	= "usb_mass_storage",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &mass_storage_pdata,
+	},
+};
+
+static struct android_usb_platform_data android_usb_pdata = {
+	.vendor_id	= GOOGLE_VENDOR_ID,
+	.product_id	= GOOGLE_PRODUCT_ID,
+	.functions	= usb_functions_all,
+	.products	= usb_products,
+	.num_products	= ARRAY_SIZE(usb_products),
+	.version	= 0x0100,
+	.product_name	= "rowboat gadget",
+	.manufacturer_name	= "rowboat",
+	.serial_number	= "20100720",
+	.num_functions	= ARRAY_SIZE(usb_functions_all),
+};
+
+static struct platform_device androidusb_device = {
+	.name	= "android_usb",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &android_usb_pdata,
+	},
+};
+
+static void omap3beagle_android_gadget_init(void)
+{
+	platform_device_register(&androidusb_device);
+}
+#endif
+/*
+ * OMAP3 Beagle revision
+ * Run time detection of Beagle revision is done by reading GPIO.
+ * GPIO ID -
+ *	AXBX	= GPIO173, GPIO172, GPIO171: 1 1 1
+ *	C1_3	= GPIO173, GPIO172, GPIO171: 1 1 0
+ *	C4	= GPIO173, GPIO172, GPIO171: 1 0 1
+ *	XM	= GPIO173, GPIO172, GPIO171: 0 0 0
+ */
+enum {
+	OMAP3BEAGLE_BOARD_UNKN = 0,
+	OMAP3BEAGLE_BOARD_AXBX,
+	OMAP3BEAGLE_BOARD_C1_3,
+	OMAP3BEAGLE_BOARD_C4,
+	OMAP3BEAGLE_BOARD_XM,
+	OMAP3BEAGLE_BOARD_XMC,
+};
+
+extern void omap_pm_sys_offmode_select(int);
+extern void omap_pm_sys_offmode_pol(int);
+extern void omap_pm_sys_clkreq_pol(int);
+extern void omap_pm_auto_off(int);
+extern void omap_pm_auto_ret(int);
+
+static u8 omap3_beagle_version;
+
+static u8 omap3_beagle_get_rev(void)
+{
+	return omap3_beagle_version;
+}
+
+/**
+ * Board specific initialization of PM components
+ */
+static void __init omap3_beagle_pm_init(void)
+{
+	/* Use sys_offmode signal */
+	omap_pm_sys_offmode_select(1);
+
+	/* sys_clkreq - active high */
+	omap_pm_sys_clkreq_pol(1);
+
+	/* sys_offmode - active low */
+	omap_pm_sys_offmode_pol(0);
+
+	/* Automatically send OFF command */
+	omap_pm_auto_off(1);
+
+	/* Automatically send RET command */
+	omap_pm_auto_ret(1);
+}
+
+static void __init omap3_beagle_init_rev(void)
+{
+	int ret;
+	u16 beagle_rev = 0;
+
+	omap_mux_init_gpio(171, OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_gpio(172, OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_gpio(173, OMAP_PIN_INPUT_PULLUP);
+
+	ret = gpio_request(171, "rev_id_0");
+	if (ret < 0)
+		goto fail0;
+
+	ret = gpio_request(172, "rev_id_1");
+	if (ret < 0)
+		goto fail1;
+
+	ret = gpio_request(173, "rev_id_2");
+	if (ret < 0)
+		goto fail2;
+
+	gpio_direction_input(171);
+	gpio_direction_input(172);
+	gpio_direction_input(173);
+
+	beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1)
+			| (gpio_get_value(173) << 2);
+
+	switch (beagle_rev) {
+	case 7:
+		printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
+		break;
+	case 6:
+		printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
+		break;
+	case 5:
+		printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
+		break;
+	case 2:
+		printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
+		break;
+	case 0:
+		printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+		break;
+	default:
+		printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
+	}
+
+	return;
+
+fail2:
+	gpio_free(172);
+fail1:
+	gpio_free(171);
+fail0:
+	printk(KERN_ERR "Unable to get revision detection GPIO pins\n");
+	omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
+
+	return;
+}
+
+static struct mtd_partition omap3beagle_nand_partitions[] = {
+	/* All the partition sizes are listed in terms of NAND block size */
+	{
+		.name		= "X-Loader",
+		.offset		= 0,
+		.size		= 4 * NAND_BLOCK_SIZE,
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+	{
+		.name		= "U-Boot",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x80000 */
+		.size		= 15 * NAND_BLOCK_SIZE,
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+	{
+		.name		= "U-Boot Env",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x260000 */
+		.size		= 1 * NAND_BLOCK_SIZE,
+	},
+	{
+		.name		= "Kernel",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x280000 */
+		.size		= 32 * NAND_BLOCK_SIZE,
+	},
+	{
+		.name		= "File System",
+		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x680000 */
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+/* DSS */
+
+static int beagle_enable_dvi(struct omap_dss_device *dssdev)
+{
+	if (gpio_is_valid(dssdev->reset_gpio))
+		gpio_set_value(dssdev->reset_gpio, 1);
+
+	return 0;
+}
+
+static void beagle_disable_dvi(struct omap_dss_device *dssdev)
+{
+	if (gpio_is_valid(dssdev->reset_gpio))
+		gpio_set_value(dssdev->reset_gpio, 0);
+}
+
+static struct omap_dss_device beagle_dvi_device = {
+	.type = OMAP_DISPLAY_TYPE_DPI,
+	.name = "dvi",
+	.driver_name = "generic_panel",
+	.phy.dpi.data_lines = 24,
+	.reset_gpio = -EINVAL,
+	.platform_enable = beagle_enable_dvi,
+	.platform_disable = beagle_disable_dvi,
+};
+
+static struct omap_dss_device beagle_tv_device = {
+	.name = "tv",
+	.driver_name = "venc",
+	.type = OMAP_DISPLAY_TYPE_VENC,
+	.phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+};
+
+static struct omap_dss_device *beagle_dss_devices[] = {
+	&beagle_dvi_device,
+	&beagle_tv_device,
+};
+
+static struct omap_dss_board_info beagle_dss_data = {
+	.num_devices = ARRAY_SIZE(beagle_dss_devices),
+	.devices = beagle_dss_devices,
+	.default_device = &beagle_dvi_device,
+};
+
+static struct platform_device beagle_dss_device = {
+	.name          = "omapdss",
+	.id            = -1,
+	.dev            = {
+		.platform_data = &beagle_dss_data,
+	},
+};
+
+static struct regulator_consumer_supply beagle_vdac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss");
+
+static struct regulator_consumer_supply beagle_vdvi_supply =
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+
+static void __init beagle_display_init(void)
+{
+	int r;
+
+	r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset");
+	if (r < 0) {
+		printk(KERN_ERR "Unable to get DVI reset GPIO\n");
+		return;
+	}
+
+	gpio_direction_output(beagle_dvi_device.reset_gpio, 0);
+}
+
+#include "sdram-micron-mt46h32m32lf-6.h"
+
+static struct omap2_hsmmc_info mmc[] = {
+	{
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+		.gpio_wp	= 29,
+	},
+	{}	/* Terminator */
+};
+
+static struct regulator_consumer_supply beagle_vmmc1_supply = {
+	.supply			= "vmmc",
+};
+
+static struct regulator_consumer_supply beagle_vsim_supply = {
+	.supply			= "vmmc_aux",
+};
+
+static struct regulator_consumer_supply beagle_vaux3_supply = {
+	.supply         = "cam_1v8",
+};
+
+static struct regulator_consumer_supply beagle_vaux4_supply = {
+	.supply         = "cam_2v8",
+};
+
+static struct gpio_led gpio_leds[];
+
+static int beagle_twl_gpio_setup(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
+		mmc[0].gpio_wp = -EINVAL;
+	} else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
+		(omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
+		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
+		mmc[0].gpio_wp = 23;
+	} else {
+		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
+	}
+	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+	mmc[0].gpio_cd = gpio + 0;
+	omap2_hsmmc_init(mmc);
+
+	/* link regulators to MMC adapters */
+	beagle_vmmc1_supply.dev = mmc[0].dev;
+	beagle_vsim_supply.dev = mmc[0].dev;
+
+	/* REVISIT: need ehci-omap hooks for external VBUS
+	 * power switch and overcurrent detect
+	 */
+	if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
+		gpio_request(gpio + 1, "EHCI_nOC");
+		gpio_direction_input(gpio + 1);
+	}
+
+	/*
+	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
+	 * high / others active low)
+	 */
+	gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+	gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
+		gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+	else
+		gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+
+	/* DVI reset GPIO is different between beagle revisions */
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC)
+		beagle_dvi_device.reset_gpio = 129;
+	else
+		beagle_dvi_device.reset_gpio = 170;
+
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+		/* Power on camera interface */
+		gpio_request(gpio + 2, "CAM_EN");
+		gpio_direction_output(gpio + 2, 1);
+
+		/* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+		gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+		gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+	} else {
+		gpio_request(gpio + 1, "EHCI_nOC");
+		gpio_direction_input(gpio + 1);
+
+		/* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+		gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+		gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+	}
+	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+
+	/*
+	 * gpio + 1 on Xm controls the TFP410's enable line (active low)
+	 * gpio + 2 control varies depending on the board rev as follows:
+	 * P7/P8 revisions(prototype): Camera EN
+	 * A2+ revisions (production): LDO (supplies DVI, serial, led blocks)
+	 */
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
+		gpio_request(gpio + 1, "nDVI_PWR_EN");
+		gpio_direction_output(gpio + 1, 0);
+		gpio_request(gpio + 2, "DVI_LDO_EN");
+		gpio_direction_output(gpio + 2, 1);
+	}
+
+	return 0;
+}
+
+static struct twl4030_gpio_platform_data beagle_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.use_leds	= true,
+	.pullups	= BIT(1),
+	.pulldowns	= BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
+				| BIT(15) | BIT(16) | BIT(17),
+	.setup		= beagle_twl_gpio_setup,
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data beagle_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vmmc1_supply,
+};
+
+/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+static struct regulator_init_data beagle_vsim = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 3000000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vsim_supply,
+};
+
+/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+static struct regulator_init_data beagle_vdac = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vdac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data beagle_vpll2 = {
+	.constraints = {
+		.name			= "VDVI",
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vdvi_supply,
+};
+
+/* VAUX3 for CAM_1V8 */
+static struct regulator_init_data beagle_vaux3 = {
+	.constraints = {
+		.min_uV                 = 1800000,
+		.max_uV                 = 1800000,
+		.apply_uV               = true,
+		.valid_modes_mask       = REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask         = REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = 1,
+	.consumer_supplies      = &beagle_vaux3_supply,
+};
+
+ /* VAUX4 for CAM_2V8 */
+static struct regulator_init_data beagle_vaux4 = {
+	.constraints = {
+		.min_uV                 = 1800000,
+		.max_uV                 = 1800000,
+		.apply_uV               = true,
+		.valid_modes_mask       = REGULATOR_MODE_NORMAL
+			| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask         = REGULATOR_CHANGE_MODE
+			| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = 1,
+	.consumer_supplies      = &beagle_vaux4_supply,
+};
+
+static struct twl4030_usb_data beagle_usb_data = {
+	.usb_mode	= T2_USB_MODE_ULPI,
+};
+
+/**
+ * Macro to configure resources
+ */
+#define TWL4030_RESCONFIG(res,grp,typ1,typ2,state)	\
+	{						\
+		.resource	= res,			\
+		.devgroup	= grp,			\
+		.type		= typ1,			\
+		.type2		= typ2,			\
+		.remap_sleep	= state			\
+	}
+
+static struct twl4030_resconfig  __initdata board_twl4030_rconfig[] = {
+	TWL4030_RESCONFIG(RES_VPLL1, DEV_GRP_P1, 3, 1, RES_STATE_OFF),		/* ? */
+	TWL4030_RESCONFIG(RES_VINTANA1, DEV_GRP_ALL, 1, 2, RES_STATE_SLEEP),
+	TWL4030_RESCONFIG(RES_VINTANA2, DEV_GRP_ALL, 0, 2, RES_STATE_SLEEP),
+	TWL4030_RESCONFIG(RES_VINTDIG, DEV_GRP_ALL, 1, 2, RES_STATE_SLEEP),
+	TWL4030_RESCONFIG(RES_VIO, DEV_GRP_ALL, 2, 2, RES_STATE_SLEEP),
+	TWL4030_RESCONFIG(RES_VDD1, DEV_GRP_P1, 4, 1, RES_STATE_OFF),		/* ? */
+	TWL4030_RESCONFIG(RES_VDD2, DEV_GRP_P1, 3, 1, RES_STATE_OFF),		/* ? */
+	TWL4030_RESCONFIG(RES_REGEN, DEV_GRP_ALL, 2, 1, RES_STATE_SLEEP),
+	TWL4030_RESCONFIG(RES_NRES_PWRON, DEV_GRP_ALL, 0, 1, RES_STATE_SLEEP),
+	TWL4030_RESCONFIG(RES_CLKEN, DEV_GRP_ALL, 3, 2, RES_STATE_SLEEP),
+	TWL4030_RESCONFIG(RES_SYSEN, DEV_GRP_ALL, 6, 1, RES_STATE_SLEEP),
+	TWL4030_RESCONFIG(RES_HFCLKOUT, DEV_GRP_P3, 0, 2, RES_STATE_SLEEP),	/* ? */
+	TWL4030_RESCONFIG(0, 0, 0, 0, 0),
+};
+
+/**
+ * Optimized 'Active to Sleep' sequence
+ */
+static struct twl4030_ins omap3beagle_sleep_seq[] __initdata = {
+	{ MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 20},
+	{ MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, RES_STATE_SLEEP), 2 },
+	{ MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_SLEEP), 2 },
+};
+
+static struct twl4030_script omap3beagle_sleep_script __initdata = {
+	.script	= omap3beagle_sleep_seq,
+	.size	= ARRAY_SIZE(omap3beagle_sleep_seq),
+	.flags	= TWL4030_SLEEP_SCRIPT,
+};
+
+/**
+ * Optimized 'Sleep to Active (P12)' sequence
+ */
+static struct twl4030_ins omap3beagle_wake_p12_seq[] __initdata = {
+	{ MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, RES_STATE_ACTIVE), 2 }
+};
+
+static struct twl4030_script omap3beagle_wake_p12_script __initdata = {
+	.script = omap3beagle_wake_p12_seq,
+	.size   = ARRAY_SIZE(omap3beagle_wake_p12_seq),
+	.flags  = TWL4030_WAKEUP12_SCRIPT,
+};
+
+/**
+ * Optimized 'Sleep to Active' (P3) sequence
+ */
+static struct twl4030_ins omap3beagle_wake_p3_seq[] __initdata = {
+	{ MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_ACTIVE), 2 }
+};
+
+static struct twl4030_script omap3beagle_wake_p3_script __initdata = {
+	.script = omap3beagle_wake_p3_seq,
+	.size   = ARRAY_SIZE(omap3beagle_wake_p3_seq),
+	.flags  = TWL4030_WAKEUP3_SCRIPT,
+};
+
+/**
+ * Optimized warm reset sequence (for less power surge)
+ */
+static struct twl4030_ins omap3beagle_wrst_seq[] __initdata = {
+	{ MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 0x2 },
+	{ MSG_SINGULAR(DEV_GRP_NULL, RES_MAIN_REF, RES_STATE_WRST), 2 },
+	{ MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_WRST), 0x2},
+	{ MSG_SINGULAR(DEV_GRP_NULL, RES_VUSB_3V1, RES_STATE_WRST), 0x2 },
+	{ MSG_SINGULAR(DEV_GRP_NULL, RES_VPLL1, RES_STATE_WRST), 0x2 },
+	{ MSG_SINGULAR(DEV_GRP_NULL, RES_VDD2, RES_STATE_WRST), 0x7 },
+	{ MSG_SINGULAR(DEV_GRP_NULL, RES_VDD1, RES_STATE_WRST), 0x25 },
+	{ MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0, RES_STATE_WRST), 0x2 },
+	{ MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 0x2 },
+
+};
+
+static struct twl4030_script omap3beagle_wrst_script __initdata = {
+	.script = omap3beagle_wrst_seq,
+	.size   = ARRAY_SIZE(omap3beagle_wrst_seq),
+	.flags  = TWL4030_WRST_SCRIPT,
+};
+
+static struct twl4030_script __initdata *board_twl4030_scripts[] = {
+	&omap3beagle_wake_p12_script,
+	&omap3beagle_wake_p3_script,
+	&omap3beagle_sleep_script,
+	&omap3beagle_wrst_script
+};
+
+static struct twl4030_power_data __initdata omap3beagle_script_data = {
+	.scripts		= board_twl4030_scripts,
+	.num			= ARRAY_SIZE(board_twl4030_scripts),
+	.resource_config	= board_twl4030_rconfig,
+};
+
+static struct twl4030_codec_audio_data beagle_audio_data = {
+	.audio_mclk = 26000000,
+	.digimic_delay = 1,
+	.ramp_delay_value = 1,
+	.offset_cncl_path = 1,
+	.check_defaults = false,
+	.reset_registers = false,
+	.reset_registers = false,
+};
+
+static struct twl4030_codec_data beagle_codec_data = {
+	.audio_mclk = 26000000,
+	.audio = &beagle_audio_data,
+};
+
+static struct twl4030_platform_data beagle_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.usb		= &beagle_usb_data,
+	.gpio		= &beagle_gpio_data,
+	.codec		= &beagle_codec_data,
+	.vmmc1		= &beagle_vmmc1,
+	.vsim		= &beagle_vsim,
+	.vdac		= &beagle_vdac,
+	.vpll2		= &beagle_vpll2,
+	.vaux3		= &beagle_vaux3,
+	.vaux4		= &beagle_vaux4,
+	.power		= &omap3beagle_script_data,
+};
+
+static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_34XX_SYS_NIRQ,
+		.platform_data = &beagle_twldata,
+	},
+};
+
+static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
+       {
+               I2C_BOARD_INFO("eeprom", 0x50),
+       },
+};
+
+static int __init omap3_beagle_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
+			ARRAY_SIZE(beagle_i2c_boardinfo));
+
+	/* Bus 2 is used for Camera/Sensor interface */
+	if (ARRAY_SIZE(bus2_i2c_devices))
+		omap_register_i2c_bus(2, 400, bus2_i2c_devices,
+				      ARRAY_SIZE(bus2_i2c_devices));
+	else
+	omap_register_i2c_bus(2, 400, NULL, 0);
+
+	/* Bus 3 is attached to the DVI port where devices like the pico DLP
+	 * projector don't work reliably with 400kHz */
+	omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
+
+	return 0;
+}
+
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "beagleboard::usr0",
+		.default_trigger	= "heartbeat",
+		.gpio			= 150,
+	},
+	{
+		.name			= "beagleboard::usr1",
+		.default_trigger	= "mmc0",
+		.gpio			= 149,
+	},
+	{
+		.name			= "beagleboard::pmu_stat",
+		.gpio			= -EINVAL,	/* gets replaced */
+		.active_low		= true,
+	},
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gpio_led_info,
+	},
+};
+
+static struct gpio_keys_button gpio_buttons[] = {
+	{
+		.code			= KEY_POWER,
+		.gpio			= 4,
+		.desc			= "user",
+		.wakeup			= 1,
+	},
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+	.buttons	= gpio_buttons,
+	.nbuttons	= ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device keys_gpio = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gpio_key_info,
+	},
+};
+
+static void __init omap3_beagle_init_irq(void)
+{
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
+	omap_init_irq();
+	gpmc_init();
+#ifdef CONFIG_OMAP_32K_TIMER
+	if (omap3_beagle_version == OMAP3BEAGLE_BOARD_AXBX)
+		omap2_gp_clockevent_set_gptimer(12);
+	else
+		omap2_gp_clockevent_set_gptimer(1);
+#endif
+}
+
+static struct platform_device *omap3_beagle_devices[] __initdata = {
+	&leds_gpio,
+	&keys_gpio,
+	&beagle_dss_device,
+	&usb_mass_storage_device,
+};
+
+static void __init omap3beagle_flash_init(void)
+{
+	u8 cs = 0;
+	u8 nandcs = GPMC_CS_NUM + 1;
+
+	/* find out the chip-select on which NAND exists */
+	while (cs < GPMC_CS_NUM) {
+		u32 ret = 0;
+		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+		if ((ret & 0xC00) == 0x800) {
+			printk(KERN_INFO "Found NAND on CS%d\n", cs);
+			if (nandcs > GPMC_CS_NUM)
+				nandcs = cs;
+		}
+		cs++;
+	}
+
+	if (nandcs > GPMC_CS_NUM) {
+		printk(KERN_INFO "NAND: Unable to find configuration "
+				 "in GPMC\n ");
+		return;
+	}
+
+	if (nandcs < GPMC_CS_NUM) {
+		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
+		board_nand_init(omap3beagle_nand_partitions,
+			ARRAY_SIZE(omap3beagle_nand_partitions),
+			nandcs, NAND_BUSWIDTH_16);
+	}
+}
+
+static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+
+	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+
+	.phy_reset  = true,
+	.reset_gpio_port[0]  = -EINVAL,
+	.reset_gpio_port[1]  = 147,
+	.reset_gpio_port[2]  = -EINVAL
+};
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+    OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
+                OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
+                OMAP_PIN_OFF_WAKEUPENABLE),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#endif
+
+static struct omap_musb_board_data musb_board_data = {
+	.interface_type		= MUSB_INTERFACE_ULPI,
+	.mode			= MUSB_OTG,
+	.power			= 100,
+};
+
+static void __init omap3_beagle_init(void)
+{
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap3_beagle_init_rev();
+	omap3_beagle_i2c_init();
+	platform_add_devices(omap3_beagle_devices,
+			ARRAY_SIZE(omap3_beagle_devices));
+	omap_serial_init();
+
+	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
+	gpio_request(170, "DVI_nPD");
+	/* REVISIT leave DVI powered down until it's needed ... */
+	gpio_direction_output(170, true);
+
+	usb_musb_init(&musb_board_data);
+	usb_ehci_init(&ehci_pdata);
+	omap3beagle_flash_init();
+
+	/* Ensure SDRC pins are mux'd for self-refresh */
+	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+
+	beagle_display_init();
+#ifdef CONFIG_USB_ANDROID
+	omap3beagle_android_gadget_init();
+#endif
+	omap3_beagle_pm_init();
+}
+
+MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
+	/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_map_io,
+	.reserve	= omap_reserve,
+	.init_irq	= omap3_beagle_init_irq,
+	.init_machine	= omap3_beagle_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/kernel/arch/arm/mach-omap2/board-omap4panda.c b/kernel/arch/arm/mach-omap2/board-omap4panda.c
new file mode 100644
index 0000000..4f8c79d
--- /dev/null
+++ b/kernel/arch/arm/mach-omap2/board-omap4panda.c
@@ -0,0 +1,1053 @@
+/*
+ * Board support file for OMAP4430 based PandaBoard.
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Author: David Anders <x0132446@ti.com>
+ *
+ * Based on mach-omap2/board-4430sdp.c
+ *
+ * Author: Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Based on mach-omap2/board-3430sdp.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/omapfb.h>
+#include <linux/reboot.h>
+#include <linux/usb/otg.h>
+#include <linux/i2c/twl.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/wl12xx.h>
+#include <linux/memblock.h>
+#include <linux/skbuff.h>
+#include <linux/ti_wilink_st.h>
+#include <linux/platform_data/ram_console.h>
+
+#include <mach/hardware.h>
+#include <mach/omap4-common.h>
+#include <mach/emif.h>
+#include <mach/lpddr2-elpida.h>
+#include <mach/dmm.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <video/omapdss.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/usb.h>
+#include <plat/mmc.h>
+#include <plat/remoteproc.h>
+#include <plat/vram.h>
+#include <video/omap-panel-generic-dpi.h>
+#include "timer-gp.h"
+
+#include "hsmmc.h"
+#include "control.h"
+#include "mux.h"
+#include "common-board-devices.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "pm.h"
+#include "resetreason.h"
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4
+#include <linux/input/synaptics_dsx.h>
+#define TM_SAMPLE1	(1)	// 2D only
+#define TM_SAMPLE2	(2)	// 2D + 0D x 2
+#define TM_SAMPLE3	(3)	// 2D + 0D x 4
+#define SYNAPTICS_MODULE TM_SAMPLE1
+#endif
+
+#define PANDA_RAMCONSOLE_START	(PLAT_PHYS_OFFSET + SZ_512M)
+#define PANDA_RAMCONSOLE_SIZE	SZ_2M
+
+#define GPIO_HUB_POWER		1
+#define GPIO_HUB_NRESET		62
+#define GPIO_WIFI_PMENA		43
+#define GPIO_WIFI_IRQ		53
+#define HDMI_GPIO_CT_CP_HPD     60
+#define HDMI_GPIO_HPD 63 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define TPS62361_GPIO   7 /* VCORE1 power control */
+#define PANDA_BT_GPIO 46
+
+
+#define PHYS_ADDR_SMC_SIZE	(SZ_1M * 3)
+#define PHYS_ADDR_SMC_MEM	(0x80000000 + SZ_1G - PHYS_ADDR_SMC_SIZE)
+#define OMAP_ION_HEAP_SECURE_INPUT_SIZE	(SZ_1M * 90)
+#define PHYS_ADDR_DUCATI_SIZE	(SZ_1M * 105)
+#define PHYS_ADDR_DUCATI_MEM	(PHYS_ADDR_SMC_MEM - PHYS_ADDR_DUCATI_SIZE - \
+				OMAP_ION_HEAP_SECURE_INPUT_SIZE)
+
+#define WILINK_UART_DEV_NAME	"/dev/ttyO1"
+
+
+/* Synaptics changes for PandaBoard */
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4
+static int synaptics_gpio_setup(unsigned gpio, bool configure)
+{
+	int retval = 0;
+
+	if (configure) {
+		retval = gpio_request(gpio, "rmi4_attn");
+		if (retval) {
+			pr_err("%s: Failed to get attn gpio %d (code: %d)",
+					 __func__, gpio, retval);
+			return retval;
+		}
+		omap_mux_init_signal("gpmc_ad15.gpio_39", OMAP_PIN_INPUT_PULLUP);
+
+		retval = gpio_direction_input(gpio);
+		if (retval) {
+			pr_err("%s: Failed to setup attn gpio %d (code: %d)",
+					__func__, gpio, retval);
+			gpio_free(gpio);
+		}
+	} else {
+		pr_warn("%s: No way to deconfigure gpio %d",
+				__func__, gpio);
+	}
+
+	return retval;
+}
+
+ #if (SYNAPTICS_MODULE == TM_SAMPLE1)
+#define TM_SAMPLE1_ADDR 0x20
+#define TM_SAMPLE1_ATTN 130
+
+static unsigned char TM_SAMPLE1_f1a_button_codes[] = {};
+
+static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE1_capacitance_button_map = {
+	.nbuttons = ARRAY_SIZE(TM_SAMPLE1_f1a_button_codes),
+	.map = TM_SAMPLE1_f1a_button_codes,
+};
+
+static struct synaptics_rmi4_platform_data rmi4_platformdata = {
+	.irq_flags = IRQF_TRIGGER_FALLING,
+	.irq_gpio = TM_SAMPLE1_ATTN,
+ 	.gpio_config = synaptics_gpio_setup,
+	.capacitance_button_map = &TM_SAMPLE1_capacitance_button_map,
+};
+
+static struct i2c_board_info bus4_i2c_devices[] = {
+ 	{
+ 		I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE1_ADDR),
+ 		.platform_data = &rmi4_platformdata,
+     	},	
+};
+
+#elif (SYNAPTICS_MODULE == TM_SAMPLE2)
+#define TM_SAMPLE2_ADDR 0x20
+#define TM_SAMPLE2_ATTN 130
+
+static unsigned char TM_SAMPLE2_f1a_button_codes[] = {KEY_MENU, KEY_BACK};
+
+static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE2_capacitance_button_map = {
+	.nbuttons = ARRAY_SIZE(TM_SAMPLE2_f1a_button_codes),
+	.map = TM_SAMPLE2_f1a_button_codes,
+};
+
+static struct synaptics_rmi4_platform_data rmi4_platformdata = {
+	.irq_flags = IRQF_TRIGGER_FALLING,
+	.irq_gpio = TM_SAMPLE2_ATTN,
+ 	.gpio_config = synaptics_gpio_setup,
+ 	.capacitance_button_map = &TM_SAMPLE2_capacitance_button_map,
+};
+
+static struct i2c_board_info bus4_i2c_devices[] = {
+ 	{
+ 		I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE2_ADDR),
+ 		.platform_data = &rmi4_platformdata,
+     	},	
+};
+};
+
+#elif (SYNAPTICS_MODULE == TM_SAMPLE3)
+#define TM_SAMPLE3_ADDR	0x20
+#define TM_SAMPLE3_ATTN	130
+
+static unsigned char TM_SAMPLE3_f1a_button_codes[] = {KEY_MENU, KEY_HOME,KEY_BACK,KEY_SEARCH};
+
+static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE3_capacitance_button_map = {
+	.nbuttons = ARRAY_SIZE(TM_SAMPLE3_f1a_button_codes),
+	.map = TM_SAMPLE3_f1a_button_codes,
+};
+
+static struct synaptics_rmi4_platform_data rmi4_platformdata = {
+	.irq_flags = IRQF_TRIGGER_FALLING,
+	.irq_gpio = TM_SAMPLE3_ATTN,
+	.gpio_config = synaptics_gpio_setup,
+	.capacitance_button_map = &TM_SAMPLE3_capacitance_button_map,
+};
+
+static struct i2c_board_info bus4_i2c_devices[] = {
+ 	{
+ 		I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE3_ADDR),
+ 		.platform_data = &rmi4_platformdata,
+     	},	
+};
+#endif
+
+void __init i2c_device_setup(void)
+{
+	pr_info(">>>>I2C device setup");
+	if (ARRAY_SIZE(bus4_i2c_devices)) {
+		i2c_register_board_info(4, bus4_i2c_devices,
+				ARRAY_SIZE(bus4_i2c_devices));
+	}
+}
+#endif
+/* End of Synaptics changes for PandaBoard */
+
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "pandaboard::status1",
+		.default_trigger	= "heartbeat",
+		.gpio			= 7,
+	},
+	{
+		.name			= "pandaboard::status2",
+		.default_trigger	= "mmc0",
+		.gpio			= 8,
+	},
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gpio_led_info,
+	},
+};
+
+/* GPIO_KEY for the panda */
+static struct gpio_keys_button panda_gpio_keys_buttons[] = {
+	[0] = {
+		.code			= KEY_HOME,
+		.gpio			= 113,
+		.desc			= "user_button",
+		.active_low		= 1,
+		.debounce_interval	= 5,
+	},
+};
+
+static struct gpio_keys_platform_data panda_gpio_keys = {
+	.buttons		= panda_gpio_keys_buttons,
+	.nbuttons		= ARRAY_SIZE(panda_gpio_keys_buttons),
+	.rep			= 0,
+};
+
+static struct platform_device panda_gpio_keys_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &panda_gpio_keys,
+	},
+};
+
+/* TODO: handle suspend/resume here.
+ * Upon every suspend, make sure the wilink chip is
+ * capable enough to wake-up the OMAP host.
+ */
+static int plat_wlink_kim_suspend(struct platform_device *pdev, pm_message_t
+		state)
+{
+	return 0;
+}
+
+static int plat_wlink_kim_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+/* wl128x BT, FM, GPS connectivity chip */
+static struct ti_st_plat_data wilink_pdata = {
+	.nshutdown_gpio = PANDA_BT_GPIO,
+	.dev_name = WILINK_UART_DEV_NAME,
+	.flow_cntrl = 1,
+	.baud_rate = 3686400,
+	.suspend = plat_wlink_kim_suspend,
+	.resume = plat_wlink_kim_resume,
+};
+
+static struct platform_device btwilink_device = {
+	.name = "btwilink",
+	.id = -1,
+};
+
+/* wl127x BT, FM, GPS connectivity chip */
+static struct platform_device wl1271_device = {
+	.name	= "kim",
+	.id	= -1,
+	.dev.platform_data = &wilink_pdata,
+};
+
+
+static struct platform_device *panda_devices[] __initdata = {
+	&leds_gpio,
+	&wl1271_device,
+	&btwilink_device,
+	&panda_gpio_keys_device,
+};
+
+static void __init omap4_panda_init_early(void)
+{
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
+}
+
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.phy_reset  = false,
+	.reset_gpio_port[0]  = -EINVAL,
+	.reset_gpio_port[1]  = -EINVAL,
+	.reset_gpio_port[2]  = -EINVAL
+};
+
+static struct gpio panda_ehci_gpios[] __initdata = {
+	{ GPIO_HUB_POWER,	GPIOF_OUT_INIT_LOW,  "hub_power"  },
+	{ GPIO_HUB_NRESET,	GPIOF_OUT_INIT_LOW,  "hub_nreset" },
+};
+
+static void __init omap4_ehci_init(void)
+{
+	int ret;
+	struct clk *phy_ref_clk;
+
+	/* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */
+	phy_ref_clk = clk_get(NULL, "auxclk3_ck");
+	if (IS_ERR(phy_ref_clk)) {
+		pr_err("Cannot request auxclk3\n");
+		return;
+	}
+	clk_set_rate(phy_ref_clk, 19200000);
+	clk_enable(phy_ref_clk);
+
+	/* disable the power to the usb hub prior to init and reset phy+hub */
+	ret = gpio_request_array(panda_ehci_gpios,
+				 ARRAY_SIZE(panda_ehci_gpios));
+	if (ret) {
+		pr_err("Unable to initialize EHCI power/reset\n");
+		return;
+	}
+
+	gpio_export(GPIO_HUB_POWER, 0);
+	gpio_export(GPIO_HUB_NRESET, 0);
+	gpio_set_value(GPIO_HUB_NRESET, 1);
+
+	usbhs_init(&usbhs_bdata);
+
+	/* enable power to hub */
+	gpio_set_value(GPIO_HUB_POWER, 1);
+}
+
+static struct omap_musb_board_data musb_board_data = {
+	.interface_type		= MUSB_INTERFACE_UTMI,
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+	.mode			= MUSB_PERIPHERAL,
+#else
+	.mode			= MUSB_OTG,
+#endif
+	.power			= 100,
+};
+
+static struct twl4030_usb_data omap4_usbphy_data = {
+	.phy_init	= omap4430_phy_init,
+	.phy_exit	= omap4430_phy_exit,
+	.phy_power	= omap4430_phy_power,
+	.phy_set_clock	= omap4430_phy_set_clk,
+	.phy_suspend	= omap4430_phy_suspend,
+};
+
+static struct omap2_hsmmc_info mmc[] = {
+	{
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+	},
+	{
+		.name		= "wl1271",
+		.mmc		= 5,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.ocr_mask	= MMC_VDD_165_195,
+		.nonremovable	= true,
+	},
+	{}	/* Terminator */
+};
+
+static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = {
+	{
+		.supply = "vmmc",
+		.dev_name = "omap_hsmmc.0",
+	},
+};
+
+static struct regulator_consumer_supply omap4_panda_vmmc5_supply = {
+	.supply = "vmmc",
+	.dev_name = "omap_hsmmc.4",
+};
+
+static struct regulator_init_data panda_vmmc5 = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &omap4_panda_vmmc5_supply,
+};
+
+static struct fixed_voltage_config panda_vwlan = {
+	.supply_name = "vwl1271",
+	.microvolts = 1800000, /* 1.8V */
+	.gpio = GPIO_WIFI_PMENA,
+	.startup_delay = 70000, /* 70msec */
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+	.init_data = &panda_vmmc5,
+};
+
+static struct platform_device omap_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &panda_vwlan,
+	},
+};
+
+struct wl12xx_platform_data omap_panda_wlan_data  __initdata = {
+	.irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ),
+	/* PANDA ref clock is 38.4 MHz */
+	.board_ref_clock = 2,
+};
+
+static int omap4_twl6030_hsmmc_late_init(struct device *dev)
+{
+	int ret = 0;
+	struct platform_device *pdev = container_of(dev,
+				struct platform_device, dev);
+	struct omap_mmc_platform_data *pdata = dev->platform_data;
+
+	if (!pdata) {
+		dev_err(dev, "%s: NULL platform data\n", __func__);
+		return -EINVAL;
+	}
+	/* Setting MMC1 Card detect Irq */
+	if (pdev->id == 0) {
+		ret = twl6030_mmc_card_detect_config();
+		 if (ret)
+			dev_err(dev, "%s: Error card detect config(%d)\n",
+				__func__, ret);
+		 else
+			pdata->slots[0].card_detect = twl6030_mmc_card_detect;
+	}
+	return ret;
+}
+
+static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
+{
+	struct omap_mmc_platform_data *pdata;
+
+	/* dev can be null if CONFIG_MMC_OMAP_HS is not set */
+	if (!dev) {
+		pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n");
+		return;
+	}
+	pdata = dev->platform_data;
+
+	pdata->init =	omap4_twl6030_hsmmc_late_init;
+}
+
+static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
+{
+	struct omap2_hsmmc_info *c;
+
+	omap2_hsmmc_init(controllers);
+	for (c = controllers; c->mmc; c++)
+		omap4_twl6030_hsmmc_set_late_init(c->dev);
+
+	return 0;
+}
+
+static struct regulator_init_data omap4_panda_vaux2 = {
+	.constraints = {
+		.min_uV			= 1200000,
+		.max_uV			= 2800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_panda_vaux3 = {
+	.constraints = {
+		.min_uV			= 1000000,
+		.max_uV			= 3000000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* VMMC1 for MMC1 card */
+static struct regulator_init_data omap4_panda_vmmc = {
+	.constraints = {
+		.min_uV			= 1200000,
+		.max_uV			= 3000000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = 1,
+	.consumer_supplies      = omap4_panda_vmmc_supply,
+};
+
+static struct regulator_init_data omap4_panda_vpp = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 2500000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_panda_vana = {
+	.constraints = {
+		.min_uV			= 2100000,
+		.max_uV			= 2100000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_panda_vcxio = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_consumer_supply panda_vdac_supply[] = {
+	{
+		.supply = "hdmi_vref",
+	},
+};
+
+static struct regulator_init_data omap4_panda_vdac = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(panda_vdac_supply),
+	.consumer_supplies      = panda_vdac_supply,
+};
+
+static struct regulator_init_data omap4_panda_vusb = {
+	.constraints = {
+		.min_uV			= 3300000,
+		.max_uV			= 3300000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask	 =	REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_panda_clk32kg = {
+	.constraints = {
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
+		.always_on		= true,
+	},
+};
+
+static void omap4_audio_conf(void)
+{
+	/* twl6040 naudint */
+	omap_mux_init_signal("sys_nirq2.sys_nirq2", \
+		OMAP_PIN_INPUT_PULLUP);
+}
+
+static struct twl4030_codec_audio_data twl6040_audio = {
+	/* single-step ramp for headset and handsfree */
+	.hs_left_step	= 0x0f,
+	.hs_right_step	= 0x0f,
+	.hf_left_step	= 0x1d,
+	.hf_right_step	= 0x1d,
+	.hs_switch_dev  = 0x1,
+	.hs_forced_hs_state = 0x1
+};
+
+static struct twl4030_codec_data twl6040_codec = {
+	.audio		= &twl6040_audio,
+	.audpwron_gpio	= 127,
+	.naudint_irq	= OMAP44XX_IRQ_SYS_2N,
+	.irq_base	= TWL6040_CODEC_IRQ_BASE,
+};
+
+static struct twl4030_platform_data omap4_panda_twldata = {
+	.irq_base	= TWL6030_IRQ_BASE,
+	.irq_end	= TWL6030_IRQ_END,
+
+	/* Regulators */
+	.vmmc		= &omap4_panda_vmmc,
+	.vpp		= &omap4_panda_vpp,
+	.vana		= &omap4_panda_vana,
+	.vcxio		= &omap4_panda_vcxio,
+	.vdac		= &omap4_panda_vdac,
+	.vusb		= &omap4_panda_vusb,
+	.vaux2		= &omap4_panda_vaux2,
+	.vaux3		= &omap4_panda_vaux3,
+	.clk32kg	= &omap4_panda_clk32kg,
+	.usb		= &omap4_usbphy_data,
+
+	/* children */
+	.codec		= &twl6040_codec,
+};
+
+/*
+ * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
+ * is connected as I2C slave device, and can be accessed at address 0x50
+ */
+static struct i2c_board_info __initdata panda_i2c_eeprom[] = {
+	{
+		I2C_BOARD_INFO("eeprom", 0x50),
+	},
+};
+
+static int __init omap4_panda_i2c_init(void)
+{
+	omap4_pmic_init("twl6030", &omap4_panda_twldata);
+	omap_register_i2c_bus(2, 400, NULL, 0);
+	/*
+	 * Bus 3 is attached to the DVI port where devices like the pico DLP
+	 * projector don't work reliably with 400kHz
+	 */
+	omap_register_i2c_bus(3, 100, panda_i2c_eeprom,
+					ARRAY_SIZE(panda_i2c_eeprom));
+	if(ARRAY_SIZE(bus4_i2c_devices))
+		omap_register_i2c_bus(4, 400, bus4_i2c_devices, ARRAY_SIZE(bus4_i2c_devices));
+	else
+		omap_register_i2c_bus(4, 400, NULL, 0);
+	return 0;
+}
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	/* WLAN IRQ - GPIO 53 */
+	OMAP4_MUX(GPMC_NCS3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+	/* WLAN POWER ENABLE - GPIO 43 */
+	OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT),
+	/* WLAN SDIO: MMC5 CMD */
+	OMAP4_MUX(SDMMC5_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC5 CLK */
+	OMAP4_MUX(SDMMC5_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC5 DAT[0-3] */
+	OMAP4_MUX(SDMMC5_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* gpio 0 - TFP410 PD */
+	OMAP4_MUX(KPD_COL1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3),
+	/* dispc2_data23 */
+	OMAP4_MUX(USBB2_ULPITLL_STP, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data22 */
+	OMAP4_MUX(USBB2_ULPITLL_DIR, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data21 */
+	OMAP4_MUX(USBB2_ULPITLL_NXT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data20 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT0, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data19 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data18 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT2, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data15 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data14 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data13 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data12 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data11 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data10 */
+	OMAP4_MUX(DPM_EMU3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data9 */
+	OMAP4_MUX(DPM_EMU4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data16 */
+	OMAP4_MUX(DPM_EMU5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data17 */
+	OMAP4_MUX(DPM_EMU6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_hsync */
+	OMAP4_MUX(DPM_EMU7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_pclk */
+	OMAP4_MUX(DPM_EMU8, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_vsync */
+	OMAP4_MUX(DPM_EMU9, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_de */
+	OMAP4_MUX(DPM_EMU10, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data8 */
+	OMAP4_MUX(DPM_EMU11, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data7 */
+	OMAP4_MUX(DPM_EMU12, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data6 */
+	OMAP4_MUX(DPM_EMU13, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data5 */
+	OMAP4_MUX(DPM_EMU14, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data4 */
+	OMAP4_MUX(DPM_EMU15, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data3 */
+	OMAP4_MUX(DPM_EMU16, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data2 */
+	OMAP4_MUX(DPM_EMU17, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data1 */
+	OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data0 */
+	OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+static inline void __init board_serial_init(void)
+{
+	omap_serial_init();
+}
+#else
+#define board_mux	NULL
+
+static inline void __init board_serial_init(void)
+{
+	omap_serial_init();
+}
+#endif
+
+/* Display DVI */
+#define PANDA_DVI_TFP410_POWER_DOWN_GPIO	0
+
+static int omap4_panda_enable_dvi(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(dssdev->reset_gpio, 1);
+	return 0;
+}
+
+static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(dssdev->reset_gpio, 0);
+}
+
+/* Using generic display panel */
+static struct panel_generic_dpi_data omap4_dvi_panel = {
+	.name			= "generic_720p",
+	.platform_enable	= omap4_panda_enable_dvi,
+	.platform_disable	= omap4_panda_disable_dvi,
+};
+
+struct omap_dss_device omap4_panda_dvi_device = {
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.name			= "dvi",
+	.driver_name		= "generic_dpi_panel",
+	.data			= &omap4_dvi_panel,
+	.phy.dpi.data_lines	= 24,
+	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+};
+
+int __init omap4_panda_dvi_init(void)
+{
+	int r;
+
+	/* Requesting TFP410 DVI GPIO and disabling it, at bootup */
+	r = gpio_request_one(omap4_panda_dvi_device.reset_gpio,
+				GPIOF_OUT_INIT_LOW, "DVI PD");
+	if (r)
+		pr_err("Failed to get DVI powerdown GPIO\n");
+
+	return r;
+}
+
+static struct gpio panda_hdmi_gpios[] = {
+	{ HDMI_GPIO_CT_CP_HPD,	GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd"   },
+	{ HDMI_GPIO_LS_OE,	GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
+};
+
+static void omap4_panda_hdmi_mux_init(void)
+{
+	u32 r;
+	int status;
+	/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
+	omap_mux_init_signal("hdmi_hpd.hdmi_hpd",
+				OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("gpmc_wait2.gpio_100",
+			OMAP_PIN_INPUT_PULLDOWN);
+	omap_mux_init_signal("hdmi_cec.hdmi_cec",
+			OMAP_PIN_INPUT_PULLUP);
+	/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
+	omap_mux_init_signal("hdmi_ddc_scl.hdmi_ddc_scl",
+			OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("hdmi_ddc_sda.hdmi_ddc_sda",
+			OMAP_PIN_INPUT_PULLUP);
+
+	/* strong pullup on DDC lines using unpublished register */
+	r = ((1 << 24) | (1 << 28)) ;
+	omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1);
+
+	gpio_request(HDMI_GPIO_HPD, NULL);
+	omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT | OMAP_PULL_ENA);
+	gpio_direction_input(HDMI_GPIO_HPD);
+
+	status = gpio_request_array(panda_hdmi_gpios,
+			ARRAY_SIZE(panda_hdmi_gpios));
+	if (status)
+		pr_err("%s: Cannot request HDMI GPIOs %x \n", __func__, status);
+}
+
+static struct omap_dss_device  omap4_panda_hdmi_device = {
+	.name = "hdmi",
+	.driver_name = "hdmi_panel",
+	.type = OMAP_DISPLAY_TYPE_HDMI,
+	.clocks	= {
+		.dispc	= {
+			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
+		},
+		.hdmi	= {
+			.regn	= 15,
+			.regm2	= 1,
+		},
+	},
+	.hpd_gpio = HDMI_GPIO_HPD,
+	.channel = OMAP_DSS_CHANNEL_DIGIT,
+};
+
+static struct omap_dss_device *omap4_panda_dss_devices[] = {
+	&omap4_panda_dvi_device,
+	&omap4_panda_hdmi_device,
+};
+
+static struct omap_dss_board_info omap4_panda_dss_data = {
+	.num_devices	= ARRAY_SIZE(omap4_panda_dss_devices),
+	.devices	= omap4_panda_dss_devices,
+	.default_device	= &omap4_panda_dvi_device,
+};
+
+/*
+ * LPDDR2 Configeration Data:
+ * The memory organisation is as below :
+ *	EMIF1 - CS0 -	2 Gb
+ *		CS1 -	2 Gb
+ *	EMIF2 - CS0 -	2 Gb
+ *		CS1 -	2 Gb
+ *	--------------------
+ *	TOTAL -		8 Gb
+ *
+ * Same devices installed on EMIF1 and EMIF2
+ */
+static __initdata struct emif_device_details emif_devices = {
+	.cs0_device = &lpddr2_elpida_2G_S4_dev,
+	.cs1_device = &lpddr2_elpida_2G_S4_dev
+};
+
+void omap4_panda_display_init(void)
+{
+	int r;
+
+	r = omap4_panda_dvi_init();
+	if (r)
+		pr_err("error initializing panda DVI\n");
+
+	omap4_panda_hdmi_mux_init();
+	omap_display_init(&omap4_panda_dss_data);
+}
+
+static int panda_notifier_call(struct notifier_block *this,
+					unsigned long code, void *cmd)
+{
+	void __iomem *sar_base;
+	u32 v = OMAP4430_RST_GLOBAL_COLD_SW_MASK;
+
+	sar_base = omap4_get_sar_ram_base();
+
+	if (!sar_base)
+		return notifier_from_errno(-ENOMEM);
+
+	if ((code == SYS_RESTART) && (cmd != NULL)) {
+		/* cmd != null; case: warm boot */
+		if (!strcmp(cmd, "bootloader")) {
+			/* Save reboot mode in scratch memory */
+			strcpy(sar_base + 0xA0C, cmd);
+			v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
+		} else if (!strcmp(cmd, "recovery")) {
+			/* Save reboot mode in scratch memory */
+			strcpy(sar_base + 0xA0C, cmd);
+			v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
+		} else {
+			v |= OMAP4430_RST_GLOBAL_COLD_SW_MASK;
+		}
+	}
+
+	omap4_prm_write_inst_reg(0xfff, OMAP4430_PRM_DEVICE_INST,
+			OMAP4_RM_RSTST);
+	omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST, OMAP4_RM_RSTCTRL);
+	v = omap4_prm_read_inst_reg(WKUP_MOD, OMAP4_RM_RSTCTRL);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block panda_reboot_notifier = {
+	.notifier_call = panda_notifier_call,
+};
+
+#define PANDA_FB_RAM_SIZE                SZ_16M /* 1920?1080*4 * 2 */
+static struct omapfb_platform_data panda_fb_pdata = {
+	.mem_desc = {
+		.region_cnt = 1,
+		.region = {
+			[0] = {
+				.size = PANDA_FB_RAM_SIZE,
+			},
+		},
+	},
+};
+
+static struct resource ramconsole_resources[] = {
+	{
+		.flags  = IORESOURCE_MEM,
+		.start	= PANDA_RAMCONSOLE_START,
+		.end	= PANDA_RAMCONSOLE_START + PANDA_RAMCONSOLE_SIZE - 1,
+	},
+};
+
+static struct ram_console_platform_data ramconsole_pdata;
+
+static struct platform_device ramconsole_device = {
+	.name           = "ram_console",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(ramconsole_resources),
+	.resource       = ramconsole_resources,
+	.dev		= {
+		.platform_data = &ramconsole_pdata,
+	},
+};
+
+extern void __init omap4_panda_android_init(void);
+
+static void __init omap4_panda_init(void)
+{
+	int package = OMAP_PACKAGE_CBS;
+	int status;
+
+	omap_emif_setup_device_details(&emif_devices, &emif_devices);
+
+	if (omap_rev() == OMAP4430_REV_ES1_0)
+		package = OMAP_PACKAGE_CBL;
+	omap4_mux_init(board_mux, NULL, package);
+
+	if (wl12xx_set_platform_data(&omap_panda_wlan_data))
+		pr_err("error setting wl12xx data\n");
+
+	register_reboot_notifier(&panda_reboot_notifier);
+	ramconsole_pdata.bootinfo = omap4_get_resetreason();
+	platform_device_register(&ramconsole_device);
+	omap4_panda_i2c_init();
+	omap4_audio_conf();
+
+	if (cpu_is_omap4430())
+		panda_gpio_keys_buttons[0].gpio = 121;
+
+	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
+	platform_device_register(&omap_vwlan_device);
+	board_serial_init();
+	omap4_twl6030_hsmmc_init(mmc);
+	omap4_ehci_init();
+	usb_musb_init(&musb_board_data);
+
+	omap_dmm_init();
+	omap_vram_set_sdram_vram(PANDA_FB_RAM_SIZE, 0);
+	omapfb_set_platform_data(&panda_fb_pdata);
+	omap4_panda_display_init();
+
+	if (cpu_is_omap446x()) {
+		/* Vsel0 = gpio, vsel1 = gnd */
+		status = omap_tps6236x_board_setup(true, TPS62361_GPIO, -1,
+					OMAP_PIN_OFF_OUTPUT_HIGH, -1);
+		if (status)
+			pr_err("TPS62361 initialization failed: %d\n", status);
+	}
+	omap_enable_smartreflex_on_init();
+}
+
+static void __init omap4_panda_map_io(void)
+{
+	omap2_set_globals_443x();
+	omap44xx_map_common_io();
+}
+
+static void __init omap4_panda_reserve(void)
+{
+	/* do the static reservations first */
+	memblock_remove(PANDA_RAMCONSOLE_START, PANDA_RAMCONSOLE_SIZE);
+	memblock_remove(PHYS_ADDR_SMC_MEM, PHYS_ADDR_SMC_SIZE);
+	memblock_remove(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE);
+	/* ipu needs to recognize secure input buffer area as well */
+	omap_ipu_set_static_mempool(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE +
+					OMAP_ION_HEAP_SECURE_INPUT_SIZE);
+
+	omap_reserve();
+}
+
+MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
+	/* Maintainer: David Anders - Texas Instruments Inc */
+	.boot_params	= 0x80000100,
+	.reserve	= omap4_panda_reserve,
+	.map_io		= omap4_panda_map_io,
+	.init_early	= omap4_panda_init_early,
+	.init_irq	= gic_init_irq,
+	.init_machine	= omap4_panda_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/kernel/drivers/input/touchscreen/Kconfig b/kernel/drivers/input/touchscreen/Kconfig
new file mode 100644
index 0000000..18655c0
--- /dev/null
+++ b/kernel/drivers/input/touchscreen/Kconfig
@@ -0,0 +1,721 @@
+#
+# Touchscreen driver configuration
+#
+menuconfig INPUT_TOUCHSCREEN
+	bool "Touchscreens"
+	help
+	  Say Y here, and a list of supported touchscreens will be displayed.
+	  This option doesn't affect the kernel.
+
+	  If unsure, say Y.
+
+if INPUT_TOUCHSCREEN
+
+config TOUCHSCREEN_88PM860X
+	tristate "Marvell 88PM860x touchscreen"
+	depends on MFD_88PM860X
+	help
+	  Say Y here if you have a 88PM860x PMIC and want to enable
+	  support for the built-in touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called 88pm860x-ts.
+
+config TOUCHSCREEN_ADS7846
+	tristate "ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens"
+	depends on SPI_MASTER
+	depends on HWMON = n || HWMON
+	help
+	  Say Y here if you have a touchscreen interface using the
+	  ADS7846/TSC2046/AD7873 or ADS7843/AD7843 controller,
+	  and your board-specific setup code includes that in its
+	  table of SPI devices.
+
+	  If HWMON is selected, and the driver is told the reference voltage
+	  on your board, you will also get hwmon interfaces for the voltage
+	  (and on ads7846/tsc2046/ad7873, temperature) sensors of this chip.
+
+	  If unsure, say N (but it's safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ads7846.
+
+config TOUCHSCREEN_AD7877
+	tristate "AD7877 based touchscreens"
+	depends on SPI_MASTER
+	help
+	  Say Y here if you have a touchscreen interface using the
+	  AD7877 controller, and your board-specific initialization
+	  code includes that in its table of SPI devices.
+
+	  If unsure, say N (but it's safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7877.
+
+config TOUCHSCREEN_AD7879
+	tristate "Analog Devices AD7879-1/AD7889-1 touchscreen interface"
+	help
+	  Say Y here if you want to support a touchscreen interface using
+	  the AD7879-1/AD7889-1 controller.
+
+	  You should select a bus connection too.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7879.
+
+config TOUCHSCREEN_AD7879_I2C
+	tristate "support I2C bus connection"
+	depends on TOUCHSCREEN_AD7879 && I2C
+	help
+	  Say Y here if you have AD7879-1/AD7889-1 hooked to an I2C bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7879-i2c.
+
+config TOUCHSCREEN_AD7879_SPI
+	tristate "support SPI bus connection"
+	depends on TOUCHSCREEN_AD7879 && SPI_MASTER
+	help
+	  Say Y here if you have AD7879-1/AD7889-1 hooked to a SPI bus.
+
+	  If unsure, say N (but it's safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7879-spi.
+
+config TOUCHSCREEN_BITSY
+	tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
+	depends on SA1100_BITSY
+	select SERIO
+	help
+	  Say Y here if you have the h3600 (Bitsy) touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called h3600_ts_input.
+
+config TOUCHSCREEN_BU21013
+	tristate "BU21013 based touch panel controllers"
+	depends on I2C
+	help
+	  Say Y here if you have a bu21013 touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bu21013_ts.
+
+config TOUCHSCREEN_CY8CTMG110
+	tristate "cy8ctmg110 touchscreen"
+	depends on I2C
+	depends on GPIOLIB
+
+	help
+	  Say Y here if you have a cy8ctmg110 capacitive touchscreen on
+	  an AAVA device.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cy8ctmg110_ts.
+
+config TOUCHSCREEN_DA9034
+	tristate "Touchscreen support for Dialog Semiconductor DA9034"
+	depends on PMIC_DA903X
+	default y
+	help
+	  Say Y here to enable the support for the touchscreen found
+	  on Dialog Semiconductor DA9034 PMIC.
+
+config TOUCHSCREEN_DYNAPRO
+	tristate "Dynapro serial touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have a Dynapro serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called dynapro.
+
+config TOUCHSCREEN_HAMPSHIRE
+	tristate "Hampshire serial touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have a Hampshire serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hampshire.
+
+config TOUCHSCREEN_EETI
+	tristate "EETI touchscreen panel support"
+	depends on I2C
+	help
+	  Say Y here to enable support for I2C connected EETI touch panels.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called eeti_ts.
+
+config TOUCHSCREEN_FUJITSU
+	tristate "Fujitsu serial touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have the Fujitsu touchscreen (such as one
+	  installed in Lifebook P series laptop) connected to your
+	  system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called fujitsu-ts.
+
+config TOUCHSCREEN_S3C2410
+	tristate "Samsung S3C2410/generic touchscreen input driver"
+	depends on ARCH_S3C2410 || SAMSUNG_DEV_TS
+	select S3C_ADC
+	help
+	  Say Y here if you have the s3c2410 touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called s3c2410_ts.
+
+config TOUCHSCREEN_GUNZE
+	tristate "Gunze AHL-51S touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have the Gunze AHL-51 touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gunze.
+
+config TOUCHSCREEN_ELO
+	tristate "Elo serial touchscreens"
+	select SERIO
+	help
+	  Say Y here if you have an Elo serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called elo.
+
+config TOUCHSCREEN_WACOM_W8001
+	tristate "Wacom W8001 penabled serial touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have an Wacom W8001 penabled serial touchscreen
+	  connected to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wacom_w8001.
+
+config TOUCHSCREEN_LPC32XX
+	tristate "LPC32XX touchscreen controller"
+	depends on ARCH_LPC32XX
+	help
+	  Say Y here if you have a LPC32XX device and want
+	  to support the built-in touchscreen.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called lpc32xx_ts.
+
+config TOUCHSCREEN_MCS5000
+	tristate "MELFAS MCS-5000 touchscreen"
+	depends on I2C
+	help
+	  Say Y here if you have the MELFAS MCS-5000 touchscreen controller
+	  chip in your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mcs5000_ts.
+
+config TOUCHSCREEN_MTOUCH
+	tristate "MicroTouch serial touchscreens"
+	select SERIO
+	help
+	  Say Y here if you have a MicroTouch (3M) serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mtouch.
+
+config TOUCHSCREEN_INEXIO
+	tristate "iNexio serial touchscreens"
+	select SERIO
+	help
+	  Say Y here if you have an iNexio serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called inexio.
+
+config TOUCHSCREEN_INTEL_MID
+	tristate "Intel MID platform resistive touchscreen"
+	depends on INTEL_SCU_IPC
+	help
+	  Say Y here if you have a Intel MID based touchscreen in
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called intel_mid_touch.
+
+config TOUCHSCREEN_MK712
+	tristate "ICS MicroClock MK712 touchscreen"
+	help
+	  Say Y here if you have the ICS MicroClock MK712 touchscreen
+	  controller chip in your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mk712.
+
+config TOUCHSCREEN_HP600
+	tristate "HP Jornada 6xx touchscreen"
+	depends on SH_HP6XX && SH_ADC
+	help
+	  Say Y here if you have a HP Jornada 620/660/680/690 and want to
+          support the built-in touchscreen.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hp680_ts_input.
+
+config TOUCHSCREEN_HP7XX
+	tristate "HP Jornada 7xx touchscreen"
+	depends on SA1100_JORNADA720_SSP
+	help
+	  Say Y here if you have a HP Jornada 710/720/728 and want
+	  to support the built-in touchscreen.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called jornada720_ts.
+
+config TOUCHSCREEN_HTCPEN
+	tristate "HTC Shift X9500 touchscreen"
+	depends on ISA
+	help
+	  Say Y here if you have an HTC Shift UMPC also known as HTC X9500
+	  Clio / Shangrila and want to support the built-in touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called htcpen.
+
+config TOUCHSCREEN_PENMOUNT
+	tristate "Penmount serial touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have a Penmount serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called penmount.
+
+config TOUCHSCREEN_QT602240
+	tristate "QT602240 I2C Touchscreen"
+	depends on I2C
+	help
+	  Say Y here if you have the AT42QT602240/ATMXT224 I2C touchscreen
+	  connected to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called qt602240_ts.
+
+config TOUCHSCREEN_MIGOR
+	tristate "Renesas MIGO-R touchscreen"
+	depends on SH_MIGOR && I2C
+	help
+	  Say Y here to enable MIGO-R touchscreen support.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called migor_ts.
+
+config TOUCHSCREEN_TNETV107X
+	tristate "TI TNETV107X touchscreen support"
+	depends on ARCH_DAVINCI_TNETV107X
+	help
+	  Say Y here if you want to use the TNETV107X touchscreen.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tnetv107x-ts.
+
+config TOUCHSCREEN_SYNAPTICS_I2C_RMI4
+	tristate "Synaptics DSX I2C touchscreen"
+	depends on I2C
+	help
+	  Say Y here if you have a Synaptics DSX I2C touchscreen
+	  connected to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called synaptics_i2c_rmi4.
+
+config TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV
+	tristate "Synaptics I2C touchscreen rmi device"
+	depends on TOUCHSCREEN_SYNAPTICS_I2C_RMI4
+	help
+	  This enables support for character device channel for Synaptics RMI
+	  touchscreens.
+
+config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE
+	tristate "Synaptics I2C touchscreen firmware update"
+	depends on TOUCHSCREEN_SYNAPTICS_I2C_RMI4
+	help
+	  This enables support for firmware update for Synaptics RMI
+	  touchscreens.
+
+config TOUCHSCREEN_TOUCHRIGHT
+	tristate "Touchright serial touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have a Touchright serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called touchright.
+
+config TOUCHSCREEN_TOUCHWIN
+	tristate "Touchwin serial touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have a Touchwin serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called touchwin.
+
+config TOUCHSCREEN_ATMEL_TSADCC
+	tristate "Atmel Touchscreen Interface"
+	depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
+	help
+	  Say Y here if you have a 4-wire touchscreen connected to the
+          ADC Controller on your Atmel SoC (such as the AT91SAM9RL).
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel_tsadcc.
+
+config TOUCHSCREEN_UCB1400
+	tristate "Philips UCB1400 touchscreen"
+	depends on AC97_BUS
+	depends on UCB1400_CORE
+	help
+	  This enables support for the Philips UCB1400 touchscreen interface.
+	  The UCB1400 is an AC97 audio codec.  The touchscreen interface
+	  will be initialized only after the ALSA subsystem has been
+	  brought up and the UCB1400 detected.  You therefore have to
+	  configure ALSA support as well (either built-in or modular,
+	  independently of whether this driver is itself built-in or
+	  modular) for this driver to work.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ucb1400_ts.
+
+config TOUCHSCREEN_WM97XX
+	tristate "Support for WM97xx AC97 touchscreen controllers"
+	depends on AC97_BUS
+	help
+	  Say Y here if you have a Wolfson Microelectronics WM97xx
+	  touchscreen connected to your system. Note that this option
+	  only enables core driver, you will also need to select
+	  support for appropriate chip below.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm97xx-ts.
+
+config TOUCHSCREEN_WM9705
+	bool "WM9705 Touchscreen interface support"
+	depends on TOUCHSCREEN_WM97XX
+	default y
+	help
+	  Say Y here to enable support for the Wolfson Microelectronics
+	  WM9705 touchscreen controller.
+
+config TOUCHSCREEN_WM9712
+	bool "WM9712 Touchscreen interface support"
+	depends on TOUCHSCREEN_WM97XX
+	default y
+	help
+	  Say Y here to enable support for the Wolfson Microelectronics
+	  WM9712 touchscreen controller.
+
+config TOUCHSCREEN_WM9713
+	bool "WM9713 Touchscreen interface support"
+	depends on TOUCHSCREEN_WM97XX
+	default y
+	help
+	  Say Y here to enable support for the Wolfson Microelectronics
+	  WM9713 touchscreen controller.
+
+config TOUCHSCREEN_WM97XX_ATMEL
+	tristate "WM97xx Atmel accelerated touch"
+	depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91)
+	help
+	  Say Y here for support for streaming mode with WM97xx touchscreens
+	  on Atmel AT91 or AVR32 systems with an AC97C module.
+
+	  Be aware that this will use channel B in the controller for
+	  streaming data, this must not conflict with other AC97C drivers.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called atmel-wm97xx.
+
+config TOUCHSCREEN_WM97XX_MAINSTONE
+	tristate "WM97xx Mainstone/Palm accelerated touch"
+	depends on TOUCHSCREEN_WM97XX && ARCH_PXA
+	help
+	  Say Y here for support for streaming mode with WM97xx touchscreens
+	  on Mainstone, Palm Tungsten T5, TX and LifeDrive systems.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mainstone-wm97xx.
+
+config TOUCHSCREEN_WM97XX_ZYLONITE
+	tristate "Zylonite accelerated touch"
+	depends on TOUCHSCREEN_WM97XX && MACH_ZYLONITE
+	select TOUCHSCREEN_WM9713
+	help
+	  Say Y here for support for streaming mode with the touchscreen
+	  on Zylonite systems.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called zylonite-wm97xx.
+
+config TOUCHSCREEN_USB_COMPOSITE
+	tristate "USB Touchscreen Driver"
+	depends on USB_ARCH_HAS_HCD
+	select USB
+	help
+	  USB Touchscreen driver for:
+	  - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700)
+	  - PanJit TouchSet USB
+	  - 3M MicroTouch USB (EX II series)
+	  - ITM
+	  - some other eTurboTouch
+	  - Gunze AHL61
+	  - DMC TSC-10/25
+	  - IRTOUCHSYSTEMS/UNITOP
+	  - IdealTEK URTC1000
+	  - GoTop Super_Q2/GogoPen/PenPower tablets
+	  - JASTEC USB Touch Controller/DigiTech DTR-02U
+	  - Zytronic controllers
+
+	  Have a look at <http://linux.chapter7.ch/touchkit/> for
+	  a usage description and the required user-space stuff.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called usbtouchscreen.
+
+config TOUCHSCREEN_MC13783
+	tristate "Freescale MC13783 touchscreen input driver"
+	depends on MFD_MC13783
+	help
+	  Say Y here if you have an Freescale MC13783 PMIC on your
+	  board and want to use its touchscreen
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mc13783_ts.
+
+config TOUCHSCREEN_USB_EGALAX
+	default y
+	bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_PANJIT
+	default y
+	bool "PanJit device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_3M
+	default y
+	bool "3M/Microtouch EX II series device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_ITM
+	default y
+	bool "ITM device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_ETURBO
+	default y
+	bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_GUNZE
+	default y
+	bool "Gunze AHL61 device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_DMC_TSC10
+	default y
+	bool "DMC TSC-10/25 device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_IRTOUCH
+	default y
+	bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_IDEALTEK
+	default y
+	bool "IdealTEK URTC1000 device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_GENERAL_TOUCH
+	default y
+	bool "GeneralTouch Touchscreen device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_GOTOP
+	default y
+	bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_JASTEC
+	default y
+	bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_E2I
+	default y
+	bool "e2i Touchscreen controller (e.g. from Mimo 740)"
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_ZYTRONIC
+	default y
+	bool "Zytronic controller" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_ETT_TC45USB
+	default y
+	bool "ET&T USB series TC4UM/TC5UH touchscreen controler support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_USB_NEXIO
+	default y
+	bool "NEXIO/iNexio device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
+config TOUCHSCREEN_TOUCHIT213
+	tristate "Sahara TouchIT-213 touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have a Sahara TouchIT-213 Tablet PC.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called touchit213.
+
+config TOUCHSCREEN_TSC2007
+	tristate "TSC2007 based touchscreens"
+	depends on I2C
+	help
+	  Say Y here if you have a TSC2007 based touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tsc2007.
+
+config TOUCHSCREEN_TSC2004
+	tristate "TSC2004 based touchscreens"
+	depends on I2C
+	help
+	  Say Y here if you have a TSC2004 based touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tsc2004.
+
+config TOUCHSCREEN_W90X900
+	tristate "W90P910 touchscreen driver"
+	depends on HAVE_CLK
+	help
+	  Say Y here if you have a W90P910 based touchscreen.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called w90p910_ts.
+
+config TOUCHSCREEN_PCAP
+	tristate "Motorola PCAP touchscreen"
+	depends on EZX_PCAP
+	help
+	  Say Y here if you have a Motorola EZX telephone and
+	  want to enable support for the built-in touchscreen.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pcap_ts.
+
+config TOUCHSCREEN_TPS6507X
+	tristate "TPS6507x based touchscreens"
+	depends on I2C
+	help
+	  Say Y here if you have a TPS6507x based touchscreen
+	  controller.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tps6507x_ts.
+
+config TOUCHSCREEN_STMPE
+	tristate "STMicroelectronics STMPE touchscreens"
+	depends on MFD_STMPE
+	help
+	  Say Y here if you want support for STMicroelectronics
+	  STMPE touchscreen controllers.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called stmpe-ts.
+
+endif
diff --git a/kernel/drivers/input/touchscreen/Makefile b/kernel/drivers/input/touchscreen/Makefile
new file mode 100644
index 0000000..a6c7d9f
--- /dev/null
+++ b/kernel/drivers/input/touchscreen/Makefile
@@ -0,0 +1,68 @@
+#
+# Makefile for the touchscreen drivers.
+#
+
+# Each configuration option enables a list of files.
+
+wm97xx-ts-y := wm97xx-core.o
+
+obj-$(CONFIG_TOUCHSCREEN_88PM860X)	+= 88pm860x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_AD7877)	+= ad7877.o
+obj-$(CONFIG_TOUCHSCREEN_AD7879)	+= ad7879.o
+obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C)	+= ad7879-i2c.o
+obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)	+= ad7879-spi.o
+obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
+obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
+obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)	+= cy8ctmg110_ts.o
+obj-$(CONFIG_TOUCHSCREEN_DA9034)	+= da9034-ts.o
+obj-$(CONFIG_TOUCHSCREEN_DYNAPRO)	+= dynapro.o
+obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)	+= hampshire.o
+obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunze.o
+obj-$(CONFIG_TOUCHSCREEN_EETI)		+= eeti_ts.o
+obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
+obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
+obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
+obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)	+= intel-mid-touch.o
+obj-$(CONFIG_TOUCHSCREEN_LPC32XX)	+= lpc32xx_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MC13783)	+= mc13783_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MCS5000)	+= mcs5000_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MIGOR)		+= migor_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
+obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
+obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
+obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
+obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
+obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
+obj-$(CONFIG_TOUCHSCREEN_QT602240)	+= qt602240_ts.o
+obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
+obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
+obj-$(CONFIG_TOUCHSCREEN_TNETV107X)	+= tnetv107x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)	+= synaptics_i2c_rmi4.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV)	+= synaptics_rmi_dev.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_fw_update.o
+obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
+obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
+obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_TSC2007)	+= tsc2007.o
+obj-$(CONFIG_TOUCHSCREEN_TSC2004)	+= tsc2004.o
+obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
+obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001)	+= wacom_w8001.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX)	+= wm97xx-ts.o
+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)	+= wm9705.o
+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)	+= wm9712.o
+wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713)	+= wm9713.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL)	+= atmel-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)	+= zylonite-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_W90X900)	+= w90p910_ts.o
+obj-$(CONFIG_TOUCHSCREEN_TPS6507X)	+= tps6507x-ts.o
+
+all:
+make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
+
+clean:
+make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
diff --git a/kernel/drivers/input/touchscreen/synaptics_fw_update.c b/kernel/drivers/input/touchscreen/synaptics_fw_update.c
new file mode 100644
index 0000000..4867d1f
--- /dev/null
+++ b/kernel/drivers/input/touchscreen/synaptics_fw_update.c
@@ -0,0 +1,1587 @@
+/*
+ * Synaptics RMI4 touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/firmware.h>
+#include <linux/input/synaptics_dsx.h>
+#include "synaptics_i2c_rmi4.h"
+
+#define DEBUG_FW_UPDATE
+#define SHOW_PROGRESS
+#define FW_IMAGE_NAME "PR12345678.img"
+
+#define CHECKSUM_OFFSET 0x00
+#define BOOTLOADER_VERSION_OFFSET 0x07
+#define IMAGE_SIZE_OFFSET 0x08
+#define CONFIG_SIZE_OFFSET 0x0C
+#define PRODUCT_ID_OFFSET 0x10
+#define PRODUCT_INFO_OFFSET 0x1E
+#define FW_IMAGE_OFFSET 0x100
+#define PRODUCT_ID_SIZE 10
+
+#define BOOTLOADER_ID_OFFSET 0
+#define FLASH_PROPERTIES_OFFSET 2
+#define BLOCK_SIZE_OFFSET 3
+#define FW_BLOCK_COUNT_OFFSET 5
+
+#define REG_MAP (1 << 0)
+#define UNLOCKED (1 << 1)
+#define HAS_CONFIG_ID (1 << 2)
+#define HAS_PERM_CONFIG (1 << 3)
+#define HAS_BL_CONFIG (1 << 4)
+#define HAS_DISP_CONFIG (1 << 5)
+#define HAS_CTRL1 (1 << 6)
+
+#define BLOCK_NUMBER_OFFSET 0
+#define BLOCK_DATA_OFFSET 2
+
+#define UI_CONFIG_AREA 0x00
+#define PERM_CONFIG_AREA 0x01
+#define BL_CONFIG_AREA 0x02
+#define DISP_CONFIG_AREA 0x03
+
+enum flash_command {
+	CMD_WRITE_FW_BLOCK		= 0x2,
+	CMD_ERASE_ALL			= 0x3,
+	CMD_READ_CONFIG_BLOCK	= 0x5,
+	CMD_WRITE_CONFIG_BLOCK	= 0x6,
+	CMD_ERASE_CONFIG		= 0x7,
+	CMD_ERASE_BL_CONFIG		= 0x9,
+	CMD_ERASE_DISP_CONFIG	= 0xA,
+	CMD_ENABLE_FLASH_PROG	= 0xF,
+};
+
+#define SLEEP_MODE_NORMAL (0x00)
+#define SLEEP_MODE_SENSOR_SLEEP (0x01)
+#define SLEEP_MODE_RESERVED0 (0x02)
+#define SLEEP_MODE_RESERVED1 (0x03)
+
+#define ENABLE_WAIT_MS (1 * 1000)
+#define WRITE_WAIT_MS (3 * 1000)
+#define ERASE_WAIT_MS (5 * 1000)
+
+#define MIN_SLEEP_TIME_US 50
+#define MAX_SLEEP_TIME_US 100
+
+static ssize_t fwu_sysfs_show_image(struct file *data_file,
+		struct kobject *kobj, struct bin_attribute *attributes,
+		char *buf, loff_t pos, size_t count);
+
+static ssize_t fwu_sysfs_store_image(struct file *data_file,
+		struct kobject *kobj, struct bin_attribute *attributes,
+		char *buf, loff_t pos, size_t count);
+
+static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_write_config_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_read_config_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_config_area_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_image_size_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_block_size_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static int fwu_wait_for_idle(int timeout_ms);
+
+struct image_header {
+	unsigned int checksum;
+	unsigned int image_size;
+	unsigned int config_size;
+	unsigned char options;
+	unsigned char bootloader_version;
+	unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
+	unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
+};
+
+struct pdt_properties {
+	union {
+		struct {
+			unsigned char reserved_1:6;
+			unsigned char has_bsr:1;
+			unsigned char reserved_2:1;
+		} __packed;
+		unsigned char data[1];
+	};
+};
+
+struct f01_device_status {
+	union {
+		struct {
+			unsigned char status_code:4;
+			unsigned char reserved:2;
+			unsigned char flash_prog:1;
+			unsigned char unconfigured:1;
+		} __packed;
+		unsigned char data[1];
+	};
+};
+
+struct f01_device_control {
+	union {
+		struct {
+			unsigned char sleep_mode:2;
+			unsigned char nosleep:1;
+			unsigned char reserved:2;
+			unsigned char charger_connected:1;
+			unsigned char report_rate:1;
+			unsigned char configured:1;
+		} __packed;
+		unsigned char data[1];
+	};
+};
+
+struct f34_flash_control {
+	union {
+		struct {
+			unsigned char command:4;
+			unsigned char status:3;
+			unsigned char program_enabled:1;
+		} __packed;
+		unsigned char data[1];
+	};
+};
+
+struct f34_flash_properties {
+	union {
+		struct {
+			unsigned char regmap:1;
+			unsigned char unlocked:1;
+			unsigned char has_configid:1;
+			unsigned char has_perm_config:1;
+			unsigned char has_bl_config:1;
+			unsigned char has_display_config:1;
+			unsigned char has_blob_config:1;
+			unsigned char reserved:1;
+		} __packed;
+		unsigned char data[1];
+	};
+};
+
+struct synaptics_rmi4_fwu_handle {
+	bool initialized;
+	char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
+	unsigned int image_size;
+	unsigned int data_pos;
+	unsigned char intr_mask;
+	unsigned char bootloader_id[2];
+	unsigned char productinfo1;
+	unsigned char productinfo2;
+	unsigned char *ext_data_source;
+	unsigned char *read_config_buf;
+	const unsigned char *firmware_data;
+	const unsigned char *config_data;
+	unsigned short block_size;
+	unsigned short fw_block_count;
+	unsigned short config_block_count;
+	unsigned short perm_config_block_count;
+	unsigned short bl_config_block_count;
+	unsigned short disp_config_block_count;
+	unsigned short config_size;
+	unsigned short config_area;
+	unsigned short addr_f34_flash_control;
+	unsigned short addr_f01_interrupt_register;
+	struct synaptics_rmi4_fn_desc f01_fd;
+	struct synaptics_rmi4_fn_desc f34_fd;
+	struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
+	struct synaptics_rmi4_data *rmi4_data;
+	struct f34_flash_control flash_control;
+	struct f34_flash_properties flash_properties;
+};
+
+static struct bin_attribute dev_attr_data = {
+	.attr = {
+		.name = "data",
+		.mode = (S_IRUGO | S_IWUGO),
+	},
+	.size = 0,
+	.read = fwu_sysfs_show_image,
+	.write = fwu_sysfs_store_image,
+};
+
+static struct device_attribute attrs[] = {
+	__ATTR(doreflash, S_IWUGO,
+			synaptics_rmi4_show_error,
+			fwu_sysfs_do_reflash_store),
+	__ATTR(writeconfig, S_IWUGO,
+			synaptics_rmi4_show_error,
+			fwu_sysfs_write_config_store),
+	__ATTR(readconfig, S_IWUGO,
+			synaptics_rmi4_show_error,
+			fwu_sysfs_read_config_store),
+	__ATTR(configarea, S_IWUGO,
+			synaptics_rmi4_show_error,
+			fwu_sysfs_config_area_store),
+	__ATTR(imagesize, S_IWUGO,
+			synaptics_rmi4_show_error,
+			fwu_sysfs_image_size_store),
+	__ATTR(blocksize, S_IRUGO,
+			fwu_sysfs_block_size_show,
+			synaptics_rmi4_store_error),
+	__ATTR(fwblockcount, S_IRUGO,
+			fwu_sysfs_firmware_block_count_show,
+			synaptics_rmi4_store_error),
+	__ATTR(configblockcount, S_IRUGO,
+			fwu_sysfs_configuration_block_count_show,
+			synaptics_rmi4_store_error),
+	__ATTR(permconfigblockcount, S_IRUGO,
+			fwu_sysfs_perm_config_block_count_show,
+			synaptics_rmi4_store_error),
+	__ATTR(blconfigblockcount, S_IRUGO,
+			fwu_sysfs_bl_config_block_count_show,
+			synaptics_rmi4_store_error),
+	__ATTR(dispconfigblockcount, S_IRUGO,
+			fwu_sysfs_disp_config_block_count_show,
+			synaptics_rmi4_store_error),
+};
+
+static struct synaptics_rmi4_fwu_handle *fwu;
+
+static struct completion remove_complete;
+
+static unsigned int extract_uint(const unsigned char *ptr)
+{
+	return (unsigned int)ptr[0] +
+			(unsigned int)ptr[1] * 0x100 +
+			(unsigned int)ptr[2] * 0x10000 +
+			(unsigned int)ptr[3] * 0x1000000;
+}
+
+static void parse_header(struct image_header *header,
+		const unsigned char *fw_image)
+{
+	header->checksum = extract_uint(&fw_image[CHECKSUM_OFFSET]);
+	header->bootloader_version = fw_image[BOOTLOADER_VERSION_OFFSET];
+	header->image_size = extract_uint(&fw_image[IMAGE_SIZE_OFFSET]);
+	header->config_size = extract_uint(&fw_image[CONFIG_SIZE_OFFSET]);
+	memcpy(header->product_id, &fw_image[PRODUCT_ID_OFFSET],
+			SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
+	header->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
+	memcpy(header->product_info, &fw_image[PRODUCT_INFO_OFFSET],
+			SYNAPTICS_RMI4_PRODUCT_INFO_SIZE);
+
+#ifdef DEBUG_FW_UPDATE
+	dev_info(&fwu->rmi4_data->i2c_client->dev,
+		"Firwmare size %d, config size %d\n",
+		header->image_size,
+		header->config_size);
+#endif
+	return;
+}
+
+static int fwu_check_version(void)
+{
+	int retval;
+	unsigned char firmware_id[4];
+	unsigned char config_id[4];
+	struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
+
+	/* device firmware id */
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+				fwu->f01_fd.query_base_addr + 18,
+				firmware_id,
+				sizeof(firmware_id));
+	if (retval < 0) {
+		dev_err(&i2c_client->dev,
+			"Failed to read firmware ID (code %d).\n", retval);
+		return retval;
+	}
+	firmware_id[3] = 0;
+
+	dev_info(&i2c_client->dev, "Device firmware ID%d\n",
+					extract_uint(firmware_id));
+
+	/* device config id */
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+				fwu->f34_fd.ctrl_base_addr,
+				config_id,
+				sizeof(config_id));
+	if (retval < 0) {
+		dev_err(&i2c_client->dev,
+			"Failed to read config ID (code %d).\n", retval);
+		return retval;
+	}
+
+	dev_info(&i2c_client->dev,
+		"Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
+		config_id[0], config_id[1], config_id[2], config_id[3]);
+
+	/* .img config id */
+	dev_info(&i2c_client->dev,
+			".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
+			fwu->config_data[0],
+			fwu->config_data[1],
+			fwu->config_data[2],
+			fwu->config_data[3]);
+	return 0;
+}
+
+static int fwu_read_f01_device_status(struct f01_device_status *status)
+{
+	int retval;
+
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+			fwu->f01_fd.data_base_addr,
+			status->data,
+			sizeof(status->data));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to read F01 device status\n",
+				__func__);
+		return retval;
+	}
+
+	return 0;
+}
+
+static int fwu_read_f34_queries(void)
+{
+	int retval;
+	unsigned char count = 4;
+	unsigned char buf[10];
+	struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
+
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+			fwu->f34_fd.query_base_addr + BOOTLOADER_ID_OFFSET,
+			fwu->bootloader_id,
+			sizeof(fwu->bootloader_id));
+	if (retval < 0) {
+		dev_err(&i2c_client->dev,
+				"%s: Failed to read bootloader ID\n",
+				__func__);
+		return retval;
+	}
+
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+			fwu->f34_fd.query_base_addr + FLASH_PROPERTIES_OFFSET,
+			fwu->flash_properties.data,
+			sizeof(fwu->flash_properties.data));
+	if (retval < 0) {
+		dev_err(&i2c_client->dev,
+				"%s: Failed to read flash properties\n",
+				__func__);
+		return retval;
+	}
+
+	dev_info(&i2c_client->dev, "%s perm:%d, bl%d, display:%d\n",
+				__func__,
+				fwu->flash_properties.has_perm_config,
+				fwu->flash_properties.has_bl_config,
+				fwu->flash_properties.has_display_config);
+
+	if (fwu->flash_properties.has_perm_config)
+		count += 2;
+
+	if (fwu->flash_properties.has_bl_config)
+		count += 2;
+
+	if (fwu->flash_properties.has_display_config)
+		count += 2;
+
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+			fwu->f34_fd.query_base_addr + BLOCK_SIZE_OFFSET,
+			buf,
+			2);
+	if (retval < 0) {
+		dev_err(&i2c_client->dev,
+				"%s: Failed to read block size info\n",
+				__func__);
+		return retval;
+	}
+
+	batohs(&fwu->block_size, &(buf[0]));
+
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+			fwu->f34_fd.query_base_addr + FW_BLOCK_COUNT_OFFSET,
+			buf,
+			count);
+	if (retval < 0) {
+		dev_err(&i2c_client->dev,
+				"%s: Failed to read block count info\n",
+				__func__);
+		return retval;
+	}
+
+	batohs(&fwu->fw_block_count, &(buf[0]));
+	batohs(&fwu->config_block_count, &(buf[2]));
+
+	count = 4;
+
+	if (fwu->flash_properties.has_perm_config) {
+		batohs(&fwu->perm_config_block_count, &(buf[count]));
+		count += 2;
+	}
+
+	if (fwu->flash_properties.has_bl_config) {
+		batohs(&fwu->bl_config_block_count, &(buf[count]));
+		count += 2;
+	}
+
+	if (fwu->flash_properties.has_display_config)
+		batohs(&fwu->disp_config_block_count, &(buf[count]));
+
+	fwu->addr_f34_flash_control = fwu->f34_fd.data_base_addr +
+					BLOCK_DATA_OFFSET +
+					fwu->block_size;
+	return 0;
+}
+
+static int fwu_read_interrupt_status(void)
+{
+	int retval;
+	unsigned char interrupt_status;
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+			fwu->addr_f01_interrupt_register,
+			&interrupt_status,
+			sizeof(interrupt_status));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to read flash status\n",
+				__func__);
+		return retval;
+	}
+	return interrupt_status;
+}
+
+static int fwu_read_f34_flash_status(void)
+{
+	int retval;
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+			fwu->addr_f34_flash_control,
+			fwu->flash_control.data,
+			sizeof(fwu->flash_control.data));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to read flash status\n",
+				__func__);
+		return retval;
+	}
+	return 0;
+}
+
+static int fwu_reset_device(void)
+{
+	int retval;
+	unsigned char reset = 0x01;
+
+#ifdef DEBUG_FW_UPDATE
+	dev_info(&fwu->rmi4_data->i2c_client->dev, "Reset device\n");
+#endif
+
+	retval = fwu->fn_ptr->write(fwu->rmi4_data,
+			fwu->f01_fd.cmd_base_addr,
+			&reset,
+			sizeof(reset));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to reset device (addr : 0x%02x)\n",
+				__func__, fwu->f01_fd.cmd_base_addr);
+		return retval;
+	}
+
+	fwu_wait_for_idle(WRITE_WAIT_MS);
+
+	retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to reset core driver after reflash\n",
+				__func__);
+		return retval;
+	}
+	return 0;
+}
+
+static int fwu_write_f34_command(unsigned char cmd)
+{
+	int retval;
+
+	retval = fwu->fn_ptr->write(fwu->rmi4_data,
+			fwu->addr_f34_flash_control,
+			&cmd,
+			sizeof(cmd));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to write command 0x%02x\n",
+				__func__, cmd);
+		return retval;
+	}
+	return 0;
+}
+
+static unsigned char fwu_check_flash_status(void)
+{
+	fwu_read_f34_flash_status();
+	return fwu->flash_control.status;
+}
+
+static int fwu_wait_for_idle(int timeout_ms)
+{
+	int count = 0;
+	int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1;
+
+	do {
+		if (fwu_read_interrupt_status() > 0)
+			return 0;
+
+		usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US);
+		count++;
+	} while (count < timeout_count);
+
+	dev_err(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Timed out waiting for idle status\n",
+			__func__);
+
+	return -ETIMEDOUT;
+}
+
+static int fwu_scan_pdt(void)
+{
+	int retval;
+	unsigned char ii;
+	unsigned char intr_count = 0;
+	unsigned char intr_off;
+	unsigned char intr_src;
+	unsigned short addr;
+	bool f01found = false;
+	bool f34found = false;
+	struct synaptics_rmi4_fn_desc rmi_fd;
+
+#ifdef DEBUG_FW_UPDATE
+	dev_info(&fwu->rmi4_data->i2c_client->dev, "Scan PDT\n");
+#endif
+
+	for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
+		retval = fwu->fn_ptr->read(fwu->rmi4_data,
+					addr,
+					(unsigned char *)&rmi_fd,
+					sizeof(rmi_fd));
+		if (retval < 0)
+			return retval;
+
+		if (rmi_fd.fn_number) {
+			dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+					"%s: Found F%02x\n",
+					__func__, rmi_fd.fn_number);
+			switch (rmi_fd.fn_number) {
+			case SYNAPTICS_RMI4_F01:
+				f01found = true;
+				fwu->f01_fd = rmi_fd;
+				fwu->addr_f01_interrupt_register =
+					fwu->f01_fd.data_base_addr + 1;
+				break;
+			case SYNAPTICS_RMI4_F34:
+				f34found = true;
+				fwu->f34_fd = rmi_fd;
+				fwu->intr_mask = 0;
+				intr_src = rmi_fd.intr_src_count;
+				intr_off = intr_count % 8;
+				for (ii = intr_off;
+						ii < ((intr_src & MASK_3BIT) +
+						intr_off);
+						ii++)
+					fwu->intr_mask |= 1 << ii;
+				break;
+			}
+		} else
+		break;
+
+		intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
+	}
+
+	if (!f01found || !f34found) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to find both F01 and F34\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	fwu_read_interrupt_status();
+	return 0;
+}
+
+static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
+		unsigned char command)
+{
+	int retval;
+	unsigned char block_offset[] = {0, 0};
+	unsigned short block_num;
+#ifdef SHOW_PROGRESS
+	unsigned int progress = (command == CMD_WRITE_CONFIG_BLOCK) ?
+				10 : 100;
+#endif
+	retval = fwu->fn_ptr->write(fwu->rmi4_data,
+			fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
+			block_offset,
+			sizeof(block_offset));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to write to block number registers\n",
+				__func__);
+		return retval;
+	}
+
+	for (block_num = 0; block_num < block_cnt; block_num++) {
+#ifdef SHOW_PROGRESS
+		if (block_num % progress == 0)
+			dev_info(&fwu->rmi4_data->i2c_client->dev,
+				"%s: update %s %3d / %3d\n",
+				__func__,
+				command == CMD_WRITE_CONFIG_BLOCK ?
+				"config" : "firmware",
+				block_num,
+				block_cnt);
+#endif
+		retval = fwu->fn_ptr->write(fwu->rmi4_data,
+			fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
+			block_ptr,
+			fwu->block_size);
+		if (retval < 0) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to write block data (block %d)\n",
+				__func__, block_num);
+			return retval;
+		}
+
+		retval = fwu_write_f34_command(command);
+		if (retval < 0) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+					"%s: Failed to write command for block %d\n",
+					__func__, block_num);
+			return retval;
+		}
+
+		retval = fwu_wait_for_idle(WRITE_WAIT_MS);
+		if (retval < 0) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to wait for idle status \
+				(block %d)\n",
+				__func__, block_num);
+			return retval;
+		}
+
+		retval = fwu_check_flash_status();
+		if (retval != 0) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+					"%s: Flash block %d status %d\n",
+					__func__, block_num, retval);
+			return -1;
+		}
+		block_ptr += fwu->block_size;
+	}
+#ifdef SHOW_PROGRESS
+	dev_info(&fwu->rmi4_data->i2c_client->dev,
+		"%s: update %s %3d / %3d\n",
+		__func__,
+		command == CMD_WRITE_CONFIG_BLOCK ?
+		"config" : "firmware",
+		block_cnt,
+		block_cnt);
+#endif
+	return 0;
+}
+
+static int fwu_write_firmware(void)
+{
+	return fwu_write_blocks((unsigned char *)fwu->firmware_data,
+		fwu->fw_block_count, CMD_WRITE_FW_BLOCK);
+}
+
+static int fwu_write_configuration(void)
+{
+	return fwu_write_blocks((unsigned char *)fwu->config_data,
+		fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK);
+}
+
+static int fwu_write_bootloader_id(void)
+{
+	int retval;
+
+#ifdef DEBUG_FW_UPDATE
+	dev_info(&fwu->rmi4_data->i2c_client->dev, "Write bootloader ID\n");
+#endif
+	retval = fwu->fn_ptr->write(fwu->rmi4_data,
+			fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
+			fwu->bootloader_id,
+			sizeof(fwu->bootloader_id));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to write bootloader ID\n",
+				__func__);
+		return retval;
+	}
+
+	return 0;
+}
+
+static int fwu_enter_flash_prog(void)
+{
+	int retval;
+	struct f01_device_status f01_device_status;
+	struct f01_device_control f01_device_control;
+
+#ifdef DEBUG_FW_UPDATE
+	dev_info(&fwu->rmi4_data->i2c_client->dev, "Enter bootloader mode\n");
+#endif
+	retval = fwu_read_f01_device_status(&f01_device_status);
+	if (retval < 0)
+		return retval;
+
+	if (f01_device_status.flash_prog) {
+		dev_info(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Already in flash prog mode\n",
+				__func__);
+		return 0;
+	}
+
+	retval = fwu_write_bootloader_id();
+	if (retval < 0)
+		return retval;
+
+	retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG);
+	if (retval < 0)
+		return retval;
+
+	retval = fwu_wait_for_idle(ENABLE_WAIT_MS);
+	if (retval < 0)
+		return retval;
+
+	retval = fwu_read_f01_device_status(&f01_device_status);
+	if (retval < 0)
+		return retval;
+
+	if (!f01_device_status.flash_prog) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Program enabled bit not set\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	retval = fwu_scan_pdt();
+	if (retval < 0)
+		return retval;
+
+	retval = fwu_read_f01_device_status(&f01_device_status);
+	if (retval < 0)
+		return retval;
+
+	if (!f01_device_status.flash_prog) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Not in flash prog mode\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	retval = fwu_read_f34_queries();
+	if (retval < 0)
+		return retval;
+
+	retval = fwu->fn_ptr->read(fwu->rmi4_data,
+			fwu->f01_fd.ctrl_base_addr,
+			f01_device_control.data,
+			sizeof(f01_device_control.data));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to read F01 device control\n",
+				__func__);
+		return retval;
+	}
+
+	f01_device_control.nosleep = true;
+	f01_device_control.sleep_mode = SLEEP_MODE_NORMAL;
+
+	retval = fwu->fn_ptr->write(fwu->rmi4_data,
+			fwu->f01_fd.ctrl_base_addr,
+			f01_device_control.data,
+			sizeof(f01_device_control.data));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to write F01 device control\n",
+				__func__);
+		return retval;
+	}
+
+	return retval;
+}
+
+static int fwu_do_reflash(void)
+{
+	int retval;
+
+	retval = fwu_enter_flash_prog();
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Entered flash prog mode\n",
+			__func__);
+
+	retval = fwu_write_bootloader_id();
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Bootloader ID written\n",
+			__func__);
+
+	retval = fwu_write_f34_command(CMD_ERASE_ALL);
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Erase all command written\n",
+			__func__);
+
+	retval = fwu_wait_for_idle(ERASE_WAIT_MS);
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Idle status detected\n",
+			__func__);
+
+	if (fwu->firmware_data) {
+		retval = fwu_write_firmware();
+		if (retval < 0)
+			return retval;
+		pr_notice("%s: Firmware programmed\n", __func__);
+	}
+
+	if (fwu->config_data) {
+		retval = fwu_write_configuration();
+		if (retval < 0)
+			return retval;
+		pr_notice("%s: Configuration programmed\n", __func__);
+	}
+
+	return retval;
+}
+
+static int fwu_start_reflash(void)
+{
+	int retval;
+	struct image_header header;
+	const unsigned char *fw_image;
+	const struct firmware *fw_entry = NULL;
+	struct f01_device_status f01_device_status;
+
+	pr_notice("%s: Start of reflash process\n", __func__);
+
+	if (fwu->ext_data_source)
+		fw_image = fwu->ext_data_source;
+	else {
+		dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Requesting firmware image %s\n",
+				__func__, FW_IMAGE_NAME);
+
+		retval = request_firmware(&fw_entry, FW_IMAGE_NAME,
+				&fwu->rmi4_data->i2c_client->dev);
+		if (retval != 0) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+					"%s: Firmware image %s not available\n",
+					__func__, FW_IMAGE_NAME);
+			retval = -EINVAL;
+			goto exit;
+		}
+
+		dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Firmware image size = %d\n",
+				__func__, fw_entry->size);
+
+		fw_image = fw_entry->data;
+	}
+
+	parse_header(&header, fw_image);
+
+	if (header.image_size)
+		fwu->firmware_data = fw_image + FW_IMAGE_OFFSET;
+	if (header.config_size) {
+		fwu->config_data = fw_image + FW_IMAGE_OFFSET +
+				header.image_size;
+	}
+
+	fwu->fn_ptr->enable(fwu->rmi4_data, false);
+
+	fwu_check_version();
+
+	retval = fwu_do_reflash();
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to do reflash\n",
+				__func__);
+	}
+
+	/* reset device */
+	fwu_reset_device();
+
+	/* check device status */
+	retval = fwu_read_f01_device_status(&f01_device_status);
+	if (retval < 0)
+		goto exit;
+
+	dev_info(&fwu->rmi4_data->i2c_client->dev, "Device is in %s mode\n",
+		f01_device_status.flash_prog == 1 ? "bootloader" : "UI");
+	if (f01_device_status.flash_prog)
+		dev_info(&fwu->rmi4_data->i2c_client->dev, "Flash status %d\n",
+				f01_device_status.status_code);
+
+	if (f01_device_status.flash_prog) {
+		dev_info(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Device is in flash prog mode 0x%02X\n",
+				__func__, f01_device_status.status_code);
+		retval = 0;
+		goto exit;
+	}
+	fwu->fn_ptr->enable(fwu->rmi4_data, true);
+	if (fw_entry)
+		release_firmware(fw_entry);
+
+	pr_notice("%s: End of reflash process\n", __func__);
+exit:
+	return retval;
+}
+
+static int fwu_do_write_config(void)
+{
+	int retval;
+
+	retval = fwu_enter_flash_prog();
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Entered flash prog mode\n",
+			__func__);
+
+	if (fwu->config_area == PERM_CONFIG_AREA) {
+		fwu->config_block_count = fwu->perm_config_block_count;
+		goto write_config;
+	}
+
+	retval = fwu_write_bootloader_id();
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Bootloader ID written\n",
+			__func__);
+
+	switch (fwu->config_area) {
+	case UI_CONFIG_AREA:
+		retval = fwu_write_f34_command(CMD_ERASE_CONFIG);
+		break;
+	case BL_CONFIG_AREA:
+		retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG);
+		fwu->config_block_count = fwu->bl_config_block_count;
+		break;
+	case DISP_CONFIG_AREA:
+		retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG);
+		fwu->config_block_count = fwu->disp_config_block_count;
+		break;
+	}
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Erase command written\n",
+			__func__);
+
+	retval = fwu_wait_for_idle(ERASE_WAIT_MS);
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Idle status detected\n",
+			__func__);
+
+write_config:
+	retval = fwu_write_configuration();
+	if (retval < 0)
+		return retval;
+
+	pr_notice("%s: Config written\n", __func__);
+
+	return retval;
+}
+
+static int fwu_start_write_config(void)
+{
+	int retval;
+	struct image_header header;
+
+	switch (fwu->config_area) {
+	case UI_CONFIG_AREA:
+		break;
+	case PERM_CONFIG_AREA:
+		if (!fwu->flash_properties.has_perm_config)
+			return -EINVAL;
+		break;
+	case BL_CONFIG_AREA:
+		if (!fwu->flash_properties.has_bl_config)
+			return -EINVAL;
+		break;
+	case DISP_CONFIG_AREA:
+		if (!fwu->flash_properties.has_display_config)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (fwu->ext_data_source)
+		fwu->config_data = fwu->ext_data_source;
+	else
+		return -EINVAL;
+
+	if (fwu->config_area == UI_CONFIG_AREA) {
+		parse_header(&header, fwu->ext_data_source);
+
+		if (header.config_size) {
+			fwu->config_data = fwu->ext_data_source +
+					FW_IMAGE_OFFSET +
+					header.image_size;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	pr_notice("%s: Start of write config process\n", __func__);
+
+	retval = fwu_do_write_config();
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to write config\n",
+				__func__);
+	}
+
+	fwu->rmi4_data->reset_device(fwu->rmi4_data);
+
+	pr_notice("%s: End of write config process\n", __func__);
+
+	return retval;
+}
+
+static int fwu_do_read_config(void)
+{
+	int retval;
+	unsigned char block_offset[] = {0, 0};
+	unsigned short block_num;
+	unsigned short block_count;
+	unsigned short index = 0;
+
+	retval = fwu_enter_flash_prog();
+	if (retval < 0)
+		goto exit;
+
+	dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+			"%s: Entered flash prog mode\n",
+			__func__);
+
+	switch (fwu->config_area) {
+	case UI_CONFIG_AREA:
+		block_count = fwu->config_block_count;
+		break;
+	case PERM_CONFIG_AREA:
+		if (!fwu->flash_properties.has_perm_config) {
+			retval = -EINVAL;
+			goto exit;
+		}
+		block_count = fwu->perm_config_block_count;
+		break;
+	case BL_CONFIG_AREA:
+		if (!fwu->flash_properties.has_bl_config) {
+			retval = -EINVAL;
+			goto exit;
+		}
+		block_count = fwu->bl_config_block_count;
+		break;
+	case DISP_CONFIG_AREA:
+		if (!fwu->flash_properties.has_display_config) {
+			retval = -EINVAL;
+			goto exit;
+		}
+		block_count = fwu->disp_config_block_count;
+		break;
+	default:
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	fwu->config_size = fwu->block_size * block_count;
+
+	kfree(fwu->read_config_buf);
+	fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL);
+
+	block_offset[1] |= (fwu->config_area << 5);
+
+	retval = fwu->fn_ptr->write(fwu->rmi4_data,
+			fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
+			block_offset,
+			sizeof(block_offset));
+	if (retval < 0) {
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+				"%s: Failed to write to block number registers\n",
+				__func__);
+		goto exit;
+	}
+
+	for (block_num = 0; block_num < block_count; block_num++) {
+		retval = fwu_write_f34_command(CMD_READ_CONFIG_BLOCK);
+		if (retval < 0) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+					"%s: Failed to write read config command\n",
+					__func__);
+			goto exit;
+		}
+
+		retval = fwu_wait_for_idle(WRITE_WAIT_MS);
+		if (retval < 0) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+					"%s: Failed to wait for idle status\n",
+					__func__);
+			goto exit;
+		}
+
+		retval = fwu->fn_ptr->read(fwu->rmi4_data,
+				fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
+				&fwu->read_config_buf[index],
+				fwu->block_size);
+		if (retval < 0) {
+			dev_err(&fwu->rmi4_data->i2c_client->dev,
+					"%s: Failed to read block data (block %d)\n",
+					__func__, block_num);
+			goto exit;
+		}
+
+		index += fwu->block_size;
+	}
+
+exit:
+	fwu->rmi4_data->reset_device(fwu->rmi4_data);
+
+	return retval;
+}
+
+int synaptics_fw_updater(unsigned char *fw_data)
+{
+	int retval;
+
+	if (!fwu)
+		return -ENODEV;
+
+	if (!fwu->initialized)
+		return -ENODEV;
+
+	fwu->ext_data_source = fw_data;
+	fwu->config_area = UI_CONFIG_AREA;
+
+	retval = fwu_start_reflash();
+
+	return retval;
+}
+EXPORT_SYMBOL(synaptics_fw_updater);
+
+static ssize_t fwu_sysfs_show_image(struct file *data_file,
+		struct kobject *kobj, struct bin_attribute *attributes,
+		char *buf, loff_t pos, size_t count)
+{
+	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+	if (count < fwu->config_size) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Not enough space (%d bytes) in buffer\n",
+				__func__, count);
+		return -EINVAL;
+	}
+
+	memcpy(buf, fwu->read_config_buf, fwu->config_size);
+
+	return fwu->config_size;
+}
+
+static ssize_t fwu_sysfs_store_image(struct file *data_file,
+		struct kobject *kobj, struct bin_attribute *attributes,
+		char *buf, loff_t pos, size_t count)
+{
+	memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
+			(const void *)buf,
+			count);
+
+	fwu->data_pos += count;
+
+	return count;
+}
+
+static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int retval;
+	unsigned int input;
+	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+	if (sscanf(buf, "%u", &input) != 1) {
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	if (input != 1) {
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	retval = synaptics_fw_updater(fwu->ext_data_source);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to do reflash\n",
+				__func__);
+		goto exit;
+	}
+
+	retval = count;
+
+exit:
+	kfree(fwu->ext_data_source);
+	fwu->ext_data_source = NULL;
+	return retval;
+}
+
+static ssize_t fwu_sysfs_write_config_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int retval;
+	unsigned int input;
+	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+	if (sscanf(buf, "%u", &input) != 1) {
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	if (input != 1) {
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	retval = fwu_start_write_config();
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to write config\n",
+				__func__);
+		goto exit;
+	}
+
+	retval = count;
+
+exit:
+	kfree(fwu->ext_data_source);
+	fwu->ext_data_source = NULL;
+	return retval;
+}
+
+static ssize_t fwu_sysfs_read_config_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int retval;
+	unsigned int input;
+	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+	if (sscanf(buf, "%u", &input) != 1)
+		return -EINVAL;
+
+	if (input != 1)
+		return -EINVAL;
+
+	retval = fwu_do_read_config();
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to read config\n",
+				__func__);
+		return retval;
+	}
+
+	return count;
+}
+
+static ssize_t fwu_sysfs_config_area_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int retval;
+	unsigned long config_area;
+
+	retval = sstrtoul(buf, 10, &config_area);
+	if (retval)
+		return retval;
+
+	fwu->config_area = config_area;
+
+	return count;
+}
+
+static ssize_t fwu_sysfs_image_size_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int retval;
+	unsigned long size;
+	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+	retval = sstrtoul(buf, 10, &size);
+	if (retval)
+		return retval;
+
+	fwu->image_size = size;
+	fwu->data_pos = 0;
+
+	kfree(fwu->ext_data_source);
+	fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL);
+	if (!fwu->ext_data_source) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for image data\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	return count;
+}
+
+static ssize_t fwu_sysfs_block_size_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size);
+}
+
+static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n", fwu->fw_block_count);
+}
+
+static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n", fwu->config_block_count);
+}
+
+static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n", fwu->perm_config_block_count);
+}
+
+static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n", fwu->bl_config_block_count);
+}
+
+static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count);
+}
+
+static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
+		unsigned char intr_mask)
+{
+	if (fwu->intr_mask & intr_mask)
+		fwu_read_f34_flash_status();
+
+	return;
+}
+
+static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	unsigned char attr_count;
+	struct pdt_properties pdt_props;
+
+	fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
+	if (!fwu) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for fwu\n",
+				__func__);
+		goto exit;
+	}
+
+	fwu->fn_ptr = kzalloc(sizeof(*(fwu->fn_ptr)), GFP_KERNEL);
+	if (!fwu->fn_ptr) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for fn_ptr\n",
+				__func__);
+		retval = -ENOMEM;
+		goto exit_free_fwu;
+	}
+
+	fwu->rmi4_data = rmi4_data;
+	fwu->fn_ptr->read = rmi4_data->i2c_read;
+	fwu->fn_ptr->write = rmi4_data->i2c_write;
+	fwu->fn_ptr->enable = rmi4_data->irq_enable;
+
+	retval = fwu->fn_ptr->read(rmi4_data,
+			PDT_PROPS,
+			pdt_props.data,
+			sizeof(pdt_props.data));
+	if (retval < 0) {
+		dev_dbg(&rmi4_data->i2c_client->dev,
+				"%s: Failed to read PDT properties, assuming 0x00\n",
+				__func__);
+	} else if (pdt_props.has_bsr) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Reflash for LTS not currently supported\n",
+				__func__);
+		goto exit_free_mem;
+	}
+
+	retval = fwu_scan_pdt();
+	if (retval < 0)
+		goto exit_free_mem;
+
+	fwu->productinfo1 = rmi4_data->rmi4_mod_info.product_info[0];
+	fwu->productinfo2 = rmi4_data->rmi4_mod_info.product_info[1];
+
+	memcpy(fwu->product_id, rmi4_data->rmi4_mod_info.product_id_string,
+			SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
+	fwu->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
+
+	dev_dbg(&rmi4_data->i2c_client->dev,
+			"%s: F01 product info: 0x%04x 0x%04x\n",
+			__func__, fwu->productinfo1, fwu->productinfo2);
+	dev_dbg(&rmi4_data->i2c_client->dev,
+			"%s: F01 product ID: %s\n",
+			__func__, fwu->product_id);
+
+	retval = fwu_read_f34_queries();
+	if (retval < 0)
+		goto exit_free_mem;
+
+	fwu->initialized = true;
+
+	retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
+			&dev_attr_data);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to create sysfs bin file\n",
+				__func__);
+		goto exit_free_mem;
+	}
+
+	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+		retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
+				&attrs[attr_count].attr);
+		if (retval < 0) {
+			dev_err(&rmi4_data->i2c_client->dev,
+					"%s: Failed to create sysfs attributes\n",
+					__func__);
+			retval = -ENODEV;
+			goto exit_remove_attrs;
+		}
+	}
+
+	return 0;
+
+exit_remove_attrs:
+for (attr_count--; attr_count >= 0; attr_count--) {
+	sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+			&attrs[attr_count].attr);
+}
+
+sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+
+exit_free_mem:
+	kfree(fwu->fn_ptr);
+
+exit_free_fwu:
+	kfree(fwu);
+
+exit:
+	return 0;
+}
+
+static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
+{
+	unsigned char attr_count;
+
+	sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+
+	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+		sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+				&attrs[attr_count].attr);
+	}
+
+	kfree(fwu->fn_ptr);
+	kfree(fwu);
+
+	complete(&remove_complete);
+
+	return;
+}
+
+static int __init rmi4_fw_update_module_init(void)
+{
+	synaptics_rmi4_new_function(RMI_FW_UPDATER, true,
+			synaptics_rmi4_fwu_init,
+			synaptics_rmi4_fwu_remove,
+			synaptics_rmi4_fwu_attn);
+	return 0;
+}
+
+static void __exit rmi4_fw_update_module_exit(void)
+{
+	init_completion(&remove_complete);
+	synaptics_rmi4_new_function(RMI_FW_UPDATER, false,
+			synaptics_rmi4_fwu_init,
+			synaptics_rmi4_fwu_remove,
+			synaptics_rmi4_fwu_attn);
+	wait_for_completion(&remove_complete);
+	return;
+}
+
+module_init(rmi4_fw_update_module_init);
+module_exit(rmi4_fw_update_module_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 FW Update Module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION);
diff --git a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c
new file mode 100644
index 0000000..8553022
--- /dev/null
+++ b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -0,0 +1,2110 @@
+/*
+ * Synaptics RMI4 touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/input/synaptics_dsx.h>
+#include "synaptics_i2c_rmi4.h"
+#ifdef KERNEL_ABOVE_2_6_38
+#include <linux/input/mt.h>
+#endif
+
+#define DRIVER_NAME "synaptics_rmi4_i2c"
+#define INPUT_PHYS_NAME "synaptics_rmi4_i2c/input0"
+
+#ifdef KERNEL_ABOVE_2_6_38
+#define TYPE_B_PROTOCOL
+#endif
+
+#define NO_0D_WHILE_2D
+/*
+#define REPORT_2D_Z
+*/
+#define REPORT_2D_W
+
+#define RPT_TYPE (1 << 0)
+#define RPT_X_LSB (1 << 1)
+#define RPT_X_MSB (1 << 2)
+#define RPT_Y_LSB (1 << 3)
+#define RPT_Y_MSB (1 << 4)
+#define RPT_Z (1 << 5)
+#define RPT_WX (1 << 6)
+#define RPT_WY (1 << 7)
+#define RPT_DEFAULT (RPT_TYPE | RPT_X_LSB | RPT_X_MSB | RPT_Y_LSB | RPT_Y_MSB)
+
+#define EXP_FN_DET_INTERVAL 1000 /* ms */
+#define POLLING_PERIOD 1 /* ms */
+#define SYN_I2C_RETRY_TIMES 10
+#define MAX_ABS_MT_TOUCH_MAJOR 15
+
+#define F01_STD_QUERY_LEN 21
+#define F01_BUID_ID_OFFSET 18
+#define F11_STD_QUERY_LEN 9
+#define F11_STD_CTRL_LEN 10
+#define F11_STD_DATA_LEN 12
+
+#define NORMAL_OPERATION (0 << 0)
+#define SENSOR_SLEEP (1 << 0)
+#define NO_SLEEP_OFF (0 << 3)
+#define NO_SLEEP_ON (1 << 3)
+
+static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
+		unsigned short addr, unsigned char *data,
+		unsigned short length);
+
+static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data,
+		unsigned short addr, unsigned char *data,
+		unsigned short length);
+
+static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static void synaptics_rmi4_early_suspend(struct early_suspend *h);
+
+static void synaptics_rmi4_late_resume(struct early_suspend *h);
+
+static int synaptics_rmi4_suspend(struct device *dev);
+
+static int synaptics_rmi4_resume(struct device *dev);
+#endif
+
+static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+struct synaptics_rmi4_f01_device_status {
+	union {
+		struct {
+			unsigned char status_code:4;
+			unsigned char reserved:2;
+			unsigned char flash_prog:1;
+			unsigned char unconfigured:1;
+		} __packed;
+		unsigned char data[1];
+	};
+};
+
+struct synaptics_rmi4_f1a_query {
+	union {
+		struct {
+			unsigned char max_button_count:3;
+			unsigned char reserved:5;
+			unsigned char has_general_control:1;
+			unsigned char has_interrupt_enable:1;
+			unsigned char has_multibutton_select:1;
+			unsigned char has_tx_rx_map:1;
+			unsigned char has_perbutton_threshold:1;
+			unsigned char has_release_threshold:1;
+			unsigned char has_strongestbtn_hysteresis:1;
+			unsigned char has_filter_strength:1;
+		} __packed;
+		unsigned char data[2];
+	};
+};
+
+struct synaptics_rmi4_f1a_control_0 {
+	union {
+		struct {
+			unsigned char multibutton_report:2;
+			unsigned char filter_mode:2;
+			unsigned char reserved:4;
+		} __packed;
+		unsigned char data[1];
+	};
+};
+
+struct synaptics_rmi4_f1a_control_3_4 {
+	unsigned char transmitterbutton;
+	unsigned char receiverbutton;
+};
+
+struct synaptics_rmi4_f1a_control {
+	struct synaptics_rmi4_f1a_control_0 general_control;
+	unsigned char *button_int_enable;
+	unsigned char *multi_button;
+	struct synaptics_rmi4_f1a_control_3_4 *electrode_map;
+	unsigned char *button_threshold;
+	unsigned char button_release_threshold;
+	unsigned char strongest_button_hysteresis;
+	unsigned char filter_strength;
+};
+
+struct synaptics_rmi4_f1a_handle {
+	int button_bitmask_size;
+	unsigned char button_count;
+	unsigned char valid_button_count;
+	unsigned char *button_data_buffer;
+	unsigned char *button_map;
+	struct synaptics_rmi4_f1a_query button_query;
+	struct synaptics_rmi4_f1a_control button_control;
+};
+
+struct synaptics_rmi4_exp_fn {
+	enum exp_fn fn_type;
+	bool inserted;
+	int (*func_init)(struct synaptics_rmi4_data *rmi4_data);
+	void (*func_remove)(struct synaptics_rmi4_data *rmi4_data);
+	void (*func_attn)(struct synaptics_rmi4_data *rmi4_data,
+			unsigned char intr_mask);
+	struct list_head link;
+};
+
+static struct device_attribute attrs[] = {
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	__ATTR(full_pm_cycle, (S_IRUGO | S_IWUGO),
+			synaptics_rmi4_full_pm_cycle_show,
+			synaptics_rmi4_full_pm_cycle_store),
+#endif
+	__ATTR(reset, S_IWUGO,
+			synaptics_rmi4_show_error,
+			synaptics_rmi4_f01_reset_store),
+	__ATTR(productinfo, S_IRUGO,
+			synaptics_rmi4_f01_productinfo_show,
+			synaptics_rmi4_store_error),
+	__ATTR(buildid, S_IRUGO,
+			synaptics_rmi4_f01_buildid_show,
+			synaptics_rmi4_store_error),
+	__ATTR(flashprog, S_IRUGO,
+			synaptics_rmi4_f01_flashprog_show,
+			synaptics_rmi4_store_error),
+	__ATTR(0dbutton, (S_IRUGO | S_IWUGO),
+			synaptics_rmi4_0dbutton_show,
+			synaptics_rmi4_0dbutton_store),
+};
+
+static bool exp_fn_inited;
+static struct mutex exp_fn_list_mutex;
+static struct list_head exp_fn_list;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			rmi4_data->full_pm_cycle);
+}
+
+static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned int input;
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	if (sscanf(buf, "%u", &input) != 1)
+		return -EINVAL;
+
+	rmi4_data->full_pm_cycle = input > 0 ? 1 : 0;
+
+	return count;
+}
+#endif
+
+static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int retval;
+	unsigned int reset;
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	if (sscanf(buf, "%u", &reset) != 1)
+		return -EINVAL;
+
+	if (reset != 1)
+		return -EINVAL;
+
+	retval = synaptics_rmi4_reset_device(rmi4_data);
+	if (retval < 0) {
+		dev_err(dev,
+				"%s: Failed to issue reset command, error = %d\n",
+				__func__, retval);
+		return retval;
+	}
+
+	return count;
+}
+
+static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n",
+			(rmi4_data->rmi4_mod_info.product_info[0]),
+			(rmi4_data->rmi4_mod_info.product_info[1]));
+}
+
+static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	unsigned int build_id;
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+	struct synaptics_rmi4_device_info *rmi;
+
+	rmi = &(rmi4_data->rmi4_mod_info);
+
+	build_id = (unsigned int)rmi->build_id[0] +
+			(unsigned int)rmi->build_id[1] * 0x100 +
+			(unsigned int)rmi->build_id[2] * 0x10000;
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			build_id);
+}
+
+static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int retval;
+	struct synaptics_rmi4_f01_device_status device_status;
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			rmi4_data->f01_data_base_addr,
+			device_status.data,
+			sizeof(device_status.data));
+	if (retval < 0) {
+		dev_err(dev,
+				"%s: Failed to read device status, error = %d\n",
+				__func__, retval);
+		return retval;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			device_status.flash_prog);
+}
+
+static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			rmi4_data->button_0d_enabled);
+}
+
+static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int retval;
+	unsigned int input;
+	unsigned char ii;
+	unsigned char intr_enable;
+	struct synaptics_rmi4_fn *fhandler;
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+	struct synaptics_rmi4_device_info *rmi;
+
+	rmi = &(rmi4_data->rmi4_mod_info);
+
+	if (sscanf(buf, "%u", &input) != 1)
+		return -EINVAL;
+
+	input = input > 0 ? 1 : 0;
+
+	if (rmi4_data->button_0d_enabled == input)
+		return count;
+
+	list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+		if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
+			ii = fhandler->intr_reg_num;
+
+			retval = synaptics_rmi4_i2c_read(rmi4_data,
+					rmi4_data->f01_ctrl_base_addr + 1 + ii,
+					&intr_enable,
+					sizeof(intr_enable));
+			if (retval < 0)
+				return retval;
+
+			if (input == 1)
+				intr_enable |= fhandler->intr_mask;
+			else
+				intr_enable &= ~fhandler->intr_mask;
+
+			retval = synaptics_rmi4_i2c_write(rmi4_data,
+					rmi4_data->f01_ctrl_base_addr + 1 + ii,
+					&intr_enable,
+					sizeof(intr_enable));
+			if (retval < 0)
+				return retval;
+		}
+	}
+
+	rmi4_data->button_0d_enabled = input;
+
+	return count;
+}
+
+ /**
+ * synaptics_rmi4_set_page()
+ *
+ * Called by synaptics_rmi4_i2c_read() and synaptics_rmi4_i2c_write().
+ *
+ * This function writes to the page select register to switch to the
+ * assigned page.
+ */
+static int synaptics_rmi4_set_page(struct synaptics_rmi4_data *rmi4_data,
+		unsigned int address)
+{
+	int retval = 0;
+	unsigned char retry;
+	unsigned char buf[PAGE_SELECT_LEN];
+	unsigned char page;
+	struct i2c_client *i2c = rmi4_data->i2c_client;
+
+	page = ((address >> 8) & MASK_8BIT);
+	if (page != rmi4_data->current_page) {
+		buf[0] = MASK_8BIT;
+		buf[1] = page;
+		for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
+			retval = i2c_master_send(i2c, buf, PAGE_SELECT_LEN);
+			if (retval != PAGE_SELECT_LEN) {
+				dev_err(&i2c->dev,
+						"%s: I2C retry %d\n",
+						__func__, retry + 1);
+				msleep(20);
+			} else {
+				rmi4_data->current_page = page;
+				break;
+			}
+		}
+	} else
+		return PAGE_SELECT_LEN;
+	return (retval == PAGE_SELECT_LEN) ? retval : -EIO;
+}
+
+ /**
+ * synaptics_rmi4_i2c_read()
+ *
+ * Called by various functions in this driver, and also exported to
+ * other expansion Function modules such as rmi_dev.
+ *
+ * This function reads data of an arbitrary length from the sensor,
+ * starting from an assigned register address of the sensor, via I2C
+ * with a retry mechanism.
+ */
+static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
+		unsigned short addr, unsigned char *data, unsigned short length)
+{
+	int retval;
+	unsigned char retry;
+	unsigned char buf;
+	struct i2c_msg msg[] = {
+		{
+			.addr = rmi4_data->i2c_client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = &buf,
+		},
+		{
+			.addr = rmi4_data->i2c_client->addr,
+			.flags = I2C_M_RD,
+			.len = length,
+			.buf = data,
+		},
+	};
+
+	buf = addr & MASK_8BIT;
+
+	mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex));
+
+	retval = synaptics_rmi4_set_page(rmi4_data, addr);
+	if (retval != PAGE_SELECT_LEN)
+		goto exit;
+
+	for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
+		if (i2c_transfer(rmi4_data->i2c_client->adapter, msg, 2) == 2) {
+			retval = length;
+			break;
+		}
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: I2C retry %d\n",
+				__func__, retry + 1);
+		msleep(20);
+	}
+
+	if (retry == SYN_I2C_RETRY_TIMES) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: I2C read over retry limit\n",
+				__func__);
+		retval = -EIO;
+	}
+
+exit:
+	mutex_unlock(&(rmi4_data->rmi4_io_ctrl_mutex));
+
+	return retval;
+}
+
+ /**
+ * synaptics_rmi4_i2c_write()
+ *
+ * Called by various functions in this driver, and also exported to
+ * other expansion Function modules such as rmi_dev.
+ *
+ * This function writes data of an arbitrary length to the sensor,
+ * starting from an assigned register address of the sensor, via I2C with
+ * a retry mechanism.
+ */
+static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data,
+		unsigned short addr, unsigned char *data, unsigned short length)
+{
+	int retval;
+	unsigned char retry;
+	unsigned char buf[length + 1];
+	struct i2c_msg msg[] = {
+		{
+			.addr = rmi4_data->i2c_client->addr,
+			.flags = 0,
+			.len = length + 1,
+			.buf = buf,
+		}
+	};
+
+	mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex));
+
+	retval = synaptics_rmi4_set_page(rmi4_data, addr);
+	if (retval != PAGE_SELECT_LEN)
+		goto exit;
+
+	buf[0] = addr & MASK_8BIT;
+	memcpy(&buf[1], &data[0], length);
+
+	for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
+		if (i2c_transfer(rmi4_data->i2c_client->adapter, msg, 1) == 1) {
+			retval = length;
+			break;
+		}
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: I2C retry %d\n",
+				__func__, retry + 1);
+		msleep(20);
+	}
+
+	if (retry == SYN_I2C_RETRY_TIMES) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: I2C write over retry limit\n",
+				__func__);
+		retval = -EIO;
+	}
+
+exit:
+	mutex_unlock(&(rmi4_data->rmi4_io_ctrl_mutex));
+
+	return retval;
+}
+
+ /**
+ * synaptics_rmi4_f11_abs_report()
+ *
+ * Called by synaptics_rmi4_report_touch() when valid Function $11
+ * finger data has been detected.
+ *
+ * This function reads the Function $11 data registers, determines the
+ * status of each finger supported by the Function, processes any
+ * necessary coordinate manipulation, reports the finger data to
+ * the input subsystem, and returns the number of fingers detected.
+ */
+static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data,
+		struct synaptics_rmi4_fn *fhandler)
+{
+	int retval;
+	unsigned char touch_count = 0; /* number of touch points */
+	unsigned char reg_index;
+	unsigned char finger;
+	unsigned char fingers_supported;
+	unsigned char num_of_finger_status_regs;
+	unsigned char finger_shift;
+	unsigned char finger_status;
+	unsigned char data_reg_blk_size;
+	unsigned char finger_status_reg[3];
+	unsigned char data[F11_STD_DATA_LEN];
+	unsigned short data_addr;
+	unsigned short data_offset;
+	int x;
+	int y;
+	int wx;
+	int wy;
+
+	/*
+	 * The number of finger status registers is determined by the
+	 * maximum number of fingers supported - 2 bits per finger. So
+	 * the number of finger status registers to read is:
+	 * register_count = ceil(max_num_of_fingers / 4)
+	 */
+	fingers_supported = fhandler->num_of_data_points;
+	num_of_finger_status_regs = (fingers_supported + 3) / 4;
+	data_addr = fhandler->full_addr.data_base;
+	data_reg_blk_size = fhandler->size_of_data_register_block;
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			data_addr,
+			finger_status_reg,
+			num_of_finger_status_regs);
+	if (retval < 0)
+		return 0;
+
+	for (finger = 0; finger < fingers_supported; finger++) {
+		reg_index = finger / 4;
+		finger_shift = (finger % 4) * 2;
+		finger_status = (finger_status_reg[reg_index] >> finger_shift)
+				& MASK_2BIT;
+
+		/*
+		 * Each 2-bit finger status field represents the following:
+		 * 00 = finger not present
+		 * 01 = finger present and data accurate
+		 * 10 = finger present but data may be inaccurate
+		 * 11 = reserved
+		 */
+#ifdef TYPE_B_PROTOCOL
+		input_mt_slot(rmi4_data->input_dev, finger);
+		input_mt_report_slot_state(rmi4_data->input_dev,
+				MT_TOOL_FINGER, finger_status != 0);
+#endif
+
+		if (finger_status) {
+			data_offset = data_addr +
+					num_of_finger_status_regs +
+					(finger * data_reg_blk_size);
+			retval = synaptics_rmi4_i2c_read(rmi4_data,
+					data_offset,
+					data,
+					data_reg_blk_size);
+			if (retval < 0)
+				return 0;
+
+			x = (data[0] << 4) | (data[2] & MASK_4BIT);
+			y = (data[1] << 4) | ((data[2] >> 4) & MASK_4BIT);
+			wx = (data[3] & MASK_4BIT);
+			wy = (data[3] >> 4) & MASK_4BIT;
+
+			if (rmi4_data->board->x_flip)
+				x = rmi4_data->sensor_max_x - x;
+			if (rmi4_data->board->y_flip)
+				y = rmi4_data->sensor_max_y - y;
+
+			dev_dbg(&rmi4_data->i2c_client->dev,
+					"%s: Finger %d:\n"
+					"status = 0x%02x\n"
+					"x = %d\n"
+					"y = %d\n"
+					"wx = %d\n"
+					"wy = %d\n",
+					__func__, finger,
+					finger_status,
+					x, y, wx, wy);
+
+#ifdef TYPE_B_PROTOCOL
+			input_report_abs(rmi4_data->input_dev,
+						ABS_MT_POSITION_X, x);
+			input_report_abs(rmi4_data->input_dev,
+						ABS_MT_POSITION_Y, y);
+#ifdef REPORT_2D_W
+			input_report_abs(rmi4_data->input_dev,
+					ABS_MT_TOUCH_MAJOR, max(wx, wy));
+			input_report_abs(rmi4_data->input_dev,
+					ABS_MT_TOUCH_MINOR, min(wx, wy));
+#endif
+#else
+			input_report_abs(rmi4_data->input_dev,
+					ABS_MT_POSITION_X, x);
+			input_report_abs(rmi4_data->input_dev,
+					ABS_MT_POSITION_Y, y);
+#ifdef REPORT_2D_W
+			input_report_abs(rmi4_data->input_dev,
+					ABS_MT_TOUCH_MAJOR, max(wx, wy));
+			input_report_abs(rmi4_data->input_dev,
+					ABS_MT_TOUCH_MINOR, min(wx, wy));
+#endif
+			input_mt_sync(rmi4_data->input_dev);
+#endif
+			touch_count++;
+		}
+	}
+
+#ifndef TYPE_B_PROTOCOL
+	if (!touch_count)
+		input_mt_sync(rmi4_data->input_dev);
+#else
+	/* sync after groups of events */
+	#ifdef KERNEL_ABOVE_3_7
+	input_mt_sync_frame(rmi4_data->input_dev);
+	#endif
+#endif
+
+	input_sync(rmi4_data->input_dev);
+
+	return touch_count;
+}
+
+static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data,
+		struct synaptics_rmi4_fn *fhandler)
+{
+	int retval;
+	unsigned char button;
+	unsigned char index;
+	unsigned char shift;
+	unsigned char status;
+	unsigned char *data;
+	unsigned short data_addr = fhandler->full_addr.data_base;
+	struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
+	static unsigned char do_once = 1;
+	static bool current_status[MAX_NUMBER_OF_BUTTONS];
+#ifdef NO_0D_WHILE_2D
+	static bool before_2d_status[MAX_NUMBER_OF_BUTTONS];
+	static bool while_2d_status[MAX_NUMBER_OF_BUTTONS];
+#endif
+
+	if (do_once) {
+		memset(current_status, 0, sizeof(current_status));
+#ifdef NO_0D_WHILE_2D
+		memset(before_2d_status, 0, sizeof(before_2d_status));
+		memset(while_2d_status, 0, sizeof(while_2d_status));
+#endif
+		do_once = 0;
+	}
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			data_addr,
+			f1a->button_data_buffer,
+			f1a->button_bitmask_size);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to read button data registers\n",
+				__func__);
+		return;
+	}
+
+	data = f1a->button_data_buffer;
+
+	for (button = 0; button < f1a->valid_button_count; button++) {
+		index = button / 8;
+		shift = button % 8;
+		status = ((data[index] >> shift) & MASK_1BIT);
+
+		if (current_status[button] == status)
+			continue;
+		else
+			current_status[button] = status;
+
+		dev_dbg(&rmi4_data->i2c_client->dev,
+				"%s: Button %d (code %d) ->%d\n",
+				__func__, button,
+				f1a->button_map[button],
+				status);
+#ifdef NO_0D_WHILE_2D
+		if (rmi4_data->fingers_on_2d == false) {
+			if (status == 1) {
+				before_2d_status[button] = 1;
+			} else {
+				if (while_2d_status[button] == 1) {
+					while_2d_status[button] = 0;
+					continue;
+				} else {
+					before_2d_status[button] = 0;
+				}
+			}
+			input_report_key(rmi4_data->input_dev,
+					f1a->button_map[button],
+					status);
+		} else {
+			if (before_2d_status[button] == 1) {
+				before_2d_status[button] = 0;
+				input_report_key(rmi4_data->input_dev,
+						f1a->button_map[button],
+						status);
+			} else {
+				if (status == 1)
+					while_2d_status[button] = 1;
+				else
+					while_2d_status[button] = 0;
+			}
+		}
+#else
+		input_report_key(rmi4_data->input_dev,
+				f1a->button_map[button],
+				status);
+#endif
+	}
+
+	input_sync(rmi4_data->input_dev);
+
+	return;
+}
+
+ /**
+ * synaptics_rmi4_report_touch()
+ *
+ * Called by synaptics_rmi4_sensor_report().
+ *
+ * This function calls the appropriate finger data reporting function
+ * based on the function handler it receives and returns the number of
+ * fingers detected.
+ */
+static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data,
+		struct synaptics_rmi4_fn *fhandler,
+		unsigned char *touch_count)
+{
+	unsigned char touch_count_2d;
+
+	dev_dbg(&rmi4_data->i2c_client->dev,
+			"%s: Function %02x reporting\n",
+			__func__, fhandler->fn_number);
+
+	switch (fhandler->fn_number) {
+	case SYNAPTICS_RMI4_F11:
+		touch_count_2d = synaptics_rmi4_f11_abs_report(rmi4_data,
+				fhandler);
+
+		*touch_count += touch_count_2d;
+
+		if (touch_count_2d)
+			rmi4_data->fingers_on_2d = true;
+		else
+			rmi4_data->fingers_on_2d = false;
+		break;
+
+	case SYNAPTICS_RMI4_F1A:
+		synaptics_rmi4_f1a_report(rmi4_data, fhandler);
+		break;
+
+	default:
+		break;
+	}
+
+	return;
+}
+
+ /**
+ * synaptics_rmi4_sensor_report()
+ *
+ * Called by synaptics_rmi4_irq().
+ *
+ * This function determines the interrupt source(s) from the sensor
+ * and calls synaptics_rmi4_report_touch() with the appropriate
+ * function handler for each function with valid data inputs.
+ */
+static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	unsigned char touch_count = 0;
+	unsigned char intr[MAX_INTR_REGISTERS];
+	struct synaptics_rmi4_fn *fhandler;
+	struct synaptics_rmi4_exp_fn *exp_fhandler;
+	struct synaptics_rmi4_device_info *rmi;
+
+	rmi = &(rmi4_data->rmi4_mod_info);
+
+	/*
+	 * Get interrupt status information from F01 Data1 register to
+	 * determine the source(s) that are flagging the interrupt.
+	 */
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			rmi4_data->f01_data_base_addr + 1,
+			intr,
+			rmi4_data->num_of_intr_regs);
+	if (retval < 0)
+		return retval;
+
+	/*
+	 * Traverse the function handler list and service the source(s)
+	 * of the interrupt accordingly.
+	 */
+	list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+		if (fhandler->num_of_data_sources) {
+			if (fhandler->intr_mask &
+					intr[fhandler->intr_reg_num]) {
+				synaptics_rmi4_report_touch(rmi4_data,
+						fhandler, &touch_count);
+			}
+		}
+	}
+
+	mutex_lock(&exp_fn_list_mutex);
+	if (!list_empty(&exp_fn_list)) {
+		list_for_each_entry(exp_fhandler, &exp_fn_list, link) {
+			if (exp_fhandler->inserted &&
+					(exp_fhandler->func_attn != NULL))
+				exp_fhandler->func_attn(rmi4_data, intr[0]);
+		}
+	}
+	mutex_unlock(&exp_fn_list_mutex);
+
+	return touch_count;
+}
+
+ /**
+ * synaptics_rmi4_irq()
+ *
+ * Called by the kernel when an interrupt occurs (when the sensor
+ * asserts the attention irq).
+ *
+ * This function is the ISR thread and handles the acquisition
+ * and the reporting of finger data when the presence of fingers
+ * is detected.
+ */
+static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
+{
+	struct synaptics_rmi4_data *rmi4_data = data;
+
+	synaptics_rmi4_sensor_report(rmi4_data);
+
+	return IRQ_HANDLED;
+}
+
+ /**
+ * synaptics_rmi4_irq_enable()
+ *
+ * Called by synaptics_rmi4_probe() and the power management functions
+ * in this driver and also exported to other expansion Function modules
+ * such as rmi_dev.
+ *
+ * This function handles the enabling and disabling of the attention
+ * irq including the setting up of the ISR thread.
+ */
+static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
+		bool enable)
+{
+	int retval = 0;
+	unsigned char intr_status;
+	const struct synaptics_rmi4_platform_data *platform_data =
+			rmi4_data->i2c_client->dev.platform_data;
+
+	if (enable) {
+		if (rmi4_data->irq_enabled)
+			return retval;
+
+		/* Clear interrupts first */
+		retval = synaptics_rmi4_i2c_read(rmi4_data,
+				rmi4_data->f01_data_base_addr + 1,
+				&intr_status,
+				rmi4_data->num_of_intr_regs);
+		if (retval < 0)
+			return retval;
+
+		retval = request_threaded_irq(rmi4_data->irq, NULL,
+				synaptics_rmi4_irq, platform_data->irq_flags,
+				DRIVER_NAME, rmi4_data);
+		if (retval < 0) {
+			dev_err(&rmi4_data->i2c_client->dev,
+					"%s: Failed to create irq thread\n",
+					__func__);
+			return retval;
+		}
+
+		rmi4_data->irq_enabled = true;
+	} else {
+		if (rmi4_data->irq_enabled) {
+			disable_irq(rmi4_data->irq);
+			free_irq(rmi4_data->irq, rmi4_data);
+			rmi4_data->irq_enabled = false;
+		}
+	}
+
+	return retval;
+}
+
+ /**
+ * synaptics_rmi4_f11_init()
+ *
+ * Called by synaptics_rmi4_query_device().
+ *
+ * This funtion parses information from the Function 11 registers
+ * and determines the number of fingers supported, x and y data ranges,
+ * offset to the associated interrupt status register, interrupt bit
+ * mask, and gathers finger data acquisition capabilities from the query
+ * registers.
+ */
+static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data,
+		struct synaptics_rmi4_fn *fhandler,
+		struct synaptics_rmi4_fn_desc *fd,
+		unsigned int intr_count)
+{
+	int retval;
+	unsigned char ii;
+	unsigned char intr_offset;
+	unsigned char abs_data_size;
+	unsigned char abs_data_blk_size;
+	unsigned char query[F11_STD_QUERY_LEN];
+	unsigned char control[F11_STD_CTRL_LEN];
+
+	fhandler->fn_number = fd->fn_number;
+	fhandler->num_of_data_sources = fd->intr_src_count;
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			fhandler->full_addr.query_base,
+			query,
+			sizeof(query));
+	if (retval < 0)
+		return retval;
+
+	/* Maximum number of fingers supported */
+	if ((query[1] & MASK_3BIT) <= 4)
+		fhandler->num_of_data_points = (query[1] & MASK_3BIT) + 1;
+	else if ((query[1] & MASK_3BIT) == 5)
+		fhandler->num_of_data_points = 10;
+
+	rmi4_data->num_of_fingers = fhandler->num_of_data_points;
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			fhandler->full_addr.ctrl_base,
+			control,
+			sizeof(control));
+	if (retval < 0)
+		return retval;
+
+	/* Maximum x and y */
+	rmi4_data->sensor_max_x = ((control[6] & MASK_8BIT) << 0) |
+			((control[7] & MASK_4BIT) << 8);
+	rmi4_data->sensor_max_y = ((control[8] & MASK_8BIT) << 0) |
+			((control[9] & MASK_4BIT) << 8);
+	dev_dbg(&rmi4_data->i2c_client->dev,
+			"%s: Function %02x max x = %d max y = %d\n",
+			__func__, fhandler->fn_number,
+			rmi4_data->sensor_max_x,
+			rmi4_data->sensor_max_y);
+
+	fhandler->intr_reg_num = (intr_count + 7) / 8;
+	if (fhandler->intr_reg_num != 0)
+		fhandler->intr_reg_num -= 1;
+
+	/* Set an enable bit for each data source */
+	intr_offset = intr_count % 8;
+	fhandler->intr_mask = 0;
+	for (ii = intr_offset;
+			ii < ((fd->intr_src_count & MASK_3BIT) +
+			intr_offset);
+			ii++)
+		fhandler->intr_mask |= 1 << ii;
+
+	abs_data_size = query[5] & MASK_2BIT;
+	abs_data_blk_size = 3 + (2 * (abs_data_size == 0 ? 1 : 0));
+	fhandler->size_of_data_register_block = abs_data_blk_size;
+
+	return retval;
+}
+
+static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data,
+		struct synaptics_rmi4_fn *fhandler)
+{
+	int retval;
+	struct synaptics_rmi4_f1a_handle *f1a;
+
+	f1a = kzalloc(sizeof(*f1a), GFP_KERNEL);
+	if (!f1a) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for function handle\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	fhandler->data = (void *)f1a;
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			fhandler->full_addr.query_base,
+			f1a->button_query.data,
+			sizeof(f1a->button_query.data));
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to read query registers\n",
+				__func__);
+		return retval;
+	}
+
+	f1a->button_count = f1a->button_query.max_button_count + 1;
+	f1a->button_bitmask_size = (f1a->button_count + 7) / 8;
+
+	f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size,
+			sizeof(*(f1a->button_data_buffer)), GFP_KERNEL);
+	if (!f1a->button_data_buffer) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for data buffer\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	f1a->button_map = kcalloc(f1a->button_count,
+			sizeof(*(f1a->button_map)), GFP_KERNEL);
+	if (!f1a->button_map) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for button map\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int synaptics_rmi4_capacitance_button_map(
+				struct synaptics_rmi4_data *rmi4_data,
+				struct synaptics_rmi4_fn *fhandler)
+{
+	unsigned char ii;
+	struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
+	const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board;
+
+	if (!pdata->capacitance_button_map) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: capacitance_button_map is \
+				NULL in board file\n",
+				__func__);
+		return -ENODEV;
+	} else if (!pdata->capacitance_button_map->map) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Button map is missing in board file\n",
+				__func__);
+		return -ENODEV;
+	} else {
+		if (pdata->capacitance_button_map->nbuttons !=
+			f1a->button_count) {
+			f1a->valid_button_count = min(f1a->button_count,
+				pdata->capacitance_button_map->nbuttons);
+		} else {
+			f1a->valid_button_count = f1a->button_count;
+		}
+
+		for (ii = 0; ii < f1a->valid_button_count; ii++)
+			f1a->button_map[ii] =
+					pdata->capacitance_button_map->map[ii];
+	}
+
+	return 0;
+}
+
+static void synaptics_rmi4_f1a_kfree(struct synaptics_rmi4_fn *fhandler)
+{
+	struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
+
+	if (f1a) {
+		kfree(f1a->button_data_buffer);
+		kfree(f1a->button_map);
+		kfree(f1a);
+		fhandler->data = NULL;
+	}
+
+	return;
+}
+
+static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data,
+		struct synaptics_rmi4_fn *fhandler,
+		struct synaptics_rmi4_fn_desc *fd,
+		unsigned int intr_count)
+{
+	int retval;
+	unsigned char ii;
+	unsigned short intr_offset;
+
+	fhandler->fn_number = fd->fn_number;
+	fhandler->num_of_data_sources = fd->intr_src_count;
+
+	fhandler->intr_reg_num = (intr_count + 7) / 8;
+	if (fhandler->intr_reg_num != 0)
+		fhandler->intr_reg_num -= 1;
+
+	/* Set an enable bit for each data source */
+	intr_offset = intr_count % 8;
+	fhandler->intr_mask = 0;
+	for (ii = intr_offset;
+			ii < ((fd->intr_src_count & MASK_3BIT) +
+			intr_offset);
+			ii++)
+		fhandler->intr_mask |= 1 << ii;
+
+	retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler);
+	if (retval < 0)
+		goto error_exit;
+
+	retval = synaptics_rmi4_capacitance_button_map(rmi4_data, fhandler);
+	if (retval < 0)
+		goto error_exit;
+
+	rmi4_data->button_0d_enabled = 1;
+
+	return 0;
+
+error_exit:
+	synaptics_rmi4_f1a_kfree(fhandler);
+
+	return retval;
+}
+
+static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler,
+		struct synaptics_rmi4_fn_desc *rmi_fd, int page_number)
+{
+	*fhandler = kmalloc(sizeof(**fhandler), GFP_KERNEL);
+	if (!(*fhandler))
+		return -ENOMEM;
+
+	(*fhandler)->full_addr.data_base =
+			(rmi_fd->data_base_addr |
+			(page_number << 8));
+	(*fhandler)->full_addr.ctrl_base =
+			(rmi_fd->ctrl_base_addr |
+			(page_number << 8));
+	(*fhandler)->full_addr.cmd_base =
+			(rmi_fd->cmd_base_addr |
+			(page_number << 8));
+	(*fhandler)->full_addr.query_base =
+			(rmi_fd->query_base_addr |
+			(page_number << 8));
+
+	return 0;
+}
+
+ /**
+ * synaptics_rmi4_query_device()
+ *
+ * Called by synaptics_rmi4_probe().
+ *
+ * This funtion scans the page description table, records the offsets
+ * to the register types of Function $01, sets up the function handlers
+ * for Function $11 and Function $12, determines the number of interrupt
+ * sources from the sensor, adds valid Functions with data inputs to the
+ * Function linked list, parses information from the query registers of
+ * Function $01, and enables the interrupt sources from the valid Functions
+ * with data inputs.
+ */
+static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	unsigned char ii;
+	unsigned char page_number;
+	unsigned char intr_count = 0;
+	unsigned char data_sources = 0;
+	unsigned char f01_query[F01_STD_QUERY_LEN];
+	unsigned short pdt_entry_addr;
+	unsigned short intr_addr;
+	struct synaptics_rmi4_f01_device_status status;
+	struct synaptics_rmi4_fn_desc rmi_fd;
+	struct synaptics_rmi4_fn *fhandler;
+	struct synaptics_rmi4_device_info *rmi;
+
+	rmi = &(rmi4_data->rmi4_mod_info);
+
+	INIT_LIST_HEAD(&rmi->support_fn_list);
+
+	/* Scan the page description tables of the pages to service */
+	for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) {
+		for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END;
+				pdt_entry_addr -= PDT_ENTRY_SIZE) {
+			pdt_entry_addr |= (page_number << 8);
+
+			retval = synaptics_rmi4_i2c_read(rmi4_data,
+					pdt_entry_addr,
+					(unsigned char *)&rmi_fd,
+					sizeof(rmi_fd));
+			if (retval < 0)
+				return retval;
+
+			fhandler = NULL;
+
+			if (rmi_fd.fn_number == 0) {
+				dev_dbg(&rmi4_data->i2c_client->dev,
+						"%s: Reached end of PDT\n",
+						__func__);
+				break;
+			}
+
+			dev_dbg(&rmi4_data->i2c_client->dev,
+					"%s: F%02x found (page %d)\n",
+					__func__, rmi_fd.fn_number,
+					page_number);
+
+			switch (rmi_fd.fn_number) {
+			case SYNAPTICS_RMI4_F01:
+				rmi4_data->f01_query_base_addr =
+						rmi_fd.query_base_addr;
+				rmi4_data->f01_ctrl_base_addr =
+						rmi_fd.ctrl_base_addr;
+				rmi4_data->f01_data_base_addr =
+						rmi_fd.data_base_addr;
+				rmi4_data->f01_cmd_base_addr =
+						rmi_fd.cmd_base_addr;
+
+				retval = synaptics_rmi4_i2c_read(rmi4_data,
+						rmi4_data->f01_data_base_addr,
+						status.data,
+						sizeof(status.data));
+				if (retval < 0)
+					return retval;
+
+				if (status.flash_prog == 1) {
+					pr_notice("%s: In flash prog mode, status = 0x%02x\n",
+							__func__,
+							status.status_code);
+					goto flash_prog_mode;
+				}
+					break;
+			case SYNAPTICS_RMI4_F11:
+				if (rmi_fd.intr_src_count == 0)
+					break;
+
+				retval = synaptics_rmi4_alloc_fh(&fhandler,
+						&rmi_fd, page_number);
+				if (retval < 0) {
+					dev_err(&rmi4_data->i2c_client->dev,
+							"%s: Failed to alloc for F%d\n",
+							__func__,
+							rmi_fd.fn_number);
+					return retval;
+				}
+
+				retval = synaptics_rmi4_f11_init(rmi4_data,
+						fhandler, &rmi_fd, intr_count);
+				if (retval < 0)
+					return retval;
+				break;
+
+			case SYNAPTICS_RMI4_F1A:
+				if (rmi_fd.intr_src_count == 0)
+					break;
+
+				retval = synaptics_rmi4_alloc_fh(&fhandler,
+						&rmi_fd, page_number);
+				if (retval < 0) {
+					dev_err(&rmi4_data->i2c_client->dev,
+							"%s: Failed to alloc for F%d\n",
+							__func__,
+							rmi_fd.fn_number);
+					return retval;
+				}
+
+				retval = synaptics_rmi4_f1a_init(rmi4_data,
+						fhandler, &rmi_fd, intr_count);
+				if (retval < 0)
+					return retval;
+				break;
+			}
+
+			/* Accumulate the interrupt count */
+			intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
+
+			if (fhandler && rmi_fd.intr_src_count) {
+				list_add_tail(&fhandler->link,
+						&rmi->support_fn_list);
+			}
+		}
+	}
+
+flash_prog_mode:
+	rmi4_data->num_of_intr_regs = (intr_count + 7) / 8;
+	dev_dbg(&rmi4_data->i2c_client->dev,
+			"%s: Number of interrupt registers = %d\n",
+			__func__, rmi4_data->num_of_intr_regs);
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			rmi4_data->f01_query_base_addr,
+			f01_query,
+			sizeof(f01_query));
+	if (retval < 0)
+		return retval;
+
+	/* RMI Version 4.0 currently supported */
+	rmi->version_major = 4;
+	rmi->version_minor = 0;
+
+	rmi->manufacturer_id = f01_query[0];
+	rmi->product_props = f01_query[1];
+	rmi->product_info[0] = f01_query[2] & MASK_7BIT;
+	rmi->product_info[1] = f01_query[3] & MASK_7BIT;
+	rmi->date_code[0] = f01_query[4] & MASK_5BIT;
+	rmi->date_code[1] = f01_query[5] & MASK_4BIT;
+	rmi->date_code[2] = f01_query[6] & MASK_5BIT;
+	rmi->tester_id = ((f01_query[7] & MASK_7BIT) << 8) |
+			(f01_query[8] & MASK_7BIT);
+	rmi->serial_number = ((f01_query[9] & MASK_7BIT) << 8) |
+			(f01_query[10] & MASK_7BIT);
+	memcpy(rmi->product_id_string, &f01_query[11], 10);
+
+	if (rmi->manufacturer_id != 1) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Non-Synaptics device found, manufacturer ID = %d\n",
+				__func__, rmi->manufacturer_id);
+	}
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET,
+			rmi->build_id,
+			sizeof(rmi->build_id));
+	if (retval < 0)
+		return retval;
+
+	memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask));
+
+	/*
+	 * Map out the interrupt bit masks for the interrupt sources
+	 * from the registered function handlers.
+	 */
+	list_for_each_entry(fhandler, &rmi->support_fn_list, link)
+		data_sources += fhandler->num_of_data_sources;
+	if (data_sources) {
+		list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+			if (fhandler->num_of_data_sources) {
+				rmi4_data->intr_mask[fhandler->intr_reg_num] |=
+						fhandler->intr_mask;
+			}
+		}
+	}
+
+	/* Enable the interrupt sources */
+	for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) {
+		if (rmi4_data->intr_mask[ii] != 0x00) {
+			dev_dbg(&rmi4_data->i2c_client->dev,
+					"%s: Interrupt enable mask %d = 0x%02x\n",
+					__func__, ii, rmi4_data->intr_mask[ii]);
+			intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii;
+			retval = synaptics_rmi4_i2c_write(rmi4_data,
+					intr_addr,
+					&(rmi4_data->intr_mask[ii]),
+					sizeof(rmi4_data->intr_mask[ii]));
+			if (retval < 0)
+				return retval;
+		}
+	}
+
+	return 0;
+}
+
+static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	unsigned char command = 0x01;
+	struct synaptics_rmi4_fn *fhandler;
+	struct synaptics_rmi4_device_info *rmi;
+
+	rmi = &(rmi4_data->rmi4_mod_info);
+
+	retval = synaptics_rmi4_i2c_write(rmi4_data,
+			rmi4_data->f01_cmd_base_addr,
+			&command,
+			sizeof(command));
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to issue reset command, error = %d\n",
+				__func__, retval);
+		return retval;
+	}
+
+	msleep(100);
+
+	list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+		if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+			synaptics_rmi4_f1a_kfree(fhandler);
+		else
+			kfree(fhandler->data);
+		kfree(fhandler);
+	}
+
+	retval = synaptics_rmi4_query_device(rmi4_data);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to query device\n",
+				__func__);
+		return retval;
+	}
+
+	return 0;
+}
+
+/**
+* synaptics_rmi4_detection_work()
+*
+* Called by the kernel at the scheduled time.
+*
+* This function is a self-rearming work thread that checks for the
+* insertion and removal of other expansion Function modules such as
+* rmi_dev and calls their initialization and removal callback functions
+* accordingly.
+*/
+static void synaptics_rmi4_detection_work(struct work_struct *work)
+{
+	struct synaptics_rmi4_exp_fn *exp_fhandler, *next_list_entry;
+	struct synaptics_rmi4_data *rmi4_data =
+			container_of(work, struct synaptics_rmi4_data,
+			det_work.work);
+
+	queue_delayed_work(rmi4_data->det_workqueue,
+			&rmi4_data->det_work,
+			msecs_to_jiffies(EXP_FN_DET_INTERVAL));
+
+	mutex_lock(&exp_fn_list_mutex);
+	if (!list_empty(&exp_fn_list)) {
+		list_for_each_entry_safe(exp_fhandler,
+				next_list_entry,
+				&exp_fn_list,
+				link) {
+			if ((exp_fhandler->func_init != NULL) &&
+					(exp_fhandler->inserted == false)) {
+				exp_fhandler->func_init(rmi4_data);
+				exp_fhandler->inserted = true;
+			} else if ((exp_fhandler->func_init == NULL) &&
+					(exp_fhandler->inserted == true)) {
+				exp_fhandler->func_remove(rmi4_data);
+				list_del(&exp_fhandler->link);
+				kfree(exp_fhandler);
+			}
+		}
+	}
+	mutex_unlock(&exp_fn_list_mutex);
+
+	return;
+}
+
+/**
+* synaptics_rmi4_new_function()
+*
+* Called by other expansion Function modules in their module init and
+* module exit functions.
+*
+* This function is used by other expansion Function modules such as
+* rmi_dev to register themselves with the driver by providing their
+* initialization and removal callback function pointers so that they
+* can be inserted or removed dynamically at module init and exit times,
+* respectively.
+*/
+void synaptics_rmi4_new_function(enum exp_fn fn_type, bool insert,
+		int (*func_init)(struct synaptics_rmi4_data *rmi4_data),
+		void (*func_remove)(struct synaptics_rmi4_data *rmi4_data),
+		void (*func_attn)(struct synaptics_rmi4_data *rmi4_data,
+		unsigned char intr_mask))
+{
+	struct synaptics_rmi4_exp_fn *exp_fhandler;
+
+	if (!exp_fn_inited) {
+		mutex_init(&exp_fn_list_mutex);
+		INIT_LIST_HEAD(&exp_fn_list);
+		exp_fn_inited = 1;
+	}
+
+	mutex_lock(&exp_fn_list_mutex);
+	if (insert) {
+		exp_fhandler = kzalloc(sizeof(*exp_fhandler), GFP_KERNEL);
+		if (!exp_fhandler) {
+			pr_err("%s: Failed to alloc mem for expansion function\n",
+					__func__);
+			goto exit;
+		}
+		exp_fhandler->fn_type = fn_type;
+		exp_fhandler->func_init = func_init;
+		exp_fhandler->func_attn = func_attn;
+		exp_fhandler->func_remove = func_remove;
+		exp_fhandler->inserted = false;
+		list_add_tail(&exp_fhandler->link, &exp_fn_list);
+	} else {
+		list_for_each_entry(exp_fhandler, &exp_fn_list, link) {
+			if (exp_fhandler->func_init == func_init) {
+				exp_fhandler->inserted = false;
+				exp_fhandler->func_init = NULL;
+				exp_fhandler->func_attn = NULL;
+				goto exit;
+			}
+		}
+	}
+
+exit:
+	mutex_unlock(&exp_fn_list_mutex);
+
+	return;
+}
+EXPORT_SYMBOL(synaptics_rmi4_new_function);
+
+ /**
+ * synaptics_rmi4_probe()
+ *
+ * Called by the kernel when an association with an I2C device of the
+ * same name is made (after doing i2c_add_driver).
+ *
+ * This funtion allocates and initializes the resources for the driver
+ * as an input driver, turns on the power to the sensor, queries the
+ * sensor for its supported Functions and characteristics, registers
+ * the driver to the input subsystem, sets up the interrupt, handles
+ * the registration of the early_suspend and late_resume functions,
+ * and creates a work queue for detection of other expansion Function
+ * modules.
+ */
+static int __devinit synaptics_rmi4_probe(struct i2c_client *client,
+		const struct i2c_device_id *dev_id)
+{
+	int retval;
+	unsigned char ii;
+	unsigned char attr_count;
+	struct synaptics_rmi4_f1a_handle *f1a;
+	struct synaptics_rmi4_fn *fhandler;
+	struct synaptics_rmi4_data *rmi4_data;
+	struct synaptics_rmi4_device_info *rmi;
+	const struct synaptics_rmi4_platform_data *platform_data =
+			client->dev.platform_data;
+
+	if (!i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev,
+				"%s: SMBus byte data not supported\n",
+				__func__);
+		return -EIO;
+	}
+
+	if (!platform_data) {
+		dev_err(&client->dev,
+				"%s: No platform data found\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	rmi4_data = kzalloc(sizeof(*rmi4_data) * 2, GFP_KERNEL);
+	if (!rmi4_data) {
+		dev_err(&client->dev,
+				"%s: Failed to alloc mem for rmi4_data\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	rmi = &(rmi4_data->rmi4_mod_info);
+
+	rmi4_data->input_dev = input_allocate_device();
+	if (rmi4_data->input_dev == NULL) {
+		dev_err(&client->dev,
+				"%s: Failed to allocate input device\n",
+				__func__);
+		retval = -ENOMEM;
+		goto err_input_device;
+	}
+/*
+	if (platform_data->regulator_en) {
+		rmi4_data->regulator = regulator_get(&client->dev, "vdd");
+		if (IS_ERR(rmi4_data->regulator)) {
+			dev_err(&client->dev,
+					"%s: Failed to get regulator\n",
+					__func__);
+			retval = PTR_ERR(rmi4_data->regulator);
+			goto err_regulator;
+		}
+		regulator_enable(rmi4_data->regulator);
+	}
+*/
+	rmi4_data->i2c_client = client;
+	rmi4_data->current_page = MASK_8BIT;
+	rmi4_data->board = platform_data;
+	rmi4_data->touch_stopped = false;
+	rmi4_data->sensor_sleep = false;
+	rmi4_data->irq_enabled = false;
+
+	rmi4_data->i2c_read = synaptics_rmi4_i2c_read;
+	rmi4_data->i2c_write = synaptics_rmi4_i2c_write;
+	rmi4_data->irq_enable = synaptics_rmi4_irq_enable;
+	rmi4_data->reset_device = synaptics_rmi4_reset_device;
+
+	init_waitqueue_head(&rmi4_data->wait);
+	mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
+
+	retval = synaptics_rmi4_query_device(rmi4_data);
+	if (retval < 0) {
+		dev_err(&client->dev,
+				"%s: Failed to query device\n",
+				__func__);
+		goto err_query_device;
+	}
+
+	i2c_set_clientdata(client, rmi4_data);
+
+	rmi4_data->input_dev->name = DRIVER_NAME;
+	rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
+	rmi4_data->input_dev->id.bustype = BUS_I2C;
+	rmi4_data->input_dev->dev.parent = &client->dev;
+	input_set_drvdata(rmi4_data->input_dev, rmi4_data);
+
+	set_bit(EV_SYN, rmi4_data->input_dev->evbit);
+	set_bit(EV_KEY, rmi4_data->input_dev->evbit);
+	set_bit(EV_ABS, rmi4_data->input_dev->evbit);
+
+#ifdef INPUT_PROP_DIRECT
+	set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit);
+#endif
+
+	input_set_abs_params(rmi4_data->input_dev,
+			ABS_MT_POSITION_X, 0,
+			rmi4_data->sensor_max_x, 0, 0);
+	input_set_abs_params(rmi4_data->input_dev,
+			ABS_MT_POSITION_Y, 0,
+			rmi4_data->sensor_max_y, 0, 0);
+#ifdef REPORT_2D_W
+	input_set_abs_params(rmi4_data->input_dev,
+			ABS_MT_TOUCH_MAJOR, 0,
+			MAX_ABS_MT_TOUCH_MAJOR, 0, 0);
+#endif
+
+#ifdef TYPE_B_PROTOCOL
+	input_mt_init_slots(rmi4_data->input_dev,
+			rmi4_data->num_of_fingers);
+#endif
+
+	f1a = NULL;
+	list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+		if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+			f1a = fhandler->data;
+	}
+
+	if (f1a) {
+		for (ii = 0; ii < f1a->valid_button_count; ii++) {
+			set_bit(f1a->button_map[ii],
+					rmi4_data->input_dev->keybit);
+			input_set_capability(rmi4_data->input_dev,
+					EV_KEY, f1a->button_map[ii]);
+		}
+	}
+
+	retval = input_register_device(rmi4_data->input_dev);
+	if (retval) {
+		dev_err(&client->dev,
+				"%s: Failed to register input device\n",
+				__func__);
+		goto err_register_input;
+	}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	rmi4_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	rmi4_data->early_suspend.suspend = synaptics_rmi4_early_suspend;
+	rmi4_data->early_suspend.resume = synaptics_rmi4_late_resume;
+	register_early_suspend(&rmi4_data->early_suspend);
+#endif
+
+	if (!exp_fn_inited) {
+		mutex_init(&exp_fn_list_mutex);
+		INIT_LIST_HEAD(&exp_fn_list);
+		exp_fn_inited = 1;
+	}
+
+	rmi4_data->det_workqueue =
+			create_singlethread_workqueue("rmi_det_workqueue");
+	INIT_DELAYED_WORK(&rmi4_data->det_work,
+			synaptics_rmi4_detection_work);
+	queue_delayed_work(rmi4_data->det_workqueue,
+			&rmi4_data->det_work,
+			msecs_to_jiffies(EXP_FN_DET_INTERVAL));
+
+	if (platform_data->gpio_config) {
+		retval = platform_data->gpio_config(platform_data->irq_gpio,
+							true);
+		if (retval < 0) {
+			dev_err(&client->dev,
+					"%s: Failed to configure GPIO\n",
+					__func__);
+			goto err_gpio;
+		}
+	}
+
+	rmi4_data->irq = gpio_to_irq(platform_data->irq_gpio);
+
+	retval = synaptics_rmi4_irq_enable(rmi4_data, true);
+	if (retval < 0) {
+		dev_err(&client->dev,
+				"%s: Failed to enable attention interrupt\n",
+				__func__);
+		goto err_enable_irq;
+	}
+
+	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+		retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
+				&attrs[attr_count].attr);
+		if (retval < 0) {
+			dev_err(&client->dev,
+					"%s: Failed to create sysfs attributes\n",
+					__func__);
+			goto err_sysfs;
+		}
+	}
+
+	return retval;
+
+err_sysfs:
+	for (attr_count--; attr_count >= 0; attr_count--) {
+		sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+				&attrs[attr_count].attr);
+	}
+
+err_enable_irq:
+err_gpio:
+	input_unregister_device(rmi4_data->input_dev);
+
+err_register_input:
+err_query_device:
+	if (platform_data->regulator_en) {
+		regulator_disable(rmi4_data->regulator);
+		regulator_put(rmi4_data->regulator);
+	}
+
+	list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+		if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+			synaptics_rmi4_f1a_kfree(fhandler);
+		else
+			kfree(fhandler->data);
+		kfree(fhandler);
+	}
+/*
+err_regulator:
+*/
+	input_free_device(rmi4_data->input_dev);
+	rmi4_data->input_dev = NULL;
+
+err_input_device:
+	kfree(rmi4_data);
+
+	return retval;
+}
+
+ /**
+ * synaptics_rmi4_remove()
+ *
+ * Called by the kernel when the association with an I2C device of the
+ * same name is broken (when the driver is unloaded).
+ *
+ * This funtion terminates the work queue, stops sensor data acquisition,
+ * frees the interrupt, unregisters the driver from the input subsystem,
+ * turns off the power to the sensor, and frees other allocated resources.
+ */
+static int __devexit synaptics_rmi4_remove(struct i2c_client *client)
+{
+	unsigned char attr_count;
+	struct synaptics_rmi4_fn *fhandler;
+	struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client);
+	struct synaptics_rmi4_device_info *rmi;
+	const struct synaptics_rmi4_platform_data *platform_data =
+			rmi4_data->board;
+
+	rmi = &(rmi4_data->rmi4_mod_info);
+
+	cancel_delayed_work_sync(&rmi4_data->det_work);
+	flush_workqueue(rmi4_data->det_workqueue);
+	destroy_workqueue(rmi4_data->det_workqueue);
+
+	rmi4_data->touch_stopped = true;
+	wake_up(&rmi4_data->wait);
+
+	synaptics_rmi4_irq_enable(rmi4_data, false);
+
+	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+		sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+				&attrs[attr_count].attr);
+	}
+
+	input_unregister_device(rmi4_data->input_dev);
+
+	if (platform_data->regulator_en) {
+		regulator_disable(rmi4_data->regulator);
+		regulator_put(rmi4_data->regulator);
+	}
+
+	list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+		if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+			synaptics_rmi4_f1a_kfree(fhandler);
+		else
+			kfree(fhandler->data);
+		kfree(fhandler);
+	}
+	input_free_device(rmi4_data->input_dev);
+
+	kfree(rmi4_data);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+ /**
+ * synaptics_rmi4_sensor_sleep()
+ *
+ * Called by synaptics_rmi4_early_suspend() and synaptics_rmi4_suspend().
+ *
+ * This function stops finger data acquisition and puts the sensor to sleep.
+ */
+static void synaptics_rmi4_sensor_sleep(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	unsigned char device_ctrl;
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			rmi4_data->f01_ctrl_base_addr,
+			&device_ctrl,
+			sizeof(device_ctrl));
+	if (retval < 0) {
+		dev_err(&(rmi4_data->input_dev->dev),
+				"%s: Failed to enter sleep mode\n",
+				__func__);
+		rmi4_data->sensor_sleep = false;
+		return;
+	}
+
+	device_ctrl = (device_ctrl & ~MASK_3BIT);
+	device_ctrl = (device_ctrl | NO_SLEEP_OFF | SENSOR_SLEEP);
+
+	retval = synaptics_rmi4_i2c_write(rmi4_data,
+			rmi4_data->f01_ctrl_base_addr,
+			&device_ctrl,
+			sizeof(device_ctrl));
+	if (retval < 0) {
+		dev_err(&(rmi4_data->input_dev->dev),
+				"%s: Failed to enter sleep mode\n",
+				__func__);
+		rmi4_data->sensor_sleep = false;
+		return;
+	} else {
+		rmi4_data->sensor_sleep = true;
+	}
+
+	return;
+}
+
+ /**
+ * synaptics_rmi4_sensor_wake()
+ *
+ * Called by synaptics_rmi4_resume() and synaptics_rmi4_late_resume().
+ *
+ * This function wakes the sensor from sleep.
+ */
+static void synaptics_rmi4_sensor_wake(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	unsigned char device_ctrl;
+
+	retval = synaptics_rmi4_i2c_read(rmi4_data,
+			rmi4_data->f01_ctrl_base_addr,
+			&device_ctrl,
+			sizeof(device_ctrl));
+	if (retval < 0) {
+		dev_err(&(rmi4_data->input_dev->dev),
+				"%s: Failed to wake from sleep mode\n",
+				__func__);
+		rmi4_data->sensor_sleep = true;
+		return;
+	}
+
+	device_ctrl = (device_ctrl & ~MASK_3BIT);
+	device_ctrl = (device_ctrl | NO_SLEEP_OFF | NORMAL_OPERATION);
+
+	retval = synaptics_rmi4_i2c_write(rmi4_data,
+			rmi4_data->f01_ctrl_base_addr,
+			&device_ctrl,
+			sizeof(device_ctrl));
+	if (retval < 0) {
+		dev_err(&(rmi4_data->input_dev->dev),
+				"%s: Failed to wake from sleep mode\n",
+				__func__);
+		rmi4_data->sensor_sleep = true;
+		return;
+	} else {
+		rmi4_data->sensor_sleep = false;
+	}
+
+	return;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ /**
+ * synaptics_rmi4_early_suspend()
+ *
+ * Called by the kernel during the early suspend phase when the system
+ * enters suspend.
+ *
+ * This function calls synaptics_rmi4_sensor_sleep() to stop finger
+ * data acquisition and put the sensor to sleep.
+ */
+static void synaptics_rmi4_early_suspend(struct early_suspend *h)
+{
+	struct synaptics_rmi4_data *rmi4_data =
+			container_of(h, struct synaptics_rmi4_data,
+			early_suspend);
+
+	rmi4_data->touch_stopped = true;
+	wake_up(&rmi4_data->wait);
+	synaptics_rmi4_irq_enable(rmi4_data, false);
+	synaptics_rmi4_sensor_sleep(rmi4_data);
+
+	if (rmi4_data->full_pm_cycle)
+		synaptics_rmi4_suspend(&(rmi4_data->input_dev->dev));
+
+	return;
+}
+
+ /**
+ * synaptics_rmi4_late_resume()
+ *
+ * Called by the kernel during the late resume phase when the system
+ * wakes up from suspend.
+ *
+ * This function goes through the sensor wake process if the system wakes
+ * up from early suspend (without going into suspend).
+ */
+static void synaptics_rmi4_late_resume(struct early_suspend *h)
+{
+	struct synaptics_rmi4_data *rmi4_data =
+			container_of(h, struct synaptics_rmi4_data,
+			early_suspend);
+
+	if (rmi4_data->full_pm_cycle)
+		synaptics_rmi4_resume(&(rmi4_data->input_dev->dev));
+
+	if (rmi4_data->sensor_sleep == true) {
+		synaptics_rmi4_sensor_wake(rmi4_data);
+		rmi4_data->touch_stopped = false;
+		synaptics_rmi4_irq_enable(rmi4_data, true);
+	}
+
+	return;
+}
+#endif
+
+ /**
+ * synaptics_rmi4_suspend()
+ *
+ * Called by the kernel during the suspend phase when the system
+ * enters suspend.
+ *
+ * This function stops finger data acquisition and puts the sensor to
+ * sleep (if not already done so during the early suspend phase),
+ * disables the interrupt, and turns off the power to the sensor.
+ */
+static int synaptics_rmi4_suspend(struct device *dev)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+	const struct synaptics_rmi4_platform_data *platform_data =
+			rmi4_data->board;
+
+	if (!rmi4_data->sensor_sleep) {
+		rmi4_data->touch_stopped = true;
+		wake_up(&rmi4_data->wait);
+		synaptics_rmi4_irq_enable(rmi4_data, false);
+		synaptics_rmi4_sensor_sleep(rmi4_data);
+	}
+
+	if (platform_data->regulator_en)
+		regulator_disable(rmi4_data->regulator);
+
+	return 0;
+}
+
+ /**
+ * synaptics_rmi4_resume()
+ *
+ * Called by the kernel during the resume phase when the system
+ * wakes up from suspend.
+ *
+ * This function turns on the power to the sensor, wakes the sensor
+ * from sleep, enables the interrupt, and starts finger data
+ * acquisition.
+ */
+static int synaptics_rmi4_resume(struct device *dev)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+	const struct synaptics_rmi4_platform_data *platform_data =
+			rmi4_data->board;
+
+	if (platform_data->regulator_en)
+		regulator_enable(rmi4_data->regulator);
+
+	synaptics_rmi4_sensor_wake(rmi4_data);
+	rmi4_data->touch_stopped = false;
+	synaptics_rmi4_irq_enable(rmi4_data, true);
+
+	return 0;
+}
+
+static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = {
+	.suspend = synaptics_rmi4_suspend,
+	.resume  = synaptics_rmi4_resume,
+};
+#endif
+
+static const struct i2c_device_id synaptics_rmi4_id_table[] = {
+	{DRIVER_NAME, 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table);
+
+static struct i2c_driver synaptics_rmi4_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &synaptics_rmi4_dev_pm_ops,
+#endif
+	},
+	.probe = synaptics_rmi4_probe,
+	.remove = __devexit_p(synaptics_rmi4_remove),
+	.id_table = synaptics_rmi4_id_table,
+};
+
+ /**
+ * synaptics_rmi4_init()
+ *
+ * Called by the kernel during do_initcalls (if built-in)
+ * or when the driver is loaded (if a module).
+ *
+ * This function registers the driver to the I2C subsystem.
+ *
+ */
+static int __init synaptics_rmi4_init(void)
+{
+	return i2c_add_driver(&synaptics_rmi4_driver);
+}
+
+ /**
+ * synaptics_rmi4_exit()
+ *
+ * Called by the kernel when the driver is unloaded.
+ *
+ * This funtion unregisters the driver from the I2C subsystem.
+ *
+ */
+static void __exit synaptics_rmi4_exit(void)
+{
+	i2c_del_driver(&synaptics_rmi4_driver);
+}
+
+module_init(synaptics_rmi4_init);
+module_exit(synaptics_rmi4_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("Synaptics RMI4 I2C Touch Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION);
diff --git a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h
new file mode 100644
index 0000000..7ee0a92
--- /dev/null
+++ b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -0,0 +1,282 @@
+/*
+ * Synaptics RMI4 touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _SYNAPTICS_DSX_RMI4_H_
+#define _SYNAPTICS_DSX_RMI4_H_
+
+#define SYNAPTICS_RMI4_DRIVER_VERSION "DSX 1.0"
+
+#include <linux/version.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38))
+#define KERNEL_ABOVE_2_6_38
+#endif
+
+#ifdef KERNEL_ABOVE_2_6_38
+#define sstrtoul(...) kstrtoul(__VA_ARGS__)
+#else
+#define sstrtoul(...) strict_strtoul(__VA_ARGS__)
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0))
+#define KERNEL_ABOVE_3_7
+#endif
+
+#define PDT_PROPS (0x00EF)
+#define PDT_START (0x00E9)
+#define PDT_END (0x000A)
+#define PDT_ENTRY_SIZE (0x0006)
+#define PAGES_TO_SERVICE (10)
+#define PAGE_SELECT_LEN (2)
+
+#define SYNAPTICS_RMI4_F01 (0x01)
+#define SYNAPTICS_RMI4_F11 (0x11)
+#define SYNAPTICS_RMI4_F1A (0x1a)
+#define SYNAPTICS_RMI4_F34 (0x34)
+#define SYNAPTICS_RMI4_F54 (0x54)
+#define SYNAPTICS_RMI4_F55 (0x55)
+
+#define SYNAPTICS_RMI4_PRODUCT_INFO_SIZE 2
+#define SYNAPTICS_RMI4_DATE_CODE_SIZE 3
+#define SYNAPTICS_RMI4_PRODUCT_ID_SIZE 10
+#define SYNAPTICS_RMI4_BUILD_ID_SIZE 3
+
+#define MAX_NUMBER_OF_FINGERS 10
+#define MAX_NUMBER_OF_BUTTONS 4
+#define MAX_INTR_REGISTERS 4
+
+#define MASK_16BIT 0xFFFF
+#define MASK_8BIT 0xFF
+#define MASK_7BIT 0x7F
+#define MASK_6BIT 0x3F
+#define MASK_5BIT 0x1F
+#define MASK_4BIT 0x0F
+#define MASK_3BIT 0x07
+#define MASK_2BIT 0x03
+#define MASK_1BIT 0x01
+
+/*
+ * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT
+ * @query_base_addr: base address for query registers
+ * @cmd_base_addr: base address for command registers
+ * @ctrl_base_addr: base address for control registers
+ * @data_base_addr: base address for data registers
+ * @intr_src_count: number of interrupt sources
+ * @fn_number: function number
+ */
+struct synaptics_rmi4_fn_desc {
+	unsigned char query_base_addr;
+	unsigned char cmd_base_addr;
+	unsigned char ctrl_base_addr;
+	unsigned char data_base_addr;
+	unsigned char intr_src_count;
+	unsigned char fn_number;
+};
+
+/*
+ * synaptics_rmi4_fn_full_addr - full 16-bit base addresses
+ * @query_base: 16-bit base address for query registers
+ * @cmd_base: 16-bit base address for data registers
+ * @ctrl_base: 16-bit base address for command registers
+ * @data_base: 16-bit base address for control registers
+ */
+struct synaptics_rmi4_fn_full_addr {
+	unsigned short query_base;
+	unsigned short cmd_base;
+	unsigned short ctrl_base;
+	unsigned short data_base;
+};
+
+/*
+ * struct synaptics_rmi4_fn - function handler data structure
+ * @fn_number: function number
+ * @num_of_data_sources: number of data sources
+ * @num_of_data_points: maximum number of fingers supported
+ * @size_of_data_register_block: data register block size
+ * @data1_offset: offset to data1 register from data base address
+ * @intr_reg_num: index to associated interrupt register
+ * @intr_mask: interrupt mask
+ * @full_addr: full 16-bit base addresses of function registers
+ * @link: linked list for function handlers
+ * @data_size: size of private data
+ * @data: pointer to private data
+ */
+struct synaptics_rmi4_fn {
+	unsigned char fn_number;
+	unsigned char num_of_data_sources;
+	unsigned char num_of_data_points;
+	unsigned char size_of_data_register_block;
+	unsigned char data1_offset;
+	unsigned char intr_reg_num;
+	unsigned char intr_mask;
+	struct synaptics_rmi4_fn_full_addr full_addr;
+	struct list_head link;
+	int data_size;
+	void *data;
+};
+
+/*
+ * struct synaptics_rmi4_device_info - device information
+ * @version_major: rmi protocol major version number
+ * @version_minor: rmi protocol minor version number
+ * @manufacturer_id: manufacturer id
+ * @product_props: product properties information
+ * @product_info: product info array
+ * @date_code: device manufacture date
+ * @tester_id: tester id array
+ * @serial_number: device serial number
+ * @product_id_string: device product id
+ * @support_fn_list: linked list for function handlers
+ */
+struct synaptics_rmi4_device_info {
+	unsigned int version_major;
+	unsigned int version_minor;
+	unsigned char manufacturer_id;
+	unsigned char product_props;
+	unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
+	unsigned char date_code[SYNAPTICS_RMI4_DATE_CODE_SIZE];
+	unsigned short tester_id;
+	unsigned short serial_number;
+	unsigned char product_id_string[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
+	unsigned char build_id[SYNAPTICS_RMI4_BUILD_ID_SIZE];
+	struct list_head support_fn_list;
+};
+
+/*
+ * struct synaptics_rmi4_data - rmi4 device instance data
+ * @i2c_client: pointer to associated i2c client
+ * @input_dev: pointer to associated input device
+ * @board: constant pointer to platform data
+ * @rmi4_mod_info: device information
+ * @regulator: pointer to associated regulator
+ * @rmi4_io_ctrl_mutex: mutex for i2c i/o control
+ * @det_work: work thread instance for expansion function detection
+ * @det_workqueue: pointer to work queue for work thread instance
+ * @early_suspend: instance to support early suspend power management
+ * @current_page: current page in sensor to acess
+ * @button_0d_enabled: flag for 0d button support
+ * @full_pm_cycle: flag for full power management cycle in early suspend stage
+ * @num_of_intr_regs: number of interrupt registers
+ * @f01_query_base_addr: query base address for f01
+ * @f01_cmd_base_addr: command base address for f01
+ * @f01_ctrl_base_addr: control base address for f01
+ * @f01_data_base_addr: data base address for f01
+ * @irq: attention interrupt
+ * @sensor_max_x: sensor maximum x value
+ * @sensor_max_y: sensor maximum y value
+ * @irq_enabled: flag for indicating interrupt enable status
+ * @touch_stopped: flag to stop interrupt thread processing
+ * @fingers_on_2d: flag to indicate presence of fingers in 2d area
+ * @sensor_sleep: flag to indicate sleep state of sensor
+ * @wait: wait queue for touch data polling in interrupt thread
+ * @i2c_read: pointer to i2c read function
+ * @i2c_write: pointer to i2c write function
+ * @irq_enable: pointer to irq enable function
+ */
+struct synaptics_rmi4_data {
+	struct i2c_client *i2c_client;
+	struct input_dev *input_dev;
+	const struct synaptics_rmi4_platform_data *board;
+	struct synaptics_rmi4_device_info rmi4_mod_info;
+	struct regulator *regulator;
+	struct mutex rmi4_io_ctrl_mutex;
+	struct delayed_work det_work;
+	struct workqueue_struct *det_workqueue;
+	struct early_suspend early_suspend;
+	unsigned char current_page;
+	unsigned char button_0d_enabled;
+	unsigned char full_pm_cycle;
+	unsigned char num_of_rx;
+	unsigned char num_of_tx;
+	unsigned char num_of_fingers;
+	unsigned char intr_mask[MAX_INTR_REGISTERS];
+	unsigned short num_of_intr_regs;
+	unsigned short f01_query_base_addr;
+	unsigned short f01_cmd_base_addr;
+	unsigned short f01_ctrl_base_addr;
+	unsigned short f01_data_base_addr;
+	int irq;
+	int sensor_max_x;
+	int sensor_max_y;
+	bool irq_enabled;
+	bool touch_stopped;
+	bool fingers_on_2d;
+	bool sensor_sleep;
+	wait_queue_head_t wait;
+	int (*i2c_read)(struct synaptics_rmi4_data *pdata, unsigned short addr,
+			unsigned char *data, unsigned short length);
+	int (*i2c_write)(struct synaptics_rmi4_data *pdata, unsigned short addr,
+			unsigned char *data, unsigned short length);
+	int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable);
+	int (*reset_device)(struct synaptics_rmi4_data *rmi4_data);
+};
+
+enum exp_fn {
+	RMI_DEV = 0,
+	RMI_F34,
+	RMI_F54,
+	RMI_FW_UPDATER,
+	RMI_LAST,
+};
+
+struct synaptics_rmi4_exp_fn_ptr {
+	int (*read)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
+			unsigned char *data, unsigned short length);
+	int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
+			unsigned char *data, unsigned short length);
+	int (*enable)(struct synaptics_rmi4_data *rmi4_data, bool enable);
+};
+
+void synaptics_rmi4_new_function(enum exp_fn fn_type, bool insert,
+		int (*func_init)(struct synaptics_rmi4_data *rmi4_data),
+		void (*func_remove)(struct synaptics_rmi4_data *rmi4_data),
+		void (*func_attn)(struct synaptics_rmi4_data *rmi4_data,
+				unsigned char intr_mask));
+
+static inline ssize_t synaptics_rmi4_show_error(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	dev_warn(dev, "%s Attempted to read from write-only attribute %s\n",
+			__func__, attr->attr.name);
+	return -EPERM;
+}
+
+static inline ssize_t synaptics_rmi4_store_error(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	dev_warn(dev, "%s Attempted to write to read-only attribute %s\n",
+			__func__, attr->attr.name);
+	return -EPERM;
+}
+
+static inline void batohs(unsigned short *dest, unsigned char *src)
+{
+	*dest = src[1] * 0x100 + src[0];
+}
+
+static inline void hstoba(unsigned char *dest, unsigned short src)
+{
+	dest[0] = src % 0x100;
+	dest[1] = src / 0x100;
+}
+
+#endif
diff --git a/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c b/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c
new file mode 100644
index 0000000..7585780
--- /dev/null
+++ b/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -0,0 +1,710 @@
+/*
+ * Synaptics RMI4 touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/uaccess.h>
+#include <linux/cdev.h>
+#include <linux/input/synaptics_dsx.h>
+#include "synaptics_i2c_rmi4.h"
+
+#define CHAR_DEVICE_NAME "rmi"
+#define DEVICE_CLASS_NAME "rmidev"
+#define DEV_NUMBER 1
+#define REG_ADDR_LIMIT 0xFFFF
+
+static ssize_t rmidev_sysfs_open_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t rmidev_sysfs_release_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t rmidev_sysfs_address_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t rmidev_sysfs_length_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t rmidev_sysfs_data_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t rmidev_sysfs_data_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+struct rmidev_handle {
+	dev_t dev_no;
+	unsigned short address;
+	unsigned int length;
+	struct device dev;
+	struct synaptics_rmi4_data *rmi4_data;
+	struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
+	struct kobject *sysfs_dir;
+	void *data;
+};
+
+struct rmidev_data {
+	int ref_count;
+	struct cdev main_dev;
+	struct class *device_class;
+	struct mutex file_mutex;
+	struct rmidev_handle *rmi_dev;
+};
+
+static struct device_attribute attrs[] = {
+	__ATTR(open, S_IWUGO,
+			synaptics_rmi4_show_error,
+			rmidev_sysfs_open_store),
+	__ATTR(release, S_IWUGO,
+			synaptics_rmi4_show_error,
+			rmidev_sysfs_release_store),
+	__ATTR(address, S_IWUGO,
+			synaptics_rmi4_show_error,
+			rmidev_sysfs_address_store),
+	__ATTR(length, S_IWUGO,
+			synaptics_rmi4_show_error,
+			rmidev_sysfs_length_store),
+	__ATTR(data, (S_IRUGO | S_IWUGO),
+			rmidev_sysfs_data_show,
+			rmidev_sysfs_data_store),
+};
+
+static int rmidev_major_num;
+
+static struct class *rmidev_device_class;
+
+static struct rmidev_handle *rmidev;
+
+static struct completion remove_complete;
+
+static ssize_t rmidev_sysfs_open_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned int input;
+
+	if (sscanf(buf, "%u", &input) != 1)
+			return -EINVAL;
+
+	if (input != 1)
+		return -EINVAL;
+
+	rmidev->fn_ptr->enable(rmidev->rmi4_data, false);
+	dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
+			"%s: Attention interrupt disabled\n",
+			__func__);
+
+	return count;
+}
+
+static ssize_t rmidev_sysfs_release_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned int input;
+
+	if (sscanf(buf, "%u", &input) != 1)
+			return -EINVAL;
+
+	if (input != 1)
+		return -EINVAL;
+
+	rmidev->fn_ptr->enable(rmidev->rmi4_data, true);
+	dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
+			"%s: Attention interrupt enabled\n",
+			__func__);
+
+	return count;
+}
+
+static ssize_t rmidev_sysfs_address_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned int input;
+
+	if (sscanf(buf, "%u", &input) != 1)
+			return -EINVAL;
+
+	if (input > REG_ADDR_LIMIT)
+		return -EINVAL;
+
+	rmidev->address = (unsigned short)input;
+
+	return count;
+}
+
+static ssize_t rmidev_sysfs_length_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned int input;
+
+	if (sscanf(buf, "%u", &input) != 1)
+			return -EINVAL;
+
+	if (input > REG_ADDR_LIMIT)
+		return -EINVAL;
+
+	rmidev->length = input;
+
+	return count;
+}
+
+static ssize_t rmidev_sysfs_data_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int retval;
+	unsigned int data_length = rmidev->length;
+
+	if (data_length > (REG_ADDR_LIMIT - rmidev->address))
+		data_length = REG_ADDR_LIMIT - rmidev->address;
+
+	if (data_length) {
+		retval = rmidev->fn_ptr->read(rmidev->rmi4_data,
+				rmidev->address,
+				(unsigned char *)buf,
+				data_length);
+		if (retval < 0) {
+			dev_err(&rmidev->rmi4_data->i2c_client->dev,
+					"%s: Failed to read data\n",
+					__func__);
+			return retval;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return data_length;
+}
+
+static ssize_t rmidev_sysfs_data_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int retval;
+	unsigned int data_length = rmidev->length;
+
+	if (data_length > (REG_ADDR_LIMIT - rmidev->address))
+		data_length = REG_ADDR_LIMIT - rmidev->address;
+
+	if (data_length) {
+		retval = rmidev->fn_ptr->write(rmidev->rmi4_data,
+				rmidev->address,
+				(unsigned char *)buf,
+				data_length);
+		if (retval < 0) {
+			dev_err(&rmidev->rmi4_data->i2c_client->dev,
+					"%s: Failed to write data\n",
+					__func__);
+			return retval;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return data_length;
+}
+
+/*
+ * rmidev_llseek - used to set up register address
+ *
+ * @filp: file structure for seek
+ * @off: offset
+ *   if whence == SEEK_SET,
+ *     high 16 bits: page address
+ *     low 16 bits: register address
+ *   if whence == SEEK_CUR,
+ *     offset from current position
+ *   if whence == SEEK_END,
+ *     offset from end position (0xFFFF)
+ * @whence: SEEK_SET, SEEK_CUR, or SEEK_END
+ */
+static loff_t rmidev_llseek(struct file *filp, loff_t off, int whence)
+{
+	loff_t newpos;
+	struct rmidev_data *dev_data = filp->private_data;
+
+	if (IS_ERR(dev_data)) {
+		pr_err("%s: Pointer of char device data is invalid", __func__);
+		return -EBADF;
+	}
+
+	mutex_lock(&(dev_data->file_mutex));
+
+	switch (whence) {
+	case SEEK_SET:
+		newpos = off;
+		break;
+	case SEEK_CUR:
+		newpos = filp->f_pos + off;
+		break;
+	case SEEK_END:
+		newpos = REG_ADDR_LIMIT + off;
+		break;
+	default:
+		newpos = -EINVAL;
+		goto clean_up;
+	}
+
+	if (newpos < 0 || newpos > REG_ADDR_LIMIT) {
+		dev_err(&rmidev->rmi4_data->i2c_client->dev,
+				"%s: New position 0x%04x is invalid\n",
+				__func__, (unsigned int)newpos);
+		newpos = -EINVAL;
+		goto clean_up;
+	}
+
+	filp->f_pos = newpos;
+
+clean_up:
+	mutex_unlock(&(dev_data->file_mutex));
+
+	return newpos;
+}
+
+/*
+ * rmidev_read: - use to read data from rmi device
+ *
+ * @filp: file structure for read
+ * @buf: user space buffer pointer
+ * @count: number of bytes to read
+ * @f_pos: offset (starting register address)
+ */
+static ssize_t rmidev_read(struct file *filp, char __user *buf,
+		size_t count, loff_t *f_pos)
+{
+	ssize_t retval;
+	unsigned char tmpbuf[count + 1];
+	struct rmidev_data *dev_data = filp->private_data;
+
+	if (IS_ERR(dev_data)) {
+		pr_err("%s: Pointer of char device data is invalid", __func__);
+		return -EBADF;
+	}
+
+	if (count == 0)
+		return 0;
+
+	if (count > (REG_ADDR_LIMIT - *f_pos))
+		count = REG_ADDR_LIMIT - *f_pos;
+
+	mutex_lock(&(dev_data->file_mutex));
+
+	retval = rmidev->fn_ptr->read(rmidev->rmi4_data,
+			*f_pos,
+			tmpbuf,
+			count);
+	if (retval < 0)
+		goto clean_up;
+
+	if (copy_to_user(buf, tmpbuf, count))
+		retval = -EFAULT;
+	else
+		*f_pos += retval;
+
+clean_up:
+	mutex_unlock(&(dev_data->file_mutex));
+
+	return retval;
+}
+
+/*
+ * rmidev_write: - used to write data to rmi device
+ *
+ * @filep: file structure for write
+ * @buf: user space buffer pointer
+ * @count: number of bytes to write
+ * @f_pos: offset (starting register address)
+ */
+static ssize_t rmidev_write(struct file *filp, const char __user *buf,
+		size_t count, loff_t *f_pos)
+{
+	ssize_t retval;
+	unsigned char tmpbuf[count + 1];
+	struct rmidev_data *dev_data = filp->private_data;
+
+	if (IS_ERR(dev_data)) {
+		pr_err("%s: Pointer of char device data is invalid", __func__);
+		return -EBADF;
+	}
+
+	if (count == 0)
+		return 0;
+
+	if (count > (REG_ADDR_LIMIT - *f_pos))
+		count = REG_ADDR_LIMIT - *f_pos;
+
+	if (copy_from_user(tmpbuf, buf, count))
+		return -EFAULT;
+
+	mutex_lock(&(dev_data->file_mutex));
+
+	retval = rmidev->fn_ptr->write(rmidev->rmi4_data,
+			*f_pos,
+			tmpbuf,
+			count);
+	if (retval >= 0)
+		*f_pos += retval;
+
+	mutex_unlock(&(dev_data->file_mutex));
+
+	return retval;
+}
+
+/*
+ * rmidev_open: enable access to rmi device
+ * @inp: inode struture
+ * @filp: file structure
+ */
+static int rmidev_open(struct inode *inp, struct file *filp)
+{
+	int retval = 0;
+	struct rmidev_data *dev_data =
+			container_of(inp->i_cdev, struct rmidev_data, main_dev);
+
+	if (!dev_data)
+		return -EACCES;
+
+	filp->private_data = dev_data;
+
+	mutex_lock(&(dev_data->file_mutex));
+
+	rmidev->fn_ptr->enable(rmidev->rmi4_data, false);
+	dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
+			"%s: Attention interrupt disabled\n",
+			__func__);
+
+	if (dev_data->ref_count < 1)
+		dev_data->ref_count++;
+	else
+		retval = -EACCES;
+
+	mutex_unlock(&(dev_data->file_mutex));
+
+	return retval;
+}
+
+/*
+ * rmidev_release: - release access to rmi device
+ * @inp: inode structure
+ * @filp: file structure
+ */
+static int rmidev_release(struct inode *inp, struct file *filp)
+{
+	struct rmidev_data *dev_data =
+			container_of(inp->i_cdev, struct rmidev_data, main_dev);
+
+	if (!dev_data)
+		return -EACCES;
+
+	mutex_lock(&(dev_data->file_mutex));
+
+	dev_data->ref_count--;
+	if (dev_data->ref_count < 0)
+		dev_data->ref_count = 0;
+
+	rmidev->fn_ptr->enable(rmidev->rmi4_data, true);
+	dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
+			"%s: Attention interrupt enabled\n",
+			__func__);
+
+	mutex_unlock(&(dev_data->file_mutex));
+
+	return 0;
+}
+
+static const struct file_operations rmidev_fops = {
+	.owner = THIS_MODULE,
+	.llseek = rmidev_llseek,
+	.read = rmidev_read,
+	.write = rmidev_write,
+	.open = rmidev_open,
+	.release = rmidev_release,
+};
+
+static void rmidev_device_cleanup(struct rmidev_data *dev_data)
+{
+	dev_t devno;
+
+	if (dev_data) {
+		devno = dev_data->main_dev.dev;
+
+		if (dev_data->device_class)
+			device_destroy(dev_data->device_class, devno);
+
+		cdev_del(&dev_data->main_dev);
+
+		unregister_chrdev_region(devno, 1);
+
+		dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
+				"%s: rmidev device removed\n",
+				__func__);
+	}
+
+	return;
+}
+
+static char *rmi_char_devnode(struct device *dev, mode_t *mode)
+{
+	if (!mode)
+		return NULL;
+
+	*mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
+	return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev));
+}
+
+static int rmidev_create_device_class(void)
+{
+	rmidev_device_class = class_create(THIS_MODULE, DEVICE_CLASS_NAME);
+
+	if (IS_ERR(rmidev_device_class)) {
+		pr_err("%s: Failed to create /dev/%s\n",
+				__func__, CHAR_DEVICE_NAME);
+		return -ENODEV;
+	}
+
+	rmidev_device_class->devnode = rmi_char_devnode;
+
+	return 0;
+}
+
+static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	dev_t dev_no;
+	unsigned char attr_count;
+	struct rmidev_data *dev_data;
+	struct device *device_ptr;
+
+	rmidev = kzalloc(sizeof(*rmidev), GFP_KERNEL);
+	if (!rmidev) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for rmidev\n",
+				__func__);
+		retval = -ENOMEM;
+		goto err_rmidev;
+	}
+
+	rmidev->fn_ptr =  kzalloc(sizeof(*(rmidev->fn_ptr)), GFP_KERNEL);
+	if (!rmidev) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for fn_ptr\n",
+				__func__);
+		retval = -ENOMEM;
+		goto err_fn_ptr;
+	}
+
+	rmidev->fn_ptr->read = rmi4_data->i2c_read;
+	rmidev->fn_ptr->write = rmi4_data->i2c_write;
+	rmidev->fn_ptr->enable = rmi4_data->irq_enable;
+	rmidev->rmi4_data = rmi4_data;
+
+	retval = rmidev_create_device_class();
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to create device class\n",
+				__func__);
+		goto err_device_class;
+	}
+
+	if (rmidev_major_num) {
+		dev_no = MKDEV(rmidev_major_num, DEV_NUMBER);
+		retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME);
+	} else {
+		retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME);
+		if (retval < 0) {
+			dev_err(&rmi4_data->i2c_client->dev,
+					"%s: Failed to allocate char device region\n",
+					__func__);
+			goto err_device_region;
+		}
+
+		rmidev_major_num = MAJOR(dev_no);
+		dev_dbg(&rmi4_data->i2c_client->dev,
+				"%s: Major number of rmidev = %d\n",
+				__func__, rmidev_major_num);
+	}
+
+	dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
+	if (!dev_data) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to alloc mem for dev_data\n",
+				__func__);
+		retval = -ENOMEM;
+		goto err_dev_data;
+	}
+
+	mutex_init(&dev_data->file_mutex);
+	dev_data->rmi_dev = rmidev;
+	rmidev->data = dev_data;
+
+	cdev_init(&dev_data->main_dev, &rmidev_fops);
+
+	retval = cdev_add(&dev_data->main_dev, dev_no, 1);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to add rmi char device\n",
+				__func__);
+		goto err_char_device;
+	}
+
+	dev_set_name(&rmidev->dev, "rmidev%d", MINOR(dev_no));
+	dev_data->device_class = rmidev_device_class;
+
+	device_ptr = device_create(dev_data->device_class, NULL, dev_no,
+			NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no));
+	if (IS_ERR(device_ptr)) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to create rmi char device\n",
+				__func__);
+		retval = -ENODEV;
+		goto err_char_device;
+	}
+
+	retval = gpio_export(rmi4_data->board->irq_gpio, false);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to export attention gpio\n",
+				__func__);
+	} else {
+		retval = gpio_export_link(&(rmi4_data->input_dev->dev),
+				"attn", rmi4_data->board->irq_gpio);
+		if (retval < 0) {
+			dev_err(&rmi4_data->input_dev->dev,
+					"%s Failed to create gpio symlink\n",
+					__func__);
+		} else {
+			dev_dbg(&rmi4_data->input_dev->dev,
+					"%s: Exported attention gpio %d\n",
+					__func__, rmi4_data->board->irq_gpio);
+		}
+	}
+
+	rmidev->sysfs_dir = kobject_create_and_add("rmidev",
+			&rmi4_data->input_dev->dev.kobj);
+	if (!rmidev->sysfs_dir) {
+		dev_err(&rmi4_data->i2c_client->dev,
+				"%s: Failed to create sysfs directory\n",
+				__func__);
+		goto err_sysfs_dir;
+	}
+
+	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+		retval = sysfs_create_file(rmidev->sysfs_dir,
+				&attrs[attr_count].attr);
+		if (retval < 0) {
+			dev_err(&rmi4_data->input_dev->dev,
+					"%s: Failed to create sysfs attributes\n",
+					__func__);
+			retval = -ENODEV;
+			goto err_sysfs_attrs;
+		}
+	}
+
+	return 0;
+
+err_sysfs_attrs:
+	for (attr_count--; attr_count >= 0; attr_count--) {
+		sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+				&attrs[attr_count].attr);
+	}
+
+	kobject_put(rmidev->sysfs_dir);
+
+err_sysfs_dir:
+err_char_device:
+	rmidev_device_cleanup(dev_data);
+	kfree(dev_data);
+
+err_dev_data:
+	unregister_chrdev_region(dev_no, 1);
+
+err_device_region:
+	class_destroy(rmidev_device_class);
+
+err_device_class:
+	kfree(rmidev->fn_ptr);
+
+err_fn_ptr:
+	kfree(rmidev);
+
+err_rmidev:
+	return retval;
+}
+
+static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data)
+{
+	unsigned char attr_count;
+	struct rmidev_data *dev_data;
+
+	if (!rmidev)
+		return;
+
+	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++)
+		sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr);
+
+	kobject_put(rmidev->sysfs_dir);
+
+	dev_data = rmidev->data;
+	if (dev_data) {
+		rmidev_device_cleanup(dev_data);
+		kfree(dev_data);
+	}
+
+	unregister_chrdev_region(rmidev->dev_no, 1);
+
+	class_destroy(rmidev_device_class);
+
+	kfree(rmidev->fn_ptr);
+	kfree(rmidev);
+
+	complete(&remove_complete);
+
+	return;
+}
+
+static int __init rmidev_module_init(void)
+{
+	synaptics_rmi4_new_function(RMI_DEV, true,
+			rmidev_init_device,
+			rmidev_remove_device,
+			NULL);
+	return 0;
+}
+
+static void __exit rmidev_module_exit(void)
+{
+	init_completion(&remove_complete);
+	synaptics_rmi4_new_function(RMI_DEV, false,
+			rmidev_init_device,
+			rmidev_remove_device,
+			NULL);
+	wait_for_completion(&remove_complete);
+	return;
+}
+
+module_init(rmidev_module_init);
+module_exit(rmidev_module_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 RMI_Dev Module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION);
diff --git a/kernel/include/linux/input/synaptics_dsx.h b/kernel/include/linux/input/synaptics_dsx.h
new file mode 100644
index 0000000..b779e42
--- /dev/null
+++ b/kernel/include/linux/input/synaptics_dsx.h
@@ -0,0 +1,59 @@
+/*
+ * Synaptics RMI4 touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _SYNAPTICS_DSX_H_
+#define _SYNAPTICS_DSX_H_
+
+/*
+ * struct synaptics_rmi4_capacitance_button_map - 0d button map
+ * @nbuttons: number of buttons
+ * @map: button map
+ */
+struct synaptics_rmi4_capacitance_button_map {
+	unsigned char nbuttons;
+	unsigned char *map;
+};
+
+/*
+ * struct synaptics_rmi4_platform_data - rmi4 platform data
+ * @x_flip: x flip flag
+ * @y_flip: y flip flag
+ * @regulator_en: regulator enable flag
+ * @irq_gpio: attention interrupt gpio
+ * @irq_flags: flags used by the irq
+ * @reset_gpio: reset gpio
+ * @panel_x: panel maximum values on the x
+ * @panel_y: panel maximum values on the y
+ * @gpio_config: pointer to gpio configuration function
+ * @capacitance_button_map: pointer to 0d button map
+ */
+struct synaptics_rmi4_platform_data {
+	bool x_flip;
+	bool y_flip;
+	bool regulator_en;
+	unsigned irq_gpio;
+	unsigned long irq_flags;
+	unsigned reset_gpio;
+	unsigned panel_x;
+	unsigned panel_y;
+	int (*gpio_config)(unsigned gpio, bool configure);
+	struct synaptics_rmi4_capacitance_button_map *capacitance_button_map;
+};
+
+#endif
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index dc6281e..a1f2955 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1,7 +1,7 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2010  Nokia Corporation
-   Copyright (c) 2011-2012 The Linux Foundation.  All rights reserved.
+   Copyright (c) 2011-2013 The Linux Foundation.  All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2 as
@@ -2238,10 +2238,11 @@
 
 		mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
 
-		hdev->disco_state = SCAN_IDLE;
-
-		if (hdev)
+		if (hdev) {
+			BT_DBG("Setting state to SCAN_IDLE\n");
+			hdev->disco_state = SCAN_IDLE;
 			goto done;
+		}
 		else
 			return;
 	}
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index f6d4cfc..2b486b1 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -1201,7 +1201,7 @@
 static int ipx_proto(const struct sk_buff *skb,
 		     struct xt_action_param *par)
 {
-	int thoff, tproto;
+	int thoff = 0, tproto;
 
 	switch (par->family) {
 	case NFPROTO_IPV6:
@@ -1773,6 +1773,8 @@
 	}
 
 	sk = skb->sk;
+	if (sk && sk->sk_state == TCP_TIME_WAIT)
+		sk = NULL;
 	if (sk == NULL) {
 		/*
 		 * A missing sk->sk_socket happens when packets are in-flight
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0410707..5c2e805 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8082,6 +8082,50 @@
 }
 EXPORT_SYMBOL(cfg80211_report_obss_beacon);
 
+void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
+				enum nl80211_tdls_operation oper,
+				u16 reason_code, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+	int err;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+	    nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) ||
+	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) ||
+	    (reason_code > 0 &&
+	     nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code)))
+		goto nla_put_failure;
+
+	err = genlmsg_end(msg, hdr);
+	if (err < 0) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+				nl80211_mlme_mcgrp.id, gfp);
+	return;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_tdls_oper_request);
+
 static int nl80211_netlink_notify(struct notifier_block * nb,
 				  unsigned long state,
 				  void *_notify)
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index 0000a1a..46bce9e 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/err.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
@@ -25,6 +26,60 @@
 	struct msm_hdmi_audio_codec_ops hdmi_ops;
 };
 
+static int msm_hdmi_edid_ctl_info(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *uinfo)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct msm_hdmi_audio_codec_rx_data *codec_data;
+	struct msm_hdmi_audio_edid_blk edid_blk;
+	int rc;
+
+	codec_data = snd_soc_codec_get_drvdata(codec);
+	rc = codec_data->hdmi_ops.get_audio_edid_blk(codec_data->hdmi_core_pdev,
+						     &edid_blk);
+	if (!IS_ERR_VALUE(rc)) {
+		uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+		uinfo->count = edid_blk.audio_data_blk_size +
+			       edid_blk.spk_alloc_data_blk_size;
+	}
+
+	return 0;
+}
+
+static int msm_hdmi_edid_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol) {
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct msm_hdmi_audio_codec_rx_data *codec_data;
+	struct msm_hdmi_audio_edid_blk edid_blk;
+	int rc;
+
+	codec_data = snd_soc_codec_get_drvdata(codec);
+	rc = codec_data->hdmi_ops.get_audio_edid_blk(codec_data->hdmi_core_pdev,
+						     &edid_blk);
+
+	if (!IS_ERR_VALUE(rc)) {
+		memcpy(ucontrol->value.bytes.data, edid_blk.audio_data_blk,
+		       edid_blk.audio_data_blk_size);
+		memcpy((ucontrol->value.bytes.data +
+		       edid_blk.audio_data_blk_size),
+		       edid_blk.spk_alloc_data_blk,
+		       edid_blk.spk_alloc_data_blk_size);
+	}
+
+	return rc;
+}
+
+static const struct snd_kcontrol_new msm_hdmi_codec_rx_controls[] = {
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ |
+			  SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+		.iface	= SNDRV_CTL_ELEM_IFACE_PCM,
+		.name	= "HDMI EDID",
+		.info	= msm_hdmi_edid_ctl_info,
+		.get	= msm_hdmi_edid_get,
+	},
+};
+
 static int msm_hdmi_audio_codec_rx_dai_hw_params(
 		struct snd_pcm_substream *substream,
 		struct snd_pcm_hw_params *params,
@@ -142,6 +197,8 @@
 static struct snd_soc_codec_driver msm_hdmi_audio_codec_rx_soc_driver = {
 	.probe = msm_hdmi_audio_codec_rx_probe,
 	.remove =  msm_hdmi_audio_codec_rx_remove,
+	.controls = msm_hdmi_codec_rx_controls,
+	.num_controls = ARRAY_SIZE(msm_hdmi_codec_rx_controls),
 };
 
 static int __devinit msm_hdmi_audio_codec_rx_plat_probe(
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index b0cf27b..0b26a56 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index eded9da..3b14c44 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -972,7 +972,7 @@
 		/* Set sample rate dependent paramater*/
 		if (tabla->comp_enabled[w->shift] != 0) {
 			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_FS_CFG +
-			w->shift * 8, 0x03,	rate);
+			w->shift * 8, 0x07,	rate);
 			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
 			w->shift * 8, 0x0F,
 			comp_samp_params[rate].peak_det_timeout);
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 9196c8e..65ab084 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -499,8 +499,8 @@
 					kcontrol->private_value)->shift;
 
 	ucontrol->value.integer.value[0] =
-		snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
-		(1 << band_idx);
+		(snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
+		(1 << band_idx)) != 0;
 
 	pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
 		iir_idx, band_idx,
@@ -524,22 +524,52 @@
 		(1 << band_idx), (value << band_idx));
 
 	pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
-		iir_idx, band_idx, value);
+		iir_idx, band_idx,
+		((snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
+		(1 << band_idx)) != 0));
 	return 0;
 }
 static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
 				int iir_idx, int band_idx,
 				int coeff_idx)
 {
+	uint32_t value = 0;
+
 	/* Address does not automatically update if reading */
 	snd_soc_write(codec,
 		(TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
-		(band_idx * BAND_MAX + coeff_idx) & 0x1F);
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t)) & 0x7F);
+
+	value |= snd_soc_read(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx));
+
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 1) & 0x7F);
+
+	value |= (snd_soc_read(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 8);
+
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 2) & 0x7F);
+
+	value |= (snd_soc_read(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 16);
+
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		((band_idx * BAND_MAX + coeff_idx)
+		* sizeof(uint32_t) + 3) & 0x7F);
 
 	/* Mask bits top 2 bits since they are reserved */
-	return ((snd_soc_read(codec,
-		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24)) &
-		0x3FFFFFFF;
+	value |= ((snd_soc_read(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) & 0x3F) << 24);
+
+	return value;
 }
 
 static int taiko_get_iir_band_audio_mixer(
@@ -583,19 +613,24 @@
 
 static void set_iir_band_coeff(struct snd_soc_codec *codec,
 				int iir_idx, int band_idx,
-				int coeff_idx, uint32_t value)
+				uint32_t value)
 {
-	/* Mask top 3 bits, 6-8 are reserved */
-	/* Update address manually each time */
 	snd_soc_write(codec,
-		(TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
-		(band_idx * BAND_MAX + coeff_idx) & 0x1F);
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+		(value & 0xFF));
+
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+		(value >> 8) & 0xFF);
+
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+		(value >> 16) & 0xFF);
 
 	/* Mask top 2 bits, 7-8 are reserved */
 	snd_soc_write(codec,
 		(TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
 		(value >> 24) & 0x3F);
-
 }
 
 static int taiko_put_iir_band_audio_mixer(
@@ -608,15 +643,21 @@
 	int band_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->shift;
 
-	set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+	/* Mask top bit it is reserved */
+	/* Updates addr automatically for each B2 write */
+	snd_soc_write(codec,
+		(TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 				ucontrol->value.integer.value[0]);
-	set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 				ucontrol->value.integer.value[1]);
-	set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 				ucontrol->value.integer.value[2]);
-	set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 				ucontrol->value.integer.value[3]);
-	set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+	set_iir_band_coeff(codec, iir_idx, band_idx,
 				ucontrol->value.integer.value[4]);
 
 	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
@@ -883,6 +924,9 @@
 	SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 12, 1,
 		line_gain),
 
+	SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 7, 1,
+		line_gain),
+
 	SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
 		-84, 40, digital_gain),
 	SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
@@ -1717,14 +1761,14 @@
 	break;
 	case 2:
 		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&taiko_p->dai[AIF1_PB].wcd9xxx_ch_list))
+			&taiko_p->dai[AIF2_PB].wcd9xxx_ch_list))
 			goto pr_err;
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list);
 	break;
 	case 3:
 		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&taiko_p->dai[AIF1_PB].wcd9xxx_ch_list))
+			&taiko_p->dai[AIF3_PB].wcd9xxx_ch_list))
 			goto pr_err;
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list);
@@ -2687,13 +2731,15 @@
 	{"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
 	{"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
 
+	/* Change Pump */
+	{"CP", NULL, "CLASS_H_CLK"},
+
 	/* Earpiece (RX MIX1) */
 	{"EAR", NULL, "EAR PA"},
 	{"EAR PA", NULL, "EAR_PA_MIXER"},
 	{"EAR_PA_MIXER", NULL, "DAC1"},
-	{"DAC1", NULL, "CP"},
-	{"CP", NULL, "CLASS_H_EAR"},
-	{"CLASS_H_EAR", NULL, "CLASS_H_CLK"},
+	{"DAC1", NULL, "CLASS_H_EAR"},
+	{"CLASS_H_EAR", NULL, "CP"},
 
 	{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
 	{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
@@ -2709,13 +2755,11 @@
 	{"HPHR", NULL, "HPHR_PA_MIXER"},
 	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
 
-	{"HPHL DAC", NULL, "CP"},
-	{"CP", NULL, "CLASS_H_HPH_L"},
-	{"CLASS_H_HPH_L", NULL, "CLASS_H_CLK"},
+	{"HPHL DAC", NULL, "CLASS_H_HPH_L"},
+	{"CLASS_H_HPH_L", NULL, "CP"},
 
-	{"HPHR DAC", NULL, "CP"},
-	{"CP", NULL, "CLASS_H_HPH_R"},
-	{"CLASS_H_HPH_R", NULL, "CLASS_H_CLK"},
+	{"HPHR DAC", NULL, "CLASS_H_HPH_R"},
+	{"CLASS_H_HPH_R", NULL, "CP"},
 
 	{"ANC", NULL, "ANC1 MUX"},
 	{"ANC", NULL, "ANC2 MUX"},
@@ -3313,8 +3357,8 @@
 		}
 		list_for_each_entry(ch, &taiko_p->dai[dai->id].wcd9xxx_ch_list,
 				    list) {
-			pr_debug("%s: rx_slot[%d] %d, ch->ch_num %d\n",
-				 __func__, i, rx_slot[i], ch->ch_num);
+			pr_debug("%s: slot_num %u ch->ch_num %d\n",
+				 __func__, i, ch->ch_num);
 			rx_slot[i++] = ch->ch_num;
 		}
 		pr_debug("%s: rx_num %d\n", __func__, i);
@@ -3330,8 +3374,8 @@
 		}
 		list_for_each_entry(ch, &taiko_p->dai[dai->id].wcd9xxx_ch_list,
 				    list) {
-			pr_debug("%s: tx_slot[%d] %d, ch->ch_num %d\n",
-				 __func__, i, tx_slot[i], ch->ch_num);
+			pr_debug("%s: slot_num %u ch->ch_num %d\n",
+				 __func__, i,  ch->ch_num);
 			tx_slot[i++] = ch->ch_num;
 		}
 		pr_debug("%s: tx_num %d\n", __func__, i);
@@ -4670,7 +4714,7 @@
 static const struct taiko_reg_mask_val taiko_reg_defaults[] = {
 
 	/* set MCLk to 9.6 */
-	TAIKO_REG_VAL(TAIKO_A_CHIP_CTL, 0x0A),
+	TAIKO_REG_VAL(TAIKO_A_CHIP_CTL, 0x02),
 	TAIKO_REG_VAL(TAIKO_A_CDC_CLK_POWER_CTL, 0x03),
 
 	/* EAR PA deafults  */
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 8acc334..c1a1aa1 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -46,6 +46,7 @@
 				  SND_JACK_BTN_6 | SND_JACK_BTN_7)
 
 #define NUM_DCE_PLUG_DETECT 3
+#define NUM_DCE_PLUG_INS_DETECT 4
 #define NUM_ATTEMPTS_INSERT_DETECT 25
 #define NUM_ATTEMPTS_TO_REPORT 5
 
@@ -81,6 +82,29 @@
 
 #define VDDIO_MICBIAS_MV 1800
 
+#define WCD9XXX_HPHL_STATUS_READY_WAIT_US 1000
+#define WCD9XXX_MEAS_DELTA_MAX_MV 50
+#define WCD9XXX_GM_SWAP_THRES_MIN_MV 150
+#define WCD9XXX_GM_SWAP_THRES_MAX_MV 500
+
+#define WCD9XXX_USLEEP_RANGE_MARGIN_US 1000
+
+static bool detect_use_vddio_switch;
+
+struct wcd9xxx_mbhc_detect {
+	u16 dce;
+	u16 sta;
+	u16 hphl_status;
+	bool swap_gnd;
+	bool vddio;
+	bool hwvalue;
+	/* internal purpose from here */
+	bool _above_no_mic;
+	bool _below_v_hs_max;
+	s16 _vdces;
+	enum wcd9xxx_mbhc_plug_type _type;
+};
+
 enum meas_type {
 	STA = 0,
 	DCE,
@@ -554,7 +578,7 @@
 		set_bit(WCD9XXX_HPHR_DAC_OFF_ACK, &mbhc->hph_pa_dac_state);
 
 	snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30, 0x00);
-	snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xC0, 0x00);
+	snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_DAC_CTL, 0x80, 0x00);
 	snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xC0, 0x00);
 	usleep_range(wg_time * 1000, wg_time * 1000);
 }
@@ -610,7 +634,7 @@
 	} else {
 		if (mbhc->mbhc_cfg->detect_extn_cable) {
 			/* Report removal of current jack type */
-			if (mbhc->hph_status != jack_type) {
+			if (mbhc->hph_status && mbhc->hph_status != jack_type) {
 				pr_debug("%s: Reporting removal (%x)\n",
 					 __func__, mbhc->hph_status);
 				wcd9xxx_jack_report(&mbhc->headset_jack,
@@ -685,26 +709,6 @@
 	return v_hs_max;
 }
 
-static bool wcd9xxx_is_inval_ins_range(struct wcd9xxx_mbhc *mbhc,
-				     s32 mic_volt, bool highhph, bool *highv)
-{
-	s16 v_hs_max;
-	bool invalid = false;
-
-	/* Perform this check only when the high voltage headphone
-	 * needs to be considered as invalid
-	 */
-	v_hs_max = wcd9xxx_get_current_v_hs_max(mbhc);
-	*highv = mic_volt > v_hs_max;
-	if (!highhph && *highv)
-		invalid = true;
-	else if (mic_volt < mbhc->mbhc_data.v_inval_ins_high &&
-		 (mic_volt > mbhc->mbhc_data.v_inval_ins_low))
-		invalid = true;
-
-	return invalid;
-}
-
 static short wcd9xxx_read_sta_result(struct snd_soc_codec *codec)
 {
 	u8 bias_msb, bias_lsb;
@@ -923,13 +927,6 @@
 		usleep_range(5000, 5000);
 }
 
-static bool wcd9xxx_is_inval_ins_delta(struct snd_soc_codec *codec,
-				       int mic_volt, int mic_volt_prev,
-				       int threshold)
-{
-	return abs(mic_volt - mic_volt_prev) > threshold;
-}
-
 static void wcd9xxx_onoff_vddio_switch(struct wcd9xxx_mbhc *mbhc, bool on)
 {
 	if (on) {
@@ -947,23 +944,117 @@
 		usleep_range(10000, 10000);
 }
 
-/* called under codec_resource_lock acquisition and mbhc override = 1 */
+static int wcd9xxx_hphl_status(struct wcd9xxx_mbhc *mbhc)
+{
+	u16 hph, status;
+	struct snd_soc_codec *codec = mbhc->codec;
+
+	WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
+	hph = snd_soc_read(codec, WCD9XXX_A_MBHC_HPH);
+	snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x12, 0x02);
+	usleep_range(WCD9XXX_HPHL_STATUS_READY_WAIT_US,
+		     WCD9XXX_HPHL_STATUS_READY_WAIT_US +
+		     WCD9XXX_USLEEP_RANGE_MARGIN_US);
+	status = snd_soc_read(codec, WCD9XXX_A_RX_HPH_L_STATUS);
+	snd_soc_write(codec, WCD9XXX_A_MBHC_HPH, hph);
+	return status;
+}
+
+/*
+ * wcd9xxx_find_plug_type : Find out and return the best plug type with given
+ *			    list of wcd9xxx_mbhc_detect structure.
+ */
+static enum wcd9xxx_mbhc_plug_type
+wcd9xxx_find_plug_type(struct wcd9xxx_mbhc *mbhc,
+		       struct wcd9xxx_mbhc_detect *dt, const int size)
+{
+	int i;
+	int ch;
+	enum wcd9xxx_mbhc_plug_type type;
+	int vdce;
+	struct wcd9xxx_mbhc_detect *d, *dprev, *dgnd = NULL;
+	int maxv = 0, minv = 0;
+	const struct wcd9xxx_mbhc_plug_type_cfg *plug_type =
+	    WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
+	const s16 hs_max = plug_type->v_hs_max;
+	const s16 no_mic = plug_type->v_no_mic;
+
+	for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
+		vdce = wcd9xxx_codec_sta_dce_v(mbhc, true, d->dce);
+		if (d->vddio)
+			d->_vdces = scale_v_micb_vddio(mbhc, vdce, false);
+		else
+			d->_vdces = vdce;
+
+		if (d->_vdces >= no_mic && d->_vdces < hs_max)
+			d->_type = PLUG_TYPE_HEADSET;
+		else if (d->_vdces < no_mic)
+			d->_type = PLUG_TYPE_HEADPHONE;
+		else
+			d->_type = PLUG_TYPE_HIGH_HPH;
+
+		ch += d->hphl_status & 0x01;
+		if (!d->swap_gnd && !d->hwvalue) {
+			if (maxv < d->_vdces)
+				maxv = d->_vdces;
+			if (!minv || minv > d->_vdces)
+				minv = d->_vdces;
+		}
+
+		pr_debug("%s: DCE #%d, %04x, V %04d(%04d), GND %d, VDDIO %d, HPHL %d TYPE %d\n",
+			 __func__, i, d->dce, vdce, d->_vdces,
+			 d->swap_gnd, d->vddio, d->hphl_status & 0x01,
+			 d->_type);
+	}
+	if (ch != size && ch > 0) {
+		pr_debug("%s: Invalid, inconsistent HPHL\n", __func__);
+		type = PLUG_TYPE_INVALID;
+		goto exit;
+	}
+
+	for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
+		if ((i > 0) && (d->_type != dprev->_type)) {
+			pr_debug("%s: Invalid, inconsistent types\n", __func__);
+			type = PLUG_TYPE_INVALID;
+			goto exit;
+		}
+
+		if (!d->swap_gnd && !d->hwvalue &&
+		    (abs(minv - d->_vdces) > WCD9XXX_MEAS_DELTA_MAX_MV ||
+		     abs(maxv - d->_vdces) > WCD9XXX_MEAS_DELTA_MAX_MV)) {
+			pr_debug("%s: Invalid, delta %dmv, %dmv and %dmv\n",
+				 __func__, d->_vdces, minv, maxv);
+			type = PLUG_TYPE_INVALID;
+			goto exit;
+		} else if (d->swap_gnd) {
+			dgnd = d;
+		}
+		dprev = d;
+	}
+
+	WARN_ON(i != size);
+	type = dt->_type;
+	if (type == PLUG_TYPE_HEADSET && dgnd) {
+		if ((dgnd->_vdces + WCD9XXX_GM_SWAP_THRES_MIN_MV <
+		     minv) &&
+		    (dgnd->_vdces + WCD9XXX_GM_SWAP_THRES_MAX_MV >
+		     maxv))
+			type = PLUG_TYPE_GND_MIC_SWAP;
+	}
+
+exit:
+	pr_debug("%s: Plug type %d detected\n", __func__, type);
+	return type;
+}
+
 static enum wcd9xxx_mbhc_plug_type
 wcd9xxx_codec_get_plug_type(struct wcd9xxx_mbhc *mbhc, bool highhph)
 {
 	int i;
-	bool gndswitch, vddioswitch;
-	int scaled;
 	struct wcd9xxx_mbhc_plug_type_cfg *plug_type_ptr;
+	struct wcd9xxx_mbhc_detect rt[NUM_DCE_PLUG_INS_DETECT];
+	enum wcd9xxx_mbhc_plug_type type = PLUG_TYPE_INVALID;
 	struct snd_soc_codec *codec = mbhc->codec;
-	const bool vddio = (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV);
-	int num_det = (NUM_DCE_PLUG_DETECT + vddio);
-	enum wcd9xxx_mbhc_plug_type plug_type[num_det];
-	s16 mb_v[num_det];
-	s32 mic_mv[num_det];
-	bool inval;
-	bool highdelta;
-	bool ahighv = false, highv;
 
 	pr_debug("%s: enter\n", __func__);
 	WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
@@ -972,106 +1063,39 @@
 	WARN_ON(!(snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_CTL) & 0x04));
 
 	/* GND and MIC swap detection requires at least 2 rounds of DCE */
-	BUG_ON(num_det < 2);
+	BUG_ON(NUM_DCE_PLUG_INS_DETECT < 2);
 
 	plug_type_ptr =
-		WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
+	    WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
 
-	plug_type[0] = PLUG_TYPE_INVALID;
-
-	/* performs DCEs for N times
-	 * 1st: check if voltage is in invalid range
-	 * 2nd - N-2nd: check voltage range and delta
-	 * N-1st: check voltage range, delta with HPHR GND switch
-	 * Nth: check voltage range with VDDIO switch if micbias V != vddio V*/
-	for (i = 0; i < num_det; i++) {
-		gndswitch = (i == (num_det - 1 - vddio));
-		vddioswitch = (vddio && ((i == num_det - 1) ||
-					(i == num_det - 2)));
-		if (i == 0) {
-			mb_v[i] = wcd9xxx_mbhc_setup_hs_polling(mbhc);
-			mic_mv[i] = wcd9xxx_codec_sta_dce_v(mbhc, 1 , mb_v[i]);
-			inval = wcd9xxx_is_inval_ins_range(mbhc, mic_mv[i],
-					highhph, &highv);
-			ahighv |= highv;
-			scaled = mic_mv[i];
-		} else {
-			if (vddioswitch)
-				wcd9xxx_onoff_vddio_switch(mbhc, true);
-			if (gndswitch)
-				wcd9xxx_codec_hphr_gnd_switch(codec, true);
-			mb_v[i] = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
-			mic_mv[i] = wcd9xxx_codec_sta_dce_v(mbhc, 1 , mb_v[i]);
-			if (vddioswitch)
-				scaled = scale_v_micb_vddio(mbhc, mic_mv[i],
-							    false);
-			else
-				scaled = mic_mv[i];
-			/* !gndswitch & vddioswitch means the previous DCE
-			 * was done with gndswitch, don't compare with DCE
-			 * with gndswitch */
-			highdelta = wcd9xxx_is_inval_ins_delta(codec, scaled,
-					mic_mv[i - !gndswitch - vddioswitch],
-					FAKE_INS_DELTA_SCALED_MV);
-			inval = (wcd9xxx_is_inval_ins_range(mbhc, mic_mv[i],
-						highhph, &highv) ||
-					highdelta);
-			ahighv |= highv;
-			if (gndswitch)
-				wcd9xxx_codec_hphr_gnd_switch(codec, false);
-			if (vddioswitch)
-				wcd9xxx_onoff_vddio_switch(mbhc, false);
-			/* claim UNSUPPORTED plug insertion when
-			 * good headset is detected but HPHR GND switch makes
-			 * delta difference */
-			if (i == (num_det - 2) && highdelta && !ahighv)
-				plug_type[0] = PLUG_TYPE_GND_MIC_SWAP;
-			else if (i == (num_det - 1) && inval)
-				plug_type[0] = PLUG_TYPE_INVALID;
-		}
-		pr_debug("%s: DCE #%d, %04x, V %d, scaled V %d, GND %d, VDDIO %d, inval %d\n",
-			 __func__, i + 1, mb_v[i] & 0xffff, mic_mv[i], scaled,
-			 gndswitch, vddioswitch, inval);
-		/* don't need to run further DCEs */
-		if (ahighv && inval)
-			break;
-		mic_mv[i] = scaled;
+	rt[0].hphl_status = wcd9xxx_hphl_status(mbhc);
+	rt[0].dce = wcd9xxx_mbhc_setup_hs_polling(mbhc);
+	rt[0].swap_gnd = false;
+	rt[0].vddio = false;
+	rt[0].hwvalue = true;
+	for (i = 1; i < NUM_DCE_PLUG_INS_DETECT; i++) {
+		rt[i].swap_gnd = (i == NUM_DCE_PLUG_INS_DETECT - 2);
+		if (detect_use_vddio_switch)
+			rt[i].vddio = (i == NUM_DCE_PLUG_INS_DETECT - 1);
+		else
+			rt[i].vddio = false;
+		rt[i].hphl_status = wcd9xxx_hphl_status(mbhc);
+		rt[i].hwvalue = false;
+		if (rt[i].swap_gnd)
+			wcd9xxx_codec_hphr_gnd_switch(codec, true);
+		if (rt[i].vddio)
+			wcd9xxx_onoff_vddio_switch(mbhc, true);
+		rt[i].dce = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
+		if (rt[i].vddio)
+			wcd9xxx_onoff_vddio_switch(mbhc, false);
+		if (rt[i].swap_gnd)
+			wcd9xxx_codec_hphr_gnd_switch(codec, false);
 	}
 
-	for (i = 0; (plug_type[0] != PLUG_TYPE_GND_MIC_SWAP && !inval) &&
-		    (i < num_det); i++) {
-		/*
-		 * If we are here, means none of the all
-		 * measurements are fake, continue plug type detection.
-		 * If all three measurements do not produce same
-		 * plug type, restart insertion detection
-		 */
-		if (mic_mv[i] < plug_type_ptr->v_no_mic) {
-			plug_type[i] = PLUG_TYPE_HEADPHONE;
-			pr_debug("%s: Detect attempt %d, detected Headphone\n",
-				 __func__, i);
-		} else if (highhph && (mic_mv[i] > plug_type_ptr->v_hs_max)) {
-			plug_type[i] = PLUG_TYPE_HIGH_HPH;
-			pr_debug("%s: Detect attempt %d, detected High Headphone\n",
-				 __func__, i);
-		} else {
-			plug_type[i] = PLUG_TYPE_HEADSET;
-			pr_debug("%s: Detect attempt %d, detected Headset\n",
-					__func__, i);
-		}
+	type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt));
 
-		if (i > 0 && (plug_type[i - 1] != plug_type[i])) {
-			pr_err("%s: Detect attempt %d and %d are not same",
-			       __func__, i - 1, i);
-			plug_type[0] = PLUG_TYPE_INVALID;
-			inval = true;
-			break;
-		}
-	}
-
-	pr_debug("%s: Detected plug type %d\n", __func__, plug_type[0]);
 	pr_debug("%s: leave\n", __func__);
-	return plug_type[0];
+	return type;
 }
 
 static bool wcd9xxx_swch_level_remove(struct wcd9xxx_mbhc *mbhc)
@@ -1584,7 +1608,7 @@
 	vddio = (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
 		 mbhc->mbhc_micbias_switched);
 	if (vddio)
-		wcd9xxx_onoff_vddio_switch(mbhc, true);
+		__wcd9xxx_switch_micbias(mbhc, 0, false, true);
 
 	if (mbhc->mbhc_cfg->detect_extn_cable &&
 	    !wcd9xxx_swch_level_remove(mbhc))
@@ -1597,8 +1621,8 @@
 	 * turn on the vddio switch back, if headset is removed then vddio
 	 * switch is off by time now and shouldn't be turn on again from here
 	 */
-	if (vddio && mbhc->current_plug == PLUG_TYPE_HEADSET)
-		wcd9xxx_onoff_vddio_switch(mbhc, true);
+	if (vddio && (mbhc->current_plug == PLUG_TYPE_HEADSET))
+		__wcd9xxx_switch_micbias(mbhc, 1, true, true);
 	WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
 
 	return IRQ_HANDLED;
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 20b9d2d..35a9646 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -107,7 +107,7 @@
 
 config SND_SOC_MSM_QDSP6V2_INTF
 	bool "SoC Q6 audio driver for MSM8974"
-	depends on MSM_QDSP6_APR
+	depends on MSM_QDSP6_APRV2
 	help
 	 To add support for SoC audio on MSM8974.
 	 This will enable all the platform specific
@@ -207,6 +207,21 @@
 	help
 	 To add support for SoC audio on MDM9615 boards
 
+config SND_SOC_MSM8X10
+	tristate "SoC Machine driver for MSM8X10 boards"
+	depends on ARCH_MSM8610
+	select SND_SOC_QDSP6V2
+	select SND_SOC_MSM_STUB
+	select SND_SOC_MSM_HOSTLESS_PCM
+	select SND_SOC_MSM8X10_WCD
+	select SND_DYNAMIC_MINORS
+	help
+	 To add support for SoC audio on MSM8X10.
+	 This will enable sound soc drivers which
+	 interfaces with DSP, also it will enable
+	 the machine drivers and the corresponding
+	 DAI-links.
+
 config SND_SOC_MSM8660_APQ
         tristate "Soc Machine driver for APQ8060 WM8903 codec"
         depends on ARCH_MSM8X60
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 452e36a..60ffd89 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -91,3 +91,8 @@
 #for MSM 8226 sound card driver
 snd-soc-msm8226-objs := msm8226.o
 obj-$(CONFIG_SND_SOC_MSM8226) += snd-soc-msm8226.o
+
+# for MSM 8x10 sound card driver
+obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_INTF) += qdsp6v2/
+snd-soc-msm8x10-objs := msm8x10.o
+obj-$(CONFIG_SND_SOC_MSM8X10) += snd-soc-msm8x10.o
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 1c47e6e..b7f8714 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -63,6 +63,8 @@
 
 /* It takes about 13ms for Class-D PAs to ramp-up */
 #define EXT_CLASS_D_EN_DELAY 13000
+#define EXT_CLASS_D_DIS_DELAY 3000
+#define EXT_CLASS_D_DELAY_DELTA 2000
 
 #define NUM_OF_AUXPCM_GPIOS 4
 
@@ -117,6 +119,16 @@
 
 void *lpaif_pri_muxsel_virt_addr;
 
+struct msm8974_liquid_dock_dev {
+	int dock_plug_gpio;
+	int dock_plug_irq;
+	int dock_plug_det;
+	struct snd_soc_dapm_context *dapm;
+	struct work_struct irq_work;
+};
+
+static struct msm8974_liquid_dock_dev *msm8974_liquid_dock_dev;
+
 /* Shared channel numbers for Slimbus ports that connect APQ to MDM. */
 enum {
 	SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
@@ -144,6 +156,7 @@
 static int clk_users;
 static atomic_t auxpcm_rsc_ref;
 
+
 static int msm8974_liquid_ext_spk_power_amp_init(void)
 {
 	int ret = 0;
@@ -178,23 +191,130 @@
 
 static void msm8974_liquid_ext_spk_power_amp_enable(u32 on)
 {
-	if (on)
+	if (on) {
 		regulator_enable(ext_spk_amp_regulator);
-	else
+		gpio_direction_output(ext_spk_amp_gpio, on);
+		/*time takes enable the external power amplifier*/
+		usleep_range(EXT_CLASS_D_EN_DELAY,
+			     EXT_CLASS_D_EN_DELAY + EXT_CLASS_D_DELAY_DELTA);
+	} else {
+		gpio_direction_output(ext_spk_amp_gpio, on);
 		regulator_disable(ext_spk_amp_regulator);
+		/*time takes disable the external power amplifier*/
+		usleep_range(EXT_CLASS_D_DIS_DELAY,
+			     EXT_CLASS_D_DIS_DELAY + EXT_CLASS_D_DELAY_DELTA);
+	}
 
-	gpio_direction_output(ext_spk_amp_gpio, on);
-	usleep_range(EXT_CLASS_D_EN_DELAY, EXT_CLASS_D_EN_DELAY);
 	pr_debug("%s: %s external speaker PAs.\n", __func__,
 			on ? "Enable" : "Disable");
 }
 
+static void msm8974_liquid_docking_irq_work(struct work_struct *work)
+{
+	struct msm8974_liquid_dock_dev *dock_dev =
+		container_of(work,
+					 struct msm8974_liquid_dock_dev,
+					 irq_work);
+
+	struct snd_soc_dapm_context *dapm = dock_dev->dapm;
+
+
+	mutex_lock(&dapm->codec->mutex);
+	dock_dev->dock_plug_det =
+		gpio_get_value(dock_dev->dock_plug_gpio);
+
+
+	if (0 == dock_dev->dock_plug_det) {
+		if ((msm8974_ext_spk_pamp & LO_1_SPK_AMP) &&
+			(msm8974_ext_spk_pamp & LO_3_SPK_AMP) &&
+			(msm8974_ext_spk_pamp & LO_2_SPK_AMP) &&
+			(msm8974_ext_spk_pamp & LO_4_SPK_AMP))
+			msm8974_liquid_ext_spk_power_amp_enable(1);
+	} else {
+		if ((msm8974_ext_spk_pamp & LO_1_SPK_AMP) &&
+			(msm8974_ext_spk_pamp & LO_3_SPK_AMP) &&
+			(msm8974_ext_spk_pamp & LO_2_SPK_AMP) &&
+			(msm8974_ext_spk_pamp & LO_4_SPK_AMP))
+			msm8974_liquid_ext_spk_power_amp_enable(0);
+	}
+
+	mutex_unlock(&dapm->codec->mutex);
+
+}
+
+
+static irqreturn_t msm8974_liquid_docking_irq_handler(int irq, void *dev)
+{
+	struct msm8974_liquid_dock_dev *dock_dev = dev;
+
+	/* switch speakers should not run in interrupt context */
+	schedule_work(&dock_dev->irq_work);
+
+	return IRQ_HANDLED;
+}
+
+static int msm8974_liquid_init_docking(struct snd_soc_dapm_context *dapm)
+{
+	int ret = 0;
+	int dock_plug_gpio = 0;
+
+	/* plug in docking speaker+plug in device OR unplug one of them */
+	u32 dock_plug_irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
+
+	dock_plug_gpio = of_get_named_gpio(spdev->dev.of_node,
+					   "qcom,dock-plug-det-irq", 0);
+
+	if (dock_plug_gpio >= 0) {
+
+		msm8974_liquid_dock_dev =
+		 kzalloc(sizeof(*msm8974_liquid_dock_dev), GFP_KERNEL);
+
+		if (!msm8974_liquid_dock_dev) {
+			pr_err("msm8974_liquid_dock_dev alloc fail.\n");
+			return -ENOMEM;
+		}
+
+		msm8974_liquid_dock_dev->dock_plug_gpio = dock_plug_gpio;
+
+		ret = gpio_request(msm8974_liquid_dock_dev->dock_plug_gpio,
+					   "dock-plug-det-irq");
+		if (ret) {
+			pr_err("%s:failed request msm8974_liquid_dock_plug_gpio.\n",
+				__func__);
+			return -EINVAL;
+		}
+
+		msm8974_liquid_dock_dev->dock_plug_det =
+			gpio_get_value(msm8974_liquid_dock_dev->dock_plug_gpio);
+
+		msm8974_liquid_dock_dev->dock_plug_irq =
+			gpio_to_irq(msm8974_liquid_dock_dev->dock_plug_gpio);
+
+		msm8974_liquid_dock_dev->dapm = dapm;
+
+		ret = request_irq(msm8974_liquid_dock_dev->dock_plug_irq,
+				  msm8974_liquid_docking_irq_handler,
+				  dock_plug_irq_flags,
+				  "liquid_dock_plug_irq",
+				  msm8974_liquid_dock_dev);
+
+		INIT_WORK(
+			&msm8974_liquid_dock_dev->irq_work,
+			msm8974_liquid_docking_irq_work);
+	}
+
+	return 0;
+}
+
+
+
+
 static void msm8974_ext_spk_power_amp_on(u32 spk)
 {
 	if (spk & (LO_1_SPK_AMP |
-					  LO_3_SPK_AMP |
-					  LO_2_SPK_AMP |
-					  LO_4_SPK_AMP)) {
+		   LO_3_SPK_AMP |
+		   LO_2_SPK_AMP |
+		   LO_4_SPK_AMP)) {
 
 		pr_debug("%s() External Left/Right Speakers already turned on. spk = 0x%08x\n",
 						__func__, spk);
@@ -206,7 +326,9 @@
 			(msm8974_ext_spk_pamp & LO_2_SPK_AMP) &&
 			(msm8974_ext_spk_pamp & LO_4_SPK_AMP)) {
 
-			if (ext_spk_amp_gpio >= 0)
+			if (ext_spk_amp_gpio >= 0 &&
+				msm8974_liquid_dock_dev != NULL &&
+				msm8974_liquid_dock_dev->dock_plug_det == 0)
 				msm8974_liquid_ext_spk_power_amp_enable(1);
 		}
 	} else  {
@@ -220,15 +342,17 @@
 static void msm8974_ext_spk_power_amp_off(u32 spk)
 {
 	if (spk & (LO_1_SPK_AMP |
-					  LO_3_SPK_AMP |
-					  LO_2_SPK_AMP |
-					  LO_4_SPK_AMP)) {
+		   LO_3_SPK_AMP |
+		   LO_2_SPK_AMP |
+		   LO_4_SPK_AMP)) {
 
 		pr_debug("%s Left and right speakers case spk = 0x%08x",
 				  __func__, spk);
 
 		if (!msm8974_ext_spk_pamp) {
-			if (ext_spk_amp_gpio >= 0)
+			if (ext_spk_amp_gpio >= 0 &&
+				msm8974_liquid_dock_dev != NULL &&
+				msm8974_liquid_dock_dev->dock_plug_det == 0)
 				msm8974_liquid_ext_spk_power_amp_enable(0);
 			msm8974_ext_spk_pamp = 0;
 		}
@@ -827,6 +951,13 @@
 		return err;
 	}
 
+	err = msm8974_liquid_init_docking(dapm);
+	if (err) {
+		pr_err("%s: LiQUID 8974 init Docking stat IRQ failed (%d)\n",
+			   __func__, err);
+		return err;
+	}
+
 	snd_soc_dapm_new_controls(dapm, msm8974_dapm_widgets,
 				ARRAY_SIZE(msm8974_dapm_widgets));
 
@@ -851,7 +982,7 @@
 	return err;
 }
 
-static int msm_snd_startup(struct snd_pcm_substream *substream)
+static int msm8974_snd_startup(struct snd_pcm_substream *substream)
 {
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
 		 substream->name, substream->stream);
@@ -996,7 +1127,7 @@
 	return ret;
 }
 
-static void msm_snd_shutdown(struct snd_pcm_substream *substream)
+static void msm8974_snd_shudown(struct snd_pcm_substream *substream)
 {
 	pr_debug("%s(): substream = %s stream = %d\n", __func__,
 		 substream->name, substream->stream);
@@ -1004,9 +1135,75 @@
 }
 
 static struct snd_soc_ops msm8974_be_ops = {
-	.startup = msm_snd_startup,
+	.startup = msm8974_snd_startup,
 	.hw_params = msm_snd_hw_params,
-	.shutdown = msm_snd_shutdown,
+	.shutdown = msm8974_snd_shudown,
+};
+
+
+
+static int msm8974_slimbus_2_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+	unsigned int num_tx_ch = 0;
+	unsigned int num_rx_ch = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+		num_rx_ch =  params_channels(params);
+
+		pr_debug("%s: %s rx_dai_id = %d  num_ch = %d\n", __func__,
+			codec_dai->name, codec_dai->id, num_rx_ch);
+
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+				num_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+	} else {
+
+		num_tx_ch =  params_channels(params);
+
+		pr_debug("%s: %s  tx_dai_id = %d  num_ch = %d\n", __func__,
+			codec_dai->name, codec_dai->id, num_tx_ch);
+
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+				num_tx_ch, tx_ch, 0 , 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+	}
+end:
+	return ret;
+}
+
+
+static struct snd_soc_ops msm8974_slimbus_2_be_ops = {
+	.startup = msm8974_snd_startup,
+	.hw_params = msm8974_slimbus_2_hw_params,
+	.shutdown = msm8974_snd_shudown,
 };
 
 /* Digital audio interface glue - connects codec <---> CPU */
@@ -1239,6 +1436,7 @@
 		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_INT_BT_SCO_TX,
@@ -1250,6 +1448,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
 		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_INT_FM_RX,
@@ -1263,6 +1462,7 @@
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_INT_FM_TX,
@@ -1274,6 +1474,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_INT_FM_TX,
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
 	},
 	/* Backend AFE DAI Links */
 	{
@@ -1288,6 +1489,7 @@
 		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_AFE_PCM_TX,
@@ -1299,6 +1501,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
 		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		.ignore_suspend = 1,
 	},
 	/* HDMI Hostless */
 	{
@@ -1328,6 +1531,7 @@
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
 		.ops = &msm_auxpcm_be_ops,
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 		/* this dainlink has playback support */
 	},
 	{
@@ -1341,6 +1545,7 @@
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
 		.ops = &msm_auxpcm_be_ops,
+		.ignore_suspend = 1,
 	},
 	/* Backend DAI Links */
 	{
@@ -1356,6 +1561,7 @@
 		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
 		.ops = &msm8974_be_ops,
 		.ignore_pmdown_time = 1, /* dai link has playback support */
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_0_TX,
@@ -1368,6 +1574,7 @@
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8974_be_ops,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_1_RX,
@@ -1382,6 +1589,7 @@
 		.ops = &msm8974_be_ops,
 		/* dai link has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_1_TX,
@@ -1394,6 +1602,7 @@
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8974_be_ops,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_3_RX,
@@ -1408,6 +1617,7 @@
 		.ops = &msm8974_be_ops,
 		/* dai link has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_3_TX,
@@ -1420,6 +1630,7 @@
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8974_be_ops,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_4_RX,
@@ -1434,6 +1645,7 @@
 		.ops = &msm8974_be_ops,
 		/* dai link has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_4_TX,
@@ -1446,6 +1658,7 @@
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8974_be_ops,
+		.ignore_suspend = 1,
 	},
 	/* Incall Record Uplink BACK END DAI Link */
 	{
@@ -1458,6 +1671,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
 	},
 	/* Incall Record Downlink BACK END DAI Link */
 	{
@@ -1470,6 +1684,44 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Music BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE_PLAYBACK_TX,
+		.stream_name = "Voice Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32773",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Ultrasound RX Back End DAI Link */
+	{
+		.name = "SLIMBUS_2 Hostless Playback",
+		.stream_name = "SLIMBUS_2 Hostless Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.16388",
+		.platform_name = "msm-pcm-hostless",
+		.codec_name = "taiko_codec",
+		.codec_dai_name = "taiko_rx2",
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ops = &msm8974_slimbus_2_be_ops,
+	},
+	/* Ultrasound TX Back End DAI Link */
+	{
+		.name = "SLIMBUS_2 Hostless Capture",
+		.stream_name = "SLIMBUS_2 Hostless Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.16389",
+		.platform_name = "msm-pcm-hostless",
+		.codec_name = "taiko_codec",
+		.codec_dai_name = "taiko_tx2",
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ops = &msm8974_slimbus_2_be_ops,
 	},
 };
 
@@ -1486,6 +1738,7 @@
 		.be_id = MSM_BACKEND_DAI_HDMI_RX,
 		.be_hw_params_fixup = msm8974_hdmi_be_hw_params_fixup,
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 };
 
@@ -1680,6 +1933,12 @@
 		card->num_links	= ARRAY_SIZE(msm8974_common_dai_links);
 	}
 
+	mutex_init(&cdc_mclk_mutex);
+	atomic_set(&auxpcm_rsc_ref, 0);
+	spdev = pdev;
+	ext_spk_amp_regulator = NULL;
+	msm8974_liquid_dock_dev = NULL;
+
 	ret = snd_soc_register_card(card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
@@ -1687,12 +1946,6 @@
 		goto err;
 	}
 
-	mutex_init(&cdc_mclk_mutex);
-	atomic_set(&auxpcm_rsc_ref, 0);
-
-	spdev = pdev;
-	ext_spk_amp_regulator = NULL;
-
 	lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
 	if (lpaif_pri_muxsel_virt_addr == NULL) {
 		pr_err("%s Pri muxsel virt addr is null\n", __func__);
@@ -1716,6 +1969,19 @@
 	gpio_free(pdata->mclk_gpio);
 	if (ext_spk_amp_gpio >= 0)
 		gpio_free(ext_spk_amp_gpio);
+
+	if (msm8974_liquid_dock_dev != NULL) {
+		if (msm8974_liquid_dock_dev->dock_plug_gpio)
+			gpio_free(msm8974_liquid_dock_dev->dock_plug_gpio);
+
+		if (msm8974_liquid_dock_dev->dock_plug_irq)
+			free_irq(msm8974_liquid_dock_dev->dock_plug_irq,
+				 msm8974_liquid_dock_dev);
+
+		kfree(msm8974_liquid_dock_dev);
+		msm8974_liquid_dock_dev = NULL;
+	}
+
 	iounmap(lpaif_pri_muxsel_virt_addr);
 	snd_soc_unregister_card(card);
 
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
new file mode 100644
index 0000000..981a9a7
--- /dev/null
+++ b/sound/soc/msm/msm8x10.c
@@ -0,0 +1,202 @@
+ /* 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/qpnp/clkdiv.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/jack.h>
+#include <asm/mach-types.h>
+#include <mach/socinfo.h>
+#include <qdsp6v2/msm-pcm-routing-v2.h>
+#include <linux/module.h>
+#define DRV_NAME "msm8x10-asoc-wcd"
+
+static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
+static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+	pr_info("%s(), dev_name%s\n", __func__, dev_name(rtd->cpu_dai->dev));
+	return 0;
+}
+
+static int msm_snd_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	return 0;
+}
+
+static int msm_snd_startup(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	return 0;
+}
+
+
+static void msm_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s stream = %d\n", __func__,
+		 substream->name, substream->stream);
+}
+
+static struct snd_soc_ops msm8x10_be_ops = {
+	.startup = msm_snd_startup,
+	.hw_params = msm_snd_hw_params,
+	.shutdown = msm_snd_shutdown,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm8x10_dai[] = {
+	/* FrontEnd DAI Links */
+	{
+		.name = "MSM8X10 Media1",
+		.stream_name = "MultiMedia1",
+		.cpu_dai_name	= "MultiMedia1",
+		.platform_name  = "msm-pcm-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+	},
+	{
+		.name = "MSM8X10 Media2",
+		.stream_name = "MultiMedia2",
+		.cpu_dai_name   = "MultiMedia2",
+		.platform_name  = "msm-pcm-dsp",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+	},
+	/* Backend I2S DAI Links */
+	{
+		.name = LPASS_BE_MI2S_RX,
+		.stream_name = "Primary MI2S Playback",
+		.cpu_dai_name = "msm-dai-q6-mi2s.0",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_MI2S_RX,
+		.init = &msm_audrx_init,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm8x10_be_ops,
+	},
+	{
+		.name = LPASS_BE_SEC_MI2S_TX,
+		.stream_name = "Secondary MI2S Capture",
+		.cpu_dai_name = "msm-dai-q6-mi2s.1",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm8x10_be_ops,
+	},
+};
+
+struct snd_soc_card snd_soc_card_msm8x10 = {
+	.name		= "msm8x10-snd-card",
+	.dai_link	= msm8x10_dai,
+	.num_links	= ARRAY_SIZE(msm8x10_dai),
+};
+
+
+static __devinit int msm8x10_asoc_machine_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &snd_soc_card_msm8x10;
+	int ret;
+
+	dev_dbg(&pdev->dev, "%s\n", __func__);
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev, "No platform supplied from device tree\n");
+		return -EINVAL;
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+			ret);
+		goto err;
+	}
+
+	return 0;
+err:
+	return ret;
+}
+
+static int __devexit msm8x10_asoc_machine_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static const struct of_device_id msm8x10_asoc_machine_of_match[]  = {
+	{ .compatible = "qcom,msm8x10-audio-codec", },
+	{},
+};
+
+static struct platform_driver msm8x10_asoc_machine_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = msm8x10_asoc_machine_of_match,
+	},
+	.probe = msm8x10_asoc_machine_probe,
+	.remove = __devexit_p(msm8x10_asoc_machine_remove),
+};
+module_platform_driver(msm8x10_asoc_machine_driver);
+
+MODULE_DESCRIPTION("ALSA SoC msm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, msm8x10_asoc_machine_of_match);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index f15aec3..6df2fb93 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -347,6 +347,7 @@
 
 	prtd->enabled = 1;
 	prtd->cmd_ack = 0;
+	prtd->cmd_interrupt = 0;
 
 	return 0;
 }
@@ -452,12 +453,12 @@
 				break;
 			}
 		}
+		atomic_set(&prtd->pending_buffer, 1);
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		pr_debug("%s: Trigger start\n", __func__);
 		q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
 		atomic_set(&prtd->start, 1);
-		atomic_set(&prtd->pending_buffer, 1);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
@@ -509,17 +510,6 @@
 	struct compr_audio *compr;
 	struct msm_audio *prtd;
 	int ret = 0;
-	struct asm_softpause_params softpause = {
-		.enable = SOFT_PAUSE_ENABLE,
-		.period = SOFT_PAUSE_PERIOD,
-		.step = SOFT_PAUSE_STEP,
-		.rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
-	};
-	struct asm_softvolume_params softvol = {
-		.period = SOFT_VOLUME_PERIOD,
-		.step = SOFT_VOLUME_STEP,
-		.rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
-	};
 
 	pr_debug("%s\n", __func__);
 	compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL);
@@ -569,20 +559,6 @@
 	atomic_set(&prtd->eos, 0);
 	atomic_set(&compressed_audio.audio_ocmem_req, 0);
 	compressed_audio.prtd =  &compr->prtd;
-	ret = compressed_set_volume(compressed_audio.volume);
-	if (ret < 0)
-		pr_err("%s : Set Volume failed : %d", __func__, ret);
-
-	ret = q6asm_set_softpause(compressed_audio.prtd->audio_client,
-								&softpause);
-	if (ret < 0)
-		pr_err("%s: Send SoftPause Param failed ret=%d\n",
-			__func__, ret);
-	ret = q6asm_set_softvolume(compressed_audio.prtd->audio_client,
-								&softvol);
-	if (ret < 0)
-		pr_err("%s: Send SoftVolume Param failed ret=%d\n",
-			__func__, ret);
 
 	return 0;
 }
@@ -720,6 +696,17 @@
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
 	struct audio_buffer *buf;
 	int dir, ret;
+	struct asm_softpause_params softpause = {
+		.enable = SOFT_PAUSE_ENABLE,
+		.period = SOFT_PAUSE_PERIOD,
+		.step = SOFT_PAUSE_STEP,
+		.rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
+	};
+	struct asm_softvolume_params softvol = {
+		.period = SOFT_VOLUME_PERIOD,
+		.step = SOFT_VOLUME_STEP,
+		.rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
+	};
 
 	pr_debug("%s\n", __func__);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -727,17 +714,32 @@
 	else
 		dir = OUT;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			ret = q6asm_open_write(prtd->audio_client,
-					compr->codec);
-			if (ret < 0) {
-				pr_err("%s: Session out open failed\n",
-					__func__);
-				return -ENOMEM;
-			}
-			msm_pcm_routing_reg_phy_stream(
-				soc_prtd->dai_link->be_id,
-				prtd->session_id,
-				substream->stream);
+		ret = q6asm_open_write(prtd->audio_client,
+				compr->codec);
+		if (ret < 0) {
+			pr_err("%s: Session out open failed\n",
+				__func__);
+			return -ENOMEM;
+		}
+		msm_pcm_routing_reg_phy_stream(
+			soc_prtd->dai_link->be_id,
+			prtd->session_id,
+			substream->stream);
+
+		ret = compressed_set_volume(compressed_audio.volume);
+		if (ret < 0)
+			pr_err("%s : Set Volume failed : %d", __func__, ret);
+
+		ret = q6asm_set_softpause(compressed_audio.prtd->audio_client,
+								&softpause);
+		if (ret < 0)
+			pr_err("%s: Send SoftPause Param failed ret=%d\n",
+				__func__, ret);
+		ret = q6asm_set_softvolume(compressed_audio.prtd->audio_client,
+								&softvol);
+		if (ret < 0)
+			pr_err("%s: Send SoftVolume Param failed ret=%d\n",
+				__func__, ret);
 	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 		switch (compr->info.codec_param.codec.id) {
 		case SND_AUDIOCODEC_AMRWB:
@@ -894,7 +896,7 @@
 			  (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
 						atomic_read(&prtd->start))) {
 			if (atomic_read(&prtd->eos)) {
-				prtd->cmd_ack = 1;
+				prtd->cmd_interrupt = 1;
 				wake_up(&the_locks.eos_wait);
 				atomic_set(&prtd->eos, 0);
 			}
@@ -917,17 +919,29 @@
 		break;
 	case SNDRV_COMPRESS_DRAIN:
 		pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
+		if (atomic_read(&prtd->pending_buffer)) {
+			pr_debug("%s: no pending writes, drain would block\n",
+			 __func__);
+			return -EWOULDBLOCK;
+		}
+
 		atomic_set(&prtd->eos, 1);
 		atomic_set(&prtd->pending_buffer, 0);
 		prtd->cmd_ack = 0;
 		q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
 		/* Wait indefinitely for  DRAIN. Flush can also signal this*/
 		rc = wait_event_interruptible(the_locks.eos_wait,
-			prtd->cmd_ack);
+			(prtd->cmd_ack || prtd->cmd_interrupt));
+
 		if (rc < 0)
 			pr_err("EOS cmd interrupted\n");
 		pr_debug("%s: SNDRV_COMPRESS_DRAIN  out of wait\n", __func__);
-		return 0;
+
+		if (prtd->cmd_interrupt)
+			rc = -EINTR;
+
+		prtd->cmd_interrupt = 0;
+		return rc;
 	default:
 		break;
 	}
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index cf7f182..4efdb24 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -452,14 +452,8 @@
 	int rc = 0;
 
 	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
-		switch (dai->id) {
-		case VOICE_PLAYBACK_TX:
-			rc = afe_start_pseudo_port(dai->id);
-			break;
-		default:
-			rc = afe_port_start(dai->id, &dai_data->port_config,
+		rc = afe_port_start(dai->id, &dai_data->port_config,
 					dai_data->rate);
-		}
 
 		if (IS_ERR_VALUE(rc))
 			dev_err(dai->dev, "fail to open AFE port %x\n",
@@ -678,10 +672,12 @@
 		break;
 	case SLIMBUS_0_RX:
 	case SLIMBUS_1_RX:
+	case SLIMBUS_2_RX:
 	case SLIMBUS_3_RX:
 	case SLIMBUS_4_RX:
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_TX:
+	case SLIMBUS_2_TX:
 	case SLIMBUS_3_TX:
 	case SLIMBUS_4_TX:
 		rc = msm_dai_q6_slim_bus_hw_params(params, dai,
@@ -700,8 +696,6 @@
 		rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
 		break;
 	case VOICE_PLAYBACK_TX:
-		rc = 0;
-		break;
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		rc = msm_dai_q6_psuedo_port_hw_params(params,
@@ -723,16 +717,9 @@
 	int rc = 0;
 
 	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
-		switch (dai->id) {
-		case VOICE_PLAYBACK_TX:
-			pr_debug("%s, stop pseudo port:%d\n",
-						__func__,  dai->id);
-			rc = afe_stop_pseudo_port(dai->id);
-			break;
-		default:
-			rc = afe_close(dai->id); /* can block */
-			break;
-		}
+		pr_debug("%s, stop pseudo port:%d\n", __func__,  dai->id);
+		rc = afe_close(dai->id); /* can block */
+
 		if (IS_ERR_VALUE(rc))
 			dev_err(dai->dev, "fail to close AFE port\n");
 		pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
@@ -794,6 +781,7 @@
 	switch (dai->id) {
 	case SLIMBUS_0_RX:
 	case SLIMBUS_1_RX:
+	case SLIMBUS_2_RX:
 	case SLIMBUS_3_RX:
 	case SLIMBUS_4_RX:
 		/*
@@ -807,17 +795,19 @@
 		for (i = 0; i < rx_num; i++) {
 			dai_data->port_config.slim_sch.shared_ch_mapping[i] =
 			    rx_slot[i];
-			pr_err("%s: find number of channels[%d] ch[%d]\n",
+			pr_debug("%s: find number of channels[%d] ch[%d]\n",
 			       __func__, i, rx_slot[i]);
 		}
 		dai_data->port_config.slim_sch.num_channels = rx_num;
-		pr_debug("%s:SLIMBUS_0_RX cnt[%d] ch[%d %d]\n", __func__,
-		rx_num, dai_data->port_config.slim_sch.shared_ch_mapping[0],
-		dai_data->port_config.slim_sch.shared_ch_mapping[1]);
+		pr_debug("%s:SLIMBUS_%d_RX cnt[%d] ch[%d %d]\n", __func__,
+			(dai->id - SLIMBUS_0_RX) / 2, rx_num,
+			dai_data->port_config.slim_sch.shared_ch_mapping[0],
+			dai_data->port_config.slim_sch.shared_ch_mapping[1]);
 
 		break;
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_TX:
+	case SLIMBUS_2_TX:
 	case SLIMBUS_3_TX:
 	case SLIMBUS_4_TX:
 		/*
@@ -835,10 +825,10 @@
 				 __func__, i, tx_slot[i]);
 		}
 		dai_data->port_config.slim_sch.num_channels = tx_num;
-		pr_debug("%s:SLIMBUS_0_TX cnt[%d] ch[%d %d]\n", __func__,
-			 tx_num,
-			 dai_data->port_config.slim_sch.shared_ch_mapping[0],
-		dai_data->port_config.slim_sch.shared_ch_mapping[1]);
+		pr_debug("%s:SLIMBUS_%d_TX cnt[%d] ch[%d %d]\n", __func__,
+			(dai->id - SLIMBUS_0_TX) / 2, tx_num,
+			dai_data->port_config.slim_sch.shared_ch_mapping[0],
+			dai_data->port_config.slim_sch.shared_ch_mapping[1]);
 		break;
 	default:
 		dev_err(dai->dev, "invalid cpu_dai id %d\n", dai->id);
@@ -882,15 +872,9 @@
 
 	/* If AFE port is still up, close it */
 	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
-		switch (dai->id) {
-		case VOICE_PLAYBACK_TX:
-			pr_debug("%s, stop pseudo port:%d\n",
-				 __func__,  dai->id);
-			rc = afe_stop_pseudo_port(dai->id);
-			break;
-		default:
-			rc = afe_close(dai->id); /* can block */
-		}
+		pr_debug("%s, stop pseudo port:%d\n", __func__,  dai->id);
+		rc = afe_close(dai->id); /* can block */
+
 		if (IS_ERR_VALUE(rc))
 			dev_err(dai->dev, "fail to close AFE port\n");
 		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
@@ -1019,6 +1003,21 @@
 	.remove = msm_dai_q6_dai_remove,
 };
 
+static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+		SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min =     8000,
+		.rate_max =     48000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.probe = msm_dai_q6_dai_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
+
 static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
 	.capture = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
@@ -1246,12 +1245,13 @@
 static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
-		SNDRV_PCM_RATE_16000,
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
+		SNDRV_PCM_RATE_192000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		.channels_min = 1,
 		.channels_max = 8,
 		.rate_min = 8000,
-		.rate_max = 48000,
+		.rate_max = 192000,
 	},
 	.ops = &msm_dai_q6_ops,
 	.probe = msm_dai_q6_dai_probe,
@@ -1261,12 +1261,13 @@
 static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
 	.capture = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
-		SNDRV_PCM_RATE_16000,
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
+		SNDRV_PCM_RATE_192000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		.channels_min = 1,
 		.channels_max = 8,
 		.rate_min = 8000,
-		.rate_max = 48000,
+		.rate_max = 192000,
 	},
 	.ops = &msm_dai_q6_ops,
 	.probe = msm_dai_q6_dai_probe,
@@ -1943,10 +1944,12 @@
 
 	switch (id) {
 	case SLIMBUS_0_RX:
+	case SLIMBUS_2_RX:
 		rc = snd_soc_register_dai(&pdev->dev,
 					  &msm_dai_q6_slimbus_rx_dai);
 		break;
 	case SLIMBUS_0_TX:
+	case SLIMBUS_2_TX:
 		rc = snd_soc_register_dai(&pdev->dev,
 					  &msm_dai_q6_slimbus_tx_dai);
 		break;
@@ -1984,6 +1987,10 @@
 	case RT_PROXY_DAI_002_TX:
 		rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
 		break;
+	case VOICE_PLAYBACK_TX:
+		rc = snd_soc_register_dai(&pdev->dev,
+					&msm_dai_q6_voice_playback_tx_dai);
+		break;
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		rc = snd_soc_register_dai(&pdev->dev,
diff --git a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
index 98401d9..827aaa3 100644
--- a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -230,6 +230,7 @@
 
 	prtd->enabled = 1;
 	prtd->cmd_ack = 0;
+	prtd->cmd_interrupt = 0;
 
 	return 0;
 }
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index 97b4a16..b9fafb1 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -68,7 +68,7 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	u32 mem_map_handle = 0;
 
-	mem_map_handle = afe_req_mmap_handle();
+	mem_map_handle = afe_req_mmap_handle(prtd->audio_client);
 	if (!mem_map_handle)
 		pr_err("%s: mem_map_handle is NULL\n", __func__);
 
@@ -99,7 +99,7 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	u32 mem_map_handle = 0;
 
-	mem_map_handle = afe_req_mmap_handle();
+	mem_map_handle = afe_req_mmap_handle(prtd->audio_client);
 	if (!mem_map_handle)
 		pr_err("%s: mem_map_handle is NULL\n", __func__);
 
@@ -394,7 +394,7 @@
 	}
 	hrtimer_cancel(&prtd->hrt);
 
-	rc = afe_cmd_memory_unmap(afe_req_mmap_handle());
+	rc = afe_cmd_memory_unmap(afe_req_mmap_handle(prtd->audio_client));
 	if (rc < 0)
 		pr_err("AFE memory unmap failed\n");
 
@@ -533,7 +533,7 @@
 
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
-	rc = afe_cmd_memory_map(dma_buf->addr, dma_buf->bytes);
+	rc = afe_memory_map(dma_buf->addr, dma_buf->bytes, prtd->audio_client);
 	if (rc < 0)
 		pr_err("fail to map memory to DSP\n");
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 6c73a85..4d88246 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -216,6 +216,8 @@
 	atomic_set(&prtd->out_count, runtime->periods);
 	prtd->enabled = 1;
 	prtd->cmd_ack = 0;
+	prtd->cmd_interrupt = 0;
+
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index fa8609e..34b38a6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -50,7 +50,8 @@
 #define PLAYBACK_MAX_PERIOD_SIZE    12288
 #define PLAYBACK_MIN_PERIOD_SIZE    2048
 #define CAPTURE_NUM_PERIODS	16
-#define CAPTURE_PERIOD_SIZE	512
+#define CAPTURE_MAX_PERIOD_SIZE 4096
+#define CAPTURE_MIN_PERIOD_SIZE 512
 
 static struct snd_pcm_hardware msm_pcm_hardware_capture = {
 	.info =                 (SNDRV_PCM_INFO_MMAP |
@@ -64,9 +65,9 @@
 	.rate_max =             48000,
 	.channels_min =         1,
 	.channels_max =         4,
-	.buffer_bytes_max =     CAPTURE_NUM_PERIODS * CAPTURE_PERIOD_SIZE,
-	.period_bytes_min =	CAPTURE_PERIOD_SIZE,
-	.period_bytes_max =     CAPTURE_PERIOD_SIZE,
+	.buffer_bytes_max =     CAPTURE_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
+	.period_bytes_min =	CAPTURE_MIN_PERIOD_SIZE,
+	.period_bytes_max =     CAPTURE_MAX_PERIOD_SIZE,
 	.periods_min =          CAPTURE_NUM_PERIODS,
 	.periods_max =          CAPTURE_NUM_PERIODS,
 	.fifo_size =            0,
@@ -231,6 +232,7 @@
 
 	prtd->enabled = 1;
 	prtd->cmd_ack = 0;
+	prtd->cmd_interrupt = 0;
 
 	return 0;
 }
@@ -373,6 +375,17 @@
 		}
 	}
 
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		ret = snd_pcm_hw_constraint_minmax(runtime,
+			SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+			CAPTURE_NUM_PERIODS * CAPTURE_MIN_PERIOD_SIZE,
+			CAPTURE_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE);
+		if (ret < 0) {
+			pr_err("constraint for buffer bytes min max ret = %d\n",
+									ret);
+		}
+	}
+
 	prtd->dsp_cnt = 0;
 	prtd->set_channel_map = false;
 	runtime->private_data = prtd;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index 9a770bf..01ed41f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -84,6 +84,7 @@
 	atomic_t pending_buffer;
 	bool set_channel_map;
 	char channel_map[8];
+	int cmd_interrupt;
 };
 
 struct output_meta_data_st {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index ad6d5e8..8a5abc9 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -188,8 +188,13 @@
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 	{ AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, 0, 0, 0},
 	{ AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, 0, 0, 0},
-	{ AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, 0, 0, 0},
-	{ AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_SECONDARY_MI2S_RX,  0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_SECONDARY_MI2S_TX,  0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_PRIMARY_MI2S_RX,    0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_PRIMARY_MI2S_TX,    0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_TERTIARY_MI2S_RX,   0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_TERTIARY_MI2S_TX,   0, 0, 0, 0, 0},
+	{ AUDIO_PORT_ID_I2S_RX,           0, 0, 0, 0, 0},
 };
 
 
@@ -420,7 +425,6 @@
 		if (!test_bit(val, &msm_bedais[reg].fe_sessions) &&
 			(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
 			voc_start_playback(set);
-
 		set_bit(val, &msm_bedais[reg].fe_sessions);
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
@@ -1155,6 +1159,21 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_MI2S_RX ,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1605,6 +1624,12 @@
 	msm_routing_put_port_mixer),
 };
 
+static const struct snd_kcontrol_new primary_mi2s_rx_port_mixer_controls[] = {
+	SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
+
 static const struct snd_kcontrol_new fm_switch_mixer_controls =
 	SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
 	0, 1, 0, msm_routing_get_switch_mixer,
@@ -1943,6 +1968,8 @@
 						0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback",
 			     0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback",
+			     0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MI2S_TX", "MI2S Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture",
@@ -2014,6 +2041,9 @@
 	SND_SOC_DAPM_MIXER("SEC_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 			   secondary_mi2s_rx_mixer_controls,
 			   ARRAY_SIZE(secondary_mi2s_rx_mixer_controls)),
+	SND_SOC_DAPM_MIXER("PRI_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+			   primary_mi2s_rx_mixer_controls,
+			   ARRAY_SIZE(primary_mi2s_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
 	mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
@@ -2108,7 +2138,9 @@
 	ARRAY_SIZE(sbus_3_rx_port_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0,
 	mi2s_rx_port_mixer_controls, ARRAY_SIZE(mi2s_rx_port_mixer_controls)),
-
+	SND_SOC_DAPM_MIXER("PRI_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0,
+	primary_mi2s_rx_port_mixer_controls,
+	ARRAY_SIZE(primary_mi2s_rx_port_mixer_controls)),
 	/* Virtual Pins to force backends ON atm */
 	SND_SOC_DAPM_OUTPUT("BE_OUT"),
 	SND_SOC_DAPM_INPUT("BE_IN"),
@@ -2170,6 +2202,12 @@
 	{"SEC_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"SEC_MI2S_RX", NULL, "SEC_MI2S_RX Audio Mixer"},
 
+	{"PRI_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+	{"PRI_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"PRI_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+	{"PRI_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Audio Mixer"},
+
 	{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
 	{"MultiMedia1 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
@@ -2355,6 +2393,10 @@
 	{"MI2S_RX Port Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
 	{"MI2S_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MI2S_RX", NULL, "MI2S_RX Port Mixer"},
+
+	{"PRI_MI2S_RX Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
+	{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Port Mixer"},
+
 	/* Backend Enablement */
 
 	{"BE_OUT", NULL, "PRI_I2S_RX"},
@@ -2367,6 +2409,13 @@
 	{"BE_OUT", NULL, "MI2S_RX"},
 	{"BE_OUT", NULL, "QUAT_MI2S_RX"},
 	{"BE_OUT", NULL, "SEC_MI2S_RX"},
+	{"BE_OUT", NULL, "PRI_MI2S_RX"},
+	{"BE_OUT", NULL, "INT_BT_SCO_RX"},
+	{"BE_OUT", NULL, "INT_FM_RX"},
+	{"BE_OUT", NULL, "PCM_RX"},
+	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
+	{"BE_OUT", NULL, "AUX_PCM_RX"},
+
 	{"PRI_I2S_TX", NULL, "BE_IN"},
 	{"MI2S_TX", NULL, "BE_IN"},
 	{"QUAT_MI2S_TX", NULL, "BE_IN"},
@@ -2386,6 +2435,7 @@
 	{"AUX_PCM_TX", NULL, "BE_IN"},
 	{"INCALL_RECORD_TX", NULL, "BE_IN"},
 	{"INCALL_RECORD_RX", NULL, "BE_IN"},
+	{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"}
 };
 
 static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 443e461..cf24f9a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -37,6 +37,11 @@
 #define LPASS_BE_QUAT_MI2S_TX "QUAT_MI2S_TX"
 #define LPASS_BE_SEC_MI2S_RX "SEC_MI2S_RX"
 #define LPASS_BE_SEC_MI2S_TX "SEC_MI2S_TX"
+#define LPASS_BE_PRI_MI2S_RX "PRI_MI2S_RX"
+#define LPASS_BE_PRI_MI2S_TX "PRI_MI2S_TX"
+#define LPASS_BE_TERT_MI2S_RX "TERTIARY_MI2S_RX"
+#define LPASS_BE_TERT_MI2S_TX "TERTIARY_MI2S_TX"
+#define LPASS_BE_AUDIO_I2S_RX "AUDIO_I2S_RX"
 #define LPASS_BE_STUB_RX "STUB_RX"
 #define LPASS_BE_STUB_TX "STUB_TX"
 #define LPASS_BE_SLIMBUS_1_RX "SLIMBUS_1_RX"
@@ -104,6 +109,11 @@
 	MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
 	MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
 	MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
+	MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+	MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
+	MSM_BACKEND_DAI_AUDIO_I2S_RX,
 	MSM_BACKEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 050a2719..1b5ad17 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -175,8 +175,11 @@
 	case INT_FM_RX:
 	case VOICE_PLAYBACK_TX:
 	case RT_PROXY_PORT_001_RX:
-	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
+	case AUDIO_PORT_ID_I2S_RX:
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
 	case AFE_PORT_ID_SECONDARY_MI2S_RX:
+	case AFE_PORT_ID_TERTIARY_MI2S_RX:
+	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
 		ret = MSM_AFE_PORT_TYPE_RX;
 		break;
 
@@ -195,8 +198,10 @@
 	case VOICE_RECORD_RX:
 	case INT_BT_SCO_TX:
 	case RT_PROXY_PORT_001_TX:
-	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+	case AFE_PORT_ID_PRIMARY_MI2S_TX:
 	case AFE_PORT_ID_SECONDARY_MI2S_TX:
+	case AFE_PORT_ID_TERTIARY_MI2S_TX:
+	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
 		ret = MSM_AFE_PORT_TYPE_TX;
 		break;
 
@@ -219,6 +224,7 @@
 	case SECONDARY_I2S_TX:
 	case MI2S_RX:
 	case MI2S_TX:
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_i2s_cfg);
 		break;
 	case HDMI_RX:
@@ -229,8 +235,11 @@
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_RX:
 	case SLIMBUS_1_TX:
+	case SLIMBUS_2_RX:
+	case SLIMBUS_2_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
 		break;
+	case VOICE_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_pseudo_port_cfg);
@@ -407,6 +416,7 @@
 	case SECONDARY_I2S_TX:
 	case MI2S_RX:
 	case MI2S_TX:
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
 	case AFE_PORT_ID_SECONDARY_MI2S_RX:
 	case AFE_PORT_ID_SECONDARY_MI2S_TX:
 	case AFE_PORT_ID_TERTIARY_MI2S_RX:
@@ -418,6 +428,7 @@
 	case HDMI_RX:
 		cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
 		break;
+	case VOICE_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
@@ -564,6 +575,8 @@
 	case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
 	case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
 	case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
+		return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
 		return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
@@ -633,6 +646,7 @@
 		break;
 	case SECONDARY_I2S_RX:
 	case SECONDARY_I2S_TX:
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
 	case MI2S_RX:
 	case MI2S_TX:
 		cfg_type = AFE_PARAM_ID_I2S_CONFIG;
@@ -1036,9 +1050,9 @@
 	return 0;
 }
 
-uint32_t afe_req_mmap_handle(void)
+uint32_t afe_req_mmap_handle(struct afe_audio_client *ac)
 {
-	return this_afe.mmap_handle;
+	return ac->mem_map_handle;
 }
 
 struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
@@ -1163,6 +1177,21 @@
 	q6afe_audio_client_buf_free_contiguous(dir, ac);
 	return -EINVAL;
 }
+
+int afe_memory_map(u32 dma_addr_p, u32 dma_buf_sz, struct afe_audio_client *ac)
+{
+	int ret = 0;
+
+	ac->mem_map_handle = 0;
+	ret = afe_cmd_memory_map(dma_addr_p, dma_buf_sz);
+	if (ret < 0) {
+		pr_err("%s: afe_cmd_memory_map failed\n", __func__);
+		return ret;
+	}
+	ac->mem_map_handle = this_afe.mmap_handle;
+	return ret;
+}
+
 int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
 {
 	int ret = 0;
@@ -1222,6 +1251,7 @@
 	pr_debug("%s: dma_addr_p 0x%x , size %d\n", __func__,
 					dma_addr_p, dma_buf_sz);
 	atomic_set(&this_afe.state, 1);
+	this_afe.mmap_handle = 0;
 	ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
 	if (ret < 0) {
 		pr_err("%s: AFE memory map cmd failed %d\n",
@@ -1980,6 +2010,7 @@
 	case RT_PROXY_PORT_001_TX:
 	case SLIMBUS_4_RX:
 	case SLIMBUS_4_TX:
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
 	{
 		ret = 0;
 		break;
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 985a33d..99cb6a6 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -41,6 +41,8 @@
 	case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
 	case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
 	case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
+	case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
+	case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
 	case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
 	case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
@@ -48,6 +50,8 @@
 	case INT_FM_TX: return IDX_INT_FM_TX;
 	case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
 	case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
+		return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
 		return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
@@ -83,6 +87,8 @@
 	case SLIMBUS_0_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX;
 	case SLIMBUS_1_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX;
 	case SLIMBUS_1_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX;
+	case SLIMBUS_2_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX;
+	case SLIMBUS_2_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX;
 	case INT_BT_SCO_RX: return AFE_PORT_ID_INTERNAL_BT_SCO_RX;
 	case INT_BT_SCO_TX: return AFE_PORT_ID_INTERNAL_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return AFE_PORT_ID_INTERNAL_BT_A2DP_RX;
@@ -90,6 +96,8 @@
 	case INT_FM_TX: return AFE_PORT_ID_INTERNAL_FM_TX;
 	case RT_PROXY_PORT_001_RX: return AFE_PORT_ID_RT_PROXY_PORT_001_RX;
 	case RT_PROXY_PORT_001_TX: return AFE_PORT_ID_RT_PROXY_PORT_001_TX;
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
+			     return AFE_PORT_ID_PRIMARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
 			     return AFE_PORT_ID_QUATERNARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
@@ -172,6 +180,8 @@
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_RX:
 	case SLIMBUS_1_TX:
+	case SLIMBUS_2_RX:
+	case SLIMBUS_2_TX:
 	case INT_BT_SCO_RX:
 	case INT_BT_SCO_TX:
 	case INT_BT_A2DP_RX:
@@ -179,6 +189,7 @@
 	case INT_FM_TX:
 	case RT_PROXY_PORT_001_RX:
 	case RT_PROXY_PORT_001_TX:
+	case AFE_PORT_ID_PRIMARY_MI2S_RX:
 	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
 	case AFE_PORT_ID_SECONDARY_MI2S_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 03e4769..6a65880 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -3280,7 +3280,7 @@
 static int voice_cvs_start_playback(struct voice_data *v)
 {
 	int ret = 0;
-	struct apr_hdr cvs_start_playback;
+	struct cvs_start_playback_cmd cvs_start_playback;
 	void *apr_cvs;
 	u16 cvs_handle;
 
@@ -3298,17 +3298,18 @@
 	cvs_handle = voice_get_cvs_handle(v);
 
 	if (!v->music_info.playing && v->music_info.count) {
-		cvs_start_playback.hdr_field = APR_HDR_FIELD(
+		cvs_start_playback.hdr.hdr_field = APR_HDR_FIELD(
 					APR_MSG_TYPE_SEQ_CMD,
 					APR_HDR_LEN(APR_HDR_SIZE),
 					APR_PKT_VER);
-		cvs_start_playback.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+		cvs_start_playback.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
 				sizeof(cvs_start_playback) - APR_HDR_SIZE);
-		cvs_start_playback.src_port = v->session_id;
-		cvs_start_playback.dest_port = cvs_handle;
-		cvs_start_playback.token = 0;
-		cvs_start_playback.opcode = VSS_ISTREAM_CMD_START_PLAYBACK;
-
+		cvs_start_playback.hdr.src_port = v->session_id;
+		cvs_start_playback.hdr.dest_port = cvs_handle;
+		cvs_start_playback.hdr.token = 0;
+		cvs_start_playback.hdr.opcode = VSS_IPLAYBACK_CMD_START;
+		cvs_start_playback.playback_mode.port_id =
+						VSS_IPLAYBACK_PORT_ID_DEFAULT;
 		v->cvs_state = CMD_STATUS_FAIL;
 
 		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_start_playback);
@@ -3371,7 +3372,7 @@
 		cvs_stop_playback.dest_port = cvs_handle;
 		cvs_stop_playback.token = 0;
 
-		cvs_stop_playback.opcode = VSS_ISTREAM_CMD_STOP_PLAYBACK;
+		cvs_stop_playback.opcode = VSS_IPLAYBACK_CMD_STOP;
 
 		v->cvs_state = CMD_STATUS_FAIL;
 
@@ -4296,8 +4297,8 @@
 			case VSS_ICOMMON_CMD_MAP_MEMORY:
 			case VSS_ICOMMON_CMD_UNMAP_MEMORY:
 			case VSS_ICOMMON_CMD_SET_UI_PROPERTY:
-			case VSS_ISTREAM_CMD_START_PLAYBACK:
-			case VSS_ISTREAM_CMD_STOP_PLAYBACK:
+			case VSS_IPLAYBACK_CMD_START:
+			case VSS_IPLAYBACK_CMD_STOP:
 			case VSS_IRECORD_CMD_START:
 			case VSS_IRECORD_CMD_STOP:
 			case VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE:
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 9f77af6..98bd002 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -489,12 +489,15 @@
 #define VOICE_PARAM_MOD_ENABLE				0x00010E00
 #define MOD_ENABLE_PARAM_LEN				4
 
-#define VSS_ISTREAM_CMD_START_PLAYBACK                  0x00011238
+#define VSS_IPLAYBACK_CMD_START				0x000112BD
 /* Start in-call music delivery on the Tx voice path. */
 
-#define VSS_ISTREAM_CMD_STOP_PLAYBACK                   0x00011239
+#define VSS_IPLAYBACK_CMD_STOP				0x00011239
 /* Stop the in-call music delivery on the Tx voice path. */
 
+#define VSS_IPLAYBACK_PORT_ID_DEFAULT			0x0000FFFF
+/* Default AFE port ID. */
+
 #define VSS_IRECORD_CMD_START				0x000112BE
 /* Start in-call conversation recording. */
 #define VSS_IRECORD_CMD_STOP				0x00011237
@@ -538,6 +541,15 @@
 
 #define VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE	0x0001136A
 
+struct vss_iplayback_cmd_start_t {
+	uint16_t port_id;
+	/*
+	 * AFE Port ID from which the audio samples are available.
+	 * To use the default AFE pseudo port (0x8005), set this value to
+	 * #VSS_IPLAYBACK_PORT_ID_DEFAULT.
+	 */
+}  __packed;
+
 struct vss_irecord_cmd_start_t {
 	uint32_t rx_tap_point;
 	/* Tap point to use on the Rx path. Supported values are:
@@ -858,6 +870,11 @@
 	struct vss_irecord_cmd_start_t rec_mode;
 } __packed;
 
+struct cvs_start_playback_cmd {
+	struct apr_hdr hdr;
+	struct vss_iplayback_cmd_start_t playback_mode;
+} __packed;
+
 struct cvs_dec_buffer_ready_cmd {
 	struct apr_hdr hdr;
 } __packed;