Merge "mmc: msm sdcc: Enabling the "Cache Ctrl" feautre"
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index 3ee63c0..717dd8c 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -11,11 +11,10 @@
 KERNEL_MODULES_OUT := $(TARGET_OUT)/lib/modules
 KERNEL_IMG=$(KERNEL_OUT)/arch/arm/boot/Image
 
-MSM_ARCH ?= $(shell $(PERL) -e 'while (<>) {$$a = $$1 if /CONFIG_ARCH_((?:MSM|QSD)[a-zA-Z0-9]+)=y/; $$r = $$1 if /CONFIG_MSM_SOC_REV_(?!NONE)(\w+)=y/;} print lc("$$a$$r\n");' $(KERNEL_CONFIG))
+DTS_NAMES ?= $(shell $(PERL) -e 'while (<>) {$$a = $$1 if /CONFIG_ARCH_((?:MSM|QSD)[a-zA-Z0-9]+)=y/; $$r = $$1 if /CONFIG_MSM_SOC_REV_(?!NONE)(\w+)=y/; $$arch = $$arch.lc("$$a$$r ") if /CONFIG_ARCH_((?:MSM|QSD)[a-zA-Z0-9]+)=y/} print $$arch;' $(KERNEL_CONFIG))
 KERNEL_USE_OF ?= $(shell $(PERL) -e '$$of = "n"; while (<>) { if (/CONFIG_USE_OF=y/) { $$of = "y"; break; } } print $$of;' kernel/arch/arm/configs/$(KERNEL_DEFCONFIG))
 
 ifeq "$(KERNEL_USE_OF)" "y"
-DTS_NAME ?= $(MSM_ARCH)
 DTS_FILES = $(wildcard $(TOP)/kernel/arch/arm/boot/dts/$(DTS_NAME)*.dts)
 DTS_FILE = $(lastword $(subst /, ,$(1)))
 DTB_FILE = $(addprefix $(KERNEL_OUT)/arch/arm/boot/,$(patsubst %.dts,%.dtb,$(call DTS_FILE,$(1))))
@@ -25,9 +24,10 @@
 
 define append-dtb
 mkdir -p $(KERNEL_OUT)/arch/arm/boot;\
-$(foreach d, $(DTS_FILES), \
-   $(DTC) -p 1024 -O dtb -o $(call DTB_FILE,$(d)) $(d); \
-   cat $(KERNEL_ZIMG) $(call DTB_FILE,$(d)) > $(call ZIMG_FILE,$(d));)
+$(foreach DTS_NAME, $(DTS_NAMES), \
+   $(foreach d, $(DTS_FILES), \
+      $(DTC) -p 1024 -O dtb -o $(call DTB_FILE,$(d)) $(d); \
+      cat $(KERNEL_ZIMG) $(call DTB_FILE,$(d)) > $(call ZIMG_FILE,$(d));))
 endef
 else
 
diff --git a/Documentation/ABI/testing/sysfs-bus-msm_subsys b/Documentation/ABI/testing/sysfs-bus-msm_subsys
new file mode 100644
index 0000000..fcfb1d4
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-msm_subsys
@@ -0,0 +1,18 @@
+What:		/sys/bus/msm_subsys/devices/.../name
+Date:		July 2012
+Contact:	Stephen Boyd <sboyd@codeaurora.org>
+Description:
+		Shows the name of the subsystem.
+
+What:		/sys/bus/msm_subsys/devices/.../state
+Date:		July 2012
+Contact:	Stephen Boyd <sboyd@codeaurora.org>
+Description:
+		Shows the state state of a subsystem. Current states
+		supported are:
+
+			OFFLINE - subsystem is offline
+			ONLINE  - subsystem is online
+
+		This file supports poll(3) to detect when a subsystem changes
+		state. Use POLLPRI to detect state changes.
diff --git a/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt b/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt
new file mode 100644
index 0000000..01301be
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt
@@ -0,0 +1,18 @@
+* MSM PC Debug Counters
+
+MSM PC debug counter reserves 16 registers in the IMEM memory space which
+maintains a count on the state of power collapse on each core. This count
+will be useful to debug the power collapse state on each core.
+
+The required nodes for MSM PC Debug Counters are:
+
+- compatible: "qcom,pc-cntr"
+- reg: physical IMEM address reserved for PC counters
+
+Example:
+
+qcom,pc-cntr@fe800000 {
+		compatible = "qcom,pc-cntr";
+		reg = <0xfe800664 0x40>;
+	};
+
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
new file mode 100644
index 0000000..1ec3081
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
@@ -0,0 +1,34 @@
+MSM Bus Scaling Driver
+
+The msm bus scaling driver provides the ability to configure
+bus performance parameters across the entire chip-set.
+Various clients use MSM scaling APIs to request bandwidth
+between multiple master-slave pairs. The bus driver then finds
+the optimal path between the master and the slave, and aggregates
+the bandwidth and clock requests for all master-slave pairs on
+that path, and programs hardware accordingly.
+
+The device-tree data required for bus-scaling can be embedded within
+the clients' device nodes. The clients can register with the bus driver
+using the following properties:
+
+- qcom,msm_bus,name:		String representing the client-name
+- qcom,msm_bus,num_cases:	Total number of usecases
+- qcom,msm_bus,active_only:	Context flag for requests in active or
+				dual (active & sleep) contex
+- qcom,msm_bus,num_paths:	Total number of master-slave pairs
+- qcom,msm_bus,vectors:		Arrays of unsigned integers representing:
+				master-id, slave-id, arbitrated bandwidth,
+				instantaneous bandwidth
+
+Example:
+
+	qcom,msm_bus,name = "client-name";
+	qcom,msm_bus,num_cases = <3>;
+	qcom,msm_bus,active_only = <0>;
+	qcom,msm_bus,num_paths = <2>;
+	qcom,msm_bus,vectors =
+			<22 512 0 0>, <26 512 0 0>,
+			<22 512 320000 320000000>, <26 512 3200000 320000000>,
+			<22 512 160000 160000000>, <26 512 1600000 160000000>;
+
diff --git a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
index 2ba7341..d7d3ec2 100644
--- a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
+++ b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
@@ -40,9 +40,10 @@
 			Select from the following unsigned int.
 			0 : Default scaling to convert raw adc code to voltage.
 			1 : Conversion to temperature based on btm parameters.
-			2 : Returns result in milli degree's Centigrade.
+			2 : Returns result in degC for 100k pull-up.
 			3 : Returns current across 0.1 ohm resistor.
 			4 : Returns XO thermistor voltage in degree's Centigrade.
+			5 : Returns result in degC for 150k pull-up.
 - qcom,hw-settle-time : Settling period for the channel before ADC read.
 			Select from the following unsigned int.
 			0 : 0us
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 75916e5..6b03fab 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -1,5 +1,6 @@
 * Qualcomm MSM CCI
 
+[First level nodes]
 Required properties:
 - cell-index: cci hardware core index
 - compatible :
@@ -11,6 +12,102 @@
 - interrupt-names : should specify relevant names to each interrupts
   property defined.
 
+[Second level nodes]
+* Qualcomm MSM Sensor
+
+MSM sensor node contains properties of camera sensor
+
+Required properties:
+- compatible : should be "qcom" followed by sensor name
+    - "qcom,s5k3l1yx"
+- reg : should contain i2c slave address of the camera sensor and
+    length of data field which is 0x0
+- qcom,csi-if : should contain number of csid cores required at the receiver
+    side
+    - 1 for 2D sensor
+    - 2 for 3D sensor
+- qcom,csid-core : should contain csid core instance that will used to receive
+    sensor data
+    - 0, 1, 2, 3
+- qcom,is-vpe : should be enabled if VPE module is required for post processing
+    of this sensor
+    - 1 if required, 0 otherwise
+- qcom,sensor-name : should contain unique sensor name to differentiate from
+    other sensor
+    - "s5k3l1yx"
+- cam_vdig-supply : should contain regulator from which digital voltage is
+    supplied
+- cam_vana-supply : should contain regulator from which analog voltage is
+    supplied
+- cam_vio-supply : should contain regulator from which IO voltage is supplied
+- qcom,cam-vreg-name : should contain names of all regulators needed by this
+    sensor
+    - "cam_vdig", "cam_vana", "cam_vio", "cam_vaf"
+- qcom,cam-vreg-type : should contain regulator type for regulators mentioned in
+    qcom,cam-vreg-name property (in the same order)
+    - 0 for LDO and 1 for LVS
+- qcom,cam-vreg-min-voltage : should contain minimum voltage level for
+    regulators mentioned in qcom,cam-vreg-name property (in the same order)
+- qcom,cam-vreg-max-voltage : should contain maximum voltage level for
+    regulators mentioned in qcom,cam-vreg-name property (in the same order)
+- qcom,cam-vreg-op-mode : should contain optimum voltage level for regulators
+    mentioned in qcom,cam-vreg-name property (in the same order)
+- qcom,camera-type : should contain sensor type
+    - 0 -> back camera 2D
+    - 1 -> front camera 2D
+    - 2 -> back camera 3D
+    - 3 -> back camera int 3D
+- qcom,sensor-type : should contain format of data that sensor streams
+    - 0 -> bayer format
+    - 1 -> yuv format
+
+Optional properties:
+- qcom,flash-type : should contain flash type if flash is supported for this
+    sensor
+    - 0 if flash is not supported, 1 if flash is supported
+- qcom,mount-angle : should contain the physical mount angle of the sensor on
+    the target
+    - 0, 90, 180, 360
+- qcom,gpio-no-mux : should contain field to indicate whether gpio mux table is
+    available
+    - 1 if gpio mux is not available, 0 otherwise
+- cam_vaf-supply : should contain regulator from which AF voltage is supplied
+- gpios : should contain phandle to gpio controller node and array of
+    #gpio-cells specifying specific gpio (controller specific)
+- qcom,gpio-common-tbl-num : should contain index to gpios shared between
+    different sensors
+- qcom,gpio-common-tbl-flags : should contain direction of gpios present in
+    qcom,gpio-common-tbl-num property (in the same order)
+- qcom,gpio-common-tbl-label : should contain name of gpios present in
+    qcom,gpio-common-tbl-num property (in the same order)
+- qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
+- qcom,gpio-req-tbl-flags : should contain direction of gpios present in
+    qcom,gpio-req-tbl-num property (in the same order)
+- qcom,gpio-req-tbl-label : should contain name of gpios present in
+    qcom,gpio-req-tbl-num property (in the same order)
+- qcom,gpio-set-tbl-num : should contain index of gpios that need to be
+    configured by msm
+- qcom,gpio-set-tbl-flags : should contain value to be configured for the gpios
+    present in qcom,gpio-set-tbl-num property (in the same order)
+- qcom,gpio-set-tbl-delay : should contain amount of delay after configuring
+    gpios as specified in gpio_set_tbl_flags property (in the same order)
+- qcom,csi-lane-assign : should contain lane assignment value to map CSIPHY
+    lanes to CSID lanes
+    - 0x4320
+- qcom,csi-lane-mask : should contain lane mask that specifies CSIPHY lanes to
+    be enabled
+- qcom,csi-phy-sel : should contain CSIPHY core instance from which CSID should
+    receive data
+- qcom,actuator-cam-name : should contain actuator cam name associated with
+    this sensor
+    - If actuator does not exist, this property should not be initialized
+    - If actuator exist, this field should indicate the index of actuator to
+      be used
+- qcom,actuator-vcm-pwd : should contain the gpio pin of vcm power to be enabled
+    for actuator
+- qcom,actuator-vcm-enable : should contain value to be set for actuator vcm
+    gpio
+
 Example:
 
    qcom,cci@0xfda0c000 {
@@ -20,4 +117,43 @@
        reg-names = "cci";
        interrupts = <0 50 0>;
        interrupt-names = "cci";
+       qcom,s5k3l1yx@6e {
+               compatible = "qcom,s5k3l1yx";
+               reg = <0x6e 0x0>;
+               qcom,csi-if = <1>;
+               qcom,csid-core = <0>;
+               qcom,is-vpe = <1>;
+               qcom,flash-type = <0>;
+               qcom,mount-angle = <90>;
+               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_vana", "cam_vio", "cam_vaf";
+               qcom,cam-vreg-type = <0 0 1 0>;
+               qcom,cam-vreg-min-voltage = <1225000 2850000 0 3000000>;
+               qcom,cam-vreg-max-voltage = <1225000 2850000 0 3000000>;
+               qcom,cam-vreg-op-mode = <105000 80000 0 100000>;
+               qcom,gpio-no-mux = <0>;
+               gpios = <&msmgpio 15 0>,
+                       <&msmgpio 19 0>,
+                       <&msmgpio 20 0>,
+                       <&msmgpio 90 0>;
+               qcom,gpio-common-tbl-num = <0 1 2>;
+               qcom,gpio-common-tbl-flags = <1 1 1>;
+               qcom,gpio-common-tbl-label = "CAMIF_MCLK", "CAMIF_I2C_DATA",
+                                            "CAMIF_I2C_CLK";
+               qcom,gpio-req-tbl-num = <3>;
+               qcom,gpio-req-tbl-flags = <0>;
+               qcom,gpio-req-tbl-label = "CAM_RESET1";
+               qcom,gpio-set-tbl-num = <3 3>;
+               qcom,gpio-set-tbl-flags = <0 2>;
+               qcom,gpio-set-tbl-delay = <1000 4000>;
+               qcom,csi-lane-assign = <0x4320>;
+               qcom,csi-lane-mask = <0x1F>;
+               qcom,csi-phy-sel = <0>;
+               qcom,camera-type = <0>;
+               qcom,sensor-type = <0>;
+       };
    };
diff --git a/Documentation/devicetree/bindings/media/video/msm-sensor.txt b/Documentation/devicetree/bindings/media/video/msm-sensor.txt
deleted file mode 100644
index e242d51..0000000
--- a/Documentation/devicetree/bindings/media/video/msm-sensor.txt
+++ /dev/null
@@ -1,137 +0,0 @@
-* Qualcomm MSM Sensor
-
-MSM sensor node contains properties of camera sensor
-
-Required properties:
-- compatible : should be "qcom" followed by sensor name
-    - "qcom,s5k3l1yx"
-- reg : should contain i2c slave address of the camera sensor and
-    length of data field which is 0x0
-- qcom,csi-if : should contain number of csid cores required at the receiver
-    side
-    - 1 for 2D sensor
-    - 2 for 3D sensor
-- qcom,csid-core : should contain csid core instance that will used to receive
-    sensor data
-    - 0, 1, 2, 3
-- qcom,is-vpe : should be enabled if VPE module is required for post processing
-    of this sensor
-    - 1 if required, 0 otherwise
-- qcom,sensor-name : should contain unique sensor name to differentiate from
-    other sensor
-    - "s5k3l1yx"
-- cam_vdig-supply : should contain regulator from which digital voltage is
-    supplied
-- cam_vana-supply : should contain regulator from which analog voltage is
-    supplied
-- cam_vio-supply : should contain regulator from which IO voltage is supplied
-- qcom,cam-vreg-name : should contain names of all regulators needed by this
-    sensor
-    - "cam_vdig", "cam_vana", "cam_vio", "cam_vaf"
-- qcom,cam-vreg-type : should contain regulator type for regulators mentioned in
-    qcom,cam-vreg-name property (in the same order)
-    - 0 for LDO and 1 for LVS
-- qcom,cam-vreg-min-voltage : should contain minimum voltage level for
-    regulators mentioned in qcom,cam-vreg-name property (in the same order)
-- qcom,cam-vreg-max-voltage : should contain maximum voltage level for
-    regulators mentioned in qcom,cam-vreg-name property (in the same order)
-- qcom,cam-vreg-op-mode : should contain optimum voltage level for regulators
-    mentioned in qcom,cam-vreg-name property (in the same order)
-- qcom,camera-type : should contain sensor type
-    - 0 -> back camera 2D
-    - 1 -> front camera 2D
-    - 2 -> back camera 3D
-    - 3 -> back camera int 3D
-- qcom,sensor-type : should contain format of data that sensor streams
-    - 0 -> bayer format
-    - 1 -> yuv format
-
-Optional properties:
-- qcom,flash-type : should contain flash type if flash is supported for this
-    sensor
-    - 0 if flash is not supported, 1 if flash is supported
-- qcom,mount-angle : should contain the physical mount angle of the sensor on
-    the target
-    - 0, 90, 180, 360
-- qcom,gpio-no-mux : should contain field to indicate whether gpio mux table is
-    available
-    - 1 if gpio mux is not available, 0 otherwise
-- cam_vaf-supply : should contain regulator from which AF voltage is supplied
-- gpios : should contain phandle to gpio controller node and array of
-    #gpio-cells specifying specific gpio (controller specific)
-- qcom,gpio-common-tbl-num : should contain index to gpios shared between
-    different sensors
-- qcom,gpio-common-tbl-flags : should contain direction of gpios present in
-    qcom,gpio-common-tbl-num property (in the same order)
-- qcom,gpio-common-tbl-label : should contain name of gpios present in
-    qcom,gpio-common-tbl-num property (in the same order)
-- qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
-- qcom,gpio-req-tbl-flags : should contain direction of gpios present in
-    qcom,gpio-req-tbl-num property (in the same order)
-- qcom,gpio-req-tbl-label : should contain name of gpios present in
-    qcom,gpio-req-tbl-num property (in the same order)
-- qcom,gpio-set-tbl-num : should contain index of gpios that need to be
-    configured by msm
-- qcom,gpio-set-tbl-flags : should contain value to be configured for the gpios
-    present in qcom,gpio-set-tbl-num property (in the same order)
-- qcom,gpio-set-tbl-delay : should contain amount of delay after configuring
-    gpios as specified in gpio_set_tbl_flags property (in the same order)
-- qcom,csi-lane-assign : should contain lane assignment value to map CSIPHY
-    lanes to CSID lanes
-    - 0x4320
-- qcom,csi-lane-mask : should contain lane mask that specifies CSIPHY lanes to
-    be enabled
-- qcom,csi-phy-sel : should contain CSIPHY core instance from which CSID should
-    receive data
-- qcom,actuator-cam-name : should contain actuator cam name associated with
-    this sensor
-    - If actuator does not exist, this property should not be initialized
-    - If actuator exist, this field should indicate the index of actuator to
-      be used
-- qcom,actuator-vcm-pwd : should contain the gpio pin of vcm power to be enabled
-    for actuator
-- qcom,actuator-vcm-enable : should contain value to be set for actuator vcm
-    gpio
-
-Example:
-
-qcom,s5k3l1yx@6e {
-        compatible = "qcom,s5k3l1yx";
-        reg = <0x6e 0x0>;
-        qcom,csi-if = <1>;
-        qcom,csid-core = <0>;
-        qcom,is-vpe = <1>;
-        qcom,flash-type = <0>;
-        qcom,mount-angle = <90>;
-        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_vana", "cam_vio", "cam_vaf";
-        qcom,cam-vreg-type = <0 0 1 0>;
-        qcom,cam-vreg-min-voltage = <1225000 2850000 0 3000000>;
-        qcom,cam-vreg-max-voltage = <1225000 2850000 0 3000000>;
-        qcom,cam-vreg-op-mode = <105000 80000 0 100000>;
-        qcom,gpio-no-mux = <0>;
-        gpios = <&msmgpio 15 0>,
-                <&msmgpio 19 0>,
-                <&msmgpio 20 0>,
-                <&msmgpio 90 0>;
-        qcom,gpio-common-tbl-num = <0 1 2>;
-        qcom,gpio-common-tbl-flags = <1 1 1>;
-        qcom,gpio-common-tbl-label = "CAMIF_MCLK", "CAMIF_I2C_DATA",
-                "CAMIF_I2C_CLK";
-        qcom,gpio-req-tbl-num = <3>;
-        qcom,gpio-req-tbl-flags = <0>;
-        qcom,gpio-req-tbl-label = "CAM_RESET1";
-        qcom,gpio-set-tbl-num = <3 3>;
-        qcom,gpio-set-tbl-flags = <0 2>;
-        qcom,gpio-set-tbl-delay = <1000 4000>;
-        qcom,csi-lane-assign = <0x4320>;
-        qcom,csi-lane-mask = <0x1F>;
-        qcom,csi-phy-sel = <0>;
-        qcom,camera-type = <0>;
-        qcom,sensor-type = <0>;
-};
-
diff --git a/Documentation/devicetree/bindings/mtd/msm_qpic_nand.txt b/Documentation/devicetree/bindings/mtd/msm_qpic_nand.txt
index bddbbae..8cef7f0 100644
--- a/Documentation/devicetree/bindings/mtd/msm_qpic_nand.txt
+++ b/Documentation/devicetree/bindings/mtd/msm_qpic_nand.txt
@@ -38,14 +38,15 @@
 	       #size-cells = <1>;
                partition@0 {
                        label = "boot";
-                       reg = <0x00000000 0x1000>;
+                       reg = <0x0 0x1000>;
+		       read-only;
                };
-               partition@00020000 {
+               partition@20000 {
                        label = "userdata";
-                       reg = <0x00020000 0x1000>;
+                       reg = <0x20000 0x1000>;
                };
-               partition@00040000 {
+               partition@40000 {
                        label = "system";
-                       reg = <0x00040000 0x1000>;
+                       reg = <0x40000 0x1000>;
                };
        };
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index f082a0f..0eb186e 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -202,3 +202,55 @@
 		qcom,msm-ocmem-audio-ib = <471859200>;
 	};
 
+* MSM8974 ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,msm8974-audio-taiko"
+- qcom,model : The user-visible name of this sound card.
+- qcom,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source.
+- qcom,cdc-mclk-gpios : GPIO on which mclk signal is comming.
+- taiko-mclk-clk : phandle to PMIC8941 clkdiv1 node.
+- qcom,taiko-mclk-clk-freq : Taiko mclk Freq in Hz. currently only 9600000Hz
+				is supported.
+
+Example:
+
+sound {
+	compatible = "qcom,msm8974-audio-taiko";
+	qcom,model = "msm8974-taiko-snd-card";
+
+	qcom,audio-routing =
+		"RX_BIAS", "MCLK",
+		"LDO_H", "MCLK",
+		"HEADPHONE", "LDO_H",
+		"Ext Spk Bottom Pos", "LINEOUT1",
+		"Ext Spk Bottom Neg", "LINEOUT3",
+		"Ext Spk Top Pos", "LINEOUT2",
+		"Ext Spk Top Neg", "LINEOUT4",
+		"AMIC1", "MIC BIAS1 Internal1",
+		"MIC BIAS1 Internal1", "Handset Mic",
+		"AMIC2", "MIC BIAS2 External",
+		"MIC BIAS2 External", "Headset Mic",
+		"AMIC3", "MIC BIAS3 Internal1",
+		"MIC BIAS3 Internal1", "ANCRight Headset Mic",
+		"AMIC4", "MIC BIAS1 Internal2",
+		"MIC BIAS1 Internal2", "ANCLeft Headset Mic",
+		"DMIC1", "MIC BIAS1 External",
+		"MIC BIAS1 External", "Digital Mic1",
+		"DMIC2", "MIC BIAS1 External",
+		"MIC BIAS1 External", "Digital Mic2",
+		"DMIC3", "MIC BIAS3 External",
+		"MIC BIAS3 External", "Digital Mic3",
+		"DMIC4", "MIC BIAS3 External",
+		"MIC BIAS3 External", "Digital Mic4",
+		"DMIC5", "MIC BIAS4 External",
+		"MIC BIAS4 External", "Digital Mic5",
+		"DMIC6", "MIC BIAS4 External",
+		"MIC BIAS4 External", "Digital Mic6";
+
+	qcom,cdc-mclk-gpios = <&pm8941_gpios 15 0>;
+	taiko-mclk-clk = <&pm8941_clkdiv1>;
+	qcom,taiko-mclk-clk-freq = <9600000>;
+};
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 43e87a8..9c2ce6c 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -35,6 +35,13 @@
   0 will be treated as 500mA
 - qcom,hsusb-otg-pclk-src-name: The source of pclk
 - qcom,hsusb-otg-pmic-id-irq: ID, routed to PMIC IRQ number
+- 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
 
 Example HSUSB OTG controller device node :
 	usb@f9690000 {
@@ -51,8 +58,32 @@
 		qcom,hsusb-otg-power-budget = <500>;
 		qcom,hsusb-otg-pclk-src-name = "dfab_usb_clk";
 		qcom,hsusb-otg-pmic-id-irq = <47>
+
+		qcom,msm_bus,name = "usb2";
+		qcom,msm_bus,num_cases = <2>;
+		qcom,msm_bus,active_only = <0>;
+		qcom,msm_bus,num_paths = <1>;
+		qcom,msm_bus,vectors =
+				<87 512 0 0>,
+				<87 512 60000000 960000000>;
 	};
 
+ANDROID USB:
+
+Required properties:
+- compatible: should be "qcom,android-usb"
+
+Optional properties :
+- reg  : offset and length of memory region that is used by driver to
+  update USB PID and serial numbers used by bootloader in DLOAD mode.
+
+Example Android USB device node :
+	android_usb@fc42b0c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfc42b0c8 0xc8>;
+	};
+
+
 BAM:
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index bff3732..9cc9e6e 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -17,6 +17,15 @@
   the MSM USB3.0 core (which also includes the Synopsys DesignWare
   USB3.0 controller)
 
+Optional properties :
+- 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
+
 Example MSM USB3.0 controller device node :
 	usb@f9200000 {
 		compatible = "qcom,dwc-usb3-msm";
@@ -30,4 +39,12 @@
 		HSUSB_1p8-supply = <&pm8941_l6>;
 		HSUSB_3p3-supply = <&pm8941_l24>;
 		qcom,dwc-usb3-msm-dbm-eps = <4>
+
+		qcom,msm_bus,name = "usb3";
+		qcom,msm_bus,num_cases = <2>;
+		qcom,msm_bus,active_only = <0>;
+		qcom,msm_bus,num_paths = <1>;
+		qcom,msm_bus,vectors =
+				<61 512 0 0>,
+				<61 512 240000000 960000000>;
 	};
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
new file mode 100644
index 0000000..e394b56
--- /dev/null
+++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
@@ -0,0 +1,45 @@
+* Qualcomm WCNSS Platform Driver
+
+WCNSS driver is the platform driver. It is used for performing the cold
+boot-up of the wireless device. It is responsible for adjusting
+the necessary I/O rails and enabling appropriate gpios for wireless
+connectivity subsystem.
+
+Required properties:
+- compatible: "wcnss_wlan"
+- reg: offset and length of the register set for the device. The pair
+  corresponds to PRONTO.
+- interupts: Pronto to Apps interrupts for tx done and rx pending.
+- qcom,pronto-vddmx-supply: regulator to supply pronto pll.
+- qcom,pronto-vddcx-supply: regulator to supply WLAN/BT/FM digital module.
+- qcom,pronto-vddpx-supply: regulator to supply WLAN DAC.
+- qcom,iris-vddxo-supply  : regulator to supply RF XO.
+- qcom,iris-vddrfa-supply : regulator to supply RFA digital.
+- qcom,iris-vddpa-supply  : regulator to supply RF PA.
+- qcom,iris-vdddig-supply : regulator to supply RF digital(BT/FM).
+- gpios: gpio numbers to configure 5-wire interface of WLAN connectivity
+- qcom,has_48mhz_xo: boolean flag to determine the usage of 24MHz XO from RF
+- qcom,has_pronto_hw: boolean flag to determine the revId of the WLAN subsystem
+
+Example:
+
+    qcom,wcnss-wlan@fb000000 {
+        compatible = "qcom,wcnss_wlan";
+        reg = <0xfb000000 0x280000>;
+        reg-names = "wcnss_mmio";
+        interrupts = <0 145 0 0 146 0>;
+        interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
+
+        qcom,pronto-vddmx-supply = <&pm8841_s1>;
+        qcom,pronto-vddcx-supply = <&pm8841_s2>;
+        qcom,pronto-vddpx-supply = <&pm8941_s3>;
+        qcom,iris-vddxo-supply = <&pm8941_l6>;
+        qcom,iris-vddrfa-supply = <&pm8941_l11>;
+        qcom,iris-vddpa-supply = <&pm8941_l19>;
+        qcom,iris-vdddig-supply = <&pm8941_l3>;
+
+        gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>,
+                <&msmgpio 39 0>, <&msmgpio 40 0>;
+        qcom,has_48mhz_xo;
+        qcom,has_pronto_hw;
+    };
diff --git a/arch/arm/boot/dts/mpq8092-sim.dts b/arch/arm/boot/dts/mpq8092-sim.dts
new file mode 100644
index 0000000..f73abe7
--- /dev/null
+++ b/arch/arm/boot/dts/mpq8092-sim.dts
@@ -0,0 +1,49 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MPQ8092 Simulator";
+	compatible = "qcom,mpq8092-sim", "qcom,mpq8092";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@f9000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0xf9000000 0x1000>,
+		<0xf9002000 0x1000>;
+	};
+
+	timer {
+		compatible = "qcom,msm-qtimer", "arm,armv7-timer";
+		interrupts = <1 2 0>, <1 3 0>;
+		clock-frequency = <19200000>;
+	};
+
+	serial@f991f000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf991f000 0x1000>;
+		interrupts = <0 109 0>;
+	};
+
+	serial@f995e000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf995e000 0x1000>;
+		interrupts = <0 114 0>;
+	};
+
+};
+
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 6347b51..0f5fd1c 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -378,7 +378,18 @@
 				label = "usb_in";
 				qcom,channel-num = <0>;
 				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <20>;
+				qcom,pre-div-channel-scaling = <4>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@1 {
+				label = "dc_in";
+				qcom,channel-num = <1>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <4>;
 				qcom,calibration-type = "absolute";
 				qcom,scale-function = <0>;
 				qcom,hw-settle-time = <0>;
@@ -389,6 +400,28 @@
 				label = "vchg_sns";
 				qcom,channel-num = <2>;
 				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <3>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@3 {
+				label = "spare1";
+				qcom,channel-num = <3>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <6>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@4 {
+				label = "spare2";
+				qcom,channel-num = <4>;
+				qcom,decimation = <0>;
 				qcom,pre-div-channel-scaling = <6>;
 				qcom,calibration-type = "absolute";
 				qcom,scale-function = <0>;
@@ -400,7 +433,7 @@
 				label = "vcoin";
 				qcom,channel-num = <5>;
 				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <3>;
+				qcom,pre-div-channel-scaling = <1>;
 				qcom,calibration-type = "absolute";
 				qcom,scale-function = <0>;
 				qcom,hw-settle-time = <0>;
@@ -411,7 +444,7 @@
 				label = "vbat_sns";
 				qcom,channel-num = <6>;
 				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <3>;
+				qcom,pre-div-channel-scaling = <1>;
 				qcom,calibration-type = "absolute";
 				qcom,scale-function = <0>;
 				qcom,hw-settle-time = <0>;
@@ -422,18 +455,29 @@
 				label = "vph_pwr";
 				qcom,channel-num = <7>;
 				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <3>;
+				qcom,pre-div-channel-scaling = <1>;
 				qcom,calibration-type = "absolute";
 				qcom,scale-function = <0>;
 				qcom,hw-settle-time = <0>;
 				qcom,fast-avg-setup = <0>;
 			};
 
+			chan@8 {
+				label = "die_temp";
+				qcom,channel-num = <8>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <3>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
 			chan@9 {
 				label = "ref_625mv";
 				qcom,channel-num = <9>;
 				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
+				qcom,pre-div-channel-scaling = <0>;
 				qcom,calibration-type = "absolute";
 				qcom,scale-function = <0>;
 				qcom,hw-settle-time = <0>;
@@ -441,15 +485,103 @@
 			};
 
 			chan@10 {
-				label = "ref_1125v";
+				label = "ref_1250v";
 				qcom,channel-num = <10>;
 				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
+				qcom,pre-div-channel-scaling = <0>;
 				qcom,calibration-type = "absolute";
 				qcom,scale-function = <0>;
 				qcom,hw-settle-time = <0>;
 				qcom,fast-avg-setup = <0>;
 			};
+
+			chan@48 {
+				label = "batt_therm";
+				qcom,channel-num = <48>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <1>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@49 {
+				label = "batt_id";
+				qcom,channel-num = <49>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@178 {
+				label = "xo_therm_pu2";
+				qcom,channel-num = <178>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <4>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@179 {
+				label = "msm_therm";
+				qcom,channel-num = <179>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@180 {
+				label = "emmc_therm";
+				qcom,channel-num = <180>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@181 {
+				label = "pa_therm1";
+				qcom,channel-num = <181>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@183 {
+				label = "pa_therm2";
+				qcom,channel-num = <183>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@184 {
+				label = "quiet_therm";
+				qcom,channel-num = <184>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
 		};
 
 		iadc@3600 {
diff --git a/arch/arm/boot/dts/msm8226-camera.dtsi b/arch/arm/boot/dts/msm8226-camera.dtsi
new file mode 100644
index 0000000..2a9fdf2
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-camera.dtsi
@@ -0,0 +1,18 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	qcom,cam_server {
+		compatible = "qcom,cam_server";
+		reg = <0xfd8C0000 0x10000>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226-ion.dtsi b/arch/arm/boot/dts/msm8226-ion.dtsi
new file mode 100644
index 0000000..beaffe5
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-ion.dtsi
@@ -0,0 +1,23 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	qcom,ion {
+		compatible = "qcom,msm-ion";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ion-heap@30 { /* SYSTEM HEAP */
+			reg = <30>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
new file mode 100644
index 0000000..4330849
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -0,0 +1,61 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+/include/ "msm8226-ion.dtsi"
+/include/ "msm8226-camera.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8226 Simulator";
+	compatible = "qcom,msm8226-sim", "qcom,msm8226";
+	qcom,msm-id = <145 1 0>;
+	interrupt-parent = <&intc>;
+
+	chosen {
+		bootargs ="root=/dev/ram rw init=/init console=ttyHSL0,115200n8 initrd=0x00000000,0x00000000 mem=512M@0x00000000";
+	};
+
+	intc: interrupt-controller@f9000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0xF9000000 0x1000>,
+		      <0xF9002000 0x1000>;
+	};
+
+	msmgpio: gpio@fd510000 {
+		compatible = "qcom,msm-gpio";
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd510000 0x4000>;
+		#gpio-cells = <2>;
+	};
+
+	timer {
+		compatible = "qcom,msm-qtimer", "arm,armv7-timer";
+		interrupts = <1 2 0 1 3 0>;
+		clock-frequency = <19200000>;
+	};
+
+	serial@f991f000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf991f000 0x1000>;
+		interrupts = <0 109 0>;
+	};
+
+	serial@f995e000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf995e000 0x1000>;
+		interrupts = <0 114 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index cf4f098..c92188a 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -125,6 +125,7 @@
 		reg-names = "jpeg";
 		interrupts = <0 59 0>;
 		interrupt-names = "jpeg";
+                vdd-supply = <&gdsc_jpeg>;
 	};
 
 	qcom,jpeg@fda20000 {
@@ -134,6 +135,7 @@
 		reg-names = "jpeg";
 		interrupts = <0 60 0>;
 		interrupt-names = "jpeg";
+		vdd-supply = <&gdsc_jpeg>;
 	};
 
 	qcom,jpeg@fda24000 {
@@ -143,6 +145,7 @@
 		reg-names = "jpeg";
 		interrupts = <0 61 0>;
 		interrupt-names = "jpeg";
+		vdd-supply = <&gdsc_jpeg>;
 	};
 
 	qcom,irqrouter@fda00000 {
@@ -251,7 +254,7 @@
 			qcom,csi-lane-assign = <0x4320>;
 			qcom,csi-lane-mask = <0x7>;
 			qcom,csi-phy-sel = <1>;
-			qcom,camera-type = <0>;
+			qcom,camera-type = <1>;
 			qcom,sensor-type = <0>;
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index e764e01..7aeb33c 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -18,7 +18,7 @@
 / {
 	model = "Qualcomm MSM 8974 CDP";
 	compatible = "qcom,msm8974-cdp", "qcom,msm8974";
-	qcom,msm-id = <126 1 0>, <126 8 0>;
+	qcom,msm-id = <126 1 0>;
 
 	serial@f991e000 {
 		status = "ok";
@@ -29,6 +29,130 @@
 			status = "ok";
 		};
 	};
+
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l18>;
+			vcc_i2c-supply = <&pm8941_lvs1>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0  0 760 1424>;
+			atmel,display-coords = <0 0 720 1280>;
+			atmel,i2c-pull-up = <1>;
+			atmel,cfg_1 {
+				atmel,family-id = <0x82>;
+				atmel,variant-id = <0x19>;
+				atmel,version = <0x10>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 6, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 38, Instance = 0 */
+					15 00 02 10 08 0C 00 00
+					/* Object 7, Instance = 0 */
+					FF FF 32 03
+					/* Object 8, Instance = 0 */
+					0F 00 0A 0A 00 00 0A 00 00 00
+					/* Object 9, Instance = 0 */
+					83 00 00 18 0E 00 70 32 02 01
+					00 03 01 01 05 0A 0A 0A 90 05
+					F8 02 00 00 0F 0F 00 00 48 2D
+					07 0C 00 00 00 00
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					00 00
+					/* Object 19, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 23, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 00 00 00 00
+					/* Object 42, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					/* Object 46, Instance = 0 */
+					00 00 10 10 00 00 03 00 00 01
+					/* Object 47, Instance = 0 */
+					08 0A 28 0A 02 0A 00 8C 00 20
+					00 00 00
+					/* Object 55, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 56, Instance = 0 */
+					03 00 01 18 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00
+					/* Object 57, Instance = 0 */
+					00 00 00
+					/* Object 61, Instance = 0 */
+					00 00 00 00 00
+					/* Object 61, Instance = 1 */
+					00 00 00 00 00
+					/* Object 62, Instance = 0 */
+					7F 03 00 16 00 00 00 00 00 00
+					04 08 10 18 05 00 0A 05 05 50
+					14 19 34 1A 64 00 00 04 40 00
+					00 00 00 00 30 32 02 00 01 00
+					05 00 00 00 00 00 00 00 00 00
+					00 00 0C 00
+					];
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&pm8941_gpios 3 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&pm8941_gpios 4 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm8941_gpios 5 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	spi@f9923000 {
+		ethernet-switch@2 {
+			compatible = "micrel,ks8851";
+			reg = <2>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <94 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&pm8941_mpps 6 0>;
+			vdd-io-supply = <&spi_eth_vreg>;
+			vdd-phy-supply = <&spi_eth_vreg>;
+		};
+	};
 };
 
 &sdcc2 {
@@ -42,4 +166,5 @@
 			2 &msmgpio 62 0x3>;
 	interrupt-names = "core_irq", "bam_irq", "status_irq";
 	cd-gpios = <&msmgpio 62 0x1>;
+	wp-gpios = <&pm8941_gpios 29 0x1>;
 };
diff --git a/arch/arm/boot/dts/msm8974-clock.dtsi b/arch/arm/boot/dts/msm8974-clock.dtsi
index bdc5d9b..043346f 100644
--- a/arch/arm/boot/dts/msm8974-clock.dtsi
+++ b/arch/arm/boot/dts/msm8974-clock.dtsi
@@ -15,6 +15,7 @@
 	qcom,pm8941@0 {
 
 		pm8941_clkdiv1: clkdiv@5b00 {
+			qcom,cxo-div = <2>;
 		};
 
 		pm8941_clkdiv2: clkdiv@5c00 {
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index c28ef9e..0b09bc8 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -13,12 +13,15 @@
 / {
 	tmc_etr: tmc@fc322000 {
 		compatible = "arm,coresight-tmc";
-		reg = <0xfc322000 0x1000>;
+		reg = <0xfc322000 0x1000>,
+		      <0xfc37c000 0x3000>;
+
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
 
 		coresight-id = <0>;
 		coresight-name = "coresight-tmc-etr";
 		coresight-nr-inports = <1>;
-		coresight-default-sink;
 	};
 
 	tpiu: tpiu@fc318000 {
@@ -52,6 +55,7 @@
 		coresight-outports = <0>;
 		coresight-child-list = <&replicator>;
 		coresight-child-ports = <0>;
+		coresight-default-sink;
 	};
 
 	funnel_merg: funnel@fc31b000 {
@@ -174,4 +178,13 @@
 		coresight-child-list = <&funnel_kpss>;
 		coresight-child-ports = <3>;
 	};
+
+	csr: csr@fc302000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0xfc302000 0x1000>;
+
+		coresight-id = <14>;
+		coresight-name = "coresight-csr";
+		coresight-nr-inports = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8974-gpio.dtsi b/arch/arm/boot/dts/msm8974-gpio.dtsi
index b36859e..e7c742c 100644
--- a/arch/arm/boot/dts/msm8974-gpio.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpio.dtsi
@@ -86,6 +86,13 @@
 
 			gpio@ce00 {
 				status = "ok";
+				qcom,mode = <1>;
+				qcom,output-type = <0>;
+				qcom,pull = <5>;
+				qcom,vin-sel = <2>;
+				qcom,out-strength = <3>;
+				qcom,src-select = <2>;
+				qcom,master-en = <1>;
 			};
 
 			gpio@cf00 {
@@ -145,7 +152,9 @@
 			};
 
 			gpio@dc00 {
-				qcom,out-strength = <1>;
+				qcom,pull = <0>; /* set to default pull */
+				qcom,master-en = <1>;
+				qcom,vin-sel = <2>; /* select 1.8 V source */
 				status = "ok";
 			};
 
@@ -215,6 +224,12 @@
 
 			mpp@a500 {
 				status = "ok";
+				/* SPI_ETH_RST config */
+				qcom,mode = <1>; /* DIG_OUT */
+				qcom,output-type = <0>; /* CMOS */
+				qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+				qcom,src-select = <0>; /* CONSTANT */
+				qcom,master-en = <1>; /* ENABLE MPP */
 			};
 
 			mpp@a600 {
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index a972d7f..2312b02 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -52,14 +52,14 @@
 
 			qcom,gpu-pwrlevel@0 {
 				reg = <0>;
-				qcom,gpu-freq = <500000000>;
+				qcom,gpu-freq = <450000000>;
 				qcom,bus-freq = <3>;
 				qcom,io-fraction = <0>;
 			};
 
 			qcom,gpu-pwrlevel@1 {
 				reg = <1>;
-				qcom,gpu-freq = <333000000>;
+				qcom,gpu-freq = <300000000>;
 				qcom,bus-freq = <2>;
 				qcom,io-fraction = <33>;
 			};
diff --git a/arch/arm/boot/dts/msm8974-liquid.dts b/arch/arm/boot/dts/msm8974-liquid.dts
new file mode 100644
index 0000000..5de2d43
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-liquid.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974 LIQUID";
+	compatible = "qcom,msm8974-liquid", "qcom,msm8974";
+	qcom,msm-id = <126 9 0>;
+
+	serial@f991e000 {
+		status = "ok";
+	};
+};
+
+
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index dbaa492..344aa7f 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -29,6 +29,30 @@
 		vreg-supply = <&pm8941_l2>;
 	};
 
+	qcom,hdmi_tx@fd922100 {
+		cell-index = <0>;
+		compatible = "qcom,hdmi-tx";
+		reg =	<0xfd922100 0x35C>,
+			<0xfd922500 0x7C>,
+			<0xfc4b8000 0x60F0>;
+		reg-names = "core_physical", "phy_physical", "qfprom_physical";
+
+		hpd-5v-supply = <&pm8941_mvs2>;
+		core-vdda-supply = <&pm8941_l12>;
+		core-vcc-supply = <&pm8941_s3>;
+		qcom,hdmi-tx-supply-names = "hpd-5v", "core-vdda", "core-vcc";
+		qcom,hdmi-tx-supply-type = <1 0 0>;
+		qcom,hdmi-tx-min-voltage-level = <0 1800000 1800000>;
+		qcom,hdmi-tx-max-voltage-level = <0 1800000 1800000>;
+		qcom,hdmi-tx-op-mode = <0 1800000 0>;
+
+		gpios = <&msmgpio 31 0>,
+			<&msmgpio 32 0>,
+			<&msmgpio 33 0>,
+			<&msmgpio 34 0>;
+		qcom,hdmi-tx-gpio-names = "cec-pin", "hpd-ddc-clk", "hpd-ddc-data", "hpd-pin";
+	};
+
 	qcom,mdss_wb_panel {
 		compatible = "qcom,mdss_wb";
 		qcom,mdss_pan_res = <640 480>;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
new file mode 100644
index 0000000..d3e0bc3
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -0,0 +1,169 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974.dtsi"
+/include/ "dsi-panel-toshiba-720p-video.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974 MTP";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974";
+	qcom,msm-id = <126 8 0>;
+
+	serial@f991e000 {
+		status = "ok";
+	};
+
+	qcom,mdss_dsi@fd922800 {
+		qcom,mdss_dsi_toshiba_720p_video {
+			status = "ok";
+		};
+	};
+
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l18>;
+			vcc_i2c-supply = <&pm8941_lvs1>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0  0 760 1424>;
+			atmel,display-coords = <0 0 720 1280>;
+			atmel,i2c-pull-up = <1>;
+			atmel,cfg_1 {
+				atmel,family-id = <0x82>;
+				atmel,variant-id = <0x19>;
+				atmel,version = <0x10>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 6, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 38, Instance = 0 */
+					15 00 02 10 08 0C 00 00
+					/* Object 7, Instance = 0 */
+					FF FF 32 03
+					/* Object 8, Instance = 0 */
+					0F 00 0A 0A 00 00 0A 00 00 00
+					/* Object 9, Instance = 0 */
+					83 00 00 18 0E 00 70 32 02 01
+					00 03 01 01 05 0A 0A 0A 90 05
+					F8 02 00 00 0F 0F 00 00 48 2D
+					07 0C 00 00 00 00
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					00 00
+					/* Object 19, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 23, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 00 00 00 00
+					/* Object 42, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					/* Object 46, Instance = 0 */
+					00 00 10 10 00 00 03 00 00 01
+					/* Object 47, Instance = 0 */
+					08 0A 28 0A 02 0A 00 8C 00 20
+					00 00 00
+					/* Object 55, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 56, Instance = 0 */
+					03 00 01 18 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00
+					/* Object 57, Instance = 0 */
+					00 00 00
+					/* Object 61, Instance = 0 */
+					00 00 00 00 00
+					/* Object 61, Instance = 1 */
+					00 00 00 00 00
+					/* Object 62, Instance = 0 */
+					7F 03 00 16 00 00 00 00 00 00
+					04 08 10 18 05 00 0A 05 05 50
+					14 19 34 1A 64 00 00 04 40 00
+					00 00 00 00 30 32 02 00 01 00
+					05 00 00 00 00 00 00 00 00 00
+					00 00 0C 00
+					];
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&pm8941_gpios 3 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&pm8941_gpios 4 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm8941_gpios 5 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	spi@f9923000 {
+		ethernet-switch@2 {
+			compatible = "micrel,ks8851";
+			reg = <2>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <94 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&pm8941_mpps 6 0>;
+			vdd-io-supply = <&spi_eth_vreg>;
+			vdd-phy-supply = <&spi_eth_vreg>;
+		};
+	};
+};
+
+&sdcc2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdcc2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 220 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "core_irq", "bam_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+};
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 1fd96f9..de9e98c 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -58,6 +58,15 @@
 			status = "okay";
 			compatible = "qcom,rpm-regulator-smd";
 		};
+		pm8841_s1_so: regulator-s1-so {
+			regulator-name = "8841_s1_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <675000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,init-voltage = <675000>;
+			status = "okay";
+			compatible = "qcom,rpm-regulator-smd";
+		};
 	};
 
 	rpm-regulator-smpb2 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 7563576..fe60c83 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -55,11 +55,9 @@
 		vidc-cp-map = <0x1000000 0x40000000>;
 		vidc-ns-map = <0x40000000 0x40000000>;
 		load-freq-tbl = <979200 410000000>,
-				<560145 266670000>,
-				<421161 200000000>,
-				<243000 133330000>,
-				<108000 100000000>,
-				<36000 50000000>;
+			<783360 410000000>,
+			<489600 266670000>,
+			<244800 133330000>;
 	};
 
 	serial@f991f000 {
@@ -93,9 +91,23 @@
 		HSUSB_3p3-supply = <&pm8941_l24>;
 
 		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-phy-init-seq = <0x63 0x81 0xffffffff>;
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <1>;
 		qcom,hsusb-otg-disable-reset;
+
+		qcom,msm_bus,name = "usb2";
+		qcom,msm_bus,num_cases = <2>;
+		qcom,msm_bus,active_only = <0>;
+		qcom,msm_bus,num_paths = <1>;
+		qcom,msm_bus,vectors =
+				<87 512 0 0>,
+				<87 512 60000000 960000000>;
+	};
+
+	android_usb@fc42b0c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfc42b0c8 0xc8>;
 	};
 
 	sdcc1: qcom,sdcc@f9824000 {
@@ -110,6 +122,8 @@
 		vdd-supply = <&pm8941_l20>;
 		vdd-io-supply = <&pm8941_s3>;
 
+		qcom,sdcc-vdd-always_on;
+		qcom,sdcc-vdd-lpm_sup;
 		qcom,sdcc-vdd-voltage_level = <2950000 2950000>;
 		qcom,sdcc-vdd-current_level = <800 500000>;
 
@@ -281,6 +295,44 @@
 		};
 	};
 
+	sound {
+		compatible = "qcom,msm8974-audio-taiko";
+		qcom,model = "msm8974-taiko-snd-card";
+
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"HEADPHONE", "LDO_H",
+			"Ext Spk Bottom Pos", "LINEOUT1",
+			"Ext Spk Bottom Neg", "LINEOUT3",
+			"Ext Spk Top Pos", "LINEOUT2",
+			"Ext Spk Top Neg", "LINEOUT4",
+			"AMIC1", "MIC BIAS1 Internal1",
+			"MIC BIAS1 Internal1", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS3 Internal1",
+			"MIC BIAS3 Internal1", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS1 Internal2",
+			"MIC BIAS1 Internal2", "ANCLeft Headset Mic",
+			"DMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic1",
+			"DMIC2", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic2",
+			"DMIC3", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic3",
+			"DMIC4", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic4",
+			"DMIC5", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic5",
+			"DMIC6", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic6";
+
+		qcom,cdc-mclk-gpios = <&pm8941_gpios 15 0>;
+		taiko-mclk-clk = <&pm8941_clkdiv1>;
+		qcom,taiko-mclk-clk-freq = <9600000>;
+	};
+
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
@@ -505,84 +557,20 @@
 		interrupt-names = "qup_err_intr";
 		qcom,i2c-bus-freq = <100000>;
 		qcom,i2c-src-freq = <24000000>;
+	};
 
-		atmel_mxt_ts@4a {
-			compatible = "atmel,mxt-ts";
-			reg = <0x4a>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <61 0x2>;
-			vdd_ana-supply = <&pm8941_l18>;
-			vcc_i2c-supply = <&pm8941_lvs1>;
-			atmel,reset-gpio = <&msmgpio 60 0x00>;
-			atmel,irq-gpio = <&msmgpio 61 0x00>;
-			atmel,panel-coords = <0  0 760 1424>;
-			atmel,display-coords = <0 0 720 1280>;
-			atmel,i2c-pull-up = <1>;
-			atmel,cfg_1 {
-				atmel,family-id = <0x82>;
-				atmel,variant-id = <0x19>;
-				atmel,version = <0x10>;
-				atmel,build = <0xaa>;
-				atmel,config = [
-					/* Object 6, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 38, Instance = 0 */
-					15 00 02 10 08 0C 00 00
-					/* Object 7, Instance = 0 */
-					FF FF 32 03
-					/* Object 8, Instance = 0 */
-					0F 00 0A 0A 00 00 0A 00 00 00
-					/* Object 9, Instance = 0 */
-					83 00 00 18 0E 00 70 32 02 01
-					00 03 01 01 05 0A 0A 0A 90 05
-					F8 02 00 00 0F 0F 00 00 48 2D
-					07 0C 00 00 00 00
-					/* Object 15, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00
-					/* Object 18, Instance = 0 */
-					00 00
-					/* Object 19, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 23, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00
-					/* Object 25, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00
-					/* Object 40, Instance = 0 */
-					00 00 00 00 00
-					/* Object 42, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					/* Object 46, Instance = 0 */
-					00 00 10 10 00 00 03 00 00 01
-					/* Object 47, Instance = 0 */
-					08 0A 28 0A 02 0A 00 8C 00 20
-					00 00 00
-					/* Object 55, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 56, Instance = 0 */
-					03 00 01 18 05 05 05 05 05 05
-					05 05 05 05 05 05 05 05 05 05
-					05 05 05 05 05 05 05 05 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00
-					/* Object 57, Instance = 0 */
-					00 00 00
-					/* Object 61, Instance = 0 */
-					00 00 00 00 00
-					/* Object 61, Instance = 1 */
-					00 00 00 00 00
-					/* Object 62, Instance = 0 */
-					7F 03 00 16 00 00 00 00 00 00
-					04 08 10 18 05 00 0A 05 05 50
-					14 19 34 1A 64 00 00 04 40 00
-					00 00 00 00 30 32 02 00 01 00
-					05 00 00 00 00 00 00 00 00 00
-					00 00 0C 00
-					];
-			};
-		};
+	spi@f9923000 {
+		cell-index = <0>;
+		compatible = "qcom,spi-qup-v2";
+		reg = <0xf9923000 0x1000>;
+		interrupts = <0 95 0>;
+		spi-max-frequency = <19200000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		gpios = <&msmgpio 3 0>, /* CLK  */
+			<&msmgpio 1 0>, /* MISO */
+			<&msmgpio 0 0>; /* MOSI */
+		cs-gpios = <&msmgpio 9 0>;
 	};
 
 	qcom,acpuclk@f9000000 {
@@ -623,6 +611,14 @@
 		HSUSB_1p8-supply = <&pm8941_l6>;
 		HSUSB_3p3-supply = <&pm8941_l24>;
 		qcom,dwc-usb3-msm-dbm-eps = <4>;
+
+		qcom,msm_bus,name = "usb3";
+		qcom,msm_bus,num_cases = <2>;
+		qcom,msm_bus,active_only = <0>;
+		qcom,msm_bus,num_paths = <1>;
+		qcom,msm_bus,vectors =
+				<61 512 0 0>,
+				<61 512 240000000 960000000>;
 	};
 
 	gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
@@ -752,6 +748,26 @@
 		qcom,firmware-name = "wcnss";
 	};
 
+	qcom,wcnss-wlan@fb000000 {
+		compatible = "qcom,wcnss_wlan";
+		reg = <0xfb000000 0x280000>;
+		reg-names = "wcnss_mmio";
+		interrupts = <0 145 0 0 146 0>;
+		interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
+
+		qcom,pronto-vddmx-supply = <&pm8841_s1>;
+		qcom,pronto-vddcx-supply = <&pm8841_s2>;
+		qcom,pronto-vddpx-supply = <&pm8941_s3>;
+		qcom,iris-vddxo-supply = <&pm8941_l6>;
+		qcom,iris-vddrfa-supply = <&pm8941_l11>;
+		qcom,iris-vddpa-supply = <&pm8941_l19>;
+		qcom,iris-vdddig-supply = <&pm8941_l3>;
+
+		gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>, <&msmgpio 39 0>, <&msmgpio 40 0>;
+		qcom,has_48mhz_xo;
+		qcom,has_pronto_hw;
+	};
+
 	qcom,ocmem@fdd00000 {
 		compatible = "qcom,msm-ocmem";
 		reg = <0xfdd00000 0x2000>,
@@ -866,8 +882,8 @@
 		reg = <0xfd440000 0x20000>,
 		      <0xfd444000 0x8000>;
 		reg-names = "crypto-base","crypto-bam-base";
-		interrupts = <0 235 0>;
-		qcom,bam-pipe-pair = <0>;
+		interrupts = <0 236 0>;
+		qcom,bam-pipe-pair = <1>;
 	};
 
         qcom,qcrypto@fd444000 {
@@ -875,8 +891,8 @@
 		reg = <0xfd440000 0x20000>,
 		      <0xfd444000 0x8000>;
 		reg-names = "crypto-base","crypto-bam-base";
-		interrupts = <0 235 0>;
-		qcom,bam-pipe-pair = <1>;
+		interrupts = <0 236 0>;
+		qcom,bam-pipe-pair = <2>;
 	};
 
 	qcom,usbbam@f9304000 {
@@ -959,37 +975,6 @@
 		qcom,freq-step = <2>;
 	};
 
-	gpio_keys {
-		compatible = "gpio-keys";
-
-		camera_snapshot {
-			label = "camera_snapshot";
-			gpios = <&pm8941_gpios 3 0x1>;
-			linux,input-type = <1>;
-			linux,code = <0x2fe>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		camera_focus {
-			label = "camera_focus";
-			gpios = <&pm8941_gpios 4 0x1>;
-			linux,input-type = <1>;
-			linux,code = <0x210>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		vol_up {
-			label = "volume_up";
-			gpios = <&pm8941_gpios 5 0x1>;
-			linux,input-type = <1>;
-			linux,code = <115>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-	};
-
 	qcom,bam_dmux@fc834000 {
 		compatible = "qcom,bam_dmux";
 		reg = <0xfc834000 0x7000>;
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index 82d317d..f3efbb8 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -111,15 +111,12 @@
 		qcom,saw2-avs-dly= <0>;
 		qcom,saw2-spm-dly= <0x20000400>;
 		qcom,saw2-spm-ctl = <0x1>;
-		qcom,saw2-pmic-dly = <0x02020204>;
-		qcom,saw2-pmic-data0 = <0x0400009c>;
-		qcom,saw2-pmic-data1 = <0x00000060>;
-		qcom,saw2-pmic-data2 = <0x0000001c>;
-		qcom,saw2-pmic-data3 = <0x04000000>;
+		qcom,saw2-pmic-data0 = <0x02030080>;
+		qcom,saw2-pmic-data1 = <0x00030000>;
 		qcom,vctl-timeout-us = <50>;
 		qcom,vctl-port = <0x0>;
 		qcom,phase-port = <0x1>;
-		qcom,saw2-spm-cmd-ret = [0b 00 20 03 22 00 0f];
+		qcom,saw2-spm-cmd-ret = [00 20 03 22 00 0f];
 		qcom,saw2-spm-cmd-gdhs = [00 20 32 0b 42 07 44 22 50 02 32 50
 				0f];
 		qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 0b 42 07 01 b0 12 44 a0
@@ -305,14 +302,14 @@
 	qcom,mpm@fc4281d0 {
 		compatible = "qcom,mpm-v2";
 		reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
-		    <0xfa006000 0x1000>;   /* MSM_APCS_GCC_BASE 4K */
+		    <0xf9011008 0x4>;   /* MSM_APCS_GCC_BASE 4K */
 		reg-names = "vmpm", "ipc";
 		interrupts = <0 171 1>;
 
-		qcom,ipc-bit-offset = <0>;
+		qcom,ipc-bit-offset = <1>;
 
 		qcom,gic-parent = <&intc>;
-		qcom,gic-map = <41 180>, /* usb2_hsic_async_wakeup_irq */
+		qcom,gic-map = <47 180>, /* usb2_hsic_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
@@ -386,4 +383,9 @@
 			<39  93>,
 			<40  95>;
 	};
+
+	qcom,pc-cntr@fe800000 {
+		compatible = "qcom,pc-cntr";
+		reg = <0xfe800664 0x40>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm9625-cdp.dts b/arch/arm/boot/dts/msm9625-cdp.dts
new file mode 100644
index 0000000..6733f59
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-cdp.dts
@@ -0,0 +1,21 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm9625.dtsi"
+
+/ {
+	model = "Qualcomm MSM 9625 CDP";
+	compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+	qcom,msm-id = <134 1 0>;
+};
diff --git a/arch/arm/boot/dts/msm9625-mtp.dts b/arch/arm/boot/dts/msm9625-mtp.dts
new file mode 100644
index 0000000..32185dc
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-mtp.dts
@@ -0,0 +1,21 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm9625.dtsi"
+
+/ {
+	model = "Qualcomm MSM 9625 MTP";
+	compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+	qcom,msm-id = <134 8 0>;
+};
diff --git a/arch/arm/boot/dts/msm9625-rumi.dts b/arch/arm/boot/dts/msm9625-rumi.dts
new file mode 100644
index 0000000..e4fa000
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-rumi.dts
@@ -0,0 +1,21 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm9625.dtsi"
+
+/ {
+	model = "Qualcomm MSM 9625 RUMI";
+	compatible = "qcom,msm9625-rumi", "qcom,msm9625";
+	qcom,msm-id = <134 15 0>;
+};
diff --git a/arch/arm/boot/dts/msm9625.dts b/arch/arm/boot/dts/msm9625.dtsi
similarity index 91%
rename from arch/arm/boot/dts/msm9625.dts
rename to arch/arm/boot/dts/msm9625.dtsi
index 041b4dd..7b7adca 100644
--- a/arch/arm/boot/dts/msm9625.dts
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
 /include/ "skeleton.dtsi"
 
 / {
@@ -98,4 +97,13 @@
 			spi-max-frequency = <5000000>;
 		};
 	};
+
+	qcom,wdt@f9017000 {
+		compatible = "qcom,msm-watchdog";
+		reg = <0xf9017000 0x1000>;
+		interrupts = <1 2 0>, <1 1 0>;
+		qcom,bark-time = <11000>;
+		qcom,pet-time = <10000>;
+		qcom,ipi-ping = <0>;
+	};
 };
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index bbd6c63..9dd4347 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -367,7 +367,8 @@
 	if (gic_arch_extn.irq_retrigger)
 		return gic_arch_extn.irq_retrigger(d);
 
-	return -ENXIO;
+	/* the genirq layer expects 0 for a failure */
+	return 0;
 }
 
 #ifdef CONFIG_SMP
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 9c07793..1b792d9 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -53,6 +53,8 @@
 CONFIG_PM8XXX_RPC_VIBRATOR=y
 CONFIG_MSM_SPM_V2=y
 CONFIG_MSM_MULTIMEDIA_USE_ION=y
+CONFIG_MSM_CPR=y
+CONFIG_MSM_VP_REGULATOR=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 1c47b0c..aeb59af 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -53,6 +53,10 @@
 CONFIG_PM8XXX_RPC_VIBRATOR=y
 CONFIG_MSM_SPM_V2=y
 CONFIG_MSM_MULTIMEDIA_USE_ION=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
+CONFIG_MSM_CPR=y
+CONFIG_MSM_VP_REGULATOR=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -377,4 +381,3 @@
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 5ec9517..2c8f71e 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -229,6 +229,7 @@
 CONFIG_NET_EMATCH_META=y
 CONFIG_NET_EMATCH_TEXT=y
 CONFIG_NET_CLS_ACT=y
+CONFIG_MARIMBA_CORE=y
 CONFIG_BT=y
 CONFIG_BT_RFCOMM=y
 CONFIG_BT_RFCOMM_TTY=y
@@ -238,6 +239,8 @@
 CONFIG_BT_HIDP=y
 CONFIG_BT_HCISMD=y
 CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
 CONFIG_BT_HCIUART_ATH3K=y
 CONFIG_MSM_BT_POWER=y
 CONFIG_CFG80211=m
@@ -322,6 +325,7 @@
 CONFIG_SMB349_CHARGER=y
 CONFIG_PM8921_CHARGER=y
 CONFIG_PM8921_BMS=y
+CONFIG_BATTERY_BCL=y
 CONFIG_SENSORS_PM8XXX_ADC=y
 CONFIG_SENSORS_EPM_ADC=y
 CONFIG_THERMAL=y
@@ -420,11 +424,11 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_QUALCOMM=y
 CONFIG_USB_SERIAL_CSVT=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_QCOM_DIAG_BRIDGE=y
 CONFIG_USB_QCOM_MDM_BRIDGE=y
+CONFIG_USB_QCOM_KS_BRIDGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_CI13XXX_MSM=y
@@ -497,3 +501,4 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 023114e..a2deab2 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -233,6 +233,7 @@
 CONFIG_NET_EMATCH_META=y
 CONFIG_NET_EMATCH_TEXT=y
 CONFIG_NET_CLS_ACT=y
+CONFIG_MARIMBA_CORE=y
 CONFIG_BT=y
 CONFIG_BT_RFCOMM=y
 CONFIG_BT_RFCOMM_TTY=y
@@ -243,6 +244,8 @@
 CONFIG_BT_HCISMD=y
 CONFIG_BT_HCIUART=y
 CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
 CONFIG_MSM_BT_POWER=y
 CONFIG_CFG80211=m
 # CONFIG_CFG80211_WEXT is not set
@@ -326,6 +329,7 @@
 CONFIG_SMB349_CHARGER=y
 CONFIG_PM8921_CHARGER=y
 CONFIG_PM8921_BMS=y
+CONFIG_BATTERY_BCL=y
 CONFIG_SENSORS_PM8XXX_ADC=y
 CONFIG_SENSORS_EPM_ADC=y
 CONFIG_THERMAL=y
@@ -422,11 +426,11 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_QUALCOMM=y
 CONFIG_USB_SERIAL_CSVT=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_QCOM_DIAG_BRIDGE=y
 CONFIG_USB_QCOM_MDM_BRIDGE=y
+CONFIG_USB_QCOM_KS_BRIDGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_CI13XXX_MSM=y
@@ -514,3 +518,4 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 258470c..471ecd9 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -32,6 +32,7 @@
 CONFIG_EFI_PARTITION=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8974=y
+CONFIG_ARCH_MSM8226=y
 CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_KERNEL_PMEM_EBI_REGION=y
@@ -48,12 +49,16 @@
 CONFIG_MSM_PIL_MBA=y
 CONFIG_MSM_PIL_VENUS=y
 CONFIG_MSM_PIL_PRONTO=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_MODEM_SSR_8974=y
+CONFIG_MSM_ADSP_SSR_8974=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_QDSS=y
 CONFIG_MSM_OCMEM=y
 CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
 CONFIG_MSM_OCMEM_DEBUG=y
-CONFIG_MSM_OCMEM_POWER_DISABLE=y
+CONFIG_MSM_OCMEM_NONSECURE=y
 CONFIG_MSM_MEMORY_DUMP=y
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_DLOAD_MODE=y
@@ -73,7 +78,6 @@
 CONFIG_HIGHMEM=y
 CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_USE_OF=y
-CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -83,6 +87,7 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -108,6 +113,10 @@
 CONFIG_IPV6_MIP6=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_BLK_DEV_LOOP=y
@@ -129,6 +138,7 @@
 CONFIG_DUMMY=y
 CONFIG_KS8851=m
 # CONFIG_MSM_RMNET is not set
+CONFIG_MSM_RMNET_BAM=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -141,10 +151,8 @@
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
-CONFIG_HVC_DCC=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
-CONFIG_DCC_TTY=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
@@ -163,9 +171,12 @@
 CONFIG_GPIO_QPNP_PIN_DEBUG=y
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_SENSORS_QPNP_ADC_CURRENT=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_STUB=y
 CONFIG_REGULATOR_QPNP=y
 CONFIG_MEDIA_SUPPORT=y
@@ -185,6 +196,11 @@
 CONFIG_MSM_CSI2_REGISTER=y
 CONFIG_MSM_ISPIF=y
 CONFIG_S5K3L1YX=y
+CONFIG_OV2720=y
+CONFIG_MSM_JPEG=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
+CONFIG_RADIO_ADAPTERS=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
@@ -193,6 +209,7 @@
 # CONFIG_FB_MSM_BACKLIGHT is not set
 CONFIG_FB_MSM_MDSS=y
 CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
@@ -218,6 +235,7 @@
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_CI13XXX_MSM=y
 CONFIG_USB_G_ANDROID=y
 CONFIG_MMC=y
@@ -305,3 +323,11 @@
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_CFG80211=m
+CONFIG_RFKILL=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_MEDIA=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index b8417fe..2cc801e 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -215,9 +215,9 @@
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_MDM9615=y
-# CONFIG_HID_SUPPORT is not set
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_EHSET=y
 CONFIG_USB_EHCI_MSM=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 446734f..0057062 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -36,6 +36,7 @@
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_ARM_ARCH_TIMER=y
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 0d0103a..88d0872 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -113,7 +113,6 @@
 	struct mutex	reserve_mutex;
 	u64		max_period;
 	struct platform_device	*plat_device;
-	u32		from_idle;
 	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
 	int     	(*request_pmu_irq)(int irq, irq_handler_t *irq_h);
 	void    	(*free_pmu_irq)(int irq);
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 23d310d..2455d1f 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -192,11 +192,17 @@
 static void arch_timer_set_mode(enum clock_event_mode mode,
 				struct clock_event_device *clk)
 {
+	unsigned long ctrl;
+
 	switch (mode) {
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
 		arch_timer_disable();
 		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
+		ctrl |= ARCH_TIMER_CTRL_ENABLE;
+		arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
 	default:
 		break;
 	}
@@ -208,11 +214,9 @@
 	unsigned long ctrl;
 
 	ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
-	ctrl &= ~(ARCH_TIMER_CTRL_ENABLE | ARCH_TIMER_CTRL_IT_MASK);
+	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
 	arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
 	arch_specific_timer->reg_write(ARCH_TIMER_REG_TVAL, evt);
-	ctrl |= ARCH_TIMER_CTRL_ENABLE;
-	arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
 
 	return 0;
 }
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index e97aef2..3f6a6d3 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -41,6 +41,7 @@
  */
 #define ARMPMU_MAX_HWEVENTS		32
 
+static DEFINE_PER_CPU(u32, from_idle);
 static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
 static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
 static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
@@ -602,7 +603,7 @@
 	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
 	int idx;
 
-	if (armpmu->from_idle) {
+	if (__get_cpu_var(from_idle)) {
 		for (idx = 0; idx <= cpu_pmu->num_events; ++idx) {
 			struct perf_event *event = hw_events->events[idx];
 
@@ -613,9 +614,12 @@
 		}
 
 		/* Reset bit so we don't needlessly re-enable counters.*/
-		armpmu->from_idle = 0;
+		__get_cpu_var(from_idle) = 0;
 	}
 
+	/* So we don't start the PMU before enabling counters after idle. */
+	barrier();
+
 	if (enabled)
 		armpmu->start();
 }
@@ -731,7 +735,6 @@
  * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
  * junk values out of them.
  */
-
 static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
 					unsigned long action, void *hcpu)
 {
@@ -805,7 +808,7 @@
 			 * Flip this bit so armpmu_enable knows it needs
 			 * to re-enable active counters.
 			 */
-			cpu_pmu->from_idle = 1;
+			__get_cpu_var(from_idle) = 1;
 			cpu_pmu->reset(NULL);
 			perf_pmu_enable(&cpu_pmu->pmu);
 		}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index a9582f9..af21496 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -300,6 +300,7 @@
 
 void machine_shutdown(void)
 {
+	preempt_disable();
 #ifdef CONFIG_SMP
 	smp_send_stop();
 #endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 7d26726..e46fd92 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -507,7 +507,7 @@
 		raw_spin_unlock(&stop_lock);
 	}
 
-	set_cpu_online(cpu, false);
+	set_cpu_active(cpu, false);
 
 	local_fiq_disable();
 	local_irq_disable();
@@ -657,10 +657,10 @@
 
 	/* Wait up to one second for other CPUs to stop */
 	timeout = USEC_PER_SEC;
-	while (num_online_cpus() > 1 && timeout--)
+	while (num_active_cpus() > 1 && timeout--)
 		udelay(1);
 
-	if (num_online_cpus() > 1)
+	if (num_active_cpus() > 1)
 		pr_warning("SMP: failed to stop secondary CPUs\n");
 
 	smp_kill_cpus(&mask);
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 42dda69..badee85 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -263,6 +263,42 @@
 	select ARM_HAS_SG_CHAIN
 	select MSM_RUN_QUEUE_STATS
 
+config ARCH_MPQ8092
+	bool "MPQ8092"
+	select ARCH_MSM_KRAITMP
+	select GPIO_MSM_V3
+	select ARM_GIC
+	select MULTI_IRQ_HANDLER
+	select CPU_V7
+	select MSM_GPIOMUX
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+	select MSM_NOPM
+
+config ARCH_MSM8226
+	bool "MSM8226"
+	select ARCH_MSM_KRAITMP
+	select GPIO_MSM_V3
+	select ARM_GIC
+	select CPU_V7
+	select MSM_SCM if SMP
+	select MSM_GPIOMUX
+	select MULTI_IRQ_HANDLER
+	select MSM_MULTIMEDIA_USE_ION
+	select MSM_PIL
+	select MSM_SPM_V2
+	select MSM_L2_SPM
+	select MSM_PM8X60 if PM
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+	select MSM_RPM_SMD
+	select REGULATOR
+	select MSM_QDSP6_APRV2
+	select MSM_QDSP6V2_CODECS
+	select MSM_AUDIO_QDSP6V2 if SND_SOC
+	select MSM_RPM_REGULATOR_SMD
+	select ARM_HAS_SG_CHAIN
+
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
 	select ARCH_MSM_SCORPION
@@ -307,6 +343,7 @@
 	select ARM_TICKET_LOCKS
 	select MSM_RUN_QUEUE_STATS
 	select MIGHT_HAVE_CACHE_L2X0
+	select ARM_HAS_SG_CHAIN
 
 config ARCH_MSM9625
 	bool "MSM9625"
@@ -320,7 +357,6 @@
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select GPIO_MSM_V3
-
 endmenu
 
 choice
@@ -398,6 +434,7 @@
 	select ARM_GIC
 	select ARCH_MSM_CORTEXMP
 	select MIGHT_HAVE_CACHE_L2X0
+	select ARM_HAS_SG_CHAIN
 
 config  MSM_VIC
 	bool
@@ -887,6 +924,8 @@
 	default "0x80200000" if ARCH_MSM8960
 	default "0x80200000" if ARCH_MSM8930
 	default "0x00000000" if ARCH_MSM8974
+	default "0x00000000" if ARCH_MPQ8092
+	default "0x00000000" if ARCH_MSM8226
 	default "0x10000000" if ARCH_FSM9XXX
 	default "0x20200000" if ARCH_MSM9625
 	default "0x00200000" if !MSM_STACKED_MEMORY
@@ -1026,6 +1065,14 @@
 		help
 		  Say Y here if you want the debug print routines to direct
 		  their output to the serial port on MSM 8974 devices.
+
+	config DEBUG_MPQ8092_UART
+                bool "Kernel low-level debugging messages via MPQ8092 UART"
+                depends on ARCH_MPQ8092
+                select MSM_HAS_DEBUG_UART_HS_V14
+                help
+                  Say Y here if you want the debug print routines to direct
+                  their output to the serial port on MPQ8092 devices.
 endchoice
 
 choice
@@ -1987,6 +2034,24 @@
 	 gss hardware watchdog interrupt lines and plugs into the subsystem
 	 restart and PIL drivers.
 
+config MSM_MODEM_SSR_8974
+	bool "MSM 8974 Modem restart driver"
+	depends on (ARCH_MSM8974)
+	help
+	 This option enables the modem subsystem restart driver for the MSM8974.
+	 It monitors the modem SMSM status bits and the modem watchdog line and
+	 restarts the modem or the 8974 when the modem encounters a fatal error,
+	 depending on the restart level selected in the subsystem restart driver.
+
+config MSM_ADSP_SSR_8974
+	bool "MSM 8974 adsp restart driver"
+	depends on (ARCH_MSM8974)
+	help
+	 This option enables the adsp restart driver for the MSM8974.
+	 It monitors the adsp SMSM status bits and the adsp watchdog line and
+	 restarts the adsp or the 8974 when the adsp encounters a fatal error,
+	 depending on the restart level selected in the subsystem restart driver.
+
 config SCORPION_Uni_45nm_BUG
 	bool "Scorpion Uni 45nm(SC45U): Workaround for ICIMVAU and BPIMVA"
 	depends on ARCH_MSM7X30 || (ARCH_QSD8X50 && MSM_SOC_REV_A)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 964d42a..70234bf 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -103,6 +103,7 @@
 ifndef CONFIG_ARCH_MSM8960
 ifndef CONFIG_ARCH_MSM8X60
 ifndef CONFIG_ARCH_MSM8974
+ifndef CONFIG_ARCH_MPQ8092
 	obj-$(CONFIG_MSM_SMD) += pmic.o
 	obj-$(CONFIG_MSM_ONCRPCROUTER) += rpc_hsusb.o rpc_pmapp.o rpc_fsusb.o
 endif
@@ -110,17 +111,22 @@
 endif
 endif
 endif
+endif
 ifndef CONFIG_ARCH_MSM8960
 ifndef CONFIG_ARCH_MSM8X60
 ifndef CONFIG_ARCH_APQ8064
 ifndef CONFIG_ARCH_MSM8974
+ifndef CONFIG_ARCH_MSM8226
 ifndef CONFIG_ARCH_MSM9625
+ifndef CONFIG_ARCH_MPQ8092
 	obj-y += nand_partitions.o
 endif
 endif
 endif
 endif
 endif
+endif
+endif
 obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
 obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -206,7 +212,9 @@
 endif
 obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
 obj-$(CONFIG_MSM_MODEM_8960) += modem-8960.o
+obj-$(CONFIG_MSM_MODEM_SSR_8974) += modem-ssr-8974.o
 obj-$(CONFIG_MSM_LPASS_8960) += lpass-8960.o
+obj-$(CONFIG_MSM_ADSP_SSR_8974) += adsp-8974.o
 obj-$(CONFIG_MSM_WCNSS_SSR_8960) += wcnss-ssr-8960.o
 obj-$(CONFIG_MSM_GSS_SSR_8064) += gss-8064.o
 
@@ -284,7 +292,7 @@
 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
-obj-$(CONFIG_MACH_MPQ8064_HRD) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_MPQ8064_HRD) += board-8064-all.o board-8064-regulator.o board-8064-bt.o
 obj-$(CONFIG_MACH_MPQ8064_DTV) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
@@ -295,6 +303,8 @@
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.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_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -349,7 +359,8 @@
 obj-$(CONFIG_ARCH_MSM9615) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8974) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += gpiomux-v2.o gpiomux.o
-
+obj-$(CONFIG_ARCH_MPQ8092) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
 
 obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
 obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_dcvs_idle.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index b57d4e1..526616a 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -54,7 +54,14 @@
 # MSM9625
    zreladdr-$(CONFIG_ARCH_MSM9625)	:= 0x20208000
 
+# MSM8226
+   zreladdr-$(CONFIG_ARCH_MSM8226)	:= 0x00008000
+
 # FSM9XXX
    zreladdr-$(CONFIG_ARCH_FSM9XXX)	:= 0x10008000
 params_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x10000100
 initrd_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x12000000
+
+# MPQ8092
+   zreladdr-$(CONFIG_ARCH_MPQ8092)	:= 0x00008000
+
diff --git a/arch/arm/mach-msm/acpuclock-7627.c b/arch/arm/mach-msm/acpuclock-7627.c
index 3bcba5f..7be3667 100644
--- a/arch/arm/mach-msm/acpuclock-7627.c
+++ b/arch/arm/mach-msm/acpuclock-7627.c
@@ -723,7 +723,7 @@
 			/* Make sure PLL4 is off before reprogramming */
 			if ((plls_enabled & (1 << tgt_s->pll))) {
 				clk_disable(pll_clk[tgt_s->pll].clk);
-				plls_enabled &= (0 << tgt_s->pll);
+				plls_enabled &= ~(1 << tgt_s->pll);
 			}
 			acpuclk_config_pll4(tgt_s->pll_rate);
 			pll_clk[tgt_s->pll].clk->rate = tgt_s->a11clk_khz*1000;
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index a9521f0..3c80875 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -122,6 +122,7 @@
 	[13] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 5 },
 	[14] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 5 },
 	[15] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 5 },
+	{ }
 };
 
 static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index 1642dae..07a7f8f 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -104,6 +104,7 @@
 	[9]  = { {  864000, HFPLL, 1, 0, 0x20 }, LVL_HIGH, 1150000, 4 },
 	[10] = { {  918000, HFPLL, 1, 0, 0x22 }, LVL_HIGH, 1150000, 4 },
 	[11] = { {  972000, HFPLL, 1, 0, 0x24 }, LVL_HIGH, 1150000, 4 },
+	{ }
 };
 
 /* TODO: Update core voltages when data is available. */
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index 782ee60..77876ee 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -144,6 +144,7 @@
 	[13] = { { 1080000, HFPLL, 1, 0, 0x28 }, LVL_HIGH, 1150000, 7 },
 	[14] = { { 1134000, HFPLL, 1, 0, 0x2A }, LVL_HIGH, 1150000, 7 },
 	[15] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 },
+	{ }
 };
 
 static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index 34ba1da..dbc3e32 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -111,6 +111,7 @@
 	[13] = { { 1080000, HFPLL, 1, 0, 0x28 }, LVL_HIGH, 1150000, 7 },
 	[14] = { { 1134000, HFPLL, 1, 0, 0x2A }, LVL_HIGH, 1150000, 7 },
 	[15] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 },
+	{ }
 };
 
 static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 8cc4b13..631bd7e 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -109,6 +109,7 @@
 	[16] = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 6 },
 	[17] = { { 1296000, HFPLL, 1, 0, 0x30 }, 1150000, 1150000, 6 },
 	[18] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 6 },
+	{ }
 };
 
 static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 3c42090..63bff55 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -99,6 +99,7 @@
 	[7]  = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 5 },
 	[8]  = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 5 },
 	[9]  = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 5 },
+	{ }
 };
 
 static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index f0b1231..16f77ba 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -134,6 +134,7 @@
 	[23] = { { 2035200, HFPLL, 1, 0, 106 }, LVL_HIGH, 1050000, 3 },
 	[24] = { { 2112000, HFPLL, 1, 0, 110 }, LVL_HIGH, 1050000, 3 },
 	[25] = { { 2188800, HFPLL, 1, 0, 114 }, LVL_HIGH, 1050000, 3 },
+	{ }
 };
 
 static struct acpu_level acpu_freq_tbl[] __initdata = {
diff --git a/arch/arm/mach-msm/adsp-8974.c b/arch/arm/mach-msm/adsp-8974.c
new file mode 100644
index 0000000..050a24b
--- /dev/null
+++ b/arch/arm/mach-msm/adsp-8974.c
@@ -0,0 +1,297 @@
+/* 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 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/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/workqueue.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <mach/irqs.h>
+#include <mach/scm.h>
+#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
+#include <mach/subsystem_notif.h>
+
+#include "smd_private.h"
+#include "ramdump.h"
+#include "sysmon.h"
+
+#define SCM_Q6_NMI_CMD			0x1
+#define MODULE_NAME			"adsp_8974"
+#define MAX_BUF_SIZE			0x51
+
+/* Interrupt line for WDOG bite*/
+#define ADSP_Q6SS_WDOG_EXPIRED		194
+
+/* Subsystem restart: QDSP6 data, functions */
+static void adsp_fatal_fn(struct work_struct *);
+static DECLARE_WORK(adsp_fatal_work, adsp_fatal_fn);
+
+struct adsp_ssr {
+	void *adsp_ramdump_dev;
+} adsp_ssr;
+
+static struct adsp_ssr adsp_ssr_8974;
+static int q6_crash_shutdown;
+
+static int riva_notifier_cb(struct notifier_block *this, unsigned long code,
+								void *ss_handle)
+{
+	int ret;
+	switch (code) {
+	case SUBSYS_BEFORE_SHUTDOWN:
+		pr_debug("%s: R-Notify: Shutdown started\n", __func__);
+		ret = sysmon_send_event(SYSMON_SS_LPASS, "wcnss",
+				SUBSYS_BEFORE_SHUTDOWN);
+		if (ret < 0)
+			pr_err("%s: sysmon_send_event error %d", __func__,
+				ret);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static void *ssr_notif_hdle;
+static struct notifier_block rnb = {
+	.notifier_call = riva_notifier_cb,
+};
+
+static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
+								void *ss_handle)
+{
+	int ret;
+	switch (code) {
+	case SUBSYS_BEFORE_SHUTDOWN:
+		pr_debug("%s: M-Notify: Shutdown started\n", __func__);
+		ret = sysmon_send_event(SYSMON_SS_LPASS, "modem",
+				SUBSYS_BEFORE_SHUTDOWN);
+		if (ret < 0)
+			pr_err("%s: sysmon_send_event error %d", __func__,
+				ret);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static void *ssr_modem_notif_hdle;
+static struct notifier_block mnb = {
+	.notifier_call = modem_notifier_cb,
+};
+
+static void adsp_log_failure_reason(void)
+{
+	char *reason;
+	char buffer[MAX_BUF_SIZE];
+	unsigned size;
+
+	reason = smem_get_entry(SMEM_SSR_REASON_LPASS0, &size);
+
+	if (!reason) {
+		pr_err("%s: subsystem failure reason: (unknown, smem_get_entry failed).",
+			 MODULE_NAME);
+		return;
+	}
+
+	if (reason[0] == '\0') {
+		pr_err("%s: subsystem failure reason: (unknown, init value found)",
+			 MODULE_NAME);
+		return;
+	}
+
+	size = size < MAX_BUF_SIZE ? size : (MAX_BUF_SIZE-1);
+	memcpy(buffer, reason, size);
+	buffer[size] = '\0';
+	pr_err("%s: subsystem failure reason: %s", MODULE_NAME, buffer);
+	memset((void *)reason, 0x0, size);
+	wmb();
+}
+
+static void adsp_fatal_fn(struct work_struct *work)
+{
+	pr_err("%s %s: Watchdog bite received from Q6!\n", MODULE_NAME,
+		__func__);
+	adsp_log_failure_reason();
+	panic(MODULE_NAME ": Resetting the SoC");
+}
+
+static void adsp_smsm_state_cb(void *data, uint32_t old_state,
+				uint32_t new_state)
+{
+	/* Ignore if we're the one that set SMSM_RESET */
+	if (q6_crash_shutdown)
+		return;
+
+	if (new_state & SMSM_RESET) {
+		pr_debug("%s: ADSP SMSM state changed to SMSM_RESET, new_state= 0x%x, old_state = 0x%x\n",
+			 __func__, new_state, old_state);
+		adsp_log_failure_reason();
+		panic(MODULE_NAME ": Resetting the SoC");
+	}
+}
+
+static void send_q6_nmi(void)
+{
+	/* Send NMI to QDSP6 via an SCM call. */
+	scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
+	pr_debug("%s: Q6 NMI was sent.\n", __func__);
+}
+
+static int adsp_shutdown(const struct subsys_desc *subsys)
+{
+	send_q6_nmi();
+
+	/* The write needs to go through before the q6 is shutdown. */
+	mb();
+
+	pil_force_shutdown("q6");
+	disable_irq_nosync(ADSP_Q6SS_WDOG_EXPIRED);
+
+	return 0;
+}
+
+static int adsp_powerup(const struct subsys_desc *subsys)
+{
+	int ret;
+
+	if (get_restart_level() == RESET_SUBSYS_INDEPENDENT) {
+		pr_debug("%s: Wait for ADSP power up!", __func__);
+		msleep(10000);
+	}
+
+	ret = pil_force_boot("q6");
+	enable_irq(ADSP_Q6SS_WDOG_EXPIRED);
+	return ret;
+}
+/* RAM segments - address and size for 8974 */
+static struct ramdump_segment q6_segment = {0xdc00000, 0x1800000};
+
+static int adsp_ramdump(int enable, const struct subsys_desc *subsys)
+{
+	pr_debug("%s: enable[%d]\n", __func__, enable);
+	if (enable)
+		return do_ramdump(adsp_ssr_8974.adsp_ramdump_dev,
+				&q6_segment, 1);
+	else
+		return 0;
+}
+
+static void adsp_crash_shutdown(const struct subsys_desc *subsys)
+{
+	q6_crash_shutdown = 1;
+	send_q6_nmi();
+}
+
+static irqreturn_t adsp_wdog_bite_irq(int irq, void *dev_id)
+{
+	int ret;
+
+	pr_debug("%s: rxed irq[0x%x]", __func__, irq);
+	disable_irq_nosync(ADSP_Q6SS_WDOG_EXPIRED);
+	ret = schedule_work(&adsp_fatal_work);
+
+	return IRQ_HANDLED;
+}
+
+static struct subsys_device *adsp_8974_dev;
+
+static struct subsys_desc adsp_8974 = {
+	.name = "adsp",
+	.shutdown = adsp_shutdown,
+	.powerup = adsp_powerup,
+	.ramdump = adsp_ramdump,
+	.crash_shutdown = adsp_crash_shutdown
+};
+
+static int __init adsp_restart_init(void)
+{
+	adsp_8974_dev = subsys_register(&adsp_8974);
+	if (IS_ERR(adsp_8974_dev))
+		return PTR_ERR(adsp_8974_dev);
+	return 0;
+}
+
+static int __init adsp_fatal_init(void)
+{
+	int ret;
+
+	ret = smsm_state_cb_register(SMSM_Q6_STATE, SMSM_RESET,
+		adsp_smsm_state_cb, 0);
+
+	if (ret < 0)
+		pr_err("%s: Unable to register SMSM callback! (%d)\n",
+				__func__, ret);
+
+	ret = request_irq(ADSP_Q6SS_WDOG_EXPIRED, adsp_wdog_bite_irq,
+			IRQF_TRIGGER_RISING, "q6_wdog", NULL);
+
+	if (ret < 0) {
+		pr_err("%s: Unable to request ADSP_Q6SS_WDOG_EXPIRED irq.",
+			__func__);
+		goto out;
+	}
+	ret = adsp_restart_init();
+	if (ret < 0) {
+		pr_err("%s: Unable to reg with adsp ssr. (%d)\n",
+				__func__, ret);
+		goto out;
+	}
+
+	adsp_ssr_8974.adsp_ramdump_dev = create_ramdump_device("adsp");
+
+	if (!adsp_ssr_8974.adsp_ramdump_dev) {
+		pr_err("%s: Unable to create ramdump device.\n",
+				__func__);
+		ret = -ENOMEM;
+		goto out;
+	}
+	ssr_notif_hdle = subsys_notif_register_notifier("riva",
+							&rnb);
+	if (IS_ERR(ssr_notif_hdle) < 0) {
+		ret = PTR_ERR(ssr_notif_hdle);
+		pr_err("%s: subsys_register_notifier for Riva: err = %d\n",
+			__func__, ret);
+		free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
+		goto out;
+	}
+
+	ssr_modem_notif_hdle = subsys_notif_register_notifier("modem",
+							&mnb);
+	if (IS_ERR(ssr_modem_notif_hdle) < 0) {
+		ret = PTR_ERR(ssr_modem_notif_hdle);
+		pr_err("%s: subsys_register_notifier for Modem: err = %d\n",
+			__func__, ret);
+		subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
+		free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
+		goto out;
+	}
+
+	pr_info("%s: adsp ssr driver init'ed.\n", __func__);
+out:
+	return ret;
+}
+
+static void __exit adsp_fatal_exit(void)
+{
+	subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
+	subsys_notif_unregister_notifier(ssr_modem_notif_hdle, &mnb);
+	subsys_unregister(adsp_8974_dev);
+	free_irq(ADSP_Q6SS_WDOG_EXPIRED, NULL);
+}
+
+module_init(adsp_fatal_init);
+module_exit(adsp_fatal_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/audio-7627a-devices.c b/arch/arm/mach-msm/audio-7627a-devices.c
index 798c118..3a636e8 100644
--- a/arch/arm/mach-msm/audio-7627a-devices.c
+++ b/arch/arm/mach-msm/audio-7627a-devices.c
@@ -198,6 +198,8 @@
 			(SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
 	CAD(FM_DIGITAL_SPEAKER_PHONE_MONO, 67, \
 			(SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+	CAD(FM_DIGITAL_SPEAKER_PHONE_MIC, 68, \
+			(SNDDEV_CAP_FM | SNDDEV_CAP_TX)),
 	CAD(FM_DIGITAL_BT_A2DP_SPKR, 69, \
 			(SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
 	CAD(MAX, 80, SNDDEV_CAP_NONE),
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index fbc3e25..1a02fce 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -1711,6 +1711,20 @@
 	}
 
 	/*
+	 * if this gets hit, that means restart_notifier_cb() has started
+	 * but probably not finished, thus we know SSR has happened, but
+	 * haven't been able to send that info to our clients yet.
+	 * in that case, abort the ul_wakeup() so that we don't undo any
+	 * work restart_notifier_cb() has done.  The clients will be notified
+	 * shortly.  No cleanup necessary (reschedule the wakeup) as our and
+	 * their SSR handling will cover it
+	 */
+	if (unlikely(in_global_reset == 1)) {
+		mutex_unlock(&wakeup_lock);
+		return;
+	}
+
+	/*
 	 * if someone is voting for UL before bam is inited (modem up first
 	 * time), set flag for init to kickoff ul wakeup once bam is inited
 	 */
diff --git a/arch/arm/mach-msm/board-8064-bt.c b/arch/arm/mach-msm/board-8064-bt.c
new file mode 100644
index 0000000..a8ae9fa
--- /dev/null
+++ b/arch/arm/mach-msm/board-8064-bt.c
@@ -0,0 +1,547 @@
+/* Copyright (c) 2011-2012, Linux Foundation. All rights reserved.
+ *
+ * This 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/delay.h>
+#include <linux/rfkill.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/marimba.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <mach/rpc_pmapp.h>
+#include <mach/msm_xo.h>
+#include <mach/socinfo.h>
+
+#include "board-8064.h"
+
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+
+#define BAHAMA_SLAVE_ID_FM_ADDR  0x2A
+#define BAHAMA_SLAVE_ID_QMEMBIST_ADDR   0x7B
+
+struct bt_vreg_info {
+	const char *name;
+	unsigned int pmapp_id;
+	unsigned int min_level;
+	unsigned int max_level;
+	unsigned int is_pin_controlled;
+	struct regulator *reg;
+};
+
+struct bahama_config_register {
+	u8 reg;
+	u8 value;
+	u8 mask;
+};
+static struct bt_vreg_info bt_vregs[] = {
+	{"bha_vddxo",  2, 1800000, 1800000, 0, NULL},
+	{"bha_vddpx", 21, 1800000, 1800000, 0, NULL},
+	{"bha_vddpa", 21, 2900000, 3300000, 0, NULL}
+};
+
+static struct msm_xo_voter *bt_clock;
+
+static struct platform_device msm_bt_power_device = {
+	.name = "bt_power",
+	.id = -1,
+};
+
+static unsigned bt_config_pcm_on[] = {
+	/*PCM_DOUT*/
+	GPIO_CFG(43, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+	/*PCM_DIN*/
+	GPIO_CFG(44, 1, GPIO_CFG_INPUT,  GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+	/*PCM_SYNC*/
+	GPIO_CFG(45, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+	/*PCM_CLK*/
+	GPIO_CFG(46, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+};
+
+static unsigned bt_config_pcm_off[] = {
+	/*PCM_DOUT*/
+	GPIO_CFG(43, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	/*PCM_DIN*/
+	GPIO_CFG(44, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	/*PCM_SYNC*/
+	GPIO_CFG(45, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	/*PCM_CLK*/
+	GPIO_CFG(46, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+};
+
+static int config_pcm(int mode)
+{
+	int pin, rc = 0;
+
+	if (mode == BT_PCM_ON) {
+		pr_err("%s mode =BT_PCM_ON", __func__);
+		for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_on);
+			pin++) {
+				rc = gpio_tlmm_config(bt_config_pcm_on[pin],
+					GPIO_CFG_ENABLE);
+				if (rc < 0)
+					return rc;
+		}
+	} else if (mode == BT_PCM_OFF) {
+		pr_err("%s mode =BT_PCM_OFF", __func__);
+		for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_off);
+			pin++) {
+				rc = gpio_tlmm_config(bt_config_pcm_off[pin],
+					GPIO_CFG_ENABLE);
+				if (rc < 0)
+					return rc;
+		}
+
+	}
+
+	return rc;
+}
+
+static int bahama_bt(int on)
+{
+	int rc = 0;
+	int i;
+
+	struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
+
+	struct bahama_variant_register {
+		const size_t size;
+		const struct bahama_config_register *set;
+	};
+
+	const struct bahama_config_register *p;
+
+	u8 version;
+
+	const struct bahama_config_register v10_bt_on[] = {
+		{ 0xE9, 0x00, 0xFF },
+		{ 0xF4, 0x80, 0xFF },
+		{ 0xE4, 0x00, 0xFF },
+		{ 0xE5, 0x00, 0x0F },
+#ifdef CONFIG_WLAN
+		{ 0xE6, 0x38, 0x7F },
+		{ 0xE7, 0x06, 0xFF },
+#endif
+		{ 0xE9, 0x21, 0xFF },
+		{ 0x01, 0x0C, 0x1F },
+		{ 0x01, 0x08, 0x1F },
+	};
+
+	const struct bahama_config_register v20_bt_on_fm_off[] = {
+		{ 0x11, 0x0C, 0xFF },
+		{ 0x13, 0x01, 0xFF },
+		{ 0xF4, 0x80, 0xFF },
+		{ 0xF0, 0x00, 0xFF },
+		{ 0xE9, 0x00, 0xFF },
+#ifdef CONFIG_WLAN
+		{ 0x81, 0x00, 0x7F },
+		{ 0x82, 0x00, 0xFF },
+		{ 0xE6, 0x38, 0x7F },
+		{ 0xE7, 0x06, 0xFF },
+#endif
+		{ 0x8E, 0x15, 0xFF },
+		{ 0x8F, 0x15, 0xFF },
+		{ 0x90, 0x15, 0xFF },
+
+		{ 0xE9, 0x21, 0xFF },
+	};
+
+	const struct bahama_config_register v20_bt_on_fm_on[] = {
+		{ 0x11, 0x0C, 0xFF },
+		{ 0x13, 0x01, 0xFF },
+		{ 0xF4, 0x86, 0xFF },
+		{ 0xF0, 0x06, 0xFF },
+		{ 0xE9, 0x00, 0xFF },
+#ifdef CONFIG_WLAN
+		{ 0x81, 0x00, 0x7F },
+		{ 0x82, 0x00, 0xFF },
+		{ 0xE6, 0x38, 0x7F },
+		{ 0xE7, 0x06, 0xFF },
+#endif
+		{ 0xE9, 0x21, 0xFF },
+	};
+
+	const struct bahama_config_register v10_bt_off[] = {
+		{ 0xE9, 0x00, 0xFF },
+	};
+
+	const struct bahama_config_register v20_bt_off_fm_off[] = {
+		{ 0xF4, 0x84, 0xFF },
+		{ 0xF0, 0x04, 0xFF },
+		{ 0xE9, 0x00, 0xFF }
+	};
+
+	const struct bahama_config_register v20_bt_off_fm_on[] = {
+		{ 0xF4, 0x86, 0xFF },
+		{ 0xF0, 0x06, 0xFF },
+		{ 0xE9, 0x00, 0xFF }
+	};
+
+	const struct bahama_variant_register bt_bahama[2][3] = {
+	{
+		{ ARRAY_SIZE(v10_bt_off), v10_bt_off },
+		{ ARRAY_SIZE(v20_bt_off_fm_off), v20_bt_off_fm_off },
+		{ ARRAY_SIZE(v20_bt_off_fm_on), v20_bt_off_fm_on }
+	},
+	{
+		{ ARRAY_SIZE(v10_bt_on), v10_bt_on },
+		{ ARRAY_SIZE(v20_bt_on_fm_off), v20_bt_on_fm_off },
+		{ ARRAY_SIZE(v20_bt_on_fm_on), v20_bt_on_fm_on }
+	}
+	};
+
+	u8 offset = 0; /* index into bahama configs */
+	on = on ? 1 : 0;
+	version = marimba_read_bahama_ver(&config);
+	if ((int)version < 0 || version == BAHAMA_VER_UNSUPPORTED) {
+		dev_err(&msm_bt_power_device.dev,
+			"%s : Bahama version read Error, version = %d\n",
+			__func__, version);
+		return -EIO;
+	}
+	if (version == BAHAMA_VER_2_0) {
+		if (marimba_get_fm_status(&config))
+			offset = 0x01;
+	}
+
+	p = bt_bahama[on][version + offset].set;
+
+	dev_dbg(&msm_bt_power_device.dev,
+		"%s: found version %d\n", __func__, version);
+
+	for (i = 0; i < bt_bahama[on][version + offset].size; i++) {
+		u8 value = (p+i)->value;
+		rc = marimba_write_bit_mask(&config,
+			(p+i)->reg,
+			&value,
+			sizeof((p+i)->value),
+			(p+i)->mask);
+		if (rc < 0) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: reg %x write failed: %d\n",
+				__func__, (p+i)->reg, rc);
+			return rc;
+		}
+		dev_dbg(&msm_bt_power_device.dev,
+			"%s: reg 0x%02x write value 0x%02x mask 0x%02x\n",
+				__func__, (p+i)->reg,
+				value, (p+i)->mask);
+		value = 0;
+		rc = marimba_read_bit_mask(&config,
+				(p+i)->reg, &value,
+				sizeof((p+i)->value), (p+i)->mask);
+		if (rc < 0)
+			dev_err(&msm_bt_power_device.dev,
+				"%s marimba_read_bit_mask- error",
+				__func__);
+		dev_dbg(&msm_bt_power_device.dev,
+			"%s: reg 0x%02x read value 0x%02x mask 0x%02x\n",
+				__func__, (p+i)->reg,
+				value, (p+i)->mask);
+	}
+	/* Update BT Status */
+	if (on)
+		marimba_set_bt_status(&config, true);
+	else
+		marimba_set_bt_status(&config, false);
+	return rc;
+}
+
+static int bluetooth_switch_regulators(int on)
+{
+	int i, rc = 0;
+
+	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+		if (IS_ERR_OR_NULL(bt_vregs[i].reg)) {
+			bt_vregs[i].reg =
+				regulator_get(&msm_bt_power_device.dev,
+						bt_vregs[i].name);
+			if (IS_ERR(bt_vregs[i].reg)) {
+				rc = PTR_ERR(bt_vregs[i].reg);
+				dev_err(&msm_bt_power_device.dev,
+					"%s: invalid regulator handle for %s: %d\n",
+						__func__, bt_vregs[i].name, rc);
+				goto reg_disable;
+			}
+		}
+		rc = on ? regulator_set_voltage(bt_vregs[i].reg,
+					bt_vregs[i].min_level,
+						bt_vregs[i].max_level) : 0;
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not set voltage for %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_disable;
+		}
+
+		rc = on ? regulator_enable(bt_vregs[i].reg) : 0;
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not %sable regulator %s: %d\n",
+					__func__, "en", bt_vregs[i].name, rc);
+			goto reg_disable;
+		}
+
+		rc = on ? 0 : regulator_disable(bt_vregs[i].reg);
+
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not %sable regulator %s: %d\n",
+					__func__, "dis", bt_vregs[i].name, rc);
+			goto reg_disable;
+		}
+	}
+
+	return rc;
+reg_disable:
+	pr_err("bluetooth_switch_regulators - FAIL!!!!\n");
+	while (i) {
+		if (on) {
+			i--;
+			regulator_disable(bt_vregs[i].reg);
+			regulator_put(bt_vregs[i].reg);
+			bt_vregs[i].reg = NULL;
+		}
+	}
+	return rc;
+}
+
+static unsigned int msm_bahama_setup_power(void)
+{
+	int rc = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+		bt_vregs[i].reg = regulator_get(&msm_bt_power_device.dev,
+						bt_vregs[i].name);
+		if (IS_ERR(bt_vregs[i].reg)) {
+			rc = PTR_ERR(bt_vregs[i].reg);
+			pr_err("%s: could not get regulator %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_fail;
+		}
+		rc = regulator_set_voltage(bt_vregs[i].reg,
+					bt_vregs[i].min_level,
+						bt_vregs[i].max_level);
+		if (rc) {
+			pr_err("%s: could not set voltage for %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_fail;
+		}
+		rc = regulator_enable(bt_vregs[i].reg);
+		if (rc) {
+			pr_err("%s: could not enable regulator %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_fail;
+		}
+	}
+	return rc;
+reg_fail:
+	pr_err("msm_bahama_setup_power FAILED !!!\n");
+
+	while (i) {
+		i--;
+		regulator_disable(bt_vregs[i].reg);
+		regulator_put(bt_vregs[i].reg);
+		bt_vregs[i].reg = NULL;
+	}
+	return rc;
+}
+
+static unsigned int msm_bahama_shutdown_power(int value)
+{
+	int rc = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+		rc = regulator_disable(bt_vregs[i].reg);
+
+		if (rc < 0) {
+			pr_err("%s: could not disable regulator %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto out;
+		}
+
+		regulator_put(bt_vregs[i].reg);
+		bt_vregs[i].reg = NULL;
+	}
+out:
+	return rc;
+}
+
+static unsigned int msm_bahama_core_config(int type)
+{
+	int rc = 0;
+
+	if (type == BAHAMA_ID) {
+		int i;
+		struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
+		const struct bahama_config_register v20_init[] = {
+			/* reg, value, mask */
+			{ 0xF4, 0x84, 0xFF }, /* AREG */
+			{ 0xF0, 0x04, 0xFF } /* DREG */
+		};
+		if (marimba_read_bahama_ver(&config) == BAHAMA_VER_2_0) {
+			for (i = 0; i < ARRAY_SIZE(v20_init); i++) {
+				u8 value = v20_init[i].value;
+				rc = marimba_write_bit_mask(&config,
+					v20_init[i].reg,
+					&value,
+					sizeof(v20_init[i].value),
+					v20_init[i].mask);
+				if (rc < 0) {
+					pr_err("%s: reg %d write failed: %d\n",
+						__func__, v20_init[i].reg, rc);
+					return rc;
+				}
+				pr_debug("%s: reg 0x%02x value 0x%02x mask 0x%02x\n",
+					__func__, v20_init[i].reg,
+					v20_init[i].value, v20_init[i].mask);
+			}
+		}
+	}
+	pr_debug("core type: %d\n", type);
+	return rc;
+}
+
+static int bluetooth_power(int on)
+{
+	int rc = 0;
+	const char *id = "BTPW";
+	int cid = 0;
+
+	pr_debug("bluetooth_power entered....\n");
+	cid = adie_get_detected_connectivity_type();
+	if (cid != BAHAMA_ID) {
+		pr_err("%s: unexpected adie connectivity type: %d\n",
+					__func__, cid);
+		return -ENODEV;
+	}
+
+	if (on) {
+		rc = bluetooth_switch_regulators(on);
+		if (rc < 0) {
+			pr_err("%s: bluetooth_switch_regulators rc = %d",
+					__func__, rc);
+			goto exit;
+		}
+		/* UART GPIO configuration to be done by by UART module*/
+		/*Setup BT clocks*/
+		bt_clock = msm_xo_get(MSM_XO_TCXO_A2, id);
+		if (IS_ERR(bt_clock)) {
+			rc = PTR_ERR(bt_clock);
+			pr_err("%s: failed to get the handle for A2(%d)\n",
+					__func__, rc);
+		}
+		rc = msm_xo_mode_vote(bt_clock, MSM_XO_MODE_ON);
+		if (rc < 0) {
+			pr_err("%s: Failed to vote for TCXO_A2 ON\n", __func__);
+			goto fail_xo_vote;
+		}
+		msleep(20);
+
+		/*I2C config for Bahama*/
+		rc = bahama_bt(1);
+		if (rc < 0) {
+			pr_err("%s: bahama_bt rc = %d", __func__, rc);
+			goto fail_i2c;
+		}
+		msleep(20);
+
+		/*setup BT PCM lines*/
+		rc = config_pcm(BT_PCM_ON);
+		if (rc < 0) {
+			pr_err("%s: config_pcm , rc =%d\n",
+				__func__, rc);
+				goto fail_power;
+		}
+		/* TO DO - Enable PIN CTRL */
+		/*
+		rc = msm_xo_mode_vote(bt_clock, MSM_XO_MODE_PIN_CTRL);
+		if (rc < 0) {
+			pr_err("%s: Failed to vote for TCXO_A2 in PIN_CTRL\n",
+				__func__);
+			goto fail_xo_vote;
+		} */
+	} else {
+		rc = bahama_bt(0);
+		if (rc < 0)
+			pr_err("%s: bahama_bt rc = %d", __func__, rc);
+
+		rc = config_pcm(BT_PCM_OFF);
+		if (rc < 0) {
+			pr_err("%s: msm_bahama_setup_pcm_i2s, rc =%d\n",
+				__func__, rc);
+		}
+fail_i2c:
+		pr_err("bluetooth_power...FAIL_I2C\n");
+
+fail_xo_vote:
+		pr_err("bluetooth_power...FAIL_XO_VOTE\n");
+		msm_xo_put(bt_clock);
+fail_power:
+		pr_err("bluetooth_power...FAIL POWER\n");
+		rc = bluetooth_switch_regulators(0);
+		if (rc < 0) {
+			pr_err("%s: switch_regulators : rc = %d",\
+				__func__, rc);
+			goto exit;
+		}
+	}
+	return rc;
+exit:
+	pr_err("%s: failed with rc = %d", __func__, rc);
+	return rc;
+}
+
+static struct marimba_platform_data marimba_pdata = {
+	.slave_id[SLAVE_ID_BAHAMA_FM]	= BAHAMA_SLAVE_ID_FM_ADDR,
+	.slave_id[SLAVE_ID_BAHAMA_QMEMBIST] = BAHAMA_SLAVE_ID_QMEMBIST_ADDR,
+	.bahama_setup			= msm_bahama_setup_power,
+	.bahama_shutdown		= msm_bahama_shutdown_power,
+	.bahama_core_config		= msm_bahama_core_config,
+	.fm			        = NULL,
+};
+
+static struct i2c_board_info bahama_devices[] = {
+{
+	I2C_BOARD_INFO("marimba", 0xc),
+	.platform_data = &marimba_pdata,
+},
+};
+
+void __init apq8064_bt_power_init(void)
+{
+	int rc = 0;
+	struct device *dev;
+
+	rc = i2c_register_board_info(APQ_8064_GSBI5_QUP_I2C_BUS_ID,
+				bahama_devices,
+				ARRAY_SIZE(bahama_devices));
+	if (rc < 0) {
+		pr_err("%s: I2C Register failed\n", __func__);
+		return;
+	}
+	rc = platform_device_register(&msm_bt_power_device);
+	if (rc < 0) {
+		pr_err("%s: device register failed\n", __func__);
+		platform_device_unregister(&msm_bt_power_device);
+		return;
+	}
+
+	dev = &msm_bt_power_device.dev;
+	dev->platform_data = &bluetooth_power;
+
+	return;
+}
+#endif
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 722b8ea..bc1eded 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -323,6 +323,40 @@
 	},
 };
 
+static struct msm_bus_vectors cam_dual_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 348192000,
+		.ib  = 1208286720,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 206807040,
+		.ib  = 488816640,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 540000000,
+		.ib  = 1350000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+};
+
+
 static struct msm_bus_paths cam_bus_client_config[] = {
 	{
 		ARRAY_SIZE(cam_init_vectors),
@@ -348,6 +382,10 @@
 		ARRAY_SIZE(cam_video_ls_vectors),
 		cam_video_ls_vectors,
 	},
+	{
+		ARRAY_SIZE(cam_dual_vectors),
+		cam_dual_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index d0f1e87..56c3241 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -16,7 +16,7 @@
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/bootmem.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <asm/mach-types.h>
 #include <mach/msm_memtypes.h>
 #include <mach/board.h>
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 9e43874..a08f45c 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -336,6 +336,13 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+static struct gpiomux_setting gpio_i2c_2ma_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+
 static struct gpiomux_setting gpio_i2c_config_sus = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_2MA,
@@ -714,12 +721,6 @@
 		},
 	},
 	{
-		.gpio      = 32,		/* EPM CS */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_epm_spi_cs_config,
-		},
-	},
-	{
 		.gpio      = 53,		/* NOR CS */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
@@ -737,6 +738,35 @@
 			[GPIOMUX_SUSPENDED] = &gsbi7_func1_cfg,
 		},
 	},
+};
+
+static struct msm_gpiomux_config apq8064_non_mi2s_gsbi_configs[] __initdata = {
+	{
+		.gpio      = 32,		/* EPM CS */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_epm_spi_cs_config,
+		},
+	},
+};
+
+static struct msm_gpiomux_config apq8064_gsbi1_i2c_2ma_configs[] __initdata = {
+	{
+		.gpio      = 21,		/* GSBI1 QUP I2C_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config_sus,
+			[GPIOMUX_ACTIVE] = &gpio_i2c_2ma_config,
+		},
+	},
+	{
+		.gpio      = 20,		/* GSBI1 QUP I2C_DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config_sus,
+			[GPIOMUX_ACTIVE] = &gpio_i2c_2ma_config,
+		},
+	},
+};
+
+static struct msm_gpiomux_config apq8064_gsbi1_i2c_8ma_configs[] __initdata = {
 	{
 		.gpio      = 21,		/* GSBI1 QUP I2C_CLK */
 		.settings = {
@@ -768,7 +798,7 @@
 	},
 };
 
-static struct gpiomux_setting spkr_i2c = {
+static struct gpiomux_setting spkr_i2s = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
 	.pull = GPIOMUX_PULL_KEEPER,
@@ -778,25 +808,25 @@
 	{
 		.gpio   = 47,           /* spkr i2c sck */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &spkr_i2c,
+			[GPIOMUX_SUSPENDED] = &spkr_i2s,
 		},
 	},
 	{
 		.gpio   = 48,           /* spkr_i2s_ws */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &spkr_i2c,
+			[GPIOMUX_SUSPENDED] = &spkr_i2s,
 		},
 	},
 	{
 		.gpio   = 49,           /* spkr_i2s_dout */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &spkr_i2c,
+			[GPIOMUX_SUSPENDED] = &spkr_i2s,
 		},
 	},
 	{
 		.gpio   = 50,           /* spkr_i2s_mclk */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &spkr_i2c,
+			[GPIOMUX_SUSPENDED] = &spkr_i2s,
 		},
 	},
 };
@@ -968,13 +998,19 @@
 	},
 };
 
-static struct gpiomux_setting mi2s_act_cfg = {
+static struct gpiomux_setting i2s_act_cfg = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
 
-static struct gpiomux_setting mi2s_sus_cfg = {
+static struct gpiomux_setting i2s_act_func_2_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting i2s_sus_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
@@ -984,55 +1020,145 @@
 	{
 		.gpio	= 27,		/* mi2s ws */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
-			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
 		},
 	},
 	{
 		.gpio	= 28,		/* mi2s sclk */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
-			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
 		},
 	},
 	{
 		.gpio	= 29,		/* mi2s dout3 */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
-			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
 		},
 	},
 	{
 		.gpio	= 30,		/* mi2s dout2 */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
-			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
 		},
 	},
 
 	{
 		.gpio	= 31,		/* mi2s dout1 */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
-			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
 		},
 	},
 	{
 		.gpio	= 32,		/* mi2s dout0 */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
-			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
 		},
 	},
 
 	{
 		.gpio	= 33,		/* mi2s mclk */
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &mi2s_act_cfg,
-			[GPIOMUX_SUSPENDED] = &mi2s_sus_cfg,
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
 		},
 	},
 };
+
+static struct msm_gpiomux_config apq8064_mi2s_configs[] __initdata = {
+	{
+		.gpio	= 27,		/* mi2s ws */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 28,		/* mi2s sclk */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 29,		/* mi2s dout3 - TX*/
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 32,		/* mi2s dout0 - RX */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+
+	{
+		.gpio	= 33,		/* mi2s mclk */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+};
+
+static struct msm_gpiomux_config apq8064_mic_i2s_configs[] __initdata = {
+	{
+		.gpio	= 35,		/* mic i2s sclk */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 36,		/* mic i2s ws */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 37,		/* mic i2s din0 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+};
+
+
+static struct msm_gpiomux_config apq8064_spkr_i2s_configs[] __initdata = {
+	{
+		.gpio	= 40,		/* spkr i2s sclk */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_func_2_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 41,		/* spkr i2s dout */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_func_2_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+	{
+		.gpio	= 42,		/* spkr i2s ws */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &i2s_act_cfg,
+			[GPIOMUX_SUSPENDED] = &i2s_sus_cfg,
+		},
+	},
+};
+
+
 static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
 	{	/* TS INTERRUPT */
 		.gpio = 6,
@@ -1351,9 +1477,9 @@
 		pr_err(KERN_ERR "msm_gpiomux_init failed %d\n", rc);
 		return;
 	}
-
-	msm_gpiomux_install(wcnss_5wire_interface,
-			ARRAY_SIZE(wcnss_5wire_interface));
+	if (!(machine_is_mpq8064_hrd()))
+		msm_gpiomux_install(wcnss_5wire_interface,
+				ARRAY_SIZE(wcnss_5wire_interface));
 
 	if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
 		 machine_is_mpq8064_dtv()) {
@@ -1373,10 +1499,28 @@
 
 		msm_gpiomux_install(apq8064_gsbi_configs,
 				ARRAY_SIZE(apq8064_gsbi_configs));
-	}
 
-	msm_gpiomux_install(apq8064_slimbus_config,
-			ARRAY_SIZE(apq8064_slimbus_config));
+		if (!(machine_is_apq8064_mtp() &&
+		(SOCINFO_VERSION_MINOR(platform_version) == 1)))
+			msm_gpiomux_install(apq8064_non_mi2s_gsbi_configs,
+				ARRAY_SIZE(apq8064_non_mi2s_gsbi_configs));
+	}
+	if (machine_is_apq8064_mtp() &&
+	(SOCINFO_VERSION_MINOR(platform_version) == 1)) {
+			msm_gpiomux_install(apq8064_mic_i2s_configs,
+				ARRAY_SIZE(apq8064_mic_i2s_configs));
+			msm_gpiomux_install(apq8064_spkr_i2s_configs,
+				ARRAY_SIZE(apq8064_spkr_i2s_configs));
+			msm_gpiomux_install(apq8064_mi2s_configs,
+				ARRAY_SIZE(apq8064_mi2s_configs));
+			msm_gpiomux_install(apq8064_gsbi1_i2c_2ma_configs,
+				ARRAY_SIZE(apq8064_gsbi1_i2c_2ma_configs));
+	} else {
+		msm_gpiomux_install(apq8064_slimbus_config,
+				ARRAY_SIZE(apq8064_slimbus_config));
+		msm_gpiomux_install(apq8064_gsbi1_i2c_8ma_configs,
+				ARRAY_SIZE(apq8064_gsbi1_i2c_8ma_configs));
+	}
 
 	msm_gpiomux_install(apq8064_audio_codec_configs,
 			ARRAY_SIZE(apq8064_audio_codec_configs));
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 04326aa..3b47d2e 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -126,7 +126,7 @@
 	PM8921_GPIO_INPUT(35, PM_GPIO_PULL_UP_30),
 	PM8921_GPIO_INPUT(38, PM_GPIO_PULL_UP_30),
 	/* TABLA CODEC RESET */
-	PM8921_GPIO_OUTPUT(34, 0, MED),
+	PM8921_GPIO_OUTPUT(34, 1, HIGH),
 	PM8921_GPIO_OUTPUT(13, 0, HIGH),               /* PCIE_CLK_PWR_EN */
 	PM8921_GPIO_INPUT(12, PM_GPIO_PULL_UP_30),     /* PCIE_WAKE_N */
 };
@@ -142,6 +142,10 @@
 	PM8921_GPIO_INPUT(17, PM_GPIO_PULL_UP_1P5),	/* SD_WP */
 };
 
+static struct pm8xxx_gpio_init pm8921_mpq8064_hrd_gpios[] __initdata = {
+	PM8921_GPIO_OUTPUT(37, 0, LOW),	/* MUX1_SEL */
+};
+
 /* Initial PM8917 GPIO configurations */
 static struct pm8xxx_gpio_init pm8917_gpios[] __initdata = {
 	PM8921_GPIO_OUTPUT(14, 1, HIGH),	/* HDMI Mux Selector */
@@ -223,6 +227,10 @@
 		apq8064_configure_gpios(pm8921_mpq_gpios,
 					ARRAY_SIZE(pm8921_mpq_gpios));
 
+	if (machine_is_mpq8064_hrd())
+		apq8064_configure_gpios(pm8921_mpq8064_hrd_gpios,
+					ARRAY_SIZE(pm8921_mpq8064_hrd_gpios));
+
 	for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
 		rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
 					&pm8xxx_mpps[i].config);
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 819f5d9..bbb9a81 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -33,6 +33,9 @@
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.2"),
 	REGULATOR_SUPPLY("lvds_pll_vdda",	"lvds.0"),
 	REGULATOR_SUPPLY("dsi1_pll_vdda",	"mipi_dsi.1"),
+	REGULATOR_SUPPLY("HRD_VDDD_CDC_D",		"tabla2x-slim"),
+	REGULATOR_SUPPLY("HRD_CDC_VDDA_A_1P2V",	"tabla2x-slim"),
+	REGULATOR_SUPPLY("dsi_pll_vdda",	"mdp.0"),
 };
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8921_l3",		NULL),
@@ -44,6 +47,7 @@
 	REGULATOR_SUPPLY("8921_l4",		NULL),
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_otg"),
 	REGULATOR_SUPPLY("iris_vddxo",		"wcnss_wlan.0"),
+	REGULATOR_SUPPLY("bha_vddxo",		"bt_power"),
 };
 VREG_CONSUMERS(L5) = {
 	REGULATOR_SUPPLY("8921_l5",		NULL),
@@ -72,6 +76,7 @@
 VREG_CONSUMERS(L10) = {
 	REGULATOR_SUPPLY("8921_l10",		NULL),
 	REGULATOR_SUPPLY("iris_vddpa",		"wcnss_wlan.0"),
+	REGULATOR_SUPPLY("bha_vddpa",		"bt_power"),
 };
 VREG_CONSUMERS(L11) = {
 	REGULATOR_SUPPLY("8921_l11",		NULL),
@@ -85,6 +90,9 @@
 	REGULATOR_SUPPLY("cam_vdig",		"4-0020"),
 	REGULATOR_SUPPLY("8921_l12",		NULL),
 };
+VREG_CONSUMERS(L13) = {
+	REGULATOR_SUPPLY("8921_l13",		NULL),
+};
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8921_l14",		NULL),
 };
@@ -128,6 +136,8 @@
 	REGULATOR_SUPPLY("CDC_VDDA_A_1P2V",	"tabla-slim"),
 	REGULATOR_SUPPLY("VDDD_CDC_D",		"tabla2x-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_A_1P2V",	"tabla2x-slim"),
+	REGULATOR_SUPPLY("VDDD_CDC_D",		"0-000d"),
+	REGULATOR_SUPPLY("CDC_VDDA_A_1P2V",	"0-000d"),
 };
 VREG_CONSUMERS(L26) = {
 	REGULATOR_SUPPLY("8921_l26",		NULL),
@@ -169,7 +179,12 @@
 	REGULATOR_SUPPLY("CDC_VDD_CP",		"tabla2x-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_TX",		"tabla2x-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_RX",		"tabla2x-slim"),
+	REGULATOR_SUPPLY("VDDIO_CDC",		"0-000d"),
+	REGULATOR_SUPPLY("CDC_VDD_CP",		"0-000d"),
+	REGULATOR_SUPPLY("CDC_VDDA_TX",		"0-000d"),
+	REGULATOR_SUPPLY("CDC_VDDA_RX",		"0-000d"),
 	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
+	REGULATOR_SUPPLY("bha_vddpx",		"bt_power"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-005b"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-0024"),
 	REGULATOR_SUPPLY("vddp",		"0-0048"),
@@ -216,6 +231,7 @@
 	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
 	REGULATOR_SUPPLY("lvds_vdda",		"lvds.0"),
 	REGULATOR_SUPPLY("dsi1_vddio",		"mipi_dsi.1"),
+	REGULATOR_SUPPLY("dsi_pll_vddio",	"mdp.0"),
 	REGULATOR_SUPPLY("hdmi_vdda",		"hdmi_msm.0"),
 };
 VREG_CONSUMERS(USB_OTG) = {
@@ -651,6 +667,7 @@
 	RPM_LDO(L10, 0, 1, 0, 2900000, 2900000, NULL,          0,     0),
 	RPM_LDO(L11, 0, 1, 0, 3000000, 3000000, NULL,          0,     0),
 	RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8921_s4",     0,     0),
+	RPM_LDO(L13, 0, 0, 0, 2220000, 2220000, NULL,          0,     0),
 	RPM_LDO(L14, 0, 1, 0, 1800000, 1800000, NULL,          0,     0),
 	RPM_LDO(L15, 0, 1, 0, 1800000, 2950000, NULL,          0,     0),
 	RPM_LDO(L16, 0, 1, 0, 2800000, 2800000, NULL,          0,     0),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 50da91b..8755f08 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -27,7 +27,7 @@
 #include <linux/spi/spi.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/qcom_crypto_device.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/memory.h>
 #include <linux/memblock.h>
 #include <linux/msm_thermal.h>
@@ -217,6 +217,13 @@
 #endif /* CONFIG_MSM_MULTIMEDIA_USE_ION */
 #endif /* CONFIG_ANDROID_PMEM */
 
+#ifdef CONFIG_BATTERY_BCL
+static struct platform_device battery_bcl_device = {
+	.name = "battery_current_limit",
+	.id = -1,
+};
+#endif
+
 struct fmem_platform_data apq8064_fmem_pdata = {
 };
 
@@ -887,7 +894,7 @@
 };
 
 static int phy_init_seq[] = {
-	0x38, 0x81, /* update DC voltage level */
+	0x68, 0x81, /* update DC voltage level */
 	0x24, 0x82, /* set pre-emphasis and rise/fall time */
 	-1
 };
@@ -964,18 +971,14 @@
 };
 
 static struct epm_chan_properties ads_adc_channel_data[] = {
-	{10, 100}, {500, 50}, {1, 1}, {1, 1},
-	{20, 50}, {10, 100}, {1, 1}, {1, 1},
-	{10, 100}, {10, 100}, {100, 100}, {200, 100},
-	{100, 50}, {2000, 50}, {1000, 50}, {200, 50},
-	{200, 100}, {1, 1}, {20, 50}, {500, 50},
-	{50, 50}, {200, 100}, {500, 100}, {20, 50},
-	{200, 50}, {2000, 100}, {1000, 50}, {100, 50},
-	{200, 100}, {500, 50}, {1000, 100}, {200, 50},
-	{1000, 50}, {50, 50}, {100, 50}, {100, 50},
-	{1, 1}, {1, 1}, {20, 100}, {20, 50},
-	{500, 100}, {1000, 100}, {100, 50}, {1000, 50},
-	{100, 50}, {1000, 100}, {100, 50}, {100, 50},
+	{10, 100}, {1000, 1}, {10, 100}, {1000, 1},
+	{10, 100}, {1000, 1}, {10, 100}, {1000, 1},
+	{10, 100}, {20, 100}, {500, 100}, {5, 100},
+	{1000, 1}, {200, 100}, {50, 100}, {10, 100},
+	{510, 100}, {50, 100}, {20, 100}, {100, 100},
+	{510, 100}, {20, 100}, {50, 100}, {200, 100},
+	{10, 100}, {20, 100}, {1000, 1}, {10, 100},
+	{200, 100}, {510, 100}, {1000, 100}, {200, 100},
 };
 
 static struct epm_adc_platform_data epm_adc_pdata = {
@@ -1148,6 +1151,152 @@
 	},
 };
 
+static struct wcd9xxx_pdata apq8064_tabla_i2c_platform_data = {
+	.irq = MSM_GPIO_TO_INT(77),
+	.irq_base = TABLA_INTERRUPT_BASE,
+	.num_irqs = NR_WCD9XXX_IRQS,
+	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+	.micbias = {
+		.ldoh_v = TABLA_LDOH_2P85_V,
+		.cfilt1_mv = 1800,
+		.cfilt2_mv = 1800,
+		.cfilt3_mv = 1800,
+		.bias1_cfilt_sel = TABLA_CFILT1_SEL,
+		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
+		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
+		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
+	},
+	.regulator = {
+	{
+		.name = "CDC_VDD_CP",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_RX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_TX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+	},
+	{
+		.name = "VDDIO_CDC",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+	},
+	{
+		.name = "VDDD_CDC_D",
+		.min_uV = 1225000,
+		.max_uV = 1250000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_A_1P2V",
+		.min_uV = 1225000,
+		.max_uV = 1250000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+	},
+	},
+};
+
+static struct i2c_board_info apq8064_tabla_i2c_device_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("tabla top level",
+				APQ_8064_TABLA_I2C_SLAVE_ADDR),
+		.platform_data = &apq8064_tabla_i2c_platform_data,
+	},
+	{
+		I2C_BOARD_INFO("tabla analog",
+				APQ_8064_TABLA_ANALOG_I2C_SLAVE_ADDR),
+		.platform_data = &apq8064_tabla_i2c_platform_data,
+	},
+	{
+		I2C_BOARD_INFO("tabla digital1",
+				APQ_8064_TABLA_DIGITAL1_I2C_SLAVE_ADDR),
+		.platform_data = &apq8064_tabla_i2c_platform_data,
+	},
+	{
+		I2C_BOARD_INFO("tabla digital2",
+				APQ_8064_TABLA_DIGITAL2_I2C_SLAVE_ADDR),
+		.platform_data = &apq8064_tabla_i2c_platform_data,
+	},
+};
+
+static struct wcd9xxx_pdata mpq8064_ashiko20_platform_data = {
+	.slimbus_slave_device = {
+		.name = "tabla-slave",
+		.e_addr = {0, 0, 0x60, 0, 0x17, 2},
+	},
+	.irq = MSM_GPIO_TO_INT(42),
+	.irq_base = TABLA_INTERRUPT_BASE,
+	.num_irqs = NR_WCD9XXX_IRQS,
+	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+	.micbias = {
+		.ldoh_v = TABLA_LDOH_2P85_V,
+		.cfilt1_mv = 1800,
+		.cfilt2_mv = 1800,
+		.cfilt3_mv = 1800,
+		.bias1_cfilt_sel = TABLA_CFILT1_SEL,
+		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
+		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
+		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
+	},
+	.regulator = {
+	{
+		.name = "CDC_VDD_CP",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_RX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+	},
+	{
+		.name = "CDC_VDDA_TX",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+	},
+	{
+		.name = "VDDIO_CDC",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+	},
+	{
+		.name = "HRD_VDDD_CDC_D",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+	},
+	{
+		.name = "HRD_CDC_VDDA_A_1P2V",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+	},
+	},
+};
+
+static struct slim_device mpq8064_slim_ashiko20 = {
+	.name = "tabla2x-slim",
+	.e_addr = {0, 1, 0x60, 0, 0x17, 2},
+	.dev = {
+		.platform_data = &mpq8064_ashiko20_platform_data,
+	},
+};
+
+
 /* enable the level shifter for cs8427 to make sure the I2C
  * clock is running at 100KHz and voltage levels are at 3.3
  * and 5 volts
@@ -1292,7 +1441,7 @@
 	/* T6 Object */
 	0, 0, 0, 0, 0, 0,
 	/* T38 Object */
-	14, 2, 0, 24, 5, 12, 0, 0, 0, 0,
+	14, 3, 0, 5, 7, 12, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1300,12 +1449,12 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0,
 	/* T7 Object */
-	100, 10, 50,
+	32, 10, 50,
 	/* T8 Object */
 	25, 0, 20, 20, 0, 0, 0, 0, 0, 0,
 	/* T9 Object */
 	139, 0, 0, 26, 42, 0, 32, 80, 2, 5,
-	0, 5, 5, 0, 10, 30, 10, 10, 255, 2,
+	0, 5, 5, 79, 10, 30, 10, 10, 255, 2,
 	85, 5, 0, 5, 9, 5, 12, 35, 70, 40,
 	20, 5, 0, 0, 0,
 	/* T18 Object */
@@ -1557,10 +1706,16 @@
 /* qseecom bus scaling */
 static struct msm_bus_vectors qseecom_clks_init_vectors[] = {
 	{
-		.src = MSM_BUS_MASTER_SPS,
+		.src = MSM_BUS_MASTER_ADM_PORT0,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ib = 0,
 		.ab = 0,
+		.ib = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT1,
+		.dst = MSM_BUS_SLAVE_GSBI1_UART,
+		.ab = 0,
+		.ib = 0,
 	},
 	{
 		.src = MSM_BUS_MASTER_SPDM,
@@ -1572,10 +1727,16 @@
 
 static struct msm_bus_vectors qseecom_enable_dfab_vectors[] = {
 	{
-		.src = MSM_BUS_MASTER_SPS,
+		.src = MSM_BUS_MASTER_ADM_PORT0,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ib = (492 * 8) * 1000000UL,
-		.ab = (492 * 8) *  100000UL,
+		.ab = 70000000UL,
+		.ib = 70000000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT1,
+		.dst = MSM_BUS_SLAVE_GSBI1_UART,
+		.ab = 2480000000UL,
+		.ib = 2480000000UL,
 	},
 	{
 		.src = MSM_BUS_MASTER_SPDM,
@@ -1587,10 +1748,16 @@
 
 static struct msm_bus_vectors qseecom_enable_sfpb_vectors[] = {
 	{
-		.src = MSM_BUS_MASTER_SPS,
+		.src = MSM_BUS_MASTER_ADM_PORT0,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ib = 0,
 		.ab = 0,
+		.ib = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT1,
+		.dst = MSM_BUS_SLAVE_GSBI1_UART,
+		.ab = 0,
+		.ib = 0,
 	},
 	{
 		.src = MSM_BUS_MASTER_SPDM,
@@ -1607,7 +1774,7 @@
 	},
 	{
 		ARRAY_SIZE(qseecom_enable_dfab_vectors),
-		qseecom_enable_sfpb_vectors,
+		qseecom_enable_dfab_vectors,
 	},
 	{
 		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
@@ -2249,6 +2416,17 @@
 	&apq8064_device_qup_i2c_gsbi4,
 };
 
+static struct platform_device *common_mpq_devices[] __initdata = {
+	&mpq_cpudai_sec_i2s_rx,
+	&mpq_cpudai_mi2s_tx,
+};
+
+static struct platform_device *common_i2s_devices[] __initdata = {
+	&apq_cpudai_mi2s,
+	&apq_cpudai_i2s_rx,
+	&apq_cpudai_i2s_tx,
+};
+
 static struct platform_device *early_common_devices[] __initdata = {
 	&apq8064_device_acpuclk,
 	&apq8064_device_dmov,
@@ -2320,8 +2498,6 @@
 	&apq_pcm_routing,
 	&apq_cpudai0,
 	&apq_cpudai1,
-	&mpq_cpudai_sec_i2s_rx,
-	&mpq_cpudai_mi2s_tx,
 	&apq_cpudai_hdmi_rx,
 	&apq_cpudai_bt_rx,
 	&apq_cpudai_bt_tx,
@@ -2386,6 +2562,9 @@
 	&msm_tsens_device,
 	&apq8064_cache_dump_device,
 	&msm_8064_device_tspp,
+#ifdef CONFIG_BATTERY_BCL
+	&battery_bcl_device,
+#endif
 };
 
 static struct platform_device *cdp_devices[] __initdata = {
@@ -2454,7 +2633,9 @@
 
 static int rf4ce_gpio_init(void)
 {
-	if (!machine_is_mpq8064_cdp())
+	if (!machine_is_mpq8064_cdp() &&
+		!machine_is_mpq8064_hrd() &&
+			!machine_is_mpq8064_dtv())
 		return -EINVAL;
 
 	/* CC2533 SRDY Input */
@@ -2935,6 +3116,14 @@
 	}
 };
 
+static struct i2c_registry apq8064_tabla_i2c_devices[] __initdata = {
+	{
+		.bus = APQ_8064_GSBI1_QUP_I2C_BUS_ID,
+		.info = apq8064_tabla_i2c_device_info,
+		.len = ARRAY_SIZE(apq8064_tabla_i2c_device_info),
+	},
+};
+
 #define SX150X_EXP1_INT_N	PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9)
 #define SX150X_EXP2_INT_N	MSM_GPIO_TO_INT(81)
 
@@ -3013,6 +3202,7 @@
 {
 	u8 mach_mask = 0;
 	int i;
+	u32 version;
 
 #ifdef CONFIG_MSM_CAMERA
 	struct i2c_registry apq8064_camera_i2c_devices = {
@@ -3055,6 +3245,18 @@
 					mpq8064_i2c_devices[i].info,
 					mpq8064_i2c_devices[i].len);
 	}
+
+	if (machine_is_apq8064_mtp()) {
+		version = socinfo_get_platform_version();
+		if (SOCINFO_VERSION_MINOR(version) == 1)
+			for (i = 0; i < ARRAY_SIZE(apq8064_tabla_i2c_devices);
+				 ++i)
+				i2c_register_board_info(
+				apq8064_tabla_i2c_devices[i].bus,
+				apq8064_tabla_i2c_devices[i].info,
+				apq8064_tabla_i2c_devices[i].len);
+	}
+
 }
 
 static void enable_ddr3_regulator(void)
@@ -3093,7 +3295,7 @@
 
 static void __init apq8064_common_init(void)
 {
-	u32 platform_version;
+	u32 platform_version = socinfo_get_platform_version();
 
 	if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
 		apq8064_pm8917_pdata_fixup();
@@ -3146,7 +3348,21 @@
 			machine_is_mpq8064_dtv()))
 		platform_add_devices(common_not_mpq_devices,
 			ARRAY_SIZE(common_not_mpq_devices));
+
+	if ((machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
+			machine_is_mpq8064_dtv()))
+		platform_add_devices(common_mpq_devices,
+			ARRAY_SIZE(common_mpq_devices));
+
+	if (machine_is_apq8064_mtp()) {
+		if (SOCINFO_VERSION_MINOR(platform_version) == 1)
+			platform_add_devices(common_i2s_devices,
+			ARRAY_SIZE(common_i2s_devices));
+	}
+
 	enable_ddr3_regulator();
+	msm_hsic_pdata.swfi_latency =
+		msm_rpmrs_levels[0].latency_us;
 	if (machine_is_apq8064_mtp()) {
 		msm_hsic_pdata.log2_irq_thresh = 5,
 		apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
@@ -3157,7 +3373,6 @@
 
 	if (machine_is_apq8064_mtp()) {
 		mdm_8064_device.dev.platform_data = &mdm_platform_data;
-		platform_version = socinfo_get_platform_version();
 		if (SOCINFO_VERSION_MINOR(platform_version) == 1) {
 			i2s_mdm_8064_device.dev.platform_data =
 				&mdm_platform_data;
@@ -3168,6 +3383,10 @@
 		}
 	}
 	platform_device_register(&apq8064_slim_ctrl);
+	if (machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
+		apq8064_slim_devices[ARRAY_SIZE(apq8064_slim_devices) - 1].\
+			slim_slave = &mpq8064_slim_ashiko20;
+	}
 	slim_register_board_info(apq8064_slim_devices,
 		ARRAY_SIZE(apq8064_slim_devices));
 	if (!PLATFORM_IS_MPQ8064()) {
@@ -3224,6 +3443,11 @@
 #endif
 	}
 
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+	if (machine_is_mpq8064_hrd())
+		apq8064_bt_power_init();
+#endif
+
 	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
 		platform_device_register(&cdp_kp_pdev);
 
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 1437b3b..5d6f988 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -86,6 +86,13 @@
 extern struct msm_camera_board_info apq8064_camera_board_info;
 void apq8064_init_cam(void);
 
+
+/* Tabla slave address for I2C */
+#define APQ_8064_TABLA_I2C_SLAVE_ADDR		0x0d
+#define APQ_8064_TABLA_ANALOG_I2C_SLAVE_ADDR	0x77
+#define APQ_8064_TABLA_DIGITAL1_I2C_SLAVE_ADDR	0x66
+#define APQ_8064_TABLA_DIGITAL2_I2C_SLAVE_ADDR	0x55
+
 #define APQ_8064_GSBI1_QUP_I2C_BUS_ID 0
 #define APQ_8064_GSBI3_QUP_I2C_BUS_ID 3
 #define APQ_8064_GSBI4_QUP_I2C_BUS_ID 4
@@ -103,6 +110,10 @@
 void apq8064_pm8xxx_gpio_mpp_init(void);
 void __init configure_apq8064_pm8917_power_grid(void);
 
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+void __init apq8064_bt_power_init(void);
+#endif
+
 #define PLATFORM_IS_MPQ8064() \
 	(machine_is_mpq8064_hrd() || \
 	 machine_is_mpq8064_dtv() || \
diff --git a/arch/arm/mach-msm/board-8092-gpiomux.c b/arch/arm/mach-msm/board-8092-gpiomux.c
new file mode 100644
index 0000000..823ef70
--- /dev/null
+++ b/arch/arm/mach-msm/board-8092-gpiomux.c
@@ -0,0 +1,53 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+
+static struct gpiomux_setting gpio_uart_config = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_HIGH,
+};
+
+static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
+	{
+		.gpio      = 45,	       /* BLSP8 UART TX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
+		},
+	},
+	{
+		.gpio      = 46,	       /* BLSP8 UART RX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
+		},
+	},
+};
+
+void __init mpq8092_init_gpiomux(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	if (rc) {
+		pr_err(KERN_ERR "mpq8092_init_gpiomux failed %d\n", rc);
+		return;
+	}
+
+	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+}
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
new file mode 100644
index 0000000..0471ff4
--- /dev/null
+++ b/arch/arm/mach-msm/board-8092.c
@@ -0,0 +1,110 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <asm/hardware/gic.h>
+#include <asm/arch_timer.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/socinfo.h>
+#include <mach/board.h>
+
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+
+#include "clock.h"
+
+static struct of_device_id irq_match[] __initdata  = {
+	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
+	{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
+	{}
+};
+
+static struct clk_lookup msm_clocks_dummy[] = {
+	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
+	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
+};
+
+struct clock_init_data mpq8092_clock_init_data __initdata = {
+	.table = msm_clocks_dummy,
+	.size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+void __init mpq8092_init_irq(void)
+{
+	of_irq_init(irq_match);
+}
+
+static void __init mpq8092_dt_timer_init(void)
+{
+	arch_timer_of_register();
+}
+
+static struct sys_timer mpq8092_dt_timer = {
+	.init = mpq8092_dt_timer_init
+};
+
+static void __init mpq8092_dt_init_irq(void)
+{
+	mpq8092_init_irq();
+}
+
+static void __init mpq8092_dt_map_io(void)
+{
+	msm_map_mpq8092_io();
+	if (socinfo_init() < 0)
+		pr_err("%s: socinfo_init() failed\n", __func__);
+
+}
+
+static struct of_dev_auxdata mpq8092_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
+			"msm_serial_hsl.0", NULL),
+	{}
+};
+
+static void __init mpq8092_init(struct of_dev_auxdata **adata)
+{
+	mpq8092_init_gpiomux();
+	*adata = mpq8092_auxdata_lookup;
+	msm_clock_init(&mpq8092_clock_init_data);
+}
+
+static void __init mpq8092_dt_init(void)
+{
+	struct of_dev_auxdata *adata = NULL;
+
+	mpq8092_init(&adata);
+	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+}
+
+static const char *mpq8092_dt_match[] __initconst = {
+	"qcom,mpq8092-sim",
+	NULL
+};
+
+DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
+	.map_io = mpq8092_dt_map_io,
+	.init_irq = mpq8092_dt_init_irq,
+	.init_machine = mpq8092_dt_init,
+	.handle_irq = gic_handle_irq,
+	.timer = &mpq8092_dt_timer,
+	.dt_compat = mpq8092_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
new file mode 100644
index 0000000..eb88ef4
--- /dev/null
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -0,0 +1,29 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+
+void __init msm8226_init_gpiomux(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	if (rc) {
+		pr_err(KERN_ERR "msm_8226_init_gpiomux failed %d\n", rc);
+		return;
+	}
+}
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
new file mode 100644
index 0000000..c845a3a
--- /dev/null
+++ b/arch/arm/mach-msm/board-8226.c
@@ -0,0 +1,114 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/memory.h>
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
+#include <asm/mach/map.h>
+#include <asm/hardware/gic.h>
+#include <asm/arch_timer.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+#ifdef CONFIG_ION_MSM
+#include <mach/ion.h>
+#endif
+#include <mach/msm_memtypes.h>
+#include <mach/socinfo.h>
+#include <mach/board.h>
+#include "clock.h"
+
+static struct clk_lookup msm_clocks_dummy[] = {
+	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
+	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
+};
+
+struct clock_init_data msm_dummy_clock_init_data __initdata = {
+	.table = msm_clocks_dummy,
+	.size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+static struct of_device_id irq_match[] __initdata  = {
+	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
+	{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
+	{}
+};
+
+static struct of_dev_auxdata msm8226_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
+			"msm_serial_hsl.0", NULL),
+	{}
+};
+
+static void __init msm8226_dt_timer_init(void)
+{
+	arch_timer_of_register();
+}
+
+static struct sys_timer msm8226_dt_timer = {
+	.init = msm8226_dt_timer_init
+};
+
+void __init msm8226_init_irq(void)
+{
+	of_irq_init(irq_match);
+}
+
+void __init msm8226_init(struct of_dev_auxdata **adata)
+{
+	msm8226_init_gpiomux();
+
+	msm_clock_init(&msm_dummy_clock_init_data);
+
+	*adata = msm8226_auxdata_lookup;
+}
+
+void __init msm8226_dt_init(void)
+{
+	struct of_dev_auxdata *adata = NULL;
+	msm8226_init(&adata);
+
+	if (socinfo_init() < 0)
+		pr_err("%s: socinfo_init() failed\n", __func__);
+
+	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+}
+
+
+static const char *msm8226_dt_match[] __initconst = {
+	"qcom,msm8226",
+	NULL
+};
+
+DT_MACHINE_START(MSM8226_DT, "Qualcomm MSM 8226 (Flattened Device Tree)")
+	.map_io = msm_map_msm8226_io,
+	.init_irq = msm8226_init_irq,
+	.init_machine = msm8226_dt_init,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm8226_dt_timer,
+	.dt_compat = msm8226_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 1352928..883e04d 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -331,6 +331,28 @@
 	},
 };
 
+static struct msm_bus_vectors cam_dual_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 302071680,
+		.ib  = 1208286720,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 206807040,
+		.ib  = 488816640,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 540000000,
+		.ib  = 1350000000,
+	},
+};
+
+
 static struct msm_bus_paths cam_bus_client_config[] = {
 	{
 		ARRAY_SIZE(cam_init_vectors),
@@ -356,6 +378,10 @@
 		ARRAY_SIZE(cam_video_ls_vectors),
 		cam_video_ls_vectors,
 	},
+	{
+		ARRAY_SIZE(cam_dual_vectors),
+		cam_dual_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 4b4a51a..a0bfabf 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -22,7 +22,7 @@
 #include <mach/board.h>
 #include <mach/gpiomux.h>
 #include <mach/socinfo.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/ion.h>
 
 #include "devices.h"
@@ -59,8 +59,16 @@
 #define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME	"mipi_video_simulator_vga"
 #define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME	"mipi_cmd_renesas_fwvga"
 #define HDMI_PANEL_NAME	"hdmi_msm"
+#define MHL_PANEL_NAME "hdmi_msm,mhl_8334"
 #define TVOUT_PANEL_NAME	"tvout_msm"
 
+static unsigned char mhl_display_enabled;
+
+unsigned char msm8930_mhl_display_enabled(void)
+{
+	return mhl_display_enabled;
+}
+
 static struct resource msm_fb_resources[] = {
 	{
 		.flags = IORESOURCE_DMA,
@@ -833,3 +841,28 @@
 	pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
 			size, addr, __pa(addr));
 }
+
+void __init msm8930_set_display_params(char *prim_panel, char *ext_panel)
+{
+	if (strnlen(prim_panel, PANEL_NAME_MAX_LEN)) {
+		strlcpy(msm_fb_pdata.prim_panel_name, prim_panel,
+			PANEL_NAME_MAX_LEN);
+		pr_debug("msm_fb_pdata.prim_panel_name %s\n",
+			msm_fb_pdata.prim_panel_name);
+	}
+	if (strnlen(ext_panel, PANEL_NAME_MAX_LEN)) {
+		strlcpy(msm_fb_pdata.ext_panel_name, ext_panel,
+			PANEL_NAME_MAX_LEN);
+		pr_debug("msm_fb_pdata.ext_panel_name %s\n",
+			msm_fb_pdata.ext_panel_name);
+
+		if (!strncmp((char *)msm_fb_pdata.ext_panel_name,
+			MHL_PANEL_NAME, strnlen(MHL_PANEL_NAME,
+				PANEL_NAME_MAX_LEN))) {
+			pr_debug("MHL is external display by boot parameter\n");
+			mhl_display_enabled = 1;
+		}
+	}
+
+	hdmi_msm_data.is_mhl_enabled = mhl_display_enabled;
+}
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index 2331b0b..fcb5abd 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -785,7 +785,7 @@
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
 	msm_gpiomux_install(msm8960_hdmi_configs,
 			ARRAY_SIZE(msm8960_hdmi_configs));
-	if (machine_is_msm8930_fluid())
+	if (msm8930_mhl_display_enabled())
 		msm_gpiomux_install(msm8930_mhl_configs,
 				ARRAY_SIZE(msm8930_mhl_configs));
 #endif
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index b6e20fd..59e4ba1 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -180,6 +180,8 @@
 
 /* Initial PM8917 MPP configurations */
 static struct pm8xxx_mpp_init pm8917_mpps[] __initdata = {
+	PM8917_MPP_INIT(PM8XXX_AMUX_MPP_3, A_INPUT,
+				PM8XXX_MPP_AIN_AMUX_CH8, DIN_TO_INT),
 };
 
 void __init msm8930_pm8038_gpio_mpp_init(void)
@@ -441,8 +443,22 @@
 	.priority		= 0,
 };
 
+/*
+ *	0x254=0xC8 (Threshold=110, preamp bias=01)
+ *	0x255=0xC1 (Hold=110, max attn=0000, mute=1)
+ *	0x256=0xB0 (decay=101, attack=10, delay=0)
+ */
+
 static struct pm8xxx_spk_platform_data pm8xxx_spk_pdata = {
 	.spk_add_enable		= false,
+	.cd_ng_threshold	= 0x6,
+	.cd_nf_preamp_bias	= 0x1,
+	.cd_ng_hold		= 0x6,
+	.cd_ng_max_atten	= 0x0,
+	.noise_mute		= 1,
+	.cd_ng_decay_rate	= 0x5,
+	.cd_ng_attack_rate	= 0x2,
+	.cd_delay		= 0x0,
 };
 
 static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
@@ -513,6 +529,8 @@
 		ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
 	{"pa_therm0", ADC_MPP_1_AMUX3, CHAN_PATH_SCALING1, AMUX_RSV1,
 		ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
+	{"pa_therm1", ADC_MPP_1_AMUX8, CHAN_PATH_SCALING1, AMUX_RSV1,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
 };
 
 static struct pm8xxx_adc_properties pm8917_adc_data = {
diff --git a/arch/arm/mach-msm/board-8930-regulator-pm8038.c b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
index ed9d802..208f15b 100644
--- a/arch/arm/mach-msm/board-8930-regulator-pm8038.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
@@ -35,6 +35,7 @@
 	REGULATOR_SUPPLY("8038_l2",		NULL),
 	REGULATOR_SUPPLY("iris_vdddig",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("dsi_vdda",		"mipi_dsi.1"),
+	REGULATOR_SUPPLY("dsi_pll_vdda",	"mdp.0"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.0"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.1"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.2"),
@@ -146,6 +147,7 @@
 VREG_CONSUMERS(L23) = {
 	REGULATOR_SUPPLY("8038_l23",		NULL),
 	REGULATOR_SUPPLY("dsi_vddio",		"mipi_dsi.1"),
+	REGULATOR_SUPPLY("dsi_pll_vddio",	"mdp.0"),
 	REGULATOR_SUPPLY("hdmi_avdd",		"hdmi_msm.0"),
 	REGULATOR_SUPPLY("hdmi_vcc",		"hdmi_msm.0"),
 	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 7760f07..aad0f3d 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -76,7 +76,7 @@
 #include <mach/msm_xo.h>
 #include <mach/restart.h>
 
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/ion.h>
 #include <mach/mdm2.h>
 #include <mach/msm_rtb.h>
@@ -730,8 +730,28 @@
 	place_movable_zone();
 }
 
+static char prim_panel_name[PANEL_NAME_MAX_LEN];
+static char ext_panel_name[PANEL_NAME_MAX_LEN];
+
+static int __init prim_display_setup(char *param)
+{
+	if (strnlen(param, PANEL_NAME_MAX_LEN))
+		strlcpy(prim_panel_name, param, PANEL_NAME_MAX_LEN);
+	return 0;
+}
+early_param("prim_display", prim_display_setup);
+
+static int __init ext_display_setup(char *param)
+{
+	if (strnlen(param, PANEL_NAME_MAX_LEN))
+		strlcpy(ext_panel_name, param, PANEL_NAME_MAX_LEN);
+	return 0;
+}
+early_param("ext_display", ext_display_setup);
+
 static void __init msm8930_reserve(void)
 {
+	msm8930_set_display_params(prim_panel_name, ext_panel_name);
 	msm_reserve();
 	if (msm8930_fmem_pdata.size) {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
@@ -971,6 +991,12 @@
 		.ab = 0,
 	},
 	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_SPS,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
 		.src = MSM_BUS_MASTER_SPDM,
 		.dst = MSM_BUS_SLAVE_SPDM,
 		.ib = 0,
@@ -986,6 +1012,12 @@
 		.ab = (492 * 8) *  100000UL,
 	},
 	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_SPS,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) *  100000UL,
+	},
+	{
 		.src = MSM_BUS_MASTER_SPDM,
 		.dst = MSM_BUS_SLAVE_SPDM,
 		.ib = 0,
@@ -1001,6 +1033,12 @@
 		.ab = 0,
 	},
 	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_SPS,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
 		.src = MSM_BUS_MASTER_SPDM,
 		.dst = MSM_BUS_SLAVE_SPDM,
 		.ib = (64 * 8) * 1000000UL,
@@ -1451,7 +1489,7 @@
 static int hsusb_phy_init_seq[] = {
 	0x44, 0x80, /* set VBUS valid threshold
 			and disconnect valid threshold */
-	0x38, 0x81, /* update DC voltage level */
+	0x68, 0x81, /* update DC voltage level */
 	0x24, 0x82, /* set preemphasis and rise/fall time */
 	0x13, 0x83, /* set source impedance adjusment */
 	-1};
@@ -2751,6 +2789,10 @@
 	else
 		msm_clock_init(&msm8930_clock_init_data);
 	msm_otg_pdata.phy_init_seq = hsusb_phy_init_seq;
+	if (msm8930_mhl_display_enabled()) {
+		mhl_platform_data.mhl_enabled = true;
+		msm_otg_pdata.mhl_enable = true;
+	}
 	msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
 	android_usb_pdata.swfi_latency =
 			msm_rpmrs_levels[0].latency_us;
diff --git a/arch/arm/mach-msm/board-8930.h b/arch/arm/mach-msm/board-8930.h
index 7c1ad5b..055576f 100644
--- a/arch/arm/mach-msm/board-8930.h
+++ b/arch/arm/mach-msm/board-8930.h
@@ -132,6 +132,7 @@
 void msm8930_init_fb(void);
 void msm8930_init_pmic(void);
 extern void msm8930_add_vidc_device(void);
+unsigned char msm8930_mhl_display_enabled(void);
 
 /*
  * TODO: When physical 8930/PM8038 hardware becomes
@@ -148,6 +149,7 @@
 void msm8930_allocate_fb_region(void);
 void msm8930_pm8038_gpio_mpp_init(void);
 void msm8930_pm8917_gpio_mpp_init(void);
+void msm8930_set_display_params(char *prim_panel, char *ext_panel);
 void msm8930_mdp_writeback(struct memtype_reserve *reserve_table);
 void __init msm8930_init_gpu(void);
 
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index c00535b..792eea4 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -400,6 +400,40 @@
 	},
 };
 
+static struct msm_bus_vectors cam_dual_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 348192000,
+		.ib  = 1208286720,
+	},
+	{
+		.src = MSM_BUS_MASTER_VPE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 206807040,
+		.ib  = 488816640,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 540000000,
+		.ib  = 1350000000,
+	},
+	{
+		.src = MSM_BUS_MASTER_JPEG_ENC,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_MM_IMEM,
+		.ab  = 43200000,
+		.ib  = 69120000,
+	},
+};
+
+
 
 static struct msm_bus_paths cam_bus_client_config[] = {
 	{
@@ -426,6 +460,10 @@
 		ARRAY_SIZE(cam_video_ls_vectors),
 		cam_video_ls_vectors,
 	},
+	{
+		ARRAY_SIZE(cam_dual_vectors),
+		cam_dual_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index f993ed8..3052902 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -15,7 +15,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/bootmem.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <mach/msm_bus_board.h>
@@ -586,6 +586,8 @@
 	.mem_hid = MEMTYPE_EBI1,
 #endif
 	.cont_splash_enabled = 0x01,
+	.splash_screen_addr = 0x00,
+	.splash_screen_size = 0x00,
 	.mdp_iommu_split_domain = 0,
 };
 
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index bcfd558..2fa98b6 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -14,6 +14,7 @@
 #include <linux/regulator/pm8xxx-regulator.h>
 #include <linux/regulator/msm-gpio-regulator.h>
 #include <mach/rpm-regulator.h>
+#include <mach/socinfo.h>
 
 #include "board-8960.h"
 
@@ -30,6 +31,7 @@
 VREG_CONSUMERS(L2) = {
 	REGULATOR_SUPPLY("8921_l2",		NULL),
 	REGULATOR_SUPPLY("dsi_vdda",		"mipi_dsi.1"),
+	REGULATOR_SUPPLY("dsi_pll_vdda",	"mdp.0"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.0"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.1"),
 	REGULATOR_SUPPLY("mipi_csi_vdd",	"msm_csid.2"),
@@ -115,6 +117,7 @@
 VREG_CONSUMERS(L23) = {
 	REGULATOR_SUPPLY("8921_l23",		NULL),
 	REGULATOR_SUPPLY("dsi_vddio",		"mipi_dsi.1"),
+	REGULATOR_SUPPLY("dsi_pll_vddio",	"mdp.0"),
 	REGULATOR_SUPPLY("hdmi_avdd",		"hdmi_msm.0"),
 	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
 	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.1"),
@@ -219,9 +222,16 @@
 	REGULATOR_SUPPLY("cam_vio",		"4-0020"),
 	REGULATOR_SUPPLY("cam_vio",		"4-0034"),
 };
+/* This mapping is used for CDP only. */
+VREG_CONSUMERS(CDP_LVS6) = {
+	REGULATOR_SUPPLY("8921_lvs6",		NULL),
+	REGULATOR_SUPPLY("vdd-io",		"spi0.0"),
+};
+/* This mapping is used for non-CDP targets only. */
 VREG_CONSUMERS(LVS6) = {
 	REGULATOR_SUPPLY("8921_lvs6",		NULL),
-	REGULATOR_SUPPLY("vdd_io",		"spi0.0"),
+	REGULATOR_SUPPLY("vdd-io",		"spi0.0"),
+	REGULATOR_SUPPLY("vdd-phy",		"spi0.0"),
 };
 VREG_CONSUMERS(LVS7) = {
 	REGULATOR_SUPPLY("8921_lvs7",		NULL),
@@ -241,7 +251,7 @@
 };
 VREG_CONSUMERS(EXT_L2) = {
 	REGULATOR_SUPPLY("ext_l2",		NULL),
-	REGULATOR_SUPPLY("vdd_phy",		"spi0.0"),
+	REGULATOR_SUPPLY("vdd-phy",		"spi0.0"),
 };
 VREG_CONSUMERS(EXT_3P3V) = {
 	REGULATOR_SUPPLY("ext_3p3v",		NULL),
@@ -605,3 +615,26 @@
 	.consumer_map		= msm_rpm_regulator_consumer_mapping,
 	.consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
 };
+
+/*
+ * Fix up regulator consumer data that moves to a different regulator based on
+ * the current target.
+ */
+void __init configure_msm8960_power_grid(void)
+{
+	static struct rpm_regulator_init_data *rpm_data;
+	int i;
+
+	if (machine_is_msm8960_cdp()) {
+		/* Only modify LVS6 consumers for CDP targets. */
+		for (i = 0; i < ARRAY_SIZE(msm_rpm_regulator_init_data); i++) {
+			rpm_data = &msm_rpm_regulator_init_data[i];
+			if (rpm_data->id == RPM_VREG_ID_PM8921_LVS6) {
+				rpm_data->init_data.consumer_supplies
+					= vreg_consumers_CDP_LVS6;
+				rpm_data->init_data.num_consumer_supplies
+					= ARRAY_SIZE(vreg_consumers_CDP_LVS6);
+			}
+		}
+	}
+}
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index a3de539..7c9f652 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -77,7 +77,7 @@
 #endif
 
 #include <linux/smsc3503.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/ion.h>
 #include <mach/mdm2.h>
 #include <mach/mdm-peripheral.h>
@@ -1056,6 +1056,12 @@
 		.ab = 0,
 	},
 	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_SPS,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
 		.src = MSM_BUS_MASTER_SPDM,
 		.dst = MSM_BUS_SLAVE_SPDM,
 		.ib = 0,
@@ -1071,6 +1077,12 @@
 		.ab = (492 * 8) *  100000UL,
 	},
 	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_SPS,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) * 100000UL,
+	},
+	{
 		.src = MSM_BUS_MASTER_SPDM,
 		.dst = MSM_BUS_SLAVE_SPDM,
 		.ib = 0,
@@ -1086,6 +1098,12 @@
 		.ab = 0,
 	},
 	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_SPS,
+		.ib = 0,
+		.ab = 0,
+	},
+	{
 		.src = MSM_BUS_MASTER_SPDM,
 		.dst = MSM_BUS_SLAVE_SPDM,
 		.ib = (64 * 8) * 1000000UL,
@@ -1100,7 +1118,7 @@
 	},
 	{
 		ARRAY_SIZE(qseecom_enable_dfab_vectors),
-		qseecom_enable_sfpb_vectors,
+		qseecom_enable_dfab_vectors,
 	},
 	{
 		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
@@ -1434,7 +1452,7 @@
 static int wr_phy_init_seq[] = {
 	0x44, 0x80, /* set VBUS valid threshold
 			and disconnect valid threshold */
-	0x38, 0x81, /* update DC voltage level */
+	0x68, 0x81, /* update DC voltage level */
 	0x14, 0x82, /* set preemphasis and rise/fall time */
 	0x13, 0x83, /* set source impedance adjusment */
 	-1};
@@ -1442,7 +1460,7 @@
 static int liquid_v1_phy_init_seq[] = {
 	0x44, 0x80,/* set VBUS valid threshold
 			and disconnect valid threshold */
-	0x3C, 0x81,/* update DC voltage level */
+	0x6C, 0x81,/* update DC voltage level */
 	0x18, 0x82,/* set preemphasis and rise/fall time */
 	0x23, 0x83,/* set source impedance sdjusment */
 	-1};
@@ -1450,7 +1468,7 @@
 static int sglte_phy_init_seq[] = {
 	0x44, 0x80, /* set VBUS valid threshold
 			and disconnect valid threshold */
-	0x3A, 0x81, /* update DC voltage level */
+	0x6A, 0x81, /* update DC voltage level */
 	0x24, 0x82, /* set preemphasis and rise/fall time */
 	0x13, 0x83, /* set source impedance adjusment */
 	-1};
@@ -2102,7 +2120,7 @@
 	/* T6 Object */
 	0, 0, 0, 0, 0, 0,
 	/* T38 Object */
-	12, 4, 0, 5, 7, 12, 0, 0, 0, 0,
+	12, 5, 0, 28, 8, 12, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -2110,7 +2128,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0,
 	/* T7 Object */
-	100, 16, 50,
+	32, 16, 50,
 	/* T8 Object */
 	25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
 	/* T9 Object */
@@ -2362,7 +2380,6 @@
 static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi4_pdata = {
 	.clk_freq = 100000,
 	.src_clk_rate = 24000000,
-	.keep_ahb_clk_on = 1,
 };
 
 static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi3_pdata = {
@@ -2448,6 +2465,13 @@
 };
 #endif
 
+#ifdef CONFIG_BATTERY_BCL
+static struct platform_device battery_bcl_device = {
+	.name = "battery_current_limit",
+	.id = -1,
+};
+#endif
+
 static struct platform_device msm8960_device_ext_5v_vreg __devinitdata = {
 	.name	= GPIO_REGULATOR_DEV_NAME,
 	.id	= PM8921_MPP_PM_TO_SYS(7),
@@ -2672,6 +2696,9 @@
 #ifdef CONFIG_MSM_FAKE_BATTERY
 	&fish_battery_device,
 #endif
+#ifdef CONFIG_BATTERY_BCL
+	&battery_bcl_device,
+#endif
 	&msm8960_fmem_device,
 #ifdef CONFIG_ANDROID_PMEM
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -2720,8 +2747,6 @@
 
 static struct platform_device *cdp_devices[] __initdata = {
 	&msm_8960_q6_lpass,
-	&msm_8960_q6_mss_fw,
-	&msm_8960_q6_mss_sw,
 	&msm_8960_riva,
 	&msm_pil_tzapps,
 	&msm_pil_dsps,
@@ -2775,6 +2800,9 @@
 
 static void __init msm8960_i2c_init(void)
 {
+	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+		msm8960_i2c_qup_gsbi4_pdata.keep_ahb_clk_on = 1;
+
 	msm8960_device_qup_i2c_gsbi4.dev.platform_data =
 					&msm8960_i2c_qup_gsbi4_pdata;
 
@@ -2794,19 +2822,24 @@
 		msm_kgsl_3d0.dev.platform_data;
 	uint32_t soc_platform_version = socinfo_get_version();
 
+	/* Fixup data that needs to change based on GPU ID */
 	if (cpu_is_msm8960ab()) {
 		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
 		/* 8960PRO nominal clock rate is 325Mhz instead of 320Mhz */
 		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 325000000;
-	} else if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
-		kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
-		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
-	} else if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
-		/* 8960v3 GPU registers returns 5 for patch release
-		 * but it should be 6, so dummy up the chipid here
-		 * based the platform type
-		 */
-		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+	} else {
+		kgsl_3d0_pdata->iommu_count = 1;
+		if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
+			kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+			kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
+		}
+		if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
+			/* 8960v3 GPU registers returns 5 for patch release
+			 * but it should be 6, so dummy up the chipid here
+			 * based the platform type
+			 */
+			kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+		}
 	}
 
 	/* Register the 3D core */
@@ -3138,6 +3171,7 @@
 	regulator_suppress_info_printing();
 	if (msm_xo_init())
 		pr_err("Failed to initialize XO votes\n");
+	configure_msm8960_power_grid();
 	platform_device_register(&msm8960_device_rpm_regulator);
 	msm_clock_init(&msm8960_clock_init_data);
 	if (machine_is_msm8960_liquid())
@@ -3210,6 +3244,11 @@
 	msm8960_add_vidc_device();
 
 	msm8960_pm8921_gpio_mpp_init();
+	/* Don't add modem devices on APQ targets */
+	if (socinfo_get_id() != 124) {
+		platform_device_register(&msm_8960_q6_mss_fw);
+		platform_device_register(&msm_8960_q6_mss_sw);
+	}
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
 	msm8960_init_smsc_hub();
 	msm8960_init_hsic();
diff --git a/arch/arm/mach-msm/board-8960.h b/arch/arm/mach-msm/board-8960.h
index 8f1c619..382723c 100644
--- a/arch/arm/mach-msm/board-8960.h
+++ b/arch/arm/mach-msm/board-8960.h
@@ -81,6 +81,7 @@
 void msm8960_init_pmic(void);
 void msm8960_init_mmc(void);
 int msm8960_init_gpiomux(void);
+void __init configure_msm8960_power_grid(void);
 unsigned char msm8960_hdmi_as_primary_selected(void);
 void msm8960_allocate_fb_region(void);
 void msm8960_set_display_params(char *prim_panel, char *ext_panel);
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 74c503d..479dec6 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -17,7 +17,7 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 
-#define KS8851_IRQ_GPIO 90
+#define KS8851_IRQ_GPIO 94
 
 static struct gpiomux_setting gpio_uart_config = {
 	.func = GPIOMUX_FUNC_2,
@@ -34,15 +34,15 @@
 
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 static struct gpiomux_setting gpio_eth_config = {
-	.pull = GPIOMUX_PULL_NONE,
-	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+	.drv = GPIOMUX_DRV_2MA,
 	.func = GPIOMUX_FUNC_GPIO,
 };
 
-static struct gpiomux_setting gpio_spi_cs_config = {
+static struct gpiomux_setting gpio_spi_cs2_config = {
 	.func = GPIOMUX_FUNC_4,
-	.drv = GPIOMUX_DRV_12MA,
-	.pull = GPIOMUX_PULL_NONE,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting gpio_spi_config = {
@@ -51,6 +51,12 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+static struct gpiomux_setting gpio_spi_cs1_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
 static struct msm_gpiomux_config msm_eth_configs[] = {
 	{
 		.gpio = KS8851_IRQ_GPIO,
@@ -60,6 +66,19 @@
 	},
 };
 #endif
+
+static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting wcnss_5wire_active_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv  = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct gpiomux_setting gpio_i2c_config = {
 	.func = GPIOMUX_FUNC_3,
 	.drv = GPIOMUX_DRV_8MA,
@@ -126,6 +145,56 @@
 	},
 
 };
+
+static struct gpiomux_setting hdmi_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting hdmi_active_1_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting hdmi_active_2_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config msm_hdmi_configs[] __initdata = {
+	{
+		.gpio = 31,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &hdmi_active_1_cfg,
+			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 32,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &hdmi_active_1_cfg,
+			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 33,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &hdmi_active_1_cfg,
+			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 34,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &hdmi_active_2_cfg,
+			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 	{
@@ -147,9 +216,15 @@
 		},
 	},
 	{
-		.gpio      = 9,		/* BLSP1 QUP SPI_CS_N */
+		.gpio      = 9,		/* BLSP1 QUP SPI_CS2A_N */
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+			[GPIOMUX_SUSPENDED] = &gpio_spi_cs2_config,
+		},
+	},
+	{
+		.gpio      = 8,		/* BLSP1 QUP SPI_CS1_N */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_cs1_config,
 		},
 	},
 #endif
@@ -361,6 +436,43 @@
 		},
 	},
 };
+static struct msm_gpiomux_config wcnss_5wire_interface[] = {
+	{
+		.gpio = 36,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &wcnss_5wire_active_cfg,
+			[GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 37,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &wcnss_5wire_active_cfg,
+			[GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 38,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &wcnss_5wire_active_cfg,
+			[GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 39,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &wcnss_5wire_active_cfg,
+			[GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 40,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &wcnss_5wire_active_cfg,
+			[GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+		},
+	},
+};
 
 static struct msm_gpiomux_config msm_taiko_config[] __initdata = {
 	{
@@ -385,6 +497,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(wcnss_5wire_interface,
+				ARRAY_SIZE(wcnss_5wire_interface));
 
 	msm_gpiomux_install(msm8974_slimbus_config,
 			ARRAY_SIZE(msm8974_slimbus_config));
@@ -394,4 +508,6 @@
 	msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
 
 	msm_gpiomux_install(msm_taiko_config, ARRAY_SIZE(msm_taiko_config));
+
+	msm_gpiomux_install(msm_hdmi_configs, ARRAY_SIZE(msm_hdmi_configs));
 }
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 8d593f6..dcc0d01 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -268,11 +268,6 @@
 	msm_reserve();
 }
 
-static struct platform_device android_usb_device = {
-	.name	= "android_usb",
-	.id	= -1,
-};
-
 #define BIMC_BASE	0xfc380000
 #define BIMC_SIZE	0x0006A000
 #define SYS_NOC_BASE	0xfc460000
@@ -463,7 +458,6 @@
 void __init msm_8974_add_devices(void)
 {
 	platform_device_register(&msm_device_smd_8974);
-	platform_device_register(&android_usb_device);
 }
 
 /*
diff --git a/arch/arm/mach-msm/board-9615-display.c b/arch/arm/mach-msm/board-9615-display.c
index 74bc984..4e4ce7a 100644
--- a/arch/arm/mach-msm/board-9615-display.c
+++ b/arch/arm/mach-msm/board-9615-display.c
@@ -15,7 +15,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/bootmem.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <asm/mach-types.h>
 #include <mach/msm_memtypes.h>
 #include <mach/board.h>
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index e599739..4523cf7 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -29,7 +29,7 @@
 #include <linux/power/ltc4088-charger.h>
 #include <linux/gpio.h>
 #include <linux/msm_tsens.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/memory.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -612,7 +612,7 @@
 static int shelby_phy_init_seq[] = {
 	0x44, 0x80,/* set VBUS valid threshold and
 			disconnect valid threshold */
-	0x38, 0x81, /* update DC voltage level */
+	0x68, 0x81, /* update DC voltage level */
 	0x24, 0x82,/* set preemphasis and rise/fall time */
 	0x13, 0x83,/* set source impedance adjustment */
 	-1};
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index d1d85fc..7a1e2ff 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -397,7 +397,9 @@
 
 	}
 	if (machine_is_msm8625_evb() || machine_is_msm7627a_evb()
-			|| machine_is_msm8625_evt()) {
+				||  machine_is_msm8625_evt()
+				|| machine_is_msm7627a_qrd3()
+				|| machine_is_msm8625_qrd7()) {
 		sensor_board_info_ov7692.cam_vreg =
 			ov7692_gpio_vreg;
 		sensor_board_info_ov7692.num_vreg =
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index 0949c5f..79f213e 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -336,6 +336,10 @@
 				goto set_gpio_fail;
 			}
 			gpio_free(gpio_wlan_sys_rest_en);
+		} else {
+			pr_err("%s: WLAN sys_rest_en GPIO %d request failed %d\n",
+				__func__, gpio_wlan_sys_rest_en, rc);
+			goto out;
 		}
 	}
 
@@ -373,6 +377,7 @@
 		gpio_free(GPIO_WLAN_3V3_EN);
 reg_disable:
 	wlan_switch_regulators(0);
+out:
 	pr_info("WLAN power-down failed\n");
 	return rc;
 }
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 8df1c9b..2a51e66 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -38,7 +38,6 @@
 #include <linux/i2c.h>
 #include <linux/i2c/sx150x.h>
 #include <linux/gpio.h>
-#include <linux/android_pmem.h>
 #include <linux/bootmem.h>
 #include <linux/mfd/marimba.h>
 #include <mach/vreg.h>
@@ -49,7 +48,7 @@
 #include <linux/smsc911x.h>
 #include <linux/atmel_maxtouch.h>
 #include <linux/msm_adc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include "devices.h"
 #include "timer.h"
 #include "board-msm7x27a-regulator.h"
@@ -60,8 +59,8 @@
 #include "pm-boot.h"
 #include "board-msm7627a.h"
 
-#define PMEM_KERNEL_EBI1_SIZE	0x3A000
-#define MSM_PMEM_AUDIO_SIZE	0x1F4000
+#define RESERVE_KERNEL_EBI1_SIZE	0x3A000
+#define MSM_RESERVE_AUDIO_SIZE	0x1F4000
 
 #if defined(CONFIG_GPIO_SX150X)
 enum {
@@ -159,12 +158,11 @@
 };
 
 #ifdef CONFIG_ARCH_MSM7X27A
-#define MSM_PMEM_MDP_SIZE                0x1B00000
-#define MSM7x25A_MSM_PMEM_MDP_SIZE       0x1500000
-
-#define MSM_PMEM_ADSP_SIZE      0x1200000
-#define MSM7x25A_MSM_PMEM_ADSP_SIZE      0xB91000
-
+#define MSM_RESERVE_MDP_SIZE		0x1B00000
+#define MSM7x25A_MSM_RESERVE_MDP_SIZE   0x1500000
+#define MSM_RESERVE_ADSP_SIZE		0x1200000
+#define MSM7x25A_MSM_RESERVE_ADSP_SIZE	0xB91000
+#define CAMERA_ZSL_SIZE			(SZ_1M * 60)
 #endif
 
 #ifdef CONFIG_ION_MSM
@@ -442,61 +440,23 @@
 	.v_addr = MSM_CFG_CTL_BASE,
 };
 
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
-	.name = "pmem_adsp",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_adsp_device = {
-	.name = "android_pmem",
-	.id = 1,
-	.dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE;
-static int __init pmem_mdp_size_setup(char *p)
+static unsigned reserve_mdp_size = MSM_RESERVE_MDP_SIZE;
+static int __init reserve_mdp_size_setup(char *p)
 {
-	pmem_mdp_size = memparse(p, NULL);
+	reserve_mdp_size = memparse(p, NULL);
 	return 0;
 }
 
-early_param("pmem_mdp_size", pmem_mdp_size_setup);
+early_param("reserve_mdp_size", reserve_mdp_size_setup);
 
-static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
-static int __init pmem_adsp_size_setup(char *p)
+static unsigned reserve_adsp_size = MSM_RESERVE_ADSP_SIZE;
+static int __init reserve_adsp_size_setup(char *p)
 {
-	pmem_adsp_size = memparse(p, NULL);
+	reserve_adsp_size = memparse(p, NULL);
 	return 0;
 }
 
-early_param("pmem_adsp_size", pmem_adsp_size_setup);
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
-	.name = "pmem_audio",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 0,
-	.memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_audio_device = {
-	.name = "android_pmem",
-	.id = 2,
-	.dev = { .platform_data = &android_pmem_audio_pdata },
-};
-
-static struct android_pmem_platform_data android_pmem_pdata = {
-	.name = "pmem",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI1,
-};
-static struct platform_device android_pmem_device = {
-	.name = "android_pmem",
-	.id = 0,
-	.dev = { .platform_data = &android_pmem_pdata },
-};
+early_param("reserve_adsp_size", reserve_adsp_size_setup);
 
 static u32 msm_calculate_batt_capacity(u32 current_voltage);
 
@@ -690,9 +650,6 @@
 
 static struct platform_device *common_devices[] __initdata = {
 	&android_usb_device,
-	&android_pmem_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
 	&msm_device_nand,
 	&msm_device_snd,
 	&msm_device_cad,
@@ -723,35 +680,39 @@
 	&msm8625_kgsl_3d0,
 };
 
-static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
-static int __init pmem_kernel_ebi1_size_setup(char *p)
+static unsigned reserve_kernel_ebi1_size = RESERVE_KERNEL_EBI1_SIZE;
+static int __init reserve_kernel_ebi1_size_setup(char *p)
 {
-	pmem_kernel_ebi1_size = memparse(p, NULL);
+	reserve_kernel_ebi1_size = memparse(p, NULL);
 	return 0;
 }
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+early_param("reserve_kernel_ebi1_size", reserve_kernel_ebi1_size_setup);
 
-static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
-static int __init pmem_audio_size_setup(char *p)
+static unsigned reserve_audio_size = MSM_RESERVE_AUDIO_SIZE;
+static int __init reserve_audio_size_setup(char *p)
 {
-	pmem_audio_size = memparse(p, NULL);
+	reserve_audio_size = memparse(p, NULL);
 	return 0;
 }
-early_param("pmem_audio_size", pmem_audio_size_setup);
+early_param("reserve_audio_size", reserve_audio_size_setup);
 
 static void fix_sizes(void)
 {
 	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
-		pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
-		pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE;
+		reserve_mdp_size = MSM7x25A_MSM_RESERVE_MDP_SIZE;
+		reserve_adsp_size = MSM7x25A_MSM_RESERVE_ADSP_SIZE;
 	} else {
-		pmem_mdp_size = MSM_PMEM_MDP_SIZE;
-		pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+		reserve_mdp_size = MSM_RESERVE_MDP_SIZE;
+		reserve_adsp_size = MSM_RESERVE_ADSP_SIZE;
 	}
+
+	if (get_ddr_size() > SZ_512M)
+		reserve_adsp_size = CAMERA_ZSL_SIZE;
 #ifdef CONFIG_ION_MSM
-	msm_ion_camera_size = pmem_adsp_size;
-	msm_ion_audio_size = (MSM_PMEM_AUDIO_SIZE + PMEM_KERNEL_EBI1_SIZE);
-	msm_ion_sf_size = pmem_mdp_size;
+	msm_ion_camera_size = reserve_adsp_size;
+	msm_ion_audio_size = (MSM_RESERVE_AUDIO_SIZE +
+					RESERVE_KERNEL_EBI1_SIZE);
+	msm_ion_sf_size = reserve_mdp_size;
 #endif
 }
 
@@ -777,7 +738,7 @@
 			.name	= ION_VMALLOC_HEAP_NAME,
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-		/* PMEM_ADSP = CAMERA */
+		/* ION_ADSP = CAMERA */
 		{
 			.id	= ION_CAMERA_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
@@ -785,7 +746,7 @@
 			.memory_type = ION_EBI_TYPE,
 			.extra_data = (void *)&co_ion_pdata,
 		},
-		/* PMEM_AUDIO */
+		/* ION_AUDIO */
 		{
 			.id	= ION_AUDIO_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
@@ -793,7 +754,7 @@
 			.memory_type = ION_EBI_TYPE,
 			.extra_data = (void *)&co_ion_pdata,
 		},
-		/* PMEM_MDP = SF */
+		/* ION_MDP = SF */
 		{
 			.id	= ION_SF_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
@@ -834,50 +795,6 @@
 }
 #endif
 
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
-		&android_pmem_adsp_pdata,
-		&android_pmem_audio_pdata,
-		&android_pmem_pdata,
-};
-#endif
-#endif
-
-static void __init size_pmem_devices(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	android_pmem_adsp_pdata.size = pmem_adsp_size;
-	android_pmem_pdata.size = pmem_mdp_size;
-	android_pmem_audio_pdata.size = pmem_audio_size;
-
-#endif
-#endif
-}
-
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
-	msm7x27a_reserve_table[p->memory_type].size += p->size;
-}
-#endif
-#endif
-
-static void __init reserve_pmem_memory(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	unsigned int i;
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i)
-		reserve_memory_for(pmem_pdata_array[i]);
-
-	msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-#endif
-#endif
-}
-
 static void __init size_ion_devices(void)
 {
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -899,8 +816,6 @@
 static void __init msm7x27a_calculate_reserve_sizes(void)
 {
 	fix_sizes();
-	size_pmem_devices();
-	reserve_pmem_memory();
 	size_ion_devices();
 	reserve_ion_memory();
 	reserve_rtb_memory();
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 47d847e..281d055 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -103,7 +103,7 @@
 #include "pm-boot.h"
 #include "board-storage-common-a.h"
 
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/ion.h>
 #include <mach/msm_rtb.h>
 
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 58cb4ab..f6b0c4f 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -20,7 +20,6 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/i2c.h>
-#include <linux/android_pmem.h>
 #include <linux/bootmem.h>
 #include <linux/mfd/marimba.h>
 #include <linux/power_supply.h>
@@ -32,7 +31,7 @@
 #include <linux/input/ft5x06_ts.h>
 #include <linux/msm_adc.h>
 #include <linux/regulator/msm-gpio-regulator.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <asm/mach/mmc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -61,8 +60,8 @@
 #include "board-msm7x27a-regulator.h"
 #include "board-msm7627a.h"
 
-#define PMEM_KERNEL_EBI1_SIZE	0x3A000
-#define MSM_PMEM_AUDIO_SIZE	0x1F4000
+#define RESERVE_KERNEL_EBI1_SIZE	0x3A000
+#define MSM_RESERVE_AUDIO_SIZE	0x1F4000
 #define BAHAMA_SLAVE_ID_FM_REG 0x02
 #define FM_GPIO	83
 #define BT_PCM_BCLK_MODE  0x88
@@ -130,8 +129,10 @@
 };
 
 #ifdef CONFIG_ARCH_MSM7X27A
-#define MSM_PMEM_MDP_SIZE       0x1B00000
-#define MSM_PMEM_ADSP_SIZE      0x1200000
+
+#define MSM_RESERVE_MDP_SIZE       0x1B00000
+#define MSM_RESERVE_ADSP_SIZE      0x1200000
+#define CAMERA_ZSL_SIZE            (SZ_1M * 60)
 
 #ifdef CONFIG_ION_MSM
 #define MSM_ION_HEAP_NUM	4
@@ -389,61 +390,23 @@
 	.v_addr = MSM_CFG_CTL_BASE,
 };
 
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
-	.name = "pmem_adsp",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_adsp_device = {
-	.name = "android_pmem",
-	.id = 1,
-	.dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE;
-static int __init pmem_mdp_size_setup(char *p)
+static unsigned reserve_mdp_size = MSM_RESERVE_MDP_SIZE;
+static int __init reserve_mdp_size_setup(char *p)
 {
-	pmem_mdp_size = memparse(p, NULL);
+	reserve_mdp_size = memparse(p, NULL);
 	return 0;
 }
 
-early_param("pmem_mdp_size", pmem_mdp_size_setup);
+early_param("reserve_mdp_size", reserve_mdp_size_setup);
 
-static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
-static int __init pmem_adsp_size_setup(char *p)
+static unsigned reserve_adsp_size = MSM_RESERVE_ADSP_SIZE;
+static int __init reserve_adsp_size_setup(char *p)
 {
-	pmem_adsp_size = memparse(p, NULL);
+	reserve_adsp_size = memparse(p, NULL);
 	return 0;
 }
 
-early_param("pmem_adsp_size", pmem_adsp_size_setup);
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
-	.name = "pmem_audio",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 0,
-	.memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_audio_device = {
-	.name = "android_pmem",
-	.id = 2,
-	.dev = { .platform_data = &android_pmem_audio_pdata },
-};
-
-static struct android_pmem_platform_data android_pmem_pdata = {
-	.name = "pmem",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI1,
-};
-static struct platform_device android_pmem_device = {
-	.name = "android_pmem",
-	.id = 0,
-	.dev = { .platform_data = &android_pmem_pdata },
-};
+early_param("reserve_adsp_size", reserve_adsp_size_setup);
 
 static u32 msm_calculate_batt_capacity(u32 current_voltage);
 
@@ -635,9 +598,6 @@
 
 static struct platform_device *common_devices[] __initdata = {
 	&android_usb_device,
-	&android_pmem_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
 	&msm_batt_device,
 	&msm_device_adspdec,
 	&msm_device_snd,
@@ -697,28 +657,32 @@
 	&msm8625_kgsl_3d0,
 };
 
-static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
-static int __init pmem_kernel_ebi1_size_setup(char *p)
+static unsigned reserve_kernel_ebi1_size = RESERVE_KERNEL_EBI1_SIZE;
+static int __init reserve_kernel_ebi1_size_setup(char *p)
 {
-	pmem_kernel_ebi1_size = memparse(p, NULL);
+	reserve_kernel_ebi1_size = memparse(p, NULL);
 	return 0;
 }
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+early_param("reserve_kernel_ebi1_size", reserve_kernel_ebi1_size_setup);
 
-static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
-static int __init pmem_audio_size_setup(char *p)
+
+static unsigned reserve_audio_size = MSM_RESERVE_AUDIO_SIZE;
+static int __init reserve_audio_size_setup(char *p)
 {
-	pmem_audio_size = memparse(p, NULL);
+	reserve_audio_size = memparse(p, NULL);
 	return 0;
 }
-early_param("pmem_audio_size", pmem_audio_size_setup);
+early_param("reserve_audio_size", reserve_audio_size_setup);
 
 static void fix_sizes(void)
 {
+	if (get_ddr_size() > SZ_512M)
+		reserve_adsp_size = CAMERA_ZSL_SIZE;
 #ifdef CONFIG_ION_MSM
-	msm_ion_camera_size = pmem_adsp_size;
-	msm_ion_audio_size = (MSM_PMEM_AUDIO_SIZE + PMEM_KERNEL_EBI1_SIZE);
-	msm_ion_sf_size = pmem_mdp_size;
+	msm_ion_camera_size = reserve_adsp_size;
+	msm_ion_audio_size = (MSM_RESERVE_AUDIO_SIZE +
+						RESERVE_KERNEL_EBI1_SIZE);
+	msm_ion_sf_size = reserve_mdp_size;
 #endif
 }
 
@@ -744,7 +708,7 @@
 			.name	= ION_VMALLOC_HEAP_NAME,
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-		/* PMEM_ADSP = CAMERA */
+		/* ION_ADSP = CAMERA */
 		{
 			.id	= ION_CAMERA_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
@@ -752,7 +716,7 @@
 			.memory_type = ION_EBI_TYPE,
 			.extra_data = (void *)&co_ion_pdata,
 		},
-		/* PMEM_AUDIO */
+		/* ION_AUDIO */
 		{
 			.id	= ION_AUDIO_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
@@ -760,7 +724,7 @@
 			.memory_type = ION_EBI_TYPE,
 			.extra_data = (void *)&co_ion_pdata,
 		},
-		/* PMEM_MDP = SF */
+		/* ION_MDP = SF */
 		{
 			.id	= ION_SF_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
@@ -801,49 +765,6 @@
 }
 #endif
 
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
-		&android_pmem_adsp_pdata,
-		&android_pmem_audio_pdata,
-		&android_pmem_pdata,
-};
-#endif
-#endif
-
-static void __init size_pmem_devices(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	android_pmem_adsp_pdata.size = pmem_adsp_size;
-	android_pmem_pdata.size = pmem_mdp_size;
-	android_pmem_audio_pdata.size = pmem_audio_size;
-#endif
-#endif
-}
-
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
-	msm7627a_reserve_table[p->memory_type].size += p->size;
-}
-#endif
-#endif
-
-static void __init reserve_pmem_memory(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	unsigned int i;
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i)
-		reserve_memory_for(pmem_pdata_array[i]);
-
-	msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-#endif
-#endif
-}
-
 static void __init size_ion_devices(void)
 {
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -865,8 +786,6 @@
 static void __init msm7627a_calculate_reserve_sizes(void)
 {
 	fix_sizes();
-	size_pmem_devices();
-	reserve_pmem_memory();
 	size_ion_devices();
 	reserve_ion_memory();
 	reserve_rtb_memory();
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index f3ac7d7..8cce34b 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -239,7 +239,6 @@
 		.rate = 19200000,
 		.ops = &clk_ops_tcxo,
 		CLK_INIT(tcxo_clk.c),
-		.warned = true,
 	},
 };
 
@@ -266,7 +265,6 @@
 		.rate = 24576000,
 		.ops = &clk_ops_lpxo,
 		CLK_INIT(lpxo_clk.c),
-		.warned = true,
 	},
 };
 
@@ -281,7 +279,6 @@
 		.rate = 768000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll1_clk.c),
-		.warned = true,
 	},
 };
 
@@ -296,7 +293,6 @@
 		.rate = 806400000, /* TODO: Support scaling */
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll2_clk.c),
-		.warned = true,
 	},
 };
 
@@ -325,7 +321,6 @@
 		.rate = 891000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
-		.warned = true,
 	},
 };
 
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 373cf47..01bc9dd 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -519,7 +519,6 @@
 		.rate = 800000000,
 		.ops = &clk_ops_local_pll,
 		CLK_INIT(pll2_clk.c),
-		.warned = true,
 	},
 };
 
@@ -533,7 +532,6 @@
 		.vdd_class = &vdd_sr2_hdmi_pll,
 		.fmax[VDD_SR2_HDMI_PLL_ON] = ULONG_MAX,
 		CLK_INIT(pll3_clk.c),
-		.warned = true,
 	},
 };
 
@@ -548,7 +546,6 @@
 		.rate = 393216000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
-		.warned = true,
 	},
 };
 
@@ -563,7 +560,6 @@
 		.rate = 384000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll8_clk.c),
-		.warned = true,
 	},
 };
 
@@ -578,7 +574,6 @@
 		.rate = 480000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll14_clk.c),
-		.warned = true,
 	},
 };
 
@@ -590,7 +585,6 @@
 		.rate = 975000000,
 		.ops = &clk_ops_local_pll,
 		CLK_INIT(pll15_clk.c),
-		.warned = true,
 	},
 };
 
@@ -2720,7 +2714,6 @@
 		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
 		CLK_INIT(csi0_src_clk.c),
-		.warned = true,
 	},
 };
 
@@ -2738,7 +2731,6 @@
 		.dbg_name = "csi0_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(csi0_clk.c),
-		.warned = true,
 	},
 };
 
@@ -2778,7 +2770,6 @@
 		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
 		CLK_INIT(csi1_src_clk.c),
-		.warned = true,
 	},
 };
 
@@ -2796,7 +2787,6 @@
 		.dbg_name = "csi1_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(csi1_clk.c),
-		.warned = true,
 	},
 };
 
@@ -2836,7 +2826,6 @@
 		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
 		CLK_INIT(csi2_src_clk.c),
-		.warned = true,
 	},
 };
 
@@ -2854,7 +2843,6 @@
 		.dbg_name = "csi2_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(csi2_clk.c),
-		.warned = true,
 	},
 };
 
@@ -2883,6 +2871,7 @@
 };
 
 struct pix_rdi_clk {
+	bool prepared;
 	bool enabled;
 	unsigned long cur_rate;
 
@@ -2908,6 +2897,7 @@
 	unsigned long flags;
 	struct pix_rdi_clk *rdi = to_pix_rdi_clk(c);
 	struct clk **mux_map = pix_rdi_mux_map;
+	unsigned long old_rate = rdi->cur_rate;
 
 	/*
 	 * These clocks select three inputs via two muxes. One mux selects
@@ -2918,7 +2908,7 @@
 	 * needs to be on at what time.
 	 */
 	for (i = 0; mux_map[i]; i++) {
-		ret = clk_enable(mux_map[i]);
+		ret = clk_prepare_enable(mux_map[i]);
 		if (ret)
 			goto err;
 	}
@@ -2927,11 +2917,21 @@
 		goto err;
 	}
 	/* Keep the new source on when switching inputs of an enabled clock */
-	if (rdi->enabled) {
-		clk_disable(mux_map[rdi->cur_rate]);
-		clk_enable(mux_map[rate]);
+	if (rdi->prepared) {
+		ret = clk_prepare(mux_map[rate]);
+		if (ret)
+			goto err;
 	}
-	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	spin_lock_irqsave(&c->lock, flags);
+	if (rdi->enabled) {
+		ret = clk_enable(mux_map[rate]);
+		if (ret) {
+			spin_unlock_irqrestore(&c->lock, flags);
+			clk_unprepare(mux_map[rate]);
+			goto err;
+		}
+	}
+	spin_lock(&local_clock_reg_lock);
 	reg = readl_relaxed(rdi->s2_reg);
 	reg &= ~rdi->s2_mask;
 	reg |= rate == 2 ? rdi->s2_mask : 0;
@@ -2953,10 +2953,16 @@
 	mb();
 	udelay(1);
 	rdi->cur_rate = rate;
-	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+	spin_unlock(&local_clock_reg_lock);
+
+	if (rdi->enabled)
+		clk_disable(mux_map[old_rate]);
+	spin_unlock_irqrestore(&c->lock, flags);
+	if (rdi->prepared)
+		clk_unprepare(mux_map[old_rate]);
 err:
 	for (i--; i >= 0; i--)
-		clk_disable(mux_map[i]);
+		clk_disable_unprepare(mux_map[i]);
 
 	return 0;
 }
@@ -2966,6 +2972,13 @@
 	return to_pix_rdi_clk(c)->cur_rate;
 }
 
+static int pix_rdi_clk_prepare(struct clk *c)
+{
+	struct pix_rdi_clk *rdi = to_pix_rdi_clk(c);
+	rdi->prepared = true;
+	return 0;
+}
+
 static int pix_rdi_clk_enable(struct clk *c)
 {
 	unsigned long flags;
@@ -2990,6 +3003,12 @@
 	rdi->enabled = false;
 }
 
+static void pix_rdi_clk_unprepare(struct clk *c)
+{
+	struct pix_rdi_clk *rdi = to_pix_rdi_clk(c);
+	rdi->prepared = false;
+}
+
 static int pix_rdi_clk_reset(struct clk *c, enum clk_reset_action action)
 {
 	return branch_reset(&to_pix_rdi_clk(c)->b, action);
@@ -3026,8 +3045,10 @@
 }
 
 static struct clk_ops clk_ops_pix_rdi_8960 = {
+	.prepare = pix_rdi_clk_prepare,
 	.enable = pix_rdi_clk_enable,
 	.disable = pix_rdi_clk_disable,
+	.unprepare = pix_rdi_clk_unprepare,
 	.handoff = pix_rdi_clk_handoff,
 	.set_rate = pix_rdi_clk_set_rate,
 	.get_rate = pix_rdi_clk_get_rate,
@@ -4742,7 +4763,6 @@
 static DEFINE_CLK_VOTER(dfab_sps_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c, 0);
-static DEFINE_CLK_VOTER(dfab_qseecom_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c, 0);
 
@@ -5462,7 +5482,6 @@
 	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,	"msm_sps"),
 	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
-	CLK_LOOKUP("bus_clk",		dfab_qseecom_clk.c,	"qseecom"),
 
 	CLK_LOOKUP("alt_core_clk",    usb_hsic_xcvr_fs_clk.c,  "msm_hsic_host"),
 	CLK_LOOKUP("phy_clk",	      usb_hsic_hsic_clk.c,     "msm_hsic_host"),
@@ -5813,7 +5832,6 @@
 	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,	"msm_sps"),
 	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
-	CLK_LOOKUP("bus_clk",		dfab_qseecom_clk.c,	"qseecom"),
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
 	CLK_LOOKUP("mem_clk",		ebi1_acpu_a_clk.c, ""),
@@ -6145,7 +6163,6 @@
 	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,	"msm_sps"),
 	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
-	CLK_LOOKUP("bus_clk",		dfab_qseecom_clk.c,	"qseecom"),
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
 	CLK_LOOKUP("mem_clk",		ebi1_acpu_a_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 357f0b7..b054e08 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -35,7 +35,6 @@
 	GCC_BASE,
 	MMSS_BASE,
 	LPASS_BASE,
-	MSS_BASE,
 	APCS_BASE,
 	N_BASES,
 };
@@ -45,7 +44,6 @@
 #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 MSS_REG_BASE(x) (void __iomem *)(virt_bases[MSS_BASE] + (x))
 #define APCS_REG_BASE(x) (void __iomem *)(virt_bases[APCS_BASE] + (x))
 
 #define GPLL0_MODE_REG                 0x0000
@@ -112,7 +110,6 @@
 #define MMSS_DEBUG_CLK_CTL_REG         0x0900
 #define LPASS_DEBUG_CLK_CTL_REG        0x29000
 #define LPASS_LPA_PLL_VOTE_APPS_REG    0x2000
-#define MSS_DEBUG_CLK_CTL_REG          0x0078
 
 #define GLB_CLK_DIAG_REG               0x001C
 
@@ -300,7 +297,6 @@
 #define OXILI_BCR                 0x4020
 #define OXILICX_BCR               0x4030
 #define LPASS_Q6SS_BCR            0x6000
-#define MSS_Q6SS_BCR              0x1068
 
 #define OCMEM_SYS_NOC_AXI_CBCR                   0x0244
 #define OCMEM_NOC_CFG_AHB_CBCR                   0x0248
@@ -498,8 +494,6 @@
 #define LPASS_Q6_AXI_CBCR			 0x11C0
 #define Q6SS_AHBM_CBCR				 0x22004
 #define AUDIO_WRAPPER_BR_CBCR			 0x24000
-#define MSS_XO_Q6_CBCR                           0x108C
-#define MSS_BUS_Q6_CBCR                          0x10A4
 #define MSS_CFG_AHB_CBCR                         0x0280
 #define MSS_Q6_BIMC_AXI_CBCR			 0x0284
 
@@ -526,7 +520,7 @@
 #define dsipll_750_mm_source_val 1
 #define dsipll0_byte_mm_source_val 1
 #define dsipll0_pixel_mm_source_val 1
-#define hdmipll_297_mm_source_val 3
+#define hdmipll_mm_source_val 3
 
 #define F(f, s, div, m, n) \
 	{ \
@@ -550,6 +544,17 @@
 			| BVAL(10, 8, s##_mm_source_val), \
 	}
 
+#define F_HDMI(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s##_clk_src, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
+			| BVAL(10, 8, s##_mm_source_val), \
+	}
+
 #define F_MDSS(f, s, div, m, n) \
 	{ \
 		.freq_hz = (f), \
@@ -638,13 +643,13 @@
 #define OXILI_ID	0x1
 #define OCMEM_ID	0x2
 
-enum {
-	D0_ID = 1,
-	D1_ID,
-	A0_ID,
-	A1_ID,
-	A2_ID,
-};
+#define D0_ID		 1
+#define D1_ID		 2
+#define A0_ID		 3
+#define A1_ID		 4
+#define A2_ID		 5
+#define DIFF_CLK_ID	 7
+#define DIV_CLK_ID	11
 
 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);
@@ -667,6 +672,8 @@
 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_clk, div_a_clk, DIV_CLK_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);
@@ -684,7 +691,6 @@
 		.rate = 600000000,
 		.dbg_name = "gpll0_clk_src",
 		.ops = &clk_ops_pll_vote,
-		.warned = true,
 		CLK_INIT(gpll0_clk_src.c),
 	},
 };
@@ -700,7 +706,6 @@
 		.rate = 480000000,
 		.dbg_name = "gpll1_clk_src",
 		.ops = &clk_ops_pll_vote,
-		.warned = true,
 		CLK_INIT(gpll1_clk_src.c),
 	},
 };
@@ -716,7 +721,6 @@
 		.rate = 491520000,
 		.dbg_name = "lpapll0_clk_src",
 		.ops = &clk_ops_pll_vote,
-		.warned = true,
 		CLK_INIT(lpapll0_clk_src.c),
 	},
 };
@@ -732,7 +736,6 @@
 		.dbg_name = "mmpll0_clk_src",
 		.rate = 800000000,
 		.ops = &clk_ops_pll_vote,
-		.warned = true,
 		CLK_INIT(mmpll0_clk_src.c),
 	},
 };
@@ -748,7 +751,6 @@
 		.dbg_name = "mmpll1_clk_src",
 		.rate = 846000000,
 		.ops = &clk_ops_pll_vote,
-		.warned = true,
 		CLK_INIT(mmpll1_clk_src.c),
 	},
 };
@@ -762,7 +764,6 @@
 		.dbg_name = "mmpll3_clk_src",
 		.rate = 1000000000,
 		.ops = &clk_ops_local_pll,
-		.warned = true,
 		CLK_INIT(mmpll3_clk_src.c),
 	},
 };
@@ -1987,9 +1988,9 @@
 	.en_mask = BIT(0),
 	.base = &virt_bases[GCC_BASE],
 	.c = {
-		.dbg_name = "gcc_ce1_ahb_clk",
+		.dbg_name = "gcc_ce2_ahb_clk",
 		.ops = &clk_ops_vote,
-		CLK_INIT(gcc_ce1_ahb_clk.c),
+		CLK_INIT(gcc_ce2_ahb_clk.c),
 	},
 };
 
@@ -1999,7 +2000,7 @@
 	.en_mask = BIT(1),
 	.base = &virt_bases[GCC_BASE],
 	.c = {
-		.dbg_name = "gcc_ce1_axi_clk",
+		.dbg_name = "gcc_ce2_axi_clk",
 		.ops = &clk_ops_vote,
 		CLK_INIT(gcc_ce2_axi_clk.c),
 	},
@@ -2382,7 +2383,7 @@
 		.dbg_name = "axi_clk_src",
 		.ops = &clk_ops_rcg,
 		VDD_DIG_FMAX_MAP3(LOW, 150000000, NOMINAL, 282000000,
-				  HIGH, 320000000),
+				  HIGH, 400000000),
 		CLK_INIT(axi_clk_src.c),
 	},
 };
@@ -2996,14 +2997,84 @@
 	},
 };
 
+static int hdmi_pll_clk_enable(struct clk *c)
+{
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	ret = hdmi_pll_enable();
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+	return ret;
+}
+
+static void hdmi_pll_clk_disable(struct clk *c)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	hdmi_pll_disable();
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+}
+
+static int hdmi_pll_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	rc = hdmi_pll_set_rate(rate);
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	return rc;
+}
+
+static struct clk *hdmi_pll_clk_get_parent(struct clk *c)
+{
+	return &cxo_clk_src.c;
+}
+
+static struct clk_ops clk_ops_hdmi_pll = {
+	.enable = hdmi_pll_clk_enable,
+	.disable = hdmi_pll_clk_disable,
+	.set_rate = hdmi_pll_clk_set_rate,
+	.get_parent = hdmi_pll_clk_get_parent,
+};
+
+static struct clk hdmipll_clk_src = {
+	.dbg_name = "hdmipll_clk_src",
+	.ops = &clk_ops_hdmi_pll,
+	CLK_INIT(hdmipll_clk_src),
+};
+
 static struct clk_freq_tbl ftbl_mdss_extpclk_clk[] = {
-	F_MDSS(148500000, hdmipll_297,   2,   0,   0),
+	/*
+	 * The zero rate is required since suspend/resume wipes out the HDMI PHY
+	 * registers. This entry allows the HDMI driver to switch the cached
+	 * rate to zero before suspend and back to the real rate after resume.
+	 */
+	F_HDMI(        0, hdmipll, 1, 0, 0),
+	F_HDMI( 25200000, hdmipll, 1, 0, 0),
+	F_HDMI( 27030000, hdmipll, 1, 0, 0),
+	F_HDMI( 74250000, hdmipll, 1, 0, 0),
+	F_HDMI(148500000, hdmipll, 1, 0, 0),
+	F_HDMI(297000000, hdmipll, 1, 0, 0),
 	F_END
 };
 
+/*
+ * Unlike other clocks, the HDMI rate is adjusted through PLL
+ * re-programming. It is also routed through an HID divider.
+ */
+static void set_rate_hdmi(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
+{
+	clk_set_rate(nf->src_clk, nf->freq_hz);
+	set_rate_hid(rcg, nf);
+}
+
 static struct rcg_clk extpclk_clk_src = {
 	.cmd_rcgr_reg = EXTPCLK_CMD_RCGR,
-	.set_rate = set_rate_hid,
+	.set_rate = set_rate_hdmi,
 	.freq_tbl = ftbl_mdss_extpclk_clk,
 	.current_freq = &rcg_dummy_freq,
 	.base = &virt_bases[MMSS_BASE],
@@ -4509,31 +4580,6 @@
 	},
 };
 
-static struct branch_clk mss_xo_q6_clk = {
-	.cbcr_reg = MSS_XO_Q6_CBCR,
-	.bcr_reg = MSS_Q6SS_BCR,
-	.has_sibling = 1,
-	.base = &virt_bases[MSS_BASE],
-	.c = {
-		.dbg_name = "mss_xo_q6_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(mss_xo_q6_clk.c),
-		.depends = &gcc_mss_cfg_ahb_clk.c,
-	},
-};
-
-static struct branch_clk mss_bus_q6_clk = {
-	.cbcr_reg = MSS_BUS_Q6_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[MSS_BASE],
-	.c = {
-		.dbg_name = "mss_bus_q6_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(mss_bus_q6_clk.c),
-		.depends = &gcc_mss_cfg_ahb_clk.c,
-	},
-};
-
 static DEFINE_CLK_MEASURE(l2_m_clk);
 static DEFINE_CLK_MEASURE(krait0_m_clk);
 static DEFINE_CLK_MEASURE(krait1_m_clk);
@@ -4718,8 +4764,6 @@
 	{&q6ss_ahbm_clk.c,			LPASS_BASE, 0x001d},
 	{&audio_core_ixfabric_clk.c,		LPASS_BASE, 0x0059},
 	{&audio_wrapper_br_clk.c,		LPASS_BASE, 0x0022},
-	{&mss_bus_q6_clk.c,			MSS_BASE, 0x003b},
-	{&mss_xo_q6_clk.c,			MSS_BASE, 0x0007},
 
 	{&l2_m_clk,				APCS_BASE, 0x0081},
 	{&krait0_m_clk,				APCS_BASE, 0x0080},
@@ -4783,13 +4827,6 @@
 		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
 		break;
 
-	case MSS_BASE:
-		writel_relaxed(0, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
-		clk_sel = 0x32;
-		regval = BVAL(5, 0, measure_mux[i].debug_mux);
-		writel_relaxed(regval, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
-		break;
-
 	case APCS_BASE:
 		clk->multiplier = 4;
 		clk_sel = 0x16A;
@@ -4966,6 +5003,7 @@
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-lpass"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-mss"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-mba"),
+	CLK_LOOKUP("xo",	cxo_clk_src.c,	"fb000000.qcom,wcnss-wlan"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil_pronto"),
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
 
@@ -4974,9 +5012,10 @@
 	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9924000.i2c"),
 	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991e000.serial"),
 	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, "f9924000.i2c"),
 	CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, "f9923000.spi"),
+	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9923000.spi"),
 	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, ""),
@@ -5013,6 +5052,7 @@
 	CLK_LOOKUP("core_clk", gcc_blsp2_uart5_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_uart6_apps_clk.c, ""),
 
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c, ""),
 	CLK_LOOKUP("core_clk", gcc_ce1_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_ce2_clk.c, ""),
 	CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, ""),
@@ -5062,6 +5102,7 @@
 	CLK_LOOKUP("sleep_clk", gcc_usb30_sleep_clk.c, "msm_dwc3"),
 	CLK_LOOKUP("sleep_a_clk", gcc_usb2a_phy_sleep_clk.c, "msm_dwc3"),
 	CLK_LOOKUP("sleep_b_clk", gcc_usb2b_phy_sleep_clk.c, "msm_dwc3"),
+	CLK_LOOKUP("ref_clk", diff_clk.c, "msm_dwc3"),
 	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c,     "msm_otg"),
 	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c,   "msm_otg"),
 	CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c,	  "msm_hsic_host"),
@@ -5090,9 +5131,9 @@
 
 	/* MM sensor clocks */
 	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6e.qcom,camera"),
-	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6c.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "6c.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6e.qcom,camera"),
-	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6c.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "6c.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, ""),
 	CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, ""),
 	CLK_LOOKUP("cam_clk", camss_mclk3_clk.c, ""),
@@ -5126,30 +5167,52 @@
 	CLK_LOOKUP("csiphy_timer_clk", camss_phy2_csi2phytimer_clk.c,
 		"fda0b400.qcom,csiphy"),
 	/* CSID clocks */
-	CLK_LOOKUP("csi_ahb_clk", camss_csi0_ahb_clk.c,	"fda08000.qcom,csid"),
-	CLK_LOOKUP("csi_src_clk", csi0_clk_src.c,	"fda08000.qcom,csid"),
-	CLK_LOOKUP("csi_phy_clk", camss_csi0phy_clk.c,	"fda08000.qcom,csid"),
-	CLK_LOOKUP("csi_clk", camss_csi0_clk.c,		"fda08000.qcom,csid"),
-	CLK_LOOKUP("csi_pix_clk", camss_csi0pix_clk.c,	"fda08000.qcom,csid"),
-	CLK_LOOKUP("csi_rdi_clk", camss_csi0rdi_clk.c,	"fda08000.qcom,csid"),
-	CLK_LOOKUP("csi_ahb_clk", camss_csi1_ahb_clk.c,	"fda08400.qcom,csid"),
-	CLK_LOOKUP("csi_src_clk", csi1_clk_src.c,	"fda08400.qcom,csid"),
-	CLK_LOOKUP("csi_phy_clk", camss_csi1phy_clk.c,	"fda08400.qcom,csid"),
-	CLK_LOOKUP("csi_clk", camss_csi1_clk.c,		"fda08400.qcom,csid"),
-	CLK_LOOKUP("csi_pix_clk", camss_csi1pix_clk.c,	"fda08400.qcom,csid"),
-	CLK_LOOKUP("csi_rdi_clk", camss_csi1rdi_clk.c,	"fda08400.qcom,csid"),
-	CLK_LOOKUP("csi_ahb_clk", camss_csi2_ahb_clk.c,	"fda08800.qcom,csid"),
-	CLK_LOOKUP("csi_src_clk", csi2_clk_src.c,	"fda08800.qcom,csid"),
-	CLK_LOOKUP("csi_phy_clk", camss_csi2phy_clk.c,	"fda08800.qcom,csid"),
-	CLK_LOOKUP("csi_clk", camss_csi2_clk.c,		"fda08800.qcom,csid"),
-	CLK_LOOKUP("csi_pix_clk", camss_csi2pix_clk.c,	"fda08800.qcom,csid"),
-	CLK_LOOKUP("csi_rdi_clk", camss_csi2rdi_clk.c,	"fda08800.qcom,csid"),
-	CLK_LOOKUP("csi_ahb_clk", camss_csi3_ahb_clk.c,	"fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi_src_clk", csi3_clk_src.c,	"fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi_phy_clk", camss_csi3phy_clk.c,	"fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi_clk", camss_csi3_clk.c,		"fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi_pix_clk", camss_csi3pix_clk.c,	"fda08c00.qcom,csid"),
-	CLK_LOOKUP("csi_rdi_clk", camss_csi3rdi_clk.c,	"fda08c00.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("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_clk", camss_csi0_clk.c, "fda08400.qcom,csid"),
+	CLK_LOOKUP("csi1_clk", camss_csi1_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"),
+
+	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi2_ahb_clk", camss_csi2_ahb_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi2_src_clk", csi2_clk_src.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi2_phy_clk", camss_csi2phy_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi0_clk", camss_csi0_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi2_clk", camss_csi2_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi2_pix_clk", camss_csi2pix_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda08800.qcom,csid"),
+	CLK_LOOKUP("csi2_rdi_clk", camss_csi2rdi_clk.c, "fda08800.qcom,csid"),
+
+	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi3_ahb_clk", camss_csi3_ahb_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi3_src_clk", csi3_clk_src.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi3_phy_clk", camss_csi3phy_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi0_clk", camss_csi0_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi3_clk", camss_csi3_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi3_pix_clk", camss_csi3pix_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda08c00.qcom,csid"),
+	CLK_LOOKUP("csi3_rdi_clk", camss_csi3rdi_clk.c, "fda08c00.qcom,csid"),
+
 	/*VFE clocks*/
 	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
 					"fda10000.qcom,vfe"),
@@ -5173,17 +5236,36 @@
 	CLK_LOOKUP("bus_clk", camss_vfe_vfe_axi_clk.c,	 "fda14000.qcom,vfe"),
 	CLK_LOOKUP("alt_bus_clk", camss_vfe_vfe_ocmemnoc_clk.c,
 					"fda14000.qcom,vfe"),
-	CLK_LOOKUP("core_clk", camss_jpeg_jpeg0_clk.c, ""),
-	CLK_LOOKUP("core_clk", camss_jpeg_jpeg1_clk.c, ""),
-	CLK_LOOKUP("core_clk", camss_jpeg_jpeg2_clk.c, ""),
+	/*Jpeg Clocks*/
+	CLK_LOOKUP("core_clk", camss_jpeg_jpeg0_clk.c, "fda1c000.qcom,jpeg"),
+	CLK_LOOKUP("core_clk", camss_jpeg_jpeg1_clk.c, "fda20000.qcom,jpeg"),
+	CLK_LOOKUP("core_clk", camss_jpeg_jpeg2_clk.c, "fda24000.qcom,jpeg"),
+	CLK_LOOKUP("iface_clk", camss_jpeg_jpeg_ahb_clk.c,
+						"fda1c000.qcom,jpeg"),
+	CLK_LOOKUP("iface_clk", camss_jpeg_jpeg_ahb_clk.c,
+						"fda20000.qcom,jpeg"),
+	CLK_LOOKUP("iface_clk", camss_jpeg_jpeg_ahb_clk.c,
+						"fda24000.qcom,jpeg"),
 	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"),
-	CLK_LOOKUP("bus_clk", camss_jpeg_jpeg_axi_clk.c, ""),
-	CLK_LOOKUP("bus_clk", camss_jpeg_jpeg_ocmemnoc_clk.c, ""),
+	CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda1c000.qcom,jpeg"),
+	CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda20000.qcom,jpeg"),
+	CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda24000.qcom,jpeg"),
+	CLK_LOOKUP("alt_bus_clk", camss_jpeg_jpeg_ocmemnoc_clk.c,
+						"fda1c000.qcom,jpeg"),
+	CLK_LOOKUP("alt_bus_clk", camss_jpeg_jpeg_ocmemnoc_clk.c,
+						"fda20000.qcom,jpeg"),
+	CLK_LOOKUP("alt_bus_clk", camss_jpeg_jpeg_ocmemnoc_clk.c,
+						"fda24000.qcom,jpeg"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+						"fda1c000.qcom,jpeg"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+						"fda20000.qcom,jpeg"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+						"fda24000.qcom,jpeg"),
 	CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
-	CLK_LOOKUP("iface_clk", camss_top_ahb_clk.c, ""),
 	CLK_LOOKUP("iface_clk", camss_vfe_cpp_ahb_clk.c, "fda44000.qcom,iommu"),
 	CLK_LOOKUP("core_clk", camss_vfe_cpp_clk.c, "fda44000.qcom,iommu"),
 	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdp.0"),
@@ -5254,10 +5336,9 @@
 	CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
 						"msm-dai-q6.4106"),
 	CLK_LOOKUP("br_clk", audio_wrapper_br_clk.c, "fdd00000.qcom,ocmem"),
-	CLK_LOOKUP("core_clk",       mss_xo_q6_clk.c,  "pil-q6v5-mss"),
+
 	CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "pil-q6v5-mss"),
 	CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "pil-q6v5-mss"),
-	CLK_LOOKUP("reg_clk",       mss_bus_q6_clk.c,  "pil-q6v5-mss"),
 	CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c,  "pil-q6v5-mss"),
 
 	CLK_LOOKUP("core_clk",         q6ss_xo_clk.c,  "pil-q6v5-lpass"),
@@ -5649,9 +5730,6 @@
 #define LPASS_CC_PHYS		0xFE000000
 #define LPASS_CC_SIZE		SZ_256K
 
-#define MSS_CC_PHYS		0xFC980000
-#define MSS_CC_SIZE		SZ_16K
-
 #define APCS_GCC_CC_PHYS	0xF9011000
 #define APCS_GCC_CC_SIZE	SZ_4K
 
@@ -5687,10 +5765,6 @@
 	if (!virt_bases[LPASS_BASE])
 		panic("clock-8974: Unable to ioremap LPASS_CC memory!");
 
-	virt_bases[MSS_BASE] = ioremap(MSS_CC_PHYS, MSS_CC_SIZE);
-	if (!virt_bases[MSS_BASE])
-		panic("clock-8974: Unable to ioremap MSS_CC memory!");
-
 	virt_bases[APCS_BASE] = ioremap(APCS_GCC_CC_PHYS, APCS_GCC_CC_SIZE);
 	if (!virt_bases[APCS_BASE])
 		panic("clock-8974: Unable to ioremap APCS_GCC_CC memory!");
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index bc57c3b..24c06c9 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -313,7 +313,6 @@
 		.rate = 384000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll8_clk.c),
-		.warned = true,
 	},
 };
 
@@ -325,7 +324,6 @@
 		.rate = 800000000,
 		.ops = &clk_ops_local_pll,
 		CLK_INIT(pll2_clk.c),
-		.warned = true,
 	},
 };
 
@@ -337,7 +335,6 @@
 		.rate = 0, /* TODO: Detect rate dynamically */
 		.ops = &clk_ops_local_pll,
 		CLK_INIT(pll3_clk.c),
-		.warned = true,
 	},
 };
 
@@ -387,7 +384,6 @@
 		.rate = 540672000,
 		.ops = &clk_ops_pll4,
 		CLK_INIT(pll4_clk.c),
-		.warned = true,
 	},
 };
 
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 494823b..648a8d4 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -272,7 +272,6 @@
 		.rate = 276000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll0_clk.c),
-		.warned = true,
 	},
 };
 
@@ -288,7 +287,6 @@
 		.rate = 276000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll0_activeonly_clk.c),
-		.warned = true,
 	},
 };
 
@@ -303,7 +301,6 @@
 		.rate = 393216000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
-		.warned = true,
 	},
 };
 
@@ -322,7 +319,6 @@
 		.rate = 384000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll8_clk.c),
-		.warned = true,
 	},
 };
 
@@ -338,7 +334,6 @@
 		.rate = 384000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll8_activeonly_clk.c),
-		.warned = true,
 	},
 };
 
@@ -349,7 +344,6 @@
 		.rate = 440000000,
 		.ops = &clk_ops_local_pll,
 		CLK_INIT(pll9_activeonly_clk.c),
-		.warned = true,
 	},
 };
 
@@ -364,7 +358,6 @@
 		.rate = 480000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll14_clk.c),
-		.warned = true,
 	},
 };
 
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 807d587..c996ff4 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -175,16 +175,18 @@
 {
 	char *start = "";
 
-	if (!c || !c->count)
+	if (!c || !c->prepare_count)
 		return 0;
 
 	pr_info("\t");
 	do {
 		if (c->vdd_class)
-			pr_cont("%s%s [%ld, %lu]", start, c->dbg_name, c->rate,
+			pr_cont("%s%s:%u:%u [%ld, %lu]", start, c->dbg_name,
+				c->prepare_count, c->count, c->rate,
 				c->vdd_class->cur_level);
 		else
-			pr_cont("%s%s [%ld]", start, c->dbg_name, c->rate);
+			pr_cont("%s%s:%u:%u [%ld]", start, c->dbg_name,
+				c->prepare_count, c->count, c->rate);
 		start = " -> ";
 	} while ((c = clk_get_parent(c)));
 
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 2df1cd1..b952f2f 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -320,10 +320,6 @@
 	u32 reg_val;
 	void __iomem *const reg = rcg->b.ctl_reg;
 
-	WARN(rcg->current_freq == &rcg_dummy_freq,
-		"Attempting to enable %s before setting its rate. "
-		"Set the rate first!\n", rcg->c.dbg_name);
-
 	/*
 	 * Program the NS register, if applicable. NS registers are not
 	 * set in the set_rate path because power can be saved by deferring
@@ -419,6 +415,18 @@
 	}
 }
 
+static int rcg_clk_prepare(struct clk *c)
+{
+	struct rcg_clk *rcg = to_rcg_clk(c);
+
+	WARN(rcg->current_freq == &rcg_dummy_freq,
+		"Attempting to prepare %s before setting its rate. "
+		"Set the rate first!\n", rcg->c.dbg_name);
+	rcg->prepared = true;
+
+	return 0;
+}
+
 /* Enable a rate-settable clock. */
 static int rcg_clk_enable(struct clk *c)
 {
@@ -445,6 +453,12 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
+static void rcg_clk_unprepare(struct clk *c)
+{
+	struct rcg_clk *rcg = to_rcg_clk(c);
+	rcg->prepared = false;
+}
+
 /*
  * Frequency-related functions
  */
@@ -456,6 +470,7 @@
 	struct clk_freq_tbl *nf, *cf;
 	struct clk *chld;
 	int rc = 0;
+	unsigned long flags;
 
 	for (nf = rcg->freq_tbl; nf->freq_hz != FREQ_END
 			&& nf->freq_hz != rate; nf++)
@@ -466,11 +481,22 @@
 
 	cf = rcg->current_freq;
 
-	if (rcg->enabled) {
-		/* Enable source clock dependency for the new freq. */
-		rc = clk_enable(nf->src_clk);
+	/* Enable source clock dependency for the new frequency */
+	if (rcg->prepared) {
+		rc = clk_prepare(nf->src_clk);
 		if (rc)
 			return rc;
+
+	}
+
+	spin_lock_irqsave(&c->lock, flags);
+	if (rcg->enabled) {
+		rc = clk_enable(nf->src_clk);
+		if (rc) {
+			spin_unlock_irqrestore(&c->lock, flags);
+			clk_unprepare(nf->src_clk);
+			return rc;
+		}
 	}
 
 	spin_lock(&local_clock_reg_lock);
@@ -519,6 +545,10 @@
 	/* Release source requirements of the old freq. */
 	if (rcg->enabled)
 		clk_disable(cf->src_clk);
+	spin_unlock_irqrestore(&c->lock, flags);
+
+	if (rcg->prepared)
+		clk_unprepare(cf->src_clk);
 
 	return rc;
 }
@@ -819,8 +849,10 @@
 }
 
 struct clk_ops clk_ops_rcg = {
+	.prepare = rcg_clk_prepare,
 	.enable = rcg_clk_enable,
 	.disable = rcg_clk_disable,
+	.unprepare = rcg_clk_unprepare,
 	.enable_hwcg = rcg_clk_enable_hwcg,
 	.disable_hwcg = rcg_clk_disable_hwcg,
 	.in_hwcg_mode = rcg_clk_in_hwcg_mode,
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 034e09c..81085ef 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -164,6 +164,7 @@
  * Generic clock-definition struct and macros
  */
 struct rcg_clk {
+	bool		prepared;
 	bool		enabled;
 	void		*const ns_reg;
 	void		*const md_reg;
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 42b36f6..3f19b2a 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -148,12 +148,12 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-static int rcg_clk_enable(struct clk *c)
+static int rcg_clk_prepare(struct clk *c)
 {
 	struct rcg_clk *rcg = to_rcg_clk(c);
 
 	WARN(rcg->current_freq == &rcg_dummy_freq,
-		"Attempting to enable %s before setting its rate. "
+		"Attempting to prepare %s before setting its rate. "
 		"Set the rate first!\n", rcg->c.dbg_name);
 
 	return 0;
@@ -163,7 +163,8 @@
 {
 	struct clk_freq_tbl *cf, *nf;
 	struct rcg_clk *rcg = to_rcg_clk(c);
-	int rc = 0;
+	int rc;
+	unsigned long flags;
 
 	for (nf = rcg->freq_tbl; nf->freq_hz != FREQ_END
 			&& nf->freq_hz != rate; nf++)
@@ -174,12 +175,21 @@
 
 	cf = rcg->current_freq;
 
-	if (rcg->c.count) {
-		/* TODO: Modify to use the prepare API */
-		/* Enable source clock dependency for the new freq. */
-		rc = clk_enable(nf->src_clk);
+	/* Enable source clock dependency for the new freq. */
+	if (c->prepare_count) {
+		rc = clk_prepare(nf->src_clk);
 		if (rc)
-			goto out;
+			return rc;
+	}
+
+	spin_lock_irqsave(&c->lock, flags);
+	if (c->count) {
+		rc = clk_enable(nf->src_clk);
+		if (rc) {
+			spin_unlock_irqrestore(&c->lock, flags);
+			clk_unprepare(nf->src_clk);
+			return rc;
+		}
 	}
 
 	BUG_ON(!rcg->set_rate);
@@ -188,12 +198,16 @@
 	rcg->set_rate(rcg, nf);
 
 	/* Release source requirements of the old freq. */
-	if (rcg->c.count)
+	if (c->count)
 		clk_disable(cf->src_clk);
+	spin_unlock_irqrestore(&c->lock, flags);
+
+	if (c->prepare_count)
+		clk_unprepare(cf->src_clk);
 
 	rcg->current_freq = nf;
-out:
-	return rc;
+
+	return 0;
 }
 
 /* Return a supported rate that's at least the specified rate. */
@@ -585,7 +599,7 @@
 struct clk_ops clk_ops_empty;
 
 struct clk_ops clk_ops_rcg = {
-	.enable = rcg_clk_enable,
+	.enable = rcg_clk_prepare,
 	.set_rate = rcg_clk_set_rate,
 	.list_rate = rcg_clk_list_rate,
 	.round_rate = rcg_clk_round_rate,
@@ -594,7 +608,7 @@
 };
 
 struct clk_ops clk_ops_rcg_mnd = {
-	.enable = rcg_clk_enable,
+	.enable = rcg_clk_prepare,
 	.set_rate = rcg_clk_set_rate,
 	.list_rate = rcg_clk_list_rate,
 	.round_rate = rcg_clk_round_rate,
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index e203028..7952a33 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -110,7 +110,6 @@
 			.dbg_name = #name, \
 			.rate = (r), \
 			CLK_INIT(name.c), \
-			.warned = true, \
 		}, \
 	}; \
 	static struct rpm_clk active = { \
@@ -129,7 +128,6 @@
 			.dbg_name = #active, \
 			.rate = (r), \
 			CLK_INIT(active.c), \
-			.warned = true, \
 		}, \
 	};
 
@@ -148,7 +146,6 @@
 			.ops = &clk_ops_rpm, \
 			.dbg_name = #name, \
 			CLK_INIT(name.c), \
-			.warned = true, \
 		}, \
 	}; \
 	static struct rpm_clk active = { \
@@ -164,7 +161,6 @@
 			.ops = &clk_ops_rpm, \
 			.dbg_name = #active, \
 			CLK_INIT(active.c), \
-			.warned = true, \
 		}, \
 	};
 
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index 4cd9b1c..3e1cbb9 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -12,13 +12,13 @@
  */
 
 #include <linux/err.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/clk.h>
 
 #include "clock.h"
 #include "clock-voter.h"
 
-static DEFINE_SPINLOCK(voter_clk_lock);
+static DEFINE_MUTEX(voter_clk_lock);
 
 /* Aggregate the rate of clocks that are currently on. */
 static unsigned long voter_clk_aggregate_rate(const struct clk *parent)
@@ -37,12 +37,11 @@
 static int voter_clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	int ret = 0;
-	unsigned long flags;
 	struct clk *clkp;
 	struct clk_voter *clkh, *v = to_clk_voter(clk);
 	unsigned long cur_rate, new_rate, other_rate = 0;
 
-	spin_lock_irqsave(&voter_clk_lock, flags);
+	mutex_lock(&voter_clk_lock);
 
 	if (v->enabled) {
 		struct clk *parent = v->parent;
@@ -68,20 +67,19 @@
 	}
 	clk->rate = rate;
 unlock:
-	spin_unlock_irqrestore(&voter_clk_lock, flags);
+	mutex_unlock(&voter_clk_lock);
 
 	return ret;
 }
 
-static int voter_clk_enable(struct clk *clk)
+static int voter_clk_prepare(struct clk *clk)
 {
 	int ret = 0;
-	unsigned long flags;
 	unsigned long cur_rate;
 	struct clk *parent;
 	struct clk_voter *v = to_clk_voter(clk);
 
-	spin_lock_irqsave(&voter_clk_lock, flags);
+	mutex_lock(&voter_clk_lock);
 	parent = v->parent;
 
 	/*
@@ -96,18 +94,18 @@
 	}
 	v->enabled = true;
 out:
-	spin_unlock_irqrestore(&voter_clk_lock, flags);
+	mutex_unlock(&voter_clk_lock);
 
 	return ret;
 }
 
-static void voter_clk_disable(struct clk *clk)
+static void voter_clk_unprepare(struct clk *clk)
 {
-	unsigned long flags, cur_rate, new_rate;
+	unsigned long cur_rate, new_rate;
 	struct clk *parent;
 	struct clk_voter *v = to_clk_voter(clk);
 
-	spin_lock_irqsave(&voter_clk_lock, flags);
+	mutex_lock(&voter_clk_lock);
 	parent = v->parent;
 
 	/*
@@ -121,7 +119,7 @@
 	if (new_rate < cur_rate)
 		clk_set_rate(parent, new_rate);
 
-	spin_unlock_irqrestore(&voter_clk_lock, flags);
+	mutex_unlock(&voter_clk_lock);
 }
 
 static int voter_clk_is_enabled(struct clk *clk)
@@ -157,8 +155,8 @@
 }
 
 struct clk_ops clk_ops_voter = {
-	.enable = voter_clk_enable,
-	.disable = voter_clk_disable,
+	.prepare = voter_clk_prepare,
+	.unprepare = voter_clk_unprepare,
 	.set_rate = voter_clk_set_rate,
 	.is_enabled = voter_clk_is_enabled,
 	.round_rate = voter_clk_round_rate,
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index f605c1f..27f2405 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -156,6 +156,9 @@
 		if (ret)
 			goto err_prepare_depends;
 
+		ret = vote_rate_vdd(clk, clk->rate);
+		if (ret)
+			goto err_vote_vdd;
 		if (clk->ops->prepare)
 			ret = clk->ops->prepare(clk);
 		if (ret)
@@ -166,6 +169,8 @@
 	mutex_unlock(&clk->prepare_lock);
 	return ret;
 err_prepare_clock:
+	unvote_rate_vdd(clk, clk->rate);
+err_vote_vdd:
 	clk_unprepare(clk->depends);
 err_prepare_depends:
 	clk_unprepare(parent);
@@ -181,6 +186,7 @@
 	int ret = 0;
 	unsigned long flags;
 	struct clk *parent;
+	const char *name = clk ? clk->dbg_name : NULL;
 
 	if (!clk)
 		return 0;
@@ -188,10 +194,8 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&clk->lock, flags);
-	if (WARN(!clk->warned && !clk->prepare_count,
-				"%s: Don't call enable on unprepared clocks\n",
-				clk->dbg_name))
-		clk->warned = true;
+	WARN(!clk->prepare_count,
+			"%s: Don't call enable on unprepared clocks\n", name);
 	if (clk->count == 0) {
 		parent = clk_get_parent(clk);
 
@@ -202,10 +206,7 @@
 		if (ret)
 			goto err_enable_depends;
 
-		ret = vote_rate_vdd(clk, clk->rate);
-		if (ret)
-			goto err_vote_vdd;
-		trace_clock_enable(clk->dbg_name, 1, smp_processor_id());
+		trace_clock_enable(name, 1, smp_processor_id());
 		if (clk->ops->enable)
 			ret = clk->ops->enable(clk);
 		if (ret)
@@ -217,8 +218,6 @@
 	return 0;
 
 err_enable_clock:
-	unvote_rate_vdd(clk, clk->rate);
-err_vote_vdd:
 	clk_disable(clk->depends);
 err_enable_depends:
 	clk_disable(parent);
@@ -230,26 +229,24 @@
 
 void clk_disable(struct clk *clk)
 {
+	const char *name = clk ? clk->dbg_name : NULL;
 	unsigned long flags;
 
 	if (IS_ERR_OR_NULL(clk))
 		return;
 
 	spin_lock_irqsave(&clk->lock, flags);
-	if (WARN(!clk->warned && !clk->prepare_count,
-				"%s: Never called prepare or calling disable "
-				"after unprepare\n",
-				clk->dbg_name))
-		clk->warned = true;
-	if (WARN(clk->count == 0, "%s is unbalanced", clk->dbg_name))
+	WARN(!clk->prepare_count,
+			"%s: Never called prepare or calling disable after unprepare\n",
+			name);
+	if (WARN(clk->count == 0, "%s is unbalanced", name))
 		goto out;
 	if (clk->count == 1) {
 		struct clk *parent = clk_get_parent(clk);
 
-		trace_clock_disable(clk->dbg_name, 0, smp_processor_id());
+		trace_clock_disable(name, 0, smp_processor_id());
 		if (clk->ops->disable)
 			clk->ops->disable(clk);
-		unvote_rate_vdd(clk, clk->rate);
 		clk_disable(clk->depends);
 		clk_disable(parent);
 	}
@@ -261,26 +258,24 @@
 
 void clk_unprepare(struct clk *clk)
 {
+	const char *name = clk ? clk->dbg_name : NULL;
+
 	if (IS_ERR_OR_NULL(clk))
 		return;
 
 	mutex_lock(&clk->prepare_lock);
-	if (!clk->prepare_count) {
-		if (WARN(!clk->warned, "%s is unbalanced (prepare)",
-				clk->dbg_name))
-			clk->warned = true;
+	if (WARN(!clk->prepare_count, "%s is unbalanced (prepare)", name))
 		goto out;
-	}
 	if (clk->prepare_count == 1) {
 		struct clk *parent = clk_get_parent(clk);
 
-		if (WARN(!clk->warned && clk->count,
+		WARN(clk->count,
 			"%s: Don't call unprepare when the clock is enabled\n",
-				clk->dbg_name))
-			clk->warned = true;
+			name);
 
 		if (clk->ops->unprepare)
 			clk->ops->unprepare(clk);
+		unvote_rate_vdd(clk, clk->rate);
 		clk_unprepare(clk->depends);
 		clk_unprepare(parent);
 	}
@@ -316,8 +311,9 @@
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	unsigned long start_rate, flags;
+	unsigned long start_rate;
 	int rc = 0;
+	const char *name = clk ? clk->dbg_name : NULL;
 
 	if (IS_ERR_OR_NULL(clk))
 		return -EINVAL;
@@ -325,14 +321,14 @@
 	if (!clk->ops->set_rate)
 		return -ENOSYS;
 
-	spin_lock_irqsave(&clk->lock, flags);
+	mutex_lock(&clk->prepare_lock);
 
 	/* Return early if the rate isn't going to change */
 	if (clk->rate == rate)
 		goto out;
 
-	trace_clock_set_rate(clk->dbg_name, rate, smp_processor_id());
-	if (clk->count) {
+	trace_clock_set_rate(name, rate, raw_smp_processor_id());
+	if (clk->prepare_count) {
 		start_rate = clk->rate;
 		/* Enforce vdd requirements for target frequency. */
 		rc = vote_rate_vdd(clk, rate);
@@ -350,14 +346,13 @@
 	if (!rc)
 		clk->rate = rate;
 out:
-	spin_unlock_irqrestore(&clk->lock, flags);
+	mutex_unlock(&clk->prepare_lock);
 	return rc;
 
 err_set_rate:
 	unvote_rate_vdd(clk, rate);
 err_vote_vdd:
-	spin_unlock_irqrestore(&clk->lock, flags);
-	return rc;
+	goto out;
 }
 EXPORT_SYMBOL(clk_set_rate);
 
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 4e3d83b..45d2f71 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -114,7 +114,6 @@
  * @depends: non-direct parent of clock to enable when this clock is enabled
  * @vdd_class: voltage scaling requirement class
  * @fmax: maximum frequency in Hz supported at each voltage level
- * @warned: true if the clock has warned of incorrect usage, false otherwise
  */
 struct clk {
 	uint32_t flags;
@@ -128,7 +127,6 @@
 	struct list_head children;
 	struct list_head siblings;
 
-	bool warned;
 	unsigned count;
 	spinlock_t lock;
 	unsigned prepare_count;
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 0fa1e2d..05bd56ef 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -92,6 +92,34 @@
 }
 
 #ifdef CONFIG_SMP
+static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb,
+					unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
+		break;
+	case CPU_DOWN_PREPARE:
+	case CPU_DOWN_PREPARE_FROZEN:
+		mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
+		per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
+		mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
+		break;
+	case CPU_DOWN_FAILED:
+	case CPU_DOWN_FAILED_FROZEN:
+		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata msm_cpufreq_cpu_notifier = {
+	.notifier_call = msm_cpufreq_cpu_callback,
+};
+
 static void set_cpu_work(struct work_struct *work)
 {
 	struct cpufreq_work_struct *cpu_work =
@@ -385,6 +413,7 @@
 
 #ifdef CONFIG_SMP
 	msm_cpufreq_wq = create_workqueue("msm-cpufreq");
+	register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
 #endif
 
 	register_pm_notifier(&msm_cpufreq_pm_notifier);
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index a3a1574..dd2dc1d 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -81,7 +81,7 @@
 #endif
 
 	pm_mode = msm_pm_idle_prepare(dev, drv, index);
-	msm_pm_idle_enter(pm_mode);
+	dev->last_residency = msm_pm_idle_enter(pm_mode);
 	for (i = 0; i < dev->state_count; i++) {
 		st_usage = &dev->states_usage[i];
 		if ((enum msm_pm_sleep_mode) cpuidle_get_statedata(st_usage)
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index da98f34..4ad5580 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -36,7 +36,7 @@
 #include <mach/msm_smd.h>
 #include <mach/msm_dcvs.h>
 #include <mach/msm_rtb.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include "clock.h"
 #include "devices.h"
 #include "footswitch.h"
@@ -746,6 +746,29 @@
 	},
 };
 
+struct msm_mi2s_pdata apq_mi2s_data = {
+	.rx_sd_lines = MSM_MI2S_SD0,
+	.tx_sd_lines = MSM_MI2S_SD3,
+};
+
+struct platform_device apq_cpudai_mi2s = {
+	.name	= "msm-dai-q6-mi2s",
+	.id	= -1,
+	.dev = {
+		.platform_data = &apq_mi2s_data,
+	},
+};
+
+struct platform_device apq_cpudai_i2s_rx = {
+	.name	= "msm-dai-q6",
+	.id	= PRIMARY_I2S_RX,
+};
+
+struct platform_device apq_cpudai_i2s_tx = {
+	.name	= "msm-dai-q6",
+	.id	= PRIMARY_I2S_TX,
+};
+
 struct platform_device apq_cpu_fe = {
 	.name	= "msm-dai-fe",
 	.id	= -1,
@@ -2809,7 +2832,7 @@
 static struct coresight_platform_data coresight_funnel_pdata = {
 	.id		= 2,
 	.name		= "coresight-funnel",
-	.nr_inports	= 4,
+	.nr_inports	= 8,
 	.outports	= coresight_funnel_outports,
 	.child_ids	= coresight_funnel_child_ids,
 	.child_ports	= coresight_funnel_child_ports,
@@ -2841,7 +2864,7 @@
 static struct coresight_platform_data coresight_etm2_pdata = {
 	.id		= 6,
 	.name		= "coresight-etm2",
-	.nr_inports	= 1,
+	.nr_inports	= 0,
 	.outports	= coresight_etm2_outports,
 	.child_ids	= coresight_etm2_child_ids,
 	.child_ports	= coresight_etm2_child_ports,
@@ -2873,7 +2896,7 @@
 static struct coresight_platform_data coresight_etm3_pdata = {
 	.id		= 7,
 	.name		= "coresight-etm3",
-	.nr_inports	= 3,
+	.nr_inports	= 0,
 	.outports	= coresight_etm3_outports,
 	.child_ids	= coresight_etm3_child_ids,
 	.child_ports	= coresight_etm3_child_ports,
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 867e8fc..292f58d 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -14,7 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <asm/io.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/msm_iomap.h>
 #include <mach/irqs-8930.h>
 #include <mach/rpm.h>
@@ -543,8 +543,8 @@
 };
 
 static struct resource msm_rpm_rbcpr_resource = {
-	.start = 0x0010CB00,
-	.end = 0x0010CB00 + SZ_8K - 1,
+	.start = 0x0010DB00,
+	.end = 0x0010DB00 + SZ_8K - 1,
 	.flags = IORESOURCE_MEM,
 };
 
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 377ecae..33782ab 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -15,7 +15,7 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/msm_rotator.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/gpio.h>
 #include <linux/coresight.h>
 #include <asm/clkdev.h>
@@ -3145,18 +3145,29 @@
 	},
 };
 
-static const struct kgsl_iommu_ctx kgsl_3d0_iommu_ctxs[] = {
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu0_ctxs[] = {
 	{ "gfx3d_user", 0 },
 	{ "gfx3d_priv", 1 },
 };
 
+static const struct kgsl_iommu_ctx kgsl_3d0_iommu1_ctxs[] = {
+	{ "gfx3d1_user", 0 },
+	{ "gfx3d1_priv", 1 },
+};
+
 static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = {
 	{
-		.iommu_ctxs = kgsl_3d0_iommu_ctxs,
-		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu_ctxs),
+		.iommu_ctxs = kgsl_3d0_iommu0_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu0_ctxs),
 		.physstart = 0x07C00000,
 		.physend = 0x07C00000 + SZ_1M - 1,
 	},
+	{
+		.iommu_ctxs = kgsl_3d0_iommu1_ctxs,
+		.iommu_ctx_count = ARRAY_SIZE(kgsl_3d0_iommu1_ctxs),
+		.physstart = 0x07D00000,
+		.physend = 0x07D00000 + SZ_1M - 1,
+	},
 };
 
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 4a6271c..cd5b2e5 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1634,6 +1634,7 @@
 		break;
 	case 0x775:
 	case 0x776:
+	case 0x779:
 	case 0x77D:
 	case 0x782:
 	case 0x8D2:
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index c12c0f7..b456f50 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -26,7 +26,7 @@
 #include <mach/dma.h>
 #include <mach/board.h>
 #include <asm/clkdev.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include "devices.h"
 #include "footswitch.h"
 
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index d086753..7bffd9b 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/irqs.h>
 #include <mach/dma.h>
 #include <asm/mach/mmc.h>
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 4d338b1..e66bf27 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -444,3 +444,8 @@
 extern struct platform_device msm9615_device_acpuclk;
 
 extern struct platform_device msm_gpio_device;
+
+extern struct platform_device apq_cpudai_mi2s;
+extern struct platform_device apq_cpudai_i2s_rx;
+extern struct platform_device apq_cpudai_i2s_tx;
+
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index ff7af32..8eed48d 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -128,6 +128,19 @@
 	bne	skip
 	bl	v7_flush_dcache_all
 skip:
+	mrc	p15, 0, r0, c0, c0, 5	/* MPIDR */
+	and	r0, r0, #15		/* what CPU am I */
+
+	ldr	r1, =msm_pc_debug_counters /*load the IMEM debug location */
+	ldr	r1, [r1]
+	cmp	r1, #0
+	beq	skip_pc_debug1
+	add	r1, r1, r0, LSL #4	/* debug location for this CPU */
+	ldr	r2, [r1]
+	add	r2, #1
+	str	r2, [r1]
+skip_pc_debug1:
+
 #ifdef CONFIG_ARCH_MSM_KRAIT
 	ldr	r0, =SCM_SVC_BOOT
 	ldr	r1, =SCM_CMD_TERMINATE_PC
@@ -155,6 +168,21 @@
 #if defined(CONFIG_MSM_FIQ_SUPPORT)
 	cpsie   f
 #endif
+	mrc	p15, 0, r0, c0, c0, 5 /* MPIDR */
+	and	r0, r0, #15              /* what CPU am I                  */
+
+	ldr	r1, =msm_pc_debug_counters /*load the IMEM debug location */
+	ldr	r1, [r1]
+	cmp	r1, #0
+	beq	skip_pc_debug2
+	add	r1, r1, r0, LSL #4	/* debug location for this CPU */
+	add	r1, #8
+	ldr	r2, [r1]
+	add	r2, #1
+	str	r2, [r1]
+
+skip_pc_debug2:
+
 #ifdef CONFIG_MSM_JTAG
 	bl	msm_jtag_restore_state
 #endif
@@ -276,6 +304,22 @@
 	mrc     p15, 0, r0, c0, c0, 5    /* MPIDR                          */
 	and     r0, r0, #15              /* what CPU am I                  */
 
+	ldr	r1, =msm_pc_debug_counters_phys /*phys addr for IMEM reg */
+	ldr	r2, =msm_pm_boot_entry
+	adr	r3, msm_pm_boot_entry
+	add	r1, r1, r3               /* translate virt to phys addr    */
+	sub	r1, r1, r2
+	ldr	r1,[r1]
+
+	cmp	r1, #0
+	beq	skip_pc_debug3
+	add	r1, r1, r0, LSL #4	/* debug location for this CPU */
+	add	r1, #4			/* warmboot entry counter*/
+	ldr	r2, [r1]
+	add	r2, #1
+	str	r2, [r1]
+
+skip_pc_debug3:
 	ldr     r1, =msm_pm_boot_vector
 	ldr     r2, =msm_pm_boot_entry
 	adr     r3, msm_pm_boot_entry
@@ -320,6 +364,14 @@
 l2x0_base_addr:
 	.long 0x0
 
+	.globl msm_pc_debug_counters_phys
+msm_pc_debug_counters_phys:
+	.long 0x0
+
+	.globl msm_pc_debug_counters
+msm_pc_debug_counters:
+	.long 0x0
+
 /*
  * Default the l2 flush flag to 1 so that caches are flushed during power
  * collapse unless the  L2 driver decides to flush them only during L2
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index aa33a0b..5b8729a 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -177,6 +177,7 @@
 struct msm_camera_csi_lane_params {
 	uint16_t csi_lane_assign;
 	uint16_t csi_lane_mask;
+	uint8_t csi_phy_sel;
 };
 
 struct msm_camera_gpio_conf {
@@ -394,6 +395,8 @@
 	u32 ov1_wb_size;  /* overlay1 writeback size */
 	u32 mem_hid;
 	char cont_splash_enabled;
+	u32 splash_screen_addr;
+	u32 splash_screen_size;
 	char mdp_iommu_split_domain;
 };
 
@@ -578,6 +581,11 @@
 void msm_8974_very_early(void);
 void msm_8974_init_gpiomux(void);
 void msm9625_init_gpiomux(void);
+void msm_map_mpq8092_io(void);
+void mpq8092_init_gpiomux(void);
+void msm_map_msm8226_io(void);
+void msm8226_init_irq(void);
+void msm8226_init_gpiomux(void);
 
 struct mmc_platform_data;
 int msm_add_sdcc(unsigned int controller,
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 6298d94..cf36388 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -24,7 +24,7 @@
 
 #include <mach/board.h>
 #include <media/msm_camera.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/iommu_domains.h>
 
 #define CONFIG_MSM_CAMERA_DEBUG
@@ -632,6 +632,7 @@
 	S_STEREO_CAPTURE,
 	S_DEFAULT,
 	S_LIVESHOT,
+	S_DUAL,
 	S_EXIT
 };
 
diff --git a/arch/arm/mach-msm/include/mach/diag_dload.h b/arch/arm/mach-msm/include/mach/diag_dload.h
new file mode 100644
index 0000000..83c7f2d
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/diag_dload.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_DIAG_DLOAD_H__
+#define __LINUX_DIAG_DLOAD_H__
+
+
+#define PID_MAGIC_ID		0x71432909
+#define SERIAL_NUM_MAGIC_ID	0x61945374
+#define SERIAL_NUMBER_LENGTH	128
+
+struct magic_num_struct {
+	uint32_t pid;
+	uint32_t serial_num;
+};
+
+struct dload_struct {
+	uint32_t	pid;
+	char		serial_number[SERIAL_NUMBER_LENGTH];
+	struct magic_num_struct magic_struct;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-8092.h b/arch/arm/mach-msm/include/mach/irqs-8092.h
new file mode 100644
index 0000000..ae9634e
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/irqs-8092.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_MSM_IRQS_8092_H
+#define __ASM_ARCH_MSM_IRQS_8092_H
+
+/* MSM ACPU Interrupt Numbers */
+
+/*
+ * 0-15:  STI/SGI (software triggered/generated interrupts)
+ * 16-31: PPI (private peripheral interrupts)
+ * 32+:   SPI (shared peripheral interrupts)
+ */
+
+#define GIC_PPI_START 16
+#define GIC_SPI_START 32
+
+#define AVS_SVICINT				(GIC_PPI_START + 6)
+#define AVS_SVICINTSWDONE			(GIC_PPI_START + 7)
+#define INT_ARMQC_PERFMON			(GIC_PPI_START + 10)
+/* PPI 15 is unused */
+
+#define APCC_QGICL2PERFMONIRPTREQ	(GIC_SPI_START + 1)
+#define SC_SICL2PERFMONIRPTREQ		APCC_QGICL2PERFMONIRPTREQ
+#define TLMM_MSM_SUMMARY_IRQ		(GIC_SPI_START + 208)
+#define SPS_BAM_DMA_IRQ			(GIC_SPI_START + 105)
+
+#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
+#define NR_GPIO_IRQS 146
+#define NR_QPNP_IRQS 32768 /* SPARSE_IRQ is required to support this */
+#define NR_BOARD_IRQS NR_QPNP_IRQS
+#define NR_TLMM_MSM_DIR_CONN_IRQ 8
+#define NR_MSM_GPIOS NR_GPIO_IRQS
+
+#endif
+
diff --git a/arch/arm/mach-msm/include/mach/irqs-8226.h b/arch/arm/mach-msm/include/mach/irqs-8226.h
new file mode 100644
index 0000000..fad7b90
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/irqs-8226.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_MSM_IRQS_8226_H
+#define __ASM_ARCH_MSM_IRQS_8226_H
+
+/* MSM ACPU Interrupt Numbers */
+
+/*
+ * 0-15:  STI/SGI (software triggered/generated interrupts)
+ * 16-31: PPI (private peripheral interrupts)
+ * 32+:   SPI (shared peripheral interrupts)
+ */
+
+#define GIC_PPI_START 16
+#define GIC_SPI_START 32
+
+#define AVS_SVICINT				(GIC_PPI_START + 6)
+#define AVS_SVICINTSWDONE			(GIC_PPI_START + 7)
+#define INT_ARMQC_PERFMON			(GIC_PPI_START + 10)
+/* PPI 15 is unused */
+
+#define APCC_QGICL2PERFMONIRPTREQ	(GIC_SPI_START + 1)
+#define SC_SICL2PERFMONIRPTREQ		APCC_QGICL2PERFMONIRPTREQ
+#define TLMM_MSM_SUMMARY_IRQ		(GIC_SPI_START + 208)
+#define SPS_BAM_DMA_IRQ			(GIC_SPI_START + 105)
+
+#define NR_MSM_IRQS 256
+#define NR_GPIO_IRQS 146
+#define NR_QPNP_IRQS 32768 /* SPARSE_IRQ is required to support this */
+#define NR_BOARD_IRQS NR_QPNP_IRQS
+#define NR_TLMM_MSM_DIR_CONN_IRQ 8
+#define NR_MSM_GPIOS NR_GPIO_IRQS
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 143159e..f562c40 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -60,10 +60,14 @@
 
 #if defined(CONFIG_ARCH_MSM8974)
 #include "irqs-8974.h"
+#elif defined(CONFIG_ARCH_MPQ8092)
+#include "irqs-8092.h"
 #elif defined(CONFIG_ARCH_MSM9615)
 #include "irqs-9615.h"
 #elif defined(CONFIG_ARCH_MSM9625)
 #include "irqs-9625.h"
+#elif defined(CONFIG_ARCH_MSM8226)
+#include "irqs-8226.h"
 #elif defined(CONFIG_ARCH_MSM7X30)
 #include "irqs-7x30.h"
 #elif defined(CONFIG_ARCH_QSD8X50)
diff --git a/arch/arm/mach-msm/include/mach/msm_bus.h b/arch/arm/mach-msm/include/mach/msm_bus.h
index 6d7a533..c94bf80 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus.h
@@ -15,6 +15,7 @@
 
 #include <linux/types.h>
 #include <linux/input.h>
+#include <linux/platform_device.h>
 
 /*
  * Macros for clients to convert their data to ib and ab
@@ -77,11 +78,24 @@
 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)
 {
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
new file mode 100644
index 0000000..dec8a58
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_8092_H
+#define __ASM_ARCH_MSM_IOMAP_8092_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * io desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MPQ8092_SHARED_RAM_PHYS	0x0FA00000
+
+#define MPQ8092_QGIC_DIST_PHYS	0xF9000000
+#define MPQ8092_QGIC_DIST_SIZE	SZ_4K
+
+#define MPQ8092_QGIC_CPU_PHYS	0xF9002000
+#define MPQ8092_QGIC_CPU_SIZE	SZ_4K
+
+#define MPQ8092_APCS_GCC_PHYS	0xF9011000
+#define MPQ8092_APCS_GCC_SIZE	SZ_4K
+
+#define MPQ8092_TLMM_PHYS	0xFD510000
+#define MPQ8092_TLMM_SIZE	SZ_16K
+
+#ifdef CONFIG_DEBUG_MPQ8092_UART
+#define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
+#define MSM_DEBUG_UART_PHYS	0xF991E000
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
new file mode 100644
index 0000000..08bc981
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_MSM8226_H
+#define __ASM_ARCH_MSM_IOMAP_MSM8226_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * io desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSM8226_MSM_SHARED_RAM_PHYS	0x0FA00000
+
+#define MSM8226_QGIC_DIST_PHYS	0xF9000000
+#define MSM8226_QGIC_DIST_SIZE	SZ_4K
+
+#define MSM8226_QGIC_CPU_PHYS	0xF9002000
+#define MSM8226_QGIC_CPU_SIZE	SZ_4K
+
+#define MSM8226_APCS_GCC_PHYS	0xF9011000
+#define MSM8226_APCS_GCC_SIZE	SZ_4K
+
+#define MSM8226_TLMM_PHYS	0xFD510000
+#define MSM8226_TLMM_SIZE	SZ_16K
+
+#define MSM8226_IMEM_PHYS	0xFC42B000
+#define MSM8226_IMEM_SIZE	SZ_4K
+
+#ifdef CONFIG_DEBUG_MSM8226_UART
+#define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
+#define MSM_DEBUG_UART_PHYS	0xF991E000
+#endif
+
+#define MSM8226_DBG_IMEM_PHYS	0xFE805000
+#define MSM8226_DBG_IMEM_SIZE	SZ_4K
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index 7f04be8..15be294 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -54,4 +54,13 @@
 #define MSM_DEBUG_UART_PHYS	0xF991E000
 #endif
 
+/*
+ * IMEM is retained for secure watchdog reset
+ * Debug Image looks at actual IMEM to
+ * do memory dumping.
+ */
+
+#define MSM8974_DBG_IMEM_PHYS	0xFE805000
+#define MSM8974_DBG_IMEM_SIZE	SZ_4K
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 4c849d4..21bea4f 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -53,7 +53,8 @@
 	defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM7X27) || \
 	defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
 	defined(CONFIG_ARCH_MSM8625) || defined(CONFIG_ARCH_MSM7X30) || \
-	defined(CONFIG_ARCH_MSM9625)
+	defined(CONFIG_ARCH_MSM9625) || defined(CONFIG_ARCH_MPQ8092) || \
+	defined(CONFIG_ARCH_MSM8226)
 
 /* Unified iomap */
 
@@ -97,6 +98,7 @@
 #define MSM_MDC_BASE		IOMEM(0xFA400000)	/*  1M */
 #define MSM_AD5_BASE		IOMEM(0xFA900000)	/*  13M (D00000)
 							  0xFB600000 */
+#define MSM_DBG_IMEM_BASE	IOMEM(0xFB600000)	/*  4K */
 
 #define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
 #define MSM8625_SECONDARY_PHYS		0x0FE00000
@@ -118,6 +120,8 @@
 #include "msm_iomap-9615.h"
 #include "msm_iomap-8974.h"
 #include "msm_iomap-9625.h"
+#include "msm_iomap-8092.h"
+#include "msm_iomap-8226.h"
 
 #else
 /* Legacy single-target iomap */
diff --git a/arch/arm/mach-msm/include/mach/msm_memory_dump.h b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
index 3b8c9fd..5e686bf 100644
--- a/arch/arm/mach-msm/include/mach/msm_memory_dump.h
+++ b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
@@ -19,9 +19,13 @@
 	MSM_CPU_CTXT = 0,
 	MSM_CACHE,
 	MSM_OCMEM,
-	MSM_ETB,
-	MSM_ETM,
-	MSM_TMC,
+	MSM_TMC_ETFETB,
+	MSM_ETM0_REG,
+	MSM_ETM1_REG,
+	MSM_ETM2_REG,
+	MSM_ETM3_REG,
+	MSM_TMC0_REG, /* TMC_ETR */
+	MSM_TMC1_REG, /* TMC_ETF */
 	MAX_NUM_CLIENTS,
 };
 
diff --git a/arch/arm/mach-msm/include/mach/msm_serial_hs.h b/arch/arm/mach-msm/include/mach/msm_serial_hs.h
index b96640d..d2905d4 100644
--- a/arch/arm/mach-msm/include/mach/msm_serial_hs.h
+++ b/arch/arm/mach-msm/include/mach/msm_serial_hs.h
@@ -25,6 +25,7 @@
 	unsigned char inject_rx_on_wakeup;
 	char rx_to_inject;
 	int (*gpio_config)(int);
+	int userid;
 };
 
 unsigned int msm_hs_tx_empty(struct uart_port *uport);
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 47f9b10..09dfac0 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -90,9 +90,10 @@
 
 /* Operational modes of each region */
 enum region_mode {
-	WIDE_MODE = 0x0,
+	MODE_NOT_SET = 0x0,
+	WIDE_MODE,
 	THIN_MODE,
-	MODE_DEFAULT = WIDE_MODE,
+	MODE_DEFAULT = MODE_NOT_SET,
 };
 
 struct ocmem_plat_data {
@@ -101,6 +102,7 @@
 	unsigned long base;
 	struct clk *core_clk;
 	struct clk *iface_clk;
+	struct clk *br_clk;
 	struct ocmem_partition *parts;
 	int nr_parts;
 	void __iomem *reg_base;
@@ -198,11 +200,17 @@
 int process_shrink(int, struct ocmem_handle *, unsigned long);
 int ocmem_rdm_transfer(int, struct ocmem_map_list *,
 				unsigned long, int);
+int ocmem_clear(unsigned long, unsigned long);
 unsigned long process_quota(int);
 int ocmem_memory_off(int, unsigned long, unsigned long);
 int ocmem_memory_on(int, unsigned long, unsigned long);
 int ocmem_enable_core_clock(void);
 int ocmem_enable_iface_clock(void);
+int ocmem_enable_br_clock(void);
 void ocmem_disable_core_clock(void);
 void ocmem_disable_iface_clock(void);
+void ocmem_disable_br_clock(void);
+int ocmem_lock(enum ocmem_client, unsigned long, unsigned long,
+				enum region_mode);
+int ocmem_unlock(enum ocmem_client, unsigned long, unsigned long);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8960.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8960.h
index 6de47bd..abcdbb8 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-8960.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8960.h
@@ -100,6 +100,7 @@
 	RPM_VREG_ID_PM8921_L10,
 	RPM_VREG_ID_PM8921_L11,
 	RPM_VREG_ID_PM8921_L12,
+	RPM_VREG_ID_PM8921_L13,
 	RPM_VREG_ID_PM8921_L14,
 	RPM_VREG_ID_PM8921_L15,
 	RPM_VREG_ID_PM8921_L16,
@@ -176,6 +177,7 @@
 };
 
 /* Minimum high power mode loads in uA. */
+#define RPM_VREG_8960_LDO_5_HPM_MIN_LOAD		0
 #define RPM_VREG_8960_LDO_50_HPM_MIN_LOAD		5000
 #define RPM_VREG_8960_LDO_150_HPM_MIN_LOAD		10000
 #define RPM_VREG_8960_LDO_300_HPM_MIN_LOAD		10000
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index a9598b1..546cbaf 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -44,6 +44,16 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm9625")
 #define machine_is_msm9625()		\
 	of_machine_is_compatible("qcom,msm9625")
+#define early_machine_is_mpq8092()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
+#define machine_is_mpq8092_sim()           \
+	of_machine_is_compatible("qcom,mpq8092-sim")
+#define early_machine_is_msm8226()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8226")
+#define machine_is_msm8226()		\
+	of_machine_is_compatible("qcom,msm8226")
+#define machine_is_msm8226_sim()		\
+	of_machine_is_compatible("qcom,msm8226-sim")
 #else
 #define early_machine_is_msm8974()	0
 #define machine_is_msm8974()		0
@@ -51,6 +61,12 @@
 #define machine_is_msm8974_rumi()	0
 #define early_machine_is_msm9625()	0
 #define machine_is_msm9625()		0
+#define early_machine_is_mpq8092()	0
+#define machine_is_mpq8092_sim()	0
+#define early_machine_is_msm8226()	0
+#define machine_is_msm8226()		0
+#define machine_is_msm8226_sim()	0
+
 #endif
 
 #define PLATFORM_SUBTYPE_SGLTE	6
@@ -80,7 +96,9 @@
 	MSM_CPU_8974,
 	MSM_CPU_8627,
 	MSM_CPU_8625,
-	MSM_CPU_9625
+	MSM_CPU_9625,
+	MSM_CPU_8092,
+	MSM_CPU_8226
 };
 
 enum pmic_model {
@@ -362,4 +380,29 @@
 #endif
 }
 
+static inline int cpu_is_mpq8092(void)
+{
+#ifdef CONFIG_ARCH_MPQ8092
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8092;
+#else
+	return 0;
+#endif
+
+}
+
+static inline int cpu_is_msm8226(void)
+{
+#ifdef CONFIG_ARCH_MSM8226
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8226;
+#else
+	return 0;
+#endif
+}
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 6d15f47..d3c4eb8 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -27,8 +27,21 @@
 	RESET_LEVEL_MAX
 };
 
+struct device;
+struct module;
+
+/**
+ * struct subsys_desc - subsystem descriptor
+ * @name: name of subsystem
+ * @depends_on: subsystem this subsystem depends on to operate
+ * @dev: parent device
+ * @owner: module the descriptor belongs to
+ */
 struct subsys_desc {
 	const char *name;
+	const char *depends_on;
+	struct device *dev;
+	struct module *owner;
 
 	int (*shutdown)(const struct subsys_desc *desc);
 	int (*powerup)(const struct subsys_desc *desc);
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 2035d3f..e0fec65 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -310,6 +310,7 @@
 #ifdef CONFIG_DEBUG_MSM8974_UART
 	MSM_DEVICE(DEBUG_UART),
 #endif
+	MSM_CHIP_DEVICE(DBG_IMEM, MSM8974),
 };
 
 void __init msm_map_8974_io(void)
@@ -477,3 +478,52 @@
 	msm_map_io(msm9625_io_desc, ARRAY_SIZE(msm9625_io_desc));
 }
 #endif /* CONFIG_ARCH_MSM9625 */
+
+#ifdef CONFIG_ARCH_MPQ8092
+static struct map_desc mpq8092_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
+	MSM_CHIP_DEVICE(QGIC_CPU, MPQ8092),
+	MSM_CHIP_DEVICE(APCS_GCC, MPQ8092),
+	MSM_CHIP_DEVICE(TLMM, MPQ8092),
+	{
+		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
+		.length =   MSM_SHARED_RAM_SIZE,
+		.type =     MT_DEVICE,
+	},
+#ifdef CONFIG_DEBUG_MPQ8092_UART
+	MSM_DEVICE(DEBUG_UART),
+#endif
+};
+
+void __init msm_map_mpq8092_io(void)
+{
+	msm_shared_ram_phys = MSM8092_MSM_SHARED_RAM_PHYS;
+	msm_map_io(mpq8092_io_desc, ARRAY_SIZE(mpq8092_io_desc));
+}
+#endif /* CONFIG_ARCH_MPQ8092 */
+
+#ifdef CONFIG_ARCH_MSM8226
+static struct map_desc msm_8226_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(QGIC_DIST, MSM8226),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8226),
+	MSM_CHIP_DEVICE(APCS_GCC, MSM8226),
+	MSM_CHIP_DEVICE(TLMM, MSM8226),
+	MSM_CHIP_DEVICE(IMEM, MSM8226),
+	MSM_CHIP_DEVICE(DBG_IMEM, MSM8226),
+	{
+		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
+		.length =   MSM_SHARED_RAM_SIZE,
+		.type =     MT_DEVICE,
+	},
+#ifdef CONFIG_DEBUG_MSM8226_UART
+	MSM_DEVICE(DEBUG_UART),
+#endif
+};
+
+
+void __init msm_map_msm8226_io(void)
+{
+	msm_shared_ram_phys = MSM8226_MSM_SHARED_RAM_PHYS;
+	msm_map_io(msm_8226_io_desc, ARRAY_SIZE(msm_8226_io_desc));
+}
+#endif /* CONFIG_ARCH_MSM8226 */
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index bf5857c..4f14b19 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.c
@@ -25,6 +25,12 @@
 
 #include "cp14.h"
 
+/* DBGv7 with baseline CP14 registers implemented */
+#define ARM_DEBUG_ARCH_V7B	(0x3)
+/* DBGv7 with all CP14 registers implemented */
+#define ARM_DEBUG_ARCH_V7	(0x4)
+#define ARM_DEBUG_ARCH_V7p1	(0x5)
+
 #define BM(lsb, msb)		((BIT(msb) - BIT(lsb)) + BIT(msb))
 #define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
 #define BVAL(val, n)		((val & BIT(n)) >> n)
@@ -363,7 +369,7 @@
 static inline bool dbg_arch_supported(uint8_t arch)
 {
 	switch (arch) {
-	case ARM_DEBUG_ARCH_V7_1:
+	case ARM_DEBUG_ARCH_V7p1:
 	case ARM_DEBUG_ARCH_V7:
 	case ARM_DEBUG_ARCH_V7B:
 		break;
@@ -381,7 +387,7 @@
 	i = cpu * MAX_DBG_REGS;
 
 	switch (dbg.arch) {
-	case ARM_DEBUG_ARCH_V7_1:
+	case ARM_DEBUG_ARCH_V7p1:
 		/* Set OS lock to inform the debugger that the OS is in the
 		 * process of saving debug registers. It prevents accidental
 		 * modification of the debug regs by the external debugger.
@@ -440,7 +446,7 @@
 	i = cpu * MAX_DBG_REGS;
 
 	switch (dbg.arch) {
-	case ARM_DEBUG_ARCH_V7_1:
+	case ARM_DEBUG_ARCH_V7p1:
 		/* Clear the OS double lock */
 		isb();
 		dbg_write(0x0, DBGOSDLR);
@@ -1070,6 +1076,20 @@
 
 	cpu = raw_smp_processor_id();
 
+	/* Attempt restore only if save has been done. If power collapse
+	 * is disabled, hotplug off of non-boot core will result in WFI
+	 * and hence msm_jtag_save_state will not occur. Subsequently,
+	 * during hotplug on of non-boot core when msm_jtag_restore_state
+	 * is called via msm_platform_secondary_init, this check will help
+	 * bail us out without restoring.
+	 */
+	if (msm_jtag_save_cntr[cpu] == msm_jtag_restore_cntr[cpu])
+		return;
+	else if (msm_jtag_save_cntr[cpu] != msm_jtag_restore_cntr[cpu] + 1)
+		pr_err_ratelimited("jtag imbalance, save:%lu, restore:%lu\n",
+				   (unsigned long)msm_jtag_save_cntr[cpu],
+				   (unsigned long)msm_jtag_restore_cntr[cpu]);
+
 	msm_jtag_restore_cntr[cpu]++;
 	/* ensure counter is updated before moving forward */
 	mb();
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 7d432f4..48d31f3 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -698,7 +698,7 @@
 	case CPU_DEAD_FROZEN:
 	case CPU_DEAD:
 		if (num_online_cpus() == 1)
-			rs->rs_data.value = MSM_LPM_L2_CACHE_GDHS;
+			rs->rs_data.value = MSM_LPM_L2_CACHE_HSFS_OPEN;
 		break;
 	}
 	return NOTIFY_OK;
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index 844a78b..f0a123b 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -258,8 +258,7 @@
 {
 	int ret;
 
-	if (!cpu_is_msm8960() && !cpu_is_msm8930() && !cpu_is_msm8930aa() &&
-	    !cpu_is_msm9615() && !cpu_is_msm8627())
+	if (cpu_is_apq8064())
 		return -ENODEV;
 
 	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
diff --git a/arch/arm/mach-msm/modem-ssr-8974.c b/arch/arm/mach-msm/modem-ssr-8974.c
new file mode 100644
index 0000000..fec578f
--- /dev/null
+++ b/arch/arm/mach-msm/modem-ssr-8974.c
@@ -0,0 +1,141 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <mach/subsystem_restart.h>
+#include <mach/msm_smsm.h>
+
+static int crash_shutdown;
+static struct subsys_device *modem_ssr_dev;
+
+#define MAX_SSR_REASON_LEN 81U
+#define Q6SS_WDOG_ENABLE		0xFC802004
+#define MSS_Q6SS_WDOG_EXP_IRQ		56
+
+static void log_modem_sfr(void)
+{
+	u32 size;
+	char *smem_reason, reason[MAX_SSR_REASON_LEN];
+
+	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+	if (!smem_reason || !size) {
+		pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
+		return;
+	}
+	if (!smem_reason[0]) {
+		pr_err("modem subsystem failure reason: (unknown, empty string found).\n");
+		return;
+	}
+
+	strlcpy(reason, smem_reason, min(size, sizeof(reason)));
+	pr_err("modem subsystem failure reason: %s.\n", reason);
+
+	smem_reason[0] = '\0';
+	wmb();
+}
+
+static void restart_modem(void)
+{
+	log_modem_sfr();
+	subsystem_restart("modem");
+}
+
+static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+{
+	/* Ignore if we're the one that set SMSM_RESET */
+	if (crash_shutdown)
+		return;
+
+	if (new_state & SMSM_RESET) {
+		pr_err("Probable fatal error on the modem.\n");
+		restart_modem();
+	}
+}
+
+static int modem_shutdown(const struct subsys_desc *subsys)
+{
+	return 0;
+}
+
+static int modem_powerup(const struct subsys_desc *subsys)
+{
+	return 0;
+}
+
+void modem_crash_shutdown(const struct subsys_desc *subsys)
+{
+	crash_shutdown = 1;
+	smsm_reset_modem(SMSM_RESET);
+}
+
+static int modem_ramdump(int enable,
+				const struct subsys_desc *crashed_subsys)
+{
+	return 0;
+}
+
+static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
+{
+	pr_err("Watchdog bite received from modem software!\n");
+	restart_modem();
+	return IRQ_HANDLED;
+}
+
+static struct subsys_desc modem_8974 = {
+	.name = "modem",
+	.shutdown = modem_shutdown,
+	.powerup = modem_powerup,
+	.ramdump = modem_ramdump,
+	.crash_shutdown = modem_crash_shutdown
+};
+
+static int __init modem_8974_init(void)
+{
+	int ret;
+
+	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
+		smsm_state_cb, 0);
+
+	if (ret < 0) {
+		pr_err("%s: Unable to register SMSM callback! (%d)\n",
+				__func__, ret);
+		goto out;
+	}
+
+	ret = request_irq(MSS_Q6SS_WDOG_EXP_IRQ, modem_wdog_bite_irq,
+			IRQF_TRIGGER_RISING, "modem_wdog_sw", NULL);
+
+	if (ret < 0) {
+		pr_err("%s: Unable to request q6sw watchdog IRQ. (%d)\n",
+				__func__, ret);
+		goto out;
+	}
+
+	modem_ssr_dev = subsys_register(&modem_8974);
+
+	if (IS_ERR_OR_NULL(modem_ssr_dev)) {
+		pr_err("%s: Unable to reg with subsystem restart. (%ld)\n",
+				__func__, PTR_ERR(modem_ssr_dev));
+		ret = PTR_ERR(modem_ssr_dev);
+		goto out;
+	}
+
+	pr_info("%s: modem subsystem restart driver init'ed.\n", __func__);
+out:
+	return ret;
+}
+
+arch_initcall(modem_8974_init);
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index 924577f..bdc6fac 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -2,7 +2,7 @@
 # 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
+obj-y += msm_bus_bimc.o msm_bus_noc.o 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_8974.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8974.c
index 265716d..1b8c07e 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
@@ -804,7 +804,7 @@
 		.num_tiers = ARRAY_SIZE(tier2),
 		.hw_sel = MSM_BUS_NOC,
 		.perm_mode = NOC_QOS_MODES_ALL_PERM,
-		.mode = NOC_QOS_MODE_FIXED,
+		.mode = NOC_QOS_MODE_BYPASS,
 		.ws = 10000,
 		.qport = qports_oxili,
 		.mas_hw_id = MAS_GFX3D,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
index e6ec722..049e8c7 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
@@ -189,10 +189,10 @@
 }
 
 static void noc_set_qos_mode(struct msm_bus_noc_info *ninfo, uint32_t mport,
-	uint8_t mode)
+	uint8_t mode, uint8_t perm_mode)
 {
 	if (mode < NOC_QOS_MODE_MAX &&
-		((1 << mode) & ninfo->mas_modes[mport])) {
+		((1 << mode) & perm_mode)) {
 		uint32_t reg_val;
 
 		reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
@@ -297,13 +297,13 @@
 }
 
 uint8_t msm_bus_noc_get_qos_mode(struct msm_bus_noc_info *ninfo,
-	uint32_t mport)
+	uint32_t mport, uint32_t mode, uint32_t perm_mode)
 {
-	if (NOC_QOS_MODES_ALL_PERM == ninfo->mas_modes[mport])
+	if (NOC_QOS_MODES_ALL_PERM == perm_mode)
 		return readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
 			mport)) & NOC_QOS_MODEn_MODE_BMSK;
 	else
-		return 31 - __CLZ(ninfo->mas_modes[mport] &
+		return 31 - __CLZ(mode &
 			NOC_QOS_MODES_ALL_PERM);
 }
 
@@ -320,9 +320,9 @@
 }
 
 void msm_bus_noc_get_qos_bw(struct msm_bus_noc_info *ninfo,
-	uint32_t mport, struct msm_bus_noc_qos_bw *qbw)
+	uint32_t mport, uint8_t perm_mode, struct msm_bus_noc_qos_bw *qbw)
 {
-	if (ninfo->mas_modes[mport] & (NOC_QOS_PERM_MODE_LIMITER |
+	if (perm_mode & (NOC_QOS_PERM_MODE_LIMITER |
 		NOC_QOS_PERM_MODE_REGULATOR)) {
 		uint32_t bw_val = readl_relaxed(NOC_QOS_BWn_ADDR(ninfo->
 			base, mport)) & NOC_QOS_BWn_BW_BMSK;
@@ -375,7 +375,7 @@
 		}
 
 		noc_set_qos_mode(ninfo, info->node_info->qport[i], info->
-			node_info->mode);
+			node_info->mode, info->node_info->perm_mode);
 	}
 
 	return 0;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.h b/arch/arm/mach-msm/msm_bus/msm_bus_noc.h
index 407d3ec..35af884 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_noc.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.h
@@ -64,10 +64,10 @@
 
 void msm_bus_noc_init(struct msm_bus_noc_info *ninfo);
 uint8_t msm_bus_noc_get_qos_mode(struct msm_bus_noc_info *ninfo,
-	uint32_t mport);
+	uint32_t mport, uint32_t mode, uint32_t perm_mode);
 void msm_bus_noc_get_qos_priority(struct msm_bus_noc_info *ninfo,
 	uint32_t mport, struct msm_bus_noc_qos_priority *qprio);
 void msm_bus_noc_get_qos_bw(struct msm_bus_noc_info *ninfo,
-	uint32_t mport, struct msm_bus_noc_qos_bw *qbw);
+	uint32_t mport, uint8_t perm_mode, struct msm_bus_noc_qos_bw *qbw);
 
 #endif /*_ARCH_ARM_MACH_MSM_BUS_NOC_H */
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_of.c b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
new file mode 100644
index 0000000..24b0ce2
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -0,0 +1,150 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <mach/msm_bus.h>
+
+/**
+ * msm_bus_cl_get_pdata() - Generate bus client data from device tree
+ * provided by clients.
+ *
+ * of_node: Device tree node to extract information from
+ *
+ * The function returns a valid pointer to the allocated bus-scale-pdata
+ * if the vectors were correctly read from the client's device node.
+ * Any error in reading or parsing the device node will return NULL
+ * to the caller.
+ */
+struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev)
+{
+	struct device_node *of_node;
+	struct msm_bus_scale_pdata *pdata = NULL;
+	struct msm_bus_paths *usecase = NULL;
+	int i = 0, j, ret, num_usecases = 0, num_paths, len;
+	const uint32_t *vec_arr = NULL;
+	bool mem_err = false;
+
+	if (!pdev) {
+		pr_err("Error: Null Platform device\n");
+		return NULL;
+	}
+
+	of_node = pdev->dev.of_node;
+	pdata = devm_kzalloc(&pdev->dev, sizeof(struct msm_bus_scale_pdata),
+		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, "qcom,msm_bus,name",
+		&pdata->name);
+	if (ret) {
+		pr_err("Error: Client name not found\n");
+		goto err;
+	}
+
+	ret = of_property_read_u32(of_node, "qcom,msm_bus,num_cases",
+		&num_usecases);
+	if (ret) {
+		pr_err("Error: num_usecases not found\n");
+		goto err;
+	}
+
+	pdata->num_usecases = num_usecases;
+	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");
+	}
+
+	usecase = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_paths) *
+		pdata->num_usecases), GFP_KERNEL);
+	if (!usecase) {
+		pr_err("Error: Memory allocation for paths failed\n");
+		mem_err = true;
+		goto err;
+	}
+
+	ret = of_property_read_u32(of_node, "qcom,msm_bus,num_paths",
+		&num_paths);
+	if (ret) {
+		pr_err("Error: num_paths not found\n");
+		goto err;
+	}
+
+	vec_arr = of_get_property(of_node, "qcom,msm_bus,vectors", &len);
+	if (len != num_usecases * num_paths * sizeof(struct msm_bus_vectors)) {
+		pr_err("Error: Length-error on getting vectors\n");
+		goto err;
+	}
+
+	for (i = 0; i < num_usecases; i++) {
+		usecase[i].num_paths = num_paths;
+		usecase[i].vectors = devm_kzalloc(&pdev->dev, num_paths *
+			sizeof(struct msm_bus_vectors), GFP_KERNEL);
+		if (!usecase[i].vectors) {
+			mem_err = true;
+			pr_err("Error: Mem alloc failure in vectors\n");
+			goto err;
+		}
+
+		for (j = 0; j < num_paths; j++) {
+			int index = ((i * num_paths) + j) * 4;
+			usecase[i].vectors[j].src = be32_to_cpu(vec_arr[index]);
+			usecase[i].vectors[j].dst =
+				be32_to_cpu(vec_arr[index + 1]);
+			usecase[i].vectors[j].ab =
+				be32_to_cpu(vec_arr[index + 2]);
+			usecase[i].vectors[j].ib =
+				be32_to_cpu(vec_arr[index + 3]);
+		}
+	}
+
+	pdata->usecase = usecase;
+	return pdata;
+err:
+	if (mem_err) {
+		for (; i > 0; i--)
+			kfree(usecase[i-1].vectors);
+
+		kfree(usecase);
+		kfree(pdata);
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(msm_bus_cl_get_pdata);
+
+/**
+ * msm_bus_cl_clear_pdata() - Clear pdata allocated from device-tree
+ * of_node: Device tree node to extract information from
+ */
+void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata)
+{
+	int i;
+
+	for (i = 0; i < pdata->num_usecases; i++)
+		kfree(pdata->usecase[i].vectors);
+
+	kfree(pdata->usecase);
+	kfree(pdata);
+}
+EXPORT_SYMBOL(msm_bus_cl_clear_pdata);
diff --git a/arch/arm/mach-msm/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index a61bd20..e2640a2 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -15,6 +15,7 @@
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -47,6 +48,10 @@
 /* Need platform device handle for suspend and resume APIs */
 static struct platform_device *cpr_pdev;
 
+static bool enable = 1;
+module_param(enable, bool, 0644);
+MODULE_PARM_DESC(enable, "CPR Enable");
+
 struct msm_cpr {
 	int curr_osc;
 	int cpr_mode;
@@ -747,6 +752,9 @@
 	struct resource *mem;
 	struct msm_cpr_mode *chip_data;
 
+	if (!enable)
+		return -EPERM;
+
 	if (!pdata) {
 		pr_err("CPR: Platform data is not available\n");
 		return -EIO;
diff --git a/arch/arm/mach-msm/msm_memory_dump.c b/arch/arm/mach-msm/msm_memory_dump.c
index 17cb2da..154b4fe 100644
--- a/arch/arm/mach-msm/msm_memory_dump.c
+++ b/arch/arm/mach-msm/msm_memory_dump.c
@@ -69,6 +69,12 @@
 	mem_dump_data.dump_table_phys = virt_to_phys(table);
 	writel_relaxed(mem_dump_data.dump_table_phys,
 				MSM_IMEM_BASE + DUMP_TABLE_OFFSET);
+	/* TODO: Write to Debug image IMEM.
+	 * Once IMEM issues are resolved MSM_IMEM_BASE
+	 * will have actual mapping.
+	 */
+	writel_relaxed(mem_dump_data.dump_table_phys,
+				MSM_DBG_IMEM_BASE + DUMP_TABLE_OFFSET);
 	atomic_notifier_chain_register(&panic_notifier_list,
 						&msm_memory_dump_blk);
 	printk(KERN_INFO "MSM Memory Dump table set up\n");
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 51445aa..793fcc5 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -372,6 +372,27 @@
 	pr_debug("ocmem: Disabled iface clock\n");
 }
 
+/* Block-Remapper Clock Operations */
+int ocmem_enable_br_clock(void)
+{
+	int ret;
+
+	ret = clk_prepare_enable(ocmem_pdata->br_clk);
+
+	if (ret) {
+		pr_err("ocmem: Failed to enable br clock\n");
+		return ret;
+	}
+	pr_debug("ocmem: Enabled br clock\n");
+	return 0;
+}
+
+void ocmem_disable_br_clock(void)
+{
+	clk_disable_unprepare(ocmem_pdata->br_clk);
+	pr_debug("ocmem: Disabled br clock\n");
+}
+
 static struct ocmem_plat_data *parse_dt_config(struct platform_device *pdev)
 {
 	struct device   *dev = &pdev->dev;
@@ -719,6 +740,7 @@
 	struct device   *dev = &pdev->dev;
 	struct clk *ocmem_core_clk = NULL;
 	struct clk *ocmem_iface_clk = NULL;
+	struct clk *ocmem_br_clk = NULL;
 
 	if (!pdev->dev.of_node) {
 		dev_info(dev, "Missing Configuration in Device Tree\n");
@@ -757,8 +779,16 @@
 		return PTR_ERR(ocmem_core_clk);
 	};
 
+	ocmem_br_clk = devm_clk_get(dev, "br_clk");
+
+	if (IS_ERR(ocmem_br_clk)) {
+		dev_err(dev, "Unable to get the BR clock\n");
+		return PTR_ERR(ocmem_br_clk);
+	}
+
 	ocmem_pdata->core_clk = ocmem_core_clk;
 	ocmem_pdata->iface_clk = ocmem_iface_clk;
+	ocmem_pdata->br_clk = ocmem_br_clk;
 
 	platform_set_drvdata(pdev, ocmem_pdata);
 
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
index 2604d47..6e094fd 100644
--- a/arch/arm/mach-msm/ocmem_api.c
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -131,6 +131,7 @@
 	return __ocmem_allocate_range(client_id, size, size,
 					size, can_block, can_wait);
 }
+EXPORT_SYMBOL(ocmem_allocate);
 
 struct ocmem_buf *ocmem_allocate_nowait(int client_id, unsigned long size)
 {
@@ -162,6 +163,7 @@
 	return __ocmem_allocate_range(client_id, size, size,
 					size, can_block, can_wait);
 }
+EXPORT_SYMBOL(ocmem_allocate_nowait);
 
 struct ocmem_buf *ocmem_allocate_range(int client_id, unsigned long min,
 		unsigned long goal, unsigned long step)
@@ -202,6 +204,7 @@
 	return __ocmem_allocate_range(client_id, min, goal,
 				step, can_block, can_wait);
 }
+EXPORT_SYMBOL(ocmem_allocate_range);
 
 struct ocmem_buf *ocmem_allocate_nb(int client_id, unsigned long size)
 {
@@ -242,6 +245,7 @@
 						can_block, can_wait);
 
 }
+EXPORT_SYMBOL(ocmem_allocate_nb);
 
 int ocmem_free(int client_id, struct ocmem_buf *buffer)
 {
@@ -263,6 +267,7 @@
 
 	return __ocmem_free(client_id, buffer);
 }
+EXPORT_SYMBOL(ocmem_free);
 
 int ocmem_shrink(int client_id, struct ocmem_buf *buffer, unsigned long len)
 {
@@ -279,6 +284,7 @@
 
 	return __ocmem_shrink(client_id, buffer, len);
 }
+EXPORT_SYMBOL(ocmem_shrink);
 
 int pre_validate_chunk_list(struct ocmem_map_list *list)
 {
@@ -350,6 +356,7 @@
 	mutex_unlock(&handle->handle_mutex);
 	return ret;
 }
+EXPORT_SYMBOL(ocmem_map);
 
 int ocmem_unmap(int client_id, struct ocmem_buf *buffer,
 			struct ocmem_map_list *list)
@@ -390,6 +397,7 @@
 	mutex_unlock(&handle->handle_mutex);
 	return ret;
 }
+EXPORT_SYMBOL(ocmem_unmap);
 
 unsigned long get_max_quota(int client_id)
 {
@@ -427,6 +435,7 @@
 	mutex_unlock(&ocmem_eviction_lock);
 	return ret;
 }
+EXPORT_SYMBOL(ocmem_evict);
 
 int ocmem_restore(int client_id)
 {
@@ -448,6 +457,7 @@
 	mutex_unlock(&ocmem_eviction_lock);
 	return ret;
 }
+EXPORT_SYMBOL(ocmem_restore);
 
 /* Wrappers until power control is transitioned to clients */
 enum ocmem_power_state ocmem_get_power_state(int client_id,
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index de9856d..5a85eec 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -38,6 +38,7 @@
 	unsigned psgsc_ctrl;
 	bool interleaved;
 	unsigned int mode;
+	atomic_t mode_counter;
 	unsigned int num_macros;
 	struct ocmem_hw_macro *macro;
 	struct msm_rpm_request *rpm_req;
@@ -57,10 +58,13 @@
 #define OC_GEN_STATUS (0xC)
 #define OC_PSGSC_STATUS (0x38)
 #define OC_PSGSC_CTL (0x3C)
-#define OC_REGION_CTL (0x1000)
+#define OC_REGION_MODE_CTL (0x1000)
+#define OC_GFX_MPU_START (0x1004)
+#define OC_GFX_MPU_END (0x1008)
 
 #define NUM_PORTS_MASK (0xF << 0)
 #define NUM_PORTS_SHIFT (0)
+#define GFX_MPU_SHIFT (12)
 
 #define NUM_MACROS_MASK (0xF << 8)
 #define NUM_MACROS_SHIFT (8)
@@ -73,7 +77,7 @@
 #define CORE_ON (0x2)
 #define PERI_ON (0x1)
 #define CLK_OFF (0x4)
-#define MACRO_ON (CORE_ON|PERI_ON)
+#define MACRO_ON (0x0)
 #define MACRO_SLEEP_RETENTION (CLK_OFF|CORE_ON)
 #define MACRO_SLEEP_RETENTION_PERI_ON (CLK_OFF|MACRO_ON)
 #define MACRO_OFF (CLK_OFF)
@@ -166,6 +170,8 @@
 	else
 		rc = ocmem_write(new_state,
 					ocmem_base + PSCGC_CTL_n(region_num));
+	/* Barrier to commit the region state */
+	mb();
 	return 0;
 }
 
@@ -325,6 +331,9 @@
 	/* In narrow mode each macro is allowed to be in a different state */
 	/* The region mode is simply the collection of all macro states */
 		for (i = 0; i < region->num_macros; i++) {
+			pr_debug("aggregated region state %x\n", r_state);
+			pr_debug("macro %d\n state %x\n", i,
+						region->macro[i].m_state);
 			r_state &= ~M_PSCGC_CTL_n(i);
 			r_state |= region->macro[i].m_state << (i * 4);
 		}
@@ -384,6 +393,198 @@
 	return 0;
 }
 
+
+static int switch_region_mode(unsigned long offset, unsigned long len,
+						enum region_mode new_mode)
+{
+	unsigned region_start = num_regions;
+	unsigned region_end = num_regions;
+	int i = 0;
+
+	if (offset < 0)
+		return -EINVAL;
+
+	if (len < region_size)
+		return -EINVAL;
+
+	pr_debug("ocmem: mode_transistion to %x\n", new_mode);
+
+	region_start = offset / region_size;
+	region_end = (offset + len - 1) / region_size;
+
+	pr_debug("ocmem: region start %u end %u\n", region_start, region_end);
+
+	if (region_start >= num_regions ||
+			(region_end >= num_regions))
+					return -EINVAL;
+
+	for (i = region_start; i <= region_end; i++) {
+		struct ocmem_hw_region *region = &region_ctrl[i];
+		if (region->mode == MODE_DEFAULT) {
+			/* No prior mode programming on this region */
+			/* Set the region to its new mode */
+			region->mode = new_mode;
+			atomic_inc(&region->mode_counter);
+			pr_debug("Region  (%d) switching to mode %d\n",
+					i, new_mode);
+			continue;
+		} else if (region->mode != new_mode) {
+			/* The region is currently set to a different mode */
+			if (new_mode == MODE_DEFAULT) {
+				if (atomic_dec_and_test
+						(&region->mode_counter)) {
+					region->mode = MODE_DEFAULT;
+					pr_debug("Region (%d) restoring to default mode\n",
+								i);
+				} else {
+					/* More than 1 client in region */
+					/* Cannot move to default mode */
+					pr_debug("Region (%d) using current mode %d\n",
+							i, region->mode);
+					continue;
+				}
+			} else {
+				/* Do not switch modes */
+				pr_err("Region (%d) requested mode %x conflicts with current\n",
+							i, new_mode);
+				goto mode_switch_fail;
+			}
+		}
+	}
+	return 0;
+
+mode_switch_fail:
+	return -EINVAL;
+}
+
+#ifdef CONFIG_MSM_OCMEM_NONSECURE
+
+static int commit_region_modes(void)
+{
+	uint32_t region_mode_ctrl = 0x0;
+	unsigned pos = 0;
+	unsigned i = 0;
+
+	for (i = 0; i < num_regions; i++) {
+		struct ocmem_hw_region *region = &region_ctrl[i];
+		pos = i << 2;
+		if (region->mode == THIN_MODE)
+			region_mode_ctrl |= BIT(pos);
+	}
+	pr_debug("ocmem_region_mode_control %x\n", region_mode_ctrl);
+	ocmem_write(region_mode_ctrl, ocmem_base + OC_REGION_MODE_CTL);
+	/* Barrier to commit the region mode */
+	mb();
+	return 0;
+}
+
+static int ocmem_gfx_mpu_set(unsigned long offset, unsigned long len)
+{
+	int mpu_start = 0x0;
+	int mpu_end = 0x0;
+
+	if (offset)
+		mpu_start = (offset >> GFX_MPU_SHIFT) - 1;
+	if (mpu_start < 0)
+		/* Avoid underflow */
+		mpu_start = 0;
+	mpu_end = ((offset+len) >> GFX_MPU_SHIFT) - 1;
+	BUG_ON(mpu_end < 0);
+
+	pr_debug("ocmem: mpu: start %x end %x\n", mpu_start, mpu_end);
+	ocmem_write(mpu_start << GFX_MPU_SHIFT, ocmem_base + OC_GFX_MPU_START);
+	ocmem_write(mpu_end << GFX_MPU_SHIFT, ocmem_base + OC_GFX_MPU_END);
+	return 0;
+}
+
+static void ocmem_gfx_mpu_remove(void)
+{
+	ocmem_write(0x0, ocmem_base + OC_GFX_MPU_START);
+	ocmem_write(0x0, ocmem_base + OC_GFX_MPU_END);
+}
+
+static int do_lock(enum ocmem_client id, unsigned long offset,
+			unsigned long len, enum region_mode mode)
+{
+	return 0;
+}
+
+static int do_unlock(enum ocmem_client id, unsigned long offset,
+			unsigned long len)
+{
+	ocmem_clear(offset, len);
+	return 0;
+}
+#else
+static int ocmem_gfx_mpu_set(unsigned long offset, unsigned long len)
+{
+	return 0;
+}
+
+static void ocmem_gfx_mpu_remove(void)
+{
+}
+
+static int commit_region_modes(void)
+{
+	return 0;
+}
+
+static int do_lock(enum ocmem_client id, unsigned long offset,
+			unsigned long len, enum region_mode mode)
+{
+	return 0;
+}
+
+static int do_unlock(enum ocmem_client id, unsigned long offset,
+			unsigned long len)
+{
+	return 0;
+}
+#endif /* CONFIG_MSM_OCMEM_NONSECURE */
+
+int ocmem_lock(enum ocmem_client id, unsigned long offset, unsigned long len,
+					enum region_mode mode)
+{
+
+	if (len < OCMEM_MIN_ALLOC) {
+		pr_err("ocmem: Invalid len %lx for lock\n", len);
+		return -EINVAL;
+	}
+
+	if (id == OCMEM_GRAPHICS)
+		ocmem_gfx_mpu_set(offset, len);
+
+	mutex_lock(&region_ctrl_lock);
+
+	if (switch_region_mode(offset, len, mode) < 0)
+			goto switch_region_fail;
+
+	commit_region_modes();
+
+	do_lock(id, offset, len, mode);
+
+	mutex_unlock(&region_ctrl_lock);
+	return 0;
+
+switch_region_fail:
+	mutex_unlock(&region_ctrl_lock);
+	return -EINVAL;
+}
+
+int ocmem_unlock(enum ocmem_client id, unsigned long offset, unsigned long len)
+{
+	if (id == OCMEM_GRAPHICS)
+		ocmem_gfx_mpu_remove();
+
+	mutex_lock(&region_ctrl_lock);
+	do_unlock(id, offset, len);
+	switch_region_mode(offset, len , MODE_DEFAULT);
+	commit_region_modes();
+	mutex_unlock(&region_ctrl_lock);
+	return 0;
+}
+
 #if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
 static int ocmem_core_set_default_state(void)
 {
@@ -398,6 +599,9 @@
 	if (rc < 0)
 		return rc;
 
+	rc = ocmem_enable_br_clock();
+	if (rc < 0)
+		return rc;
 	return 0;
 }
 
@@ -808,6 +1012,7 @@
 		struct msm_rpm_request *req = NULL;
 		region->interleaved = interleaved;
 		region->mode = MODE_DEFAULT;
+		atomic_set(&region->mode_counter, 0);
 		region->r_state = REGION_DEFAULT_OFF;
 		region->num_macros = num_banks;
 
diff --git a/arch/arm/mach-msm/ocmem_rdm.c b/arch/arm/mach-msm/ocmem_rdm.c
index ccbef9b..85dc85d 100644
--- a/arch/arm/mach-msm/ocmem_rdm.c
+++ b/arch/arm/mach-msm/ocmem_rdm.c
@@ -38,8 +38,12 @@
 
 #define DM_INTR_CLR (0x8)
 #define DM_INTR_MASK (0xC)
-#define DM_GEN_STATUS (0x10)
-#define DM_STATUS (0x14)
+#define DM_INT_STATUS (0x10)
+#define DM_GEN_STATUS (0x14)
+#define DM_CLR_OFFSET (0x18)
+#define DM_CLR_SIZE (0x1C)
+#define DM_CLR_PATTERN (0x20)
+#define DM_CLR_TRIGGER (0x24)
 #define DM_CTRL (0x1000)
 #define DM_TBL_BASE (0x1010)
 #define DM_TBL_IDX(x) ((x) * 0x18)
@@ -82,8 +86,9 @@
 #define DM_DIR_SHIFT 0x0
 
 #define DM_DONE 0x1
-#define DM_INTR_ENABLE 0x0
-#define DM_INTR_DISABLE 0x1
+#define DM_MASK_RESET 0x0
+#define DM_INTR_RESET 0x20003
+#define DM_CLR_ENABLE 0x1
 
 static void *br_base;
 static void *dm_base;
@@ -122,12 +127,59 @@
 
 static irqreturn_t ocmem_dm_irq_handler(int irq, void *dev_id)
 {
+	unsigned status;
+	unsigned irq_status;
+	status = ocmem_read(dm_base + DM_GEN_STATUS);
+	irq_status = ocmem_read(dm_base + DM_INT_STATUS);
+	pr_debug("irq:dm_status %x irq_status %x\n", status, irq_status);
+	if (irq_status & BIT(0)) {
+		pr_debug("Data mover completed\n");
+		irq_status &= ~BIT(0);
+		ocmem_write(irq_status, dm_base + DM_INTR_CLR);
+	} else if (irq_status & BIT(1)) {
+		pr_debug("Data clear engine completed\n");
+		irq_status &= ~BIT(1);
+		ocmem_write(irq_status, dm_base + DM_INTR_CLR);
+	} else {
+		BUG_ON(1);
+	}
 	atomic_set(&dm_pending, 0);
-	ocmem_write(DM_INTR_DISABLE, dm_base + DM_INTR_CLR);
 	wake_up_interruptible(&dm_wq);
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_MSM_OCMEM_NONSECURE
+int ocmem_clear(unsigned long start, unsigned long size)
+{
+	atomic_set(&dm_pending, 1);
+	/* Clear DM Mask */
+	ocmem_write(DM_MASK_RESET, dm_base + DM_INTR_MASK);
+	/* Clear DM Interrupts */
+	ocmem_write(DM_INTR_RESET, dm_base + DM_INTR_CLR);
+	/* DM CLR offset */
+	ocmem_write(start, dm_base + DM_CLR_OFFSET);
+	/* DM CLR size */
+	ocmem_write(size, dm_base + DM_CLR_SIZE);
+	/* Wipe out memory as "OCMM" */
+	ocmem_write(0x4D4D434F, dm_base + DM_CLR_PATTERN);
+	/* The offset, size and pattern for clearing must be set
+	 * before triggering the clearing engine
+	 */
+	mb();
+	/* Trigger Data Clear */
+	ocmem_write(DM_CLR_ENABLE, dm_base + DM_CLR_TRIGGER);
+
+	wait_event_interruptible(dm_wq,
+		atomic_read(&dm_pending) == 0);
+	return 0;
+}
+#else
+int ocmem_clear(unsigned long start, unsigned long size)
+{
+	return 0;
+}
+#endif
+
 /* Lock during transfers */
 int ocmem_rdm_transfer(int id, struct ocmem_map_list *clist,
 			unsigned long start, int direction)
@@ -195,9 +247,13 @@
 	dm_ctrl |= (DM_BLOCK_256 << DM_BR_BLK_SHIFT);
 	dm_ctrl |= (direction << DM_DIR_SHIFT);
 
-	status = ocmem_read(dm_base + DM_STATUS);
+	status = ocmem_read(dm_base + DM_GEN_STATUS);
 	pr_debug("Transfer status before %x\n", status);
 	atomic_set(&dm_pending, 1);
+	/* The DM and BR tables must be programmed before triggering the
+	 * Data Mover else the coherent transfer would be corrupted
+	 */
+	mb();
 	/* Trigger DM */
 	ocmem_write(dm_ctrl, dm_base + DM_CTRL);
 	pr_debug("ocmem: rdm: dm_ctrl %x br_ctrl %x\n", dm_ctrl, br_ctrl);
@@ -236,8 +292,10 @@
 	}
 
 	init_waitqueue_head(&dm_wq);
+	/* Clear DM Mask */
+	ocmem_write(DM_MASK_RESET, dm_base + DM_INTR_MASK);
 	/* enable dm interrupts */
-	ocmem_write(DM_INTR_ENABLE, dm_base + DM_INTR_MASK);
+	ocmem_write(DM_INTR_RESET, dm_base + DM_INTR_CLR);
 	ocmem_disable_core_clock();
 	return 0;
 }
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index c95728e..e8854d5 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -202,6 +202,15 @@
 	return 0;
 }
 
+inline int get_mode(int id)
+{
+	if (!check_id(id))
+		return MODE_NOT_SET;
+	else
+		return ocmem_client_table[id].mode == OCMEM_PERFORMANCE ?
+							WIDE_MODE : THIN_MODE;
+}
+
 /* Returns the address that can be used by a device core to access OCMEM */
 static unsigned long device_address(int id, unsigned long addr)
 {
@@ -577,11 +586,38 @@
 	rc = ocmem_enable_iface_clock();
 
 	if (rc < 0)
+		goto iface_clock_fail;
+
+	rc = ocmem_enable_br_clock();
+
+	if (rc < 0)
+		goto br_clock_fail;
+
+	rc = do_map(req);
+
+	if (rc < 0) {
+		pr_err("ocmem: Failed to map request %p for %d\n",
+							req, req->owner);
 		goto process_map_fail;
 
-	return do_map(req);
+	}
 
+	if (ocmem_lock(req->owner, phys_to_offset(req->req_start), req->req_sz,
+							get_mode(req->owner))) {
+		pr_err("ocmem: Failed to secure request %p for %d\n", req,
+				req->owner);
+		rc = -EINVAL;
+		goto lock_failed;
+	}
+
+	return 0;
+lock_failed:
+	do_unmap(req);
 process_map_fail:
+	ocmem_disable_br_clock();
+br_clock_fail:
+	ocmem_disable_iface_clock();
+iface_clock_fail:
 	ocmem_disable_core_clock();
 core_clock_fail:
 	pr_err("ocmem: Failed to map ocmem request\n");
@@ -593,16 +629,25 @@
 {
 	int rc = 0;
 
+	if (ocmem_unlock(req->owner, phys_to_offset(req->req_start),
+							req->req_sz)) {
+		pr_err("ocmem: Failed to un-secure request %p for %d\n", req,
+				req->owner);
+		rc = -EINVAL;
+		goto unlock_failed;
+	}
+
 	rc = do_unmap(req);
 
 	if (rc < 0)
 		goto process_unmap_fail;
 
+	ocmem_disable_br_clock();
 	ocmem_disable_iface_clock();
 	ocmem_disable_core_clock();
-
 	return 0;
 
+unlock_failed:
 process_unmap_fail:
 	pr_err("ocmem: Failed to unmap ocmem request\n");
 	return rc;
@@ -1306,7 +1351,6 @@
 			return -EINVAL;
 	}
 
-
 	if (req->req_sz != 0) {
 
 		offset = phys_to_offset(req->req_start);
@@ -1321,7 +1365,6 @@
 	}
 
 	rc = do_free(req);
-
 	if (rc < 0)
 		return -EINVAL;
 
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 1720729..1fdd342 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -84,18 +84,9 @@
 	ret = clk_prepare_enable(drv->ahb_clk);
 	if (ret)
 		goto err_ahb_clk;
-	ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
-	if (ret)
-		goto err_reset;
-	ret = clk_prepare_enable(drv->core_clk);
-	if (ret)
-		goto err_core_clk;
 	ret = clk_prepare_enable(drv->axi_clk);
 	if (ret)
 		goto err_axi_clk;
-	ret = clk_prepare_enable(drv->reg_clk);
-	if (ret)
-		goto err_reg_clk;
 	ret = clk_prepare_enable(drv->rom_clk);
 	if (ret)
 		goto err_rom_clk;
@@ -109,14 +100,8 @@
 	return 0;
 
 err_rom_clk:
-	clk_disable_unprepare(drv->reg_clk);
-err_reg_clk:
 	clk_disable_unprepare(drv->axi_clk);
 err_axi_clk:
-	clk_disable_unprepare(drv->core_clk);
-err_core_clk:
-	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
-err_reset:
 	clk_disable_unprepare(drv->ahb_clk);
 err_ahb_clk:
 	return ret;
@@ -125,10 +110,7 @@
 static void pil_mss_disable_clks(struct q6v5_data *drv)
 {
 	clk_disable_unprepare(drv->rom_clk);
-	clk_disable_unprepare(drv->reg_clk);
 	clk_disable_unprepare(drv->axi_clk);
-	clk_disable_unprepare(drv->core_clk);
-	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
 	clk_disable_unprepare(drv->ahb_clk);
 }
 
@@ -321,18 +303,10 @@
 	if (IS_ERR(drv->ahb_clk))
 		return PTR_ERR(drv->ahb_clk);
 
-	drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
-	if (IS_ERR(drv->core_clk))
-		return PTR_ERR(drv->core_clk);
-
 	drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
 	if (IS_ERR(drv->axi_clk))
 		return PTR_ERR(drv->axi_clk);
 
-	drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
-	if (IS_ERR(drv->reg_clk))
-		return PTR_ERR(drv->reg_clk);
-
 	drv->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
 	if (IS_ERR(drv->rom_clk))
 		return PTR_ERR(drv->rom_clk);
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 3040a31..ba0e242 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -21,6 +21,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/clk.h>
 
+#include <asm/mach-types.h>
 #include <mach/msm_iomap.h>
 
 #include "peripheral-loader.h"
@@ -358,12 +359,18 @@
 
 static int __init pil_riva_init(void)
 {
+	if (machine_is_mpq8064_hrd()) {
+		pr_err("pil_riva not supported on this target\n");
+		return 0;
+	}
 	return platform_driver_register(&pil_riva_driver);
 }
 module_init(pil_riva_init);
 
 static void __exit pil_riva_exit(void)
 {
+	if (machine_is_mpq8064_hrd())
+		return;
 	platform_driver_unregister(&pil_riva_driver);
 }
 module_exit(pil_riva_exit);
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index 49c39ec..1ccde72 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -328,6 +328,59 @@
 	.proxy_unvote = pil_venus_remove_proxy_vote,
 };
 
+static int pil_venus_init_image_trusted(struct pil_desc *pil,
+		const u8 *metadata, size_t size)
+{
+	return pas_init_image(PAS_VIDC, metadata, size);
+}
+
+static int pil_venus_reset_trusted(struct pil_desc *pil)
+{
+	int rc;
+	struct venus_data *drv = dev_get_drvdata(pil->dev);
+
+	/*
+	 * GDSC needs to remain on till Venus is shutdown. So, enable
+	 * the GDSC here again to make sure it remains on beyond the
+	 * expiry of the proxy vote timer.
+	 */
+	rc = regulator_enable(drv->gdsc);
+	if (rc) {
+		dev_err(pil->dev, "GDSC enable failed\n");
+		return rc;
+	}
+
+	rc = pas_auth_and_reset(PAS_VIDC);
+	if (rc)
+		regulator_disable(drv->gdsc);
+
+	return rc;
+}
+
+static int pil_venus_shutdown_trusted(struct pil_desc *pil)
+{
+	int rc;
+	struct venus_data *drv = dev_get_drvdata(pil->dev);
+
+	venus_clock_prepare_enable(pil->dev);
+
+	rc = pas_shutdown(PAS_VIDC);
+
+	venus_clock_disable_unprepare(pil->dev);
+
+	regulator_disable(drv->gdsc);
+
+	return rc;
+}
+
+static struct pil_reset_ops pil_venus_ops_trusted = {
+	.init_image = pil_venus_init_image_trusted,
+	.auth_and_reset = pil_venus_reset_trusted,
+	.shutdown = pil_venus_shutdown_trusted,
+	.proxy_vote = pil_venus_make_proxy_vote,
+	.proxy_unvote = pil_venus_remove_proxy_vote,
+};
+
 static int __devinit pil_venus_probe(struct platform_device *pdev)
 {
 	struct venus_data *drv;
@@ -422,9 +475,13 @@
 	desc->owner = THIS_MODULE;
 	desc->proxy_timeout = VENUS_PROXY_TIMEOUT;
 
-	/* TODO: need to add secure boot when the support is available */
-	desc->ops = &pil_venus_ops;
-	dev_info(&pdev->dev, "using non-secure boot\n");
+	if (pas_supported(PAS_VIDC) > 0) {
+		desc->ops = &pil_venus_ops_trusted;
+		dev_info(&pdev->dev, "using secure boot\n");
+	} else {
+		desc->ops = &pil_venus_ops;
+		dev_info(&pdev->dev, "using non-secure boot\n");
+	}
 
 	drv->pil = msm_pil_register(desc);
 	if (IS_ERR(drv->pil))
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index f6b44c6..f6ed1ea 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -84,7 +84,8 @@
 	if (!base_ptr)
 		return -ENODEV;
 
-	if (machine_is_msm8974_sim()) {
+	if (machine_is_msm8974_sim() || machine_is_mpq8092_sim() ||
+	    machine_is_msm8226_sim()) {
 		writel_relaxed(0x800, base_ptr+0x04);
 		writel_relaxed(0x3FFF, base_ptr+0x14);
 	}
@@ -159,7 +160,8 @@
 	if (cpu_is_msm8x60())
 		return scorpion_release_secondary();
 
-	if (machine_is_msm8974_sim())
+	if (machine_is_msm8974_sim() || machine_is_mpq8092_sim() ||
+	    machine_is_msm8226_sim())
 		return krait_release_secondary_sim(0xf9088000, cpu);
 
 	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 40929cc..dbb23d5 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -24,6 +24,7 @@
 #include <linux/smp.h>
 #include <linux/suspend.h>
 #include <linux/tick.h>
+#include <linux/platform_device.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
 #include <mach/system.h>
@@ -71,7 +72,6 @@
 );
 static int msm_pm_retention_tz_call;
 
-
 /******************************************************************************
  * Sleep Modes and Parameters
  *****************************************************************************/
@@ -491,7 +491,6 @@
 #ifdef CONFIG_VFP
 	vfp_pm_suspend();
 #endif
-
 	collapsed = msm_pm_l2x0_power_collapse();
 
 	msm_pm_boot_config_after_pc(cpu);
@@ -685,6 +684,7 @@
 
 		switch (mode) {
 		case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+		case MSM_PM_SLEEP_MODE_RETENTION:
 			if (!allow)
 				break;
 
@@ -699,15 +699,6 @@
 				break;
 			/* fall through */
 
-		case MSM_PM_SLEEP_MODE_RETENTION:
-			if (!allow)
-				break;
-			if (num_online_cpus() > 1) {
-				allow = false;
-				break;
-			}
-			/* fall through */
-
 		case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
 			if (!allow)
 				break;
@@ -958,6 +949,46 @@
 	msm_pm_retention_tz_call = flag;
 }
 
+static int __devinit msm_pc_debug_probe(struct platform_device *pdev)
+{
+	struct resource *res = NULL;
+	int i ;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto fail;
+
+	msm_pc_debug_counters_phys = res->start;
+	WARN_ON(resource_size(res) < SZ_64);
+	msm_pc_debug_counters = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+
+	if (!msm_pc_debug_counters)
+		goto fail;
+
+	for (i = 0; i < resource_size(res)/4; i++)
+		__raw_writel(0, msm_pc_debug_counters + i * 4);
+	return 0;
+fail:
+	msm_pc_debug_counters = 0;
+	msm_pc_debug_counters_phys = 0;
+	return -EFAULT;
+}
+
+static struct of_device_id msm_pc_debug_table[] = {
+	{.compatible = "qcom,pc-cntr"},
+	{},
+};
+
+static struct platform_driver msm_pc_counter_driver = {
+	.probe = msm_pc_debug_probe,
+	.driver = {
+		.name = "pc-cntr",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_pc_debug_table,
+	},
+};
+
 static int __init msm_pm_init(void)
 {
 	pgd_t *pc_pgd;
@@ -973,6 +1004,7 @@
 	unsigned long exit_phys;
 
 	/* Page table for cores to come back up safely. */
+
 	pc_pgd = pgd_alloc(&init_mm);
 	if (!pc_pgd)
 		return -ENOMEM;
@@ -1015,6 +1047,7 @@
 	suspend_set_ops(&msm_pm_ops);
 	msm_pm_qtimer_available();
 	msm_cpuidle_init();
+	platform_driver_register(&msm_pc_counter_driver);
 
 	return 0;
 }
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 552fb16..e2553e2 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -131,5 +131,6 @@
 #endif
 
 void msm_pm_set_cpr_ops(struct msm_pm_cpr_ops *ops);
-
+extern void *msm_pc_debug_counters;
+extern unsigned long msm_pc_debug_counters_phys;
 #endif  /* __ARCH_ARM_MACH_MSM_PM_H */
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index 11f6b28..6189da8 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -720,11 +720,22 @@
 	mutex_lock(&module->lock);
 	switch (event) {
 	case RPC_ADSP_RTOS_MOD_READY:
-		MM_INFO("module %s: READY\n", module->name);
-		module->state = ADSP_STATE_ENABLED;
-		wake_up(&module->state_wait);
-		adsp_set_image(module->info, image);
-		break;
+		if (module->state == ADSP_STATE_ENABLING) {
+			MM_INFO("module %s: READY\n", module->name);
+			module->state = ADSP_STATE_ENABLED;
+			wake_up(&module->state_wait);
+			adsp_set_image(module->info, image);
+			break;
+		} else {
+			MM_ERR("module %s got READY event in state[%d]\n",
+								module->name,
+								module->state);
+			rpc_send_accepted_void_reply(rpc_cb_server_client,
+						req->xid,
+						RPC_ACCEPTSTAT_GARBAGE_ARGS);
+			mutex_unlock(&module->lock);
+			return;
+		}
 	case RPC_ADSP_RTOS_MOD_DISABLE:
 		MM_INFO("module %s: DISABLED\n", module->name);
 		module->state = ADSP_STATE_DISABLED;
diff --git a/arch/arm/mach-msm/qdsp5/adsp.h b/arch/arm/mach-msm/qdsp5/adsp.h
index 06e2f22..50f5b83 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.h
+++ b/arch/arm/mach-msm/qdsp5/adsp.h
@@ -20,7 +20,7 @@
 
 #include <linux/types.h>
 #include <linux/msm_adsp.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/msm_rpcrouter.h>
 #include <mach/msm_adsp.h>
 
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac.c b/arch/arm/mach-msm/qdsp5/audio_aac.c
index 01e529f..ac7cca3 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac.c
@@ -34,7 +34,7 @@
 #include <linux/slab.h>
 #include <linux/msm_audio_aac.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac_in.c b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
index 4a35939..2e64a09 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
@@ -33,7 +33,7 @@
 #include <linux/delay.h>
 #include <linux/msm_audio_aac.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include "audmgr.h"
 
diff --git a/arch/arm/mach-msm/qdsp5/audio_ac3.c b/arch/arm/mach-msm/qdsp5/audio_ac3.c
index c0e2059..63904fb 100644
--- a/arch/arm/mach-msm/qdsp5/audio_ac3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_ac3.c
@@ -37,7 +37,7 @@
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio_ac3.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 7e6c9ce..8aa102a 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -42,7 +42,7 @@
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
index 05ad373..4effc8e 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
@@ -37,7 +37,7 @@
 #include <linux/delay.h>
 #include <linux/msm_audio_amrnb.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include "audmgr.h"
 
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrwb.c b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
index f18aca7..83320f3 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
@@ -41,7 +41,7 @@
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc.c b/arch/arm/mach-msm/qdsp5/audio_evrc.c
index 7aeadac..c0486db 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc.c
@@ -36,7 +36,7 @@
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
index 3310743..9bf0e83 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
@@ -33,7 +33,7 @@
 
 
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <asm/atomic.h>
 #include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index 6cbb981a3..a067b83 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -37,7 +37,7 @@
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/earlysuspend.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_mp3.c b/arch/arm/mach-msm/qdsp5/audio_mp3.c
index 167de9c..cef3d99 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mp3.c
@@ -34,7 +34,7 @@
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
@@ -2298,7 +2298,10 @@
 		if (rc) {
 			MM_ERR("audmgr open failed, freeing instance \
 					0x%08x\n", (int)audio);
-			goto err;
+			if (!(file->f_flags & O_NONBLOCK))
+				goto err;
+			else
+				goto resource_err;
 		}
 	}
 
@@ -2310,7 +2313,10 @@
 				audio->module_name, (int)audio);
 		if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
 			audmgr_close(&audio->audmgr);
-		goto err;
+		if (!(file->f_flags & O_NONBLOCK))
+			goto err;
+		else
+			goto resource_err;
 	}
 
 	rc = rmt_get_resource(audio);
@@ -2320,7 +2326,10 @@
 		if (audio->pcm_feedback == TUNNEL_MODE_PLAYBACK)
 			audmgr_close(&audio->audmgr);
 		msm_adsp_put(audio->audplay);
-		goto err;
+		if (!(file->f_flags & O_NONBLOCK))
+			goto err;
+		else
+			goto resource_err;
 	}
 
 	if (file->f_flags & O_NONBLOCK) {
@@ -2410,6 +2419,7 @@
 output_buff_alloc_error:
 	ion_client_destroy(client);
 client_create_error:
+resource_err:
 	audpp_adec_free(audio->dec_id);
 	kfree(audio);
 	return rc;
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm.c b/arch/arm/mach-msm/qdsp5/audio_pcm.c
index 3a92e0c..340bcc6 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm.c
@@ -38,7 +38,7 @@
 #include <linux/delay.h>
 #include <linux/earlysuspend.h>
 #include <linux/list.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 4dcbc7b..2da1f19 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -26,7 +26,7 @@
 #include <linux/kthread.h>
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <linux/delay.h>
 
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp.c b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
index e1a6299..1a0c333 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
@@ -37,7 +37,7 @@
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
index 57ae772..ee079bc 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
@@ -33,7 +33,7 @@
 
 
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <asm/atomic.h>
 #include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_wma.c b/arch/arm/mach-msm/qdsp5/audio_wma.c
index 276c9d4..0a77b58 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wma.c
@@ -41,7 +41,7 @@
 #include <linux/msm_audio.h>
 #include <linux/msm_audio_wma.h>
 #include <linux/memory_alloc.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_wmapro.c b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
index b881c59..82fc3f9 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
@@ -40,7 +40,7 @@
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio_wmapro.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/qdsp5/qdsp5audppcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
index 790c510..2f03cd0 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
@@ -27,7 +27,7 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/msm_audio_amrnb.h>
-#include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
 #include <linux/memory_alloc.h>
 
 #include <mach/iommu.h>
@@ -105,6 +105,8 @@
 	int running;
 	int stopped; /* set when stopped, cleared on flush */
 	char *build_id;
+	struct ion_client *client;
+	struct ion_handle *buff_handle;
 };
 
 struct audio_frame {
@@ -766,8 +768,9 @@
 	audio->audrec = NULL;
 	audio->opened = 0;
 	if (audio->data) {
-		iounmap(audio->map_v_read);
-		free_contiguous_memory_by_paddr(audio->phys);
+		ion_unmap_kernel(audio->client, audio->buff_handle);
+		ion_free(audio->client, audio->buff_handle);
+		ion_client_destroy(audio->client);
 		audio->data = NULL;
 	}
 	mutex_unlock(&audio->lock);
@@ -779,27 +782,62 @@
 	struct audio_in *audio = &the_audio_amrnb_in;
 	int rc;
 	int encid;
+	int len = 0;
+	unsigned long ionflag = 0;
+	ion_phys_addr_t addr = 0;
+	struct ion_handle *handle = NULL;
+	struct ion_client *client = NULL;
 
 	mutex_lock(&audio->lock);
 	if (audio->opened) {
 		rc = -EBUSY;
 		goto done;
 	}
-	audio->phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K);
-	if (audio->phys) {
-		audio->map_v_read = ioremap(audio->phys, DMASZ);
-		if (IS_ERR(audio->map_v_read)) {
-			MM_ERR("could not map DMA buffers\n");
-			rc = -ENOMEM;
-			free_contiguous_memory_by_paddr(audio->phys);
-			goto done;
-		}
-		audio->data = audio->map_v_read;
-	} else {
-		MM_ERR("could not allocate DMA buffers\n");
+
+	client = msm_ion_client_create(UINT_MAX, "Audio_AMR_In_Client");
+	if (IS_ERR_OR_NULL(client)) {
+		MM_ERR("Unable to create ION client\n");
 		rc = -ENOMEM;
-		goto done;
+		goto client_create_error;
 	}
+	audio->client = client;
+
+	handle = ion_alloc(client, DMASZ, SZ_4K,
+		ION_HEAP(ION_AUDIO_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		MM_ERR("Unable to create allocate O/P buffers\n");
+		rc = -ENOMEM;
+		goto buff_alloc_error;
+	}
+	audio->buff_handle = handle;
+
+	rc = ion_phys(client, handle, &addr, &len);
+	if (rc) {
+		MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+		goto buff_get_phys_error;
+	} else {
+		MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+	}
+	audio->phys = (int32_t)addr;
+
+	rc = ion_handle_get_flags(client, handle, &ionflag);
+	if (rc) {
+		MM_ERR("could not get flags for the handle\n");
+		goto buff_get_flags_error;
+	}
+
+	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	if (IS_ERR(audio->map_v_read)) {
+		MM_ERR("could not map write buffers\n");
+		rc = -ENOMEM;
+		goto buff_map_error;
+	}
+	audio->data = audio->map_v_read;
+	MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
+		audio->phys, (int)audio->data);
+
 	MM_DBG("Memory addr = 0x%8x  phy addr = 0x%8x\n",\
 		(int) audio->data, (int) audio->phys);
 	if ((file->f_mode & FMODE_WRITE) &&
@@ -871,6 +909,14 @@
 	msm_adsp_put(audio->audrec);
 	audpreproc_aenc_free(audio->enc_id);
 	mutex_unlock(&audio->lock);
+	ion_unmap_kernel(client, audio->buff_handle);
+buff_map_error:
+buff_get_phys_error:
+buff_get_flags_error:
+	ion_free(client, audio->buff_handle);
+buff_alloc_error:
+	ion_client_destroy(client);
+client_create_error:
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c b/arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c
index 1ee5029..1180e8d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c
@@ -27,7 +27,7 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/msm_audio_qcp.h>
-#include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
 #include <linux/memory_alloc.h>
 
 #include <mach/msm_adsp.h>
@@ -137,6 +137,9 @@
 	int running;
 	int stopped; /* set when stopped, cleared on flush */
 	char *build_id;
+	struct ion_client *client;
+	struct ion_handle *input_buff_handle;
+	struct ion_handle *output_buff_handle;
 };
 
 struct audio_frame {
@@ -1318,15 +1321,16 @@
 	audio->audrec = NULL;
 	audio->opened = 0;
 	if (audio->data) {
-		iounmap(audio->map_v_read);
-		free_contiguous_memory_by_paddr(audio->phys);
+		ion_unmap_kernel(audio->client, audio->input_buff_handle);
+		ion_free(audio->client, audio->input_buff_handle);
 		audio->data = NULL;
 	}
 	if (audio->out_data) {
-		iounmap(audio->map_v_write);
-		free_contiguous_memory_by_paddr(audio->out_phys);
+		ion_unmap_kernel(audio->client, audio->output_buff_handle);
+		ion_free(audio->client, audio->output_buff_handle);
 		audio->out_data = NULL;
 	}
+	ion_client_destroy(audio->client);
 	mutex_unlock(&audio->lock);
 	return 0;
 }
@@ -1337,27 +1341,65 @@
 	struct audio_in *audio = &the_audio_evrc_in;
 	int rc;
 	int encid;
+	int len = 0;
+	unsigned long ionflag = 0;
+	ion_phys_addr_t addr = 0;
+	struct ion_handle *handle = NULL;
+	struct ion_client *client = NULL;
 
 	mutex_lock(&audio->lock);
 	if (audio->opened) {
 		rc = -EBUSY;
 		goto done;
 	}
-	audio->phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K);
-	if (audio->phys) {
-		audio->map_v_read = ioremap(audio->phys, DMASZ);
-		if (IS_ERR(audio->map_v_read)) {
-			MM_ERR("failed to map read physical address\n");
-			rc = -ENOMEM;
-			free_contiguous_memory_by_paddr(audio->phys);
-			goto done;
-		}
-		audio->data = audio->map_v_read;
-	} else {
-		MM_ERR("could not allocate DMA buffers\n");
+
+	client = msm_ion_client_create(UINT_MAX, "Audio_EVRC_in_client");
+	if (IS_ERR_OR_NULL(client)) {
+		MM_ERR("Unable to create ION client\n");
 		rc = -ENOMEM;
-		goto done;
+		goto client_create_error;
 	}
+	audio->client = client;
+
+	MM_DBG("allocating mem sz = %d\n", DMASZ);
+	handle = ion_alloc(client, DMASZ, SZ_4K,
+		ION_HEAP(ION_AUDIO_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		MM_ERR("Unable to create allocate O/P buffers\n");
+		rc = -ENOMEM;
+		goto output_buff_alloc_error;
+	}
+
+	audio->output_buff_handle = handle;
+
+	rc = ion_phys(client , handle, &addr, &len);
+	if (rc) {
+		MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+		rc = -ENOMEM;
+		goto output_buff_get_phys_error;
+	} else {
+		MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+	}
+	audio->phys = (int32_t)addr;
+
+	rc = ion_handle_get_flags(client, handle, &ionflag);
+	if (rc) {
+		MM_ERR("could not get flags for the handle\n");
+		rc = -ENOMEM;
+		goto output_buff_get_flags_error;
+	}
+
+	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	if (IS_ERR(audio->map_v_read)) {
+		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
+				(int)audio);
+		rc = -ENOMEM;
+		goto output_buff_map_error;
+	}
+	audio->data = audio->map_v_read;
+
 	MM_DBG("Memory addr = 0x%8x  phy addr = 0x%8x\n",\
 		(int) audio->data, (int) audio->phys);
 	if ((file->f_mode & FMODE_WRITE) &&
@@ -1414,25 +1456,50 @@
 	audevrc_in_flush(audio);
 	audevrc_out_flush(audio);
 
-	audio->out_phys = allocate_contiguous_ebi_nomap(BUFFER_SIZE,
-								SZ_4K);
-	if (!audio->out_phys) {
-		MM_ERR("could not allocate write buffers\n");
+	MM_DBG("allocating BUFFER_SIZE  %d\n", BUFFER_SIZE);
+	handle = ion_alloc(client, BUFFER_SIZE,
+			SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		MM_ERR("Unable to create allocate I/P buffers\n");
 		rc = -ENOMEM;
-		goto evt_error;
-	} else {
-		audio->map_v_write = ioremap(audio->out_phys, BUFFER_SIZE);
-		if (IS_ERR(audio->map_v_write)) {
-			MM_ERR("could map write buffers\n");
-			rc = -ENOMEM;
-			free_contiguous_memory_by_paddr(audio->out_phys);
-			goto evt_error;
-		}
-		audio->out_data = audio->map_v_write;
-		MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
-				audio->out_phys, (int)audio->out_data);
+		goto input_buff_alloc_error;
 	}
 
+	audio->input_buff_handle = handle;
+
+	rc = ion_phys(client , handle, &addr, &len);
+	if (rc) {
+		MM_ERR("I/P buffers:Invalid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+		rc = -ENOMEM;
+		goto input_buff_alloc_error;
+	} else {
+		MM_INFO("Got valid phy: %x sz: %x\n",
+			(unsigned int) addr,
+			(unsigned int) len);
+	}
+	audio->out_phys = (int32_t)addr;
+
+	rc = ion_handle_get_flags(client,
+		handle, &ionflag);
+	if (rc) {
+		MM_ERR("could not get flags for the handle\n");
+		rc = -ENOMEM;
+		goto input_buff_alloc_error;
+	}
+
+	audio->map_v_write = ion_map_kernel(client,
+		handle, ionflag);
+	if (IS_ERR(audio->map_v_write)) {
+		MM_ERR("could not map write buffers\n");
+		rc = -ENOMEM;
+		goto input_buff_map_error;
+	}
+	audio->out_data = audio->map_v_write;
+	MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
+				(unsigned int)addr,
+				(unsigned int)audio->out_data);
+
 		/* Initialize buffer */
 	audio->out[0].data = audio->out_data + 0;
 	audio->out[0].addr = audio->out_phys + 0;
@@ -1472,6 +1539,17 @@
 	msm_adsp_put(audio->audrec);
 	audpreproc_aenc_free(audio->enc_id);
 	mutex_unlock(&audio->lock);
+input_buff_map_error:
+	ion_free(client, audio->input_buff_handle);
+input_buff_alloc_error:
+	ion_unmap_kernel(client, audio->output_buff_handle);
+output_buff_map_error:
+output_buff_get_phys_error:
+output_buff_get_flags_error:
+	ion_free(client, audio->output_buff_handle);
+output_buff_alloc_error:
+	ion_client_destroy(client);
+client_create_error:
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
index e1af2ad..7fac2ea 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
@@ -27,7 +27,7 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/msm_audio_qcp.h>
-#include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
 #include <linux/memory_alloc.h>
 
 #include <mach/msm_adsp.h>
@@ -140,6 +140,9 @@
 	int running;
 	int stopped; /* set when stopped, cleared on flush */
 	char *build_id;
+	struct ion_client *client;
+	struct ion_handle *input_buff_handle;
+	struct ion_handle *output_buff_handle;
 };
 
 struct audio_frame {
@@ -1324,15 +1327,16 @@
 	audio->audrec = NULL;
 	audio->opened = 0;
 	if (audio->data) {
-		iounmap(audio->map_v_read);
-		free_contiguous_memory_by_paddr(audio->phys);
+		ion_unmap_kernel(audio->client, audio->input_buff_handle);
+		ion_free(audio->client, audio->input_buff_handle);
 		audio->data = NULL;
 	}
 	if (audio->out_data) {
-		iounmap(audio->map_v_write);
-		free_contiguous_memory_by_paddr(audio->out_phys);
+		ion_unmap_kernel(audio->client, audio->output_buff_handle);
+		ion_free(audio->client, audio->output_buff_handle);
 		audio->out_data = NULL;
 	}
+	ion_client_destroy(audio->client);
 	mutex_unlock(&audio->lock);
 	return 0;
 }
@@ -1343,27 +1347,64 @@
 	struct audio_in *audio = &the_audio_qcelp_in;
 	int rc;
 	int encid;
+	int len = 0;
+	unsigned long ionflag = 0;
+	ion_phys_addr_t addr = 0;
+	struct ion_handle *handle = NULL;
+	struct ion_client *client = NULL;
 
 	mutex_lock(&audio->lock);
 	if (audio->opened) {
 		rc = -EBUSY;
 		goto done;
 	}
-	audio->phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K);
-	if (audio->phys) {
-		audio->map_v_read = ioremap(audio->phys, DMASZ);
-		if (IS_ERR(audio->map_v_read)) {
-			MM_ERR("could not map DMA buffers\n");
-			rc = -ENOMEM;
-			free_contiguous_memory_by_paddr(audio->phys);
-			goto done;
-		}
-		audio->data = audio->map_v_read;
-	} else {
-		MM_ERR("could not allocate DMA buffers\n");
+	client = msm_ion_client_create(UINT_MAX, "Audio_EVRC_in_client");
+	if (IS_ERR_OR_NULL(client)) {
+		MM_ERR("Unable to create ION client\n");
 		rc = -ENOMEM;
-		goto done;
+		goto client_create_error;
 	}
+	audio->client = client;
+
+	MM_DBG("allocating mem sz = %d\n", DMASZ);
+	handle = ion_alloc(client, DMASZ, SZ_4K,
+		ION_HEAP(ION_AUDIO_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		MM_ERR("Unable to create allocate O/P buffers\n");
+		rc = -ENOMEM;
+		goto output_buff_alloc_error;
+	}
+
+	audio->output_buff_handle = handle;
+
+	rc = ion_phys(client , handle, &addr, &len);
+	if (rc) {
+		MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+		rc = -ENOMEM;
+		goto output_buff_get_phys_error;
+	} else {
+		MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+	}
+	audio->phys = (int32_t)addr;
+
+	rc = ion_handle_get_flags(client, handle, &ionflag);
+	if (rc) {
+		MM_ERR("could not get flags for the handle\n");
+		rc = -ENOMEM;
+		goto output_buff_get_flags_error;
+	}
+
+	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	if (IS_ERR(audio->map_v_read)) {
+		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
+				(int)audio);
+		rc = -ENOMEM;
+		goto output_buff_map_error;
+	}
+	audio->data = audio->map_v_read;
+
 	MM_DBG("Memory addr = 0x%8x  phy addr = 0x%8x\n",\
 		(int) audio->data, (int) audio->phys);
 	if ((file->f_mode & FMODE_WRITE) &&
@@ -1422,24 +1463,50 @@
 	audqcelp_in_flush(audio);
 	audqcelp_out_flush(audio);
 
-	audio->out_phys = allocate_contiguous_ebi_nomap(BUFFER_SIZE, SZ_4K);
-	if (!audio->out_phys) {
-		MM_ERR("could not allocate write buffers\n");
+	MM_DBG("allocating BUFFER_SIZE  %d\n", BUFFER_SIZE);
+	handle = ion_alloc(client, BUFFER_SIZE,
+			SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		MM_ERR("Unable to create allocate I/P buffers\n");
 		rc = -ENOMEM;
-		goto evt_error;
-	} else {
-		audio->map_v_write = ioremap(audio->out_phys, BUFFER_SIZE);
-		if (IS_ERR(audio->map_v_write)) {
-			MM_ERR("could not map write buffers\n");
-			rc = -ENOMEM;
-			free_contiguous_memory_by_paddr(audio->out_phys);
-			goto evt_error;
-		}
-		audio->out_data = audio->map_v_write;
-		MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
-				audio->out_phys, (int)audio->out_data);
+		goto input_buff_alloc_error;
 	}
 
+	audio->input_buff_handle = handle;
+
+	rc = ion_phys(client , handle, &addr, &len);
+	if (rc) {
+		MM_ERR("I/P buffers:Invalid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+		rc = -ENOMEM;
+		goto input_buff_alloc_error;
+	} else {
+		MM_INFO("Got valid phy: %x sz: %x\n",
+			(unsigned int) addr,
+			(unsigned int) len);
+	}
+	audio->out_phys = (int32_t)addr;
+
+	rc = ion_handle_get_flags(client,
+		handle, &ionflag);
+	if (rc) {
+		MM_ERR("could not get flags for the handle\n");
+		rc = -ENOMEM;
+		goto input_buff_alloc_error;
+	}
+
+	audio->map_v_write = ion_map_kernel(client,
+		handle, ionflag);
+	if (IS_ERR(audio->map_v_write)) {
+		MM_ERR("could not map write buffers\n");
+		rc = -ENOMEM;
+		goto input_buff_map_error;
+	}
+	audio->out_data = audio->map_v_write;
+	MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
+				(unsigned int)addr,
+				(unsigned int)audio->out_data);
+
 		/* Initialize buffer */
 	audio->out[0].data = audio->out_data + 0;
 	audio->out[0].addr = audio->out_phys + 0;
@@ -1478,6 +1545,17 @@
 	msm_adsp_put(audio->audrec);
 	audpreproc_aenc_free(audio->enc_id);
 	mutex_unlock(&audio->lock);
+input_buff_map_error:
+	ion_free(client, audio->input_buff_handle);
+input_buff_alloc_error:
+	ion_unmap_kernel(client, audio->output_buff_handle);
+output_buff_map_error:
+output_buff_get_phys_error:
+output_buff_get_flags_error:
+	ion_free(client, audio->output_buff_handle);
+output_buff_alloc_error:
+	ion_client_destroy(client);
+client_create_error:
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wma.c b/arch/arm/mach-msm/qdsp5v2/audio_wma.c
index 80adebd..4ba5821 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wma.c
@@ -35,12 +35,11 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/msm_audio_wma.h>
 #include <linux/memory_alloc.h>
-#include <mach/qdsp5v2/audio_dev_ctl.h>
+#include <linux/msm_ion.h>
 
 #include <mach/msm_adsp.h>
 #include <mach/iommu.h>
@@ -190,6 +189,9 @@
 	int eq_needs_commit;
 	struct audpp_cmd_cfg_object_params_eqalizer eq;
 	struct audpp_cmd_cfg_object_params_volume vol_pan;
+	struct ion_client *client;
+	struct ion_handle *input_buff_handle;
+	struct ion_handle *output_buff_handle;
 };
 
 static int auddec_dsp_config(struct audio *audio, int enable);
@@ -814,6 +816,10 @@
 	uint16_t enable_mask;
 	int enable;
 	int prev_state;
+	unsigned long ionflag = 0;
+	ion_phys_addr_t addr = 0;
+	struct ion_handle *handle = NULL;
+	int len = 0;
 
 	MM_DBG("cmd = %d\n", cmd);
 
@@ -1052,24 +1058,54 @@
 				MM_DBG("allocate PCM buffer %d\n",
 						config.buffer_count *
 						config.buffer_size);
-				audio->read_phys =
-						allocate_contiguous_ebi_nomap(
-							config.buffer_size *
-							config.buffer_count,
-							SZ_4K);
-				if (!audio->read_phys) {
+				handle = ion_alloc(audio->client,
+					(config.buffer_size *
+					config.buffer_count),
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+				if (IS_ERR_OR_NULL(handle)) {
+					MM_ERR("Unable to alloc I/P buffs\n");
+					audio->input_buff_handle = NULL;
 					rc = -ENOMEM;
 					break;
 				}
-				audio->map_v_read = ioremap(
-							audio->read_phys,
-							config.buffer_size *
-							config.buffer_count);
-				if (IS_ERR(audio->map_v_read)) {
-					MM_ERR("read buf alloc fail\n");
+
+				audio->input_buff_handle = handle;
+
+				rc = ion_phys(audio->client ,
+					handle, &addr, &len);
+				if (rc) {
+					MM_ERR("Invalid phy: %x sz: %x\n",
+						(unsigned int) addr,
+						(unsigned int) len);
+					ion_free(audio->client, handle);
+					audio->input_buff_handle = NULL;
 					rc = -ENOMEM;
-					free_contiguous_memory_by_paddr(
-							audio->read_phys);
+					break;
+				} else {
+					MM_INFO("Got valid phy: %x sz: %x\n",
+						(unsigned int) audio->read_phys,
+						(unsigned int) len);
+				}
+				audio->read_phys = (int32_t)addr;
+
+				rc = ion_handle_get_flags(audio->client,
+					handle, &ionflag);
+				if (rc) {
+					MM_ERR("could not get flags\n");
+					ion_free(audio->client, handle);
+					audio->input_buff_handle = NULL;
+					rc = -ENOMEM;
+					break;
+				}
+
+				audio->map_v_read = ion_map_kernel(
+					audio->client,
+					handle, ionflag);
+				if (IS_ERR(audio->map_v_read)) {
+					MM_ERR("map of read buf failed\n");
+					ion_free(audio->client, handle);
+					audio->input_buff_handle = NULL;
+					rc = -ENOMEM;
 				} else {
 					uint8_t index;
 					uint32_t offset = 0;
@@ -1455,12 +1491,13 @@
 	audio->event_abort = 1;
 	wake_up(&audio->event_wait);
 	audwma_reset_event_queue(audio);
-	iounmap(audio->map_v_write);
-	free_contiguous_memory_by_paddr(audio->phys);
-	if (audio->read_data) {
-		iounmap(audio->map_v_read);
-		free_contiguous_memory_by_paddr(audio->read_phys);
+	ion_unmap_kernel(audio->client, audio->output_buff_handle);
+	ion_free(audio->client, audio->output_buff_handle);
+	if (audio->input_buff_handle != NULL) {
+		ion_unmap_kernel(audio->client, audio->input_buff_handle);
+		ion_free(audio->client, audio->input_buff_handle);
 	}
+	ion_client_destroy(audio->client);
 	mutex_unlock(&audio->lock);
 #ifdef CONFIG_DEBUG_FS
 	if (audio->dentry)
@@ -1601,8 +1638,13 @@
 {
 	struct audio *audio = NULL;
 	int rc, dec_attrb, decid, i;
-	unsigned pmem_sz = DMASZ_MAX;
+	unsigned mem_sz = DMASZ_MAX;
 	struct audwma_event *e_node = NULL;
+	unsigned long ionflag = 0;
+	ion_phys_addr_t addr = 0;
+	struct ion_handle *handle = NULL;
+	struct ion_client *client = NULL;
+	int len = 0;
 #ifdef CONFIG_DEBUG_FS
 	/* 4 bytes represents decoder number, 1 byte for terminate string */
 	char name[sizeof "msm_wma_" + 5];
@@ -1645,36 +1687,52 @@
 	}
 	audio->dec_id = decid & MSM_AUD_DECODER_MASK;
 
-	while (pmem_sz >= DMASZ_MIN) {
-		MM_DBG("pmemsz = %d\n", pmem_sz);
-		audio->phys = allocate_contiguous_ebi_nomap(pmem_sz, SZ_4K);
-		if (audio->phys) {
-			audio->map_v_write = ioremap(audio->phys, pmem_sz);
-			if (IS_ERR(audio->map_v_write)) {
-				MM_ERR("could not allocate write buffers, \
-						freeing instance 0x%08x\n",
-						(int)audio);
-				rc = -ENOMEM;
-				free_contiguous_memory_by_paddr(audio->phys);
-				audpp_adec_free(audio->dec_id);
-				kfree(audio);
-				goto done;
-			}
-			audio->data = audio->map_v_write;
-			MM_DBG("write buf: phy addr 0x%08x kernel addr \
-				0x%08x\n", audio->phys, (int)audio->data);
-			break;
-		} else if (pmem_sz == DMASZ_MIN) {
-			MM_ERR("could not allocate write buffers, freeing \
-					instance 0x%08x\n", (int)audio);
-			rc = -ENOMEM;
-			audpp_adec_free(audio->dec_id);
-			kfree(audio);
-			goto done;
-		} else
-		pmem_sz >>= 1;
+	client = msm_ion_client_create(UINT_MAX, "Audio_WMA_Client");
+	if (IS_ERR_OR_NULL(client)) {
+		pr_err("Unable to create ION client\n");
+		rc = -ENOMEM;
+		goto client_create_error;
 	}
-	audio->out_dma_sz = pmem_sz;
+	audio->client = client;
+
+	handle = ion_alloc(client, mem_sz, SZ_4K,
+		ION_HEAP(ION_AUDIO_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		MM_ERR("Unable to create allocate O/P buffers\n");
+		rc = -ENOMEM;
+		goto output_buff_alloc_error;
+	}
+	audio->output_buff_handle = handle;
+
+	rc = ion_phys(client, handle, &addr, &len);
+	if (rc) {
+		MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+		goto output_buff_get_phys_error;
+	} else {
+		MM_INFO("O/P buffers:valid phy: %x sz: %x\n",
+			(unsigned int) addr, (unsigned int) len);
+	}
+	audio->phys = (int32_t)addr;
+
+
+	rc = ion_handle_get_flags(client, handle, &ionflag);
+	if (rc) {
+		MM_ERR("could not get flags for the handle\n");
+		goto output_buff_get_flags_error;
+	}
+
+	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	if (IS_ERR(audio->map_v_write)) {
+		MM_ERR("could not map write buffers\n");
+		rc = -ENOMEM;
+		goto output_buff_map_error;
+	}
+			audio->data = audio->map_v_write;
+	MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
+		audio->phys, (int)audio->data);
+
+	audio->out_dma_sz = mem_sz;
 
 	rc = msm_adsp_get(audio->module_name, &audio->audplay,
 			&audplay_adsp_ops_wma, audio);
@@ -1766,8 +1824,14 @@
 event_err:
 	msm_adsp_put(audio->audplay);
 err:
-	iounmap(audio->map_v_write);
-	free_contiguous_memory_by_paddr(audio->phys);
+	ion_unmap_kernel(client, audio->output_buff_handle);
+output_buff_map_error:
+output_buff_get_phys_error:
+output_buff_get_flags_error:
+	ion_free(client, audio->output_buff_handle);
+output_buff_alloc_error:
+	ion_client_destroy(client);
+client_create_error:
 	audpp_adec_free(audio->dec_id);
 	kfree(audio);
 	return rc;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
index 485234f..44ab611 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, 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
@@ -81,7 +81,13 @@
 		aac_cfg.spectral_data_resilience =
 			aac_config->aac_spectral_data_resilience_flag;
 		aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
-		aac_cfg.sample_rate =  audio->pcm_cfg.sample_rate;
+		if (audio->feedback == TUNNEL_MODE) {
+			aac_cfg.sample_rate = aac_config->sample_rate;
+			aac_cfg.ch_cfg = aac_config->channel_configuration;
+		} else {
+			aac_cfg.sample_rate =  audio->pcm_cfg.sample_rate;
+			aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
+		}
 
 		pr_debug("%s:format=%x aot=%d  ch=%d sr=%d\n",
 			__func__, aac_cfg.format,
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index 5c1e7ce..7298fa1 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -15,7 +15,7 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/mm.h>
 #include <mach/qdsp6v2/audio_acdb.h>
 
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
index f89eb18..b5a382e 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
@@ -28,7 +28,7 @@
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/earlysuspend.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <asm/atomic.h>
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index fbd94c5..b53edd9 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, 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
@@ -43,8 +43,13 @@
 		struct msm_audio_aac_config *aac_config;
 		uint32_t sbr_ps = 0x00;
 		aac_config = (struct msm_audio_aac_config *)audio->codec_cfg;
-		aac_cfg.ch_cfg = aac_config->channel_configuration;
-		aac_cfg.sample_rate =  audio->pcm_cfg.sample_rate;
+		if (audio->feedback == TUNNEL_MODE) {
+			aac_cfg.sample_rate = aac_config->sample_rate;
+			aac_cfg.ch_cfg = aac_config->channel_configuration;
+		} else {
+			aac_cfg.sample_rate =  audio->pcm_cfg.sample_rate;
+			aac_cfg.ch_cfg = audio->pcm_cfg.channel_count;
+		}
 		pr_debug("%s: AUDIO_START session_id[%d]\n", __func__,
 						audio->ac->session);
 		if (audio->feedback == NON_TUNNEL_MODE) {
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 1937aafc..a7e34d9 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -21,7 +21,7 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ioctls.h>
 #include <linux/debugfs.h>
 #include "audio_utils_aio.h"
@@ -93,39 +93,6 @@
 		sizeof(meta_data->meta_out_dsp[0]);
 }
 
-void extract_meta_out_info(struct q6audio_aio *audio,
-		struct audio_aio_buffer_node *buf_node, int dir)
-{
-	struct dec_meta_out *meta_data = buf_node->kvaddr;
-	if (dir) { /* input buffer - Write */
-		if (audio->buf_cfg.meta_info_enable)
-			memcpy(&buf_node->meta_info.meta_in,
-			(char *)buf_node->kvaddr, sizeof(struct dec_meta_in));
-		else
-			memset(&buf_node->meta_info.meta_in,
-			0, sizeof(struct dec_meta_in));
-		pr_debug("%s[%p]:i/p: msw_ts 0x%lx lsw_ts 0x%lx nflags 0x%8x\n",
-			__func__, audio,
-			buf_node->meta_info.meta_in.ntimestamp.highpart,
-			buf_node->meta_info.meta_in.ntimestamp.lowpart,
-			buf_node->meta_info.meta_in.nflags);
-	} else { /* output buffer - Read */
-		memcpy((char *)buf_node->kvaddr,
-			&buf_node->meta_info.meta_out,
-			sizeof(struct dec_meta_out));
-		meta_data->meta_out_dsp[0].nflags = 0x00000000;
-		pr_debug("%s[%p]:o/p: msw_ts 0x%8x lsw_ts 0x%8x nflags 0x%8x, num_frames = %d\n",
-		__func__, audio,
-		((struct dec_meta_out *)buf_node->kvaddr)->\
-			meta_out_dsp[0].msw_ts,
-		((struct dec_meta_out *)buf_node->kvaddr)->\
-			meta_out_dsp[0].lsw_ts,
-		((struct dec_meta_out *)buf_node->kvaddr)->\
-			meta_out_dsp[0].nflags,
-		((struct dec_meta_out *)buf_node->kvaddr)->num_of_frames);
-	}
-}
-
 static int audio_aio_ion_lookup_vaddr(struct q6audio_aio *audio, void *addr,
 					unsigned long len,
 					struct audio_aio_ion_region **region)
@@ -198,7 +165,7 @@
 
 static int audio_aio_pause(struct q6audio_aio  *audio)
 {
-	int rc = 0;
+	int rc = -EINVAL;
 
 	pr_debug("%s[%p], enabled = %d\n", __func__, audio,
 			audio->enabled);
@@ -1162,9 +1129,12 @@
 		mutex_lock(&audio->lock);
 		if (arg == 1) {
 			rc = audio_aio_pause(audio);
-			if (rc < 0)
+			if (rc < 0) {
 				pr_err("%s[%p]: pause FAILED rc=%d\n",
 					__func__, audio, rc);
+				mutex_unlock(&audio->lock);
+				break;
+			}
 			audio->drv_status |= ADRV_STATUS_PAUSE;
 		} else if (arg == 0) {
 			if (audio->drv_status & ADRV_STATUS_PAUSE) {
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
index 4401f6f..2b936c5 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
@@ -24,7 +24,7 @@
 #include <linux/debugfs.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <asm/ioctls.h>
 #include <asm/atomic.h>
 #include "q6audio_common.h"
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_v1_aio.c b/arch/arm/mach-msm/qdsp6v2/q6audio_v1_aio.c
index 8304cb8..b46e0d3 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6audio_v1_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_v1_aio.c
@@ -19,7 +19,7 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ioctls.h>
 #include "audio_utils_aio.h"
 
@@ -121,6 +121,39 @@
 	}
 }
 
+void extract_meta_out_info(struct q6audio_aio *audio,
+		struct audio_aio_buffer_node *buf_node, int dir)
+{
+	struct dec_meta_out *meta_data = buf_node->kvaddr;
+	if (dir) { /* input buffer - Write */
+		if (audio->buf_cfg.meta_info_enable)
+			memcpy(&buf_node->meta_info.meta_in,
+			(char *)buf_node->kvaddr, sizeof(struct dec_meta_in));
+		else
+			memset(&buf_node->meta_info.meta_in,
+			0, sizeof(struct dec_meta_in));
+		pr_debug("%s[%p]:i/p: msw_ts 0x%lx lsw_ts 0x%lx nflags 0x%8x\n",
+			__func__, audio,
+			buf_node->meta_info.meta_in.ntimestamp.highpart,
+			buf_node->meta_info.meta_in.ntimestamp.lowpart,
+			buf_node->meta_info.meta_in.nflags);
+	} else { /* output buffer - Read */
+		memcpy((char *)buf_node->kvaddr,
+			&buf_node->meta_info.meta_out,
+			sizeof(struct dec_meta_out));
+		meta_data->meta_out_dsp[0].nflags = 0x00000000;
+		pr_debug("%s[%p]:o/p: msw_ts 0x%8x lsw_ts 0x%8x nflags 0x%8x, num_frames = %d\n",
+		__func__, audio,
+		((struct dec_meta_out *)buf_node->kvaddr)->\
+			meta_out_dsp[0].msw_ts,
+		((struct dec_meta_out *)buf_node->kvaddr)->\
+			meta_out_dsp[0].lsw_ts,
+		((struct dec_meta_out *)buf_node->kvaddr)->\
+			meta_out_dsp[0].nflags,
+		((struct dec_meta_out *)buf_node->kvaddr)->num_of_frames);
+	}
+}
+
 /* Read buffer from DSP / Handle Ack from DSP */
 void audio_aio_async_read_ack(struct q6audio_aio *audio, uint32_t token,
 			uint32_t *payload)
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c b/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
index ad4fc6f..10adc26 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
@@ -19,7 +19,7 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ioctls.h>
 #include "audio_utils_aio.h"
 
@@ -110,6 +110,46 @@
 	}
 }
 
+void extract_meta_out_info(struct q6audio_aio *audio,
+		struct audio_aio_buffer_node *buf_node, int dir)
+{
+	struct dec_meta_out *meta_data = buf_node->kvaddr;
+	uint32_t temp;
+
+	if (dir) { /* input buffer - Write */
+		if (audio->buf_cfg.meta_info_enable)
+			memcpy(&buf_node->meta_info.meta_in,
+			(char *)buf_node->kvaddr, sizeof(struct dec_meta_in));
+		else
+			memset(&buf_node->meta_info.meta_in,
+			0, sizeof(struct dec_meta_in));
+		pr_debug("%s[%p]:i/p: msw_ts 0x%lx lsw_ts 0x%lx nflags 0x%8x\n",
+			__func__, audio,
+			buf_node->meta_info.meta_in.ntimestamp.highpart,
+			buf_node->meta_info.meta_in.ntimestamp.lowpart,
+			buf_node->meta_info.meta_in.nflags);
+	} else { /* output buffer - Read */
+		memcpy((char *)buf_node->kvaddr,
+			&buf_node->meta_info.meta_out,
+			sizeof(struct dec_meta_out));
+		meta_data->meta_out_dsp[0].nflags = 0x00000000;
+		temp = meta_data->meta_out_dsp[0].msw_ts;
+		meta_data->meta_out_dsp[0].msw_ts =
+				meta_data->meta_out_dsp[0].lsw_ts;
+		meta_data->meta_out_dsp[0].lsw_ts = temp;
+
+		pr_debug("%s[%p]:o/p: msw_ts 0x%8x lsw_ts 0x%8x nflags 0x%8x, num_frames = %d\n",
+		__func__, audio,
+		((struct dec_meta_out *)buf_node->kvaddr)->\
+			meta_out_dsp[0].msw_ts,
+		((struct dec_meta_out *)buf_node->kvaddr)->\
+			meta_out_dsp[0].lsw_ts,
+		((struct dec_meta_out *)buf_node->kvaddr)->\
+			meta_out_dsp[0].nflags,
+		((struct dec_meta_out *)buf_node->kvaddr)->num_of_frames);
+	}
+}
+
 /* Read buffer from DSP / Handle Ack from DSP */
 void audio_aio_async_read_ack(struct q6audio_aio *audio, uint32_t token,
 			uint32_t *payload)
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 8808375..cae0f3a 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -353,7 +353,7 @@
 	return;
 }
 
-static int get_voice_index(u32 cvs_handle)
+static int get_voice_index_cvs(u32 cvs_handle)
 {
 	u32 i;
 
@@ -367,6 +367,32 @@
 	return 0;
 }
 
+static int get_voice_index_cvp(u32 cvp_handle)
+{
+	u32 i;
+
+	for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
+		if (rtac_voice_data.voice[i].cvp_handle == cvp_handle)
+			return i;
+	}
+
+	pr_err("%s: No voice index for CVP handle %d found returning 0\n",
+	       __func__, cvp_handle);
+	return 0;
+}
+
+static int get_voice_index(u32 mode, u32 handle)
+{
+	if (mode == RTAC_CVP)
+		return get_voice_index_cvp(handle);
+	if (mode == RTAC_CVS)
+		return get_voice_index_cvs(handle);
+
+	pr_err("%s: Invalid mode %d, returning 0\n",
+	       __func__, mode);
+	return 0;
+}
+
 
 /* ADM APR */
 void rtac_set_adm_handle(void *handle)
@@ -752,7 +778,7 @@
 	u32	count = 0;
 	u32	bytes_returned = 0;
 	u32	payload_size;
-	u16	dest_port;
+	u32	dest_port;
 	struct	apr_hdr	voice_params;
 	pr_debug("%s\n", __func__);
 
@@ -768,7 +794,8 @@
 		goto done;
 	}
 
-	if (copy_from_user(&payload_size, buf + sizeof(u32), sizeof(u32))) {
+	if (copy_from_user(&payload_size, buf + sizeof(payload_size),
+						sizeof(payload_size))) {
 		pr_err("%s: Could not copy payload size from user buffer\n",
 			__func__);
 		goto done;
@@ -780,7 +807,8 @@
 		goto done;
 	}
 
-	if (copy_from_user(&dest_port, buf + 2 * sizeof(u32), sizeof(u32))) {
+	if (copy_from_user(&dest_port, buf + 2 * sizeof(dest_port),
+						sizeof(dest_port))) {
 		pr_err("%s: Could not copy port id from user buffer\n",
 			__func__);
 		goto done;
@@ -817,10 +845,10 @@
 	voice_params.src_svc = 0;
 	voice_params.src_domain = APR_DOMAIN_APPS;
 	voice_params.src_port = voice_session_id[
-					get_voice_index(dest_port)];
+					get_voice_index(mode, dest_port)];
 	voice_params.dest_svc = 0;
 	voice_params.dest_domain = APR_DOMAIN_MODEM;
-	voice_params.dest_port = dest_port;
+	voice_params.dest_port = (u16)dest_port;
 	voice_params.token = 0;
 	voice_params.opcode = opcode;
 
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index aac83e5..53736ac 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -26,6 +26,7 @@
 #include <linux/mfd/pm8xxx/misc.h>
 
 #include <asm/mach-types.h>
+#include <asm/cacheflush.h>
 
 #include <mach/msm_iomap.h>
 #include <mach/restart.h>
@@ -129,7 +130,11 @@
 	pm8xxx_reset_pwr_off(0);
 
 	if (lower_pshold) {
-		__raw_writel(0, PSHOLD_CTL_SU);
+		if (!use_restart_v2())
+			__raw_writel(0, PSHOLD_CTL_SU);
+		else
+			__raw_writel(0, MSM_MPM2_PSHOLD_BASE);
+
 		mdelay(10000);
 		printk(KERN_ERR "Powering off has failed\n");
 	}
@@ -217,6 +222,8 @@
 			__raw_writel(0x77665501, restart_reason);
 		}
 	}
+
+	flush_cache_all();
 }
 
 void msm_restart(char mode, const char *cmd)
diff --git a/arch/arm/mach-msm/rpm-regulator-8960.c b/arch/arm/mach-msm/rpm-regulator-8960.c
index e75d730..8fe3571 100644
--- a/arch/arm/mach-msm/rpm-regulator-8960.c
+++ b/arch/arm/mach-msm/rpm-regulator-8960.c
@@ -74,6 +74,11 @@
 	VOLTAGE_RANGE( 750000, 1537500, 12500),
 };
 
+static struct vreg_range ln_ldo_ranges[] = {
+	VOLTAGE_RANGE( 690000, 1110000,  60000),
+	VOLTAGE_RANGE(1380000, 2220000, 120000),
+};
+
 static struct vreg_range smps_ranges[] = {
 	VOLTAGE_RANGE( 375000,  737500, 12500),
 	VOLTAGE_RANGE( 750000, 1487500, 12500),
@@ -93,6 +98,7 @@
 static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
 static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
 static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges);
+static struct vreg_set_points ln_ldo_set_points = SET_POINTS(ln_ldo_ranges);
 static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges);
 static struct vreg_set_points ftsmps_set_points = SET_POINTS(ftsmps_ranges);
 static struct vreg_set_points ncp_set_points = SET_POINTS(ncp_ranges);
@@ -101,6 +107,7 @@
 	&pldo_set_points,
 	&nldo_set_points,
 	&nldo1200_set_points,
+	&ln_ldo_set_points,
 	&smps_set_points,
 	&ftsmps_set_points,
 	&ncp_set_points,
@@ -190,6 +197,7 @@
 	LDO(L10,  "8921_l10",  "8921_l10_pc", pldo,     LDO_600,  0),
 	LDO(L11,  "8921_l11",  "8921_l11_pc", pldo,     LDO_150,  0),
 	LDO(L12,  "8921_l12",  "8921_l12_pc", nldo,     LDO_150,  1),
+	LDO(L13,  "8921_l13",  NULL,          ln_ldo,   LDO_5,    0),
 	LDO(L14,  "8921_l14",  "8921_l14_pc", pldo,     LDO_50,   0),
 	LDO(L15,  "8921_l15",  "8921_l15_pc", pldo,     LDO_150,  0),
 	LDO(L16,  "8921_l16",  "8921_l16_pc", pldo,     LDO_300,  0),
@@ -264,8 +272,12 @@
 {
 	int real_id;
 
-	if (id >= RPM_VREG_ID_PM8921_L1_PC && id <= RPM_VREG_ID_PM8921_L23_PC)
+	if (id >= RPM_VREG_ID_PM8921_L1_PC && id <= RPM_VREG_ID_PM8921_L12_PC)
 		real_id = id - RPM_VREG_ID_PM8921_L1_PC;
+	else if (id >= RPM_VREG_ID_PM8921_L14_PC
+			&& id <= RPM_VREG_ID_PM8921_L23_PC)
+		real_id = id - RPM_VREG_ID_PM8921_L14_PC
+				+ RPM_VREG_ID_PM8921_L14;
 	else if (id >= RPM_VREG_ID_PM8921_L29_PC
 			&& id <= RPM_VREG_ID_PM8921_S4_PC)
 		real_id = id - RPM_VREG_ID_PM8921_L29_PC
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index cd5556a..a190342 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -490,13 +490,14 @@
 
 	pkt_sz = smd_cur_packet_size(msm_rpm_data.ch_info);
 
+	if (!pkt_sz)
+		return -EAGAIN;
+
 	BUG_ON(pkt_sz > MAX_ERR_BUFFER_SIZE);
 
 	if (pkt_sz != smd_read_avail(msm_rpm_data.ch_info))
 		return -EAGAIN;
 
-	BUG_ON(pkt_sz == 0);
-
 	do {
 		int len;
 
@@ -822,7 +823,6 @@
 	unsigned long flags;
 	int rc = 0;
 	uint32_t id = 0;
-	int count = 0;
 
 	if (!msg_id)  {
 		pr_err("%s(): Invalid msg id\n", __func__);
@@ -852,7 +852,7 @@
 		goto wait_ack_cleanup;
 	}
 
-	while ((id != msg_id) && (count++ < 10)) {
+	while (id != msg_id) {
 		if (smd_is_pkt_avail(msm_rpm_data.ch_info)) {
 			int errno;
 			char buf[MAX_ERR_BUFFER_SIZE] = {};
@@ -861,17 +861,11 @@
 			id = msm_rpm_get_msg_id_from_ack(buf);
 			errno = msm_rpm_get_error_from_ack(buf);
 			msm_rpm_process_ack(id, errno);
-		} else
-			udelay(100);
+		}
 	}
 
-	if (count == 10) {
-		rc = -ETIMEDOUT;
-		pr_warn("%s(): Timed out after 1ms\n", __func__);
-	} else {
-		rc = elem->errno;
-		msm_rpm_free_list_entry(elem);
-	}
+	rc = elem->errno;
+	msm_rpm_free_list_entry(elem);
 wait_ack_cleanup:
 	irq_process = false;
 	spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags);
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 55ae2f8..43436e5 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -204,7 +204,11 @@
 		}
 	}
 
-	scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
+	/* TODO : Remove once bus scaling driver is in place */
+	if (!cpu_is_msm8226())
+		scm_perf_client = msm_bus_scale_register_client(
+				&scm_pas_bus_pdata);
+
 	if (!scm_perf_client)
 		pr_warn("unable to register bus client\n");
 
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 332d9f3..e33f87b 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -782,17 +782,21 @@
  * @pid:       Processor ID of processor on edge
  * @local_ch:  Channel that belongs to processor @pid
  * @remote_ch: Other side of edge contained @pid
+ * @is_word_access_ch: Bool, is this a word aligned access channel
  *
  * Returns 0 for not on edge, 1 for found on edge
  */
-static int pid_is_on_edge(struct smd_shared_v2 *shared2,
+static int pid_is_on_edge(void *shared2,
 		uint32_t type, uint32_t pid,
-		struct smd_half_channel **local_ch,
-		struct smd_half_channel **remote_ch
+		void **local_ch,
+		void **remote_ch,
+		int is_word_access_ch
 		)
 {
 	int ret = 0;
 	struct edge_to_pid *edge;
+	void *ch0;
+	void *ch1;
 
 	*local_ch = 0;
 	*remote_ch = 0;
@@ -800,15 +804,23 @@
 	if (!shared2 || (type >= ARRAY_SIZE(edge_to_pids)))
 		return 0;
 
+	if (is_word_access_ch) {
+		ch0 = &((struct smd_shared_v2_word_access *)(shared2))->ch0;
+		ch1 = &((struct smd_shared_v2_word_access *)(shared2))->ch1;
+	} else {
+		ch0 = &((struct smd_shared_v2 *)(shared2))->ch0;
+		ch1 = &((struct smd_shared_v2 *)(shared2))->ch1;
+	}
+
 	edge = &edge_to_pids[type];
 	if (edge->local_pid != edge->remote_pid) {
 		if (pid == edge->local_pid) {
-			*local_ch = &shared2->ch0;
-			*remote_ch = &shared2->ch1;
+			*local_ch = ch0;
+			*remote_ch = ch1;
 			ret = 1;
 		} else if (pid == edge->remote_pid) {
-			*local_ch = &shared2->ch1;
-			*remote_ch = &shared2->ch0;
+			*local_ch = ch1;
+			*remote_ch = ch0;
 			ret = 1;
 		}
 	}
@@ -860,14 +872,29 @@
 }
 EXPORT_SYMBOL(smd_pid_to_subsystem);
 
-static void smd_reset_edge(struct smd_half_channel *ch, unsigned new_state)
+static void smd_reset_edge(void *void_ch, unsigned new_state,
+				int is_word_access_ch)
 {
-	if (ch->state != SMD_SS_CLOSED) {
-		ch->state = new_state;
-		ch->fDSR = 0;
-		ch->fCTS = 0;
-		ch->fCD = 0;
-		ch->fSTATE = 1;
+	if (is_word_access_ch) {
+		struct smd_half_channel_word_access *ch =
+			(struct smd_half_channel_word_access *)(void_ch);
+		if (ch->state != SMD_SS_CLOSED) {
+			ch->state = new_state;
+			ch->fDSR = 0;
+			ch->fCTS = 0;
+			ch->fCD = 0;
+			ch->fSTATE = 1;
+		}
+	} else {
+		struct smd_half_channel *ch =
+			(struct smd_half_channel *)(void_ch);
+		if (ch->state != SMD_SS_CLOSED) {
+			ch->state = new_state;
+			ch->fDSR = 0;
+			ch->fCTS = 0;
+			ch->fCD = 0;
+			ch->fSTATE = 1;
+		}
 	}
 }
 
@@ -875,10 +902,11 @@
 		unsigned new_state, unsigned pid)
 {
 	unsigned n;
-	struct smd_shared_v2 *shared2;
+	void *shared2;
 	uint32_t type;
-	struct smd_half_channel *local_ch;
-	struct smd_half_channel *remote_ch;
+	void *local_ch;
+	void *remote_ch;
+	int is_word_access;
 
 	for (n = 0; n < SMD_CHANNELS; n++) {
 		if (!shared[n].ref_count)
@@ -887,12 +915,19 @@
 			continue;
 
 		type = SMD_CHANNEL_TYPE(shared[n].type);
-		shared2 = smem_alloc(SMEM_SMD_BASE_ID + n, sizeof(*shared2));
+		is_word_access = is_word_access_ch(type);
+		if (is_word_access)
+			shared2 = smem_alloc(SMEM_SMD_BASE_ID + n,
+				sizeof(struct smd_shared_v2_word_access));
+		else
+			shared2 = smem_alloc(SMEM_SMD_BASE_ID + n,
+				sizeof(struct smd_shared_v2));
 		if (!shared2)
 			continue;
 
-		if (pid_is_on_edge(shared2, type, pid, &local_ch, &remote_ch))
-			smd_reset_edge(local_ch, new_state);
+		if (pid_is_on_edge(shared2, type, pid, &local_ch, &remote_ch,
+							is_word_access))
+			smd_reset_edge(local_ch, new_state, is_word_access);
 
 		/*
 		 * ModemFW is in the same subsystem as ModemSW, but has
@@ -900,8 +935,8 @@
 		 */
 		if (pid == SMSM_MODEM &&
 				pid_is_on_edge(shared2, type, SMD_MODEM_Q6_FW,
-				 &local_ch, &remote_ch))
-			smd_reset_edge(local_ch, new_state);
+				 &local_ch, &remote_ch, is_word_access))
+			smd_reset_edge(local_ch, new_state, is_word_access);
 	}
 }
 
@@ -912,16 +947,17 @@
 	unsigned long flags;
 
 	SMD_DBG("%s: starting reset\n", __func__);
+
+	/* release any held spinlocks */
+	remote_spin_release(&remote_spinlock, restart_pid);
+	remote_spin_release_all(restart_pid);
+
 	shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
 	if (!shared) {
 		pr_err("%s: allocation table not initialized\n", __func__);
 		return;
 	}
 
-	/* release any held spinlocks */
-	remote_spin_release(&remote_spinlock, restart_pid);
-	remote_spin_release_all(restart_pid);
-
 	/* reset SMSM entry */
 	if (smsm_info.state) {
 		writel_relaxed(0, SMSM_STATE_ADDR(restart_pid));
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index b9fe341..5962d71 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -143,6 +143,13 @@
 	if (msm_smd_pkt_debug_mask & SMD_PKT_POLL) \
 		pr_info("Poll: "x); \
 } while (0)
+
+#define E_SMD_PKT_SSR(x) \
+do { \
+	if (x->do_reset_notification) \
+		pr_err("%s notifying reset for smd_pkt_dev id:%d\n", \
+			__func__, x->i); \
+} while (0)
 #else
 #define D_STATUS(x...) do {} while (0)
 #define D_READ(x...) do {} while (0)
@@ -150,6 +157,7 @@
 #define D_READ_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
 #define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
 #define D_POLL(x...) do {} while (0)
+#define E_SMD_PKT_SSR(x) do {} while (0)
 #endif
 
 static ssize_t open_timeout_store(struct device *d,
@@ -310,8 +318,7 @@
 
 	if (smd_pkt_devp->do_reset_notification) {
 		/* notify client that a reset occurred */
-		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
-			__func__, smd_pkt_devp->i);
+		E_SMD_PKT_SSR(smd_pkt_devp);
 		return notify_reset(smd_pkt_devp);
 	}
 	D_READ("Begin %s on smd_pkt_dev id:%d buffer_size %d\n",
@@ -327,8 +334,7 @@
 	mutex_lock(&smd_pkt_devp->rx_lock);
 	if (smd_pkt_devp->has_reset) {
 		mutex_unlock(&smd_pkt_devp->rx_lock);
-		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
-			__func__, smd_pkt_devp->i);
+		E_SMD_PKT_SSR(smd_pkt_devp);
 		return notify_reset(smd_pkt_devp);
 	}
 
@@ -377,8 +383,7 @@
 		if (r < 0) {
 			mutex_unlock(&smd_pkt_devp->rx_lock);
 			if (smd_pkt_devp->has_reset) {
-				pr_err("%s notifying reset for smd_pkt_dev"
-				       " id:%d\n", __func__, smd_pkt_devp->i);
+				E_SMD_PKT_SSR(smd_pkt_devp);
 				return notify_reset(smd_pkt_devp);
 			}
 			pr_err("%s Error while reading %d\n", __func__, r);
@@ -391,8 +396,7 @@
 				   smd_pkt_devp->has_reset);
 		if (smd_pkt_devp->has_reset) {
 			mutex_unlock(&smd_pkt_devp->rx_lock);
-			pr_err("%s notifying reset for smd_pkt_dev  id:%d\n",
-				__func__, smd_pkt_devp->i);
+			E_SMD_PKT_SSR(smd_pkt_devp);
 			return notify_reset(smd_pkt_devp);
 		}
 	} while (pkt_size != bytes_read);
@@ -444,8 +448,7 @@
 	}
 
 	if (smd_pkt_devp->do_reset_notification || smd_pkt_devp->has_reset) {
-		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
-			__func__, smd_pkt_devp->i);
+		E_SMD_PKT_SSR(smd_pkt_devp);
 		/* notify client that a reset occurred */
 		return notify_reset(smd_pkt_devp);
 	}
@@ -484,8 +487,7 @@
 
 		if (smd_pkt_devp->has_reset) {
 			mutex_unlock(&smd_pkt_devp->tx_lock);
-			pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
-				__func__, smd_pkt_devp->i);
+			E_SMD_PKT_SSR(smd_pkt_devp);
 			return notify_reset(smd_pkt_devp);
 		} else {
 			r = smd_write_segment(smd_pkt_devp->ch,
@@ -494,9 +496,7 @@
 			if (r < 0) {
 				mutex_unlock(&smd_pkt_devp->tx_lock);
 				if (smd_pkt_devp->has_reset) {
-					pr_err("%s notifying reset for"
-					       " smd_pkt_dev id:%d\n",
-						__func__, smd_pkt_devp->i);
+					E_SMD_PKT_SSR(smd_pkt_devp);
 					return notify_reset(smd_pkt_devp);
 				}
 				pr_err("%s on smd_pkt_dev id:%d failed r:%d\n",
@@ -532,8 +532,6 @@
 	mutex_lock(&smd_pkt_devp->ch_lock);
 	if (smd_pkt_devp->has_reset || !smd_pkt_devp->ch) {
 		mutex_unlock(&smd_pkt_devp->ch_lock);
-		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
-			__func__, smd_pkt_devp->i);
 		return POLLERR;
 	}
 
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index ea0b7a3..86de130 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -280,6 +280,12 @@
 	[143] = MSM_CPU_8930AA,
 	[144] = MSM_CPU_8930AA,
 
+	/* 8226 IDs */
+	[145] = MSM_CPU_8226,
+
+	/* 8092 IDs */
+	[146] = MSM_CPU_8092,
+
 	/* Uninitialized IDs are not known to run Linux.
 	   MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
 	   considered as unknown CPU. */
@@ -713,8 +719,17 @@
 		dummy_socinfo.id = 134;
 		strlcpy(dummy_socinfo.build_id, "msm9625 - ",
 			sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_msm8226()) {
+		dummy_socinfo.id = 145;
+		strlcpy(dummy_socinfo.build_id, "msm8226 - ",
+			sizeof(dummy_socinfo.build_id));
 	} else if (machine_is_msm8625_rumi3())
 		dummy_socinfo.id = 127;
+	else if (early_machine_is_mpq8092()) {
+		dummy_socinfo.id = 146;
+		strlcpy(dummy_socinfo.build_id, "mpq8092 - ",
+		sizeof(dummy_socinfo.build_id));
+	}
 	strlcat(dummy_socinfo.build_id, "Dummy socinfo",
 		sizeof(dummy_socinfo.build_id));
 	return (void *) &dummy_socinfo;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index fdde328..0318a70 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -27,6 +27,9 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/debugfs.h>
 
 #include <asm/current.h>
 
@@ -52,9 +55,18 @@
 	struct list_head list;
 };
 
+enum subsys_state {
+	SUBSYS_OFFLINE,
+	SUBSYS_ONLINE,
+};
+
+static const char * const subsys_states[] = {
+	[SUBSYS_OFFLINE] = "OFFLINE",
+	[SUBSYS_ONLINE] = "ONLINE",
+};
+
 struct subsys_device {
 	struct subsys_desc *desc;
-	struct list_head list;
 	struct wake_lock wake_lock;
 	char wlname[64];
 	struct work_struct work;
@@ -62,21 +74,58 @@
 	int restart_count;
 
 	void *notify;
+	struct device dev;
+	struct module *owner;
+	int count;
+	enum subsys_state state;
+	int id;
 
 	struct mutex shutdown_lock;
 	struct mutex powerup_lock;
 
 	void *restart_order;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *dentry;
+#endif
 };
 
+static struct subsys_device *to_subsys(struct device *d)
+{
+	return container_of(d, struct subsys_device, dev);
+}
+
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", to_subsys(dev)->desc->name);
+}
+
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	enum subsys_state state = to_subsys(dev)->state;
+	return snprintf(buf, PAGE_SIZE, "%s\n", subsys_states[state]);
+}
+
+static struct device_attribute subsys_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(state),
+	__ATTR_NULL,
+};
+
+static struct bus_type subsys_bus_type = {
+	.name		= "msm_subsys",
+	.dev_attrs	= subsys_attrs,
+};
+
+static DEFINE_IDA(subsys_ida);
+
 static int enable_ramdumps;
 module_param(enable_ramdumps, int, S_IRUGO | S_IWUSR);
 
 struct workqueue_struct *ssr_wq;
 
 static LIST_HEAD(restart_log_list);
-static LIST_HEAD(subsystem_list);
-static DEFINE_MUTEX(subsystem_list_lock);
 static DEFINE_MUTEX(soc_order_reg_lock);
 static DEFINE_MUTEX(restart_log_mutex);
 
@@ -101,28 +150,16 @@
 static const char * const _order_8x60_modems[] = {"external_modem", "modem"};
 DEFINE_SINGLE_RESTART_ORDER(orders_8x60_modems, _order_8x60_modems);
 
-/* MSM 8960 restart ordering info */
-static const char * const order_8960[] = {"modem", "lpass"};
 /*SGLTE restart ordering info*/
 static const char * const order_8960_sglte[] = {"external_modem",
 						"modem"};
 
-static struct subsys_soc_restart_order restart_orders_8960_one = {
-	.subsystem_list = order_8960,
-	.count = ARRAY_SIZE(order_8960),
-	.subsys_ptrs = {[ARRAY_SIZE(order_8960)] = NULL}
-	};
-
 static struct subsys_soc_restart_order restart_orders_8960_fusion_sglte = {
 	.subsystem_list = order_8960_sglte,
 	.count = ARRAY_SIZE(order_8960_sglte),
 	.subsys_ptrs = {[ARRAY_SIZE(order_8960_sglte)] = NULL}
 	};
 
-static struct subsys_soc_restart_order *restart_orders_8960[] = {
-	&restart_orders_8960_one,
-	};
-
 static struct subsys_soc_restart_order *restart_orders_8960_sglte[] = {
 	&restart_orders_8960_fusion_sglte,
 	};
@@ -156,9 +193,13 @@
 		return ret;
 
 	switch (restart_level) {
-	case RESET_SOC:
-	case RESET_SUBSYS_COUPLED:
 	case RESET_SUBSYS_INDEPENDENT:
+		if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
+			pr_info("Phase 3 is currently unsupported. Using phase 2 instead.\n");
+			restart_level = RESET_SUBSYS_COUPLED;
+		}
+	case RESET_SUBSYS_COUPLED:
+	case RESET_SOC:
 		pr_info("Phase %d behavior activated.\n", restart_level);
 		break;
 	default:
@@ -312,6 +353,24 @@
 		panic("[%p]: Failed to powerup %s!", current, name);
 }
 
+static int __find_subsys(struct device *dev, void *data)
+{
+	struct subsys_device *subsys = to_subsys(dev);
+	return !strcmp(subsys->desc->name, data);
+}
+
+static struct subsys_device *find_subsys(const char *str)
+{
+	struct device *dev;
+
+	if (!str)
+		return NULL;
+
+	dev = bus_find_device(&subsys_bus_type, NULL, (void *)str,
+			__find_subsys);
+	return dev ? to_subsys(dev) : NULL;
+}
+
 static void subsystem_restart_wq_func(struct work_struct *work)
 {
 	struct subsys_device *dev = container_of(work,
@@ -436,8 +495,17 @@
 
 int subsystem_restart_dev(struct subsys_device *dev)
 {
-	const char *name = dev->desc->name;
+	const char *name;
 
+	if (!get_device(&dev->dev))
+		return -ENODEV;
+
+	if (!try_module_get(dev->owner)) {
+		put_device(&dev->dev);
+		return -ENODEV;
+	}
+
+	name = dev->desc->name;
 	pr_info("Restart sequence requested for %s, restart_level = %d.\n",
 		name, restart_level);
 
@@ -454,6 +522,8 @@
 		panic("subsys-restart: Unknown restart level!\n");
 		break;
 	}
+	module_put(dev->owner);
+	put_device(&dev->dev);
 
 	return 0;
 }
@@ -461,69 +531,192 @@
 
 int subsystem_restart(const char *name)
 {
-	struct subsys_device *dev;
+	int ret;
+	struct subsys_device *dev = find_subsys(name);
 
-	mutex_lock(&subsystem_list_lock);
-	list_for_each_entry(dev, &subsystem_list, list)
-		if (!strncmp(dev->desc->name, name, SUBSYS_NAME_MAX_LENGTH))
-			goto found;
-	dev = NULL;
-found:
-	mutex_unlock(&subsystem_list_lock);
-	if (dev)
-		return subsystem_restart_dev(dev);
-	return -ENODEV;
+	if (!dev)
+		return -ENODEV;
+
+	ret = subsystem_restart_dev(dev);
+	put_device(&dev->dev);
+	return ret;
 }
 EXPORT_SYMBOL(subsystem_restart);
 
+#ifdef CONFIG_DEBUG_FS
+static ssize_t subsys_debugfs_read(struct file *filp, char __user *ubuf,
+		size_t cnt, loff_t *ppos)
+{
+	int r;
+	char buf[40];
+	struct subsys_device *subsys = filp->private_data;
+
+	r = snprintf(buf, sizeof(buf), "%d\n", subsys->count);
+	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t subsys_debugfs_write(struct file *filp,
+		const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	struct subsys_device *subsys = filp->private_data;
+	char buf[10];
+	char *cmp;
+
+	cnt = min(cnt, sizeof(buf) - 1);
+	if (copy_from_user(&buf, ubuf, cnt))
+		return -EFAULT;
+	buf[cnt] = '\0';
+	cmp = strstrip(buf);
+
+	if (!strcmp(cmp, "restart")) {
+		if (subsystem_restart_dev(subsys))
+			return -EIO;
+	} else {
+		return -EINVAL;
+	}
+
+	return cnt;
+}
+
+static const struct file_operations subsys_debugfs_fops = {
+	.open	= simple_open,
+	.read	= subsys_debugfs_read,
+	.write	= subsys_debugfs_write,
+};
+
+static struct dentry *subsys_base_dir;
+
+static int __init subsys_debugfs_init(void)
+{
+	subsys_base_dir = debugfs_create_dir("msm_subsys", NULL);
+	return !subsys_base_dir ? -ENOMEM : 0;
+}
+
+static void subsys_debugfs_exit(void)
+{
+	debugfs_remove_recursive(subsys_base_dir);
+}
+
+static int subsys_debugfs_add(struct subsys_device *subsys)
+{
+	if (!subsys_base_dir)
+		return -ENOMEM;
+
+	subsys->dentry = debugfs_create_file(subsys->desc->name,
+				S_IRUGO | S_IWUSR, subsys_base_dir,
+				subsys, &subsys_debugfs_fops);
+	return !subsys->dentry ? -ENOMEM : 0;
+}
+
+static void subsys_debugfs_remove(struct subsys_device *subsys)
+{
+	debugfs_remove(subsys->dentry);
+}
+#else
+static int __init subsys_debugfs_init(void) { return 0; };
+static void subsys_debugfs_exit(void) { }
+static int subsys_debugfs_add(struct subsys_device *subsys) { return 0; }
+static void subsys_debugfs_remove(struct subsys_device *subsys) { }
+#endif
+
+static void subsys_device_release(struct device *dev)
+{
+	struct subsys_device *subsys = to_subsys(dev);
+
+	wake_lock_destroy(&subsys->wake_lock);
+	mutex_destroy(&subsys->shutdown_lock);
+	mutex_destroy(&subsys->powerup_lock);
+	ida_simple_remove(&subsys_ida, subsys->id);
+	kfree(subsys);
+}
+
 struct subsys_device *subsys_register(struct subsys_desc *desc)
 {
-	struct subsys_device *dev;
+	struct subsys_device *subsys;
+	int ret;
 
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
+	subsys = kzalloc(sizeof(*subsys), GFP_KERNEL);
+	if (!subsys)
 		return ERR_PTR(-ENOMEM);
 
-	dev->desc = desc;
-	dev->notify = subsys_notif_add_subsys(desc->name);
-	dev->restart_order = update_restart_order(dev);
+	subsys->desc = desc;
+	subsys->owner = desc->owner;
+	subsys->dev.parent = desc->dev;
+	subsys->dev.bus = &subsys_bus_type;
+	subsys->dev.release = subsys_device_release;
 
-	snprintf(dev->wlname, sizeof(dev->wlname), "ssr(%s)", desc->name);
-	wake_lock_init(&dev->wake_lock, WAKE_LOCK_SUSPEND, dev->wlname);
-	INIT_WORK(&dev->work, subsystem_restart_wq_func);
-	spin_lock_init(&dev->restart_lock);
+	subsys->notify = subsys_notif_add_subsys(desc->name);
+	subsys->restart_order = update_restart_order(subsys);
 
-	mutex_init(&dev->shutdown_lock);
-	mutex_init(&dev->powerup_lock);
+	snprintf(subsys->wlname, sizeof(subsys->wlname), "ssr(%s)", desc->name);
+	wake_lock_init(&subsys->wake_lock, WAKE_LOCK_SUSPEND, subsys->wlname);
+	INIT_WORK(&subsys->work, subsystem_restart_wq_func);
+	spin_lock_init(&subsys->restart_lock);
 
-	mutex_lock(&subsystem_list_lock);
-	list_add(&dev->list, &subsystem_list);
-	mutex_unlock(&subsystem_list_lock);
+	subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL);
+	if (subsys->id < 0) {
+		ret = subsys->id;
+		goto err_ida;
+	}
+	dev_set_name(&subsys->dev, "subsys%d", subsys->id);
 
-	return dev;
+	mutex_init(&subsys->shutdown_lock);
+	mutex_init(&subsys->powerup_lock);
+
+	ret = subsys_debugfs_add(subsys);
+	if (ret)
+		goto err_debugfs;
+
+	ret = device_register(&subsys->dev);
+	if (ret) {
+		put_device(&subsys->dev);
+		goto err_register;
+	}
+
+	return subsys;
+
+err_register:
+	subsys_debugfs_remove(subsys);
+err_debugfs:
+	mutex_destroy(&subsys->shutdown_lock);
+	mutex_destroy(&subsys->powerup_lock);
+	ida_simple_remove(&subsys_ida, subsys->id);
+err_ida:
+	wake_lock_destroy(&subsys->wake_lock);
+	kfree(subsys);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(subsys_register);
 
-void subsys_unregister(struct subsys_device *dev)
+void subsys_unregister(struct subsys_device *subsys)
 {
-	if (IS_ERR_OR_NULL(dev))
+	if (IS_ERR_OR_NULL(subsys))
 		return;
-	mutex_lock(&subsystem_list_lock);
-	list_del(&dev->list);
-	mutex_unlock(&subsystem_list_lock);
-	wake_lock_destroy(&dev->wake_lock);
-	kfree(dev);
+
+	if (get_device(&subsys->dev)) {
+		mutex_lock(&subsys->powerup_lock);
+		WARN_ON(subsys->count);
+		device_unregister(&subsys->dev);
+		mutex_unlock(&subsys->powerup_lock);
+		subsys_debugfs_remove(subsys);
+		put_device(&subsys->dev);
+	}
 }
 EXPORT_SYMBOL(subsys_unregister);
 
+static int subsys_panic(struct device *dev, void *data)
+{
+	struct subsys_device *subsys = to_subsys(dev);
+
+	if (subsys->desc->crash_shutdown)
+		subsys->desc->crash_shutdown(subsys->desc);
+	return 0;
+}
+
 static int ssr_panic_handler(struct notifier_block *this,
 				unsigned long event, void *ptr)
 {
-	struct subsys_device *dev;
-
-	list_for_each_entry(dev, &subsystem_list, list)
-		if (dev->desc->crash_shutdown)
-			dev->desc->crash_shutdown(dev->desc);
+	bus_for_each_dev(&subsys_bus_type, NULL, NULL, subsys_panic);
 	return NOTIFY_DONE;
 }
 
@@ -553,26 +746,18 @@
 		n_restart_orders = ARRAY_SIZE(orders_8x60_all);
 	}
 
-	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
-	    cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627() ||
-	    cpu_is_msm8960ab()) {
-		if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
-			restart_orders = restart_orders_8960_sglte;
-			n_restart_orders =
-				ARRAY_SIZE(restart_orders_8960_sglte);
-		} else {
-			restart_orders = restart_orders_8960;
-			n_restart_orders = ARRAY_SIZE(restart_orders_8960);
-		}
-		for (i = 0; i < n_restart_orders; i++) {
-			mutex_init(&restart_orders[i]->powerup_lock);
-			mutex_init(&restart_orders[i]->shutdown_lock);
-		}
+	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
+		restart_orders = restart_orders_8960_sglte;
+		n_restart_orders = ARRAY_SIZE(restart_orders_8960_sglte);
+	}
+
+	for (i = 0; i < n_restart_orders; i++) {
+		mutex_init(&restart_orders[i]->powerup_lock);
+		mutex_init(&restart_orders[i]->shutdown_lock);
 	}
 
 	if (restart_orders == NULL || n_restart_orders < 1) {
 		WARN_ON(1);
-		return -EINVAL;
 	}
 
 	return 0;
@@ -580,11 +765,29 @@
 
 static int __init subsys_restart_init(void)
 {
-	ssr_wq = alloc_workqueue("ssr_wq", 0, 0);
-	if (!ssr_wq)
-		panic("Couldn't allocate workqueue for subsystem restart.\n");
+	int ret;
 
-	return ssr_init_soc_restart_orders();
+	ssr_wq = alloc_workqueue("ssr_wq", WQ_CPU_INTENSIVE, 0);
+	BUG_ON(!ssr_wq);
+
+	ret = bus_register(&subsys_bus_type);
+	if (ret)
+		goto err_bus;
+	ret = subsys_debugfs_init();
+	if (ret)
+		goto err_debugfs;
+	ret = ssr_init_soc_restart_orders();
+	if (ret)
+		goto err_soc;
+	return 0;
+
+err_soc:
+	subsys_debugfs_exit();
+err_debugfs:
+	bus_unregister(&subsys_bus_type);
+err_bus:
+	destroy_workqueue(ssr_wq);
+	return ret;
 }
 arch_initcall(subsys_restart_init);
 
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index cbf1d72..f014df9 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/wcnss_wlan.h>
 #include <linux/err.h>
+#include <asm/mach-types.h>
 #include <mach/irqs.h>
 #include <mach/scm.h>
 #include <mach/subsystem_restart.h>
@@ -180,13 +181,8 @@
 static void riva_crash_shutdown(const struct subsys_desc *subsys)
 {
 	pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
-	if (riva_crash != true) {
+	if (riva_crash != true)
 		smsm_riva_reset();
-		/* give sufficient time for wcnss to finish it's error
-		 * fatal routine */
-		msleep(3000);
-	}
-
 }
 
 static struct subsys_desc riva_8960 = {
@@ -226,6 +222,11 @@
 {
 	int ret;
 
+	if (machine_is_mpq8064_hrd()) {
+		pr_err("Riva not supported on this target\n");
+		return 0;
+	}
+
 	ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
 					smsm_state_cb_hdlr, 0);
 	if (ret < 0) {
@@ -264,6 +265,8 @@
 
 static void __exit riva_ssr_module_exit(void)
 {
+	if (machine_is_mpq8064_hrd())
+		return;
 	subsys_unregister(riva_8960_dev);
 	free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
 }
diff --git a/drivers/base/sync.c b/drivers/base/sync.c
index 9bc0da5..c0690c8 100644
--- a/drivers/base/sync.c
+++ b/drivers/base/sync.c
@@ -218,8 +218,10 @@
 	spin_lock_irqsave(&obj->active_list_lock, flags);
 
 	err = _sync_pt_has_signaled(pt);
-	if (err != 0)
+	if (err != 0) {
+		sync_fence_signal_pt(pt);
 		goto out;
+	}
 
 	list_add_tail(&pt->active_list, &obj->active_list_head);
 
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 4495eb0..1c14859 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/mempool.h>
 #include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/sched.h>
 #include <mach/msm_smd.h>
@@ -305,6 +306,7 @@
 	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/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 2dc1929..59139dc 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -93,6 +93,9 @@
 	ret += length;						\
 } while (0)
 
+/* Identifier for data from MDM */
+#define MDM_TOKEN	-1
+
 static void drain_timer_func(unsigned long data)
 {
 	queue_work(driver->diag_wq , &(driver->diag_drain_work));
@@ -122,6 +125,27 @@
 	mutex_unlock(&driver->diagchar_mutex);
 }
 
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+void diag_clear_hsic_tbl(void)
+{
+	int i;
+
+	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;
+		}
+		driver->hsic_buf_tbl[i].length = 0;
+	}
+}
+#else
+void diag_clear_hsic_tbl(void) { }
+#endif
+
 void diag_read_smd_work_fn(struct work_struct *work)
 {
 	__diag_smd_send_req();
@@ -243,17 +267,7 @@
 		driver->logging_mode = USB_MODE;
 		diagfwd_connect();
 #ifdef CONFIG_DIAG_BRIDGE_CODE
-		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;
-				driver->hsic_buf_tbl[i].length = 0;
-			}
-		}
+		diag_clear_hsic_tbl();
 		diagfwd_cancel_hsic();
 		diagfwd_connect_bridge(0);
 #endif
@@ -500,6 +514,7 @@
 		temp = driver->logging_mode;
 		driver->logging_mode = (int)ioarg;
 		if (driver->logging_mode == MEMORY_DEVICE_MODE) {
+			diag_clear_hsic_tbl();
 			driver->mask_check = 1;
 			if (driver->socket_process) {
 				/*
@@ -517,10 +532,12 @@
 			}
 		}
 		if (driver->logging_mode == UART_MODE) {
+			diag_clear_hsic_tbl();
 			driver->mask_check = 0;
 			driver->logging_mode = MEMORY_DEVICE_MODE;
 		}
 		if (driver->logging_mode == SOCKET_MODE) {
+			diag_clear_hsic_tbl();
 			driver->socket_process = current;
 			driver->mask_check = 0;
 			driver->logging_mode = MEMORY_DEVICE_MODE;
@@ -539,18 +556,8 @@
 			driver->in_busy_sdio = 1;
 #endif
 #ifdef CONFIG_DIAG_BRIDGE_CODE
-			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;
-					driver->hsic_buf_tbl[i].length = 0;
-				}
-			}
 			diagfwd_disconnect_bridge(0);
+			diag_clear_hsic_tbl();
 #endif
 		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
 							== MEMORY_DEVICE_MODE) {
@@ -578,11 +585,6 @@
 					&(driver->diag_read_sdio_work));
 #endif
 #ifdef CONFIG_DIAG_BRIDGE_CODE
-			driver->num_hsic_buf_tbl_entries = 0;
-			for (i = 0; i < driver->poolsize_hsic_write; i++) {
-				driver->hsic_buf_tbl[i].buf = 0;
-				driver->hsic_buf_tbl[i].length = 0;
-			}
 			diagfwd_connect_bridge(0);
 #endif
 		}
@@ -627,11 +629,6 @@
 					&(driver->diag_read_sdio_work));
 #endif
 #ifdef CONFIG_DIAG_BRIDGE_CODE
-			driver->num_hsic_buf_tbl_entries = 0;
-			for (i = 0; i < driver->poolsize_hsic_write; i++) {
-				driver->hsic_buf_tbl[i].buf = 0;
-				driver->hsic_buf_tbl[i].length = 0;
-			}
 			diagfwd_cancel_hsic();
 			diagfwd_connect_bridge(0);
 #endif
@@ -639,17 +636,7 @@
 				 driver->logging_mode == USB_MODE) {
 			diagfwd_connect();
 #ifdef CONFIG_DIAG_BRIDGE_CODE
-			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;
-					driver->hsic_buf_tbl[i].length = 0;
-				}
-			}
+			diag_clear_hsic_tbl();
 			diagfwd_cancel_hsic();
 			diagfwd_connect_bridge(0);
 #endif
@@ -666,6 +653,10 @@
 {
 	int index = -1, i = 0, ret = 0;
 	int num_data = 0, data_type;
+#if defined(CONFIG_DIAG_SDIO_PIPE) || defined(CONFIG_DIAG_BRIDGE_CODE)
+	int mdm_token = MDM_TOKEN;
+#endif
+
 	for (i = 0; i < driver->num_clients; i++)
 		if (driver->client_map[i].pid == current->tgid)
 			index = i;
@@ -681,6 +672,11 @@
 
 	if ((driver->data_ready[index] & USER_SPACE_LOG_TYPE) && (driver->
 					logging_mode == MEMORY_DEVICE_MODE)) {
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+		unsigned long spin_lock_flags;
+		struct diag_write_device hsic_buf_tbl[NUM_HSIC_BUF_TBL_ENTRIES];
+#endif
+
 		pr_debug("diag: process woken up\n");
 		/*Copy the type of data being passed*/
 		data_type = driver->data_ready[index] & USER_SPACE_LOG_TYPE;
@@ -800,6 +796,8 @@
 		/* copy 9K data over SDIO */
 		if (driver->in_busy_sdio == 1) {
 			num_data++;
+			/*Copy the negative  token of data being passed*/
+			COPY_USER_SPACE_OR_EXIT(buf+ret, mdm_token, 4);
 			/*Copy the length of data being passed*/
 			COPY_USER_SPACE_OR_EXIT(buf+ret,
 				 (driver->write_ptr_mdm->length), 4);
@@ -811,17 +809,36 @@
 		}
 #endif
 #ifdef CONFIG_DIAG_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);
 
 		for (i = 0; i < driver->poolsize_hsic_write; i++) {
-			if (driver->hsic_buf_tbl[i].length > 0) {
+			if (hsic_buf_tbl[i].length > 0) {
 				pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n",
-					 i, (unsigned int)
-					(driver->hsic_buf_tbl[i].buf),
-					driver->hsic_buf_tbl[i].length);
+					 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, &mdm_token, 4)) {
+					num_data--;
+					goto drop_hsic;
+				}
+				ret += 4;
+
 				/* Copy the length of data being passed */
-				if (copy_to_user(buf+ret, (void *)&(driver->
-					hsic_buf_tbl[i].length), 4)) {
+				if (copy_to_user(buf+ret,
+					(void *)&(hsic_buf_tbl[i].length),
+					4)) {
 					num_data--;
 					goto drop_hsic;
 				}
@@ -829,27 +846,38 @@
 
 				/* Copy the actual data being passed */
 				if (copy_to_user(buf+ret,
-					(void *)driver->hsic_buf_tbl[i].buf,
-					driver->hsic_buf_tbl[i].length)) {
+						(void *)hsic_buf_tbl[i].buf,
+						hsic_buf_tbl[i].length)) {
 					ret -= 4;
 					num_data--;
 					goto drop_hsic;
 				}
-				ret += driver->hsic_buf_tbl[i].length;
+				ret += hsic_buf_tbl[i].length;
 drop_hsic:
 				/* Return the buffer to the pool */
-				diagmem_free(driver, (unsigned char *)
-					(driver->hsic_buf_tbl[i].buf),
+				diagmem_free(driver,
+					(unsigned char *)(hsic_buf_tbl[i].buf),
 					POOL_TYPE_HSIC);
 
-				driver->hsic_buf_tbl[i].length = 0;
-				driver->hsic_buf_tbl[i].buf = 0;
-				driver->num_hsic_buf_tbl_entries--;
-
 				/* Call the write complete function */
 				diagfwd_write_complete_hsic(NULL);
 			}
 		}
+		if (driver->in_busy_smux == 1) {
+			num_data++;
+
+			/* Copy the negative  token of data being passed */
+			COPY_USER_SPACE_OR_EXIT(buf+ret, mdm_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);
@@ -954,6 +982,7 @@
 			      size_t count, loff_t *ppos)
 {
 	int err, ret = 0, pkt_type;
+	bool mdm_mask = false;
 #ifdef DIAG_DEBUG
 	int length = 0, i;
 #endif
@@ -989,6 +1018,12 @@
 							 payload_size);
 		/* Check masks for On-Device logging */
 		if (driver->mask_check) {
+			/* Check if mask is for MDM or MSM */
+			if (*(int *)driver->user_space_data == MDM_TOKEN) {
+				mdm_mask = true;
+				driver->user_space_data += 4;
+				buf += 4;
+			}
 			if (!mask_request_validate(driver->user_space_data)) {
 				pr_alert("diag: mask request Invalid\n");
 				return -EFAULT;
@@ -1002,7 +1037,7 @@
 #endif
 #ifdef CONFIG_DIAG_SDIO_PIPE
 		/* send masks to 9k too */
-		if (driver->sdio_ch) {
+		if (driver->sdio_ch && mdm_mask) {
 			wait_event_interruptible(driver->wait_q,
 				 (sdio_write_avail(driver->sdio_ch) >=
 					 payload_size));
@@ -1014,7 +1049,7 @@
 #endif
 #ifdef CONFIG_DIAG_BRIDGE_CODE
 		/* send masks to 9k too */
-		if (driver->hsic_ch && (payload_size > 0)) {
+		if (driver->hsic_ch && (payload_size > 0) && mdm_mask) {
 			/* wait sending mask updates if HSIC ch not ready */
 			if (driver->in_busy_hsic_write)
 				wait_event_interruptible(driver->wait_q,
@@ -1036,9 +1071,22 @@
 					driver->in_busy_hsic_write = 0;
 			}
 		}
+		if (driver->diag_smux_enabled && mdm_mask && driver->lcid) {
+			if (payload_size > 0) {
+				err = msm_smux_write(driver->lcid, NULL,
+						driver->user_space_data,
+						payload_size);
+				if (err) {
+					pr_err("diag:send mask to MDM err %d",
+							err);
+					return err;
+				}
+			}
+		}
 #endif
 		/* send masks to 8k now */
-		diag_process_hdlc((void *)(driver->user_space_data),
+		if (!mdm_mask)
+			diag_process_hdlc((void *)(driver->user_space_data),
 							 payload_size);
 		return 0;
 	}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 4b24e2b..c827ec7 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
+#include <linux/ratelimit.h>
 #include <linux/workqueue.h>
 #include <linux/pm_runtime.h>
 #include <linux/diagchar.h>
@@ -313,21 +314,27 @@
 
 #ifdef CONFIG_DIAG_BRIDGE_CODE
 		else if (proc_num == HSIC_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 =
 							driver->write_len_mdm;
 					driver->num_hsic_buf_tbl_entries++;
-#ifdef DIAG_DEBUG
-					pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d\n",
-						(unsigned int)
-						(driver->hsic_buf_tbl[i].buf),
-						driver->hsic_buf_tbl[i].length);
-#endif
+					foundIndex = i;
 					break;
 				}
 			}
+			spin_unlock_irqrestore(&driver->hsic_spinlock, flags);
+			if (foundIndex == -1)
+				err = -1;
+			else
+				pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d\n",
+					(unsigned int)buf,
+					driver->write_len_mdm);
 		}
 #endif
 		for (i = 0; i < driver->num_clients; i++)
@@ -433,7 +440,8 @@
 						diagmem_free(driver,
 							write_ptr_mdm,
 							POOL_TYPE_HSIC_WRITE);
-					pr_err("diag: HSIC write failure\n");
+						pr_err_ratelimited("diag: HSIC write failure, err: %d\n",
+							err);
 					}
 				} else {
 					pr_err("diag: allocate write fail\n");
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 11a8471..3878a82 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -32,13 +32,8 @@
 #include "diagfwd_hsic.h"
 #include "diagfwd_smux.h"
 
-#define N_MDM_WRITE	8
-#define N_MDM_READ	1
-
 #define READ_HSIC_BUF_SIZE 2048
 
-#define NUM_HSIC_BUF_TBL_ENTRIES N_MDM_WRITE
-
 static void diag_read_hsic_work_fn(struct work_struct *work)
 {
 	unsigned char *buf_in_hsic = NULL;
@@ -76,6 +71,13 @@
 
 		write_ptrs_available--;
 
+		/*
+		 * No sense queuing a read if the hsic bridge was
+		 * closed in another thread
+		 */
+		if (!driver->hsic_ch)
+			break;
+
 		buf_in_hsic = diagmem_alloc(driver, READ_HSIC_BUF_SIZE,
 							POOL_TYPE_HSIC);
 		if (buf_in_hsic) {
@@ -107,11 +109,13 @@
 	} while (buf_in_hsic);
 
 	/*
-	 * If there are no buffers available or for some reason there
-	 * was no hsic data, and if no unrecoverable error occurred
+	 * If there are read buffers available and for some reason the
+	 * read was not queued, and if no unrecoverable error occurred
 	 * (-ENODEV is an unrecoverable error), then set up the next read
 	 */
-	if ((num_reads_submitted == 0) && (err != -ENODEV))
+	if ((driver->count_hsic_pool < driver->poolsize_hsic) &&
+		(num_reads_submitted == 0) && (err != -ENODEV) &&
+		(driver->hsic_ch != 0))
 		queue_work(driver->diag_bridge_wq,
 				 &driver->diag_read_hsic_work);
 }
@@ -132,8 +136,12 @@
 		return;
 	}
 
-	/* Note that zero length is valid and still needs to be sent */
-	if (actual_size >= 0) {
+	/*
+	 * Note that zero length is valid and still needs to be sent to
+	 * the USB only when we are logging data to the USB
+	 */
+	if ((actual_size > 0) ||
+		((actual_size == 0) && (driver->logging_mode == USB_MODE))) {
 		if (!buf) {
 			pr_err("diag: Out of diagmem for HSIC\n");
 		} else {
@@ -146,7 +154,7 @@
 			/* If an error, return buffer to the pool */
 			if (err) {
 				diagmem_free(driver, buf, POOL_TYPE_HSIC);
-				pr_err("diag: In %s, error calling diag_device_write, err: %d\n",
+				pr_err_ratelimited("diag: In %s, error calling diag_device_write, err: %d\n",
 					__func__, err);
 			}
 		}
@@ -213,8 +221,9 @@
 	pr_debug("diag: hsic_resume\n");
 	driver->hsic_suspend = 0;
 
-	if ((driver->logging_mode == MEMORY_DEVICE_MODE) ||
-				(driver->usb_mdm_connected))
+	if ((driver->count_hsic_pool < driver->poolsize_hsic) &&
+		((driver->logging_mode == MEMORY_DEVICE_MODE) ||
+				(driver->usb_mdm_connected)))
 		queue_work(driver->diag_bridge_wq,
 			 &driver->diag_read_hsic_work);
 }
@@ -347,19 +356,19 @@
 		usb_diag_free_req(driver->mdm_ch);
 	}
 
-	if (driver->logging_mode == USB_MODE) {
-		if (driver->hsic_device_enabled) {
-			driver->in_busy_hsic_read_on_device = 1;
-			driver->in_busy_hsic_write = 1;
-			/* Turn off communication over usb mdm and hsic */
-			return diag_hsic_close();
-		} else if (driver->diag_smux_enabled) {
-			driver->in_busy_smux = 1;
-			driver->lcid = LCID_INVALID;
-			driver->smux_connected = 0;
-			/* Turn off communication over usb mdm and smux */
-			msm_smux_close(LCID_VALID);
-		}
+	if (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 mdm and hsic */
+		return diag_hsic_close();
+	} else if (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 mdm and smux */
+		msm_smux_close(LCID_VALID);
 	}
 	return 0;
 }
@@ -629,6 +638,7 @@
 	driver->read_len_mdm = 0;
 	driver->write_len_mdm = 0;
 	driver->num_hsic_buf_tbl_entries = 0;
+	spin_lock_init(&driver->hsic_spinlock);
 	if (driver->usb_buf_mdm_out  == NULL)
 		driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
 							 GFP_KERNEL);
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index b2d9c9f..19ed3c7 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -15,6 +15,11 @@
 
 #include <mach/diag_bridge.h>
 
+#define N_MDM_WRITE	8
+#define N_MDM_READ	1
+
+#define NUM_HSIC_BUF_TBL_ENTRIES N_MDM_WRITE
+
 int diagfwd_connect_bridge(int);
 int diagfwd_disconnect_bridge(int);
 int diagfwd_write_complete_hsic(struct diag_request *);
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 6f3b79b..e1e3ff5 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -28,7 +28,7 @@
 #include <linux/file.h>
 #include <linux/major.h>
 #include <linux/regulator/consumer.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #ifdef CONFIG_MSM_BUS_SCALING
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index bded488..4ee93cf 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -1,3 +1,3 @@
 
 obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-tmc.o coresight-tpiu.o coresight-etb.o coresight-funnel.o coresight-replicator.o coresight-stm.o coresight-etm.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
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
new file mode 100644
index 0000000..e9ac904
--- /dev/null
+++ b/drivers/coresight/coresight-csr.c
@@ -0,0 +1,202 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+#define csr_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
+#define csr_readl(drvdata, off)		__raw_readl(drvdata->base + off)
+
+#define CSR_LOCK(drvdata)						\
+do {									\
+	mb();								\
+	csr_writel(drvdata, 0x0, CORESIGHT_LAR);			\
+} while (0)
+#define CSR_UNLOCK(drvdata)						\
+do {									\
+	csr_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
+	mb();								\
+} while (0)
+
+#define CSR_SWDBGPWRCTRL	(0x000)
+#define CSR_SWDBGPWRACK		(0x004)
+#define CSR_SWSPADREG0		(0x008)
+#define CSR_SWSPADREG1		(0x00C)
+#define CSR_STMTRANSCTRL	(0x010)
+#define CSR_STMAWIDCTRL		(0x014)
+#define CSR_STMCHNOFST0		(0x018)
+#define CSR_STMCHNOFST1		(0x01C)
+#define CSR_STMEXTHWCTRL0	(0x020)
+#define CSR_STMEXTHWCTRL1	(0x024)
+#define CSR_STMEXTHWCTRL2	(0x028)
+#define CSR_STMEXTHWCTRL3	(0x02C)
+#define CSR_USBBAMCTRL		(0x030)
+#define CSR_USBFLSHCTRL		(0x034)
+#define CSR_TIMESTAMPCTRL	(0x038)
+#define CSR_AOTIMEVAL0		(0x03C)
+#define CSR_AOTIMEVAL1		(0x040)
+#define CSR_QDSSTIMEVAL0	(0x044)
+#define CSR_QDSSTIMEVAL1	(0x048)
+#define CSR_QDSSTIMELOAD0	(0x04C)
+#define CSR_QDSSTIMELOAD1	(0x050)
+#define CSR_DAPMSAVAL		(0x054)
+#define CSR_QDSSCLKVOTE		(0x058)
+#define CSR_QDSSCLKIPI		(0x05C)
+#define CSR_QDSSPWRREQIGNORE	(0x060)
+#define CSR_QDSSSPARE		(0x064)
+#define CSR_IPCAT		(0x068)
+
+#define BLKSIZE_256		0
+#define BLKSIZE_512		1
+#define BLKSIZE_1024		2
+#define BLKSIZE_2048		3
+
+struct csr_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+};
+
+static struct csr_drvdata *csrdrvdata;
+
+void msm_qdss_csr_enable_bam_to_usb(void)
+{
+	struct csr_drvdata *drvdata = csrdrvdata;
+	uint32_t usbbamctrl, usbflshctrl;
+
+	CSR_UNLOCK(drvdata);
+
+	usbbamctrl = csr_readl(drvdata, CSR_USBBAMCTRL);
+	usbbamctrl = (usbbamctrl & ~0x3) | BLKSIZE_256;
+	csr_writel(drvdata, usbbamctrl, CSR_USBBAMCTRL);
+
+	usbflshctrl = csr_readl(drvdata, CSR_USBFLSHCTRL);
+	usbflshctrl = (usbflshctrl & ~0x3FFFC) | (0x1000 << 2);
+	csr_writel(drvdata, usbflshctrl, CSR_USBFLSHCTRL);
+	usbflshctrl |= 0x2;
+	csr_writel(drvdata, usbflshctrl, CSR_USBFLSHCTRL);
+
+	usbbamctrl |= 0x4;
+	csr_writel(drvdata, usbbamctrl, CSR_USBBAMCTRL);
+
+	CSR_LOCK(drvdata);
+}
+EXPORT_SYMBOL_GPL(msm_qdss_csr_enable_bam_to_usb);
+
+void msm_qdss_csr_disable_bam_to_usb(void)
+{
+	struct csr_drvdata *drvdata = csrdrvdata;
+	uint32_t usbbamctrl;
+
+	CSR_UNLOCK(drvdata);
+
+	usbbamctrl = csr_readl(drvdata, CSR_USBBAMCTRL);
+	usbbamctrl &= (~0x4);
+	csr_writel(drvdata, usbbamctrl, CSR_USBBAMCTRL);
+
+	CSR_LOCK(drvdata);
+}
+EXPORT_SYMBOL_GPL(msm_qdss_csr_disable_bam_to_usb);
+
+static int __devinit csr_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct csr_drvdata *drvdata;
+	struct resource *res;
+	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)
+		return -ENOMEM;
+	/* Store the driver data pointer for use in exported functions */
+	csrdrvdata = drvdata;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	desc->type = CORESIGHT_DEV_TYPE_NONE;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
+
+	dev_info(dev, "CSR initialized\n");
+	return 0;
+}
+
+static int __devexit csr_remove(struct platform_device *pdev)
+{
+	struct csr_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	coresight_unregister(drvdata->csdev);
+	return 0;
+}
+
+static struct of_device_id csr_match[] = {
+	{.compatible = "qcom,coresight-csr"},
+	{}
+};
+
+static struct platform_driver csr_driver = {
+	.probe          = csr_probe,
+	.remove         = __devexit_p(csr_remove),
+	.driver         = {
+		.name   = "coresight-csr",
+		.owner	= THIS_MODULE,
+		.of_match_table = csr_match,
+	},
+};
+
+static int __init csr_init(void)
+{
+	return platform_driver_register(&csr_driver);
+}
+module_init(csr_init);
+
+static void __exit csr_exit(void)
+{
+	platform_driver_unregister(&csr_driver);
+}
+module_exit(csr_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight CSR driver");
diff --git a/drivers/coresight/coresight-etb.c b/drivers/coresight/coresight-etb.c
index 56cee06..bd5bf8e 100644
--- a/drivers/coresight/coresight-etb.c
+++ b/drivers/coresight/coresight-etb.c
@@ -127,7 +127,9 @@
 	ETB_UNLOCK(drvdata);
 
 	ffcr = etb_readl(drvdata, ETB_FFCR);
-	ffcr |= (BIT(12) | BIT(6));
+	ffcr |= BIT(12);
+	etb_writel(drvdata, ffcr, ETB_FFCR);
+	ffcr |= BIT(6);
 	etb_writel(drvdata, ffcr, ETB_FFCR);
 	for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFCR), 6) != 0
 				&& count > 0; count--)
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 46d3e5d..f4c4d08 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/smp.h>
 #include <linux/wakelock.h>
-#include <linux/pm_qos.h>
 #include <linux/sysfs.h>
 #include <linux/stat.h>
 #include <linux/mutex.h>
@@ -32,6 +31,7 @@
 #include <linux/coresight.h>
 #include <asm/sections.h>
 #include <mach/socinfo.h>
+#include <mach/msm_memory_dump.h>
 
 #include "coresight-priv.h"
 
@@ -132,6 +132,9 @@
 
 #define ETM_SEQ_STATE_MAX_VAL	(0x2)
 
+#define ETM_REG_DUMP_VER_OFF	(4)
+#define ETM_REG_DUMP_VER	(1)
+
 enum etm_addr_type {
 	ETM_ADDR_TYPE_NONE,
 	ETM_ADDR_TYPE_SINGLE,
@@ -156,7 +159,6 @@
 	struct clk			*clk;
 	struct mutex			mutex;
 	struct wake_lock		wake_lock;
-	struct pm_qos_request		qos_req;
 	int				cpu;
 	uint8_t				arch;
 	uint8_t				nr_addr_cmp;
@@ -195,6 +197,8 @@
 	uint32_t			timestamp_event;
 };
 
+static struct etm_drvdata *etm0drvdata;
+
 /* ETM clock is derived from the processor clock and gets enabled on a
  * logical OR of below items on Krait (pass2 onwards):
  * 1.CPMR[ETMCLKEN] is 1
@@ -258,9 +262,10 @@
 	     etm_readl(drvdata, ETMSR));
 }
 
-static void __etm_enable(struct etm_drvdata *drvdata)
+static void __etm_enable(void *info)
 {
 	int i;
+	struct etm_drvdata *drvdata = info;
 
 	ETM_UNLOCK(drvdata);
 	/* Vote for ETM power/clock enable */
@@ -305,6 +310,8 @@
 
 	etm_clr_prog(drvdata);
 	ETM_LOCK(drvdata);
+
+	dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
 }
 
 static int etm_enable(struct coresight_device *csdev)
@@ -313,36 +320,31 @@
 	int ret;
 
 	wake_lock(&drvdata->wake_lock);
-	/* 1. causes all online cpus to come out of idle PC
-	 * 2. prevents idle PC until save restore flag is enabled atomically
-	 *
-	 * we rely on the user to prevent hotplug on/off racing with this
-	 * operation and to ensure cores where trace is expected to be turned
-	 * on are already hotplugged on
-	 */
-	pm_qos_update_request(&drvdata->qos_req, 0);
 
 	ret = clk_prepare_enable(drvdata->clk);
 	if (ret)
 		goto err_clk;
 
 	mutex_lock(&drvdata->mutex);
-	__etm_enable(drvdata);
+	/* executing __etm_enable on the cpu whose ETM is being enabled
+	 * ensures that register writes occur when cpu is powered.
+	 */
+	smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
 	mutex_unlock(&drvdata->mutex);
 
-	pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
 	wake_unlock(&drvdata->wake_lock);
 
 	dev_info(drvdata->dev, "ETM tracing enabled\n");
 	return 0;
 err_clk:
-	pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
 	wake_unlock(&drvdata->wake_lock);
 	return ret;
 }
 
-static void __etm_disable(struct etm_drvdata *drvdata)
+static void __etm_disable(void *info)
 {
+	struct etm_drvdata *drvdata = info;
+
 	ETM_UNLOCK(drvdata);
 	etm_set_prog(drvdata);
 
@@ -352,6 +354,8 @@
 	/* Vote for ETM power/clock disable */
 	etm_set_pwrdwn(drvdata);
 	ETM_LOCK(drvdata);
+
+	dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
 }
 
 static void etm_disable(struct coresight_device *csdev)
@@ -359,22 +363,16 @@
 	struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
 	wake_lock(&drvdata->wake_lock);
-	/* 1. causes all online cpus to come out of idle PC
-	 * 2. prevents idle PC until save restore flag is disabled atomically
-	 *
-	 * we rely on the user to prevent hotplug on/off racing with this
-	 * operation and to ensure cores where trace is expected to be turned
-	 * off are already hotplugged on
-	 */
-	pm_qos_update_request(&drvdata->qos_req, 0);
 
 	mutex_lock(&drvdata->mutex);
-	__etm_disable(drvdata);
+	/* executing __etm_disable on the cpu whose ETM is being disabled
+	 * ensures that register writes occur when cpu is powered.
+	 */
+	smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
 	mutex_unlock(&drvdata->mutex);
 
 	clk_disable_unprepare(drvdata->clk);
 
-	pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
 	wake_unlock(&drvdata->wake_lock);
 
 	dev_info(drvdata->dev, "ETM tracing disabled\n");
@@ -1418,9 +1416,8 @@
 	return true;
 }
 
-static int __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
+static void __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
 {
-	int ret;
 	uint32_t etmidr;
 	uint32_t etmccr;
 
@@ -1438,10 +1435,6 @@
 	/* find all capabilities */
 	etmidr = etm_readl(drvdata, ETMIDR);
 	drvdata->arch = BMVAL(etmidr, 4, 11);
-	if (etm_arch_supported(drvdata->arch) == false) {
-		ret = -EINVAL;
-		goto err;
-	}
 
 	etmccr = etm_readl(drvdata, ETMCCR);
 	drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
@@ -1453,10 +1446,16 @@
 	/* Vote for ETM power/clock disable */
 	etm_set_pwrdwn(drvdata);
 	ETM_LOCK(drvdata);
+}
 
-	return 0;
-err:
-	return ret;
+static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
+{
+	drvdata->arch = etm0drvdata->arch;
+	drvdata->nr_addr_cmp = etm0drvdata->nr_addr_cmp;
+	drvdata->nr_cntr = etm0drvdata->nr_cntr;
+	drvdata->nr_ext_inp = etm0drvdata->nr_ext_inp;
+	drvdata->nr_ext_out = etm0drvdata->nr_ext_out;
+	drvdata->nr_ctxid_cmp = etm0drvdata->nr_ctxid_cmp;
 }
 
 static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
@@ -1513,7 +1512,10 @@
 	struct coresight_platform_data *pdata;
 	struct etm_drvdata *drvdata;
 	struct resource *res;
-	static int etm_count;
+	uint32_t reg_size;
+	static int count;
+	void *baddr;
+	struct msm_client_dump dump;
 	struct coresight_desc *desc;
 
 	/* Fail probe for Krait pass3 until supported */
@@ -1538,6 +1540,7 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
+	reg_size = resource_size(res);
 
 	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
 	if (!drvdata->base)
@@ -1545,8 +1548,6 @@
 
 	mutex_init(&drvdata->mutex);
 	wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
-	pm_qos_add_request(&drvdata->qos_req, PM_QOS_CPU_DMA_LATENCY,
-			   PM_QOS_DEFAULT_VALUE);
 
 	drvdata->clk = devm_clk_get(dev, "core_clk");
 	if (IS_ERR(drvdata->clk)) {
@@ -1558,19 +1559,44 @@
 	if (ret)
 		goto err0;
 
-	drvdata->cpu = etm_count++;
+	drvdata->cpu = count++;
 
 	ret = clk_prepare_enable(drvdata->clk);
 	if (ret)
 		goto err0;
 
-	ret = etm_init_arch_data(drvdata);
-	if (ret)
+	/* Use CPU0 to populate read-only configuration data for ETM0. For other
+	 * ETMs copy it over from ETM0.
+	 */
+	if (drvdata->cpu == 0) {
+		etm_init_arch_data(drvdata);
+		etm0drvdata = drvdata;
+	} else {
+		etm_copy_arch_data(drvdata);
+	}
+	if (etm_arch_supported(drvdata->arch) == false) {
+		ret = -EINVAL;
 		goto err1;
+	}
 	etm_init_default_data(drvdata);
 
 	clk_disable_unprepare(drvdata->clk);
 
+	baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
+	if (baddr) {
+		*(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
+		dump.id = MSM_ETM0_REG + drvdata->cpu;
+		dump.start_addr = virt_to_phys(baddr);
+		dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
+		ret = msm_dump_table_register(&dump);
+		if (ret) {
+			devm_kfree(dev, baddr);
+			dev_err(dev, "ETM REG dump setup failed\n");
+		}
+	} else {
+		dev_err(dev, "ETM REG dump space allocation failed\n");
+	}
+
 	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
 	if (!desc) {
 		ret = -ENOMEM;
@@ -1598,7 +1624,6 @@
 err1:
 	clk_disable_unprepare(drvdata->clk);
 err0:
-	pm_qos_remove_request(&drvdata->qos_req);
 	wake_lock_destroy(&drvdata->wake_lock);
 	mutex_destroy(&drvdata->mutex);
 	return ret;
@@ -1609,7 +1634,6 @@
 	struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
 
 	coresight_unregister(drvdata->csdev);
-	pm_qos_remove_request(&drvdata->qos_req);
 	wake_lock_destroy(&drvdata->wake_lock);
 	mutex_destroy(&drvdata->mutex);
 	return 0;
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index a28a3a5..2b00242 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -36,4 +36,12 @@
 #define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
 #define BVAL(val, n)		((val & BIT(n)) >> n)
 
+#ifdef CONFIG_MSM_QDSS
+extern void msm_qdss_csr_enable_bam_to_usb(void);
+extern void msm_qdss_csr_disable_bam_to_usb(void);
+#else
+static inline void msm_qdss_csr_enable_bam_to_usb(void) {}
+static inline void msm_qdss_csr_disable_bam_to_usb(void) {}
+#endif
+
 #endif
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index e366918..70b2c43 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -150,7 +150,10 @@
 {
 	STM_UNLOCK(drvdata);
 
-	stm_writel(drvdata, 0x0, STMHETER);
+	/* Program STMHETER to ensure TRIGOUTHETE (fed to CTI) is asserted
+	   for HW events.
+	*/
+	stm_writel(drvdata, 0xFFFFFFFF, STMHETER);
 	stm_writel(drvdata, 0xFFFFFFFF, STMHEER);
 	stm_writel(drvdata, 0x5, STMHEMCR);
 
@@ -187,7 +190,7 @@
 {
 	STM_UNLOCK(drvdata);
 
-	stm_writel(drvdata, 0xFFFFFFFF, STMSPTER);
+	stm_writel(drvdata, 0x10, STMSPTRIGCSR);
 	stm_writel(drvdata, 0xFFFFFFFF, STMSPER);
 
 	STM_LOCK(drvdata);
@@ -214,9 +217,9 @@
 
 	STM_UNLOCK(drvdata);
 
-	stm_writel(drvdata, 0x80, STMSYNCR);
+	stm_writel(drvdata, 0xFFF, STMSYNCR);
 	/* SYNCEN is read-only and HWTEN is not implemented */
-	stm_writel(drvdata, 0x30003, STMTCSR);
+	stm_writel(drvdata, 0x100003, STMTCSR);
 
 	STM_LOCK(drvdata);
 }
@@ -243,9 +246,9 @@
 {
 	STM_UNLOCK(drvdata);
 
-	stm_writel(drvdata, 0x0, STMHETER);
-	stm_writel(drvdata, 0x0, STMHEER);
 	stm_writel(drvdata, 0x0, STMHEMCR);
+	stm_writel(drvdata, 0x0, STMHEER);
+	stm_writel(drvdata, 0x0, STMHETER);
 
 	STM_LOCK(drvdata);
 }
@@ -263,7 +266,7 @@
 	STM_UNLOCK(drvdata);
 
 	stm_writel(drvdata, 0x0, STMSPER);
-	stm_writel(drvdata, 0x0, STMSPTER);
+	stm_writel(drvdata, 0x0, STMSPTRIGCSR);
 
 	STM_LOCK(drvdata);
 }
@@ -280,7 +283,7 @@
 {
 	STM_UNLOCK(drvdata);
 
-	stm_writel(drvdata, 0x30000, STMTCSR);
+	stm_writel(drvdata, 0x100000, STMTCSR);
 
 	STM_LOCK(drvdata);
 
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 1c85aff..0be5882 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,7 +28,11 @@
 #include <linux/clk.h>
 #include <linux/of_coresight.h>
 #include <linux/coresight.h>
+#include <linux/usb/usb_qdss.h>
 #include <mach/memory.h>
+#include <mach/sps.h>
+#include <mach/usb_bam.h>
+#include <mach/msm_memory_dump.h>
 
 #include "coresight-priv.h"
 
@@ -74,6 +78,13 @@
 #define TMC_ITATBCTR0		(0xEF8)
 
 #define BYTES_PER_WORD		4
+#define TMC_ETR_BAM_PIPE_INDEX	0
+#define TMC_ETR_BAM_NR_PIPES	2
+
+#define TMC_ETFETB_DUMP_VER_OFF	(4)
+#define TMC_ETFETB_DUMP_VER	(1)
+#define TMC_REG_DUMP_VER_OFF	(4)
+#define TMC_REG_DUMP_VER	(1)
 
 enum tmc_config_type {
 	TMC_CONFIG_TYPE_ETB,
@@ -87,6 +98,12 @@
 	TMC_MODE_HARDWARE_FIFO,
 };
 
+enum tmc_etr_out_mode {
+	TMC_ETR_OUT_MODE_NONE,
+	TMC_ETR_OUT_MODE_MEM,
+	TMC_ETR_OUT_MODE_USB,
+};
+
 enum tmc_mem_intf_width {
 	TMC_MEM_INTF_WIDTH_32BITS	= 0x2,
 	TMC_MEM_INTF_WIDTH_64BITS	= 0x3,
@@ -94,6 +111,19 @@
 	TMC_MEM_INTF_WIDTH_256BITS	= 0x5,
 };
 
+struct tmc_etr_bam_data {
+	struct sps_bam_props	props;
+	uint32_t		handle;
+	struct sps_pipe		*pipe;
+	struct sps_connect	connect;
+	uint32_t		src_pipe_idx;
+	uint32_t		dest;
+	uint32_t		dest_pipe_idx;
+	struct sps_mem_buffer	desc_fifo;
+	struct sps_mem_buffer	data_fifo;
+	bool			enable;
+};
+
 struct tmc_drvdata {
 	void __iomem		*base;
 	struct device		*dev;
@@ -101,12 +131,18 @@
 	struct miscdevice	miscdev;
 	struct clk		*clk;
 	spinlock_t		spinlock;
+	struct mutex		read_lock;
 	int			read_count;
 	bool			reading;
 	char			*buf;
 	unsigned long		paddr;
 	void __iomem		*vaddr;
 	uint32_t		size;
+	struct mutex		usb_lock;
+	struct usb_qdss_ch	*usbch;
+	struct tmc_etr_bam_data	*bamdata;
+	enum tmc_etr_out_mode	out_mode;
+	bool			enable_to_bam;
 	bool			enable;
 	enum tmc_config_type	config_type;
 	uint32_t		trigger_cntr;
@@ -154,6 +190,151 @@
 	tmc_writel(drvdata, 0x0, TMC_CTL);
 }
 
+static void tmc_etr_fill_usb_bam_data(struct tmc_drvdata *drvdata)
+{
+	struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
+
+	get_bam2bam_connection_info(0, PEER_PERIPHERAL_TO_USB,
+				    &bamdata->dest,
+				    &bamdata->dest_pipe_idx,
+				    &bamdata->src_pipe_idx,
+				    &bamdata->desc_fifo,
+				    &bamdata->data_fifo);
+}
+
+static void __tmc_etr_enable_to_bam(struct tmc_drvdata *drvdata)
+{
+	struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
+	uint32_t axictl;
+
+	if (drvdata->enable_to_bam)
+		return;
+
+	/* Configure and enable required CSR registers */
+	msm_qdss_csr_enable_bam_to_usb();
+
+	/* Configure and enable ETR for usb bam output */
+
+	TMC_UNLOCK(drvdata);
+
+	tmc_writel(drvdata, bamdata->data_fifo.size / BYTES_PER_WORD,
+		   TMC_RSZ);
+	tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
+
+	axictl = tmc_readl(drvdata, TMC_AXICTL);
+	axictl |= (0xF << 8);
+	tmc_writel(drvdata, axictl, TMC_AXICTL);
+	axictl &= ~(0x1 << 7);
+	tmc_writel(drvdata, axictl, TMC_AXICTL);
+	axictl = (axictl & ~0x3) | 0x2;
+	tmc_writel(drvdata, axictl, TMC_AXICTL);
+
+	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, drvdata->trigger_cntr, TMC_TRG);
+	__tmc_enable(drvdata);
+
+	TMC_LOCK(drvdata);
+
+	drvdata->enable_to_bam = true;
+}
+
+static int tmc_etr_bam_enable(struct tmc_drvdata *drvdata)
+{
+	struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
+	int ret;
+
+	if (bamdata->enable)
+		return 0;
+
+	/* Configure and enable ndp bam */
+
+	bamdata->pipe = sps_alloc_endpoint();
+	if (!bamdata->pipe)
+		return -ENOMEM;
+
+	ret = sps_get_config(bamdata->pipe, &bamdata->connect);
+	if (ret)
+		goto err;
+
+	bamdata->connect.mode = SPS_MODE_SRC;
+	bamdata->connect.source = bamdata->handle;
+	bamdata->connect.event_thresh = 0x4;
+	bamdata->connect.src_pipe_index = TMC_ETR_BAM_PIPE_INDEX;
+	bamdata->connect.options = SPS_O_AUTO_ENABLE;
+
+	bamdata->connect.destination = bamdata->dest;
+	bamdata->connect.dest_pipe_index = bamdata->dest_pipe_idx;
+	bamdata->connect.desc = bamdata->desc_fifo;
+	bamdata->connect.data = bamdata->data_fifo;
+
+	ret = sps_connect(bamdata->pipe, &bamdata->connect);
+	if (ret)
+		goto err;
+
+	bamdata->enable = true;
+	return 0;
+err:
+	sps_free_endpoint(bamdata->pipe);
+	return ret;
+}
+
+static void __tmc_etr_disable_to_bam(struct tmc_drvdata *drvdata)
+{
+	if (!drvdata->enable_to_bam)
+		return;
+
+	TMC_UNLOCK(drvdata);
+
+	tmc_flush_and_stop(drvdata);
+	__tmc_disable(drvdata);
+
+	TMC_LOCK(drvdata);
+
+	/* Disable CSR registers */
+	msm_qdss_csr_disable_bam_to_usb();
+	drvdata->enable_to_bam = false;
+}
+
+static void tmc_etr_bam_disable(struct tmc_drvdata *drvdata)
+{
+	struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
+
+	if (!bamdata->enable)
+		return;
+
+	sps_disconnect(bamdata->pipe);
+	sps_free_endpoint(bamdata->pipe);
+	bamdata->enable = false;
+}
+
+static void usb_notifier(void *priv, unsigned int event,
+			struct qdss_request *d_req, struct usb_qdss_ch *ch)
+{
+	struct tmc_drvdata *drvdata = priv;
+	unsigned long flags;
+	int ret = 0;
+
+	mutex_lock(&drvdata->usb_lock);
+	if (event == USB_QDSS_CONNECT) {
+		tmc_etr_fill_usb_bam_data(drvdata);
+		ret = tmc_etr_bam_enable(drvdata);
+		if (ret)
+			dev_err(drvdata->dev, "ETR BAM enable failed\n");
+
+		spin_lock_irqsave(&drvdata->spinlock, flags);
+		__tmc_etr_enable_to_bam(drvdata);
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	} else if (event == USB_QDSS_DISCONNECT) {
+		spin_lock_irqsave(&drvdata->spinlock, flags);
+		__tmc_etr_disable_to_bam(drvdata);
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		tmc_etr_bam_disable(drvdata);
+	}
+	mutex_unlock(&drvdata->usb_lock);
+}
+
 static void __tmc_etb_enable(struct tmc_drvdata *drvdata)
 {
 	/* Zero out the memory to help with debug */
@@ -169,7 +350,7 @@
 	TMC_LOCK(drvdata);
 }
 
-static void __tmc_etr_enable(struct tmc_drvdata *drvdata)
+static void __tmc_etr_enable_to_mem(struct tmc_drvdata *drvdata)
 {
 	uint32_t axictl;
 
@@ -192,6 +373,7 @@
 	tmc_writel(drvdata, drvdata->paddr, TMC_DBALO);
 	tmc_writel(drvdata, 0x0, TMC_DBAHI);
 	tmc_writel(drvdata, 0x133, TMC_FFCR);
+	tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
 	__tmc_enable(drvdata);
 
 	TMC_LOCK(drvdata);
@@ -218,17 +400,30 @@
 	if (ret)
 		return ret;
 
+	mutex_lock(&drvdata->usb_lock);
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
+			drvdata->usbch = usb_qdss_open("qdss", drvdata,
+						       usb_notifier);
+			if (IS_ERR(drvdata->usbch)) {
+				dev_err(drvdata->dev, "usb_qdss_open failed\n");
+				ret = PTR_ERR(drvdata->usbch);
+				goto err0;
+			}
+		}
+	}
+
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
-		clk_disable_unprepare(drvdata->clk);
-		return -EBUSY;
+		ret = -EBUSY;
+		goto err1;
 	}
 
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		__tmc_etb_enable(drvdata);
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		__tmc_etr_enable(drvdata);
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
+			__tmc_etr_enable_to_mem(drvdata);
 	} else {
 		if (mode == TMC_MODE_CIRCULAR_BUFFER)
 			__tmc_etb_enable(drvdata);
@@ -237,9 +432,19 @@
 	}
 	drvdata->enable = true;
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	mutex_unlock(&drvdata->usb_lock);
 
 	dev_info(drvdata->dev, "TMC enabled\n");
 	return 0;
+err1:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
+			usb_qdss_close(drvdata->usbch);
+err0:
+	mutex_unlock(&drvdata->usb_lock);
+	clk_disable_unprepare(drvdata->clk);
+	return ret;
 }
 
 static int tmc_enable_sink(struct coresight_device *csdev)
@@ -306,12 +511,12 @@
 	rwphi = tmc_readl(drvdata, TMC_RWPHI);
 
 	if (BVAL(tmc_readl(drvdata, TMC_STS), 0))
-		drvdata->buf = drvdata->vaddr + rwp;
+		drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
 	else
 		drvdata->buf = drvdata->vaddr;
 }
 
-static void __tmc_etr_disable(struct tmc_drvdata *drvdata)
+static void __tmc_etr_disable_to_mem(struct tmc_drvdata *drvdata)
 {
 	TMC_UNLOCK(drvdata);
 
@@ -335,7 +540,9 @@
 static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
 {
 	unsigned long flags;
+	bool etr_bam_disable = false;
 
+	mutex_lock(&drvdata->usb_lock);
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading)
 		goto out;
@@ -343,7 +550,10 @@
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		__tmc_etb_disable(drvdata);
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		__tmc_etr_disable(drvdata);
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
+			__tmc_etr_disable_to_mem(drvdata);
+		else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
+			etr_bam_disable = true;
 	} else {
 		if (mode == TMC_MODE_CIRCULAR_BUFFER)
 			__tmc_etb_disable(drvdata);
@@ -354,6 +564,20 @@
 	drvdata->enable = false;
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
+	if (etr_bam_disable) {
+		if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+			if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
+				spin_lock_irqsave(&drvdata->spinlock, flags);
+				__tmc_etr_disable_to_bam(drvdata);
+				spin_unlock_irqrestore(&drvdata->spinlock,
+						       flags);
+				tmc_etr_bam_disable(drvdata);
+				usb_qdss_close(drvdata->usbch);
+			}
+		}
+	}
+	mutex_unlock(&drvdata->usb_lock);
+
 	clk_disable_unprepare(drvdata->clk);
 
 	dev_info(drvdata->dev, "TMC disabled\n");
@@ -387,7 +611,8 @@
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		__tmc_etb_disable(drvdata);
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		__tmc_etr_disable(drvdata);
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
+			__tmc_etr_disable_to_mem(drvdata);
 	} else {
 		mode = tmc_readl(drvdata, TMC_MODE);
 		if (mode == TMC_MODE_CIRCULAR_BUFFER)
@@ -442,7 +667,12 @@
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		__tmc_etb_disable(drvdata);
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		__tmc_etr_disable(drvdata);
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
+			__tmc_etr_disable_to_mem(drvdata);
+		} else {
+			ret = -ENODEV;
+			goto err;
+		}
 	} else {
 		mode = tmc_readl(drvdata, TMC_MODE);
 		if (mode == TMC_MODE_CIRCULAR_BUFFER) {
@@ -475,7 +705,8 @@
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		__tmc_etb_enable(drvdata);
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		__tmc_etr_enable(drvdata);
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
+			__tmc_etr_enable_to_mem(drvdata);
 	} else {
 		mode = tmc_readl(drvdata, TMC_MODE);
 		if (mode == TMC_MODE_CIRCULAR_BUFFER)
@@ -494,17 +725,23 @@
 						   struct tmc_drvdata, miscdev);
 	int ret = 0;
 
+	mutex_lock(&drvdata->read_lock);
 	if (drvdata->read_count++)
 		goto out;
 
 	ret = tmc_read_prepare(drvdata);
 	if (ret)
-		return ret;
+		goto err;
 out:
+	mutex_unlock(&drvdata->read_lock);
 	nonseekable_open(inode, file);
 
 	dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
 	return 0;
+err:
+	drvdata->read_count--;
+	mutex_unlock(&drvdata->read_lock);
+	return ret;
 }
 
 static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
@@ -520,6 +757,8 @@
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 		if (bufp == (char *)(drvdata->vaddr + drvdata->size))
 			bufp = drvdata->vaddr;
+		else if (bufp > (char *)(drvdata->vaddr + drvdata->size))
+			bufp -= drvdata->size;
 		if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size))
 			len = (char *)(drvdata->vaddr + drvdata->size) - bufp;
 	}
@@ -541,6 +780,7 @@
 	struct tmc_drvdata *drvdata = container_of(file->private_data,
 						   struct tmc_drvdata, miscdev);
 
+	mutex_lock(&drvdata->read_lock);
 	if (--drvdata->read_count) {
 		if (drvdata->read_count < 0) {
 			WARN_ONCE(1, "mismatched close\n");
@@ -551,6 +791,7 @@
 
 	tmc_read_unprepare(drvdata);
 out:
+	mutex_unlock(&drvdata->read_lock);
 	dev_dbg(drvdata->dev, "%s: released\n", __func__);
 	return 0;
 }
@@ -588,6 +829,87 @@
 static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, tmc_show_trigger_cntr,
 		   tmc_store_trigger_cntr);
 
+static ssize_t tmc_etr_show_out_mode(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+			 drvdata->out_mode == TMC_ETR_OUT_MODE_MEM ?
+			 "mem" : "usb");
+}
+
+static ssize_t tmc_etr_store_out_mode(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t size)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	char str[10] = "";
+	unsigned long flags;
+	bool etr_bam_flag = false;
+	int ret;
+
+	if (strlen(buf) >= 10)
+		return -EINVAL;
+	if (sscanf(buf, "%s", str) != 1)
+		return -EINVAL;
+
+	mutex_lock(&drvdata->usb_lock);
+	if (!strcmp(str, "mem")) {
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
+			goto out;
+
+		spin_lock_irqsave(&drvdata->spinlock, flags);
+		if (drvdata->enable) {
+			__tmc_etr_disable_to_bam(drvdata);
+			__tmc_etr_enable_to_mem(drvdata);
+			etr_bam_flag = true;
+		}
+		drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+		if (etr_bam_flag) {
+			tmc_etr_bam_disable(drvdata);
+			usb_qdss_close(drvdata->usbch);
+		}
+	} else if (!strcmp(str, "usb")) {
+		if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
+			goto out;
+
+		spin_lock_irqsave(&drvdata->spinlock, flags);
+		if (drvdata->enable) {
+			if (drvdata->reading) {
+				ret = -EBUSY;
+				goto err1;
+			}
+			__tmc_etr_disable_to_mem(drvdata);
+			etr_bam_flag = true;
+		}
+		drvdata->out_mode = TMC_ETR_OUT_MODE_USB;
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+		if (etr_bam_flag) {
+			drvdata->usbch = usb_qdss_open("qdss", drvdata,
+						       usb_notifier);
+			if (IS_ERR(drvdata->usbch)) {
+				dev_err(drvdata->dev, "usb_qdss_open failed\n");
+				ret = PTR_ERR(drvdata->usbch);
+				goto err0;
+			}
+		}
+	}
+out:
+	mutex_unlock(&drvdata->usb_lock);
+	return size;
+err1:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+err0:
+	mutex_unlock(&drvdata->usb_lock);
+	return ret;
+}
+static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tmc_etr_show_out_mode,
+		   tmc_etr_store_out_mode);
+
 static struct attribute *tmc_attrs[] = {
 	&dev_attr_trigger_cntr.attr,
 	NULL,
@@ -597,6 +919,15 @@
 	.attrs = tmc_attrs,
 };
 
+static struct attribute *tmc_etr_attrs[] = {
+	&dev_attr_out_mode.attr,
+	NULL,
+};
+
+static struct attribute_group tmc_etr_attr_grp = {
+	.attrs = tmc_etr_attrs,
+};
+
 static const struct attribute_group *tmc_etb_attr_grps[] = {
 	&tmc_attr_grp,
 	NULL,
@@ -604,6 +935,7 @@
 
 static const struct attribute_group *tmc_etr_attr_grps[] = {
 	&tmc_attr_grp,
+	&tmc_etr_attr_grp,
 	NULL,
 };
 
@@ -612,6 +944,46 @@
 	NULL,
 };
 
+static int __devinit tmc_etr_bam_init(struct platform_device *pdev,
+				      struct tmc_drvdata *drvdata)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct tmc_etr_bam_data *bamdata;
+
+	bamdata = devm_kzalloc(dev, sizeof(*bamdata), GFP_KERNEL);
+	if (!bamdata)
+		return -ENOMEM;
+	drvdata->bamdata = bamdata;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -ENODEV;
+
+	bamdata->props.phys_addr = res->start;
+	bamdata->props.virt_addr = devm_ioremap(dev, res->start,
+						resource_size(res));
+	if (!bamdata->props.virt_addr)
+		return -ENOMEM;
+	bamdata->props.virt_size = resource_size(res);
+
+	bamdata->props.event_threshold = 0x4; /* Pipe event threshold */
+	bamdata->props.summing_threshold = 0x10; /* BAM event threshold */
+	bamdata->props.irq = 0;
+	bamdata->props.num_pipes = TMC_ETR_BAM_NR_PIPES;
+
+	return sps_register_bam_device(&bamdata->props, &bamdata->handle);
+}
+
+static void tmc_etr_bam_exit(struct tmc_drvdata *drvdata)
+{
+	struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
+
+	if (!bamdata->handle)
+		return;
+	sps_deregister_bam_device(bamdata->handle);
+}
+
 static int __devinit tmc_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -620,6 +992,11 @@
 	struct coresight_platform_data *pdata;
 	struct tmc_drvdata *drvdata;
 	struct resource *res;
+	uint32_t reg_size;
+	static int etfetb_count;
+	static int count;
+	void *baddr;
+	struct msm_client_dump dump;
 	struct coresight_desc *desc;
 
 	if (pdev->dev.of_node) {
@@ -638,12 +1015,15 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
+	reg_size = resource_size(res);
 
 	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
 	if (!drvdata->base)
 		return -ENOMEM;
 
 	spin_lock_init(&drvdata->spinlock);
+	mutex_init(&drvdata->read_lock);
+	mutex_init(&drvdata->usb_lock);
 
 	drvdata->clk = devm_clk_get(dev, "core_clk");
 	if (IS_ERR(drvdata->clk))
@@ -663,7 +1043,8 @@
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
 		drvdata->size = SZ_1M;
 	else
-		drvdata->size = tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD;
+		drvdata->size = (tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD)
+				+ PAGE_SIZE;
 
 	clk_disable_unprepare(drvdata->clk);
 
@@ -679,16 +1060,50 @@
 			goto err0;
 		}
 		memset(drvdata->vaddr, 0, drvdata->size);
+		drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
+
+		ret = tmc_etr_bam_init(pdev, drvdata);
+		if (ret)
+			goto err0;
 	} else {
-		drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
-		if (!drvdata->buf)
+		baddr = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
+		if (!baddr)
 			return -ENOMEM;
+		drvdata->buf = baddr + PAGE_SIZE;
+		*(uint32_t *)(baddr + TMC_ETFETB_DUMP_VER_OFF) =
+							TMC_ETFETB_DUMP_VER;
+		dump.id = MSM_TMC_ETFETB + etfetb_count;
+		dump.start_addr = virt_to_phys(baddr);
+		dump.end_addr = dump.start_addr + drvdata->size;
+		ret = msm_dump_table_register(&dump);
+		/* Don't free the buffer in case of error since it can still
+		 * be used to provide dump collection via the device node
+		 */
+		if (ret)
+			dev_info(dev, "TMC ETF-ETB dump setup failed\n");
+		etfetb_count++;
 	}
 
+	baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
+	if (baddr) {
+		*(uint32_t *)(baddr + TMC_REG_DUMP_VER_OFF) = TMC_REG_DUMP_VER;
+		dump.id = MSM_TMC0_REG + count;
+		dump.start_addr = virt_to_phys(baddr);
+		dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
+		ret = msm_dump_table_register(&dump);
+		if (ret) {
+			devm_kfree(dev, baddr);
+			dev_info(dev, "TMC REG dump setup failed\n");
+		}
+	} else {
+		dev_info(dev, "TMC REG dump space allocation failed\n");
+	}
+	count++;
+
 	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
 	if (!desc) {
 		ret = -ENOMEM;
-		goto err0;
+		goto err1;
 	}
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		desc->type = CORESIGHT_DEV_TYPE_SINK;
@@ -701,7 +1116,7 @@
 		drvdata->csdev = coresight_register(desc);
 		if (IS_ERR(drvdata->csdev)) {
 			ret = PTR_ERR(drvdata->csdev);
-			goto err0;
+			goto err1;
 		}
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 		desc->type = CORESIGHT_DEV_TYPE_SINK;
@@ -714,7 +1129,7 @@
 		drvdata->csdev = coresight_register(desc);
 		if (IS_ERR(drvdata->csdev)) {
 			ret = PTR_ERR(drvdata->csdev);
-			goto err0;
+			goto err1;
 		}
 	} else {
 		desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
@@ -728,7 +1143,7 @@
 		drvdata->csdev = coresight_register(desc);
 		if (IS_ERR(drvdata->csdev)) {
 			ret = PTR_ERR(drvdata->csdev);
-			goto err0;
+			goto err1;
 		}
 	}
 
@@ -738,12 +1153,14 @@
 	drvdata->miscdev.fops = &tmc_fops;
 	ret = misc_register(&drvdata->miscdev);
 	if (ret)
-		goto err1;
+		goto err2;
 
 	dev_info(dev, "TMC initialized\n");
 	return 0;
-err1:
+err2:
 	coresight_unregister(drvdata->csdev);
+err1:
+	tmc_etr_bam_exit(drvdata);
 err0:
 	free_contiguous_memory_by_paddr(drvdata->paddr);
 	return ret;
@@ -755,6 +1172,7 @@
 
 	misc_deregister(&drvdata->miscdev);
 	coresight_unregister(drvdata->csdev);
+	tmc_etr_bam_exit(drvdata);
 	free_contiguous_memory_by_paddr(drvdata->paddr);
 	return 0;
 }
@@ -763,6 +1181,7 @@
 	{.compatible = "arm,coresight-tmc"},
 	{}
 };
+EXPORT_COMPAT("arm,coresight-tmc");
 
 static struct platform_driver tmc_driver = {
 	.probe          = tmc_probe,
diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c
index f76d303..cccb5a7 100644
--- a/drivers/coresight/coresight.c
+++ b/drivers/coresight/coresight.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -496,6 +496,9 @@
 
 static struct device_type coresight_dev_type[] = {
 	{
+		.name = "none",
+	},
+	{
 		.name = "sink",
 		.groups = coresight_attr_grps_sink,
 	},
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 4ccd89d..de5f10f 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -66,6 +66,7 @@
 	struct clk *ce_core_src_clk;	/* Handle to CE src clk*/
 	struct clk *ce_core_clk;	/* Handle to CE clk */
 	struct clk *ce_clk;		/* Handle to CE clk */
+	struct clk *ce_bus_clk;	/* Handle to CE AXI clk*/
 
 	qce_comp_func_ptr_t qce_cb;	/* qce callback function pointer */
 
@@ -647,6 +648,21 @@
 	return 0;
 };
 
+static int _qce_unlock_other_pipes(struct qce_device *pce_dev)
+{
+	int rc = 0;
+
+	pce_dev->ce_sps.consumer.event.callback = NULL;
+	rc = sps_transfer_one(pce_dev->ce_sps.consumer.pipe,
+	GET_PHYS_ADDR(pce_dev->ce_sps.cmdlistptr.unlock_all_pipes.cmdlist),
+	0, NULL, (SPS_IOVEC_FLAG_CMD | SPS_IOVEC_FLAG_UNLOCK));
+	if (rc) {
+		pr_err("sps_xfr_one() fail rc=%d", rc);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
 static int _aead_complete(struct qce_device *pce_dev)
 {
 	struct aead_request *areq;
@@ -665,6 +681,9 @@
 	/* check MAC */
 	memcpy(mac, (char *)(&pce_dev->ce_sps.result->auth_iv[0]),
 						SHA256_DIGEST_SIZE);
+	if (_qce_unlock_other_pipes(pce_dev))
+		return -EINVAL;
+
 	if (pce_dev->mode == QCE_MODE_CCM) {
 		uint32_t result_status;
 		result_status = pce_dev->ce_sps.result->status;
@@ -690,7 +709,7 @@
 	return 0;
 };
 
-static void _sha_complete(struct qce_device *pce_dev)
+static int _sha_complete(struct qce_device *pce_dev)
 {
 	struct ahash_request *areq;
 	unsigned char digest[SHA256_DIGEST_SIZE];
@@ -700,9 +719,12 @@
 				DMA_TO_DEVICE);
 	memcpy(digest, (char *)(&pce_dev->ce_sps.result->auth_iv[0]),
 						SHA256_DIGEST_SIZE);
+	if (_qce_unlock_other_pipes(pce_dev))
+		return -EINVAL;
 	pce_dev->qce_cb(areq, digest,
 			(char *)pce_dev->ce_sps.result->auth_byte_count,
 				pce_dev->ce_sps.consumer_status);
+	return 0;
 };
 
 static int _ablk_cipher_complete(struct qce_device *pce_dev)
@@ -719,6 +741,8 @@
 	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))
+		return -EINVAL;
 
 	if (pce_dev->mode == QCE_MODE_ECB) {
 		pce_dev->qce_cb(areq, NULL, NULL,
@@ -760,7 +784,7 @@
 {
 	int i, j, ents;
 	struct sps_iovec *iovec = pce_dev->ce_sps.in_transfer.iovec;
-	uint32_t cmd_flags = SPS_IOVEC_FLAG_CMD | SPS_IOVEC_FLAG_NWD;
+	uint32_t cmd_flags = SPS_IOVEC_FLAG_CMD;
 
 	printk(KERN_INFO "==============================================\n");
 	printk(KERN_INFO "CONSUMER (TX/IN/DEST) PIPE DESCRIPTOR\n");
@@ -806,11 +830,11 @@
 	pce_dev->ce_sps.out_transfer.iovec_count = 0;
 }
 
-static void _qce_set_eot_flag(struct sps_transfer *sps_bam_pipe)
+static void _qce_set_flag(struct sps_transfer *sps_bam_pipe, uint32_t flag)
 {
 	struct sps_iovec *iovec = sps_bam_pipe->iovec +
 					(sps_bam_pipe->iovec_count - 1);
-	iovec->flags |= SPS_IOVEC_FLAG_EOT;
+	iovec->flags |= flag;
 }
 
 static void _qce_sps_add_data(uint32_t addr, uint32_t len,
@@ -870,7 +894,7 @@
 					sps_bam_pipe->iovec_count;
 	iovec->size = cmdptr->size;
 	iovec->addr = GET_PHYS_ADDR(cmdptr->cmdlist);
-	iovec->flags = SPS_IOVEC_FLAG_CMD | SPS_IOVEC_FLAG_NWD | flag;
+	iovec->flags = SPS_IOVEC_FLAG_CMD | flag;
 	sps_bam_pipe->iovec_count++;
 
 	return 0;
@@ -959,7 +983,7 @@
 		/* Producer pipe will handle this connection */
 		sps_connect_info->mode = SPS_MODE_SRC;
 		sps_connect_info->options =
-			SPS_O_AUTO_ENABLE | SPS_O_EOT;
+			SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_DESC_DONE;
 	} else {
 		/* For CE consumer transfer, source should be
 		 * system memory where as destination should
@@ -976,6 +1000,8 @@
 	sps_connect_info->src_pipe_index = pce_dev->ce_sps.src_pipe_index;
 	/* Consumer pipe index */
 	sps_connect_info->dest_pipe_index = pce_dev->ce_sps.dest_pipe_index;
+	/* Set pipe group */
+	sps_connect_info->lock_group = pce_dev->ce_sps.pipe_pair_index;
 	sps_connect_info->event_thresh = 0x10;
 	/*
 	 * Max. no of scatter/gather buffers that can
@@ -1009,7 +1035,10 @@
 	}
 
 	sps_event->mode = SPS_TRIGGER_CALLBACK;
-	sps_event->options = SPS_O_EOT;
+	if (is_producer)
+		sps_event->options = SPS_O_EOT | SPS_O_DESC_DONE;
+	else
+		sps_event->options = SPS_O_EOT;
 	sps_event->xfer_done = NULL;
 	sps_event->user = (void *)pce_dev;
 
@@ -1093,6 +1122,7 @@
 	/* SPS driver wll handle the crypto BAM IRQ */
 	bam.irq = (u32)pce_dev->ce_sps.bam_irq;
 	bam.manage = SPS_BAM_MGR_LOCAL;
+	bam.ee = 1;
 
 	pr_debug("bam physical base=0x%x\n", (u32)bam.phys_addr);
 	pr_debug("bam virtual base=0x%x\n", (u32)bam.virt_addr);
@@ -1178,15 +1208,8 @@
 			notify->data.transfer.iovec.addr,
 			notify->data.transfer.iovec.size,
 			notify->data.transfer.iovec.flags);
-
-	pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
-	if (pce_dev->ce_sps.consumer_state == QCE_PIPE_STATE_COMP) {
-		pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_IDLE;
-		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
-
-		/* done */
-		_aead_complete(pce_dev);
-	}
+	/* done */
+	_aead_complete(pce_dev);
 };
 
 static void _aead_sps_consumer_callback(struct sps_event_notify *notify)
@@ -1200,15 +1223,6 @@
 			notify->data.transfer.iovec.addr,
 			notify->data.transfer.iovec.size,
 			notify->data.transfer.iovec.flags);
-
-	pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_COMP;
-	if (pce_dev->ce_sps.producer_state == QCE_PIPE_STATE_COMP) {
-		pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_IDLE;
-		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
-
-		/* done */
-		_aead_complete(pce_dev);
-	}
 };
 
 static void _sha_sps_producer_callback(struct sps_event_notify *notify)
@@ -1222,15 +1236,8 @@
 			notify->data.transfer.iovec.addr,
 			notify->data.transfer.iovec.size,
 			notify->data.transfer.iovec.flags);
-
-	pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
-	if (pce_dev->ce_sps.consumer_state == QCE_PIPE_STATE_COMP) {
-		pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_IDLE;
-		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
-
-		/* done */
-		_sha_complete(pce_dev);
-	}
+	/* done */
+	_sha_complete(pce_dev);
 };
 
 static void _sha_sps_consumer_callback(struct sps_event_notify *notify)
@@ -1244,15 +1251,6 @@
 			notify->data.transfer.iovec.addr,
 			notify->data.transfer.iovec.size,
 			notify->data.transfer.iovec.flags);
-
-	pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_COMP;
-	if (pce_dev->ce_sps.producer_state == QCE_PIPE_STATE_COMP) {
-		pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_IDLE;
-		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
-
-		/* done */
-	_sha_complete(pce_dev);
-	}
 };
 
 static void _ablk_cipher_sps_producer_callback(struct sps_event_notify *notify)
@@ -1266,15 +1264,8 @@
 			notify->data.transfer.iovec.addr,
 			notify->data.transfer.iovec.size,
 			notify->data.transfer.iovec.flags);
-
-	pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
-	if (pce_dev->ce_sps.consumer_state == QCE_PIPE_STATE_COMP) {
-		pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_IDLE;
-		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
-
-		/* done */
-		_ablk_cipher_complete(pce_dev);
-	}
+	/* done */
+	_ablk_cipher_complete(pce_dev);
 };
 
 static void _ablk_cipher_sps_consumer_callback(struct sps_event_notify *notify)
@@ -1288,15 +1279,6 @@
 			notify->data.transfer.iovec.addr,
 			notify->data.transfer.iovec.size,
 			notify->data.transfer.iovec.flags);
-
-	pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_COMP;
-	if (pce_dev->ce_sps.producer_state == QCE_PIPE_STATE_COMP) {
-		pce_dev->ce_sps.consumer_state = QCE_PIPE_STATE_IDLE;
-		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
-
-		/* done */
-		_ablk_cipher_complete(pce_dev);
-	}
 };
 
 static void qce_add_cmd_element(struct qce_device *pdev,
@@ -1315,9 +1297,8 @@
 		unsigned char **pvaddr, enum qce_cipher_mode_enum mode,
 		bool key_128)
 {
-	struct sps_command_element *ce_vaddr =
-				(struct sps_command_element *)(*pvaddr);
-	uint32_t ce_vaddr_start = (uint32_t)(*pvaddr);
+	struct sps_command_element *ce_vaddr;
+	uint32_t ce_vaddr_start;
 	struct qce_cmdlistptr_ops *cmdlistptr = &pdev->ce_sps.cmdlistptr;
 	struct qce_cmdlist_info *pcl_info = NULL;
 	int i = 0;
@@ -1329,6 +1310,10 @@
 	uint32_t beats = (pdev->ce_sps.ce_burst_size >> 3) - 1;
 	uint32_t pipe_pair = pdev->ce_sps.pipe_pair_index;
 
+	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
+					pdev->ce_sps.ce_burst_size);
+	ce_vaddr = (struct sps_command_element *)(*pvaddr);
+	ce_vaddr_start = (uint32_t)(*pvaddr);
 	crypto_cfg = (beats << CRYPTO_REQ_SIZE) |
 			BIT(CRYPTO_MASK_DOUT_INTR) |
 			BIT(CRYPTO_MASK_DIN_INTR) |
@@ -1480,10 +1465,16 @@
 						0, &pcl_info->auth_seg_size);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
 						0, &pcl_info->auth_seg_size);
+	} else {
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
+						0, &pcl_info->auth_seg_size);
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
+						0, &pcl_info->auth_seg_size);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_START_REG,
 						0, &pcl_info->auth_seg_size);
-
 	}
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+				(crypto_cfg | CRYPTO_LITTLE_ENDIAN_MASK), NULL);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
 			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
@@ -1500,9 +1491,8 @@
 		bool mode_cbc)
 {
 
-	struct sps_command_element *ce_vaddr =
-				(struct sps_command_element *)(*pvaddr);
-	uint32_t ce_vaddr_start = (uint32_t)(*pvaddr);
+	struct sps_command_element *ce_vaddr;
+	uint32_t ce_vaddr_start;
 	struct qce_cmdlistptr_ops *cmdlistptr = &pdev->ce_sps.cmdlistptr;
 	struct qce_cmdlist_info *pcl_info = NULL;
 	int i = 0;
@@ -1513,6 +1503,10 @@
 	uint32_t beats = (pdev->ce_sps.ce_burst_size >> 3) - 1;
 	uint32_t pipe_pair = pdev->ce_sps.pipe_pair_index;
 
+	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
+					pdev->ce_sps.ce_burst_size);
+	ce_vaddr = (struct sps_command_element *)(*pvaddr);
+	ce_vaddr_start = (uint32_t)(*pvaddr);
 	crypto_cfg = (beats << CRYPTO_REQ_SIZE) |
 			BIT(CRYPTO_MASK_DOUT_INTR) |
 			BIT(CRYPTO_MASK_DIN_INTR) |
@@ -1613,9 +1607,6 @@
 						&pcl_info->encr_cntr_iv);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CNTR1_IV1_REG, 0,
 								NULL);
-		/* Add 2 dummy to  align size to burst-size multiple */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CNTR2_IV2_REG, 0,
-								NULL);
 	}
 	/* Add dummy to  align size to burst-size multiple */
 	if (!mode_cbc) {
@@ -1623,10 +1614,17 @@
 						0, &pcl_info->auth_seg_size);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
 						0, &pcl_info->auth_seg_size);
+	} else {
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
+						0, &pcl_info->auth_seg_size);
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
+						0, &pcl_info->auth_seg_size);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_START_REG,
 						0, &pcl_info->auth_seg_size);
-
 	}
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+			(crypto_cfg | CRYPTO_LITTLE_ENDIAN_MASK),
+			NULL);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
 			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
@@ -1642,9 +1640,8 @@
 		unsigned char **pvaddr, enum qce_hash_alg_enum alg,
 		bool key_128)
 {
-	struct sps_command_element *ce_vaddr =
-			(struct sps_command_element *)(*pvaddr);
-	uint32_t ce_vaddr_start = (uint32_t)(*pvaddr);
+	struct sps_command_element *ce_vaddr;
+	uint32_t ce_vaddr_start;
 	struct qce_cmdlistptr_ops *cmdlistptr = &pdev->ce_sps.cmdlistptr;
 	struct qce_cmdlist_info *pcl_info = NULL;
 	int i = 0;
@@ -1655,6 +1652,10 @@
 	uint32_t beats = (pdev->ce_sps.ce_burst_size >> 3) - 1;
 	uint32_t pipe_pair = pdev->ce_sps.pipe_pair_index;
 
+	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
+					pdev->ce_sps.ce_burst_size);
+	ce_vaddr_start = (uint32_t)(*pvaddr);
+	ce_vaddr = (struct sps_command_element *)(*pvaddr);
 	crypto_cfg = (beats << CRYPTO_REQ_SIZE) |
 			BIT(CRYPTO_MASK_DOUT_INTR) |
 			BIT(CRYPTO_MASK_DIN_INTR) |
@@ -1678,9 +1679,6 @@
 		iv_reg = 5;
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 					crypto_cfg, &pcl_info->crypto_cfg);
-		/* 1 dummy write */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
-								0, NULL);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
 							0, NULL);
 
@@ -1696,9 +1694,7 @@
 		iv_reg = 8;
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 					crypto_cfg, &pcl_info->crypto_cfg);
-		/* 2 dummy writes */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
-								0, NULL);
+		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
@@ -1716,9 +1712,6 @@
 		iv_reg = 5;
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 					crypto_cfg, &pcl_info->crypto_cfg);
-		/* 1 dummy write */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
-								0, NULL);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
 							0, NULL);
 	break;
@@ -1736,9 +1729,7 @@
 		iv_reg = 5;
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 					crypto_cfg, &pcl_info->crypto_cfg);
-		/* 2 dummy writes */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
-								0, NULL);
+		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
@@ -1757,9 +1748,7 @@
 
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 					crypto_cfg, &pcl_info->crypto_cfg);
-		/* 2 dummy writes */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
-								0, NULL);
+		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
@@ -1797,9 +1786,7 @@
 		}
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 					crypto_cfg, &pcl_info->crypto_cfg);
-		/* 2 dummy writes */
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
-								0, NULL);
+		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
@@ -1852,6 +1839,10 @@
 				(CRYPTO_AUTH_KEY0_REG + i*sizeof(uint32_t)),
 				0, NULL);
 	}
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+			(crypto_cfg | CRYPTO_LITTLE_ENDIAN_MASK),
+			NULL);
+
 	if (alg != QCE_AEAD_SHA1_HMAC)
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
 			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
@@ -1866,9 +1857,8 @@
 static int _setup_aead_cmdlistptrs(struct qce_device *pdev,
 				unsigned char **pvaddr, bool key_128)
 {
-	struct sps_command_element *ce_vaddr =
-				(struct sps_command_element *)(*pvaddr);
-	uint32_t ce_vaddr_start = (uint32_t)(*pvaddr);
+	struct sps_command_element *ce_vaddr;
+	uint32_t ce_vaddr_start;
 	struct qce_cmdlistptr_ops *cmdlistptr = &pdev->ce_sps.cmdlistptr;
 	struct qce_cmdlist_info *pcl_info = NULL;
 	int i = 0;
@@ -1879,6 +1869,10 @@
 	uint32_t beats = (pdev->ce_sps.ce_burst_size >> 3) - 1;
 	uint32_t pipe_pair = pdev->ce_sps.pipe_pair_index;
 
+	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
+					pdev->ce_sps.ce_burst_size);
+	ce_vaddr_start = (uint32_t)(*pvaddr);
+	ce_vaddr = (struct sps_command_element *)(*pvaddr);
 	crypto_cfg = (beats << CRYPTO_REQ_SIZE) |
 			BIT(CRYPTO_MASK_DOUT_INTR) |
 			BIT(CRYPTO_MASK_DIN_INTR) |
@@ -1927,8 +1921,6 @@
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_START_REG, 0,
 									NULL);
-	/* add 1 dummy */
-	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_SEG_SIZE_REG, 0,
 						&pcl_info->seg_size);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG,
@@ -1992,6 +1984,10 @@
 			(CRYPTO_ENCR_CCM_INT_CNTR0_REG + i * sizeof(uint32_t)),
 			0, NULL);
 
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+			(crypto_cfg | CRYPTO_LITTLE_ENDIAN_MASK),
+			NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
 			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
 			&pcl_info->go_proc);
@@ -2005,12 +2001,14 @@
 static int _setup_unlock_pipe_cmdlistptrs(struct qce_device *pdev,
 		unsigned char **pvaddr)
 {
-	struct sps_command_element *ce_vaddr =
-			(struct sps_command_element *)(*pvaddr);
+	struct sps_command_element *ce_vaddr;
 	uint32_t ce_vaddr_start = (uint32_t)(*pvaddr);
 	struct qce_cmdlistptr_ops *cmdlistptr = &pdev->ce_sps.cmdlistptr;
 	struct qce_cmdlist_info *pcl_info = NULL;
 
+	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
+					pdev->ce_sps.ce_burst_size);
+	ce_vaddr = (struct sps_command_element *)(*pvaddr);
 	cmdlistptr->unlock_all_pipes.cmdlist = (uint32_t)ce_vaddr;
 	pcl_info = &(cmdlistptr->unlock_all_pipes);
 
@@ -2020,12 +2018,6 @@
 	 */
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 					CRYPTO_CONFIG_RESET, NULL);
-	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					CRYPTO_CONFIG_RESET, NULL);
-	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					CRYPTO_CONFIG_RESET, NULL);
-	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					CRYPTO_CONFIG_RESET, NULL);
 	pcl_info->size = (uint32_t)ce_vaddr - (uint32_t)ce_vaddr_start;
 	*pvaddr = (unsigned char *) ce_vaddr;
 
@@ -2044,7 +2036,7 @@
 	 */
 	ce_vaddr =
 		(struct sps_command_element *) ALIGN(((unsigned int) ce_vaddr),
-									16);
+					pdev->ce_sps.ce_burst_size);
 	*pvaddr = (unsigned char *) ce_vaddr;
 
 	_setup_cipher_aes_cmdlistptrs(pdev, pvaddr, QCE_MODE_CBC, true);
@@ -2084,8 +2076,8 @@
 	unsigned char *vaddr;
 
 	vaddr = pce_dev->coh_vmem;
-	vaddr = (unsigned char *) ALIGN(((unsigned int)vaddr),  16);
-
+	vaddr = (unsigned char *) ALIGN(((unsigned int)vaddr),
+					pce_dev->ce_sps.ce_burst_size);
 	/* Allow for 256 descriptor (cmd and data) entries per pipe */
 	pce_dev->ce_sps.in_transfer.iovec = (struct sps_iovec *)vaddr;
 	pce_dev->ce_sps.in_transfer.iovec_phys =
@@ -2098,6 +2090,8 @@
 	vaddr += MAX_BAM_DESCRIPTORS * 8;
 
 	qce_setup_cmdlistptrs(pce_dev, &vaddr);
+	vaddr = (unsigned char *) ALIGN(((unsigned int)vaddr),
+					pce_dev->ce_sps.ce_burst_size);
 	pce_dev->ce_sps.result_dump = (uint32_t)vaddr;
 	pce_dev->ce_sps.result = (struct ce_result_dump_format *)vaddr;
 	vaddr += 128;
@@ -2235,20 +2229,24 @@
 
 	_qce_sps_iovec_count_init(pce_dev);
 
-	_qce_sps_add_cmd(pce_dev, 0, cmdlistinfo,
+	_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
 					&pce_dev->ce_sps.in_transfer);
 
 	if (pce_dev->ce_sps.minor_version == 0) {
 		_qce_sps_add_sg_data(pce_dev, areq->src, totallen_in,
 					&pce_dev->ce_sps.in_transfer);
 
-		_qce_set_eot_flag(&pce_dev->ce_sps.in_transfer);
+		_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
+
 		_qce_sps_add_sg_data(pce_dev, areq->dst, out_len +
 					areq->assoclen + hw_pad_out,
 				&pce_dev->ce_sps.out_transfer);
 		_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
 					CRYPTO_RESULT_DUMP_SIZE,
 					&pce_dev->ce_sps.out_transfer);
+		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+					SPS_IOVEC_FLAG_INT);
 	} else {
 		_qce_sps_add_sg_data(pce_dev, areq->assoc, areq->assoclen,
 					 &pce_dev->ce_sps.in_transfer);
@@ -2256,7 +2254,8 @@
 					&pce_dev->ce_sps.in_transfer);
 		_qce_sps_add_sg_data(pce_dev, areq->src, areq->cryptlen,
 					&pce_dev->ce_sps.in_transfer);
-		_qce_set_eot_flag(&pce_dev->ce_sps.in_transfer);
+		_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
 
 		/* Pass through to ignore associated (+iv, if applicable) data*/
 		_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.ignore_buffer),
@@ -2270,6 +2269,8 @@
 
 		_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
 			CRYPTO_RESULT_DUMP_SIZE, &pce_dev->ce_sps.out_transfer);
+		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+					SPS_IOVEC_FLAG_INT);
 	}
 	rc = _qce_sps_transfer(pce_dev);
 	if (rc)
@@ -2356,17 +2357,19 @@
 
 	_qce_sps_iovec_count_init(pce_dev);
 
-	_qce_sps_add_cmd(pce_dev, 0, cmdlistinfo,
+	_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
 					&pce_dev->ce_sps.in_transfer);
 	_qce_sps_add_sg_data(pce_dev, areq->src, areq->nbytes,
 					&pce_dev->ce_sps.in_transfer);
-	_qce_set_eot_flag(&pce_dev->ce_sps.in_transfer);
+	_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
 
 	_qce_sps_add_sg_data(pce_dev, areq->dst, areq->nbytes,
 					&pce_dev->ce_sps.out_transfer);
 	_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
 					CRYPTO_RESULT_DUMP_SIZE,
 					  &pce_dev->ce_sps.out_transfer);
+	_qce_set_flag(&pce_dev->ce_sps.out_transfer, SPS_IOVEC_FLAG_INT);
 	rc = _qce_sps_transfer(pce_dev);
 	if (rc)
 		goto bad;
@@ -2425,15 +2428,17 @@
 
 	_qce_sps_iovec_count_init(pce_dev);
 
-	_qce_sps_add_cmd(pce_dev, 0, cmdlistinfo,
+	_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
 					&pce_dev->ce_sps.in_transfer);
 	_qce_sps_add_sg_data(pce_dev, areq->src, areq->nbytes,
 						 &pce_dev->ce_sps.in_transfer);
-	_qce_set_eot_flag(&pce_dev->ce_sps.in_transfer);
+	_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
 
 	_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
 					CRYPTO_RESULT_DUMP_SIZE,
 					  &pce_dev->ce_sps.out_transfer);
+	_qce_set_flag(&pce_dev->ce_sps.out_transfer, SPS_IOVEC_FLAG_INT);
 	rc = _qce_sps_transfer(pce_dev);
 	if (rc)
 		goto bad;
@@ -2527,6 +2532,7 @@
 	struct clk *ce_core_clk;
 	struct clk *ce_clk;
 	struct clk *ce_core_src_clk;
+	struct clk *ce_bus_clk;
 
 	/* Get CE3 src core clk. */
 	ce_core_src_clk = clk_get(pce_dev->pdev, "core_clk_src");
@@ -2568,6 +2574,19 @@
 	}
 	pce_dev->ce_clk = ce_clk;
 
+	/* Get CE AXI clk */
+	ce_bus_clk = clk_get(pce_dev->pdev, "bus_clk");
+	if (IS_ERR(ce_bus_clk)) {
+		rc = PTR_ERR(ce_bus_clk);
+		pr_err("Unable to get CE BUS interface clk\n");
+		if (pce_dev->ce_core_src_clk != NULL)
+			clk_put(pce_dev->ce_core_src_clk);
+		clk_put(pce_dev->ce_core_clk);
+		clk_put(pce_dev->ce_clk);
+		goto err_clk;
+	}
+	pce_dev->ce_bus_clk = ce_bus_clk;
+
 	/* Enable CE core clk */
 	rc = clk_prepare_enable(pce_dev->ce_core_clk);
 	if (rc) {
@@ -2589,6 +2608,18 @@
 			clk_put(pce_dev->ce_clk);
 			goto err_clk;
 		}
+		/* Enable AXI clk */
+		rc = clk_prepare_enable(pce_dev->ce_bus_clk);
+		if (rc) {
+			pr_err("Unable to enable/prepare CE BUS clk\n");
+			clk_disable_unprepare(pce_dev->ce_core_clk);
+			if (pce_dev->ce_core_src_clk != NULL)
+				clk_put(pce_dev->ce_core_src_clk);
+			clk_put(pce_dev->ce_core_clk);
+			clk_put(pce_dev->ce_clk);
+			clk_put(pce_dev->ce_bus_clk);
+			goto err_clk;
+		}
 	}
 err_clk:
 	if (rc)
@@ -2680,10 +2711,12 @@
 
 	clk_disable_unprepare(pce_dev->ce_clk);
 	clk_disable_unprepare(pce_dev->ce_core_clk);
+	clk_disable_unprepare(pce_dev->ce_bus_clk);
 	if (pce_dev->ce_core_src_clk != NULL)
 		clk_put(pce_dev->ce_core_src_clk);
 	clk_put(pce_dev->ce_clk);
 	clk_put(pce_dev->ce_core_clk);
+	clk_put(pce_dev->ce_bus_clk);
 
 	qce_sps_exit(pce_dev);
 	kfree(handle);
diff --git a/drivers/crypto/msm/qcryptohw_50.h b/drivers/crypto/msm/qcryptohw_50.h
index 898109e..1c904ed 100644
--- a/drivers/crypto/msm/qcryptohw_50.h
+++ b/drivers/crypto/msm/qcryptohw_50.h
@@ -345,6 +345,7 @@
 #define CRYPTO_IRQ_ENABLES_MASK			(0xF << CRYPTO_IRQ_ENABLES)
 
 #define CRYPTO_LITTLE_ENDIAN_MODE		9
+#define CRYPTO_LITTLE_ENDIAN_MASK		(1 << CRYPTO_LITTLE_ENDIAN_MODE)
 #define CRYPTO_PIPE_SET_SELECT			5 /* bit 8-5 */
 #define CRYPTO_PIPE_SET_SELECT_MASK		(0xF << CRYPTO_PIPE_SET_SELECT)
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 03fdc5a..c799c1f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -556,7 +556,6 @@
 	  PMICs through RPC.
 
 config GPIO_QPNP_PIN
-	depends on ARCH_MSM8974
 	depends on SPMI
 	depends on OF_SPMI
 	depends on MSM_QPNP_INT
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 4fe1f01..7f760ed 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -33,6 +33,7 @@
 #include <linux/uaccess.h>
 #include <linux/debugfs.h>
 #include <linux/dma-buf.h>
+#include <linux/msm_ion.h>
 
 #include <mach/iommu_domains.h>
 #include "ion_priv.h"
@@ -330,8 +331,6 @@
 	struct ion_client *client = handle->client;
 	struct ion_buffer *buffer = handle->buffer;
 
-	mutex_lock(&client->lock);
-
 	mutex_lock(&buffer->lock);
 	while (handle->kmap_cnt)
 		ion_handle_kmap_put(handle);
@@ -339,7 +338,6 @@
 
 	if (!RB_EMPTY_NODE(&handle->node))
 		rb_erase(&handle->node, &client->handles);
-	mutex_unlock(&client->lock);
 
 	ion_buffer_put(buffer);
 	kfree(handle);
@@ -514,8 +512,8 @@
 		WARN(1, "%s: invalid handle passed to free.\n", __func__);
 		return;
 	}
-	mutex_unlock(&client->lock);
 	ion_handle_put(handle);
+	mutex_unlock(&client->lock);
 }
 EXPORT_SYMBOL(ion_free);
 
@@ -704,6 +702,8 @@
 
 			if (iommu_map->flags & ION_IOMMU_UNMAP_DELAYED)
 				kref_get(&iommu_map->ref);
+		} else {
+			ret = PTR_ERR(iommu_map);
 		}
 	} else {
 		if (iommu_map->flags != iommu_flags) {
@@ -822,31 +822,6 @@
 }
 EXPORT_SYMBOL(ion_unmap_kernel);
 
-static int check_vaddr_bounds(unsigned long start, unsigned long end)
-{
-	struct mm_struct *mm = current->active_mm;
-	struct vm_area_struct *vma;
-	int ret = 1;
-
-	if (end < start)
-		goto out;
-
-	down_read(&mm->mmap_sem);
-	vma = find_vma(mm, start);
-	if (vma && vma->vm_start < end) {
-		if (start < vma->vm_start)
-			goto out_up;
-		if (end > vma->vm_end)
-			goto out_up;
-		ret = 0;
-	}
-
-out_up:
-	up_read(&mm->mmap_sem);
-out:
-	return ret;
-}
-
 int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
 			void *uaddr, unsigned long offset, unsigned long len,
 			unsigned int cmd)
@@ -1416,8 +1391,10 @@
 				   sizeof(struct ion_fd_data)))
 			return -EFAULT;
 		data.handle = ion_import_dma_buf(client, data.fd);
-		if (IS_ERR(data.handle))
+		if (IS_ERR(data.handle)) {
+			ret = PTR_ERR(data.handle);
 			data.handle = NULL;
+		}
 		if (copy_to_user((void __user *)arg, &data,
 				 sizeof(struct ion_fd_data)))
 			return -EFAULT;
@@ -1438,65 +1415,17 @@
 		return dev->custom_ioctl(client, data.cmd, data.arg);
 	}
 	case ION_IOC_CLEAN_CACHES:
+		return client->dev->custom_ioctl(client,
+						ION_IOC_CLEAN_CACHES, arg);
 	case ION_IOC_INV_CACHES:
+		return client->dev->custom_ioctl(client,
+						ION_IOC_INV_CACHES, arg);
 	case ION_IOC_CLEAN_INV_CACHES:
-	{
-		struct ion_flush_data data;
-		unsigned long start, end;
-		struct ion_handle *handle = NULL;
-		int ret;
-
-		if (copy_from_user(&data, (void __user *)arg,
-				sizeof(struct ion_flush_data)))
-			return -EFAULT;
-
-		start = (unsigned long) data.vaddr;
-		end = (unsigned long) data.vaddr + data.length;
-
-		if (check_vaddr_bounds(start, end)) {
-			pr_err("%s: virtual address %p is out of bounds\n",
-				__func__, data.vaddr);
-			return -EINVAL;
-		}
-
-		if (!data.handle) {
-			handle = ion_import_dma_buf(client, data.fd);
-			if (IS_ERR(handle)) {
-				pr_info("%s: Could not import handle: %d\n",
-					__func__, (int)handle);
-				return -EINVAL;
-			}
-		}
-
-		ret = ion_do_cache_op(client,
-					data.handle ? data.handle : handle,
-					data.vaddr, data.offset, data.length,
-					cmd);
-
-		if (!data.handle)
-			ion_free(client, handle);
-
-		if (ret < 0)
-			return ret;
-		break;
-
-	}
+		return client->dev->custom_ioctl(client,
+						ION_IOC_CLEAN_INV_CACHES, arg);
 	case ION_IOC_GET_FLAGS:
-	{
-		struct ion_flag_data data;
-		int ret;
-		if (copy_from_user(&data, (void __user *)arg,
-				   sizeof(struct ion_flag_data)))
-			return -EFAULT;
-
-		ret = ion_handle_get_flags(client, data.handle, &data.flags);
-		if (ret < 0)
-			return ret;
-		if (copy_to_user((void __user *)arg, &data,
-				 sizeof(struct ion_flag_data)))
-			return -EFAULT;
-		break;
-	}
+		return client->dev->custom_ioctl(client,
+						ION_IOC_GET_FLAGS, arg);
 	default:
 		return -ENOTTY;
 	}
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index a591eb4..7d7ea36 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -31,6 +31,7 @@
 #include <mach/iommu_domains.h>
 #include <asm/mach/map.h>
 #include <asm/cacheflush.h>
+#include <linux/msm_ion.h>
 
 struct ion_carveout_heap {
 	struct ion_heap heap;
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 23ccab3..9f33859 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -19,7 +19,7 @@
 #include <linux/err.h>
 #include <linux/genalloc.h>
 #include <linux/io.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index 6ea49db..165a7bf 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -18,6 +18,7 @@
 #include <linux/err.h>
 #include <linux/ion.h>
 #include "ion_priv.h"
+#include <linux/msm_ion.h>
 
 struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
 {
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index d0f101c..345c07d 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -12,7 +12,7 @@
  */
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index c79c184..ad2ef83 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -27,6 +27,7 @@
 #include "ion_priv.h"
 #include <mach/memory.h>
 #include <asm/cacheflush.h>
+#include <linux/msm_ion.h>
 
 static atomic_t system_heap_allocated;
 static atomic_t system_contig_heap_allocated;
diff --git a/drivers/gpu/ion/msm/ion_cp_common.h b/drivers/gpu/ion/msm/ion_cp_common.h
index 69dd19e..634473f 100644
--- a/drivers/gpu/ion/msm/ion_cp_common.h
+++ b/drivers/gpu/ion/msm/ion_cp_common.h
@@ -15,7 +15,7 @@
 #define ION_CP_COMMON_H
 
 #include <asm-generic/errno-base.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #define ION_CP_V1	1
 #define ION_CP_V2	2
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index c65a000..4c9be1d 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -13,12 +13,17 @@
 
 #include <linux/export.h>
 #include <linux/err.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/memory_alloc.h>
 #include <linux/fmem.h>
 #include <linux/of.h>
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/sched.h>
+#include <linux/rwsem.h>
+#include <linux/uaccess.h>
 #include <mach/ion.h>
 #include <mach/msm_memtypes.h>
 #include "../ion_priv.h"
@@ -556,6 +561,102 @@
 	return ERR_PTR(ret);
 }
 
+static int check_vaddr_bounds(unsigned long start, unsigned long end)
+{
+	struct mm_struct *mm = current->active_mm;
+	struct vm_area_struct *vma;
+	int ret = 1;
+
+	if (end < start)
+		goto out;
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, start);
+	if (vma && vma->vm_start < end) {
+		if (start < vma->vm_start)
+			goto out_up;
+		if (end > vma->vm_end)
+			goto out_up;
+		ret = 0;
+	}
+
+out_up:
+	up_read(&mm->mmap_sem);
+out:
+	return ret;
+}
+
+static long msm_ion_custom_ioctl(struct ion_client *client,
+				unsigned int cmd,
+				unsigned long arg)
+{
+	switch (cmd) {
+	case ION_IOC_CLEAN_CACHES:
+	case ION_IOC_INV_CACHES:
+	case ION_IOC_CLEAN_INV_CACHES:
+	{
+		struct ion_flush_data data;
+		unsigned long start, end;
+		struct ion_handle *handle = NULL;
+		int ret;
+
+		if (copy_from_user(&data, (void __user *)arg,
+					sizeof(struct ion_flush_data)))
+			return -EFAULT;
+
+		start = (unsigned long) data.vaddr;
+		end = (unsigned long) data.vaddr + data.length;
+
+		if (check_vaddr_bounds(start, end)) {
+			pr_err("%s: virtual address %p is out of bounds\n",
+				__func__, data.vaddr);
+			return -EINVAL;
+		}
+
+		if (!data.handle) {
+			handle = ion_import_dma_buf(client, data.fd);
+			if (IS_ERR(handle)) {
+				pr_info("%s: Could not import handle: %d\n",
+					__func__, (int)handle);
+				return -EINVAL;
+			}
+		}
+
+		ret = ion_do_cache_op(client,
+				data.handle ? data.handle : handle,
+				data.vaddr, data.offset, data.length,
+				cmd);
+
+		if (!data.handle)
+			ion_free(client, handle);
+
+		if (ret < 0)
+			return ret;
+		break;
+
+	}
+	case ION_IOC_GET_FLAGS:
+	{
+		struct ion_flag_data data;
+		int ret;
+		if (copy_from_user(&data, (void __user *)arg,
+					sizeof(struct ion_flag_data)))
+			return -EFAULT;
+
+		ret = ion_handle_get_flags(client, data.handle, &data.flags);
+		if (ret < 0)
+			return ret;
+		if (copy_to_user((void __user *)arg, &data,
+					sizeof(struct ion_flag_data)))
+			return -EFAULT;
+		break;
+	}
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
 static int msm_ion_probe(struct platform_device *pdev)
 {
 	struct ion_platform_data *pdata;
@@ -583,7 +684,7 @@
 		goto out;
 	}
 
-	idev = ion_device_create(NULL);
+	idev = ion_device_create(msm_ion_custom_ioctl);
 	if (IS_ERR_OR_NULL(idev)) {
 		err = PTR_ERR(idev);
 		goto freeheaps;
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 6fe316a..05c7967 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -77,6 +77,9 @@
 #define A3XX_CP_PFP_UCODE_DATA 0x1CA
 #define A3XX_CP_ROQ_ADDR 0x1CC
 #define A3XX_CP_ROQ_DATA 0x1CD
+#define A3XX_CP_MERCIU_ADDR 0x1D1
+#define A3XX_CP_MERCIU_DATA 0x1D2
+#define A3XX_CP_MERCIU_DATA2 0x1D3
 #define A3XX_CP_MEQ_ADDR 0x1DA
 #define A3XX_CP_MEQ_DATA 0x1DB
 #define A3XX_CP_HW_FAULT  0x45C
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d99d398..cf7f3ce 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -336,13 +336,6 @@
 				device->mmu.setstate_memory.gpuaddr +
 				KGSL_IOMMU_SETSTATE_NOP_OFFSET);
 		}
-		/* invalidate all base pointers */
-		*cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
-		*cmds++ = 0x7fff;
-
-		cmds += __adreno_add_idle_indirect_cmds(cmds,
-			device->mmu.setstate_memory.gpuaddr +
-			KGSL_IOMMU_SETSTATE_NOP_OFFSET);
 	}
 	if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
 		/*
@@ -386,6 +379,10 @@
 
 	sizedwords += (cmds - &link[0]);
 	if (sizedwords) {
+		/* invalidate all base pointers */
+		*cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
+		*cmds++ = 0x7fff;
+		sizedwords += 2;
 		/*
 		 * add an interrupt at the end of commands so that the smmu
 		 * disable clock off function will get called
@@ -1094,7 +1091,7 @@
 static int
 adreno_ocmem_gmem_malloc(struct adreno_device *adreno_dev)
 {
-	if (adreno_dev->gpurev != ADRENO_REV_A330)
+	if (!adreno_is_a330(adreno_dev))
 		return 0;
 
 	/* OCMEM is only needed once, do not support consective allocation */
@@ -1115,7 +1112,7 @@
 static void
 adreno_ocmem_gmem_free(struct adreno_device *adreno_dev)
 {
-	if (adreno_dev->gpurev != ADRENO_REV_A330)
+	if (!adreno_is_a330(adreno_dev))
 		return;
 
 	if (adreno_dev->ocmem_hdl == NULL)
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index d151255..66402fe 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -165,6 +165,9 @@
 extern const unsigned int a3xx_registers[];
 extern const unsigned int a3xx_registers_count;
 
+extern const unsigned int a330_registers[];
+extern const unsigned int a330_registers_count;
+
 extern unsigned int hang_detect_regs[];
 extern const unsigned int hang_detect_regs_count;
 
@@ -252,6 +255,11 @@
 	return (adreno_dev->gpurev == ADRENO_REV_A320);
 }
 
+static inline int adreno_is_a330(struct adreno_device *adreno_dev)
+{
+	return (adreno_dev->gpurev == ADRENO_REV_A330);
+}
+
 static inline int adreno_rb_ctxtswitch(unsigned int *cmd)
 {
 	return (cmd[0] == cp_nop_packet(1) &&
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 23d61ff..1f32e54 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1507,7 +1507,7 @@
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 
-	if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTOYED))
+	if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED))
 		return;
 
 	if (context->flags & CTXT_FLAGS_GPU_HANG)
@@ -1840,7 +1840,7 @@
 	unsigned int *cmds, cmds_gpu;
 
 	/* ME_INIT */
-	cmds = adreno_ringbuffer_allocspace(rb, 19);
+	cmds = adreno_ringbuffer_allocspace(rb, NULL, 19);
 	cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19);
 
 	GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 18));
@@ -1983,10 +1983,10 @@
 			0x18000000);
 	}
 
-	if (adreno_is_a203(adreno_dev))
-		/* For A203 increase number of clocks that RBBM
-		 * will wait before de-asserting Register Clock
-		 * Active signal */
+	if (adreno_is_a20x(adreno_dev))
+		/* For A20X based targets increase number of clocks
+		 * that RBBM will wait before de-asserting Register
+		 * Clock Active signal */
 		adreno_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF);
 	else
 		adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442);
diff --git a/drivers/gpu/msm/adreno_a2xx_snapshot.c b/drivers/gpu/msm/adreno_a2xx_snapshot.c
index 2368264..282440c 100644
--- a/drivers/gpu/msm/adreno_a2xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a2xx_snapshot.c
@@ -232,6 +232,7 @@
 	int *remain, int hang)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
+	struct kgsl_snapshot_registers_list list;
 	struct kgsl_snapshot_registers regs;
 	unsigned int pmoverride;
 
@@ -248,10 +249,13 @@
 		regs.count = a225_registers_count;
 	}
 
+	list.registers = &regs;
+	list.count = 1;
+
 	/* Master set of (non debug) registers */
 	snapshot = kgsl_snapshot_add_section(device,
 		KGSL_SNAPSHOT_SECTION_REGS, snapshot, remain,
-		kgsl_snapshot_dump_regs, &regs);
+		kgsl_snapshot_dump_regs, &list);
 
 	/* CP_STATE_DEBUG indexed registers */
 	snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 4b3263d..d89e882 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -69,6 +69,14 @@
 
 const unsigned int a3xx_registers_count = ARRAY_SIZE(a3xx_registers) / 2;
 
+/* The set of additional registers to be dumped for A330 */
+
+const unsigned int a330_registers[] = {
+	0x1d0, 0x1d0, 0x1d4, 0x1d4, 0x453, 0x453,
+};
+
+const unsigned int a330_registers_count = ARRAY_SIZE(a330_registers) / 2;
+
 /* Simple macro to facilitate bit setting in the gmem2sys and sys2gmem
  * functions.
  */
@@ -2347,7 +2355,7 @@
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 
-	if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTOYED))
+	if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED))
 		return;
 
 	if (context->flags & CTXT_FLAGS_GPU_HANG)
@@ -2455,7 +2463,7 @@
 			 struct adreno_ringbuffer *rb)
 {
 	unsigned int *cmds, cmds_gpu;
-	cmds = adreno_ringbuffer_allocspace(rb, 18);
+	cmds = adreno_ringbuffer_allocspace(rb, NULL, 18);
 	cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint) * (rb->wptr - 18);
 
 	GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 17));
@@ -2698,7 +2706,7 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 
 	/* Set up 16 deep read/write request queues */
-	if (adreno_dev->gpurev == ADRENO_REV_A330) {
+	if (adreno_is_a330(adreno_dev)) {
 		adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
 		adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
 		adreno_regwrite(device, A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
@@ -2781,7 +2789,7 @@
 			A3XX_RBBM_CLOCK_CTL_DEFAULT);
 
 	/* Set the OCMEM base address for A330 */
-	if (adreno_dev->gpurev == ADRENO_REV_A330) {
+	if (adreno_is_a330(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 a3bee4d..d49fc23 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -156,28 +156,68 @@
 	return DEBUG_SECTION_SZ(size);
 }
 
-#define CP_ROQ_SIZE 128
+/* This is the ROQ buffer size on both the A305 and A320 */
+#define A320_CP_ROQ_SIZE 128
+/* This is the ROQ buffer size on the A330 */
+#define A330_CP_ROQ_SIZE 512
 
 static int a3xx_snapshot_cp_roq(struct kgsl_device *device, void *snapshot,
 		int remain, void *priv)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct kgsl_snapshot_debug *header = snapshot;
 	unsigned int *data = snapshot + sizeof(*header);
-	int i;
+	int i, size;
 
-	if (remain < DEBUG_SECTION_SZ(CP_ROQ_SIZE)) {
+	/* The size of the ROQ buffer is core dependent */
+	size = adreno_is_a330(adreno_dev) ?
+		A330_CP_ROQ_SIZE : A320_CP_ROQ_SIZE;
+
+	if (remain < DEBUG_SECTION_SZ(size)) {
 		SNAPSHOT_ERR_NOMEM(device, "CP ROQ DEBUG");
 		return 0;
 	}
 
 	header->type = SNAPSHOT_DEBUG_CP_ROQ;
-	header->size = CP_ROQ_SIZE;
+	header->size = size;
 
 	adreno_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0);
-	for (i = 0; i < CP_ROQ_SIZE; i++)
+	for (i = 0; i < size; i++)
 		adreno_regread(device, A3XX_CP_ROQ_DATA, &data[i]);
 
-	return DEBUG_SECTION_SZ(CP_ROQ_SIZE);
+	return DEBUG_SECTION_SZ(size);
+}
+
+#define A330_CP_MERCIU_QUEUE_SIZE 32
+
+static int a330_snapshot_cp_merciu(struct kgsl_device *device, void *snapshot,
+		int remain, void *priv)
+{
+	struct kgsl_snapshot_debug *header = snapshot;
+	unsigned int *data = snapshot + sizeof(*header);
+	int i, size;
+
+	/* The MERCIU data is two dwords per entry */
+	size = A330_CP_MERCIU_QUEUE_SIZE << 1;
+
+	if (remain < DEBUG_SECTION_SZ(size)) {
+		SNAPSHOT_ERR_NOMEM(device, "CP MERCIU DEBUG");
+		return 0;
+	}
+
+	header->type = SNAPSHOT_DEBUG_CP_MERCIU;
+	header->size = size;
+
+	adreno_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0);
+
+	for (i = 0; i < A330_CP_MERCIU_QUEUE_SIZE; i++) {
+		adreno_regread(device, A3XX_CP_MERCIU_DATA,
+			&data[(i * 2)]);
+		adreno_regread(device, A3XX_CP_MERCIU_DATA2,
+			&data[(i * 2) + 1]);
+	}
+
+	return DEBUG_SECTION_SZ(size);
 }
 
 #define DEBUGFS_BLOCK_SIZE 0x40
@@ -265,15 +305,26 @@
 	int *remain, int hang)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
-	struct kgsl_snapshot_registers regs;
+	struct kgsl_snapshot_registers_list list;
+	struct kgsl_snapshot_registers regs[2];
 
-	regs.regs = (unsigned int *) a3xx_registers;
-	regs.count = a3xx_registers_count;
+	regs[0].regs = (unsigned int *) a3xx_registers;
+	regs[0].count = a3xx_registers_count;
+
+	list.registers = regs;
+	list.count = 1;
+
+	/* For A330, append the additional list of new registers to grab */
+	if (adreno_is_a330(adreno_dev)) {
+		regs[1].regs = (unsigned int *) a330_registers;
+		regs[1].count = a330_registers_count;
+		list.count++;
+	}
 
 	/* Master set of (non debug) registers */
 	snapshot = kgsl_snapshot_add_section(device,
 		KGSL_SNAPSHOT_SECTION_REGS, snapshot, remain,
-		kgsl_snapshot_dump_regs, &regs);
+		kgsl_snapshot_dump_regs, &list);
 
 	/* CP_STATE_DEBUG indexed registers */
 	snapshot = kgsl_snapshot_indexed_registers(device, snapshot,
@@ -322,6 +373,12 @@
 			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
 			a3xx_snapshot_cp_roq, NULL);
 
+	if (adreno_is_a330(adreno_dev)) {
+		snapshot = kgsl_snapshot_add_section(device,
+			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
+			a330_snapshot_cp_merciu, NULL);
+	}
+
 	snapshot = a3xx_snapshot_debugbus(device, snapshot, remain);
 
 	/* Enable Clock gating */
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index a50747d..b51342f 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -221,17 +221,13 @@
 				     CTXT_FLAGS_GMEM_SHADOW |
 				     CTXT_FLAGS_STATE_SHADOW);
 
-		drawctxt->flags |= CTXT_FLAGS_BEING_DESTOYED;
+		drawctxt->flags |= CTXT_FLAGS_BEING_DESTROYED;
 
 		adreno_drawctxt_switch(adreno_dev, NULL, 0);
 	}
 
 	adreno_idle(device);
 
-	if (adreno_is_a20x(adreno_dev) && adreno_dev->drawctxt_active)
-		kgsl_setstate(&device->mmu, adreno_dev->drawctxt_active->id,
-			KGSL_MMUFLAGS_PTUPDATE);
-
 	kgsl_sharedmem_free(&drawctxt->gpustate);
 	kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
 
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index d58f2da..034d6e9 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -19,35 +19,35 @@
 /* Flags */
 
 #define CTXT_FLAGS_NOT_IN_USE		0x00000000
-#define CTXT_FLAGS_IN_USE		0x00000001
+#define CTXT_FLAGS_IN_USE		BIT(0)
 
 /* state shadow memory allocated */
-#define CTXT_FLAGS_STATE_SHADOW		0x00000010
+#define CTXT_FLAGS_STATE_SHADOW		BIT(1)
 
 /* gmem shadow memory allocated */
-#define CTXT_FLAGS_GMEM_SHADOW		0x00000100
+#define CTXT_FLAGS_GMEM_SHADOW		BIT(2)
 /* gmem must be copied to shadow */
-#define CTXT_FLAGS_GMEM_SAVE		0x00000200
+#define CTXT_FLAGS_GMEM_SAVE		BIT(3)
 /* gmem can be restored from shadow */
-#define CTXT_FLAGS_GMEM_RESTORE		0x00000400
+#define CTXT_FLAGS_GMEM_RESTORE		BIT(4)
 /* preamble packed in cmdbuffer for context switching */
-#define CTXT_FLAGS_PREAMBLE		0x00000800
+#define CTXT_FLAGS_PREAMBLE		BIT(5)
 /* shader must be copied to shadow */
-#define CTXT_FLAGS_SHADER_SAVE		0x00002000
+#define CTXT_FLAGS_SHADER_SAVE		BIT(6)
 /* shader can be restored from shadow */
-#define CTXT_FLAGS_SHADER_RESTORE	0x00004000
+#define CTXT_FLAGS_SHADER_RESTORE	BIT(7)
 /* Context has caused a GPU hang */
-#define CTXT_FLAGS_GPU_HANG		0x00008000
+#define CTXT_FLAGS_GPU_HANG		BIT(8)
 /* Specifies there is no need to save GMEM */
-#define CTXT_FLAGS_NOGMEMALLOC          0x00010000
+#define CTXT_FLAGS_NOGMEMALLOC          BIT(9)
 /* Trash state for context */
-#define CTXT_FLAGS_TRASHSTATE		0x00020000
+#define CTXT_FLAGS_TRASHSTATE		BIT(10)
 /* per context timestamps enabled */
-#define CTXT_FLAGS_PER_CONTEXT_TS	0x00040000
+#define CTXT_FLAGS_PER_CONTEXT_TS	BIT(11)
 /* Context has caused a GPU hang and recovered properly */
-#define CTXT_FLAGS_GPU_HANG_RECOVERED	0x00008000
+#define CTXT_FLAGS_GPU_HANG_RECOVERED	BIT(12)
 /* Context is being destroyed so dont save it */
-#define CTXT_FLAGS_BEING_DESTOYED	0x00010000
+#define CTXT_FLAGS_BEING_DESTROYED	BIT(13)
 
 struct kgsl_device;
 struct adreno_device;
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 261e518..620b82c 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -869,9 +869,14 @@
 		else if (adreno_is_a225(adreno_dev))
 			adreno_dump_regs(device, a225_registers,
 				a225_registers_count);
-		else if (adreno_is_a3xx(adreno_dev))
+		else if (adreno_is_a3xx(adreno_dev)) {
 			adreno_dump_regs(device, a3xx_registers,
 					a3xx_registers_count);
+
+			if (adreno_is_a330(adreno_dev))
+				adreno_dump_regs(device, a330_registers,
+					a330_registers_count);
+		}
 	}
 
 error_vfree:
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 1a9da60..db913a5 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -44,9 +44,10 @@
 	adreno_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr);
 }
 
-static void
-adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned int numcmds,
-			  int wptr_ahead)
+static int
+adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb,
+				struct adreno_context *context,
+				unsigned int numcmds, int wptr_ahead)
 {
 	int nopcount;
 	unsigned int freecmds;
@@ -120,19 +121,28 @@
 		continue;
 
 err:
-		if (!adreno_dump_and_recover(rb->device))
-				wait_time = jiffies + wait_timeout;
-			else
-				/* GPU is hung and we cannot recover */
-				BUG();
+		if (!adreno_dump_and_recover(rb->device)) {
+			if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
+				KGSL_CTXT_WARN(rb->device,
+				"Context %p caused a gpu hang. Will not accept commands for context %d\n",
+				context, context->id);
+				return -EDEADLK;
+			}
+			wait_time = jiffies + wait_timeout;
+		} else {
+			/* GPU is hung and we cannot recover */
+			BUG();
+		}
 	}
+	return 0;
 }
 
 unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
-					     unsigned int numcmds)
+					struct adreno_context *context,
+					unsigned int numcmds)
 {
-	unsigned int	*ptr = NULL;
-
+	unsigned int *ptr = NULL;
+	int ret = 0;
 	BUG_ON(numcmds >= rb->sizedwords);
 
 	GSL_RB_GET_READPTR(rb, &rb->rptr);
@@ -142,20 +152,25 @@
 		/* reserve dwords for nop packet */
 		if ((rb->wptr + numcmds) > (rb->sizedwords -
 				GSL_RB_NOP_SIZEDWORDS))
-			adreno_ringbuffer_waitspace(rb, numcmds, 1);
+			ret = adreno_ringbuffer_waitspace(rb, context,
+							numcmds, 1);
 	} else {
 		/* wptr behind rptr */
 		if ((rb->wptr + numcmds) >= rb->rptr)
-			adreno_ringbuffer_waitspace(rb, numcmds, 0);
+			ret = adreno_ringbuffer_waitspace(rb, context,
+							numcmds, 0);
 		/* check for remaining space */
 		/* reserve dwords for nop packet */
-		if ((rb->wptr + numcmds) > (rb->sizedwords -
+		if (!ret && (rb->wptr + numcmds) > (rb->sizedwords -
 				GSL_RB_NOP_SIZEDWORDS))
-			adreno_ringbuffer_waitspace(rb, numcmds, 1);
+			ret = adreno_ringbuffer_waitspace(rb, context,
+							numcmds, 1);
 	}
 
-	ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
-	rb->wptr += numcmds;
+	if (!ret) {
+		ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
+		rb->wptr += numcmds;
+	}
 
 	return ptr;
 }
@@ -512,13 +527,12 @@
 		total_sizedwords += 4; /* global timestamp for recovery*/
 	}
 
-	ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
-	/* GPU may hang during space allocation, if thats the case the current
-	 * context may have hung the GPU */
-	if (context->flags & CTXT_FLAGS_GPU_HANG) {
-		KGSL_CTXT_WARN(rb->device,
-		"Context %p caused a gpu hang. Will not accept commands for context %d\n",
-		context, context->id);
+	ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
+	if (!ringcmds) {
+		/*
+		 * We could not allocate space in ringbuffer, just return the
+		 * last timestamp
+		 */
 		return rb->timestamp[context_id];
 	}
 
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index 6c3d9b1..4f58a15 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -127,7 +127,8 @@
 			int num_rb_contents);
 
 unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
-					     unsigned int numcmds);
+						struct adreno_context *context,
+						unsigned int numcmds);
 
 static inline int adreno_ringbuffer_count(struct adreno_ringbuffer *rb,
 	unsigned int rptr)
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1066b49..f630f2a 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -25,7 +25,7 @@
 #include <linux/rbtree.h>
 #include <linux/ashmem.h>
 #include <linux/major.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/io.h>
 #include <mach/socinfo.h>
 
@@ -1380,104 +1380,6 @@
 	return vma;
 }
 
-static long
-kgsl_ioctl_sharedmem_from_vmalloc(struct kgsl_device_private *dev_priv,
-				unsigned int cmd, void *data)
-{
-	int result = 0, len = 0;
-	struct kgsl_process_private *private = dev_priv->process_priv;
-	struct kgsl_sharedmem_from_vmalloc *param = data;
-	struct kgsl_mem_entry *entry = NULL;
-	struct vm_area_struct *vma;
-
-	KGSL_DEV_ERR_ONCE(dev_priv->device, "IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC"
-			" is deprecated\n");
-	if (!kgsl_mmu_enabled())
-		return -ENODEV;
-
-	if (!param->hostptr) {
-		KGSL_CORE_ERR("invalid hostptr %x\n", param->hostptr);
-		result = -EINVAL;
-		goto error;
-	}
-
-	vma = kgsl_get_vma_from_start_addr(param->hostptr);
-	if (!vma) {
-		result = -EINVAL;
-		goto error;
-	}
-
-	/*
-	 * If the user specified a length, use it, otherwise try to
-	 * infer the length if the vma region
-	 */
-	if (param->gpuaddr != 0) {
-		len = param->gpuaddr;
-	} else {
-		/*
-		 * For this to work, we have to assume the VMA region is only
-		 * for this single allocation.  If it isn't, then bail out
-		 */
-		if (vma->vm_pgoff || (param->hostptr != vma->vm_start)) {
-			KGSL_CORE_ERR("VMA region does not match hostaddr\n");
-			result = -EINVAL;
-			goto error;
-		}
-
-		len = vma->vm_end - vma->vm_start;
-	}
-
-	/* Make sure it fits */
-	if (len == 0 || param->hostptr + len > vma->vm_end) {
-		KGSL_CORE_ERR("Invalid memory allocation length %d\n", len);
-		result = -EINVAL;
-		goto error;
-	}
-
-	entry = kgsl_mem_entry_create();
-	if (entry == NULL) {
-		result = -ENOMEM;
-		goto error;
-	}
-
-	result = kgsl_sharedmem_page_alloc_user(&entry->memdesc,
-					     private->pagetable, len,
-					     param->flags);
-	if (result != 0)
-		goto error_free_entry;
-
-	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-
-	result = kgsl_sharedmem_map_vma(vma, &entry->memdesc);
-	if (result) {
-		KGSL_CORE_ERR("kgsl_sharedmem_map_vma failed: %d\n", result);
-		goto error_free_alloc;
-	}
-
-	param->gpuaddr = entry->memdesc.gpuaddr;
-
-	entry->memtype = KGSL_MEM_ENTRY_KERNEL;
-
-	kgsl_mem_entry_attach_process(entry, private);
-
-	trace_kgsl_mem_alloc(entry);
-	/* Process specific statistics */
-	kgsl_process_add_stats(private, entry->memtype, len);
-
-	kgsl_check_idle(dev_priv->device);
-	return 0;
-
-error_free_alloc:
-	kgsl_sharedmem_free(&entry->memdesc);
-
-error_free_entry:
-	kfree(entry);
-
-error:
-	kgsl_check_idle(dev_priv->device);
-	return result;
-}
-
 static inline int _check_region(unsigned long start, unsigned long size,
 				uint64_t len)
 {
@@ -2161,8 +2063,6 @@
 			kgsl_ioctl_map_user_mem, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FREE,
 			kgsl_ioctl_sharedmem_free, 0),
-	KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC,
-			kgsl_ioctl_sharedmem_from_vmalloc, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE,
 			kgsl_ioctl_sharedmem_flush_cache, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC,
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 71dfe8c..87e8746 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -606,8 +606,10 @@
 		}
 		iommu_unit->reg_map.size = data.physend - data.physstart + 1;
 		iommu_unit->reg_map.physaddr = data.physstart;
-		memdesc_sg_phys(&iommu_unit->reg_map, data.physstart,
+		ret = memdesc_sg_phys(&iommu_unit->reg_map, data.physstart,
 				iommu_unit->reg_map.size);
+		if (ret)
+			goto err;
 	}
 	iommu->unit_count = pdata_dev->iommu_count;
 	return ret;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 8c45475..739dcb5 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -459,6 +459,15 @@
 						clk_unprepare(pwr->grp_clks[i]);
 			}
 			kgsl_pwrctrl_busy_time(device, true);
+		} else if (requested_state == KGSL_STATE_SLEEP) {
+			/* High latency clock maintenance. */
+			if ((pwr->pwrlevels[0].gpu_freq > 0))
+				clk_set_rate(pwr->grp_clks[0],
+					pwr->pwrlevels[pwr->num_pwrlevels - 1].
+					gpu_freq);
+			for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
+				if (pwr->grp_clks[i])
+					clk_unprepare(pwr->grp_clks[i]);
 		}
 	} else if (state == KGSL_PWRFLAGS_ON) {
 		if (!test_and_set_bit(KGSL_PWRFLAGS_CLK_ON,
@@ -851,7 +860,6 @@
 static int
 _sleep(struct kgsl_device *device)
 {
-	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	switch (device->state) {
 	case KGSL_STATE_ACTIVE:
 		if (!device->ftbl->isidle(device)) {
@@ -862,10 +870,6 @@
 	case KGSL_STATE_NAP:
 		kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
 		kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_OFF);
-		if (pwr->pwrlevels[0].gpu_freq > 0)
-			clk_set_rate(pwr->grp_clks[0],
-				pwr->pwrlevels[pwr->num_pwrlevels - 1].
-				gpu_freq);
 		_sleep_accounting(device);
 		kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP);
@@ -970,9 +974,8 @@
 		/* Re-enable HW access */
 		mod_timer(&device->idle_timer,
 				jiffies + device->pwrctrl.interval_timeout);
-		if (device->pwrctrl.restore_slumber == false)
-			pm_qos_update_request(&device->pm_qos_req_dma,
-						GPU_SWFI_LATENCY);
+		pm_qos_update_request(&device->pm_qos_req_dma,
+					GPU_SWFI_LATENCY);
 	case KGSL_STATE_ACTIVE:
 		break;
 	default:
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index c6f8b1b..879b381 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -127,6 +127,28 @@
 	return;
 }
 
+static void msm_remove_io_fraction(struct kgsl_device *device)
+{
+	int i;
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+
+	for (i = 0; i < pwr->num_pwrlevels; i++)
+		pwr->pwrlevels[i].io_fraction = 100;
+
+}
+
+static void msm_restore_io_fraction(struct kgsl_device *device)
+{
+	int i;
+	struct kgsl_device_platform_data *pdata =
+				kgsl_device_get_drvdata(device);
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+
+	for (i = 0; i < pdata->num_levels; i++)
+		pwr->pwrlevels[i].io_fraction =
+			pdata->pwrlevel[i].io_fraction;
+}
+
 static int msm_init(struct kgsl_device *device,
 		     struct kgsl_pwrscale *pwrscale)
 {
@@ -177,6 +199,7 @@
 		} else {
 			priv->gpu_busy = 1;
 		}
+		msm_remove_io_fraction(device);
 		return 0;
 	}
 
@@ -201,6 +224,7 @@
 	msm_dcvs_freq_sink_unregister(&priv->freq_sink);
 	kfree(pwrscale->priv);
 	pwrscale->priv = NULL;
+	msm_restore_io_fraction(device);
 }
 
 struct kgsl_pwrscale_policy kgsl_pwrscale_policy_msm = {
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index 1b029b1..7c2514b 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -178,15 +178,11 @@
 	priv->no_switch_cnt = 0;
 }
 
+#ifdef CONFIG_MSM_SCM
 static int tz_init(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale)
 {
 	struct tz_priv *priv;
 
-	/* Trustzone is only valid for some SOCs */
-	if (!(cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
-		cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627()))
-		return -EINVAL;
-
 	priv = pwrscale->priv = kzalloc(sizeof(struct tz_priv), GFP_KERNEL);
 	if (pwrscale->priv == NULL)
 		return -ENOMEM;
@@ -197,6 +193,12 @@
 
 	return 0;
 }
+#else
+static int tz_init(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_MSM_SCM */
 
 static void tz_close(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale)
 {
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 034ade4..de89ac1 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -117,6 +117,8 @@
 		unsigned int physaddr, unsigned int size)
 {
 	memdesc->sg = kgsl_sg_alloc(1);
+	if (memdesc->sg == NULL)
+		return -ENOMEM;
 
 	kmemleak_not_leak(memdesc->sg);
 
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index abaa8ce..a2ab5b1 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -414,18 +414,24 @@
 int kgsl_snapshot_dump_regs(struct kgsl_device *device, void *snapshot,
 	int remain, void *priv)
 {
+	struct kgsl_snapshot_registers_list *list = priv;
+
 	struct kgsl_snapshot_regs *header = snapshot;
-	struct kgsl_snapshot_registers *regs = priv;
+	struct kgsl_snapshot_registers *regs;
 	unsigned int *data = snapshot + sizeof(*header);
-	int count = 0, i, j;
+	int count = 0, i, j, k;
 
 	/* Figure out how many registers we are going to dump */
 
-	for (i = 0; i < regs->count; i++) {
-		int start = regs->regs[i * 2];
-		int end = regs->regs[i * 2 + 1];
+	for (i = 0; i < list->count; i++) {
+		regs = &(list->registers[i]);
 
-		count += (end - start + 1);
+		for (j = 0; j < regs->count; j++) {
+			int start = regs->regs[j * 2];
+			int end = regs->regs[j * 2 + 1];
+
+			count += (end - start + 1);
+		}
 	}
 
 	if (remain < (count * 8) + sizeof(*header)) {
@@ -433,16 +439,20 @@
 		return 0;
 	}
 
-	for (i = 0; i < regs->count; i++) {
-		unsigned int start = regs->regs[i * 2];
-		unsigned int end = regs->regs[i * 2 + 1];
 
-		for (j = start; j <= end; j++) {
-			unsigned int val;
+	for (i = 0; i < list->count; i++) {
+		regs = &(list->registers[i]);
+		for (j = 0; j < regs->count; j++) {
+			unsigned int start = regs->regs[j * 2];
+			unsigned int end = regs->regs[j * 2 + 1];
 
-			kgsl_regread(device, j, &val);
-			*data++ = j;
-			*data++ = val;
+			for (k = start; k <= end; k++) {
+				unsigned int val;
+
+				kgsl_regread(device, k, &val);
+				*data++ = k;
+				*data++ = val;
+			}
 		}
 	}
 
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
index d54afcf..6d81bcf 100644
--- a/drivers/gpu/msm/kgsl_snapshot.h
+++ b/drivers/gpu/msm/kgsl_snapshot.h
@@ -144,6 +144,7 @@
 #define SNAPSHOT_DEBUG_CP_PFP_RAM 9
 #define SNAPSHOT_DEBUG_CP_ROQ     10
 #define SNAPSHOT_DEBUG_SHADER_MEMORY 11
+#define SNAPSHOT_DEBUG_CP_MERCIU 12
 
 struct kgsl_snapshot_debug {
 	int type;    /* Type identifier for the attached tata */
@@ -240,12 +241,22 @@
 /* A common helper function to dump a range of registers.  This will be used in
  * the GPU specific devices like this:
  *
- * struct kgsl_snapshot_registers priv;
- * priv.regs = registers_array;;
- * priv.count = num_registers;
+ * struct kgsl_snapshot_registers_list list;
+ * struct kgsl_snapshot_registers priv[2];
+ *
+ * priv[0].regs = registers_array;;
+ * priv[o].count = num_registers;
+ * priv[1].regs = registers_array_new;;
+ * priv[1].count = num_registers_new;
+ *
+ * list.registers = priv;
+ * list.count = 2;
  *
  * kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot,
- *	remain, kgsl_snapshot_dump_regs, &priv).
+ *	remain, kgsl_snapshot_dump_regs, &list).
+ *
+ * Pass in a struct pointing to a list of register definitions as described
+ * below:
  *
  * Pass in an array of register range pairs in the form of:
  * start reg, stop reg
@@ -257,6 +268,13 @@
 	int count;	     /* Number of entries in the array */
 };
 
+struct kgsl_snapshot_registers_list {
+	/* Pointer to an array of register lists */
+	struct kgsl_snapshot_registers *registers;
+	/* Number of registers lists in the array */
+	int count;
+};
+
 int kgsl_snapshot_dump_regs(struct kgsl_device *device, void *snapshot,
 	int remain, void *priv);
 
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index ab15945..3969319 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -67,6 +67,40 @@
 #define GPIO_EPM_GLOBAL_ENABLE		86
 #define EPM_ADC_CONVERSION_TIME_MIN	50000
 #define EPM_ADC_CONVERSION_TIME_MAX	51000
+/* PSoc Commands */
+#define EPM_PSOC_INIT_CMD				0x1
+#define EPM_PSOC_INIT_RESPONSE_CMD			0x2
+#define EPM_PSOC_CHANNEL_ENABLE_DISABLE_CMD		0x5
+#define EPM_PSOC_CHANNEL_ENABLE_DISABLE_RESPONSE_CMD	0x6
+#define EPM_PSOC_SET_AVERAGING_CMD			0x7
+#define EPM_PSOC_SET_AVERAGING_RESPONSE_CMD		0x8
+#define EPM_PSOC_GET_LAST_MEASUREMENT_CMD		0x9
+#define EPM_PSOC_GET_LAST_MEASUREMENT_RESPONSE_CMD	0xa
+#define EPM_PSOC_GET_BUFFERED_DATA_CMD			0xb
+#define EPM_PSOC_GET_BUFFERED_RESPONSE_CMD		0xc
+#define EPM_PSOC_GET_SYSTEM_TIMESTAMP_CMD		0x11
+#define EPM_PSOC_GET_SYSTEM_TIMESTAMP_RESPONSE_CMD	0x12
+#define EPM_PSOC_SET_SYSTEM_TIMESTAMP_CMD		0x13
+#define EPM_PSOC_SET_SYSTEM_TIMESTAMP_RESPONSE_CMD	0x14
+#define EPM_PSOC_SET_CHANNEL_TYPE_CMD			0x15
+#define EPM_PSOC_SET_CHANNEL_TYPE_RESPONSE_CMD		0x16
+#define EPM_PSOC_GET_AVERAGED_DATA_CMD			0x19
+#define EPM_PSOC_GET_AVERAGED_DATA_RESPONSE_CMD		0x1a
+#define EPM_PSOC_SET_CHANNEL_SWITCH_DELAY_CMD		0x1b
+#define EPM_PSOC_SET_CHANNEL_SWITCH_DELAY_RESPONSE_CMD	0x1c
+#define EPM_PSOC_CLEAR_BUFFER_CMD			0x1d
+#define EPM_PSOC_CLEAR_BUFFER_RESPONSE_CMD		0x1e
+#define EPM_PSOC_SET_VADC_REFERENCE_CMD			0x1f
+#define EPM_PSOC_SET_VADC_REFERENCE_RESPONSE_CMD	0x20
+
+#define EPM_PSOC_GLOBAL_ENABLE				81
+#define EPM_PSOC_VREF_VOLTAGE				2048
+#define EPM_PSOC_MAX_ADC_CODE_16_BIT			32767
+#define EPM_GLOBAL_ENABLE_MIN_DELAY			5000
+#define EPM_GLOBAL_ENABLE_MAX_DELAY			5100
+
+#define EPM_PSOC_BUFFERED_DATA_LENGTH			48
+#define EPM_PSOC_BUFFERED_DATA_LENGTH2			54
 
 #define EPM_SPI_NOR_CS_N_GPIO		53
 
@@ -77,6 +111,7 @@
 	struct mutex			conv_lock;
 	uint32_t			bus_id;
 	struct miscdevice		misc;
+	struct epm_chan_properties	epm_psoc_ch_prop[0];
 };
 
 static struct epm_adc_drv *epm_adc_drv;
@@ -220,13 +255,11 @@
 	if (!rc) {
 		rc = gpio_direction_output(GPIO_EPM_SPI_ADC2_CS_N, 1);
 		if (rc) {
-			pr_err("%s: Set GPIO_EPM_SPI_ADC2_CS_N "
-					"failed\n", __func__);
+			pr_err("Set GPIO_EPM_SPI_ADC2_CS_N failed\n");
 			return rc;
 		}
 	} else {
-		pr_err("%s: gpio_request GPIO_EPM_SPI_ADC2_CS_N "
-				"failed\n", __func__);
+		pr_err("gpio_request GPIO_EPM_SPI_ADC2_CS_N failed\n");
 		return rc;
 	}
 
@@ -471,8 +504,7 @@
 	mutex_lock(&epm_adc->conv_lock);
 	rc = epm_adc_gpio_configure_expander_disable();
 	if (rc != 0) {
-		pr_err("epm gpio configure expander disable failed,"
-			" rc = %d\n", rc);
+		pr_err("gpio expander disable failed with %d\n", rc);
 		goto epm_adc_hw_deinit_err;
 	}
 
@@ -518,7 +550,7 @@
 		channel_num -= EPM_ADC_CHANNEL_AIN_OFFSET;
 		/*
 		 * Conversion for the adc channels.
-		 * mvVRef is in milli-volts and resistorValue is in micro-ohms.
+		 * mvVRef is in milli-volts and resistorvalue is in micro-ohms.
 		 * Hence, I = V/R gives us current in kilo-amps.
 		 */
 		if (*adc_scaled_data & EPM_ADC_MAX_NEGATIVE_SCALE_CODE) {
@@ -540,7 +572,7 @@
 			*adc_scaled_data *= EPM_ADC_SCALE_MILLI;
 			 /* Data is now in micro-amps.*/
 			do_div(*adc_scaled_data,
-				pdata->channel[chan_idx].resistorValue);
+				pdata->channel[chan_idx].resistorvalue);
 			 /* Set the sign bit for lekage current. */
 			*adc_scaled_data *= sign_bit;
 		}
@@ -550,6 +582,18 @@
 	return 0;
 }
 
+static int epm_psoc_scale_result(uint16_t *adc_raw_data, uint32_t index)
+{
+	struct epm_adc_drv *epm_adc = epm_adc_drv;
+	/* result = 2.048V/(32767 * gain * rsense) */
+	*adc_raw_data = (EPM_PSOC_VREF_VOLTAGE/EPM_PSOC_MAX_ADC_CODE_16_BIT)
+				* (*adc_raw_data);
+	*adc_raw_data = *adc_raw_data/
+		(epm_adc->epm_psoc_ch_prop[index].gain *
+			epm_adc->epm_psoc_ch_prop[index].resistorvalue);
+	return 0;
+}
+
 static int epm_adc_blocking_conversion(struct epm_adc_drv *epm_adc,
 					struct epm_chan_request *conv)
 {
@@ -620,6 +664,465 @@
 	return rc;
 }
 
+static int epm_adc_psoc_gpio_init(bool enable)
+{
+	int rc = 0;
+
+	if (enable) {
+		rc = gpio_request(EPM_PSOC_GLOBAL_ENABLE, "EPM_PSOC_GLOBAL_EN");
+		if (!rc) {
+			gpio_direction_output(EPM_PSOC_GLOBAL_ENABLE, 1);
+		} else {
+			pr_err("%s: Configure EPM_GLOBAL_EN Failed\n",
+								__func__);
+			return rc;
+		}
+	} else {
+		gpio_direction_output(EPM_PSOC_GLOBAL_ENABLE, 0);
+		gpio_free(EPM_PSOC_GLOBAL_ENABLE);
+	}
+
+	return 0;
+}
+
+static int epm_psoc_init(struct epm_adc_drv *epm_adc,
+					struct epm_psoc_init_resp *init_resp)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[17], rx_buf[17];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = init_resp->cmd;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	init_resp->cmd			= rx_buf[0];
+	init_resp->version		= rx_buf[1];
+	init_resp->compatible_ver	= rx_buf[2];
+	init_resp->firm_ver[0]		= rx_buf[3];
+	init_resp->firm_ver[1]		= rx_buf[4];
+	init_resp->firm_ver[2]		= rx_buf[5];
+	init_resp->num_dev		= rx_buf[6];
+	init_resp->num_channel		= rx_buf[7];
+
+	return rc;
+}
+
+static int epm_psoc_channel_configure(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_channel_configure *psoc_chan_configure)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[9], rx_buf[9];
+	int32_t rc = 0, chan_num;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	chan_num = psoc_chan_configure->channel_num;
+
+	tx_buf[0] = psoc_chan_configure->cmd;
+	tx_buf[1] = 0;
+	tx_buf[2] = (chan_num & 0xff000000) >> 24;
+	tx_buf[3] = (chan_num & 0xff0000) >> 16;
+	tx_buf[4] = (chan_num & 0xff00) >> 8;
+	tx_buf[5] = (chan_num & 0xff);
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_chan_configure->cmd		= rx_buf[0];
+	psoc_chan_configure->device_num		= rx_buf[1];
+	chan_num = rx_buf[2] << 24 | (rx_buf[3] << 16) | (rx_buf[4] << 8) |
+						rx_buf[5];
+	psoc_chan_configure->channel_num	= chan_num;
+	pr_debug("dev_num:%d, chan_num:%d\n", rx_buf[1], chan_num);
+
+	return rc;
+}
+
+static int epm_psoc_set_averaging(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_set_avg *psoc_set_avg)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[4], rx_buf[4];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = psoc_set_avg->cmd;
+	tx_buf[1] = psoc_set_avg->avg_period;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_set_avg->cmd		= rx_buf[0];
+	psoc_set_avg->return_code	= rx_buf[1];
+
+	return rc;
+}
+
+static int epm_psoc_get_data(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_get_data *psoc_get_meas)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[10], rx_buf[10];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = psoc_get_meas->cmd;
+	tx_buf[1] = psoc_get_meas->dev_num;
+	tx_buf[2] = psoc_get_meas->chan_num;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_get_meas->cmd		= rx_buf[0];
+	psoc_get_meas->dev_num		= rx_buf[1];
+	psoc_get_meas->chan_num		= rx_buf[2];
+	psoc_get_meas->timestamp_resp_value = (rx_buf[3] << 24) |
+			(rx_buf[4] << 16) | (rx_buf[5] << 8) |
+			rx_buf[6];
+	psoc_get_meas->reading_value = (rx_buf[7] << 8) | rx_buf[8];
+
+	pr_debug("dev_num:%d, chan_num:%d\n", rx_buf[1], rx_buf[2]);
+	pr_debug("data %d\n", psoc_get_meas->reading_value);
+	return rc;
+}
+
+static int epm_psoc_get_buffered_data(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_get_buffered_data *psoc_get_meas)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[64], rx_buf[64];
+	int rc = 0, i;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = psoc_get_meas->cmd;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_get_meas->cmd		= rx_buf[0];
+	psoc_get_meas->dev_num		= rx_buf[1];
+	psoc_get_meas->status_mask	= rx_buf[2];
+	psoc_get_meas->chan_idx		= rx_buf[3];
+	psoc_get_meas->chan_mask	= (rx_buf[4] << 24 |
+		rx_buf[5] << 16 | rx_buf[6] << 8
+			| rx_buf[7]);
+	psoc_get_meas->timestamp_start	= (rx_buf[8] << 24 |
+			rx_buf[9] << 16 | rx_buf[10] << 8
+			| rx_buf[11]);
+	psoc_get_meas->timestamp_end	= (rx_buf[12] << 24 |
+			rx_buf[13] << 16 | rx_buf[14] << 8
+			| rx_buf[15]);
+
+	for (i = 0; i < EPM_PSOC_BUFFERED_DATA_LENGTH; i++)
+		psoc_get_meas->buff_data[i] = rx_buf[16 + i];
+
+	return rc;
+}
+
+static int epm_psoc_timestamp(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_system_time_stamp *psoc_timestamp)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[10], rx_buf[10];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	if (psoc_timestamp->cmd == EPM_PSOC_SET_SYSTEM_TIMESTAMP_CMD) {
+		tx_buf[0] = psoc_timestamp->cmd;
+		tx_buf[1] = (psoc_timestamp->timestamp & 0xff000000) >> 24;
+		tx_buf[2] = (psoc_timestamp->timestamp & 0xff0000) >> 16;
+		tx_buf[3] = (psoc_timestamp->timestamp & 0xff00) >> 8;
+		tx_buf[4] = (psoc_timestamp->timestamp & 0xff);
+	} else if (psoc_timestamp->cmd == EPM_PSOC_GET_SYSTEM_TIMESTAMP_CMD) {
+		tx_buf[0] = psoc_timestamp->cmd;
+	}
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_timestamp->cmd		= rx_buf[0];
+	psoc_timestamp->timestamp = rx_buf[1] << 24 | rx_buf[2] << 16 |
+					rx_buf[3] << 8 | rx_buf[4];
+
+	return rc;
+}
+
+static int epm_psoc_get_avg_buffered_switch_data(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_get_avg_buffered_switch_data *psoc_get_meas)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[64], rx_buf[64];
+	int rc = 0, i;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = psoc_get_meas->cmd;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_get_meas->cmd		= rx_buf[0];
+	psoc_get_meas->status		= rx_buf[1];
+	psoc_get_meas->timestamp_start	= (rx_buf[2] << 24 |
+			rx_buf[3] << 16 | rx_buf[4] << 8
+			| rx_buf[5]);
+	psoc_get_meas->channel_mask	= (rx_buf[6] << 24 |
+		rx_buf[7] << 16 | rx_buf[8] << 8
+			| rx_buf[9]);
+
+	for (i = 0; i < EPM_PSOC_BUFFERED_DATA_LENGTH2; i++)
+		psoc_get_meas->avg_data[i] = rx_buf[10 + i];
+
+	return rc;
+}
+
+static int epm_psoc_set_vadc(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_set_vadc *psoc_set_vadc)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[10], rx_buf[10];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = psoc_set_vadc->cmd;
+	tx_buf[1] = psoc_set_vadc->vadc_dev;
+	tx_buf[2] = (psoc_set_vadc->vadc_voltage & 0xff000000) >> 24;
+	tx_buf[3] = (psoc_set_vadc->vadc_voltage & 0xff0000) >> 16;
+	tx_buf[4] = (psoc_set_vadc->vadc_voltage & 0xff00) >> 8;
+	tx_buf[5] = psoc_set_vadc->vadc_voltage & 0xff;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_set_vadc->cmd		= rx_buf[0];
+	psoc_set_vadc->vadc_dev		= rx_buf[1];
+	psoc_set_vadc->vadc_voltage = (rx_buf[2] << 24) | (rx_buf[3] << 16) |
+					(rx_buf[4] << 8) | (rx_buf[5]);
+
+	return rc;
+}
+
+static int epm_psoc_set_channel_switch(struct epm_adc_drv *epm_adc,
+		struct epm_psoc_set_channel_switch *psoc_channel_switch)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[10], rx_buf[10];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = psoc_channel_switch->cmd;
+	tx_buf[1] = psoc_channel_switch->dev;
+	tx_buf[2] = (psoc_channel_switch->delay & 0xff000000) >> 24;
+	tx_buf[3] = (psoc_channel_switch->delay & 0xff0000) >> 16;
+	tx_buf[4] = (psoc_channel_switch->delay & 0xff00) >> 8;
+	tx_buf[5] = psoc_channel_switch->delay & 0xff;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	psoc_channel_switch->cmd		= rx_buf[0];
+	psoc_channel_switch->dev		= rx_buf[1];
+	psoc_channel_switch->delay		= rx_buf[2] << 24 |
+					rx_buf[3] << 16 |
+					rx_buf[4] << 8 | rx_buf[5];
+
+	return rc;
+}
+
+static int epm_psoc_clear_buffer(struct epm_adc_drv *epm_adc)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	char tx_buf[3], rx_buf[3];
+	int rc = 0;
+
+	spi_setup(epm_adc->epm_spi_client);
+
+	memset(&t, 0, sizeof t);
+	memset(tx_buf, 0, sizeof tx_buf);
+	memset(rx_buf, 0, sizeof tx_buf);
+	t.tx_buf = tx_buf;
+	t.rx_buf = rx_buf;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	tx_buf[0] = EPM_PSOC_CLEAR_BUFFER_CMD;
+
+	t.len = sizeof(tx_buf);
+	t.bits_per_word = EPM_ADC_ADS_SPI_BITS_PER_WORD;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = spi_sync(epm_adc->epm_spi_client, &m);
+	if (rc)
+		return rc;
+
+	rc = rx_buf[2];
+
+	return rc;
+}
+
 static long epm_adc_ioctl(struct file *file, unsigned int cmd,
 						unsigned long arg)
 {
@@ -659,7 +1162,7 @@
 				epm_adc_expander_register = true;
 			}
 
-			result = epm_adc_hw_init(epm_adc_drv);
+			result = epm_adc_hw_init(epm_adc);
 
 			if (copy_to_user((void __user *)arg, &result,
 						sizeof(uint32_t)))
@@ -669,13 +1172,232 @@
 	case EPM_ADC_DEINIT:
 		{
 			uint32_t result;
-			result = epm_adc_hw_deinit(epm_adc_drv);
+			result = epm_adc_hw_deinit(epm_adc);
 
 			if (copy_to_user((void __user *)arg, &result,
 						sizeof(uint32_t)))
 				return -EFAULT;
 			break;
 		}
+	case EPM_PSOC_ADC_INIT:
+		{
+			struct epm_psoc_init_resp psoc_init;
+			int rc;
+
+			if (copy_from_user(&psoc_init, (void __user *)arg,
+					sizeof(struct epm_psoc_init_resp)))
+				return -EFAULT;
+
+			psoc_init.cmd = EPM_PSOC_INIT_CMD;
+			rc = epm_psoc_init(epm_adc, &psoc_init);
+			if (rc) {
+				pr_err("PSOC initialization failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &psoc_init,
+				sizeof(struct epm_psoc_init_resp)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_ADC_CHANNEL_ENABLE:
+	case EPM_PSOC_ADC_CHANNEL_DISABLE:
+		{
+			struct epm_psoc_channel_configure psoc_chan_configure;
+			int rc;
+
+			if (copy_from_user(&psoc_chan_configure,
+				(void __user *)arg,
+				sizeof(struct epm_psoc_channel_configure)))
+				return -EFAULT;
+
+			psoc_chan_configure.cmd =
+					EPM_PSOC_CHANNEL_ENABLE_DISABLE_CMD;
+			rc = epm_psoc_channel_configure(epm_adc,
+							&psoc_chan_configure);
+			if (rc) {
+				pr_err("PSOC channel configure failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg,
+				&psoc_chan_configure,
+				sizeof(struct epm_psoc_channel_configure)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_ADC_SET_AVERAGING:
+		{
+			struct epm_psoc_set_avg psoc_set_avg;
+			int rc;
+
+			if (copy_from_user(&psoc_set_avg, (void __user *)arg,
+					sizeof(struct epm_psoc_set_avg)))
+				return -EFAULT;
+
+			psoc_set_avg.cmd = EPM_PSOC_SET_AVERAGING_CMD;
+			rc = epm_psoc_set_averaging(epm_adc, &psoc_set_avg);
+			if (rc) {
+				pr_err("PSOC averaging failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &psoc_set_avg,
+					sizeof(struct epm_psoc_set_avg)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_ADC_GET_LAST_MEASUREMENT:
+		{
+			struct epm_psoc_get_data psoc_get_data;
+			int rc;
+
+			if (copy_from_user(&psoc_get_data,
+					(void __user *)arg,
+					sizeof(struct epm_psoc_get_data)))
+				return -EFAULT;
+
+			psoc_get_data.cmd = EPM_PSOC_GET_LAST_MEASUREMENT_CMD;
+			rc = epm_psoc_get_data(epm_adc, &psoc_get_data);
+			if (rc) {
+				pr_err("PSOC last measured data failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &psoc_get_data,
+				sizeof(struct epm_psoc_get_data)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_ADC_GET_BUFFERED_DATA:
+		{
+			struct epm_psoc_get_buffered_data psoc_get_data;
+			int rc;
+
+			if (copy_from_user(&psoc_get_data,
+				(void __user *)arg,
+				sizeof(struct epm_psoc_get_buffered_data)))
+				return -EFAULT;
+
+			psoc_get_data.cmd = EPM_PSOC_GET_BUFFERED_DATA_CMD;
+			rc = epm_psoc_get_buffered_data(epm_adc,
+								&psoc_get_data);
+			if (rc) {
+				pr_err("PSOC buffered measurement failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &psoc_get_data,
+				sizeof(struct epm_psoc_get_buffered_data)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_ADC_GET_SYSTEM_TIMESTAMP:
+	case EPM_PSOC_ADC_SET_SYSTEM_TIMESTAMP:
+		{
+			struct epm_psoc_system_time_stamp psoc_timestamp;
+			int rc;
+
+			if (copy_from_user(&psoc_timestamp,
+				(void __user *)arg,
+				sizeof(struct epm_psoc_system_time_stamp)))
+				return -EFAULT;
+
+			rc = epm_psoc_timestamp(epm_adc, &psoc_timestamp);
+			if (rc) {
+				pr_err("PSOC buffered measurement failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &psoc_timestamp,
+				sizeof(struct epm_psoc_system_time_stamp)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_ADC_GET_AVERAGE_DATA:
+		{
+			struct epm_psoc_get_avg_buffered_switch_data
+								psoc_get_data;
+			int rc;
+
+			if (copy_from_user(&psoc_get_data,
+				(void __user *)arg,
+				sizeof(struct
+				epm_psoc_get_avg_buffered_switch_data)))
+				return -EFAULT;
+
+			psoc_get_data.cmd = EPM_PSOC_GET_AVERAGED_DATA_CMD;
+			rc = epm_psoc_get_avg_buffered_switch_data(epm_adc,
+								&psoc_get_data);
+			if (rc) {
+				pr_err("Get averaged buffered data failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &psoc_get_data,
+				sizeof(struct
+				epm_psoc_get_avg_buffered_switch_data)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_SET_CHANNEL_SWITCH:
+		{
+			struct epm_psoc_set_channel_switch psoc_channel_switch;
+			int rc;
+
+			if (copy_from_user(&psoc_channel_switch,
+				(void __user *)arg,
+				sizeof(struct epm_psoc_set_channel_switch)))
+				return -EFAULT;
+
+			rc = epm_psoc_set_channel_switch(epm_adc,
+						&psoc_channel_switch);
+			if (rc) {
+				pr_err("PSOC channel switch failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg,
+				&psoc_channel_switch,
+				sizeof(struct epm_psoc_set_channel_switch)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_CLEAR_BUFFER:
+		{
+			int rc;
+			rc = epm_psoc_clear_buffer(epm_adc);
+			if (rc) {
+				pr_err("PSOC clear buffer failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &rc,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_PSOC_ADC_SET_VADC_REFERENCE:
+		{
+			struct epm_psoc_set_vadc psoc_set_vadc;
+			int rc;
+
+			if (copy_from_user(&psoc_set_vadc,
+					(void __user *)arg,
+					sizeof(struct epm_psoc_set_vadc)))
+				return -EFAULT;
+
+			rc = epm_psoc_set_vadc(epm_adc, &psoc_set_vadc);
+			if (rc) {
+				pr_err("PSOC set VADC failed\n");
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void __user *)arg, &psoc_set_vadc,
+				sizeof(struct epm_psoc_set_vadc)))
+				return -EFAULT;
+			break;
+		}
 	default:
 		return -EINVAL;
 	}
@@ -687,6 +1409,252 @@
 	.unlocked_ioctl = epm_adc_ioctl,
 };
 
+static ssize_t epm_adc_psoc_show_in(struct device *dev,
+				 struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct epm_adc_drv *epm_adc = epm_adc_drv;
+	struct epm_psoc_init_resp init_resp;
+	struct epm_psoc_channel_configure psoc_chan_configure;
+	struct epm_psoc_get_data psoc_get_meas;
+	int16_t *adc_code = 0;
+	int rc = 0;
+
+	rc = epm_adc_psoc_gpio_init(true);
+	if (rc) {
+		pr_err("GPIO init failed\n");
+		return 0;
+	}
+	usleep_range(EPM_GLOBAL_ENABLE_MIN_DELAY,
+				EPM_GLOBAL_ENABLE_MAX_DELAY);
+
+	init_resp.cmd = EPM_PSOC_INIT_CMD;
+	rc = epm_psoc_init(epm_adc, &init_resp);
+	if (rc) {
+		pr_info("PSOC init failed %d\n", rc);
+		return 0;
+	}
+
+	psoc_chan_configure.channel_num = (1 << attr->index);
+	psoc_chan_configure.cmd = EPM_PSOC_CHANNEL_ENABLE_DISABLE_CMD;
+	rc = epm_psoc_channel_configure(epm_adc, &psoc_chan_configure);
+	if (rc) {
+		pr_info("PSOC channel configure failed\n");
+		return 0;
+	}
+
+	usleep_range(EPM_GLOBAL_ENABLE_MIN_DELAY,
+				EPM_GLOBAL_ENABLE_MAX_DELAY);
+
+	psoc_get_meas.cmd = EPM_PSOC_GET_LAST_MEASUREMENT_CMD;
+	psoc_get_meas.dev_num = 0;
+	psoc_get_meas.chan_num = attr->index;
+	rc = epm_psoc_get_data(epm_adc, &psoc_get_meas);
+	if (rc) {
+		pr_info("PSOC get data failed\n");
+		return 0;
+	}
+
+	*adc_code = psoc_get_meas.reading_value;
+
+	rc = epm_psoc_scale_result(adc_code,
+			psoc_chan_configure.channel_num);
+	if (rc) {
+		pr_info("Scale result failed\n");
+		return 0;
+	}
+
+	psoc_get_meas.reading_value = *adc_code;
+
+	rc = epm_adc_psoc_gpio_init(false);
+	if (rc) {
+		pr_err("GPIO de-init failed\n");
+		return 0;
+	}
+
+	return snprintf(buf, 16, "Result: %d\n", psoc_get_meas.reading_value);
+}
+
+static struct sensor_device_attribute epm_adc_psoc_in_attrs[] = {
+	SENSOR_ATTR(ads0_chan0,  S_IRUGO, epm_adc_psoc_show_in, NULL, 0),
+	SENSOR_ATTR(ads0_chan1,  S_IRUGO, epm_adc_psoc_show_in, NULL, 1),
+	SENSOR_ATTR(ads0_chan2,  S_IRUGO, epm_adc_psoc_show_in, NULL, 2),
+	SENSOR_ATTR(ads0_chan3,  S_IRUGO, epm_adc_psoc_show_in, NULL, 3),
+	SENSOR_ATTR(ads0_chan4,  S_IRUGO, epm_adc_psoc_show_in, NULL, 4),
+	SENSOR_ATTR(ads0_chan5,  S_IRUGO, epm_adc_psoc_show_in, NULL, 5),
+	SENSOR_ATTR(ads0_chan6,  S_IRUGO, epm_adc_psoc_show_in, NULL, 6),
+	SENSOR_ATTR(ads0_chan7,  S_IRUGO, epm_adc_psoc_show_in, NULL, 7),
+	SENSOR_ATTR(ads0_chan8,  S_IRUGO, epm_adc_psoc_show_in, NULL, 8),
+	SENSOR_ATTR(ads0_chan9,  S_IRUGO, epm_adc_psoc_show_in, NULL, 9),
+	SENSOR_ATTR(ads0_chan10, S_IRUGO, epm_adc_psoc_show_in, NULL, 10),
+	SENSOR_ATTR(ads0_chan11, S_IRUGO, epm_adc_psoc_show_in, NULL, 11),
+	SENSOR_ATTR(ads0_chan12, S_IRUGO, epm_adc_psoc_show_in, NULL, 12),
+	SENSOR_ATTR(ads0_chan13, S_IRUGO, epm_adc_psoc_show_in, NULL, 13),
+	SENSOR_ATTR(ads0_chan14, S_IRUGO, epm_adc_psoc_show_in, NULL, 14),
+	SENSOR_ATTR(ads0_chan15, S_IRUGO, epm_adc_psoc_show_in, NULL, 15),
+	SENSOR_ATTR(ads1_chan0,  S_IRUGO, epm_adc_psoc_show_in, NULL, 16),
+	SENSOR_ATTR(ads1_chan1,  S_IRUGO, epm_adc_psoc_show_in, NULL, 17),
+	SENSOR_ATTR(ads1_chan2,  S_IRUGO, epm_adc_psoc_show_in, NULL, 18),
+	SENSOR_ATTR(ads1_chan3,  S_IRUGO, epm_adc_psoc_show_in, NULL, 19),
+	SENSOR_ATTR(ads1_chan4,  S_IRUGO, epm_adc_psoc_show_in, NULL, 20),
+	SENSOR_ATTR(ads1_chan5,  S_IRUGO, epm_adc_psoc_show_in, NULL, 21),
+	SENSOR_ATTR(ads1_chan6,  S_IRUGO, epm_adc_psoc_show_in, NULL, 22),
+	SENSOR_ATTR(ads1_chan7,  S_IRUGO, epm_adc_psoc_show_in, NULL, 23),
+	SENSOR_ATTR(ads1_chan8,  S_IRUGO, epm_adc_psoc_show_in, NULL, 24),
+	SENSOR_ATTR(ads1_chan9,  S_IRUGO, epm_adc_psoc_show_in, NULL, 25),
+	SENSOR_ATTR(ads1_chan10, S_IRUGO, epm_adc_psoc_show_in, NULL, 26),
+	SENSOR_ATTR(ads1_chan11, S_IRUGO, epm_adc_psoc_show_in, NULL, 27),
+	SENSOR_ATTR(ads1_chan12, S_IRUGO, epm_adc_psoc_show_in, NULL, 28),
+	SENSOR_ATTR(ads1_chan13, S_IRUGO, epm_adc_psoc_show_in, NULL, 29),
+	SENSOR_ATTR(ads1_chan14, S_IRUGO, epm_adc_psoc_show_in, NULL, 30),
+	SENSOR_ATTR(ads1_chan15, S_IRUGO, epm_adc_psoc_show_in, NULL, 31),
+};
+
+static int __devinit epm_adc_psoc_init_hwmon(struct spi_device *spi,
+						struct epm_adc_drv *epm_adc)
+{
+	int i, rc, num_chans = 15;
+
+	for (i = 0; i < num_chans; i++) {
+		rc = device_create_file(&spi->dev,
+				&epm_adc_psoc_in_attrs[i].dev_attr);
+		if (rc) {
+			dev_err(&spi->dev, "device_create_file failed\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static int get_device_tree_data(struct spi_device *spi)
+{
+	const struct device_node *node = spi->dev.of_node;
+	struct epm_adc_drv *epm_adc;
+	int32_t *epm_ch_gain, *epm_ch_rsense;
+	u32 rc = 0, epm_num_channels, i;
+
+	if (!node)
+		return -EINVAL;
+
+	rc = of_property_read_u32(node,
+			"qcom,channels", &epm_num_channels);
+	if (rc) {
+		dev_err(&spi->dev, "missing channel numbers\n");
+		return -ENODEV;
+	}
+
+	epm_ch_gain = devm_kzalloc(&spi->dev,
+				epm_num_channels, GFP_KERNEL);
+	if (!epm_ch_gain) {
+		dev_err(&spi->dev, "cannot allocate gain\n");
+		return -ENOMEM;
+	}
+
+	epm_ch_rsense = devm_kzalloc(&spi->dev,
+				epm_num_channels, GFP_KERNEL);
+	if (!epm_ch_rsense) {
+		dev_err(&spi->dev, "cannot allocate rsense\n");
+		return -ENOMEM;
+	}
+
+	rc = of_property_read_u32_array(node,
+			"qcom,gain", epm_ch_gain, epm_num_channels);
+	if (rc) {
+		dev_err(&spi->dev, "invalid gain property:%d\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32_array(node,
+			"qcom,rsense", epm_ch_rsense, epm_num_channels);
+	if (rc) {
+		dev_err(&spi->dev, "invalid rsense property:%d\n", rc);
+		return rc;
+	}
+
+	epm_adc = devm_kzalloc(&spi->dev,
+			sizeof(struct epm_adc_drv) +
+			(epm_num_channels *
+			sizeof(struct epm_chan_properties)),
+			GFP_KERNEL);
+	if (!epm_adc) {
+		dev_err(&spi->dev, "Unable to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < epm_num_channels; i++) {
+		epm_adc->epm_psoc_ch_prop[i].resistorvalue =
+							epm_ch_rsense[i];
+		epm_adc->epm_psoc_ch_prop[i].gain =
+							epm_ch_gain[i];
+	}
+
+	epm_adc_drv = epm_adc;
+
+	return 0;
+}
+
+static int __devinit epm_adc_psoc_spi_probe(struct spi_device *spi)
+{
+	struct epm_adc_drv *epm_adc;
+	struct device_node *node = spi->dev.of_node;
+	int rc = 0;
+
+	if (!node) {
+		dev_err(&spi->dev, "no platform data?\n");
+		pr_info("Error in the probe\n");
+		return -EINVAL;
+	}
+
+	if (node)
+		rc = get_device_tree_data(spi);
+	else
+		return -ENODEV;
+
+	epm_adc = epm_adc_drv;
+	epm_adc->misc.name = EPM_ADC_DRIVER_NAME;
+	epm_adc->misc.minor = MISC_DYNAMIC_MINOR;
+	epm_adc_drv->epm_spi_client = spi;
+	epm_adc_drv->epm_spi_client->bits_per_word =
+				EPM_ADC_ADS_SPI_BITS_PER_WORD;
+	rc = epm_adc_psoc_init_hwmon(spi, epm_adc);
+	if (rc) {
+		dev_err(&spi->dev, "msm_adc_dev_init failed\n");
+		return rc;
+	}
+
+	epm_adc->hwmon = hwmon_device_register(&spi->dev);
+	if (IS_ERR(epm_adc->hwmon)) {
+		dev_err(&spi->dev, "hwmon_device_register failed\n");
+		return rc;
+	}
+
+	mutex_init(&epm_adc->conv_lock);
+
+	return rc;
+}
+
+static int __devexit epm_adc_psoc_spi_remove(struct spi_device *spi)
+{
+	epm_adc_drv->epm_spi_client = NULL;
+	return 0;
+}
+
+static const struct of_device_id epm_adc_psoc_match_table[] = {
+	{	.compatible = "qcom,epm-adc",
+	},
+	{}
+};
+
+static struct spi_driver epm_spi_driver = {
+	.probe = epm_adc_psoc_spi_probe,
+	.remove = __devexit_p(epm_adc_psoc_spi_remove),
+	.driver = {
+		.name = EPM_ADC_DRIVER_NAME,
+		.of_match_table = epm_adc_psoc_match_table,
+	},
+};
+
 static ssize_t epm_adc_show_in(struct device *dev,
 				 struct device_attribute *devattr, char *buf)
 {
@@ -786,33 +1754,6 @@
 	return 0;
 }
 
-static int __devinit epm_adc_spi_probe(struct spi_device *spi)
-
-{
-	if (!epm_adc_drv)
-		return -ENODEV;
-	epm_adc_drv->epm_spi_client = spi;
-	epm_adc_drv->epm_spi_client->bits_per_word =
-				EPM_ADC_ADS_SPI_BITS_PER_WORD;
-
-	return 0;
-}
-
-static int __devexit epm_adc_spi_remove(struct spi_device *spi)
-{
-	epm_adc_drv->epm_spi_client = NULL;
-	return 0;
-}
-
-static struct spi_driver epm_spi_driver = {
-	.probe = epm_adc_spi_probe,
-	.remove = __devexit_p(epm_adc_spi_remove),
-	.driver = {
-		.name = EPM_ADC_DRIVER_NAME,
-		.owner = THIS_MODULE,
-	},
-};
-
 static int __devinit epm_adc_probe(struct platform_device *pdev)
 {
 	struct epm_adc_drv *epm_adc;
@@ -863,6 +1804,7 @@
 	epm_adc->bus_id = pdata->bus_id;
 	epm_gpio_expander_base_addr = pdata->gpio_expander_base_addr;
 	epm_adc_expander_register = false;
+
 	return rc;
 }
 
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index c122270..a384103 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -26,6 +26,7 @@
 #include <linux/spmi.h>
 #include <linux/of_irq.h>
 #include <linux/interrupt.h>
+#include <linux/completion.h>
 #include <linux/qpnp/qpnp-adc.h>
 #include <linux/platform_device.h>
 
@@ -33,6 +34,601 @@
 #define QPNP_VADC_MIN_ADC_CODE			0x6000
 /* Max ADC code represents full-scale range of 1.8V */
 #define QPNP_VADC_MAX_ADC_CODE			0xA800
+#define KELVINMIL_DEGMIL	273160
+
+/* Units for temperature below (on x axis) is in 0.1DegC as
+   required by the battery driver. Note the resolution used
+   here to compute the table was done for DegC to milli-volts.
+   In consideration to limit the size of the table for the given
+   temperature range below, the result is linearly interpolated
+   and provided to the battery driver in the units desired for
+   their framework which is 0.1DegC. True resolution of 0.1DegC
+   will result in the below table size to increase by 10 times */
+static const struct qpnp_vadc_map_pt adcmap_btm_threshold[] = {
+	{-300,	1642},
+	{-200,	1544},
+	{-100,	1414},
+	{0,	1260},
+	{10,	1244},
+	{20,	1228},
+	{30,	1212},
+	{40,	1195},
+	{50,	1179},
+	{60,	1162},
+	{70,	1146},
+	{80,	1129},
+	{90,	1113},
+	{100,	1097},
+	{110,	1080},
+	{120,	1064},
+	{130,	1048},
+	{140,	1032},
+	{150,	1016},
+	{160,	1000},
+	{170,	985},
+	{180,	969},
+	{190,	954},
+	{200,	939},
+	{210,	924},
+	{220,	909},
+	{230,	894},
+	{240,	880},
+	{250,	866},
+	{260,	852},
+	{270,	838},
+	{280,	824},
+	{290,	811},
+	{300,	798},
+	{310,	785},
+	{320,	773},
+	{330,	760},
+	{340,	748},
+	{350,	736},
+	{360,	725},
+	{370,	713},
+	{380,	702},
+	{390,	691},
+	{400,	681},
+	{410,	670},
+	{420,	660},
+	{430,	650},
+	{440,	640},
+	{450,	631},
+	{460,	622},
+	{470,	613},
+	{480,	604},
+	{490,	595},
+	{500,	587},
+	{510,	579},
+	{520,	571},
+	{530,	563},
+	{540,	556},
+	{550,	548},
+	{560,	541},
+	{570,	534},
+	{580,	527},
+	{590,	521},
+	{600,	514},
+	{610,	508},
+	{620,	502},
+	{630,	496},
+	{640,	490},
+	{650,	485},
+	{660,	281},
+	{670,	274},
+	{680,	267},
+	{690,	260},
+	{700,	254},
+	{710,	247},
+	{720,	241},
+	{730,	235},
+	{740,	229},
+	{750,	224},
+	{760,	218},
+	{770,	213},
+	{780,	208},
+	{790,	203}
+};
+
+static const struct qpnp_vadc_map_pt adcmap_ntcg_104ef_104fb[] = {
+	{696483,	-40960},
+	{649148,	-39936},
+	{605368,	-38912},
+	{564809,	-37888},
+	{527215,	-36864},
+	{492322,	-35840},
+	{460007,	-34816},
+	{429982,	-33792},
+	{402099,	-32768},
+	{376192,	-31744},
+	{352075,	-30720},
+	{329714,	-29696},
+	{308876,	-28672},
+	{289480,	-27648},
+	{271417,	-26624},
+	{254574,	-25600},
+	{238903,	-24576},
+	{224276,	-23552},
+	{210631,	-22528},
+	{197896,	-21504},
+	{186007,	-20480},
+	{174899,	-19456},
+	{164521,	-18432},
+	{154818,	-17408},
+	{145744,	-16384},
+	{137265,	-15360},
+	{129307,	-14336},
+	{121866,	-13312},
+	{114896,	-12288},
+	{108365,	-11264},
+	{102252,	-10240},
+	{96499,		-9216},
+	{91111,		-8192},
+	{86055,		-7168},
+	{81308,		-6144},
+	{76857,		-5120},
+	{72660,		-4096},
+	{68722,		-3072},
+	{65020,		-2048},
+	{61538,		-1024},
+	{58261,		0},
+	{55177,		1024},
+	{52274,		2048},
+	{49538,		3072},
+	{46962,		4096},
+	{44531,		5120},
+	{42243,		6144},
+	{40083,		7168},
+	{38045,		8192},
+	{36122,		9216},
+	{34308,		10240},
+	{32592,		11264},
+	{30972,		12288},
+	{29442,		13312},
+	{27995,		14336},
+	{26624,		15360},
+	{25333,		16384},
+	{24109,		17408},
+	{22951,		18432},
+	{21854,		19456},
+	{20807,		20480},
+	{19831,		21504},
+	{18899,		22528},
+	{18016,		23552},
+	{17178,		24576},
+	{16384,		25600},
+	{15631,		26624},
+	{14916,		27648},
+	{14237,		28672},
+	{13593,		29696},
+	{12976,		30720},
+	{12400,		31744},
+	{11848,		32768},
+	{11324,		33792},
+	{10825,		34816},
+	{10354,		35840},
+	{9900,		36864},
+	{9471,		37888},
+	{9062,		38912},
+	{8674,		39936},
+	{8306,		40960},
+	{7951,		41984},
+	{7616,		43008},
+	{7296,		44032},
+	{6991,		45056},
+	{6701,		46080},
+	{6424,		47104},
+	{6160,		48128},
+	{5908,		49152},
+	{5667,		50176},
+	{5439,		51200},
+	{5219,		52224},
+	{5010,		53248},
+	{4810,		54272},
+	{4619,		55296},
+	{4440,		56320},
+	{4263,		57344},
+	{4097,		58368},
+	{3938,		59392},
+	{3785,		60416},
+	{3637,		61440},
+	{3501,		62464},
+	{3368,		63488},
+	{3240,		64512},
+	{3118,		65536},
+	{2998,		66560},
+	{2889,		67584},
+	{2782,		68608},
+	{2680,		69632},
+	{2581,		70656},
+	{2490,		71680},
+	{2397,		72704},
+	{2310,		73728},
+	{2227,		74752},
+	{2147,		75776},
+	{2064,		76800},
+	{1998,		77824},
+	{1927,		78848},
+	{1860,		79872},
+	{1795,		80896},
+	{1736,		81920},
+	{1673,		82944},
+	{1615,		83968},
+	{1560,		84992},
+	{1507,		86016},
+	{1456,		87040},
+	{1407,		88064},
+	{1360,		89088},
+	{1314,		90112},
+	{1271,		91136},
+	{1228,		92160},
+	{1189,		93184},
+	{1150,		94208},
+	{1112,		95232},
+	{1076,		96256},
+	{1042,		97280},
+	{1008,		98304},
+	{976,		99328},
+	{945,		100352},
+	{915,		101376},
+	{886,		102400},
+	{859,		103424},
+	{832,		104448},
+	{807,		105472},
+	{782,		106496},
+	{756,		107520},
+	{735,		108544},
+	{712,		109568},
+	{691,		110592},
+	{670,		111616},
+	{650,		112640},
+	{631,		113664},
+	{612,		114688},
+	{594,		115712},
+	{577,		116736},
+	{560,		117760},
+	{544,		118784},
+	{528,		119808},
+	{513,		120832},
+	{498,		121856},
+	{483,		122880},
+	{470,		123904},
+	{457,		124928},
+	{444,		125952},
+	{431,		126976},
+	{419,		128000}
+};
+
+static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
+	{-40,	1758},
+	{-35,	1742},
+	{-30,	1719},
+	{-25,	1691},
+	{-20,	1654},
+	{-15,	1608},
+	{-10,	1551},
+	{-5,	1483},
+	{0,	1404},
+	{5,	1315},
+	{10,	1218},
+	{15,	1114},
+	{20,	1007},
+	{25,	900},
+	{30,	795},
+	{35,	696},
+	{40,	605},
+	{45,	522},
+	{50,	448},
+	{55,	383},
+	{60,	327},
+	{65,	278},
+	{70,	237},
+	{75,	202},
+	{80,	172},
+	{85,	146},
+	{90,	125},
+	{95,	107},
+	{100,	92},
+	{105,	79},
+	{110,	68},
+	{115,	59},
+	{120,	51},
+	{125,	44}
+};
+
+static const struct qpnp_vadc_map_pt adcmap_150k_104ef_104fb[] = {
+	{-40,	1738},
+	{-35,	1714},
+	{-30,	1682},
+	{-25,	1641},
+	{-20,	1589},
+	{-15,	1526},
+	{-10,	1451},
+	{-5,	1363},
+	{0,	1266},
+	{5,	1159},
+	{10,	1048},
+	{15,	936},
+	{20,	825},
+	{25,	720},
+	{30,	622},
+	{35,	533},
+	{40,	454},
+	{45,	385},
+	{50,	326},
+	{55,	275},
+	{60,	232},
+	{65,	195},
+	{70,	165},
+	{75,	139},
+	{80,	118},
+	{85,	100},
+	{90,	85},
+	{95,	73},
+	{100,	62},
+	{105,	53},
+	{110,	46},
+	{115,	40},
+	{120,	34},
+	{125,	30}
+};
+
+static int32_t qpnp_adc_map_linear(const struct qpnp_vadc_map_pt *pts,
+		uint32_t tablesize, int32_t input, int64_t *output)
+{
+	bool descending = 1;
+	uint32_t i = 0;
+
+	if ((pts == NULL) || (output == NULL))
+		return -EINVAL;
+
+	/* Check if table is descending or ascending */
+	if (tablesize > 1) {
+		if (pts[0].x < pts[1].x)
+			descending = 0;
+	}
+
+	while (i < tablesize) {
+		if ((descending == 1) && (pts[i].x < input)) {
+			/* table entry is less than measured
+				value and table is descending, stop */
+			break;
+		} else if ((descending == 0) &&
+				(pts[i].x > input)) {
+			/* table entry is greater than measured
+				value and table is ascending, stop */
+			break;
+		} else {
+			i++;
+		}
+	}
+
+	if (i == 0)
+		*output = pts[0].y;
+	else if (i == tablesize)
+		*output = pts[tablesize-1].y;
+	else {
+		/* result is between search_index and search_index-1 */
+		/* interpolate linearly */
+		*output = (((int32_t) ((pts[i].y - pts[i-1].y)*
+			(input - pts[i-1].x))/
+			(pts[i].x - pts[i-1].x))+
+			pts[i-1].y);
+	}
+
+	return 0;
+}
+
+static int32_t qpnp_adc_map_batt_therm(const struct qpnp_vadc_map_pt *pts,
+		uint32_t tablesize, int32_t input, int64_t *output)
+{
+	bool descending = 1;
+	uint32_t i = 0;
+
+	if ((pts == NULL) || (output == NULL))
+		return -EINVAL;
+
+	/* Check if table is descending or ascending */
+	if (tablesize > 1) {
+		if (pts[0].y < pts[1].y)
+			descending = 0;
+	}
+
+	while (i < tablesize) {
+		if ((descending == 1) && (pts[i].y < input)) {
+			/* table entry is less than measured
+				value and table is descending, stop */
+			break;
+		} else if ((descending == 0) && (pts[i].y > input)) {
+			/* table entry is greater than measured
+				value and table is ascending, stop */
+			break;
+		} else {
+			i++;
+		}
+	}
+
+	if (i == 0) {
+		*output = pts[0].x;
+	} else if (i == tablesize) {
+		*output = pts[tablesize-1].x;
+	} else {
+		/* result is between search_index and search_index-1 */
+		/* interpolate linearly */
+		*output = (((int32_t) ((pts[i].x - pts[i-1].x)*
+			(input - pts[i-1].y))/
+			(pts[i].y - pts[i-1].y))+
+			pts[i-1].x);
+	}
+
+	return 0;
+}
+
+static int64_t qpnp_adc_scale_ratiometric_calib(int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties)
+{
+	int64_t adc_voltage = 0;
+	bool negative_offset = 0;
+
+	if (!chan_properties || !chan_properties->offset_gain_numerator ||
+		!chan_properties->offset_gain_denominator || !adc_properties)
+		return -EINVAL;
+
+	adc_voltage = (adc_code -
+		chan_properties->adc_graph[CALIB_RATIOMETRIC].adc_gnd)
+		* adc_properties->adc_vdd_reference;
+	if (adc_voltage < 0) {
+		negative_offset = 1;
+		adc_voltage = -adc_voltage;
+	}
+	do_div(adc_voltage,
+		chan_properties->adc_graph[CALIB_RATIOMETRIC].dy);
+	if (negative_offset)
+		adc_voltage = -adc_voltage;
+
+	return adc_voltage;
+}
+
+int32_t qpnp_adc_scale_pmic_therm(int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int64_t pmic_voltage = 0;
+	bool negative_offset = 0;
+
+	if (!chan_properties || !chan_properties->offset_gain_numerator ||
+		!chan_properties->offset_gain_denominator || !adc_properties
+		|| !adc_chan_result)
+		return -EINVAL;
+
+	pmic_voltage = (adc_code -
+		chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
+		* chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
+	if (pmic_voltage < 0) {
+		negative_offset = 1;
+		pmic_voltage = -pmic_voltage;
+	}
+	do_div(pmic_voltage,
+		chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
+	if (negative_offset)
+		pmic_voltage = -pmic_voltage;
+	pmic_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
+
+	if (pmic_voltage > 0) {
+		/* 2mV/K */
+		adc_chan_result->measurement = pmic_voltage*
+			chan_properties->offset_gain_denominator;
+
+		do_div(adc_chan_result->measurement,
+			chan_properties->offset_gain_numerator * 2);
+	} else {
+		adc_chan_result->measurement = 0;
+	}
+	/* Change to .001 deg C */
+	adc_chan_result->measurement -= KELVINMIL_DEGMIL;
+	adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_pmic_therm);
+
+/* Scales the ADC code to 0.001 degrees C using the map
+ * table for the XO thermistor.
+ */
+int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int64_t xo_thm = 0;
+
+	if (!chan_properties || !chan_properties->offset_gain_numerator ||
+		!chan_properties->offset_gain_denominator || !adc_properties
+		|| !adc_chan_result)
+		return -EINVAL;
+
+	xo_thm = qpnp_adc_scale_ratiometric_calib(adc_code,
+			adc_properties, chan_properties);
+	xo_thm <<= 4;
+	qpnp_adc_map_linear(adcmap_ntcg_104ef_104fb,
+		ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
+		xo_thm, &adc_chan_result->physical);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_tdkntcg_therm);
+
+int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int64_t bat_voltage = 0;
+
+	bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+			adc_properties, chan_properties);
+
+	return qpnp_adc_map_batt_therm(
+			adcmap_btm_threshold,
+			ARRAY_SIZE(adcmap_btm_threshold),
+			bat_voltage,
+			&adc_chan_result->physical);
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_therm);
+
+int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int64_t therm_voltage = 0;
+
+	therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+			adc_properties, chan_properties);
+
+	qpnp_adc_map_linear(adcmap_150k_104ef_104fb,
+		ARRAY_SIZE(adcmap_150k_104ef_104fb),
+		therm_voltage, &adc_chan_result->physical);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu1);
+
+int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int64_t therm_voltage = 0;
+
+	therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+			adc_properties, chan_properties);
+
+	qpnp_adc_map_linear(adcmap_100k_104ef_104fb,
+		ARRAY_SIZE(adcmap_100k_104ef_104fb),
+		therm_voltage, &adc_chan_result->physical);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu2);
+
+int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int64_t batt_id_voltage = 0;
+
+	batt_id_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+			adc_properties, chan_properties);
+	adc_chan_result->physical = batt_id_voltage;
+	adc_chan_result->physical = adc_chan_result->measurement;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_id);
 
 int32_t qpnp_adc_scale_default(int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
@@ -203,7 +799,7 @@
 				"qcom,calibration-type", NULL);
 		if (!strncmp(calibration_param, "absolute", 8))
 			calib_type = CALIB_ABSOLUTE;
-		else if (!strncmp(calibration_param, "historical", 9))
+		else if (!strncmp(calibration_param, "ratiometric", 11))
 			calib_type = CALIB_RATIOMETRIC;
 		else {
 			pr_err("%s: Invalid calibration property\n", __func__);
@@ -252,6 +848,8 @@
 		return -ENXIO;
 	}
 
+	init_completion(&adc_qpnp->adc_rslt_completion);
+
 	mutex_init(&adc_qpnp->adc_lock);
 
 	return 0;
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index b689255..aa375d7 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -33,6 +33,15 @@
 #include <linux/platform_device.h>
 
 /* QPNP IADC register definition */
+#define QPNP_IADC_REVISION1				0x0
+#define QPNP_IADC_REVISION2				0x1
+#define QPNP_IADC_REVISION3				0x2
+#define QPNP_IADC_REVISION4				0x3
+#define QPNP_IADC_PERPH_TYPE				0x4
+#define QPNP_IADC_PERH_SUBTYPE				0x5
+
+#define QPNP_IADC_SUPPORTED_REVISION2			1
+
 #define QPNP_STATUS1					0x8
 #define QPNP_STATUS1_OP_MODE				4
 #define QPNP_STATUS1_MULTI_MEAS_EN			BIT(3)
@@ -67,13 +76,14 @@
 #define QPNP_INT_CLR_FIFO_NOT_EMPTY_INT_EN		BIT(1)
 #define QPNP_INT_CLR_EOC_INT_EN_CLR			BIT(0)
 #define QPNP_INT_CLR_MASK				0x1f
-#define QPNP_MODE_CTL					0x40
+#define QPNP_IADC_MODE_CTL				0x40
 #define QPNP_OP_MODE_SHIFT				4
 #define QPNP_USE_BMS_DATA				BIT(4)
 #define QPNP_VADC_SYNCH_EN				BIT(2)
 #define QPNP_OFFSET_RMV_EN				BIT(1)
 #define QPNP_ADC_TRIM_EN				BIT(0)
-#define QPNP_EN_CTL1					0x46
+#define QPNP_IADC_EN_CTL1				0x46
+#define QPNP_IADC_ADC_EN				BIT(7)
 #define QPNP_ADC_CH_SEL_CTL				0x48
 #define QPNP_ADC_DIG_PARAM				0x50
 #define QPNP_ADC_CLK_SEL_MASK				0x3
@@ -101,13 +111,6 @@
 #define QPNP_DATA1					0x61
 #define QPNP_CONV_TIMEOUT_ERR				2
 
-#define QPNP_IADC_MODE_CTL				0x40
-#define QPNP_IADC_USE_BMS_DATA				BIT(4)
-#define QPNP_IADC_RESERVED_BIT3				BIT(3)
-#define QPNP_IADC_VADC_SYNC_EN				BIT(2)
-#define QPNP_IADC_OFFSET_RMV_EN				BIT(1)
-#define QPNP_IADC_ADC_TRIM_EN				BIT(0)
-
 #define QPNP_IADC_ADC_CH_SEL_CTL			0x48
 #define QPNP_IADC_ADC_CHX_SEL_SHIFT			3
 
@@ -121,16 +124,18 @@
 #define QPNP_IADC_DATA0					0x60
 #define QPNP_IADC_DATA1					0x61
 
-#define QPNP_ADC_CONV_TIME_MIN				2000
-#define QPNP_ADC_CONV_TIME_MAX				2200
+#define QPNP_ADC_CONV_TIME_MIN				8000
+#define QPNP_ADC_CONV_TIME_MAX				8200
 
-#define QPNP_ADC_GAIN_CALCULATION			2500
+#define QPNP_ADC_GAIN_CALCULATION_UV			17857
+#define QPNP_IADC_RSENSE_MILLI_FACTOR			1000
 
 struct qpnp_iadc_drv {
 	struct qpnp_adc_drv		*adc;
 	int32_t				rsense;
 	struct device			*iadc_hwmon;
 	bool				iadc_init_calib;
+	bool				iadc_initialized;
 	struct sensor_device_attribute		sens_attr[0];
 };
 
@@ -223,6 +228,31 @@
 	return IRQ_HANDLED;
 }
 
+static int32_t qpnp_iadc_enable(bool state)
+{
+	int rc = 0;
+	u8 data = 0;
+
+	data = QPNP_IADC_ADC_EN;
+	if (state) {
+		rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
+					data);
+		if (rc < 0) {
+			pr_err("IADC enable failed\n");
+			return rc;
+		}
+	} else {
+		rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
+					(~data & QPNP_IADC_ADC_EN));
+		if (rc < 0) {
+			pr_err("IADC disable failed\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
 static int32_t qpnp_iadc_read_conversion_result(int32_t *data)
 {
 	uint8_t rslt_lsb, rslt_msb;
@@ -242,12 +272,9 @@
 
 	*data = (rslt_msb << 8) | rslt_lsb;
 
-	rc = qpnp_vadc_check_result(data);
-	if (rc < 0) {
-		pr_err("VADC data check failed\n");
+	rc = qpnp_iadc_enable(false);
+	if (rc)
 		return rc;
-	}
-
 	return 0;
 }
 
@@ -259,10 +286,7 @@
 	u8 qpnp_iadc_conv_req = 0, qpnp_iadc_dig_param_reg = 0;
 	int32_t rc = 0;
 
-	qpnp_iadc_mode_reg |= (QPNP_IADC_USE_BMS_DATA | QPNP_IADC_USE_BMS_DATA
-			| QPNP_IADC_OFFSET_RMV_EN | QPNP_IADC_ADC_TRIM_EN);
-
-	qpnp_iadc_ch_sel_reg = channel << QPNP_IADC_ADC_CHX_SEL_SHIFT;
+	qpnp_iadc_ch_sel_reg = channel;
 
 	qpnp_iadc_dig_param_reg |= iadc->adc->amux_prop->decimation <<
 					QPNP_IADC_DEC_RATIO_SEL;
@@ -310,6 +334,10 @@
 		return rc;
 	}
 
+	rc = qpnp_iadc_enable(true);
+	if (rc)
+		return rc;
+
 	rc = qpnp_iadc_write_reg(QPNP_CONV_REQ, qpnp_iadc_conv_req);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
@@ -353,17 +381,53 @@
 	return rc;
 }
 
+static int32_t qpnp_iadc_version_check(void)
+{
+	uint8_t revision;
+	int rc;
+
+	rc = qpnp_iadc_read_reg(QPNP_IADC_REVISION2, &revision);
+	if (rc < 0) {
+		pr_err("qpnp adc result read failed with %d\n", rc);
+		return rc;
+	}
+
+	if (revision < QPNP_IADC_SUPPORTED_REVISION2) {
+		pr_err("IADC Version not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int32_t qpnp_iadc_is_ready(void)
+{
+	struct qpnp_iadc_drv *iadc = qpnp_iadc;
+
+	if (!iadc || !iadc->iadc_initialized)
+		return -EPROBE_DEFER;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(qpnp_iadc_is_ready);
+
 int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
 						int32_t *result)
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
 	int32_t vsense_mv = 0, rc;
 
+	if (!iadc || !iadc->iadc_initialized)
+		return -EPROBE_DEFER;
+
 	mutex_lock(&iadc->adc->adc_lock);
 
 	if (!iadc->iadc_init_calib) {
+		rc = qpnp_iadc_version_check();
+		if (rc)
+			goto fail;
 		rc = qpnp_iadc_init_calib();
-		if (!rc) {
+		if (rc) {
 			pr_err("Calibration failed\n");
 			goto fail;
 		} else
@@ -376,12 +440,11 @@
 		goto fail;
 	}
 
-	vsense_mv = ((*result - iadc->adc->calib.offset)/
-			(iadc->adc->calib.gain - iadc->adc->calib.offset))
-			* QPNP_ADC_GAIN_CALCULATION;
+	*result = ((vsense_mv - iadc->adc->calib.offset) *
+				QPNP_ADC_GAIN_CALCULATION_UV)/
+			(iadc->adc->calib.gain - iadc->adc->calib.offset);
 
-	*result = (vsense_mv/qpnp_iadc->rsense);
-
+	*result = (*result / (qpnp_iadc->rsense));
 fail:
 	mutex_unlock(&iadc->adc->adc_lock);
 
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 9e8a2e2..5690c88 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -32,6 +32,15 @@
 #include <linux/platform_device.h>
 
 /* QPNP VADC register definition */
+#define QPNP_VADC_REVISION1				0x0
+#define QPNP_VADC_REVISION2				0x1
+#define QPNP_VADC_REVISION3				0x2
+#define QPNP_VADC_REVISION4				0x3
+#define QPNP_VADC_PERPH_TYPE				0x4
+#define QPNP_VADC_PERH_SUBTYPE				0x5
+
+#define QPNP_VADC_SUPPORTED_REVISION2			1
+
 #define QPNP_VADC_STATUS1					0x8
 #define QPNP_VADC_STATUS1_OP_MODE				4
 #define QPNP_VADC_STATUS1_MEAS_INTERVAL_EN_STS			BIT(2)
@@ -98,6 +107,8 @@
 	struct dentry			*dent;
 	struct device			*vadc_hwmon;
 	bool				vadc_init_calib;
+	bool				vadc_initialized;
+	int				max_channels_available;
 	struct sensor_device_attribute		sens_attr[0];
 };
 
@@ -105,6 +116,11 @@
 
 static struct qpnp_vadc_scale_fn vadc_scale_fn[] = {
 	[SCALE_DEFAULT] = {qpnp_adc_scale_default},
+	[SCALE_BATT_THERM] = {qpnp_adc_scale_batt_therm},
+	[SCALE_PMIC_THERM] = {qpnp_adc_scale_pmic_therm},
+	[SCALE_XOTHERM] = {qpnp_adc_tdkntcg_therm},
+	[SCALE_THERM_100K_PULLUP] = {qpnp_adc_scale_therm_pu2},
+	[SCALE_THERM_150K_PULLUP] = {qpnp_adc_scale_therm_pu1},
 };
 
 static int32_t qpnp_vadc_read_reg(int16_t reg, u8 *data)
@@ -206,32 +222,21 @@
 	u8 mode_ctrl = 0;
 	int rc = 0;
 
-	if (vadc->vadc_init_calib) {
-		/* Configure interrupt if calibration is complete */
-		rc = qpnp_vadc_write_reg(QPNP_VADC_INT_EN_SET,
-				QPNP_VADC_INT_EOC_BIT);
-		if (rc < 0) {
-			pr_err("Configure error for interrupt setup\n");
-			return rc;
-		}
+	rc = qpnp_vadc_write_reg(QPNP_VADC_INT_EN_SET,
+			QPNP_VADC_INT_EOC_BIT);
+	if (rc < 0) {
+		pr_err("Configure error for interrupt setup\n");
+		return rc;
 	}
 
 	/* Mode selection */
-	rc = qpnp_vadc_read_reg(QPNP_VADC_MODE_CTL, &mode_ctrl);
-	if (rc < 0) {
-		pr_err("Mode configure read error\n");
-		return rc;
-	}
-	mode_ctrl |= chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT;
+	mode_ctrl = chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT;
 	rc = qpnp_vadc_write_reg(QPNP_VADC_MODE_CTL, mode_ctrl);
 	if (rc < 0) {
 		pr_err("Mode configure write error\n");
 		return rc;
 	}
 
-	rc = qpnp_vadc_enable(true);
-	if (rc)
-		return rc;
 
 	/* Channel selection */
 	rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_CH_SEL_CTL,
@@ -242,12 +247,7 @@
 	}
 
 	/* Digital parameter setup */
-	rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_DIG_PARAM, &decimation);
-	if (rc < 0) {
-		pr_err("Digital parameter configure read error\n");
-		return rc;
-	}
-	decimation |= chan_prop->decimation <<
+	decimation = chan_prop->decimation <<
 				QPNP_VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT;
 	rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_DIG_PARAM, decimation);
 	if (rc < 0) {
@@ -296,6 +296,12 @@
 		}
 	}
 
+	INIT_COMPLETION(vadc->adc->adc_rslt_completion);
+
+	rc = qpnp_vadc_enable(true);
+	if (rc)
+		return rc;
+
 	/* Request conversion */
 	rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_REQ, QPNP_VADC_CONV_REQ_SET);
 	if (rc < 0) {
@@ -402,6 +408,25 @@
 	return IRQ_HANDLED;
 }
 
+static int32_t qpnp_vadc_version_check(void)
+{
+	uint8_t revision;
+	int rc;
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_REVISION2, &revision);
+	if (rc < 0) {
+		pr_err("qpnp adc result read failed with %d\n", rc);
+		return rc;
+	}
+
+	if (revision < QPNP_VADC_SUPPORTED_REVISION2) {
+		pr_err("VADC Version not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static uint32_t qpnp_vadc_calib_device(void)
 {
 	struct qpnp_vadc_drv *vadc = qpnp_vadc;
@@ -421,8 +446,7 @@
 		goto calib_fail;
 	}
 
-	while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
-					QPNP_VADC_STATUS1_EOC)) {
+	while (status1 != QPNP_VADC_STATUS1_EOC) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
@@ -449,8 +473,7 @@
 	}
 
 	status1 = 0;
-	while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
-					QPNP_VADC_STATUS1_EOC)) {
+	while (status1 != QPNP_VADC_STATUS1_EOC) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
@@ -459,7 +482,7 @@
 					QPNP_VADC_CONV_TIME_MAX);
 	}
 
-	rc = qpnp_vadc_read_conversion_result(&calib_read_1);
+	rc = qpnp_vadc_read_conversion_result(&calib_read_2);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
 		goto calib_fail;
@@ -467,6 +490,7 @@
 
 	vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy =
 					(calib_read_1 - calib_read_2);
+
 	vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx
 						= QPNP_ADC_625_UV;
 	vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_vref =
@@ -486,8 +510,7 @@
 	}
 
 	status1 = 0;
-	while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
-					QPNP_VADC_STATUS1_EOC)) {
+	while (status1 != QPNP_VADC_STATUS1_EOC) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
@@ -502,7 +525,7 @@
 		goto calib_fail;
 	}
 
-	conv.amux_channel = VDD_VADC;
+	conv.amux_channel = GND_REF;
 	conv.decimation = DECIMATION_TYPE2;
 	conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
 	conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
@@ -514,8 +537,7 @@
 	}
 
 	status1 = 0;
-	while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
-					QPNP_VADC_STATUS1_EOC)) {
+	while (status1 != QPNP_VADC_STATUS1_EOC) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
@@ -524,7 +546,7 @@
 					QPNP_VADC_CONV_TIME_MAX);
 	}
 
-	rc = qpnp_vadc_read_conversion_result(&calib_read_1);
+	rc = qpnp_vadc_read_conversion_result(&calib_read_2);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
 		goto calib_fail;
@@ -543,14 +565,31 @@
 	return rc;
 }
 
+int32_t qpnp_vadc_is_ready(void)
+{
+	struct qpnp_vadc_drv *vadc = qpnp_vadc;
+
+	if (!vadc || !vadc->vadc_initialized)
+		return -EPROBE_DEFER;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(qpnp_vadc_is_ready);
+
 int32_t qpnp_vadc_conv_seq_request(enum qpnp_vadc_trigger trigger_channel,
 					enum qpnp_vadc_channels channel,
 					struct qpnp_vadc_result *result)
 {
 	struct qpnp_vadc_drv *vadc = qpnp_vadc;
-	int rc = 0, scale_type, amux_prescaling;
+	int rc = 0, scale_type, amux_prescaling, dt_index = 0;
+
+	if (!vadc || !vadc->vadc_initialized)
+		return -EPROBE_DEFER;
 
 	if (!vadc->vadc_init_calib) {
+		rc = qpnp_vadc_version_check();
+		if (rc)
+			return rc;
 		rc = qpnp_vadc_calib_device();
 		if (rc) {
 			pr_err("Calibration failed\n");
@@ -562,12 +601,20 @@
 	mutex_lock(&vadc->adc->adc_lock);
 
 	vadc->adc->amux_prop->amux_channel = channel;
+
+	while (vadc->adc->adc_channels[dt_index].channel_num
+			!= channel || dt_index > vadc->max_channels_available)
+		dt_index++;
+
+	if (dt_index > vadc->max_channels_available)
+		goto fail_unlock;
+
 	vadc->adc->amux_prop->decimation =
-			vadc->adc->adc_channels[channel].adc_decimation;
+			vadc->adc->adc_channels[dt_index].adc_decimation;
 	vadc->adc->amux_prop->hw_settle_time =
-			vadc->adc->adc_channels[channel].hw_settle_time;
+			vadc->adc->adc_channels[dt_index].hw_settle_time;
 	vadc->adc->amux_prop->fast_avg_setup =
-			vadc->adc->adc_channels[channel].fast_avg_setup;
+			vadc->adc->adc_channels[dt_index].fast_avg_setup;
 
 	if (trigger_channel < ADC_SEQ_NONE)
 		vadc->adc->amux_prop->mode_sel = (ADC_OP_CONVERSION_SEQUENCER
@@ -602,14 +649,15 @@
 		goto fail_unlock;
 	}
 
-	amux_prescaling = vadc->adc->adc_channels[channel].chan_path_prescaling;
+	amux_prescaling =
+		vadc->adc->adc_channels[dt_index].chan_path_prescaling;
 
 	vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
 		qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
 	vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
 		 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
 
-	scale_type = vadc->adc->adc_channels[channel].adc_scale_fn;
+	scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
 	if (scale_type >= SCALE_NONE) {
 		rc = -EBADF;
 		goto fail_unlock;
@@ -642,8 +690,10 @@
 
 	rc = qpnp_vadc_read(attr->index, &result);
 
-	if (rc)
+	if (rc) {
+		pr_err("VADC read error with %d\n", rc);
 		return 0;
+	}
 
 	return snprintf(buf, QPNP_ADC_HWMON_NAME_LENGTH,
 		"Result:%lld Raw:%d\n", result.physical, result.adc_code);
@@ -738,6 +788,8 @@
 		dev_err(&spmi->dev,
 			"failed to request adc irq with error %d\n", rc);
 		return rc;
+	} else {
+		enable_irq_wake(vadc->adc->adc_irq);
 	}
 
 	qpnp_vadc = vadc;
@@ -749,6 +801,8 @@
 	}
 	vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
 	vadc->vadc_init_calib = false;
+	vadc->vadc_initialized = true;
+	vadc->max_channels_available = count_adc_channel_list;
 
 	rc = qpnp_vadc_configure_interrupt();
 	if (rc) {
@@ -777,6 +831,7 @@
 		i++;
 	}
 	free_irq(vadc->adc->adc_irq, vadc);
+	vadc->vadc_initialized = false;
 	dev_set_drvdata(&spmi->dev, NULL);
 
 	return 0;
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index 58f9661..9f64cec 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,8 @@
 struct pmic8xxx_pwrkey {
 	struct input_dev *pwr;
 	int key_press_irq;
+	int key_release_irq;
+	bool press;
 	const struct pm8xxx_pwrkey_platform_data *pdata;
 };
 
@@ -42,6 +44,13 @@
 {
 	struct pmic8xxx_pwrkey *pwrkey = _pwrkey;
 
+	if (pwrkey->press == true) {
+		pwrkey->press = false;
+		return IRQ_HANDLED;
+	} else {
+		pwrkey->press = true;
+	}
+
 	input_report_key(pwrkey->pwr, KEY_POWER, 1);
 	input_sync(pwrkey->pwr);
 
@@ -52,6 +61,14 @@
 {
 	struct pmic8xxx_pwrkey *pwrkey = _pwrkey;
 
+	if (pwrkey->press == false) {
+		input_report_key(pwrkey->pwr, KEY_POWER, 1);
+		input_sync(pwrkey->pwr);
+		pwrkey->press = true;
+	} else {
+		pwrkey->press = false;
+	}
+
 	input_report_key(pwrkey->pwr, KEY_POWER, 0);
 	input_sync(pwrkey->pwr);
 
@@ -63,8 +80,10 @@
 {
 	struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
 
-	if (device_may_wakeup(dev))
+	if (device_may_wakeup(dev)) {
 		enable_irq_wake(pwrkey->key_press_irq);
+		enable_irq_wake(pwrkey->key_release_irq);
+	}
 
 	return 0;
 }
@@ -73,8 +92,10 @@
 {
 	struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
 
-	if (device_may_wakeup(dev))
+	if (device_may_wakeup(dev)) {
 		disable_irq_wake(pwrkey->key_press_irq);
+		disable_irq_wake(pwrkey->key_release_irq);
+	}
 
 	return 0;
 }
@@ -155,7 +176,9 @@
 	}
 
 	pwrkey->key_press_irq = key_press_irq;
+	pwrkey->key_release_irq = key_release_irq;
 	pwrkey->pwr = pwr;
+	pwrkey->press = false;
 
 	platform_set_drvdata(pdev, pwrkey);
 
diff --git a/drivers/input/touchscreen/cyttsp-i2c-qc.c b/drivers/input/touchscreen/cyttsp-i2c-qc.c
index d8881a4..e54a24a 100644
--- a/drivers/input/touchscreen/cyttsp-i2c-qc.c
+++ b/drivers/input/touchscreen/cyttsp-i2c-qc.c
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
@@ -422,7 +423,7 @@
 static int cyttsp_set_sysinfo_mode(struct cyttsp *ts, u8 sleep)
 {
 	int retval;
-	u8 mode = CY_SYSINFO_MODE + sleep;
+	u8 mode = CY_SYSINFO_MODE | sleep;
 
 	cyttsp_change_state(ts, CY_SYSINFO);
 
@@ -448,10 +449,10 @@
 	return retval;
 }
 
-static void cyttsp_set_opmode(struct cyttsp *ts, u8 sleep)
+static int cyttsp_set_opmode(struct cyttsp *ts, u8 sleep)
 {
 	int retval, tries = 0;
-	u8 host_reg = CY_OP_MODE + sleep;
+	u8 host_reg = CY_OP_MODE | sleep;
 
 	cyttsp_change_state(ts, CY_ACTIVE);
 	do {
@@ -460,6 +461,8 @@
 		if (retval < 0)
 			msleep(20);
 	} while (tries++ < 10 && (retval < 0));
+
+	return retval;
 }
 
 static int cyttsp_set_lp_mode(struct cyttsp *ts)
@@ -878,7 +881,8 @@
 	cyttsp_exit_bl_mode(ts);
 	msleep(100);
 	/* set low power mode and enter application mode*/
-	cyttsp_set_lp_mode(ts);
+	if (ts->platform_data->use_sleep & CY_LOW_PWR_MODE)
+		cyttsp_set_lp_mode(ts);
 }
 
 static void cyttspfw_upgrade_start(struct cyttsp *ts, const u8 *data,
@@ -1154,7 +1158,9 @@
 				tries++ < 100);
 			cyttsp_putbl(ts, 2, true, false, false);
 		}
-		cyttsp_set_lp_mode(ts);
+		if (ts->platform_data->use_sleep & CY_LOW_PWR_MODE)
+			cyttsp_set_lp_mode(ts);
+
 		goto exit_xy_handler;
 	} else {
 		cur_tch = GET_NUM_TOUCHES(g_xy_data.tt_stat);
@@ -1693,22 +1699,9 @@
 			cyttsp_debug("ST->F1:%3d X:%3d Y:%3d Z:%3d\n", \
 				cur_st_tch[CY_ST_FNGR1_IDX], \
 				st_x1, st_y1, st_z1);
-			if (cur_st_tch[CY_ST_FNGR2_IDX] < CY_NUM_TRK_ID) {
-				input_report_key(ts->input, BTN_2, CY_TCH);
-				input_report_abs(ts->input, ABS_HAT0X, st_x2);
-				input_report_abs(ts->input, ABS_HAT0Y, st_y2);
-				cyttsp_debug("ST->F2:%3d X:%3d Y:%3d Z:%3d\n", \
-					cur_st_tch[CY_ST_FNGR2_IDX],
-					st_x2, st_y2, st_z2);
-			} else {
-				input_report_key(ts->input,
-					BTN_2,
-					CY_NTCH);
-			}
 		} else {
 			input_report_abs(ts->input, ABS_PRESSURE, CY_NTCH);
 			input_report_key(ts->input, BTN_TOUCH, CY_NTCH);
-			input_report_key(ts->input, BTN_2, CY_NTCH);
 		}
 		/* update platform data for the current single touch info */
 		ts->prv_st_tch[CY_ST_FNGR1_IDX] = cur_st_tch[CY_ST_FNGR1_IDX];
@@ -1852,6 +1845,9 @@
 					id, tmp_trk[id], \
 					id, snd_trk[id]);
 				if (snd_trk[id] < CY_NUM_TRK_ID) {
+					input_mt_slot(ts->input, snd_trk[id]);
+					input_mt_report_slot_state(ts->input,
+						MT_TOOL_FINGER, true);
 					input_report_abs(ts->input,
 						ABS_MT_TOUCH_MAJOR,
 						cur_mt_z[snd_trk[id]]);
@@ -1864,7 +1860,6 @@
 					input_report_abs(ts->input,
 						ABS_MT_POSITION_Y,
 						cur_mt_pos[snd_trk[id]][CY_YPOS]);
-					CY_MT_SYNC(ts->input);
 					cyttsp_debug("MT1->TID:%2d X:%3d Y:%3d Z:%3d touch-sent\n", \
 						snd_trk[id], \
 						cur_mt_pos[snd_trk[id]][CY_XPOS], \
@@ -1872,19 +1867,10 @@
 						cur_mt_z[snd_trk[id]]);
 				} else if (ts->prv_mt_tch[id] < CY_NUM_TRK_ID) {
 					/* void out this touch */
-					input_report_abs(ts->input,
-						ABS_MT_TOUCH_MAJOR,
-						CY_NTCH);
-					input_report_abs(ts->input,
-						ABS_MT_WIDTH_MAJOR,
-						curr_tool_width);
-					input_report_abs(ts->input,
-						ABS_MT_POSITION_X,
-						ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_XPOS]);
-					input_report_abs(ts->input,
-						ABS_MT_POSITION_Y,
-						ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_YPOS]);
-					CY_MT_SYNC(ts->input);
+					input_mt_slot(ts->input,
+						ts->prv_mt_tch[id]);
+					input_mt_report_slot_state(ts->input,
+						MT_TOOL_FINGER, false);
 					cyttsp_debug("MT2->TID:%2d X:%3d Y:%3d Z:%3d lift off-sent\n", \
 						ts->prv_mt_tch[id], \
 						ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_XPOS], \
@@ -2555,7 +2541,11 @@
 
 	/* switch to System Information mode to read versions
 	 * and set interval registers */
-	retval = cyttsp_set_sysinfo_mode(ts, CY_LOW_PWR_MODE);
+	if (ts->platform_data->use_sleep & CY_LOW_PWR_MODE)
+		retval = cyttsp_set_sysinfo_mode(ts, CY_LOW_PWR_MODE);
+	else
+		retval = cyttsp_set_opmode(ts, CY_OP_MODE);
+
 	if (!(retval < CY_OK)) {
 		retval = i2c_smbus_read_i2c_block_data(ts->client,
 			CY_REG_BASE,
@@ -2577,7 +2567,10 @@
 	/* switch back to Operational mode */
 	cyttsp_debug("switch back to operational mode\n");
 	if (!(retval < CY_OK)) {
-		cyttsp_set_opmode(ts, CY_LOW_PWR_MODE);
+		if (ts->platform_data->use_sleep & CY_LOW_PWR_MODE)
+			cyttsp_set_opmode(ts, CY_LOW_PWR_MODE);
+		else
+			cyttsp_set_opmode(ts, CY_OP_MODE);
 		/* wait for TTSP Device to complete
 		 * switch to Operational mode */
 		msleep(100);
@@ -2667,7 +2660,6 @@
 	set_bit(EV_KEY, input_device->evbit);
 	set_bit(EV_ABS, input_device->evbit);
 	set_bit(BTN_TOUCH, input_device->keybit);
-	set_bit(BTN_2, input_device->keybit);
 	set_bit(INPUT_PROP_DIRECT, input_device->propbit);
 
 	if (ts->platform_data->use_gestures)
@@ -2681,10 +2673,6 @@
 		ABS_TOOL_WIDTH, 0, CY_LARGE_TOOL_WIDTH, 0 , 0);
 	input_set_abs_params(input_device,
 		ABS_PRESSURE, 0, CY_MAXZ, 0, 0);
-	input_set_abs_params(input_device,
-		ABS_HAT0X, 0, ts->platform_data->panel_maxx, 0, 0);
-	input_set_abs_params(input_device,
-		ABS_HAT0Y, 0, ts->platform_data->panel_maxy, 0, 0);
 	if (ts->platform_data->use_gestures) {
 		input_set_abs_params(input_device,
 			ABS_HAT1X, 0, CY_MAXZ, 0, 0);
@@ -2702,6 +2690,7 @@
 			ABS_MT_TOUCH_MAJOR, 0, CY_MAXZ, 0, 0);
 		input_set_abs_params(input_device,
 			ABS_MT_WIDTH_MAJOR, 0, CY_LARGE_TOOL_WIDTH, 0, 0);
+		input_mt_init_slots(input_device, CY_NUM_TRK_ID);
 		if (ts->platform_data->use_trk_id) {
 			input_set_abs_params(input_device,
 				ABS_MT_TRACKING_ID, 0, CY_NUM_TRK_ID, 0, 0);
@@ -2982,7 +2971,8 @@
 #endif /* CONFIG_HAS_EARLYSUSPEND */
 	device_init_wakeup(&client->dev, ts->platform_data->wakeup);
 	mutex_init(&ts->mutex);
-	retval = cyttsp_set_lp_mode(ts);
+	if (ts->platform_data->use_sleep & CY_LOW_PWR_MODE)
+		retval = cyttsp_set_lp_mode(ts);
 
 	cyttsp_info("Start Probe %s\n", \
 		(retval < CY_OK) ? "FAIL" : "PASS");
@@ -3119,7 +3109,10 @@
 	cyttsp_debug("Wake Up %s\n", \
 		(retval < CY_OK) ? "FAIL" : "PASS");
 
-	return cyttsp_set_lp_mode(ts);
+	if (ts->platform_data->use_sleep & CY_LOW_PWR_MODE)
+		retval = cyttsp_set_lp_mode(ts);
+
+	return retval;
 }
 
 /* Function to manage low power suspend */
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c
index de31859..c7f6b82 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v2.c
@@ -256,19 +256,30 @@
 		SET_SMR_MASK(base, num, 0);
 		SET_SMR_ID(base, num, sids[i]);
 
-		/* Set VMID = 0 */
 		SET_S2CR_N(base, num, 0);
 		SET_S2CR_CBNDX(base, num, ctx);
+		SET_S2CR_MEMATTR(base, num, 0x0A);
 		/* Set security bit override to be Non-secure */
 		SET_S2CR_NSCFG(base, num, 3);
 	}
 
 	SET_CBAR_N(base, ctx, 0);
+
 	/* Stage 1 Context with Stage 2 bypass */
 	SET_CBAR_TYPE(base, ctx, 1);
+
 	/* Route page faults to the non-secure interrupt */
 	SET_CBAR_IRPTNDX(base, ctx, 1);
 
+	/* Set VMID to non-secure HLOS */
+	SET_CBAR_VMID(base, ctx, 3);
+
+	/* Bypass is treated as inner-shareable */
+	SET_CBAR_BPSHCFG(base, ctx, 2);
+
+	/* Do not downgrade memory attributes */
+	SET_CBAR_MEMATTR(base, ctx, 0x0A);
+
        /* Find if this page table is used elsewhere, and re-use ASID */
 	found = 0;
 	for (i = 0; i < ncb; i++)
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
index 68cfcd1..893273d 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
@@ -13,7 +13,7 @@
 #ifndef _MPQ_DMX_PLUGIN_COMMON_H
 #define _MPQ_DMX_PLUGIN_COMMON_H
 
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include "dvbdev.h"
 #include "dmxdev.h"
diff --git a/drivers/media/dvb/mpq/video/mpq_dvb_video.c b/drivers/media/dvb/mpq/video/mpq_dvb_video.c
index cd0f605..3dc31bb 100644
--- a/drivers/media/dvb/mpq/video/mpq_dvb_video.c
+++ b/drivers/media/dvb/mpq/video/mpq_dvb_video.c
@@ -55,6 +55,8 @@
 
 static int mpq_int_vid_dec_decode_frame(struct video_client_ctx *client_ctx,
 				struct video_data_buffer *input_frame);
+static int mpq_int_vid_dec_get_buffer_req(struct video_client_ctx *client_ctx,
+				  struct video_buffer_req *vdec_buf_req);
 
 static struct mpq_dvb_video_dev *mpq_dvb_video_device;
 
@@ -63,7 +65,6 @@
 {
 	int i;
 
-	mutex_lock(&mpq_dvb_video_device->lock);
 	for (i = 0; i < DVB_MPQ_NUM_VIDEO_DEVICES; i++) {
 		if (mpq_dvb_video_device->dev_inst[i].client_ctx ==
 						client_ctx) {
@@ -71,7 +72,6 @@
 			break;
 		}
 	}
-	mutex_unlock(&mpq_dvb_video_device->lock);
 
 	if (i == DVB_MPQ_NUM_VIDEO_DEVICES)
 		return -ENODEV;
@@ -423,26 +423,26 @@
 		mutex_unlock(&client_ctx->msg_queue_lock);
 		wake_up(&client_ctx->msg_wait);
 	} else {
-		bcast_msg = kzalloc(sizeof(struct mpq_bcast_msg),
-					GFP_KERNEL);
-		if (!bcast_msg) {
-			DBG("mpq_int_vid_dec_input_frame_done(): "\
-				"cannot allocate mpq_bcast_msg buffer\n");
-			return;
-		}
-
 		if (event == VCD_EVT_RESP_INPUT_DONE) {
+			bcast_msg = kzalloc(sizeof(struct mpq_bcast_msg),
+						GFP_KERNEL);
+			if (!bcast_msg) {
+				DBG("mpq_int_vid_dec_input_frame_done(): "\
+				"cannot allocate mpq_bcast_msg buffer\n");
+				return;
+			}
+
 			bcast_msg->info.code = MPQ_BCAST_MSG_IBD;
 			bcast_msg->info.data =
 				(unsigned int)vcd_frame_data->frm_clnt_data;
+
+			dmx_data = dev_inst->dmx_src_data;
+
+			mutex_lock(&dmx_data->msg_queue_lock);
+			list_add_tail(&bcast_msg->list, &dmx_data->msg_queue);
+			mutex_unlock(&dmx_data->msg_queue_lock);
+			wake_up(&dmx_data->msg_wait);
 		}
-
-		dmx_data = dev_inst->dmx_src_data;
-
-		mutex_lock(&dmx_data->msg_queue_lock);
-		list_add_tail(&bcast_msg->list, &dmx_data->msg_queue);
-		mutex_unlock(&dmx_data->msg_queue_lock);
-		wake_up(&dmx_data->msg_wait);
 	}
 }
 
@@ -821,11 +821,32 @@
 		return 0;
 }
 
+static int mpq_int_set_out_buffer_req(struct video_client_ctx *client_ctx,
+					struct video_buffer_req *vdec_buf_req)
+{
+	struct vcd_buffer_requirement buffer_req;
+	u32 vcd_status = VCD_ERR_FAIL;
+
+	buffer_req.actual_count = vdec_buf_req->num_output_buffers;
+	buffer_req.align = vdec_buf_req->output_buf_prop.alignment;
+	buffer_req.max_count = vdec_buf_req->num_output_buffers;
+	buffer_req.min_count = vdec_buf_req->num_output_buffers;
+	buffer_req.sz = vdec_buf_req->output_buf_prop.buf_size;
+
+	vcd_status = vcd_set_buffer_requirements(client_ctx->vcd_handle,
+			VCD_BUFFER_OUTPUT, &buffer_req);
+	if (vcd_status)
+		return -EFAULT;
+	else
+		return 0;
+}
+
 static int mpq_int_set_full_hd_frame_resolution(
 				struct video_client_ctx *client_ctx)
 {
 	struct vdec_picsize pic_res;
 	int rc;
+	struct video_buffer_req vdec_buf_req;
 
 	pic_res.frame_height = 1080;
 	pic_res.frame_width  = 1920;
@@ -843,6 +864,15 @@
 		DBG("Failed in mpq_int_vid_dec_set_cont_on_reconfig : %d\n",\
 			rc);
 
+	rc = mpq_int_vid_dec_get_buffer_req(client_ctx, &vdec_buf_req);
+	if (rc)
+		DBG("Failed in mpq_int_vid_dec_get_buffer_req : %d\n", rc);
+
+	vdec_buf_req.num_output_buffers = 15;
+	rc = mpq_int_set_out_buffer_req(client_ctx, &vdec_buf_req);
+	if (rc)
+		DBG("Failed in mpq_int_set_out_buffer_req (15) : %d\n", rc);
+
 	return rc;
 
 }
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index d596782..ac143b1 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -3479,12 +3479,20 @@
 				struct v4l2_buffer *buffer)
 {
 	struct iris_device  *radio = video_get_drvdata(video_devdata(file));
-	enum iris_buf_t buf_type = buffer->index;
-	struct kfifo *data_fifo;
-	unsigned char *buf = (unsigned char *)buffer->m.userptr;
-	unsigned int len = buffer->length;
-	if (!access_ok(VERIFY_WRITE, buf, len))
-		return -EFAULT;
+	enum iris_buf_t buf_type = -1;
+	unsigned char buf_fifo[STD_BUF_SIZE] = {0};
+	struct kfifo *data_fifo = NULL;
+	unsigned char *buf = NULL;
+	unsigned int len = 0, retval = -1;
+
+	if ((radio == NULL) || (buffer == NULL)) {
+		FMDERR("radio/buffer is NULL\n");
+		return -ENXIO;
+	}
+	buf_type = buffer->index;
+	buf = (unsigned char *)buffer->m.userptr;
+	len = buffer->length;
+
 	if ((buf_type < IRIS_BUF_MAX) && (buf_type >= 0)) {
 		data_fifo = &radio->data_buf[buf_type];
 		if (buf_type == IRIS_BUF_EVENTS)
@@ -3495,10 +3503,20 @@
 		FMDERR("invalid buffer type\n");
 		return -EINVAL;
 	}
-	buffer->bytesused = kfifo_out_locked(data_fifo, buf, len,
-					&radio->buf_lock[buf_type]);
+	if (len <= STD_BUF_SIZE) {
+		buffer->bytesused = kfifo_out_locked(data_fifo, &buf_fifo[0],
+					len, &radio->buf_lock[buf_type]);
+	} else {
+		FMDERR("kfifo_out_locked can not use len more than 128\n");
+		return -EINVAL;
+	}
+	retval = copy_to_user(buf, &buf_fifo[0], buffer->bytesused);
+	if (retval > 0) {
+		FMDERR("Failed to copy %d bytes of data\n", retval);
+		return -EAGAIN;
+	}
 
-	return 0;
+	return retval;
 }
 
 static int iris_vidioc_g_fmt_type_private(struct file *file, void *priv,
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index c5abd76..e9b4e2b 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -254,6 +254,15 @@
         ---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/video/msm/Makefile
index 740e424..5921632 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -20,7 +20,7 @@
   obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
 endif
 obj-$(CONFIG_MSM_CAMERA) += vfe/
-obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/ mercury/
+obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/ mercury/ jpeg_10/
 obj-$(CONFIG_MSM_CAMERA_FLASH) += flash.o
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   obj-$(CONFIG_ARCH_MSM8X60) += msm_vpe.o
diff --git a/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h b/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h
index 68c78d5..2d489b9 100644
--- a/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h
+++ b/drivers/media/video/msm/cci/msm_cam_cci_hwreg.h
@@ -26,6 +26,7 @@
 #define CCI_I2C_M0_SDA_CTL_2_ADDR                                   0x0000010c
 #define CCI_I2C_M0_READ_DATA_ADDR                                   0x00000118
 #define CCI_I2C_M0_MISC_CTL_ADDR                                    0x00000110
+#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
diff --git a/drivers/media/video/msm/cci/msm_cci.c b/drivers/media/video/msm/cci/msm_cci.c
index 77bd91e..09dfd7c 100644
--- a/drivers/media/video/msm/cci/msm_cci.c
+++ b/drivers/media/video/msm/cci/msm_cci.c
@@ -221,7 +221,7 @@
 {
 	uint32_t rc = 0;
 	uint32_t val = 0;
-	int32_t read_bytes = 0;
+	int32_t read_words = 0, exp_words = 0;
 	int32_t index = 0, first_byte = 0;
 	uint32_t i = 0;
 	enum cci_i2c_master_t master;
@@ -291,7 +291,15 @@
 	wait_for_completion_interruptible_timeout(&cci_dev->
 		cci_master_info[master].reset_complete, CCI_TIMEOUT);
 
-	read_bytes = (read_cfg->num_byte / 4) + 1;
+	read_words = msm_camera_io_r(cci_dev->base +
+		CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
+	exp_words = ((read_cfg->num_byte / 4) + 1);
+	if (read_words != exp_words) {
+		pr_err("%s:%d read_words = %d, exp words = %d\n", __func__,
+			__LINE__, read_words, exp_words);
+		memset(read_cfg->data, 0, read_cfg->num_byte);
+		goto ERROR;
+	}
 	index = 0;
 	CDBG("%s index %d num_type %d\n", __func__, index,
 		read_cfg->num_byte);
@@ -313,7 +321,7 @@
 				index++;
 			}
 		}
-	} while (--read_bytes > 0);
+	} while (--read_words > 0);
 ERROR:
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 	return rc;
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
index b66bee0..4682f8f 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
@@ -46,7 +46,7 @@
 #define CSID_RST_DONE_IRQ_BITSHIFT                  11
 #define CSID_RST_STB_ALL                            0x7FFF
 #define CSID_DL_INPUT_SEL_SHIFT                     0x2
-#define CSID_PHY_SEL_SHIFT                          0x17
+#define CSID_PHY_SEL_SHIFT                          17
 #define CSID_VERSION                                0x02000011
 
 #endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
index ca21238..11a04d5 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
@@ -46,7 +46,7 @@
 #define CSID_RST_DONE_IRQ_BITSHIFT                  11
 #define CSID_RST_STB_ALL                            0x7FFF
 #define CSID_DL_INPUT_SEL_SHIFT                     0x4
-#define CSID_PHY_SEL_SHIFT                          0x17
+#define CSID_PHY_SEL_SHIFT                          17
 #define CSID_VERSION                                0x30000000
 
 #endif
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index e5258f1..535ea0a 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -61,6 +61,7 @@
 			((csid_lut_params->vc_cfg[i].cid % 4) * 8));
 		msm_camera_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
 			(csid_lut_params->vc_cfg[i].cid >> 2) * 4);
+
 		val = (csid_lut_params->vc_cfg[i].decode_format << 4) | 0x3;
 		msm_camera_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
 			(csid_lut_params->vc_cfg[i].cid * 4));
@@ -95,10 +96,11 @@
 		return -EINVAL;
 	}
 
-	CDBG("%s csid_params, lane_cnt = %d, lane_assign = %x\n",
+	CDBG("%s csid_params, lane_cnt = %d, lane_assign = %x, phy sel = %d\n",
 		__func__,
 		csid_params->lane_cnt,
-		csid_params->lane_assign);
+		csid_params->lane_assign,
+		csid_params->phy_sel);
 	val = csid_params->lane_cnt - 1;
 	val |= csid_params->lane_assign << CSID_DL_INPUT_SEL_SHIFT;
 	if (csid_dev->hw_version < 0x30000000) {
@@ -169,13 +171,47 @@
 	{"csi_pclk", -1},
 };
 
-static struct msm_cam_clk_info csid_8974_clk_info[] = {
-	{"csi_ahb_clk", -1},
-	{"csi_src_clk", 200000000},
-	{"csi_clk", -1},
-	{"csi_phy_clk", -1},
-	{"csi_pix_clk", -1},
-	{"csi_rdi_clk", -1},
+static struct msm_cam_clk_info csid0_8974_clk_info[] = {
+	{"csi0_ahb_clk", -1},
+	{"csi0_src_clk", 200000000},
+	{"csi0_clk", -1},
+	{"csi0_phy_clk", -1},
+	{"csi0_pix_clk", -1},
+	{"csi0_rdi_clk", -1},
+};
+
+static struct msm_cam_clk_info csid1_8974_clk_info[] = {
+	{"csi1_ahb_clk", -1},
+	{"csi1_src_clk", 200000000},
+	{"csi1_clk", -1},
+	{"csi1_phy_clk", -1},
+	{"csi1_pix_clk", -1},
+	{"csi1_rdi_clk", -1},
+};
+
+static struct msm_cam_clk_info csid2_8974_clk_info[] = {
+	{"csi2_ahb_clk", -1},
+	{"csi2_src_clk", 200000000},
+	{"csi2_clk", -1},
+	{"csi2_phy_clk", -1},
+	{"csi2_pix_clk", -1},
+	{"csi2_rdi_clk", -1},
+};
+
+static struct msm_cam_clk_info csid3_8974_clk_info[] = {
+	{"csi3_ahb_clk", -1},
+	{"csi3_src_clk", 200000000},
+	{"csi3_clk", -1},
+	{"csi3_phy_clk", -1},
+	{"csi3_pix_clk", -1},
+	{"csi3_rdi_clk", -1},
+};
+
+static struct msm_cam_clk_setting csid_8974_clk_info[] = {
+	{&csid0_8974_clk_info[0], ARRAY_SIZE(csid0_8974_clk_info)},
+	{&csid1_8974_clk_info[0], ARRAY_SIZE(csid1_8974_clk_info)},
+	{&csid2_8974_clk_info[0], ARRAY_SIZE(csid2_8974_clk_info)},
+	{&csid3_8974_clk_info[0], ARRAY_SIZE(csid3_8974_clk_info)},
 };
 
 static struct camera_vreg_t csid_8960_vreg_info[] = {
@@ -189,6 +225,7 @@
 static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
 {
 	int rc = 0;
+	uint8_t core_id = 0;
 
 	if (!csid_version) {
 		pr_err("%s:%d csid_version NULL\n", __func__, __LINE__);
@@ -232,7 +269,7 @@
 			csid_8960_clk_info, csid_dev->csid_clk,
 			ARRAY_SIZE(csid_8960_clk_info), 1);
 		if (rc < 0) {
-			pr_err("%s: regulator enable failed\n", __func__);
+			pr_err("%s: clock enable failed\n", __func__);
 			goto clk_enable_failed;
 		}
 	} else if (CSID_VERSION == CSID_VERSION_V3) {
@@ -253,11 +290,23 @@
 		}
 
 		rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
-			csid_8974_clk_info, csid_dev->csid_clk,
-			ARRAY_SIZE(csid_8974_clk_info), 1);
+			csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
+			csid_8974_clk_info[0].num_clk_info, 1);
 		if (rc < 0) {
-			pr_err("%s: regulator enable failed\n", __func__);
-			goto clk_enable_failed;
+			pr_err("%s: clock enable failed\n", __func__);
+			goto csid0_clk_enable_failed;
+		}
+		core_id = csid_dev->pdev->id;
+		if (core_id) {
+			rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+				csid_8974_clk_info[core_id].clk_info,
+				csid_dev->csid_clk,
+				csid_8974_clk_info[core_id].num_clk_info, 1);
+			if (rc < 0) {
+				pr_err("%s: clock enable failed\n",
+					__func__);
+				goto clk_enable_failed;
+			}
 		}
 	}
 
@@ -274,6 +323,12 @@
 	return rc;
 
 clk_enable_failed:
+	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);
+	}
+csid0_clk_enable_failed:
 	if (CSID_VERSION <= CSID_VERSION_V2) {
 		msm_camera_enable_vreg(&csid_dev->pdev->dev,
 			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
@@ -302,6 +357,7 @@
 static int msm_csid_release(struct csid_device *csid_dev)
 {
 	uint32_t irq;
+	uint8_t core_id = 0;
 
 	if (csid_dev->csid_state != CSID_POWER_UP) {
 		pr_err("%s: csid invalid state %d\n", __func__,
@@ -327,8 +383,16 @@
 			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) {
-		msm_cam_clk_enable(&csid_dev->pdev->dev, csid_8974_clk_info,
-			csid_dev->csid_clk, ARRAY_SIZE(csid_8974_clk_info), 0);
+		core_id = csid_dev->pdev->id;
+		if (core_id)
+			msm_cam_clk_enable(&csid_dev->pdev->dev,
+				csid_8974_clk_info[core_id].clk_info,
+				csid_dev->csid_clk,
+				csid_8974_clk_info[core_id].num_clk_info, 0);
+
+		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);
 
 		msm_camera_enable_vreg(&csid_dev->pdev->dev,
 			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/video/msm/csi/msm_csid.h
index 1d4de01..46e8117 100644
--- a/drivers/media/video/msm/csi/msm_csid.h
+++ b/drivers/media/video/msm/csi/msm_csid.h
@@ -36,7 +36,8 @@
 	uint32_t hw_version;
 	enum msm_csid_state_t csid_state;
 
-	struct clk *csid_clk[5];
+	struct clk *csid0_clk[6];
+	struct clk *csid_clk[6];
 };
 
 #define VIDIOC_MSM_CSID_CFG \
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index bbaa0da..62858a8 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -29,7 +29,6 @@
 
 static atomic_t ispif_irq_cnt;
 static spinlock_t ispif_tasklet_lock;
-static spinlock_t ispif_sof_lock;
 static struct list_head ispif_tasklet_q;
 
 static int msm_ispif_intf_reset(struct ispif_device *ispif,
@@ -264,8 +263,8 @@
 	for (i = 0; i < params_len; i++) {
 		intftype = ispif_params[i].intftype;
 		vfe_intf = ispif_params[i].vfe_intf;
-		CDBG("%s intftype %x, vfe_intf %d\n", __func__, intftype,
-			vfe_intf);
+		CDBG("%s intftype %x, vfe_intf %d, csid %d\n", __func__,
+			intftype, vfe_intf, ispif_params[i].csid);
 		if ((intftype >= INTF_MAX) ||
 			(ispif->csid_version <= CSID_VERSION_V2 &&
 			vfe_intf > VFE0) ||
@@ -343,10 +342,9 @@
 static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint16_t intfmask,
 	uint8_t intf_cmd_mask, uint8_t vfe_intf)
 {
-	uint8_t vc = 0;
+	uint8_t vc = 0, val = 0;
 	uint16_t mask = intfmask, intfnum = 0;
 	uint32_t cid_mask = 0;
-	uint32_t global_intf_cmd_mask = 0xFFFFFFFF;
 	uint32_t global_intf_cmd_mask1 = 0xFFFFFFFF;
 	while (mask != 0) {
 		if (!(intfmask & (0x1 << intfnum))) {
@@ -360,12 +358,15 @@
 
 		while (cid_mask != 0) {
 			if ((cid_mask & 0xf) != 0x0) {
-				if (intfnum != RDI2)
-					global_intf_cmd_mask &=
-						~((0x3 & ~intf_cmd_mask)
-						<< ((vc * 2) +
+				if (intfnum != RDI2) {
+					val = (intf_cmd_mask>>(vc*2)) & 0x3;
+					ispif->global_intf_cmd_mask |=
+						(0x3 << ((vc * 2) +
 						(intfnum * 8)));
-				else
+					ispif->global_intf_cmd_mask &=
+						~((0x3 & ~val) << ((vc * 2) +
+						(intfnum * 8)));
+				} else
 					global_intf_cmd_mask1 &=
 						~((0x3 & ~intf_cmd_mask)
 						<< ((vc * 2) + 8));
@@ -376,7 +377,7 @@
 		mask >>= 1;
 		intfnum++;
 	}
-	msm_camera_io_w(global_intf_cmd_mask,
+	msm_camera_io_w(ispif->global_intf_cmd_mask,
 		ispif->base + ISPIF_INTF_CMD_ADDR + (0x200 * vfe_intf));
 	if (global_intf_cmd_mask1 != 0xFFFFFFFF)
 		msm_camera_io_w(global_intf_cmd_mask1,
@@ -388,11 +389,20 @@
 	uint16_t intfmask, uint8_t vfe_intf)
 {
 	int rc = 0;
-	uint8_t intf_cmd_mask = 0x02;
+	uint8_t intf_cmd_mask = 0xAA;
+	uint16_t intfnum = 0, mask = intfmask;
 	mutex_lock(&ispif->mutex);
 	CDBG("%s intfmask %x intf_cmd_mask %x\n", __func__, intfmask,
 		intf_cmd_mask);
 	msm_ispif_intf_cmd(ispif, intfmask, intf_cmd_mask, vfe_intf);
+	while (mask != 0) {
+		if (intfmask & (0x1 << intfnum))
+			ispif->global_intf_cmd_mask |= (0xFF << (intfnum * 8));
+		mask >>= 1;
+		intfnum++;
+		if (intfnum == RDI2)
+			break;
+	}
 	mutex_unlock(&ispif->mutex);
 	return rc;
 }
@@ -400,11 +410,11 @@
 static int msm_ispif_start_intf_transfer(struct ispif_device *ispif,
 	uint16_t intfmask, uint8_t vfe_intf)
 {
-	uint8_t intf_cmd_mask = 0x01;
+	uint8_t intf_cmd_mask = 0x55;
 	int rc = 0;
 	mutex_lock(&ispif->mutex);
 	rc = msm_ispif_intf_reset(ispif, intfmask, vfe_intf);
-	CDBG("%s intfmask %x intf_cmd_mask %x\n", __func__, intfmask,
+	CDBG("%s intfmask start after%x intf_cmd_mask %x\n", __func__, intfmask,
 		intf_cmd_mask);
 	msm_ispif_intf_cmd(ispif, intfmask, intf_cmd_mask, vfe_intf);
 	mutex_unlock(&ispif->mutex);
@@ -472,6 +482,9 @@
 			default:
 				break;
 			}
+			if (intfnum != RDI2)
+				ispif->global_intf_cmd_mask |= (0xFF <<
+					(intfnum * 8));
 		}
 		mask >>= 1;
 		intfnum++;
@@ -547,26 +560,6 @@
 		spin_unlock_irqrestore(&ispif_tasklet_lock,
 			flags);
 
-		spin_lock_irqsave(&ispif_sof_lock, flags);
-		if (qcmd->ispifInterruptStatus0 &
-			ISPIF_IRQ_STATUS_RDI0_SOF_MASK) {
-			CDBG("%s: ispif RDI0 irq status", __func__);
-			ispif->rdi0_sof_count++;
-			send_rdi_sof(ispif, RDI_0, ispif->rdi0_sof_count);
-		}
-		if (qcmd->ispifInterruptStatus1 &
-			ISPIF_IRQ_STATUS_RDI1_SOF_MASK) {
-			CDBG("%s: ispif RDI1 irq status", __func__);
-			ispif->rdi1_sof_count++;
-			send_rdi_sof(ispif, RDI_1, ispif->rdi1_sof_count);
-		}
-		if (qcmd->ispifInterruptStatus2 &
-			ISPIF_IRQ_STATUS_RDI2_SOF_MASK) {
-			CDBG("%s: ispif RDI2 irq status", __func__);
-			ispif->rdi2_sof_count++;
-			send_rdi_sof(ispif, RDI_2, ispif->rdi2_sof_count);
-		}
-		spin_unlock_irqrestore(&ispif_sof_lock, flags);
 		kfree(qcmd);
 	}
 }
@@ -586,6 +579,7 @@
 	qcmd->ispifInterruptStatus0 = out->ispifIrqStatus0;
 	qcmd->ispifInterruptStatus1 = out->ispifIrqStatus1;
 	qcmd->ispifInterruptStatus2 = out->ispifIrqStatus2;
+
 	if (qcmd->ispifInterruptStatus0 &
 			ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
 			CDBG("%s: ispif PIX irq status", __func__);
@@ -595,6 +589,25 @@
 				(void *)&ispif->pix_sof_count);
 	}
 
+	if (qcmd->ispifInterruptStatus0 &
+			ISPIF_IRQ_STATUS_RDI0_SOF_MASK) {
+			CDBG("%s: ispif RDI0 irq status", __func__);
+			ispif->rdi0_sof_count++;
+			send_rdi_sof(ispif, RDI_0, ispif->rdi0_sof_count);
+	}
+	if (qcmd->ispifInterruptStatus1 &
+		ISPIF_IRQ_STATUS_RDI1_SOF_MASK) {
+		CDBG("%s: ispif RDI1 irq status", __func__);
+		ispif->rdi1_sof_count++;
+		send_rdi_sof(ispif, RDI_1, ispif->rdi1_sof_count);
+	}
+	if (qcmd->ispifInterruptStatus2 &
+		ISPIF_IRQ_STATUS_RDI2_SOF_MASK) {
+		CDBG("%s: ispif RDI2 irq status", __func__);
+		ispif->rdi2_sof_count++;
+		send_rdi_sof(ispif, RDI_2, ispif->rdi2_sof_count);
+	}
+
 	spin_lock_irqsave(&ispif_tasklet_lock, flags);
 	list_add_tail(&qcmd->list, &ispif_tasklet_q);
 
@@ -693,6 +706,7 @@
 	INIT_LIST_HEAD(&ispif_tasklet_q);
 	rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
 		IRQF_TRIGGER_RISING, "ispif", ispif);
+	ispif->global_intf_cmd_mask = 0xFFFFFFFF;
 	init_completion(&ispif->reset_complete);
 
 	tasklet_init(&ispif->ispif_tasklet,
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
index ea69959..d4ca864 100644
--- a/drivers/media/video/msm/csi/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -44,6 +44,7 @@
 	uint32_t rdi0_sof_count;
 	uint32_t rdi1_sof_count;
 	uint32_t rdi2_sof_count;
+	uint32_t global_intf_cmd_mask;
 	struct tasklet_struct ispif_tasklet;
 	enum msm_ispif_state_t ispif_state;
 };
diff --git a/drivers/media/video/msm/gemini/msm_gemini_hw.h b/drivers/media/video/msm/gemini/msm_gemini_hw.h
index 233f082..248ba06 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_hw.h
+++ b/drivers/media/video/msm/gemini/msm_gemini_hw.h
@@ -15,7 +15,7 @@
 
 #include <media/msm_gemini.h>
 #include "msm_gemini_hw_reg.h"
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/iommu_domains.h>
 
 struct msm_gemini_hw_buf {
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.h b/drivers/media/video/msm/gemini/msm_gemini_platform.h
index eb6b9f0..d7f81aa 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_platform.h
+++ b/drivers/media/video/msm/gemini/msm_gemini_platform.h
@@ -15,7 +15,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/iommu.h>
 void msm_gemini_platform_p2v(struct file  *file,
 				struct ion_handle **ionhandle);
diff --git a/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
index 9549dcc..d508c1d 100644
--- a/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
+++ b/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
@@ -139,11 +139,11 @@
 	switch (perf_setting) {
 	case S_INIT:
 		add_axi_qos();
-		break;
-	case S_PREVIEW:
 		update_axi_qos(MSM_AXI_QOS_PREVIEW);
 		axi_allocate(AXI_FLOW_VIEWFINDER_HI);
 		break;
+	case S_PREVIEW:
+		break;
 	case S_VIDEO:
 		update_axi_qos(MSM_AXI_QOS_RECORDING);
 		break;
diff --git a/drivers/media/video/msm/io/msm_io_8960.c b/drivers/media/video/msm/io/msm_io_8960.c
index 699425a..808cc32 100644
--- a/drivers/media/video/msm/io/msm_io_8960.c
+++ b/drivers/media/video/msm/io/msm_io_8960.c
@@ -95,6 +95,14 @@
 		} else
 			CDBG("%s: Bus Client NOT Registered!!!\n", __func__);
 		break;
+	case S_DUAL:
+		if (bus_perf_client) {
+			rc = msm_bus_scale_client_update_request(
+				bus_perf_client, 6);
+			CDBG("%s: S_DUAL rc = %d\n", __func__, rc);
+		} else
+			CDBG("%s: Bus Client NOT Registered!!!\n", __func__);
+		break;
 	case S_DEFAULT:
 		break;
 	default:
diff --git a/drivers/media/video/msm/jpeg_10/Makefile b/drivers/media/video/msm/jpeg_10/Makefile
new file mode 100644
index 0000000..d99d1a4
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/Makefile
@@ -0,0 +1,3 @@
+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/jpeg_10/msm_jpeg_common.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h
new file mode 100644
index 0000000..88ec1ad
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_common.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_JPEG_COMMON_H
+#define MSM_JPEG_COMMON_H
+
+#ifdef MSM_JPEG_DEBUG
+#define JPEG_DBG(fmt, args...) printk(fmt, ##args)
+#else
+#define JPEG_DBG(fmt, args...) do { } while (0)
+#endif
+
+#define JPEG_PR_ERR   pr_err
+
+enum JPEG_MODE {
+	JPEG_MODE_DISABLE,
+	JPEG_MODE_OFFLINE,
+	JPEG_MODE_REALTIME,
+	JPEG_MODE_REALTIME_ROTATION
+};
+
+enum JPEG_ROTATION {
+	JPEG_ROTATION_0,
+	JPEG_ROTATION_90,
+	JPEG_ROTATION_180,
+	JPEG_ROTATION_270
+};
+
+#endif /* MSM_JPEG_COMMON_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c
new file mode 100644
index 0000000..7905ff3
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.c
@@ -0,0 +1,223 @@
+/* Copyright (c) 2012,The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include "msm_jpeg_hw.h"
+#include "msm_jpeg_core.h"
+#include "msm_jpeg_platform.h"
+#include "msm_jpeg_common.h"
+
+static struct msm_jpeg_hw_pingpong fe_pingpong_buf;
+static struct msm_jpeg_hw_pingpong we_pingpong_buf;
+static int we_pingpong_index;
+static int reset_done_ack;
+static spinlock_t reset_lock;
+static wait_queue_head_t reset_wait;
+
+int msm_jpeg_core_reset(uint8_t op_mode, void *base, int size)
+{
+	unsigned long flags;
+	int rc = 0;
+	int tm = 500; /*500ms*/
+	memset(&fe_pingpong_buf, 0, sizeof(fe_pingpong_buf));
+	fe_pingpong_buf.is_fe = 1;
+	we_pingpong_index = 0;
+	memset(&we_pingpong_buf, 0, sizeof(we_pingpong_buf));
+	spin_lock_irqsave(&reset_lock, flags);
+	reset_done_ack = 0;
+	msm_jpeg_hw_reset(base, size);
+	spin_unlock_irqrestore(&reset_lock, flags);
+	rc = wait_event_interruptible_timeout(
+			reset_wait,
+			reset_done_ack,
+			msecs_to_jiffies(tm));
+
+	if (!reset_done_ack) {
+		JPEG_DBG("%s: reset ACK failed %d", __func__, rc);
+		return -EBUSY;
+	}
+
+	JPEG_DBG("%s: reset_done_ack rc %d", __func__, rc);
+	spin_lock_irqsave(&reset_lock, flags);
+	reset_done_ack = 0;
+	spin_unlock_irqrestore(&reset_lock, flags);
+
+	return 0;
+}
+
+void msm_jpeg_core_release(int release_buf, int domain_num)
+{
+	int i = 0;
+	for (i = 0; i < 2; i++) {
+		if (we_pingpong_buf.buf_status[i] && release_buf)
+			msm_jpeg_platform_p2v(we_pingpong_buf.buf[i].file,
+				&we_pingpong_buf.buf[i].handle, domain_num);
+		we_pingpong_buf.buf_status[i] = 0;
+	}
+}
+
+void msm_jpeg_core_init(void)
+{
+	init_waitqueue_head(&reset_wait);
+	spin_lock_init(&reset_lock);
+}
+
+int msm_jpeg_core_fe_start(void)
+{
+	msm_jpeg_hw_fe_start();
+	return 0;
+}
+
+/* fetch engine */
+int msm_jpeg_core_fe_buf_update(struct msm_jpeg_core_buf *buf)
+{
+	JPEG_DBG("%s:%d] 0x%08x %d 0x%08x %d\n", __func__, __LINE__,
+		(int) buf->y_buffer_addr, buf->y_len,
+		(int) buf->cbcr_buffer_addr, buf->cbcr_len);
+	return msm_jpeg_hw_pingpong_update(&fe_pingpong_buf, buf);
+}
+
+void *msm_jpeg_core_fe_pingpong_irq(int jpeg_irq_status, void *context)
+{
+	return msm_jpeg_hw_pingpong_irq(&fe_pingpong_buf);
+}
+
+/* write engine */
+int msm_jpeg_core_we_buf_update(struct msm_jpeg_core_buf *buf)
+{
+	JPEG_DBG("%s:%d] 0x%08x 0x%08x %d\n", __func__, __LINE__,
+		(int) buf->y_buffer_addr, (int) buf->cbcr_buffer_addr,
+		buf->y_len);
+	we_pingpong_buf.buf[0] = *buf;
+	we_pingpong_buf.buf_status[0] = 1;
+	msm_jpeg_hw_we_buffer_update(
+			&we_pingpong_buf.buf[0], 0);
+
+	return 0;
+}
+
+int msm_jpeg_core_we_buf_reset(struct msm_jpeg_hw_buf *buf)
+{
+	int i = 0;
+	for (i = 0; i < 2; i++) {
+		if (we_pingpong_buf.buf[i].y_buffer_addr
+					== buf->y_buffer_addr)
+			we_pingpong_buf.buf_status[i] = 0;
+	}
+	return 0;
+}
+
+void *msm_jpeg_core_we_pingpong_irq(int jpeg_irq_status, void *context)
+{
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+
+	return msm_jpeg_hw_pingpong_irq(&we_pingpong_buf);
+}
+
+void *msm_jpeg_core_framedone_irq(int jpeg_irq_status, void *context)
+{
+	struct msm_jpeg_hw_buf *buf_p;
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+
+	buf_p = msm_jpeg_hw_pingpong_active_buffer(&we_pingpong_buf);
+	if (buf_p) {
+		buf_p->framedone_len = msm_jpeg_hw_encode_output_size();
+		JPEG_DBG("%s:%d] framedone_len %d\n", __func__, __LINE__,
+			buf_p->framedone_len);
+	}
+
+	return buf_p;
+}
+
+void *msm_jpeg_core_reset_ack_irq(int jpeg_irq_status, void *context)
+{
+	/* @todo return the status back to msm_jpeg_core_reset */
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	return NULL;
+}
+
+void *msm_jpeg_core_err_irq(int jpeg_irq_status, void *context)
+{
+	JPEG_PR_ERR("%s:%d]\n", __func__, jpeg_irq_status);
+	return NULL;
+}
+
+static int (*msm_jpeg_irq_handler) (int, void *, void *);
+
+irqreturn_t msm_jpeg_core_irq(int irq_num, void *context)
+{
+	void *data = NULL;
+	unsigned long flags;
+	int jpeg_irq_status;
+
+	JPEG_DBG("%s:%d] irq_num = %d\n", __func__, __LINE__, irq_num);
+
+	jpeg_irq_status = msm_jpeg_hw_irq_get_status();
+
+	JPEG_DBG("%s:%d] jpeg_irq_status = %0x\n", __func__, __LINE__,
+		jpeg_irq_status);
+
+	/*For reset and framedone IRQs, clear all bits*/
+	if (jpeg_irq_status & 0x10000000) {
+		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
+			JPEG_IRQ_CLEAR_ALL);
+	} else if (jpeg_irq_status & 0x1) {
+		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
+			JPEG_IRQ_CLEAR_ALL);
+	} else {
+		msm_jpeg_hw_irq_clear(JPEG_IRQ_CLEAR_BMSK,
+			jpeg_irq_status);
+	}
+
+	if (msm_jpeg_hw_irq_is_frame_done(jpeg_irq_status)) {
+		data = msm_jpeg_core_framedone_irq(jpeg_irq_status,
+			context);
+		if (msm_jpeg_irq_handler)
+			msm_jpeg_irq_handler(
+				MSM_JPEG_HW_MASK_COMP_FRAMEDONE,
+				context, data);
+	}
+	if (msm_jpeg_hw_irq_is_reset_ack(jpeg_irq_status)) {
+		data = msm_jpeg_core_reset_ack_irq(jpeg_irq_status,
+			context);
+		spin_lock_irqsave(&reset_lock, flags);
+		reset_done_ack = 1;
+		spin_unlock_irqrestore(&reset_lock, flags);
+		wake_up(&reset_wait);
+		if (msm_jpeg_irq_handler)
+			msm_jpeg_irq_handler(
+				MSM_JPEG_HW_MASK_COMP_RESET_ACK,
+				context, data);
+	}
+
+	/* Unexpected/unintended HW interrupt */
+	if (msm_jpeg_hw_irq_is_err(jpeg_irq_status)) {
+		data = msm_jpeg_core_err_irq(jpeg_irq_status, context);
+		if (msm_jpeg_irq_handler)
+			msm_jpeg_irq_handler(MSM_JPEG_HW_MASK_COMP_ERR,
+				context, data);
+	}
+
+	return IRQ_HANDLED;
+}
+
+void msm_jpeg_core_irq_install(int (*irq_handler) (int, void *, void *))
+{
+	msm_jpeg_irq_handler = irq_handler;
+}
+
+void msm_jpeg_core_irq_remove(void)
+{
+	msm_jpeg_irq_handler = NULL;
+}
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h
new file mode 100644
index 0000000..b5c725c
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_core.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_JPEG_CORE_H
+#define MSM_JPEG_CORE_H
+
+#include <linux/interrupt.h>
+#include "msm_jpeg_hw.h"
+
+#define msm_jpeg_core_buf msm_jpeg_hw_buf
+
+irqreturn_t msm_jpeg_core_irq(int irq_num, void *context);
+
+void msm_jpeg_core_irq_install(int (*irq_handler) (int, void *, void *));
+void msm_jpeg_core_irq_remove(void);
+
+int msm_jpeg_core_fe_buf_update(struct msm_jpeg_core_buf *buf);
+int msm_jpeg_core_we_buf_update(struct msm_jpeg_core_buf *buf);
+int msm_jpeg_core_we_buf_reset(struct msm_jpeg_hw_buf *buf);
+
+int msm_jpeg_core_reset(uint8_t op_mode, void *base, int size);
+int msm_jpeg_core_fe_start(void);
+
+void msm_jpeg_core_release(int, int);
+void msm_jpeg_core_init(void);
+#endif /* MSM_JPEG_CORE_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
new file mode 100644
index 0000000..45a9a38
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_dev.c
@@ -0,0 +1,299 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <mach/board.h>
+#include <linux/of.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <media/msm_jpeg.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "msm.h"
+#include "msm_jpeg_sync.h"
+#include "msm_jpeg_common.h"
+
+#define MSM_JPEG_NAME "jpeg"
+#define MSM_JPEGE1_NAME "jpege1"
+#define MSM_JPEGD_NAME "jpegd"
+
+
+static int msm_jpeg_open(struct inode *inode, struct file *filp)
+{
+	int rc = 0;
+
+	struct msm_jpeg_device *pgmn_dev = container_of(inode->i_cdev,
+		struct msm_jpeg_device, cdev);
+	filp->private_data = pgmn_dev;
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+
+	rc = __msm_jpeg_open(pgmn_dev);
+
+	JPEG_DBG(KERN_INFO "%s:%d] %s open_count = %d\n", __func__, __LINE__,
+		filp->f_path.dentry->d_name.name, pgmn_dev->open_count);
+
+	return rc;
+}
+
+static int msm_jpeg_release(struct inode *inode, struct file *filp)
+{
+	int rc;
+
+	struct msm_jpeg_device *pgmn_dev = filp->private_data;
+
+	JPEG_DBG(KERN_INFO "%s:%d]\n", __func__, __LINE__);
+
+	rc = __msm_jpeg_release(pgmn_dev);
+
+	JPEG_DBG(KERN_INFO "%s:%d] %s open_count = %d\n", __func__, __LINE__,
+		filp->f_path.dentry->d_name.name, pgmn_dev->open_count);
+	return rc;
+}
+
+static long msm_jpeg_ioctl(struct file *filp, unsigned int cmd,
+	unsigned long arg)
+{
+	int rc;
+	struct msm_jpeg_device *pgmn_dev = filp->private_data;
+
+	JPEG_DBG("%s:%d] cmd=%d pgmn_dev=0x%x arg=0x%x\n", __func__,
+		__LINE__, _IOC_NR(cmd), (uint32_t)pgmn_dev, (uint32_t)arg);
+
+	rc = __msm_jpeg_ioctl(pgmn_dev, cmd, arg);
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	return rc;
+}
+
+static const struct file_operations msm_jpeg_fops = {
+	.owner		= THIS_MODULE,
+	.open		 = msm_jpeg_open,
+	.release	= msm_jpeg_release,
+	.unlocked_ioctl = msm_jpeg_ioctl,
+};
+
+
+int msm_jpeg_subdev_init(struct v4l2_subdev *jpeg_sd)
+{
+	int rc;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *)jpeg_sd->host_priv;
+
+	JPEG_DBG("%s:%d: jpeg_sd=0x%x pgmn_dev=0x%x\n",
+		__func__, __LINE__, (uint32_t)jpeg_sd, (uint32_t)pgmn_dev);
+	rc = __msm_jpeg_open(pgmn_dev);
+	JPEG_DBG("%s:%d: rc=%d\n",
+		__func__, __LINE__, rc);
+	return rc;
+}
+
+static long msm_jpeg_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	long rc;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *)sd->host_priv;
+
+	JPEG_DBG("%s: cmd=%d\n", __func__, cmd);
+
+	JPEG_DBG("%s: pgmn_dev 0x%x", __func__, (uint32_t)pgmn_dev);
+
+	JPEG_DBG("%s: Calling __msm_jpeg_ioctl\n", __func__);
+
+	rc = __msm_jpeg_ioctl(pgmn_dev, cmd, (unsigned long)arg);
+	pr_debug("%s: X\n", __func__);
+	return rc;
+}
+
+void msm_jpeg_subdev_release(struct v4l2_subdev *jpeg_sd)
+{
+	int rc;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *)jpeg_sd->host_priv;
+	JPEG_DBG("%s:pgmn_dev=0x%x", __func__, (uint32_t)pgmn_dev);
+	rc = __msm_jpeg_release(pgmn_dev);
+	JPEG_DBG("%s:rc=%d", __func__, rc);
+}
+
+static const struct v4l2_subdev_core_ops msm_jpeg_subdev_core_ops = {
+	.ioctl = msm_jpeg_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_jpeg_subdev_ops = {
+	.core = &msm_jpeg_subdev_core_ops,
+};
+
+static int msm_jpeg_init_dev(struct platform_device *pdev)
+{
+	int rc = -1;
+	struct device *dev;
+	struct msm_jpeg_device *msm_jpeg_device_p;
+	char devname[10];
+
+	msm_jpeg_device_p = kzalloc(sizeof(struct msm_jpeg_device), GFP_ATOMIC);
+	if (!msm_jpeg_device_p) {
+		JPEG_PR_ERR("%s: no mem\n", __func__);
+		return -EFAULT;
+	}
+
+	msm_jpeg_device_p->pdev = pdev;
+
+	if (pdev->dev.of_node)
+		of_property_read_u32((&pdev->dev)->of_node, "cell-index",
+								&pdev->id);
+
+	snprintf(devname, sizeof(devname), "%s%d", MSM_JPEG_NAME, pdev->id);
+
+	rc = __msm_jpeg_init(msm_jpeg_device_p);
+	if (rc < -1) {
+		JPEG_PR_ERR("%s: initialization failed\n", __func__);
+		goto fail;
+	}
+
+	v4l2_subdev_init(&msm_jpeg_device_p->subdev, &msm_jpeg_subdev_ops);
+	v4l2_set_subdev_hostdata(&msm_jpeg_device_p->subdev, msm_jpeg_device_p);
+	JPEG_DBG("%s: msm_jpeg_device_p 0x%x", __func__,
+			(uint32_t)msm_jpeg_device_p);
+
+	rc = alloc_chrdev_region(&msm_jpeg_device_p->msm_jpeg_devno, 0, 1,
+				devname);
+	if (rc < 0) {
+		JPEG_PR_ERR("%s: failed to allocate chrdev\n", __func__);
+		goto fail_1;
+	}
+
+	if (!msm_jpeg_device_p->msm_jpeg_class) {
+		msm_jpeg_device_p->msm_jpeg_class =
+				class_create(THIS_MODULE, devname);
+		if (IS_ERR(msm_jpeg_device_p->msm_jpeg_class)) {
+			rc = PTR_ERR(msm_jpeg_device_p->msm_jpeg_class);
+			JPEG_PR_ERR("%s: create device class failed\n",
+				__func__);
+			goto fail_2;
+		}
+	}
+
+	dev = device_create(msm_jpeg_device_p->msm_jpeg_class, NULL,
+		MKDEV(MAJOR(msm_jpeg_device_p->msm_jpeg_devno),
+		MINOR(msm_jpeg_device_p->msm_jpeg_devno)), NULL,
+		"%s%d", MSM_JPEG_NAME, pdev->id);
+	if (IS_ERR(dev)) {
+		JPEG_PR_ERR("%s: error creating device\n", __func__);
+		rc = -ENODEV;
+		goto fail_3;
+	}
+
+	cdev_init(&msm_jpeg_device_p->cdev, &msm_jpeg_fops);
+	msm_jpeg_device_p->cdev.owner = THIS_MODULE;
+	msm_jpeg_device_p->cdev.ops	 =
+		(const struct file_operations *) &msm_jpeg_fops;
+	rc = cdev_add(&msm_jpeg_device_p->cdev,
+			msm_jpeg_device_p->msm_jpeg_devno, 1);
+	if (rc < 0) {
+		JPEG_PR_ERR("%s: error adding cdev\n", __func__);
+		rc = -ENODEV;
+		goto fail_4;
+	}
+
+	platform_set_drvdata(pdev, &msm_jpeg_device_p);
+
+	JPEG_DBG("%s %s%d: success\n", __func__, MSM_JPEG_NAME, pdev->id);
+
+	return rc;
+
+fail_4:
+	device_destroy(msm_jpeg_device_p->msm_jpeg_class,
+			msm_jpeg_device_p->msm_jpeg_devno);
+
+fail_3:
+	class_destroy(msm_jpeg_device_p->msm_jpeg_class);
+
+fail_2:
+	unregister_chrdev_region(msm_jpeg_device_p->msm_jpeg_devno, 1);
+
+fail_1:
+	__msm_jpeg_exit(msm_jpeg_device_p);
+
+fail:
+	kfree(msm_jpeg_device_p);
+	return rc;
+
+}
+
+static void msm_jpeg_exit(struct msm_jpeg_device *msm_jpeg_device_p)
+{
+	cdev_del(&msm_jpeg_device_p->cdev);
+	device_destroy(msm_jpeg_device_p->msm_jpeg_class,
+			msm_jpeg_device_p->msm_jpeg_devno);
+	class_destroy(msm_jpeg_device_p->msm_jpeg_class);
+	unregister_chrdev_region(msm_jpeg_device_p->msm_jpeg_devno, 1);
+
+	__msm_jpeg_exit(msm_jpeg_device_p);
+}
+
+static int __msm_jpeg_probe(struct platform_device *pdev)
+{
+	return msm_jpeg_init_dev(pdev);
+}
+
+static int __msm_jpeg_remove(struct platform_device *pdev)
+{
+	struct msm_jpeg_device *msm_jpegd_device_p;
+
+	msm_jpegd_device_p = platform_get_drvdata(pdev);
+	if (msm_jpegd_device_p)
+		msm_jpeg_exit(msm_jpegd_device_p);
+
+	return 0;
+}
+
+static const struct of_device_id msm_jpeg_dt_match[] = {
+			{.compatible = "qcom,jpeg"},
+};
+
+MODULE_DEVICE_TABLE(of, msm_jpeg_dt_match);
+
+static struct platform_driver msm_jpeg_driver = {
+	.probe	= __msm_jpeg_probe,
+	.remove = __msm_jpeg_remove,
+	.driver = {
+		.name = MSM_JPEG_DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = msm_jpeg_dt_match,
+	},
+};
+
+static int __init msm_jpeg_driver_init(void)
+{
+	int rc;
+	rc = platform_driver_register(&msm_jpeg_driver);
+	return rc;
+}
+
+static void __exit msm_jpeg_driver_exit(void)
+{
+	platform_driver_unregister(&msm_jpeg_driver);
+}
+
+MODULE_DESCRIPTION("msm jpeg jpeg driver");
+
+module_init(msm_jpeg_driver_init);
+module_exit(msm_jpeg_driver_exit);
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c
new file mode 100644
index 0000000..0bfb6a8
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.c
@@ -0,0 +1,380 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "msm_jpeg_hw.h"
+#include "msm_jpeg_common.h"
+
+#include <linux/io.h>
+
+static void *jpeg_region_base;
+static uint32_t jpeg_region_size;
+
+int msm_jpeg_hw_pingpong_update(struct msm_jpeg_hw_pingpong *pingpong_hw,
+	struct msm_jpeg_hw_buf *buf)
+{
+	int buf_free_index = -1;
+
+	if (!pingpong_hw->buf_status[0]) {
+		buf_free_index = 0;
+	} else if (!pingpong_hw->buf_status[1]) {
+		buf_free_index = 1;
+	} else {
+		JPEG_PR_ERR("%s:%d: pingpong buffer busy\n",
+		__func__, __LINE__);
+		return -EBUSY;
+	}
+
+	pingpong_hw->buf[buf_free_index] = *buf;
+	pingpong_hw->buf_status[buf_free_index] = 1;
+
+	if (pingpong_hw->is_fe) {
+		/* it is fe */
+		msm_jpeg_hw_fe_buffer_update(
+			&pingpong_hw->buf[buf_free_index], buf_free_index);
+	} else {
+		/* it is we */
+		msm_jpeg_hw_we_buffer_update(
+			&pingpong_hw->buf[buf_free_index], buf_free_index);
+	}
+	return 0;
+}
+
+void *msm_jpeg_hw_pingpong_irq(struct msm_jpeg_hw_pingpong *pingpong_hw)
+{
+	struct msm_jpeg_hw_buf *buf_p = NULL;
+
+	if (pingpong_hw->buf_status[pingpong_hw->buf_active_index]) {
+		buf_p = &pingpong_hw->buf[pingpong_hw->buf_active_index];
+		pingpong_hw->buf_status[pingpong_hw->buf_active_index] = 0;
+	}
+
+	pingpong_hw->buf_active_index = !pingpong_hw->buf_active_index;
+
+	return (void *) buf_p;
+}
+
+void *msm_jpeg_hw_pingpong_active_buffer(
+	struct msm_jpeg_hw_pingpong *pingpong_hw)
+{
+	struct msm_jpeg_hw_buf *buf_p = NULL;
+
+	if (pingpong_hw->buf_status[pingpong_hw->buf_active_index])
+		buf_p = &pingpong_hw->buf[pingpong_hw->buf_active_index];
+
+	return (void *) buf_p;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_irq_get_status[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_READ, 1, JPEG_IRQ_STATUS_ADDR,
+		JPEG_IRQ_STATUS_BMSK, {0} },
+};
+
+int msm_jpeg_hw_irq_get_status(void)
+{
+	uint32_t n_irq_status = 0;
+	rmb();
+	n_irq_status = msm_jpeg_hw_read(&hw_cmd_irq_get_status[0]);
+	rmb();
+	return n_irq_status;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_encode_output_size[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_READ, 1,
+	JPEG_ENCODE_OUTPUT_SIZE_STATUS_ADDR,
+	JPEG_ENCODE_OUTPUT_SIZE_STATUS_BMSK, {0} } ,
+};
+
+long msm_jpeg_hw_encode_output_size(void)
+{
+	uint32_t encode_output_size = 0;
+
+	encode_output_size = msm_jpeg_hw_read(&hw_cmd_encode_output_size[0]);
+
+	return encode_output_size;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_irq_clear[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_CLEAR_ADDR,
+		JPEG_IRQ_CLEAR_BMSK, {JPEG_IRQ_CLEAR_ALL} },
+};
+
+void msm_jpeg_hw_irq_clear(uint32_t mask, uint32_t data)
+{
+	JPEG_DBG("%s:%d] mask %0x data %0x", __func__, __LINE__, mask, data);
+	hw_cmd_irq_clear[0].mask = mask;
+	hw_cmd_irq_clear[0].data = data;
+	msm_jpeg_hw_write(&hw_cmd_irq_clear[0]);
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_fe_ping_update[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
+		JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_ALLSOURCES_ENABLE} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_CMD_ADDR,
+		JPEG_CMD_BMSK, {JPEG_CMD_CLEAR_WRITE_PLN_QUEUES} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_RD_OFFSET_ADDR,
+		JPEG_PLN0_RD_OFFSET_BMSK, {0} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_RD_PNTR_ADDR,
+		JPEG_PLN0_RD_PNTR_BMSK, {0} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN1_RD_OFFSET_ADDR,
+		JPEG_PLN1_RD_OFFSET_BMSK, {0} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN1_RD_PNTR_ADDR,
+		JPEG_PLN1_RD_PNTR_BMSK, {0} },
+};
+
+void msm_jpeg_hw_fe_buffer_update(struct msm_jpeg_hw_buf *p_input,
+	uint8_t pingpong_index)
+{
+	struct msm_jpeg_hw_cmd *hw_cmd_p;
+
+	if (pingpong_index == 0) {
+		hw_cmd_p = &hw_cmd_fe_ping_update[0];
+		wmb();
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		hw_cmd_p->data = p_input->y_buffer_addr;
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+		hw_cmd_p->data = p_input->cbcr_buffer_addr;
+		msm_jpeg_hw_write(hw_cmd_p++);
+		wmb();
+
+	}
+	return;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_fe_start[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_CMD_ADDR,
+		JPEG_CMD_BMSK, {JPEG_OFFLINE_CMD_START} },
+};
+
+void msm_jpeg_hw_fe_start(void)
+{
+	msm_jpeg_hw_write(&hw_cmd_fe_start[0]);
+
+	return;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_we_ping_update[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_PLN0_WR_PNTR_ADDR,
+		JPEG_PLN0_WR_PNTR_BMSK, {0} },
+};
+
+void msm_jpeg_hw_we_buffer_update(struct msm_jpeg_hw_buf *p_input,
+	uint8_t pingpong_index)
+{
+	struct msm_jpeg_hw_cmd *hw_cmd_p;
+
+	if (pingpong_index == 0) {
+		hw_cmd_p = &hw_cmd_we_ping_update[0];
+		hw_cmd_p->data = p_input->y_buffer_addr;
+		JPEG_PR_ERR("%s Output buffer address is %x\n", __func__,
+						p_input->y_buffer_addr);
+		msm_jpeg_hw_write(hw_cmd_p++);
+
+	}
+	return;
+}
+
+struct msm_jpeg_hw_cmd hw_cmd_reset[] = {
+	/* type, repeat n times, offset, mask, data or pdata */
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
+		JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_DISABLE_ALL} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_CLEAR_ADDR,
+		JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_CLEAR_ALL} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_IRQ_MASK_ADDR,
+		JPEG_IRQ_MASK_BMSK, {JPEG_IRQ_ALLSOURCES_ENABLE} },
+	{MSM_JPEG_HW_CMD_TYPE_WRITE, 1, JPEG_RESET_CMD_ADDR,
+		JPEG_RESET_CMD_RMSK, {JPEG_RESET_DEFAULT} },
+};
+
+void msm_jpeg_hw_init(void *base, int size)
+{
+	jpeg_region_base = base;
+	jpeg_region_size = size;
+}
+
+void msm_jpeg_hw_reset(void *base, int size)
+{
+	struct msm_jpeg_hw_cmd *hw_cmd_p;
+
+	hw_cmd_p = &hw_cmd_reset[0];
+	wmb();
+	msm_jpeg_hw_write(hw_cmd_p++);
+	wmb();
+	msm_jpeg_hw_write(hw_cmd_p++);
+	wmb();
+	msm_jpeg_hw_write(hw_cmd_p++);
+	wmb();
+	msm_jpeg_hw_write(hw_cmd_p);
+	wmb();
+
+	return;
+}
+
+uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *hw_cmd_p)
+{
+	uint32_t *paddr;
+	uint32_t data;
+
+	paddr = jpeg_region_base + hw_cmd_p->offset;
+
+	data = readl_relaxed(paddr);
+	data &= hw_cmd_p->mask;
+
+	return data;
+}
+
+void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p)
+{
+	uint32_t *paddr;
+	uint32_t old_data, new_data;
+
+	paddr = jpeg_region_base + hw_cmd_p->offset;
+
+	if (hw_cmd_p->mask == 0xffffffff) {
+		old_data = 0;
+	} else {
+		old_data = readl_relaxed(paddr);
+		old_data &= ~hw_cmd_p->mask;
+	}
+
+	new_data = hw_cmd_p->data & hw_cmd_p->mask;
+	new_data |= old_data;
+	writel_relaxed(new_data, paddr);
+}
+
+int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us)
+{
+	int tm = hw_cmd_p->n;
+	uint32_t data;
+	uint32_t wait_data = hw_cmd_p->data & hw_cmd_p->mask;
+
+	data = msm_jpeg_hw_read(hw_cmd_p);
+	if (data != wait_data) {
+		while (tm) {
+			udelay(m_us);
+			data = msm_jpeg_hw_read(hw_cmd_p);
+			if (data == wait_data)
+				break;
+			tm--;
+		}
+	}
+	hw_cmd_p->data = data;
+	return tm;
+}
+
+void msm_jpeg_hw_delay(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us)
+{
+	int tm = hw_cmd_p->n;
+	while (tm) {
+		udelay(m_us);
+		tm--;
+	}
+}
+
+int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_cmds)
+{
+	int is_copy_to_user = -1;
+	uint32_t data;
+
+	while (m_cmds--) {
+		if (hw_cmd_p->offset > jpeg_region_size) {
+			JPEG_PR_ERR("%s:%d] %d exceed hw region %d\n", __func__,
+				__LINE__, hw_cmd_p->offset, jpeg_region_size);
+			return -EFAULT;
+		}
+
+		switch (hw_cmd_p->type) {
+		case MSM_JPEG_HW_CMD_TYPE_READ:
+			hw_cmd_p->data = msm_jpeg_hw_read(hw_cmd_p);
+			is_copy_to_user = 1;
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_WRITE:
+			msm_jpeg_hw_write(hw_cmd_p);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_WRITE_OR:
+			data = msm_jpeg_hw_read(hw_cmd_p);
+			hw_cmd_p->data = (hw_cmd_p->data & hw_cmd_p->mask) |
+				data;
+			msm_jpeg_hw_write(hw_cmd_p);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_UWAIT:
+			msm_jpeg_hw_wait(hw_cmd_p, 1);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_MWAIT:
+			msm_jpeg_hw_wait(hw_cmd_p, 1000);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_UDELAY:
+			msm_jpeg_hw_delay(hw_cmd_p, 1);
+			break;
+
+		case MSM_JPEG_HW_CMD_TYPE_MDELAY:
+			msm_jpeg_hw_delay(hw_cmd_p, 1000);
+			break;
+
+		default:
+			JPEG_PR_ERR("wrong hw command type\n");
+			break;
+		}
+
+		hw_cmd_p++;
+	}
+	return is_copy_to_user;
+}
+
+void msm_jpeg_io_dump(int size)
+{
+	char line_str[128], *p_str;
+	void __iomem *addr = jpeg_region_base;
+	int i;
+	u32 *p = (u32 *) addr;
+	u32 data;
+	JPEG_PR_ERR("%s: %p %d reg_size %d\n", __func__, addr, size,
+							jpeg_region_size);
+	line_str[0] = '\0';
+	p_str = line_str;
+	for (i = 0; i < size/4; i++) {
+		if (i % 4 == 0) {
+			snprintf(p_str, 12, "%08x: ", (u32) p);
+			p_str += 10;
+		}
+		data = readl_relaxed(p++);
+		snprintf(p_str, 12, "%08x ", data);
+		p_str += 9;
+		if ((i + 1) % 4 == 0) {
+			JPEG_PR_ERR("%s\n", line_str);
+			line_str[0] = '\0';
+			p_str = line_str;
+		}
+	}
+	if (line_str[0] != '\0')
+		JPEG_PR_ERR("%s\n", line_str);
+}
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h
new file mode 100644
index 0000000..73a0e27
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw.h
@@ -0,0 +1,101 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_JPEG_HW_H
+#define MSM_JPEG_HW_H
+
+#include <media/msm_jpeg.h>
+#include "msm_jpeg_hw_reg.h"
+#include <linux/ion.h>
+#include <mach/iommu_domains.h>
+
+struct msm_jpeg_hw_buf {
+	struct msm_jpeg_buf vbuf;
+	struct file  *file;
+	uint32_t framedone_len;
+	uint32_t y_buffer_addr;
+	uint32_t y_len;
+	uint32_t cbcr_buffer_addr;
+	uint32_t cbcr_len;
+	uint32_t num_of_mcu_rows;
+	struct ion_handle *handle;
+};
+
+struct msm_jpeg_hw_pingpong {
+	uint8_t is_fe; /* 1: fe; 0: we */
+	struct  msm_jpeg_hw_buf buf[2];
+	int     buf_status[2];
+	int     buf_active_index;
+};
+
+int msm_jpeg_hw_pingpong_update(struct msm_jpeg_hw_pingpong *pingpong_hw,
+	struct msm_jpeg_hw_buf *buf);
+void *msm_jpeg_hw_pingpong_irq(struct msm_jpeg_hw_pingpong *pingpong_hw);
+void *msm_jpeg_hw_pingpong_active_buffer(struct msm_jpeg_hw_pingpong
+	*pingpong_hw);
+
+void msm_jpeg_hw_irq_clear(uint32_t, uint32_t);
+int msm_jpeg_hw_irq_get_status(void);
+long msm_jpeg_hw_encode_output_size(void);
+#define MSM_JPEG_HW_MASK_COMP_FRAMEDONE \
+		MSM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK
+#define MSM_JPEG_HW_MASK_COMP_FE \
+		MSM_JPEG_HW_IRQ_STATUS_FE_RD_DONE_MASK
+#define MSM_JPEG_HW_MASK_COMP_WE \
+		(MSM_JPEG_HW_IRQ_STATUS_WE_Y_PINGPONG_MASK | \
+		 MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_PINGPONG_MASK)
+#define MSM_JPEG_HW_MASK_COMP_RESET_ACK \
+		MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK
+#define MSM_JPEG_HW_MASK_COMP_ERR \
+		(MSM_JPEG_HW_IRQ_STATUS_FE_RTOVF_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_FE_VFE_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK | \
+		MSM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK)
+
+#define msm_jpeg_hw_irq_is_frame_done(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_FRAMEDONE)
+#define msm_jpeg_hw_irq_is_fe_pingpong(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_FE)
+#define msm_jpeg_hw_irq_is_we_pingpong(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_WE)
+#define msm_jpeg_hw_irq_is_reset_ack(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_RESET_ACK)
+#define msm_jpeg_hw_irq_is_err(jpeg_irq_status) \
+	(jpeg_irq_status & MSM_JPEG_HW_MASK_COMP_ERR)
+
+void msm_jpeg_hw_fe_buffer_update(struct msm_jpeg_hw_buf *p_input,
+	uint8_t pingpong_index);
+void msm_jpeg_hw_we_buffer_update(struct msm_jpeg_hw_buf *p_input,
+	uint8_t pingpong_index);
+
+void msm_jpeg_hw_we_buffer_cfg(uint8_t is_realtime);
+
+void msm_jpeg_hw_fe_start(void);
+void msm_jpeg_hw_clk_cfg(void);
+
+void msm_jpeg_hw_reset(void *base, int size);
+void msm_jpeg_hw_irq_cfg(void);
+void msm_jpeg_hw_init(void *base, int size);
+
+uint32_t msm_jpeg_hw_read(struct msm_jpeg_hw_cmd *hw_cmd_p);
+void msm_jpeg_hw_write(struct msm_jpeg_hw_cmd *hw_cmd_p);
+int msm_jpeg_hw_wait(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us);
+void msm_jpeg_hw_delay(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_us);
+int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, int m_cmds);
+void msm_jpeg_hw_region_dump(int size);
+void msm_jpeg_io_dump(int size);
+
+#endif /* MSM_JPEG_HW_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
new file mode 100644
index 0000000..ae64c32
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_hw_reg.h
@@ -0,0 +1,121 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_JPEG_HW_REG_H
+#define MSM_JPEG_HW_REG_H
+
+#define JPEG_REG_BASE 0
+
+#define MSM_JPEG_HW_IRQ_MASK_ADDR 0x00000018
+#define MSM_JPEG_HW_IRQ_MASK_RMSK 0xFFFFFFFF
+#define MSM_JPEG_HW_IRQ_ENABLE 0xFFFFFFFF
+
+#define MSM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK 0x00000001
+#define MSM_JPEG_HW_IRQ_STATUS_FRAMEDONE_SHIFT 0x00000000
+
+#define MSM_JPEG_HW_IRQ_STATUS_FE_RD_DONE_MASK 0x00000010
+#define MSM_JPEG_HW_IRQ_STATUS_FE_RD_DONE_SHIFT 0x00000001
+
+#define MSM_JPEG_HW_IRQ_STATUS_FE_RTOVF_MASK 0x00000004
+#define MSM_JPEG_HW_IRQ_STATUS_FE_RTOVF_SHIFT 0x00000002
+
+#define MSM_JPEG_HW_IRQ_STATUS_FE_VFE_OVERFLOW_MASK 0x00000008
+#define MSM_JPEG_HW_IRQ_STATUS_FE_VFE_OVERFLOW_SHIFT 0x00000003
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_PINGPONG_MASK 0x00000010
+#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_PINGPONG_SHIFT 0x00000004
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_PINGPONG_MASK 0x00000020
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_PINGPONG_SHIFT 0x00000005
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_MASK 0x00000040
+#define MSM_JPEG_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_SHIFT 0x00000006
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_MASK 0x00000080
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_SHIFT 0x00000007
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_MASK 0x00000100
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_SHIFT 0x00000008
+
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_MASK 0x00000200
+#define MSM_JPEG_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_SHIFT 0x00000009
+
+#define MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000
+#define MSM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a
+
+#define MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800
+#define MSM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b
+
+#define MSM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK 0x00001000
+#define MSM_JPEG_HW_IRQ_STATUS_VIOLATION_SHIFT 0x0000000c
+
+#define JPEG_OFFLINE_CMD_START 0x00000001
+
+#define JPEG_RESET_DEFAULT 0x00000003 /* cfff? */
+
+#define JPEG_IRQ_DISABLE_ALL 0x00000000
+#define JPEG_IRQ_CLEAR_ALL 0xFFFFFFFF
+
+#define JPEG_PLN0_RD_PNTR_ADDR (JPEG_REG_BASE + 0x00000038)
+#define JPEG_PLN0_RD_PNTR_BMSK  0xFFFFFFFF
+
+#define JPEG_PLN0_RD_OFFSET_ADDR 0x0000003C
+#define JPEG_PLN0_RD_OFFSET_BMSK 0x1FFFFFFF
+
+#define JPEG_PLN1_RD_PNTR_ADDR (JPEG_REG_BASE + 0x00000044)
+#define JPEG_PLN1_RD_PNTR_BMSK 0xFFFFFFFF
+
+#define JPEG_PLN1_RD_OFFSET_ADDR 0x00000048
+#define JPEG_PLN1_RD_OFFSET_BMSK 0x1FFFFFFF
+
+#define JPEG_CMD_ADDR (JPEG_REG_BASE + 0x00000010)
+#define JPEG_CMD_BMSK 0x00000FFF
+#define JPEG_CMD_CLEAR_WRITE_PLN_QUEUES 0x700
+
+#define JPEG_PLN0_WR_PNTR_ADDR (JPEG_REG_BASE + 0x000000cc)
+#define JPEG_PLN0_WR_PNTR_BMSK 0xFFFFFFFF
+
+#define JPEG_PLN1_WR_PNTR_ADDR (JPEG_REG_BASE + 0x000000D0)
+#define JPEG_PLN1_WR_PNTR_BMSK 0xFFFFFFFF
+
+#define JPEG_IRQ_MASK_ADDR (JPEG_REG_BASE + 0x00000018)
+#define JPEG_IRQ_MASK_BMSK 0xFFFFFFFF
+#define JPEG_IRQ_ALLSOURCES_ENABLE 0xFFFFFFFF
+
+#define JPEG_IRQ_CLEAR_ADDR (JPEG_REG_BASE + 0x0000001c)
+#define JPEG_IRQ_CLEAR_BMSK 0xFFFFFFFF
+
+#define JPEG_RESET_CMD_ADDR (JPEG_REG_BASE + 0x00000008)
+#define JPEG_RESET_CMD_RMSK 0xFFFFFFFF
+
+#define JPEG_IRQ_STATUS_ADDR (JPEG_REG_BASE + 0x00000020)
+#define JPEG_IRQ_STATUS_BMSK 0xFFFFFFFF
+
+#define JPEG_ENCODE_OUTPUT_SIZE_STATUS_ADDR (JPEG_REG_BASE + 0x00000180)
+#define JPEG_ENCODE_OUTPUT_SIZE_STATUS_BMSK 0x1FFFFFFF
+
+
+#define VBIF_BASE_ADDRESS                      0xFDA60000
+#define VBIF_REGION_SIZE                       0xC30
+#define JPEG_VBIF_CLKON                        0x4
+#define JPEG_VBIF_IN_RD_LIM_CONF0              0xB0
+#define JPEG_VBIF_IN_RD_LIM_CONF1              0xB4
+#define JPEG_VBIF_IN_RD_LIM_CONF2              0xB8
+#define JPEG_VBIF_IN_WR_LIM_CONF0              0xC0
+#define JPEG_VBIF_IN_WR_LIM_CONF1              0xC4
+#define JPEG_VBIF_IN_WR_LIM_CONF2              0xC8
+#define JPEG_VBIF_OUT_RD_LIM_CONF0             0xD0
+#define JPEG_VBIF_OUT_WR_LIM_CONF0             0xD4
+#define JPEG_VBIF_DDR_OUT_MAX_BURST            0xD8
+#define JPEG_VBIF_OCMEM_OUT_MAX_BURST          0xDC
+
+#endif /* MSM_JPEG_HW_REG_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
new file mode 100644
index 0000000..981c56c
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
@@ -0,0 +1,288 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+
+#include <linux/module.h>
+#include <linux/pm_qos.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <linux/io.h>
+#include <linux/android_pmem.h>
+#include <mach/camera.h>
+#include <mach/iommu_domains.h>
+
+#include "msm_jpeg_platform.h"
+#include "msm_jpeg_sync.h"
+#include "msm_jpeg_common.h"
+#include "msm_jpeg_hw.h"
+
+/* AXI rate in KHz */
+struct ion_client *jpeg_client;
+static void *jpeg_vbif;
+
+void msm_jpeg_platform_p2v(struct file  *file,
+				struct ion_handle **ionhandle, int domain_num)
+{
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_unmap_iommu(jpeg_client, *ionhandle, domain_num, 0);
+	ion_free(jpeg_client, *ionhandle);
+	*ionhandle = NULL;
+#elif CONFIG_ANDROID_PMEM
+	put_pmem_file(file);
+#endif
+}
+
+uint32_t msm_jpeg_platform_v2p(int fd, uint32_t len, struct file **file_p,
+				struct ion_handle **ionhandle, int domain_num)
+{
+	unsigned long paddr;
+	unsigned long size;
+	int rc;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	*ionhandle = ion_import_dma_buf(jpeg_client, fd);
+	if (IS_ERR_OR_NULL(*ionhandle))
+		return 0;
+
+	rc = ion_map_iommu(jpeg_client, *ionhandle, domain_num, 0,
+			 SZ_4K, 0, &paddr, (unsigned long *)&size, UNCACHED, 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,
+			rc);
+		goto error1;
+	}
+
+	/* validate user input */
+	if (len > size) {
+		JPEG_PR_ERR("%s: invalid offset + len\n", __func__);
+		goto error1;
+	}
+
+	return paddr;
+error1:
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_free(jpeg_client, *ionhandle);
+#endif
+	return 0;
+}
+
+static struct msm_cam_clk_info jpeg_8x_clk_info[] = {
+	{"core_clk", 228570000},
+	{"iface_clk", -1},
+	{"bus_clk0", -1},
+	{"alt_bus_clk", -1},
+	{"camss_top_ahb_clk", -1},
+};
+
+static void set_vbif_params(void *jpeg_vbif_base)
+{
+	writel_relaxed(0x1,
+		jpeg_vbif_base + JPEG_VBIF_CLKON);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF0);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF1);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF2);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF0);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF1);
+	writel_relaxed(0x10101010,
+		jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF2);
+	writel_relaxed(0x00001010,
+		jpeg_vbif_base + JPEG_VBIF_OUT_RD_LIM_CONF0);
+	writel_relaxed(0x00001010,
+		jpeg_vbif_base + JPEG_VBIF_OUT_WR_LIM_CONF0);
+	writel_relaxed(0x00000707,
+		jpeg_vbif_base + JPEG_VBIF_DDR_OUT_MAX_BURST);
+	writel_relaxed(0x00000707,
+		jpeg_vbif_base + JPEG_VBIF_OCMEM_OUT_MAX_BURST);
+}
+
+
+int msm_jpeg_platform_init(struct platform_device *pdev,
+	struct resource **mem,
+	void **base,
+	int *irq,
+	irqreturn_t (*handler) (int, void *),
+	void *context)
+{
+	int rc = -1;
+	int i = 0;
+	int jpeg_irq;
+	struct resource *jpeg_mem, *jpeg_io, *jpeg_irq_res;
+	void *jpeg_base;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *) context;
+
+	jpeg_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!jpeg_mem) {
+		JPEG_PR_ERR("%s: no mem resource?\n", __func__);
+		return -ENODEV;
+	}
+
+	jpeg_irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!jpeg_irq_res) {
+		JPEG_PR_ERR("no irq resource?\n");
+		return -ENODEV;
+	}
+	jpeg_irq = jpeg_irq_res->start;
+	JPEG_DBG("%s base address: 0x%x, jpeg irq number: %d\n", __func__,
+						jpeg_mem->start, jpeg_irq);
+
+	jpeg_io = request_mem_region(jpeg_mem->start,
+					resource_size(jpeg_mem), pdev->name);
+	if (!jpeg_io) {
+		JPEG_PR_ERR("%s: region already claimed\n", __func__);
+		return -EBUSY;
+	}
+
+	jpeg_base = ioremap(jpeg_mem->start, resource_size(jpeg_mem));
+	if (!jpeg_base) {
+		rc = -ENOMEM;
+		JPEG_PR_ERR("%s: ioremap failed\n", __func__);
+		goto fail1;
+	}
+
+	jpeg_vbif = ioremap(VBIF_BASE_ADDRESS, VBIF_REGION_SIZE);
+	if (!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)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__); }
+
+	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;
+	}
+
+#ifdef CONFIG_MSM_IOMMU
+	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
+		rc = iommu_attach_device(pgmn_dev->domain,
+				pgmn_dev->iommu_ctx_arr[i]);
+		if (rc < 0) {
+			rc = -ENODEV;
+			JPEG_PR_ERR("%s: Device attach failed\n", __func__);
+			goto fail;
+		}
+		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(jpeg_vbif);
+
+	msm_jpeg_hw_init(jpeg_base, resource_size(jpeg_mem));
+	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;
+	}
+
+	*mem  = jpeg_mem;
+	*base = jpeg_base;
+	*irq  = jpeg_irq;
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	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:
+#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__,
+					(uint32_t)pgmn_dev->domain,
+					(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
+		iommu_detach_device(pgmn_dev->domain,
+					pgmn_dev->iommu_ctx_arr[i]);
+	}
+#endif
+fail:
+	release_mem_region(jpeg_mem->start, resource_size(jpeg_mem));
+	JPEG_DBG("%s:%d] fail\n", __func__, __LINE__);
+	return rc;
+}
+
+int msm_jpeg_platform_release(struct resource *mem, void *base, int irq,
+	void *context)
+{
+	int result = 0;
+	int i = 0;
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *) context;
+
+	free_irq(irq, context);
+
+#ifdef CONFIG_MSM_IOMMU
+	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
+		iommu_detach_device(pgmn_dev->domain,
+				pgmn_dev->iommu_ctx_arr[i]);
+		JPEG_DBG("%s:%d]", __func__, __LINE__);
+	}
+#endif
+
+	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__);
+
+	if (pgmn_dev->jpeg_fs) {
+		regulator_put(pgmn_dev->jpeg_fs);
+		regulator_disable(pgmn_dev->jpeg_fs);
+		pgmn_dev->jpeg_fs = NULL;
+	}
+	iounmap(jpeg_vbif);
+	iounmap(base);
+	release_mem_region(mem->start, resource_size(mem));
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_client_destroy(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/video/msm/jpeg_10/msm_jpeg_platform.h
new file mode 100644
index 0000000..8a37cef
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_JPEG_PLATFORM_H
+#define MSM_JPEG_PLATFORM_H
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/ion.h>
+#include <linux/iommu.h>
+#include <mach/iommu.h>
+
+
+void msm_jpeg_platform_p2v(struct file  *file,
+				struct ion_handle **ionhandle, int domain_num);
+uint32_t msm_jpeg_platform_v2p(int fd, uint32_t len, struct file **file,
+				struct ion_handle **ionhandle, int domain_num);
+
+int msm_jpeg_platform_clk_enable(void);
+int msm_jpeg_platform_clk_disable(void);
+
+int msm_jpeg_platform_init(struct platform_device *pdev,
+	struct resource **mem,
+	void **base,
+	int *irq,
+	irqreturn_t (*handler) (int, void *),
+	void *context);
+int msm_jpeg_platform_release(struct resource *mem, void *base, int irq,
+	void *context);
+
+#endif /* MSM_JPEG_PLATFORM_H */
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
new file mode 100644
index 0000000..6ac4a5e
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.c
@@ -0,0 +1,897 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <media/msm_jpeg.h>
+#include "msm_jpeg_sync.h"
+#include "msm_jpeg_core.h"
+#include "msm_jpeg_platform.h"
+#include "msm_jpeg_common.h"
+
+static int release_buf;
+
+inline void msm_jpeg_q_init(char const *name, struct msm_jpeg_q *q_p)
+{
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, name);
+	q_p->name = name;
+	spin_lock_init(&q_p->lck);
+	INIT_LIST_HEAD(&q_p->q);
+	init_waitqueue_head(&q_p->wait);
+	q_p->unblck = 0;
+}
+
+inline void *msm_jpeg_q_out(struct msm_jpeg_q *q_p)
+{
+	unsigned long flags;
+	struct msm_jpeg_q_entry *q_entry_p = NULL;
+	void *data = NULL;
+
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	spin_lock_irqsave(&q_p->lck, flags);
+	if (!list_empty(&q_p->q)) {
+		q_entry_p = list_first_entry(&q_p->q, struct msm_jpeg_q_entry,
+			list);
+		list_del_init(&q_entry_p->list);
+	}
+	spin_unlock_irqrestore(&q_p->lck, flags);
+
+	if (q_entry_p) {
+		data = q_entry_p->data;
+		kfree(q_entry_p);
+	} else {
+		JPEG_DBG("%s:%d] %s no entry\n", __func__, __LINE__,
+			q_p->name);
+	}
+
+	return data;
+}
+
+inline int msm_jpeg_q_in(struct msm_jpeg_q *q_p, void *data)
+{
+	unsigned long flags;
+
+	struct msm_jpeg_q_entry *q_entry_p;
+
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+
+	q_entry_p = kmalloc(sizeof(struct msm_jpeg_q_entry), GFP_ATOMIC);
+	if (!q_entry_p) {
+		JPEG_PR_ERR("%s: no mem\n", __func__);
+		return -EFAULT;
+	}
+	q_entry_p->data = data;
+
+	spin_lock_irqsave(&q_p->lck, flags);
+	list_add_tail(&q_entry_p->list, &q_p->q);
+	spin_unlock_irqrestore(&q_p->lck, flags);
+
+	return 0;
+}
+
+inline int msm_jpeg_q_in_buf(struct msm_jpeg_q *q_p,
+	struct msm_jpeg_core_buf *buf)
+{
+	struct msm_jpeg_core_buf *buf_p;
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC);
+	if (!buf_p) {
+		JPEG_PR_ERR("%s: no mem\n", __func__);
+		return -EFAULT;
+	}
+
+	memcpy(buf_p, buf, sizeof(struct msm_jpeg_core_buf));
+
+	msm_jpeg_q_in(q_p, buf_p);
+	return 0;
+}
+
+inline int msm_jpeg_q_wait(struct msm_jpeg_q *q_p)
+{
+	int tm = MAX_SCHEDULE_TIMEOUT; /* 500ms */
+	int rc;
+
+	JPEG_DBG("%s:%d] %s wait\n", __func__, __LINE__, q_p->name);
+	rc = wait_event_interruptible_timeout(q_p->wait,
+		(!list_empty_careful(&q_p->q) || q_p->unblck),
+		msecs_to_jiffies(tm));
+	JPEG_DBG("%s:%d] %s wait done\n", __func__, __LINE__, q_p->name);
+	if (list_empty_careful(&q_p->q)) {
+		if (rc == 0) {
+			rc = -ETIMEDOUT;
+			JPEG_PR_ERR("%s:%d] %s timeout\n", __func__, __LINE__,
+				q_p->name);
+		} else if (q_p->unblck) {
+			JPEG_DBG("%s:%d] %s unblock is true\n", __func__,
+				__LINE__, q_p->name);
+			q_p->unblck = 0;
+			rc = -ECANCELED;
+		} else if (rc < 0) {
+			JPEG_PR_ERR("%s:%d] %s rc %d\n", __func__, __LINE__,
+				q_p->name, rc);
+		}
+	}
+	return rc;
+}
+
+inline int msm_jpeg_q_wakeup(struct msm_jpeg_q *q_p)
+{
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	wake_up(&q_p->wait);
+	return 0;
+}
+
+inline int msm_jpeg_q_unblock(struct msm_jpeg_q *q_p)
+{
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	q_p->unblck = 1;
+	wake_up(&q_p->wait);
+	return 0;
+}
+
+inline void msm_jpeg_outbuf_q_cleanup(struct msm_jpeg_q *q_p,
+				int domain_num)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	do {
+		buf_p = msm_jpeg_q_out(q_p);
+		if (buf_p) {
+			msm_jpeg_platform_p2v(buf_p->file,
+				&buf_p->handle, domain_num);
+			JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+			kfree(buf_p);
+		}
+	} while (buf_p);
+	q_p->unblck = 0;
+}
+
+inline void msm_jpeg_q_cleanup(struct msm_jpeg_q *q_p)
+{
+	void *data;
+	JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+	do {
+		data = msm_jpeg_q_out(q_p);
+		if (data) {
+			JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name);
+			kfree(data);
+		}
+	} while (data);
+	q_p->unblck = 0;
+}
+
+/*************** event queue ****************/
+
+int msm_jpeg_framedone_irq(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf_in)
+{
+	int rc = 0;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+
+	if (buf_in) {
+		buf_in->vbuf.framedone_len = buf_in->framedone_len;
+		buf_in->vbuf.type = MSM_JPEG_EVT_SESSION_DONE;
+		JPEG_DBG("%s:%d] 0x%08x %d framedone_len %d\n",
+			__func__, __LINE__,
+			(int) buf_in->y_buffer_addr, buf_in->y_len,
+			buf_in->vbuf.framedone_len);
+		rc = msm_jpeg_q_in_buf(&pgmn_dev->evt_q, buf_in);
+	} else {
+		JPEG_PR_ERR("%s:%d] no output return buffer\n",
+			__func__, __LINE__);
+		rc = -1;
+	}
+
+	if (buf_in)
+		rc = msm_jpeg_q_wakeup(&pgmn_dev->evt_q);
+
+	return rc;
+}
+
+int msm_jpeg_evt_get(struct msm_jpeg_device *pgmn_dev,
+	void __user *to)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	struct msm_jpeg_ctrl_cmd ctrl_cmd;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+
+	msm_jpeg_q_wait(&pgmn_dev->evt_q);
+	buf_p = msm_jpeg_q_out(&pgmn_dev->evt_q);
+
+	if (!buf_p) {
+		JPEG_DBG("%s:%d] no buffer\n", __func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	ctrl_cmd.type = buf_p->vbuf.type;
+	kfree(buf_p);
+
+	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		(int) ctrl_cmd.value, ctrl_cmd.len);
+
+	if (copy_to_user(to, &ctrl_cmd, sizeof(ctrl_cmd))) {
+		JPEG_PR_ERR("%s:%d]\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int msm_jpeg_evt_get_unblock(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_q_unblock(&pgmn_dev->evt_q);
+	return 0;
+}
+
+void msm_jpeg_reset_ack_irq(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+}
+
+void msm_jpeg_err_irq(struct msm_jpeg_device *pgmn_dev,
+	int event)
+{
+	int rc = 0;
+	struct msm_jpeg_core_buf buf;
+
+	JPEG_PR_ERR("%s:%d] error: %d\n", __func__, __LINE__, event);
+
+	buf.vbuf.type = MSM_JPEG_EVT_ERR;
+	rc = msm_jpeg_q_in_buf(&pgmn_dev->evt_q, &buf);
+	if (!rc)
+		rc = msm_jpeg_q_wakeup(&pgmn_dev->evt_q);
+
+	if (!rc)
+		JPEG_PR_ERR("%s:%d] err err\n", __func__, __LINE__);
+
+	return;
+}
+
+/*************** output queue ****************/
+
+int msm_jpeg_we_pingpong_irq(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf_in)
+{
+	int rc = 0;
+	struct msm_jpeg_core_buf *buf_out;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (buf_in) {
+		JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+			(int) buf_in->y_buffer_addr, buf_in->y_len);
+		rc = msm_jpeg_q_in_buf(&pgmn_dev->output_rtn_q, buf_in);
+	} else {
+		JPEG_DBG("%s:%d] no output return buffer\n", __func__,
+			__LINE__);
+		rc = -1;
+		return rc;
+	}
+
+	buf_out = msm_jpeg_q_out(&pgmn_dev->output_buf_q);
+
+	if (buf_out) {
+		JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+			(int) buf_out->y_buffer_addr, buf_out->y_len);
+		rc = msm_jpeg_core_we_buf_update(buf_out);
+		kfree(buf_out);
+	} else {
+		msm_jpeg_core_we_buf_reset(buf_in);
+		JPEG_DBG("%s:%d] no output buffer\n", __func__, __LINE__);
+		rc = -2;
+	}
+
+	if (buf_in)
+		rc = msm_jpeg_q_wakeup(&pgmn_dev->output_rtn_q);
+
+	return rc;
+}
+
+int msm_jpeg_output_get(struct msm_jpeg_device *pgmn_dev, void __user *to)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	struct msm_jpeg_buf buf_cmd;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+
+	msm_jpeg_q_wait(&pgmn_dev->output_rtn_q);
+	buf_p = msm_jpeg_q_out(&pgmn_dev->output_rtn_q);
+
+	if (!buf_p) {
+		JPEG_DBG("%s:%d] no output buffer return\n",
+			__func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	buf_cmd = buf_p->vbuf;
+	msm_jpeg_platform_p2v(buf_p->file, &buf_p->handle,
+		pgmn_dev->domain_num);
+	kfree(buf_p);
+
+	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		(int) buf_cmd.vaddr, buf_cmd.y_len);
+
+	if (copy_to_user(to, &buf_cmd, sizeof(buf_cmd))) {
+		JPEG_PR_ERR("%s:%d]", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int msm_jpeg_output_get_unblock(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_q_unblock(&pgmn_dev->output_rtn_q);
+	return 0;
+}
+
+int msm_jpeg_output_buf_enqueue(struct msm_jpeg_device *pgmn_dev,
+	void __user *arg)
+{
+	struct msm_jpeg_buf buf_cmd;
+	struct msm_jpeg_core_buf *buf_p;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_jpeg_buf))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC);
+	if (!buf_p) {
+		JPEG_PR_ERR("%s:%d] no mem\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	JPEG_DBG("%s:%d] vaddr = 0x%08x y_len = %d\n, fd = %d",
+		__func__, __LINE__, (int) buf_cmd.vaddr, buf_cmd.y_len,
+		buf_cmd.fd);
+
+	buf_p->y_buffer_addr = msm_jpeg_platform_v2p(buf_cmd.fd,
+		buf_cmd.y_len, &buf_p->file, &buf_p->handle,
+		pgmn_dev->domain_num);
+	if (!buf_p->y_buffer_addr) {
+		JPEG_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__);
+		kfree(buf_p);
+		return -EFAULT;
+	}
+	JPEG_DBG("%s:%d]After v2p y_address =0x%08x, handle = %p\n",
+		__func__, __LINE__, buf_p->y_buffer_addr, buf_p->handle);
+	buf_p->y_len = buf_cmd.y_len;
+	buf_p->vbuf = buf_cmd;
+
+	msm_jpeg_q_in(&pgmn_dev->output_buf_q, buf_p);
+	return 0;
+}
+
+/*************** input queue ****************/
+
+int msm_jpeg_fe_pingpong_irq(struct msm_jpeg_device *pgmn_dev,
+	struct msm_jpeg_core_buf *buf_in)
+{
+	struct msm_jpeg_core_buf *buf_out;
+	int rc = 0;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (buf_in) {
+		JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+			(int) buf_in->y_buffer_addr, buf_in->y_len);
+		rc = msm_jpeg_q_in_buf(&pgmn_dev->input_rtn_q, buf_in);
+	} else {
+		JPEG_DBG("%s:%d] no input return buffer\n", __func__,
+			__LINE__);
+		rc = -EFAULT;
+	}
+
+	buf_out = msm_jpeg_q_out(&pgmn_dev->input_buf_q);
+
+	if (buf_out) {
+		rc = msm_jpeg_core_fe_buf_update(buf_out);
+		kfree(buf_out);
+		msm_jpeg_core_fe_start();
+	} else {
+		JPEG_DBG("%s:%d] no input buffer\n", __func__, __LINE__);
+		rc = -EFAULT;
+	}
+
+	if (buf_in)
+		rc = msm_jpeg_q_wakeup(&pgmn_dev->input_rtn_q);
+
+	return rc;
+}
+
+int msm_jpeg_input_get(struct msm_jpeg_device *pgmn_dev, void __user *to)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	struct msm_jpeg_buf buf_cmd;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_q_wait(&pgmn_dev->input_rtn_q);
+	buf_p = msm_jpeg_q_out(&pgmn_dev->input_rtn_q);
+
+	if (!buf_p) {
+		JPEG_DBG("%s:%d] no input buffer return\n",
+			__func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	buf_cmd = buf_p->vbuf;
+	msm_jpeg_platform_p2v(buf_p->file, &buf_p->handle,
+					pgmn_dev->domain_num);
+	kfree(buf_p);
+
+	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		(int) buf_cmd.vaddr, buf_cmd.y_len);
+
+	if (copy_to_user(to, &buf_cmd, sizeof(buf_cmd))) {
+		JPEG_PR_ERR("%s:%d]\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int msm_jpeg_input_get_unblock(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_q_unblock(&pgmn_dev->input_rtn_q);
+	return 0;
+}
+
+int msm_jpeg_input_buf_enqueue(struct msm_jpeg_device *pgmn_dev,
+	void __user *arg)
+{
+	struct msm_jpeg_core_buf *buf_p;
+	struct msm_jpeg_buf buf_cmd;
+
+	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_jpeg_buf))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC);
+	if (!buf_p) {
+		JPEG_PR_ERR("%s:%d] no mem\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		(int) buf_cmd.vaddr, buf_cmd.y_len);
+
+	buf_p->y_buffer_addr    = msm_jpeg_platform_v2p(buf_cmd.fd,
+		buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
+		&buf_p->handle, pgmn_dev->domain_num) + buf_cmd.offset
+		+ buf_cmd.y_off;
+	buf_p->y_len          = buf_cmd.y_len;
+	buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr + buf_cmd.y_len
+						+ buf_cmd.cbcr_off;
+	buf_p->cbcr_len       = buf_cmd.cbcr_len;
+	buf_p->num_of_mcu_rows = buf_cmd.num_of_mcu_rows;
+	JPEG_DBG("%s: y_addr=%x, y_len=%x, cbcr_addr=%x, cbcr_len=%x, fd =%d\n",
+		__func__, buf_p->y_buffer_addr, buf_p->y_len,
+		buf_p->cbcr_buffer_addr, buf_p->cbcr_len, buf_cmd.fd);
+
+	if (!buf_p->y_buffer_addr || !buf_p->cbcr_buffer_addr) {
+		JPEG_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__);
+		kfree(buf_p);
+		return -EFAULT;
+	}
+	buf_p->vbuf           = buf_cmd;
+
+	msm_jpeg_q_in(&pgmn_dev->input_buf_q, buf_p);
+
+	return 0;
+}
+
+int msm_jpeg_irq(int event, void *context, void *data)
+{
+	struct msm_jpeg_device *pgmn_dev =
+		(struct msm_jpeg_device *) context;
+
+	switch (event) {
+	case MSM_JPEG_EVT_SESSION_DONE:
+		msm_jpeg_framedone_irq(pgmn_dev, data);
+		msm_jpeg_we_pingpong_irq(pgmn_dev, data);
+		break;
+
+	case MSM_JPEG_HW_MASK_COMP_FE:
+		msm_jpeg_fe_pingpong_irq(pgmn_dev, data);
+		break;
+
+	case MSM_JPEG_HW_MASK_COMP_WE:
+		msm_jpeg_we_pingpong_irq(pgmn_dev, data);
+		break;
+
+	case MSM_JPEG_HW_MASK_COMP_RESET_ACK:
+		msm_jpeg_reset_ack_irq(pgmn_dev);
+		break;
+
+	case MSM_JPEG_HW_MASK_COMP_ERR:
+	default:
+		msm_jpeg_err_irq(pgmn_dev, event);
+		break;
+	}
+
+	return 0;
+}
+
+int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev)
+{
+	int rc;
+
+	mutex_lock(&pgmn_dev->lock);
+	if (pgmn_dev->open_count) {
+		/* only open once */
+		JPEG_PR_ERR("%s:%d] busy\n", __func__, __LINE__);
+		mutex_unlock(&pgmn_dev->lock);
+		return -EBUSY;
+	}
+	pgmn_dev->open_count++;
+	mutex_unlock(&pgmn_dev->lock);
+
+	msm_jpeg_core_irq_install(msm_jpeg_irq);
+	rc = msm_jpeg_platform_init(pgmn_dev->pdev,
+		&pgmn_dev->mem, &pgmn_dev->base,
+		&pgmn_dev->irq, msm_jpeg_core_irq, pgmn_dev);
+	if (rc) {
+		JPEG_PR_ERR("%s:%d] platform_init fail %d\n", __func__,
+			__LINE__, rc);
+		return rc;
+	}
+
+	JPEG_DBG("%s:%d] platform resources - mem %p, base %p, irq %d\n",
+		__func__, __LINE__,
+		pgmn_dev->mem, pgmn_dev->base, pgmn_dev->irq);
+
+	msm_jpeg_q_cleanup(&pgmn_dev->evt_q);
+	msm_jpeg_q_cleanup(&pgmn_dev->output_rtn_q);
+	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->output_buf_q,
+	pgmn_dev->domain_num); msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q);
+	msm_jpeg_q_cleanup(&pgmn_dev->input_buf_q);
+	msm_jpeg_core_init();
+
+	JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
+	return rc;
+}
+
+int __msm_jpeg_release(struct msm_jpeg_device *pgmn_dev)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	mutex_lock(&pgmn_dev->lock);
+	if (!pgmn_dev->open_count) {
+		JPEG_PR_ERR(KERN_ERR "%s: not opened\n", __func__);
+		mutex_unlock(&pgmn_dev->lock);
+		return -EINVAL;
+	}
+	pgmn_dev->open_count--;
+	mutex_unlock(&pgmn_dev->lock);
+
+	msm_jpeg_core_release(release_buf, pgmn_dev->domain_num);
+	msm_jpeg_q_cleanup(&pgmn_dev->evt_q);
+	msm_jpeg_q_cleanup(&pgmn_dev->output_rtn_q);
+	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->output_buf_q,
+					pgmn_dev->domain_num);
+	msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q);
+	msm_jpeg_outbuf_q_cleanup(&pgmn_dev->input_buf_q, pgmn_dev->domain_num);
+
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	if (pgmn_dev->open_count)
+		JPEG_PR_ERR(KERN_ERR "%s: multiple opens\n", __func__);
+
+	msm_jpeg_platform_release(pgmn_dev->mem, pgmn_dev->base,
+		pgmn_dev->irq, pgmn_dev);
+
+	return 0;
+}
+
+int msm_jpeg_ioctl_hw_cmd(struct msm_jpeg_device *pgmn_dev,
+	void * __user arg)
+{
+	struct msm_jpeg_hw_cmd hw_cmd;
+	int is_copy_to_user;
+
+	if (copy_from_user(&hw_cmd, arg, sizeof(struct msm_jpeg_hw_cmd))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	is_copy_to_user = msm_jpeg_hw_exec_cmds(&hw_cmd, 1);
+	JPEG_DBG("%s:%d] type %d, n %d, offset %d, mask %x, data %x,pdata %x\n",
+		__func__, __LINE__, hw_cmd.type, hw_cmd.n, hw_cmd.offset,
+		hw_cmd.mask, hw_cmd.data, (int) hw_cmd.pdata);
+
+	if (is_copy_to_user >= 0) {
+		if (copy_to_user(arg, &hw_cmd, sizeof(hw_cmd))) {
+			JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+int msm_jpeg_ioctl_hw_cmds(struct msm_jpeg_device *pgmn_dev,
+	void * __user arg)
+{
+	int is_copy_to_user;
+	int len;
+	uint32_t m;
+	struct msm_jpeg_hw_cmds *hw_cmds_p;
+	struct msm_jpeg_hw_cmd *hw_cmd_p;
+
+	if (copy_from_user(&m, arg, sizeof(m))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	len = sizeof(struct msm_jpeg_hw_cmds) +
+		sizeof(struct msm_jpeg_hw_cmd) * (m - 1);
+	hw_cmds_p = kmalloc(len, GFP_KERNEL);
+	if (!hw_cmds_p) {
+		JPEG_PR_ERR("%s:%d] no mem %d\n", __func__, __LINE__, len);
+		return -EFAULT;
+	}
+
+	if (copy_from_user(hw_cmds_p, arg, len)) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		kfree(hw_cmds_p);
+		return -EFAULT;
+	}
+
+	hw_cmd_p = (struct msm_jpeg_hw_cmd *) &(hw_cmds_p->hw_cmd);
+
+	is_copy_to_user = msm_jpeg_hw_exec_cmds(hw_cmd_p, m);
+
+	if (is_copy_to_user >= 0) {
+		if (copy_to_user(arg, hw_cmds_p, len)) {
+			JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+			kfree(hw_cmds_p);
+			return -EFAULT;
+		}
+	}
+	kfree(hw_cmds_p);
+	return 0;
+}
+
+int msm_jpeg_start(struct msm_jpeg_device *pgmn_dev, void * __user arg)
+{
+	struct msm_jpeg_core_buf *buf_out;
+	struct msm_jpeg_core_buf *buf_out_free[2] = {NULL, NULL};
+	int i, rc;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+
+	release_buf = 1;
+	for (i = 0; i < 2; i++) {
+		buf_out = msm_jpeg_q_out(&pgmn_dev->input_buf_q);
+
+		if (buf_out) {
+			msm_jpeg_core_fe_buf_update(buf_out);
+			kfree(buf_out);
+		} else {
+			JPEG_DBG("%s:%d] no input buffer\n", __func__,
+					__LINE__);
+			break;
+		}
+	}
+
+	for (i = 0; i < 2; i++) {
+		buf_out_free[i] = msm_jpeg_q_out(&pgmn_dev->output_buf_q);
+
+		if (buf_out_free[i]) {
+			msm_jpeg_core_we_buf_update(buf_out_free[i]);
+			release_buf = 0;
+		} else {
+			JPEG_DBG("%s:%d] no output buffer\n",
+			__func__, __LINE__);
+			break;
+		}
+	}
+
+	for (i = 0; i < 2; i++)
+		kfree(buf_out_free[i]);
+
+	rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, arg);
+	JPEG_DBG("%s:%d]\n", __func__, __LINE__);
+	return rc;
+}
+
+int msm_jpeg_ioctl_reset(struct msm_jpeg_device *pgmn_dev,
+	void * __user arg)
+{
+	int rc;
+	struct msm_jpeg_ctrl_cmd ctrl_cmd;
+
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	if (copy_from_user(&ctrl_cmd, arg, sizeof(ctrl_cmd))) {
+		JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	pgmn_dev->op_mode = ctrl_cmd.type;
+
+	rc = msm_jpeg_core_reset(pgmn_dev->op_mode, pgmn_dev->base,
+		resource_size(pgmn_dev->mem));
+	return rc;
+}
+
+int msm_jpeg_ioctl_test_dump_region(struct msm_jpeg_device *pgmn_dev,
+	unsigned long arg)
+{
+	JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	msm_jpeg_io_dump(arg);
+	return 0;
+}
+
+long __msm_jpeg_ioctl(struct msm_jpeg_device *pgmn_dev,
+	unsigned int cmd, unsigned long arg)
+{
+	int rc = 0;
+	switch (cmd) {
+	case MSM_JPEG_IOCTL_GET_HW_VERSION:
+		JPEG_DBG("%s:%d] VERSION 1\n", __func__, __LINE__);
+		rc = msm_jpeg_ioctl_hw_cmd(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_RESET:
+		rc = msm_jpeg_ioctl_reset(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_STOP:
+		rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_START:
+		rc = msm_jpeg_start(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_INPUT_BUF_ENQUEUE:
+		rc = msm_jpeg_input_buf_enqueue(pgmn_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_INPUT_GET:
+		rc = msm_jpeg_input_get(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_INPUT_GET_UNBLOCK:
+		rc = msm_jpeg_input_get_unblock(pgmn_dev);
+		break;
+
+	case MSM_JPEG_IOCTL_OUTPUT_BUF_ENQUEUE:
+		rc = msm_jpeg_output_buf_enqueue(pgmn_dev,
+			(void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_OUTPUT_GET:
+		rc = msm_jpeg_output_get(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_OUTPUT_GET_UNBLOCK:
+		rc = msm_jpeg_output_get_unblock(pgmn_dev);
+		break;
+
+	case MSM_JPEG_IOCTL_EVT_GET:
+		rc = msm_jpeg_evt_get(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_EVT_GET_UNBLOCK:
+		rc = msm_jpeg_evt_get_unblock(pgmn_dev);
+		break;
+
+	case MSM_JPEG_IOCTL_HW_CMD:
+		rc = msm_jpeg_ioctl_hw_cmd(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_HW_CMDS:
+		rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg);
+		break;
+
+	case MSM_JPEG_IOCTL_TEST_DUMP_REGION:
+		rc = msm_jpeg_ioctl_test_dump_region(pgmn_dev, arg);
+		break;
+
+	default:
+		JPEG_PR_ERR(KERN_INFO "%s:%d] cmd = %d not supported\n",
+			__func__, __LINE__, _IOC_NR(cmd));
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+static int camera_register_domain(void)
+{
+	struct msm_iova_partition camera_fw_partition = {
+		.start = SZ_128K,
+		.size = SZ_2G - SZ_128K,
+	};
+
+	struct msm_iova_layout camera_fw_layout = {
+		.partitions = &camera_fw_partition,
+		.npartitions = 1,
+		.client_name = "camera_jpeg",
+		.domain_flags = 0,
+	};
+	return msm_register_domain(&camera_fw_layout);
+}
+#endif
+
+int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev)
+{
+	int rc = 0, i = 0;
+	int idx = 0;
+	char *iommu_name[3] = {"jpeg_enc0", "jpeg_enc1", "jpeg_dec"};
+
+	mutex_init(&pgmn_dev->lock);
+
+	pr_err("%s:%d] Jpeg Device id %d", __func__, __LINE__,
+		   pgmn_dev->pdev->id);
+	idx = pgmn_dev->pdev->id;
+	pgmn_dev->idx = idx;
+	pgmn_dev->iommu_cnt = 1;
+
+	msm_jpeg_q_init("evt_q", &pgmn_dev->evt_q);
+	msm_jpeg_q_init("output_rtn_q", &pgmn_dev->output_rtn_q);
+	msm_jpeg_q_init("output_buf_q", &pgmn_dev->output_buf_q);
+	msm_jpeg_q_init("input_rtn_q", &pgmn_dev->input_rtn_q);
+	msm_jpeg_q_init("input_buf_q", &pgmn_dev->input_buf_q);
+
+#ifdef CONFIG_MSM_IOMMU
+/*get device context for IOMMU*/
+	for (i = 0; i < pgmn_dev->iommu_cnt; i++) {
+		pgmn_dev->iommu_ctx_arr[i] = msm_iommu_get_ctx(iommu_name[i]);
+		JPEG_DBG("%s:%d] name %s", __func__, __LINE__, iommu_name[i]);
+		JPEG_DBG("%s:%d] ctx 0x%x", __func__, __LINE__,
+					(uint32_t)pgmn_dev->iommu_ctx_arr[i]);
+		if (!pgmn_dev->iommu_ctx_arr[i]) {
+			JPEG_PR_ERR("%s: No iommu fw context found\n",
+					__func__);
+			goto error;
+		}
+	}
+	pgmn_dev->domain_num = camera_register_domain();
+	JPEG_DBG("%s:%d] dom_num 0x%x", __func__, __LINE__,
+				pgmn_dev->domain_num);
+	if (pgmn_dev->domain_num < 0) {
+		JPEG_PR_ERR("%s: could not register domain\n", __func__);
+		goto error;
+	}
+	pgmn_dev->domain = msm_get_iommu_domain(pgmn_dev->domain_num);
+	JPEG_DBG("%s:%d] dom 0x%x", __func__, __LINE__,
+					(uint32_t)pgmn_dev->domain);
+	if (!pgmn_dev->domain) {
+		JPEG_PR_ERR("%s: cannot find domain\n", __func__);
+		goto error;
+	}
+#endif
+
+	return rc;
+error:
+	mutex_destroy(&pgmn_dev->lock);
+	return -EFAULT;
+}
+
+int __msm_jpeg_exit(struct msm_jpeg_device *pgmn_dev)
+{
+	mutex_destroy(&pgmn_dev->lock);
+	kfree(pgmn_dev);
+	return 0;
+}
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
new file mode 100644
index 0000000..1d82060
--- /dev/null
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_sync.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+
+#ifndef MSM_JPEG_SYNC_H
+#define MSM_JPEG_SYNC_H
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include "msm_jpeg_core.h"
+
+#define JPEG_7X 0x1
+#define JPEG_8X60 (0x1 << 1)
+#define JPEG_8960 (0x1 << 2)
+#define JPEG_8974 0x1
+
+struct msm_jpeg_q {
+	char const	*name;
+	struct list_head  q;
+	spinlock_t	lck;
+	wait_queue_head_t wait;
+	int	       unblck;
+};
+
+struct msm_jpeg_q_entry {
+	struct list_head list;
+	void   *data;
+};
+
+struct msm_jpeg_device {
+	struct platform_device *pdev;
+	struct resource        *mem;
+	int                     irq;
+	void                   *base;
+	struct clk *jpeg_clk[5];
+	struct regulator *jpeg_fs;
+	uint32_t hw_version;
+
+	struct device *device;
+	struct cdev   cdev;
+	struct mutex  lock;
+	char	  open_count;
+	uint8_t       op_mode;
+
+	/* event queue including frame done & err indications
+	 */
+	struct msm_jpeg_q evt_q;
+
+	/* output return queue
+	 */
+	struct msm_jpeg_q output_rtn_q;
+
+	/* output buf queue
+	 */
+	struct msm_jpeg_q output_buf_q;
+
+	/* input return queue
+	 */
+	struct msm_jpeg_q input_rtn_q;
+
+	/* input buf queue
+	 */
+	struct msm_jpeg_q input_buf_q;
+
+	struct v4l2_subdev subdev;
+
+	struct class *msm_jpeg_class;
+
+	dev_t msm_jpeg_devno;
+
+	/*iommu domain and context*/
+	int domain_num;
+	int idx;
+	struct iommu_domain *domain;
+	struct device *iommu_ctx_arr[3];
+	int iommu_cnt;
+};
+
+int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev);
+int __msm_jpeg_release(struct msm_jpeg_device *pgmn_dev);
+
+long __msm_jpeg_ioctl(struct msm_jpeg_device *pgmn_dev,
+	unsigned int cmd, unsigned long arg);
+
+int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev);
+int __msm_jpeg_exit(struct msm_jpeg_device *pgmn_dev);
+
+#endif /* MSM_JPEG_SYNC_H */
diff --git a/drivers/media/video/msm/mercury/msm_mercury_platform.h b/drivers/media/video/msm/mercury/msm_mercury_platform.h
index 8f4a7e3..9edbb30 100644
--- a/drivers/media/video/msm/mercury/msm_mercury_platform.h
+++ b/drivers/media/video/msm/mercury/msm_mercury_platform.h
@@ -15,7 +15,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 int msm_mercury_platform_clk_enable(void);
 int msm_mercury_platform_clk_disable(void);
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index e4dd756..50a9776 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -725,17 +725,22 @@
 				struct v4l2_streamparm *a)
 {
 	int rc = 0;
+	int is_bayer_sensor = 0;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 	pcam_inst->image_mode = (a->parm.capture.extendedmode & 0x7F);
+	SET_DEVID_MODE(pcam_inst->inst_handle, pcam_inst->pcam->vnode_id);
 	SET_IMG_MODE(pcam_inst->inst_handle, pcam_inst->image_mode);
 	SET_VIDEO_INST_IDX(pcam_inst->inst_handle, pcam_inst->my_index);
 	pcam_inst->pcam->dev_inst_map[pcam_inst->image_mode] = pcam_inst;
 	pcam_inst->path = msm_vidbuf_get_path(pcam_inst->image_mode);
+	if (pcam_inst->pcam->sdata->sensor_type == BAYER_SENSOR)
+		is_bayer_sensor = 1;
 	rc = msm_cam_server_config_interface_map(pcam_inst->image_mode,
-			pcam_inst->pcam->mctl_handle);
-	D("%spath=%d,rc=%d\n", __func__,
+			pcam_inst->pcam->mctl_handle, pcam_inst->pcam->vnode_id,
+			is_bayer_sensor);
+	D("%s path=%d, rc=%d\n", __func__,
 		pcam_inst->path, rc);
 	return rc;
 }
@@ -1149,6 +1154,7 @@
 
 	CLR_VIDEO_INST_IDX(pcam_inst->inst_handle);
 	CLR_IMG_MODE(pcam_inst->inst_handle);
+	CLR_DEVID_MODE(pcam_inst->inst_handle);
 	mutex_unlock(&pcam_inst->inst_lock);
 	mutex_destroy(&pcam_inst->inst_lock);
 	kfree(pcam_inst);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 3dc0fe7..cb59d68 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -33,7 +33,7 @@
 #include <mach/camera.h>
 #include <mach/iommu.h>
 #include <media/msm_isp.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/iommu.h>
 #include <media/msm_gestures.h>
 
@@ -58,6 +58,7 @@
 #define MSM_VPE_DRV_NAME "msm_vpe"
 #define MSM_GEMINI_DRV_NAME "msm_gemini"
 #define MSM_MERCURY_DRV_NAME "msm_mercury"
+#define MSM_JPEG_DRV_NAME "msm_jpeg"
 #define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
 #define MSM_IRQ_ROUTER_DRV_NAME "msm_cam_irq_router"
 #define MSM_CPP_DRV_NAME "msm_cpp"
@@ -514,12 +515,14 @@
 };
 
 struct interface_map {
-	/* The interafce a particular stream belongs to.
+	/* The interface a particular stream belongs to.
 	 * PIX0, RDI0, RDI1, or RDI2
 	 */
 	int interface;
-	/* The handle of the mctl intstance interface runs on */
+	/* The handle of the mctl instance, interface runs on */
 	uint32_t mctl_handle;
+	int vnode_id;
+	int is_bayer_sensor;
 };
 
 /* abstract camera server device for all sensor successfully probed*/
@@ -538,6 +541,8 @@
 	struct msm_cam_config_dev_info config_info;
 	/* active working camera device - only one allowed at this time*/
 	struct msm_cam_v4l2_device *pcam_active[MAX_NUM_ACTIVE_CAMERA];
+	/* save the opened pcam for finding the mctl when doing buf lookup */
+	struct msm_cam_v4l2_device *opened_pcam[MAX_NUM_ACTIVE_CAMERA];
 	/* number of camera devices opened*/
 	atomic_t number_pcam_active;
 	struct v4l2_queue_util server_command_queue;
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/video/msm/msm_camera.c
index 2f1d1ab..dce3630 100644
--- a/drivers/media/video/msm/msm_camera.c
+++ b/drivers/media/video/msm/msm_camera.c
@@ -34,7 +34,7 @@
 #include <mach/camera.h>
 #include <linux/syscalls.h>
 #include <linux/hrtimer.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #include <mach/cpuidle.h>
 DEFINE_MUTEX(ctrl_cmd_lock);
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 83f762c..1e17c5c 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -555,6 +555,7 @@
 	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC:
 	case CMD_AXI_START:
 	case CMD_AXI_STOP:
+	case CMD_AXI_RESET:
 	case CMD_AXI_CFG_TERT1:
 	case CMD_AXI_CFG_TERT2:
 		/* Dont need to pass buffer information.
@@ -640,6 +641,7 @@
 {
 	struct msm_vfe_cfg_cmd cfgcmd;
 	int rc = 0;
+	v4l2_set_subdev_hostdata(sd, mctl);
 	switch (cmd) {
 	case MSM_CAM_IOCTL_STATS_REQBUF: {
 		struct msm_stats_reqbuf reqbuf;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 0711ca5..c94da2a 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -449,10 +449,11 @@
 		break;
 			/* ISFIF config*/
 	case MSM_CAM_IOCTL_AXI_CONFIG:
-		if (p_mctl->axi_sdev)
+		if (p_mctl->axi_sdev) {
+			v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
 			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
 				VIDIOC_MSM_AXI_CFG, (void __user *)arg);
-		else
+		} else
 			rc = p_mctl->isp_config(p_mctl, cmd, arg);
 		break;
 	case MSM_CAM_IOCTL_ISPIF_IO_CFG:
@@ -478,6 +479,22 @@
 				core, ioctl, VIDIOC_MSM_CSID_CFG, argp);
 		break;
 
+	case MSM_CAM_IOCTL_AXI_INIT:
+		if (p_mctl->axi_sdev) {
+			v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
+			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+				VIDIOC_MSM_AXI_INIT, (void __user *)arg);
+		}
+		break;
+
+	case MSM_CAM_IOCTL_AXI_RELEASE:
+		if (p_mctl->axi_sdev) {
+			v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
+			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+				VIDIOC_MSM_AXI_RELEASE, NULL);
+		}
+		break;
+
 	default:
 		/* ISP config*/
 		D("%s:%d: go to default. Calling msm_isp_config\n",
@@ -575,7 +592,6 @@
 	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
 	struct msm_camera_sensor_info *sinfo =
 		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
-
 	v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
 		VIDIOC_MSM_SENSOR_RELEASE, NULL);
 
@@ -590,6 +606,7 @@
 	}
 
 	if (p_mctl->axi_sdev) {
+		v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
 		v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
 			VIDIOC_MSM_AXI_RELEASE, NULL);
 	}
@@ -899,6 +916,7 @@
 	pcam->mctl_node.dev_inst[pcam_inst->my_index] = NULL;
 	msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
 	CLR_MCTLPP_INST_IDX(pcam_inst->inst_handle);
+	CLR_DEVID_MODE(pcam_inst->inst_handle);
 	CLR_IMG_MODE(pcam_inst->inst_handle);
 	mutex_unlock(&pcam_inst->inst_lock);
 	mutex_destroy(&pcam_inst->inst_lock);
@@ -1163,7 +1181,7 @@
 static int msm_mctl_v4l2_dqbuf(struct file *f, void *pctx,
 					struct v4l2_buffer *pb)
 {
-	int rc = 0;
+	int rc = 0, i;
 	/* get the camera device */
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
@@ -1180,6 +1198,26 @@
 	rc = vb2_dqbuf(&pcam_inst->vid_bufq, pb,  f->f_flags & O_NONBLOCK);
 	D("%s, videobuf_dqbuf returns %d\n", __func__, rc);
 
+	if (pb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		/* Reject the buffer if planes array was not allocated */
+		if (pb->m.planes == NULL) {
+			pr_err("%s Planes array is null\n", __func__);
+			mutex_unlock(&pcam_inst->inst_lock);
+			return -EINVAL;
+		}
+		for (i = 0; i < pcam_inst->plane_info.num_planes; i++) {
+			pb->m.planes[i].data_offset =
+				pcam_inst->buf_offset[pb->index][i].data_offset;
+			pb->m.planes[i].reserved[0] =
+				pcam_inst->buf_offset[pb->index][i].addr_offset;
+			D("%s update offsets for plane %d as A %d D %d\n",
+				__func__, i, pb->m.planes[i].reserved[0],
+				pb->m.planes[i].data_offset);
+		}
+	} else {
+		pb->reserved = pcam_inst->buf_offset[pb->index][0].addr_offset;
+		D("%s stored reserved info %d\n", __func__, pb->reserved);
+	}
 	mutex_unlock(&pcam_inst->inst_lock);
 	return rc;
 }
@@ -1457,18 +1495,30 @@
 				struct v4l2_streamparm *a)
 {
 	int rc = 0;
+	int is_bayer_sensor = 0;
+	struct msm_cam_media_controller *pmctl = NULL;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 	pcam_inst->image_mode = (a->parm.capture.extendedmode & 0x7F);
+
+	pmctl = msm_cam_server_get_mctl(pcam_inst->pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s: invalid mctl controller", __func__);
+		return -EINVAL;
+	}
+	/* save msm_dev node idx for subdev notify lookup */
+	SET_DEVID_MODE(pcam_inst->inst_handle, pmctl->pcam_ptr->vnode_id);
 	SET_IMG_MODE(pcam_inst->inst_handle, pcam_inst->image_mode);
 	SET_MCTLPP_INST_IDX(pcam_inst->inst_handle, pcam_inst->my_index);
 	pcam_inst->pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] =
 		pcam_inst;
 	pcam_inst->path = msm_mctl_vidbuf_get_path(pcam_inst->image_mode);
-
+	if (pcam_inst->pcam->sdata->sensor_type == BAYER_SENSOR)
+		is_bayer_sensor = 1;
 	rc = msm_cam_server_config_interface_map(pcam_inst->image_mode,
-			pcam_inst->pcam->mctl_handle);
+			pcam_inst->pcam->mctl_handle,
+			pcam_inst->pcam->vnode_id, is_bayer_sensor);
 	D("%s path=%d, image mode = %d rc=%d\n", __func__,
 		pcam_inst->path, pcam_inst->image_mode, rc);
 	return rc;
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index b2cddb0..a114b37 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -103,6 +103,10 @@
 		if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_T)
 			*pp_type = OUTPUT_TYPE_T;
 		break;
+	case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
+		if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_R)
+			*pp_type = OUTPUT_TYPE_R;
+		break;
 	default:
 		break;
 	}
@@ -405,8 +409,8 @@
 			ERR_COPY_FROM_USER();
 			return -EFAULT;
 		}
-		D("%s: PP_PATH, path=%d",
-			__func__, divert_pp.path);
+		D("%s: Divert Image mode =%d Enable %d",
+			__func__, divert_pp.path, divert_pp.enable);
 		spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
 		if (divert_pp.enable)
 			p_mctl->pp_info.pp_ctrl.pp_msg_type |= divert_pp.path;
diff --git a/drivers/media/video/msm/sensors/imx091.h b/drivers/media/video/msm/sensors/imx091.h
index 862b43a..3618b4c 100644
--- a/drivers/media/video/msm/sensors/imx091.h
+++ b/drivers/media/video/msm/sensors/imx091.h
@@ -42,7 +42,8 @@
 	{REQUEST_VREG, 0},
 	{ENABLE_VREG, 0},
 	{ENABLE_GPIO, 0},
-	{CONFIG_CLK, 0},
+	{CONFIG_CLK, 1},
+	{CONFIG_I2C_MUX, 0},
 };
 
 static const struct i2c_device_id imx091_i2c_id[] = {
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 8fbcc01..999783e 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -86,7 +86,10 @@
 			output_settings[s_ctrl->curr_res].vt_pixel_clk /
 			s_ctrl->curr_frame_length_lines /
 			s_ctrl->curr_line_length_pclk;
-		delay = (1000 * s_ctrl->wait_num_frames) / fps / Q10;
+		if (fps == 0)
+			delay = s_ctrl->min_delay;
+		else
+			delay = (1000 * s_ctrl->wait_num_frames) / fps / Q10;
 	}
 	CDBG("%s fps = %ld, delay = %d, min_delay %d\n", __func__, fps,
 		delay, s_ctrl->min_delay);
@@ -399,6 +402,7 @@
 			csi_lane_assign;
 		sensor_output_info->csi_lane_mask = csi_lane_params->
 			csi_lane_mask;
+		sensor_output_info->csi_phy_sel = csi_lane_params->csi_phy_sel;
 	}
 	sensor_output_info->csi_if = s_ctrl->sensordata->csi_if;
 	for (index = 0; index < sensor_output_info->csi_if; index++)
@@ -1174,6 +1178,14 @@
 	}
 	pinfo->csi_lane_params->csi_lane_mask = val;
 
+	rc = of_property_read_u32(of_node, "qcom,csi-phy-sel", &val);
+	CDBG("%s qcom,csi-phy-sel %x, rc %d\n", __func__, val, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR3;
+	}
+	pinfo->csi_lane_params->csi_phy_sel = val;
+
 	kfree(val_array);
 	return rc;
 ERROR3:
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index 1423063..bc38f62 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.c
@@ -700,9 +700,15 @@
 	int_time[0] = line >> 12;
 	int_time[1] = line >> 4;
 	int_time[2] = line << 4;
-	msm_camera_i2c_write_seq(s_ctrl->sensor_i2c_client,
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr-1,
-		&int_time[0], 3);
+		int_time[0], MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
+		int_time[1], MSM_CAMERA_I2C_BYTE_DATA);
+	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+		s_ctrl->sensor_exp_gain_info->coarse_int_time_addr+1,
+		int_time[2], MSM_CAMERA_I2C_BYTE_DATA);
 	msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
 		s_ctrl->sensor_exp_gain_info->global_gain_addr, gain,
 		MSM_CAMERA_I2C_WORD_DATA);
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index 79aa7aa..f6cf427 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -23,6 +23,8 @@
 
 static struct msm_camera_i2c_reg_conf ov5647_start_settings[] = {
 	{0x4202, 0x00},  /* streaming on */
+	{0x0100, 0x01},
+	{0x4800, 0x04},
 };
 
 static struct msm_camera_i2c_reg_conf ov5647_stop_settings[] = {
@@ -159,7 +161,7 @@
 
 static struct msm_camera_i2c_reg_conf ov5647_zsl_settings[] = {
 	{0x3035, 0x21},
-	{0x3036, 0x2f},
+	{0x3036, 0x4f},
 	{0x3821, 0x06},
 	{0x3820, 0x00},
 	{0x3612, 0x0b},
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index fda59db..6a2372e 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -481,7 +481,7 @@
 		.line_length_pclk = 5336,
 		.frame_length_lines = 3052,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 30 fps preview */
@@ -491,7 +491,7 @@
 		.line_length_pclk = 4480,
 		.frame_length_lines = 2412,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 60 fps video */
@@ -501,7 +501,7 @@
 		.line_length_pclk = 5336,
 		.frame_length_lines = 992,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 90 fps video */
@@ -511,7 +511,7 @@
 		.line_length_pclk = 5336,
 		.frame_length_lines = 664,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 120 fps video */
@@ -521,7 +521,7 @@
 		.line_length_pclk = 5336,
 		.frame_length_lines = 514,
 		.vt_pixel_clk = 330000000,
-		.op_pixel_clk = 320000000,
+		.op_pixel_clk = 264000000,
 		.binning_factor = 1,
 	},
 	/* 24 fps snapshot */
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index db83621..b78e20d 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -109,13 +109,20 @@
 	v4l2_fh_exit(eventHandle);
 }
 
-int msm_cam_server_config_interface_map(u32 extendedmode, uint32_t mctl_handle)
+int msm_cam_server_config_interface_map(u32 extendedmode,
+	uint32_t mctl_handle, int vnode_id, int is_bayer_sensor)
 {
 	int i = 0;
 	int rc = 0;
 	int old_handle;
 	int interface;
 
+	if (vnode_id >= MAX_NUM_ACTIVE_CAMERA) {
+		pr_err("%s: invalid msm_dev node id = %d", __func__, vnode_id);
+		return -EINVAL;
+	}
+	D("%s: extendedmode = %d, vnode_id = %d, is_bayer_sensor = %d",
+		__func__, extendedmode, vnode_id, is_bayer_sensor);
 	switch (extendedmode) {
 	case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
 		interface = RDI_0;
@@ -130,18 +137,50 @@
 		interface = PIX_0;
 		break;
 	}
+
 	for (i = 0; i < INTF_MAX; i++) {
 		if (g_server_dev.interface_map_table[i].interface ==
 							interface) {
+			if (is_bayer_sensor && interface == PIX_0) {
+				if (g_server_dev.
+					interface_map_table[i].mctl_handle &&
+					!g_server_dev.interface_map_table[i].
+						is_bayer_sensor) {
+					/* in simultaneous camera usecase
+					 * SoC does not use PIX interface */
+					g_server_dev.interface_map_table[i].
+						mctl_handle = 0;
+				}
+			}
 			old_handle =
 				g_server_dev.interface_map_table[i].mctl_handle;
 			if (old_handle == 0) {
 				g_server_dev.interface_map_table[i].mctl_handle
 					= mctl_handle;
-			} else if (old_handle != mctl_handle) {
-				pr_err("%s: interface_map[%d] was set: %d\n",
-					__func__, i, old_handle);
-				rc = -EINVAL;
+				g_server_dev.interface_map_table[i].
+					is_bayer_sensor = is_bayer_sensor;
+				g_server_dev.interface_map_table[i].vnode_id
+					= vnode_id;
+			} else {
+				if (!g_server_dev.interface_map_table[i].
+					is_bayer_sensor &&
+					(extendedmode ==
+					MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW ||
+					extendedmode ==
+					MSM_V4L2_EXT_CAPTURE_MODE_VIDEO ||
+					extendedmode ==
+					MSM_V4L2_EXT_CAPTURE_MODE_MAIN ||
+					extendedmode ==
+					MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL)) {
+					D("%s: SoC sensor, image_mode = %d",
+					__func__, extendedmode);
+					break;
+				}
+				if (old_handle != mctl_handle) {
+					pr_err("%s: iface_map[%d] is set: %d\n",
+						__func__, i, old_handle);
+					rc = -EINVAL;
+				}
 			}
 			break;
 		}
@@ -156,9 +195,10 @@
 {
 	int i;
 	for (i = 0; i < INTF_MAX; i++)
-		if (g_server_dev.interface_map_table[i].mctl_handle ==
-								mctl_handle)
-			g_server_dev.interface_map_table[i].mctl_handle = 0;
+		if (g_server_dev.interface_map_table[i].
+			mctl_handle == mctl_handle)
+			g_server_dev.interface_map_table[i].
+				mctl_handle = 0;
 }
 
 struct iommu_domain *msm_cam_server_get_domain()
@@ -181,7 +221,7 @@
 			g_server_dev.mctl[i].handle =
 				(++g_server_dev.mctl_handle_cnt) << 8 | i;
 			memset(&g_server_dev.mctl[i].mctl,
-				   0, sizeof(g_server_dev.mctl[i].mctl));
+				0, sizeof(g_server_dev.mctl[i].mctl));
 			return g_server_dev.mctl[i].handle;
 		}
 	}
@@ -245,7 +285,7 @@
 	if (copy_from_user(command, (void __user *)ioctl_ptr->ioctl_ptr,
 					   sizeof(struct msm_ctrl_cmd))) {
 		pr_err("%s: copy_from_user failed, size=%d\n",
-			   __func__, sizeof(struct msm_ctrl_cmd));
+			__func__, sizeof(struct msm_ctrl_cmd));
 		goto ctrl_cmd_done_error;
 	}
 
@@ -302,6 +342,7 @@
 				uint32_t id, struct msm_ctrl_cmd *out)
 {
 	int rc = 0;
+	uint8_t wait_count;
 	void *value;
 	struct msm_queue_cmd *rcmd;
 	struct msm_queue_cmd *event_qcmd;
@@ -369,9 +410,20 @@
 
 	/* wait for config return status */
 	D("Waiting for config status\n");
-	rc = wait_event_interruptible_timeout(queue->wait,
-		!list_empty_careful(&queue->list),
-		msecs_to_jiffies(out->timeout_ms));
+	/* wait event may be interrupted by sugnal,
+	 * in this case -ERESTARTSYS is returned and retry is needed.
+	 * Now we only retry once. */
+	wait_count = 2;
+	do {
+		rc = wait_event_interruptible_timeout(queue->wait,
+			!list_empty_careful(&queue->list),
+			msecs_to_jiffies(out->timeout_ms));
+		wait_count--;
+		if (rc != -ERESTARTSYS)
+			break;
+		D("%s: wait_event interrupted by signal, remain_count = %d",
+			__func__, wait_count);
+	} while (wait_count > 0);
 	D("Waiting is over for config status\n");
 	if (list_empty_careful(&queue->list)) {
 		if (!rc)
@@ -1028,6 +1080,7 @@
 	}
 	/* book keeping this camera session*/
 	ps->pcam_active[pcam->server_queue_idx] = pcam;
+	ps->opened_pcam[pcam->vnode_id] = pcam;
 	atomic_inc(&ps->number_pcam_active);
 
 	D("config pcam = 0x%p\n", pcam);
@@ -1053,7 +1106,7 @@
 
 	atomic_dec(&ps->number_pcam_active);
 	ps->pcam_active[pcam->server_queue_idx] = NULL;
-
+	ps->opened_pcam[pcam->vnode_id] = NULL;
 	for (i = 0; i < INTF_MAX; i++) {
 		if (ps->interface_map_table[i].mctl_handle ==
 			pcam->mctl_handle)
@@ -1562,7 +1615,6 @@
 {
 	int i;
 	uint32_t interface;
-
 	switch (notification) {
 	case NOTIFY_ISP_MSG_EVT:
 		if (((struct isp_msg_event *)arg)->msg_id ==
@@ -1587,14 +1639,32 @@
 	case NOTIFY_VFE_BUF_EVT: {
 		struct msm_vfe_resp *rp;
 		struct msm_frame_info *frame_info;
+		uint8_t vnode_id;
+
 		rp = (struct msm_vfe_resp *)arg;
 		frame_info = rp->evt_msg.data;
-		if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY1)
-			interface = RDI_0;
-		else if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY2)
-			interface = RDI_1;
-		else
+		if (!frame_info) {
 			interface = PIX_0;
+			break;
+		}
+		if (frame_info->inst_handle) {
+			vnode_id = GET_DEVID_MODE(frame_info->inst_handle);
+			if (vnode_id < MAX_NUM_ACTIVE_CAMERA &&
+				g_server_dev.opened_pcam[vnode_id]) {
+				return g_server_dev.
+					opened_pcam[vnode_id]->mctl_handle;
+			} else {
+				pr_err("%s: cannot find mctl handle", __func__);
+				return 0;
+			}
+		} else {
+			if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY1)
+				interface = RDI_0;
+			else if (frame_info->path == VFE_MSG_OUTPUT_TERTIARY2)
+				interface = RDI_1;
+			else
+				interface = PIX_0;
+		}
 		}
 		break;
 	case NOTIFY_AXI_RDI_SOF_COUNT: {
@@ -1609,7 +1679,6 @@
 		interface = PIX_0;
 		break;
 	}
-
 	for (i = 0; i < INTF_MAX; i++) {
 		if (interface == g_server_dev.interface_map_table[i].interface)
 			break;
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index d38bb98..5e39d25 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -69,5 +69,5 @@
 int msm_cam_server_update_irqmap(
 	struct msm_cam_server_irqmap_entry *entry);
 int msm_cam_server_config_interface_map(u32 extendedmode,
-	uint32_t mctl_handle);
+	uint32_t mctl_handle, int vnode_id, int is_bayer_sensor);
 #endif /* _MSM_CAM_SERVER_H */
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index 2a9c186..6e22388 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -412,28 +412,166 @@
 	}
 }
 
+static void axi_enable_wm_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
+	uint32_t irq_mask, irq_comp_mask = 0;
+	uint16_t vfe_output_mode =
+		share_ctrl->outpath.output_mode &
+			~(VFE32_OUTPUT_MODE_TERTIARY1|
+			VFE32_OUTPUT_MODE_TERTIARY2);
+
+	if (vfe_output_mode)
+		irq_comp_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_COMP_MASK);
+	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_0);
+
+	if (share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
+		if (share_ctrl->current_mode == VFE_OUTPUTS_RAW)
+			irq_comp_mask |= (
+				0x1 << share_ctrl->outpath.out0.ch0);
+		else
+			irq_comp_mask |= (
+				0x1 << share_ctrl->outpath.out0.ch0 |
+				0x1 << share_ctrl->outpath.out0.ch1);
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	} else if (share_ctrl->outpath.output_mode &
+			   VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+		irq_comp_mask |= (
+			0x1 << share_ctrl->outpath.out0.ch0 |
+			0x1 << share_ctrl->outpath.out0.ch1 |
+			0x1 << share_ctrl->outpath.out0.ch2);
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	}
+	if (share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask |= (
+			0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch1 + 8));
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	} else if (share_ctrl->outpath.output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+		irq_comp_mask |= (
+			0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch1 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch2 + 8));
+		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	}
+
+	if (share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY1) {
+		irq_mask |= (0x1 << (share_ctrl->outpath.out2.ch0 +
+			VFE_WM_OFFSET));
+	}
+
+	if (share_ctrl->outpath.output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY2) {
+		irq_mask |= (0x1 << (share_ctrl->outpath.out3.ch0 +
+			VFE_WM_OFFSET));
+	}
+
+	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+			VFE_IRQ_MASK_0);
+	if (vfe_output_mode)
+		msm_camera_io_w(irq_comp_mask,
+			share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+}
+
+static void axi_disable_wm_irq(struct vfe_share_ctrl_t *share_ctrl,
+	uint16_t output_mode)
+{
+	uint32_t irq_mask, irq_comp_mask = 0;
+	uint16_t vfe_output_mode =
+		output_mode &
+			~(VFE32_OUTPUT_MODE_TERTIARY1|
+			VFE32_OUTPUT_MODE_TERTIARY2);
+	if (vfe_output_mode)
+		irq_comp_mask =
+		msm_camera_io_r(share_ctrl->vfebase +
+			VFE_IRQ_COMP_MASK);
+	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_0);
+
+	if (output_mode &
+			VFE32_OUTPUT_MODE_PRIMARY) {
+		irq_comp_mask &= ~(
+			0x1 << share_ctrl->outpath.out0.ch0 |
+			0x1 << share_ctrl->outpath.out0.ch1);
+		irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	} else if (output_mode &
+			   VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+		irq_comp_mask &= ~(
+			0x1 << share_ctrl->outpath.out0.ch0 |
+			0x1 << share_ctrl->outpath.out0.ch1 |
+			0x1 << share_ctrl->outpath.out0.ch2);
+		irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+	}
+	if (output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY) {
+		irq_comp_mask &= ~(
+			0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch1 + 8));
+		irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	} else if (output_mode &
+			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+		irq_comp_mask &= ~(
+			0x1 << (share_ctrl->outpath.out1.ch0 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch1 + 8) |
+			0x1 << (share_ctrl->outpath.out1.ch2 + 8));
+		irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+	}
+	if (output_mode &
+			VFE32_OUTPUT_MODE_TERTIARY1) {
+			irq_mask &= ~(0x1 << (share_ctrl->outpath.out2.ch0 +
+				VFE_WM_OFFSET));
+	}
+	if (output_mode &
+		VFE32_OUTPUT_MODE_TERTIARY2) {
+		irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
+			VFE_WM_OFFSET));
+	}
+	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+				VFE_IRQ_MASK_0);
+	if (vfe_output_mode)
+		msm_camera_io_w(irq_comp_mask,
+			share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+}
+
 static void axi_enable_irq(struct vfe_share_ctrl_t *share_ctrl)
 {
 	uint32_t irq_mask, irq_mask1;
-	uint16_t vfe_operation_mode =
+	uint32_t vfe_mode =
 		share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
 			VFE_OUTPUTS_RDI1);
-	irq_mask1 =
-		msm_camera_io_r(share_ctrl->vfebase +
+
+	if (share_ctrl->axi_ref_cnt == 1) {
+		irq_mask1 =
+			msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_1);
+
+		irq_mask1 |= VFE_IMASK_WHILE_STOPPING_1;
+			msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
+				VFE_IRQ_MASK_1);
+	}
+
+	if (share_ctrl->current_mode & (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1)) {
+		irq_mask1 =
+			msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_1);
+
+		if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+			irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
+
+		if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+			irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+
+		msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
 			VFE_IRQ_MASK_1);
+	}
 
-	irq_mask1 |= VFE_IMASK_WHILE_STOPPING_1;
-
-	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
-		irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
-
-	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
-		irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
-
-	msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
-		VFE_IRQ_MASK_1);
-
-	if (vfe_operation_mode) {
+	if (vfe_mode) {
 		irq_mask =
 		msm_camera_io_r(share_ctrl->vfebase +
 			VFE_IRQ_MASK_0);
@@ -449,37 +587,39 @@
 	atomic_set(&share_ctrl->handle_common_irq, 1);
 }
 
-static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl)
+static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl,
+	uint32_t mode)
 {
 
 	/* disable all interrupts.  */
 
-	uint32_t irq_mask, irq_mask1;
-	uint16_t vfe_operation_mode =
-		share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
-			VFE_OUTPUTS_RDI1);
+	uint32_t irq_mask = 0, irq_mask1 = 0, clear_mask1 = 0;
+	uint32_t vfe_mode =
+		(mode & ~(VFE_OUTPUTS_RDI0|
+			VFE_OUTPUTS_RDI1));
 
-	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+	if (mode & (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1)) {
 		irq_mask1 =
-		msm_camera_io_r(share_ctrl->vfebase +
-			VFE_IRQ_MASK_1);
-		irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK);
+			msm_camera_io_r(share_ctrl->vfebase +
+				VFE_IRQ_MASK_1);
+
+		if (mode & VFE_OUTPUTS_RDI0) {
+			irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK);
+			clear_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
+		}
+
+		if (mode & VFE_OUTPUTS_RDI1) {
+			irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK);
+			clear_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+		}
+
 		msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
 			VFE_IRQ_MASK_1);
-		msm_camera_io_w(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK,
+		msm_camera_io_w(clear_mask1,
 			share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
 	}
-	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
-		irq_mask1 =
-		msm_camera_io_r(share_ctrl->vfebase +
-			VFE_IRQ_MASK_1);
-		irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK);
-		msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
-			VFE_IRQ_MASK_1);
-		msm_camera_io_w(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK,
-			share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
-	}
-	if (vfe_operation_mode) {
+
+	if (vfe_mode) {
 		atomic_set(&share_ctrl->vstate, 0);
 		irq_mask =
 		msm_camera_io_r(share_ctrl->vfebase +
@@ -492,7 +632,7 @@
 		msm_camera_io_w(irq_mask, share_ctrl->vfebase +
 			VFE_IRQ_MASK_0);
 	}
-
+	/*Dont Disable for concurrent*/
 	if (share_ctrl->axi_ref_cnt == 1) {
 		atomic_set(&share_ctrl->handle_common_irq, 0);
 		msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
@@ -517,11 +657,14 @@
 
 	/* in either continuous or snapshot mode, stop command can be issued
 	 * at any time. stop camif immediately. */
-	msm_camera_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
-		vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+	if (!vfe32_ctrl->share_ctrl->dual_enabled)
+		msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+	else
+		msm_camera_io_w(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+			vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
 	vfe32_ctrl->share_ctrl->operation_mode &=
-		~(vfe32_ctrl->share_ctrl->current_mode);
-	vfe32_ctrl->share_ctrl->current_mode = 0;
+		(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
 }
 
 static void vfe32_subdev_notify(int id, int path, uint32_t inst_handle,
@@ -630,8 +773,6 @@
 		V32_AXI_BUS_CFG_LEN);
 	axi_cfg += V32_AXI_BUS_CFG_LEN/4;
 	for (i = 0; i < ARRAY_SIZE(vfe32_AXI_WM_CFG); i++) {
-		msm_camera_io_w(*axi_cfg,
-			axi_ctrl->share_ctrl->vfebase+vfe32_AXI_WM_CFG[i]);
 		axi_cfg += 3;
 		msm_camera_io_memcpy(
 			axi_ctrl->share_ctrl->vfebase+vfe32_AXI_WM_CFG[i]+12,
@@ -654,6 +795,33 @@
 }
 
 static void axi_reset_internal_variables(
+	struct axi_ctrl_t *axi_ctrl,
+	struct msm_camera_vfe_params_t vfe_params)
+{
+	if (vfe_params.operation_mode & VFE_OUTPUTS_RDI0) {
+		atomic_set(&axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+		axi_ctrl->share_ctrl->rdi0_capture_count = -1;
+		axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+		axi_ctrl->share_ctrl->rdi0FrameId = 0;
+		axi_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY1;
+		axi_ctrl->share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI0);
+	}
+
+	if (vfe_params.operation_mode & VFE_OUTPUTS_RDI1) {
+		atomic_set(&axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+		axi_ctrl->share_ctrl->rdi1_capture_count = -1;
+		axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+		axi_ctrl->share_ctrl->rdi1FrameId = 0;
+		axi_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY2;
+		axi_ctrl->share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI1);
+	}
+}
+
+static void axi_global_reset_internal_variables(
 	struct axi_ctrl_t *axi_ctrl)
 {
 	unsigned long flags;
@@ -687,6 +855,12 @@
 	axi_ctrl->share_ctrl->outpath.output_mode = 0;
 	axi_ctrl->share_ctrl->comp_output_mode = 0;
 	axi_ctrl->share_ctrl->vfe_capture_count = 0;
+	axi_ctrl->share_ctrl->rdi0_capture_count = -1;
+	axi_ctrl->share_ctrl->rdi1_capture_count = -1;
+	axi_ctrl->share_ctrl->outpath.out0.capture_cnt = -1;
+	axi_ctrl->share_ctrl->outpath.out1.capture_cnt = -1;
+	axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+	axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
 
 	/* this is unsigned 32 bit integer. */
 	axi_ctrl->share_ctrl->vfeFrameId = 0;
@@ -695,6 +869,7 @@
 	axi_ctrl->share_ctrl->rdi2FrameId = 0;
 }
 
+
 static void vfe32_program_dmi_cfg(
 	enum VFE32_DMI_RAM_SEL bankSel,
 	struct vfe32_ctrl_type *vfe32_ctrl)
@@ -833,6 +1008,17 @@
 static void vfe32_reset_internal_variables(
 	struct vfe32_ctrl_type *vfe32_ctrl)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&vfe32_ctrl->share_ctrl->update_ack_lock,
+		flags);
+	vfe32_ctrl->share_ctrl->update_ack_pending = FALSE;
+	spin_unlock_irqrestore(&vfe32_ctrl->share_ctrl->update_ack_lock,
+		flags);
+	vfe32_ctrl->share_ctrl->vfe_capture_count = 0;
+	/* this is unsigned 32 bit integer. */
+	vfe32_ctrl->share_ctrl->vfeFrameId = 0;
+	vfe32_ctrl->share_ctrl->update_counter = 0;
+
 	/* Stats control variables. */
 	memset(&(vfe32_ctrl->afbfStatsControl), 0,
 		sizeof(struct vfe_stats_control));
@@ -854,6 +1040,13 @@
 
 	memset(&(vfe32_ctrl->csStatsControl), 0,
 		sizeof(struct vfe_stats_control));
+	vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt = -1;
+	vfe32_ctrl->share_ctrl->outpath.out1.capture_cnt = -1;
+	vfe32_ctrl->share_ctrl->recording_state = VFE_STATE_IDLE;
+	vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
+
+	atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
+	atomic_set(&vfe32_ctrl->share_ctrl->pix0_update_ack_pending, 0);
 
 	vfe32_ctrl->frame_skip_cnt = 31;
 	vfe32_ctrl->frame_skip_pattern = 0xffffffff;
@@ -878,6 +1071,11 @@
 
 	msm_camera_io_w(irq_mask, vfe32_ctrl->share_ctrl->vfebase +
 		VFE_IRQ_MASK_0);
+	vfe32_ctrl->share_ctrl->operation_mode &=
+		(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
+	vfe32_ctrl->share_ctrl->comp_output_mode &=
+			(VFE32_OUTPUT_MODE_TERTIARY1|
+			VFE32_OUTPUT_MODE_TERTIARY2);
 
 	/* enable reset_ack interrupt.  */
 	irq_mask1 = msm_camera_io_r(
@@ -892,9 +1090,15 @@
 			&vfe32_ctrl->share_ctrl->reset_complete);
 }
 
-static int axi_reset(struct axi_ctrl_t *axi_ctrl)
+static int axi_reset(struct axi_ctrl_t *axi_ctrl,
+	struct msm_camera_vfe_params_t vfe_params)
 {
-	axi_reset_internal_variables(axi_ctrl);
+	int rc = 0;
+	if (vfe_params.skip_reset) {
+		axi_reset_internal_variables(axi_ctrl, vfe_params);
+		return rc;
+	}
+	axi_global_reset_internal_variables(axi_ctrl);
 	/* disable all interrupts.  vfeImaskLocal is also reset to 0
 	* to begin with. */
 	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
@@ -1256,17 +1460,11 @@
 
 static void vfe32_start_common(struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	uint16_t vfe_operation_mode =
-		vfe32_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
-			VFE_OUTPUTS_RDI1);
 	CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
-		vfe32_ctrl->share_ctrl->current_mode,
+		vfe32_ctrl->share_ctrl->operation_mode,
 		vfe32_ctrl->share_ctrl->outpath.output_mode);
-
-	if (vfe_operation_mode) {
 		msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
 			VFE_CAMIF_COMMAND);
-	}
 }
 
 static int vfe32_start_recording(
@@ -2792,8 +2990,6 @@
 				goto proc_general_done;
 		}
 
-		vfe32_ctrl->share_ctrl->current_mode =
-			vfe_params.operation_mode;
 		vfe32_stop(vfe32_ctrl);
 		break;
 
@@ -3168,23 +3364,17 @@
 
 }
 
-void axi_stop_pix(struct vfe_share_ctrl_t *share_ctrl)
+void axi_stop_pix(struct vfe_share_ctrl_t *share_ctrl,
+	uint32_t vfe_mode, uint8_t cmd_type)
 {
-	uint32_t operation_mode =
-	share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
-		VFE_OUTPUTS_RDI1);
-	uint32_t irq_comp_mask, irq_mask;
 	uint32_t reg_update = 0x1;
-
-	irq_comp_mask =
-		msm_camera_io_r(share_ctrl->vfebase +
-			VFE_IRQ_COMP_MASK);
-	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-
-	switch (share_ctrl->cmd_type) {
+	switch (cmd_type) {
+	case AXI_CMD_RAW_CAPTURE:
+		msm_camera_io_w(0, share_ctrl->vfebase
+			+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out0.ch0]);
+		break;
 	case AXI_CMD_PREVIEW: {
-		switch (operation_mode) {
+		switch (vfe_mode) {
 		case VFE_OUTPUTS_PREVIEW:
 		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
 			if (share_ctrl->comp_output_mode &
@@ -3195,11 +3385,6 @@
 				msm_camera_io_w(0, share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[share_ctrl->
 					outpath.out0.ch1]);
-				irq_comp_mask &= ~(
-					0x1 << share_ctrl->outpath.out0.ch0 |
-					0x1 << share_ctrl->outpath.out0.ch1);
-				share_ctrl->outpath.output_mode |=
-					VFE32_OUTPUT_MODE_PRIMARY;
 			} else if (share_ctrl->comp_output_mode &
 					VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
 				msm_camera_io_w(0, share_ctrl->vfebase
@@ -3211,14 +3396,7 @@
 				msm_camera_io_w(0, share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[share_ctrl->
 					outpath.out0.ch2]);
-				irq_comp_mask &= ~(
-					0x1 << share_ctrl->outpath.out0.ch0 |
-					0x1 << share_ctrl->outpath.out0.ch1 |
-					0x1 << share_ctrl->outpath.out0.ch2);
-				share_ctrl->outpath.output_mode |=
-					VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
 			}
-			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
 			break;
 		default:
 			if (share_ctrl->comp_output_mode &
@@ -3229,11 +3407,6 @@
 				msm_camera_io_w(0, share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[share_ctrl->
 					outpath.out1.ch1]);
-				irq_comp_mask &= ~(
-					0x1 << share_ctrl->outpath.out1.ch0 |
-					0x1 << share_ctrl->outpath.out1.ch1);
-				share_ctrl->outpath.output_mode |=
-					VFE32_OUTPUT_MODE_SECONDARY;
 			} else if (share_ctrl->comp_output_mode &
 				VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
 				msm_camera_io_w(0, share_ctrl->vfebase
@@ -3245,14 +3418,7 @@
 				msm_camera_io_w(0, share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[share_ctrl->
 					outpath.out1.ch2]);
-				irq_comp_mask &= ~(
-					0x1 << share_ctrl->outpath.out1.ch0 |
-					0x1 << share_ctrl->outpath.out1.ch1 |
-					0x1 << share_ctrl->outpath.out1.ch2);
-				share_ctrl->outpath.output_mode |=
-					VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
 			}
-			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
 			break;
 			}
 		}
@@ -3266,12 +3432,6 @@
 			msm_camera_io_w(0, share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[share_ctrl->
 				outpath.out0.ch1]);
-			irq_comp_mask &= ~(
-				0x1 << share_ctrl->outpath.out0.ch0 |
-				0x1 << share_ctrl->outpath.out0.ch1);
-			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
-			share_ctrl->outpath.output_mode |=
-					VFE32_OUTPUT_MODE_PRIMARY;
 		} else if (share_ctrl->comp_output_mode &
 				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
 			msm_camera_io_w(0, share_ctrl->vfebase +
@@ -3283,13 +3443,6 @@
 			msm_camera_io_w(0, share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[share_ctrl->
 				outpath.out0.ch2]);
-			irq_comp_mask &= ~(
-				0x1 << share_ctrl->outpath.out0.ch0 |
-				0x1 << share_ctrl->outpath.out0.ch1 |
-				0x1 << share_ctrl->outpath.out0.ch2);
-			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
-			share_ctrl->outpath.output_mode |=
-					VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
 		}
 
 		if (share_ctrl->comp_output_mode &
@@ -3299,12 +3452,6 @@
 				outpath.out1.ch0]);
 			msm_camera_io_w(0, share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
-			irq_comp_mask &= ~(
-				0x1 << share_ctrl->outpath.out1.ch0 |
-				0x1 << share_ctrl->outpath.out1.ch1);
-			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
-			share_ctrl->outpath.output_mode |=
-					VFE32_OUTPUT_MODE_SECONDARY;
 		} else if (share_ctrl->comp_output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
 			msm_camera_io_w(0, share_ctrl->vfebase +
@@ -3313,82 +3460,63 @@
 				vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
 			msm_camera_io_w(0, share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch2]);
-			irq_comp_mask &= ~(
-				0x1 << share_ctrl->outpath.out1.ch0 |
-				0x1 << share_ctrl->outpath.out1.ch1 |
-				0x1 << share_ctrl->outpath.out1.ch2);
-			irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
-			share_ctrl->outpath.output_mode |=
-					VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
 		}
 		break;
 	}
 
 	msm_camera_io_w_mb(reg_update,
 		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	msm_camera_io_w(irq_comp_mask,
-		share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
 }
 
 void axi_stop_rdi0(struct vfe_share_ctrl_t *share_ctrl)
 {
 	uint32_t reg_update = 0x2;
-	uint32_t irq_mask;
-	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-
-	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
-		msm_camera_io_w(0, share_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[share_ctrl->outpath.out2.ch0]);
-		irq_mask &= ~(0x1 << (share_ctrl->outpath.out2.ch0 +
-				VFE_WM_OFFSET));
-	}
+	msm_camera_io_w(0, share_ctrl->vfebase +
+		vfe32_AXI_WM_CFG[share_ctrl->outpath.out2.ch0]);
 	msm_camera_io_w_mb(reg_update,
 		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
 }
 
 void axi_stop_rdi1(struct vfe_share_ctrl_t *share_ctrl)
 {
 	uint32_t reg_update = 0x4;
-	uint32_t irq_mask;
-	irq_mask = msm_camera_io_r(share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-
-	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
-		msm_camera_io_w(1, share_ctrl->vfebase +
-			vfe32_AXI_WM_CFG[share_ctrl->outpath.out3.ch0]);
-		irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
-			VFE_WM_OFFSET));
-	}
-
+	msm_camera_io_w(0, share_ctrl->vfebase +
+		vfe32_AXI_WM_CFG[share_ctrl->outpath.out3.ch0]);
 	msm_camera_io_w_mb(reg_update,
 		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
-	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
 }
 
 void axi_stop_process(struct vfe_share_ctrl_t *share_ctrl)
 {
-	uint32_t operation_mode =
+	uint32_t vfe_mode =
 	share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
 		VFE_OUTPUTS_RDI1);
 
 	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
 		axi_stop_rdi0(share_ctrl);
+		axi_disable_wm_irq(share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY1);
 		share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY1;
+		share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI0);
 	}
 	if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
 		axi_stop_rdi1(share_ctrl);
+		axi_disable_wm_irq(share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY2);
 		share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY2;
+		share_ctrl->operation_mode &=
+			~(VFE_OUTPUTS_RDI1);
 	}
-	if (operation_mode) {
-		axi_stop_pix(share_ctrl);
+	if (vfe_mode) {
+		uint16_t mode = share_ctrl->comp_output_mode &
+			~(VFE32_OUTPUT_MODE_TERTIARY1|
+			VFE32_OUTPUT_MODE_TERTIARY2);
+		axi_stop_pix(share_ctrl, vfe_mode, share_ctrl->cmd_type);
+		axi_disable_wm_irq(share_ctrl, mode);
 		share_ctrl->comp_output_mode &=
-				~(share_ctrl->outpath.output_mode);
+				(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2);
 	}
 }
 
@@ -3397,25 +3525,47 @@
 {
 	unsigned long flags;
 	struct vfe_share_ctrl_t *share_ctrl = vfe32_ctrl->share_ctrl;
+	if (atomic_read(
+		&share_ctrl->pix0_update_ack_pending) == 2) {
+		uint32_t vfe_mode =
+				share_ctrl->operation_mode & ~(VFE_OUTPUTS_RDI0|
+					VFE_OUTPUTS_RDI1);
 
-	if (atomic_cmpxchg(
-		&share_ctrl->pix0_update_ack_pending, 2, 0) == 2) {
-		axi_stop_pix(share_ctrl);
-		msm_camera_io_w_mb(
-				CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
-				share_ctrl->vfebase + VFE_CAMIF_COMMAND);
-		axi_disable_irq(share_ctrl);
-		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			share_ctrl->vfeFrameId,
-			MSG_ID_PIX0_UPDATE_ACK);
-		share_ctrl->comp_output_mode &=
-				~(share_ctrl->outpath.output_mode);
-		share_ctrl->current_mode &=
-			(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
+		if (share_ctrl->dual_enabled && !share_ctrl->update_counter) {
+			axi_stop_pix(share_ctrl, vfe_mode,
+				share_ctrl->cmd_type);
+			share_ctrl->update_counter++;
+		} else {
+			uint16_t output_mode =
+				share_ctrl->comp_output_mode &
+				~(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2);
+			share_ctrl->update_counter = 0;
+			if (!share_ctrl->dual_enabled)
+				axi_stop_pix(share_ctrl, vfe_mode,
+					share_ctrl->cmd_type);
+			axi_disable_wm_irq(share_ctrl, output_mode);
+			axi_disable_irq(share_ctrl, vfe_mode);
+			atomic_set(&share_ctrl->pix0_update_ack_pending, 0);
+			msm_camera_io_w_mb(
+					CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+					share_ctrl->vfebase +
+					VFE_CAMIF_COMMAND);
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				share_ctrl->vfeFrameId,
+				MSG_ID_PIX0_UPDATE_ACK);
+			share_ctrl->comp_output_mode &=
+				(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2);
+		}
 	}  else {
 		if (share_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
 			if (share_ctrl->operation_mode &
 					VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+				msm_camera_io_w((
+					0x1 << share_ctrl->outpath.out0.ch0 |
+					0x1 << share_ctrl->outpath.out0.ch1),
+					share_ctrl->vfebase + VFE_BUS_CMD);
 				msm_camera_io_w(1,
 					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
 					share_ctrl->outpath.out0.ch0]);
@@ -3424,6 +3574,10 @@
 					share_ctrl->outpath.out0.ch1]);
 			} else if (share_ctrl->operation_mode &
 					VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+				msm_camera_io_w((
+					0x1 << share_ctrl->outpath.out1.ch0 |
+					0x1 << share_ctrl->outpath.out1.ch1),
+					share_ctrl->vfebase + VFE_BUS_CMD);
 				msm_camera_io_w(1,
 					share_ctrl->vfebase + vfe32_AXI_WM_CFG[
 					share_ctrl->outpath.out1.ch0]);
@@ -3465,8 +3619,6 @@
 					VFE32_OUTPUT_MODE_TERTIARY2));
 			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
 				share_ctrl->vfeFrameId, MSG_ID_PIX0_UPDATE_ACK);
-			share_ctrl->current_mode &=
-				(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
 		} else {
 			if (share_ctrl->recording_state ==
 						VFE_STATE_STOP_REQUESTED) {
@@ -3504,6 +3656,10 @@
 			CDBG("%s enabling liveshot output\n", __func__);
 			if (share_ctrl->comp_output_mode &
 						VFE32_OUTPUT_MODE_PRIMARY) {
+				msm_camera_io_w((
+					0x1 << share_ctrl->outpath.out0.ch0 |
+					0x1 << share_ctrl->outpath.out0.ch1),
+					share_ctrl->vfebase + VFE_BUS_CMD);
 				msm_camera_io_w(1, share_ctrl->vfebase +
 					vfe32_AXI_WM_CFG[
 					share_ctrl->outpath.out0.ch0]);
@@ -3572,32 +3728,12 @@
 				/* if last frame to be captured: */
 				if (share_ctrl->vfe_capture_count == 0) {
 					/* stop the bus output: */
-					if (share_ctrl->comp_output_mode
-						& VFE32_OUTPUT_MODE_PRIMARY) {
-						msm_camera_io_w(0,
-							share_ctrl->vfebase+
-							vfe32_AXI_WM_CFG[
-							share_ctrl->
-							outpath.out0.ch0]);
-						msm_camera_io_w(0,
-							share_ctrl->vfebase+
-							vfe32_AXI_WM_CFG[
-							share_ctrl->
-							outpath.out0.ch1]);
-					}
-					if (share_ctrl->comp_output_mode &
-						VFE32_OUTPUT_MODE_SECONDARY) {
-						msm_camera_io_w(0,
-							share_ctrl->vfebase+
-							vfe32_AXI_WM_CFG[
-							share_ctrl->
-							outpath.out1.ch0]);
-						msm_camera_io_w(0,
-							share_ctrl->vfebase+
-							vfe32_AXI_WM_CFG[
-							share_ctrl->
-							outpath.out1.ch1]);
-					}
+					uint32_t vfe_mode =
+						share_ctrl->operation_mode &
+							~(VFE_OUTPUTS_RDI0|
+							VFE_OUTPUTS_RDI1);
+					axi_stop_pix(share_ctrl, vfe_mode,
+						AXI_CMD_CAPTURE);
 					msm_camera_io_w_mb
 					(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
 					share_ctrl->vfebase +
@@ -3620,56 +3756,84 @@
 	struct vfe32_ctrl_type *vfe32_ctrl)
 {
 	if (atomic_cmpxchg(
-		&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 2, 0) == 2) {
-		axi_stop_rdi0(vfe32_ctrl->share_ctrl);
-		axi_disable_irq(vfe32_ctrl->share_ctrl);
-		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			vfe32_ctrl->share_ctrl->vfeFrameId,
-			MSG_ID_RDI0_UPDATE_ACK);
-		vfe32_ctrl->share_ctrl->comp_output_mode &=
-			~VFE32_OUTPUT_MODE_TERTIARY1;
-		vfe32_ctrl->share_ctrl->current_mode &=
-			~(VFE_OUTPUTS_RDI0);
-	}
-
-	if (atomic_cmpxchg(
 		&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 1, 0) == 1) {
 		vfe32_ctrl->share_ctrl->comp_output_mode |=
 			VFE32_OUTPUT_MODE_TERTIARY1;
 		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			vfe32_ctrl->share_ctrl->vfeFrameId,
+			vfe32_ctrl->share_ctrl->rdi0FrameId,
 			MSG_ID_RDI0_UPDATE_ACK);
-		vfe32_ctrl->share_ctrl->current_mode &=
+	}
+
+	if ((atomic_read(
+		&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending) == 2)
+		|| (vfe32_ctrl->share_ctrl->rdi0_capture_count == 0)) {
+		axi_disable_wm_irq(vfe32_ctrl->share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY1);
+		axi_disable_irq(vfe32_ctrl->share_ctrl, VFE_OUTPUTS_RDI0);
+		atomic_set(&vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->rdi0FrameId,
+			MSG_ID_RDI0_UPDATE_ACK);
+
+		if (vfe32_ctrl->share_ctrl->rdi0_capture_count == 0)
+			vfe32_ctrl->share_ctrl->rdi0_capture_count = -1;
+		if (vfe32_ctrl->share_ctrl->outpath.out2.capture_cnt
+			== 0)
+			vfe32_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+		vfe32_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY1;
+		vfe32_ctrl->share_ctrl->operation_mode &=
 			~(VFE_OUTPUTS_RDI0);
 	}
+
+	if (vfe32_ctrl->share_ctrl->rdi0_capture_count > 0) {
+		vfe32_ctrl->share_ctrl->rdi0_capture_count--;
+		if (!vfe32_ctrl->share_ctrl->rdi0_capture_count)
+			axi_stop_rdi0(vfe32_ctrl->share_ctrl);
+	}
 }
 
 static void vfe32_process_rdi1_reg_update_irq(
 	struct vfe32_ctrl_type *vfe32_ctrl)
 {
-	if (atomic_cmpxchg(
-		&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 2, 0) == 2) {
-		axi_stop_rdi1(vfe32_ctrl->share_ctrl);
-		axi_disable_irq(vfe32_ctrl->share_ctrl);
-		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			vfe32_ctrl->share_ctrl->vfeFrameId,
-			MSG_ID_RDI1_UPDATE_ACK);
-			vfe32_ctrl->share_ctrl->comp_output_mode &=
-				~VFE32_OUTPUT_MODE_TERTIARY2;
-		vfe32_ctrl->share_ctrl->current_mode &=
-			~(VFE_OUTPUTS_RDI1);
-	}
 
 	if (atomic_cmpxchg(
-		&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0) == 1) {
+		&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0)
+				== 1) {
 		vfe32_ctrl->share_ctrl->comp_output_mode |=
 			VFE32_OUTPUT_MODE_TERTIARY2;
 		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
-			vfe32_ctrl->share_ctrl->vfeFrameId,
+			vfe32_ctrl->share_ctrl->rdi1FrameId,
 			MSG_ID_RDI1_UPDATE_ACK);
-		vfe32_ctrl->share_ctrl->current_mode &=
+	}
+
+	if ((atomic_read(
+		&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending) == 2)
+		|| (vfe32_ctrl->share_ctrl->rdi1_capture_count == 0)) {
+		axi_disable_wm_irq(vfe32_ctrl->share_ctrl,
+			VFE32_OUTPUT_MODE_TERTIARY2);
+		axi_disable_irq(vfe32_ctrl->share_ctrl, VFE_OUTPUTS_RDI1);
+		atomic_set(&vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+		vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+			vfe32_ctrl->share_ctrl->rdi1FrameId,
+			MSG_ID_RDI1_UPDATE_ACK);
+
+		if (vfe32_ctrl->share_ctrl->rdi1_capture_count == 0)
+			vfe32_ctrl->share_ctrl->rdi1_capture_count = -1;
+		if (vfe32_ctrl->share_ctrl->outpath.out3.capture_cnt
+			== 0)
+			vfe32_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+		vfe32_ctrl->share_ctrl->comp_output_mode &=
+			~VFE32_OUTPUT_MODE_TERTIARY2;
+		vfe32_ctrl->share_ctrl->operation_mode &=
 			~(VFE_OUTPUTS_RDI1);
 	}
+
+	if (vfe32_ctrl->share_ctrl->rdi1_capture_count > 0) {
+		vfe32_ctrl->share_ctrl->rdi1_capture_count--;
+		if (!vfe32_ctrl->share_ctrl->rdi1_capture_count)
+			axi_stop_rdi1(vfe32_ctrl->share_ctrl);
+	}
 }
 
 static void vfe32_process_reset_irq(
@@ -3714,9 +3878,18 @@
 {
 	if (vfe32_ctrl->share_ctrl->operation_mode ==
 		VFE_OUTPUTS_RAW) {
-		if (vfe32_ctrl->share_ctrl->start_ack_pending) {
-			vfe32_ctrl->share_ctrl->start_ack_pending = FALSE;
+		if (atomic_cmpxchg(
+			&vfe32_ctrl->share_ctrl->pix0_update_ack_pending,
+					1, 0) == 1) {
+			vfe32_ctrl->share_ctrl->comp_output_mode |=
+				(vfe32_ctrl->share_ctrl->outpath.output_mode
+				& ~(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2));
+			vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+				vfe32_ctrl->share_ctrl->vfeFrameId,
+				MSG_ID_PIX0_UPDATE_ACK);
 		}
+
 		vfe32_ctrl->share_ctrl->vfe_capture_count--;
 		/* if last frame to be captured: */
 		if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
@@ -3881,7 +4054,6 @@
 	uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
 	uint8_t out_bool = 0;
 	struct msm_free_buf *free_buf = NULL;
-
 	free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
 		VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
 
@@ -4058,10 +4230,12 @@
 	/* this must be rdi image output. */
 	struct msm_free_buf *free_buf = NULL;
 	/*RDI0*/
+	CDBG("rdi0 out irq\n");
 	if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
 		free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
 			VFE_MSG_OUTPUT_TERTIARY1, axi_ctrl);
-		if (free_buf) {
+		if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt > 0 ||
+							free_buf) {
 			ping_pong = msm_camera_io_r(axi_ctrl->
 				share_ctrl->vfebase +
 				VFE_BUS_PING_PONG_STATUS);
@@ -4074,11 +4248,14 @@
 			pr_debug("%s ch0 = 0x%x\n",
 				__func__, ch0_paddr);
 
-			/* Y channel */
-			vfe32_put_ch_addr(ping_pong,
-				axi_ctrl->share_ctrl->vfebase,
-				axi_ctrl->share_ctrl->outpath.out2.ch0,
-				free_buf->ch_paddr[0]);
+			if (free_buf)
+				vfe32_put_ch_addr(ping_pong,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out2.ch0,
+					free_buf->ch_paddr[0]);
+			if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt == 1)
+				axi_ctrl->share_ctrl->
+					outpath.out2.capture_cnt = 0;
 
 			vfe_send_outmsg(axi_ctrl,
 				MSG_ID_OUTPUT_TERTIARY1, ch0_paddr,
@@ -4103,7 +4280,8 @@
 	if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1) {
 		free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
 			VFE_MSG_OUTPUT_TERTIARY2, axi_ctrl);
-		if (free_buf) {
+		if (axi_ctrl->share_ctrl->outpath.out3.capture_cnt > 0 ||
+							free_buf) {
 			ping_pong = msm_camera_io_r(axi_ctrl->
 				share_ctrl->vfebase +
 				VFE_BUS_PING_PONG_STATUS);
@@ -4115,11 +4293,15 @@
 			pr_debug("%s ch0 = 0x%x\n",
 				__func__, ch0_paddr);
 
-			/* Y channel */
-			vfe32_put_ch_addr(ping_pong,
-				axi_ctrl->share_ctrl->vfebase,
-				axi_ctrl->share_ctrl->outpath.out3.ch0,
-				free_buf->ch_paddr[0]);
+			if (free_buf)
+				vfe32_put_ch_addr(ping_pong,
+					axi_ctrl->share_ctrl->vfebase,
+					axi_ctrl->share_ctrl->outpath.out3.ch0,
+					free_buf->ch_paddr[0]);
+			if (axi_ctrl->share_ctrl->
+					outpath.out3.capture_cnt == 1)
+				axi_ctrl->share_ctrl->
+				outpath.out3.capture_cnt = 0;
 
 			vfe_send_outmsg(axi_ctrl,
 				MSG_ID_OUTPUT_TERTIARY2, ch0_paddr,
@@ -5209,6 +5391,9 @@
 	int round_rate;
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
 
+	if (axi_ctrl->share_ctrl->dual_enabled)
+		return rc;
+
 	round_rate = clk_round_rate(axi_ctrl->vfe_clk[0], freq);
 	if (rc < 0) {
 		pr_err("%s: clk_round_rate failed %d\n",
@@ -5233,21 +5418,22 @@
 	.core = &msm_vfe_subdev_core_ops,
 };
 
-int msm_axi_subdev_init(struct v4l2_subdev *sd)
+int msm_axi_subdev_init(struct v4l2_subdev *sd,
+	uint8_t dual_enabled)
 {
 	int rc = 0;
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
-	struct msm_cam_media_controller *mctl;
-	mctl = v4l2_get_subdev_hostdata(sd);
+	struct msm_cam_media_controller *mctl =
+		v4l2_get_subdev_hostdata(sd);
 	if (mctl == NULL) {
-		pr_err("%s: mctl is NULL\n", __func__);
 		rc = -EINVAL;
 		goto mctl_failed;
 	}
+
 	axi_ctrl->share_ctrl->axi_ref_cnt++;
 	if (axi_ctrl->share_ctrl->axi_ref_cnt > 1)
 		return rc;
-
+	axi_ctrl->share_ctrl->dual_enabled = dual_enabled;
 	spin_lock_init(&axi_ctrl->tasklet_lock);
 	INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
 	spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
@@ -5290,8 +5476,13 @@
 
 	msm_camio_bus_scale_cfg(
 		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
-	msm_camio_bus_scale_cfg(
-		mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+
+	if (axi_ctrl->share_ctrl->dual_enabled)
+		msm_camio_bus_scale_cfg(
+			mctl->sdata->pdata->cam_bus_scale_table, S_DUAL);
+	else
+		msm_camio_bus_scale_cfg(
+			mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 
 	if (msm_camera_io_r(
 		axi_ctrl->share_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
@@ -5351,18 +5542,19 @@
 
 void msm_axi_subdev_release(struct v4l2_subdev *sd)
 {
-	struct msm_cam_media_controller *pmctl =
-		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+	struct msm_cam_media_controller *pmctl =
+		v4l2_get_subdev_hostdata(sd);
+
 	if (!axi_ctrl->share_ctrl->vfebase) {
 		pr_err("%s: base address unmapped\n", __func__);
 		return;
 	}
 
-	CDBG("%s, free_irq\n", __func__);
 	axi_ctrl->share_ctrl->axi_ref_cnt--;
 	if (axi_ctrl->share_ctrl->axi_ref_cnt > 0)
 		return;
+	axi_ctrl->share_ctrl->dual_enabled = 0;
 	disable_irq(axi_ctrl->vfeirq->start);
 	tasklet_kill(&axi_ctrl->vfe32_tasklet);
 #ifdef CONFIG_MSM_IOMMU
@@ -5534,39 +5726,53 @@
 		}
 		break;
 	case AXI_CMD_CAPTURE:
-		if (axi_ctrl->share_ctrl->current_mode ==
-			VFE_OUTPUTS_JPEG_AND_THUMB ||
-		axi_ctrl->share_ctrl->current_mode ==
-			VFE_OUTPUTS_THUMB_AND_JPEG) {
+		if (vfe_mode) {
+			if (axi_ctrl->share_ctrl->current_mode ==
+				VFE_OUTPUTS_JPEG_AND_THUMB ||
+			axi_ctrl->share_ctrl->current_mode ==
+				VFE_OUTPUTS_THUMB_AND_JPEG) {
 
-			/* Configure primary channel for JPEG */
+				/* Configure primary channel for JPEG */
+				rc = configure_pingpong_buffers(
+					VFE_MSG_JPEG_CAPTURE,
+					VFE_MSG_OUTPUT_PRIMARY,
+					axi_ctrl);
+			} else {
+				/* Configure primary channel */
+				rc = configure_pingpong_buffers(
+					VFE_MSG_CAPTURE,
+					VFE_MSG_OUTPUT_PRIMARY,
+					axi_ctrl);
+			}
+			if (rc < 0) {
+				pr_err("%s error configuring pingpong buffers for primary output",
+					__func__);
+				rc = -EINVAL;
+				goto config_done;
+			}
+			/* Configure secondary channel */
 			rc = configure_pingpong_buffers(
-				VFE_MSG_JPEG_CAPTURE,
-				VFE_MSG_OUTPUT_PRIMARY,
-				axi_ctrl);
-		} else {
-			/* Configure primary channel */
+					VFE_MSG_CAPTURE,
+					VFE_MSG_OUTPUT_SECONDARY,
+					axi_ctrl);
+			if (rc < 0) {
+				pr_err("%s error configuring pingpong buffers for secondary output",
+					__func__);
+				rc = -EINVAL;
+				goto config_done;
+			}
+		}
+
+		if (axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_RDI0)
 			rc = configure_pingpong_buffers(
-				VFE_MSG_CAPTURE,
-				VFE_MSG_OUTPUT_PRIMARY,
+				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_TERTIARY1,
 				axi_ctrl);
-		}
-		if (rc < 0) {
-			pr_err("%s error configuring pingpong buffers for primary output",
-				__func__);
-			rc = -EINVAL;
-			goto config_done;
-		}
-		/* Configure secondary channel */
-		rc = configure_pingpong_buffers(
-				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
+		if (axi_ctrl->share_ctrl->current_mode &
+				VFE_OUTPUTS_RDI1)
+			rc = configure_pingpong_buffers(
+				VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_TERTIARY2,
 				axi_ctrl);
-		if (rc < 0) {
-			pr_err("%s error configuring pingpong buffers for secondary output",
-				__func__);
-			rc = -EINVAL;
-			goto config_done;
-		}
 		break;
 	default:
 		rc = -EINVAL;
@@ -5580,10 +5786,9 @@
 void axi_start(struct msm_cam_media_controller *pmctl,
 	struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
 {
-	uint32_t irq_comp_mask = 0, irq_mask = 0, irq_mask1 = 0;
 	int rc = 0;
 	uint32_t reg_update = 0;
-	uint16_t operation_mode =
+	uint32_t vfe_mode =
 		(axi_ctrl->share_ctrl->current_mode &
 		~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
 	rc = axi_config_buffers(axi_ctrl, vfe_params);
@@ -5592,99 +5797,77 @@
 
 	switch (vfe_params.cmd_type) {
 	case AXI_CMD_PREVIEW:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 		break;
 	case AXI_CMD_CAPTURE:
 	case AXI_CMD_RAW_CAPTURE:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 		break;
 	case AXI_CMD_RECORD:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
 		return;
 	case AXI_CMD_ZSL:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
 		break;
 	case AXI_CMD_LIVESHOT:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_LIVESHOT);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_LIVESHOT);
 		return;
 	default:
 		return;
 	}
-
-	irq_comp_mask =
-		msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_COMP_MASK);
-	irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
-
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_PRIMARY) {
-		if (vfe_params.cmd_type == AXI_CMD_RAW_CAPTURE)
-			irq_comp_mask |= (
-				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0);
-		else
-		irq_comp_mask |= (
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
-		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
-	} else if (axi_ctrl->share_ctrl->outpath.output_mode &
-			   VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
-		irq_comp_mask |= (
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2);
-		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
-	}
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_SECONDARY) {
-		irq_comp_mask |= (
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8));
-		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
-	} else if (axi_ctrl->share_ctrl->outpath.output_mode &
-			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
-		irq_comp_mask |= (
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
-			0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch2 + 8));
-		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
-	}
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-		VFE32_OUTPUT_MODE_TERTIARY1) {
-		irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0 +
-			VFE_WM_OFFSET));
-	}
-	if (axi_ctrl->share_ctrl->outpath.output_mode &
-		VFE32_OUTPUT_MODE_TERTIARY2) {
-		irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0 +
-			VFE_WM_OFFSET));
-	}
-
-	msm_camera_io_w(irq_comp_mask,
-		axi_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-	msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_0);
+	axi_enable_wm_irq(axi_ctrl->share_ctrl);
 
 	switch (vfe_params.cmd_type) {
+	case AXI_CMD_RAW_CAPTURE:
+		msm_camera_io_w((
+			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0),
+			axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+			+ vfe32_AXI_WM_CFG[axi_ctrl->
+			share_ctrl->outpath.out0.ch0]);
+		break;
 	case AXI_CMD_PREVIEW: {
-		switch (operation_mode) {
+		switch (vfe_mode) {
 		case VFE_OUTPUTS_PREVIEW:
 		case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
 			if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_PRIMARY) {
+				msm_camera_io_w((
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch0 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch1),
+					axi_ctrl->share_ctrl->vfebase +
+							VFE_BUS_CMD);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out0.ch0]);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out0.ch1]);
+
+
 			} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 					VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+				msm_camera_io_w((
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch0 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch1 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out0.ch2),
+					axi_ctrl->share_ctrl->vfebase +
+							VFE_BUS_CMD);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out0.ch0]);
@@ -5699,6 +5882,13 @@
 		default:
 			if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_SECONDARY) {
+				msm_camera_io_w((
+					0x1 << axi_ctrl->share_ctrl->
+						outpath.out1.ch0 |
+					0x1 << axi_ctrl->share_ctrl->
+						outpath.out1.ch1),
+					axi_ctrl->share_ctrl->vfebase +
+						VFE_BUS_CMD);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out1.ch0]);
@@ -5707,6 +5897,15 @@
 					share_ctrl->outpath.out1.ch1]);
 			} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+				msm_camera_io_w((
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out1.ch0 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out1.ch1 |
+					0x1 << axi_ctrl->share_ctrl->
+							outpath.out1.ch2),
+					axi_ctrl->share_ctrl->vfebase +
+							VFE_BUS_CMD);
 				msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
 					+ vfe32_AXI_WM_CFG[axi_ctrl->
 					share_ctrl->outpath.out1.ch0]);
@@ -5724,6 +5923,10 @@
 	default:
 		if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_PRIMARY) {
+			msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[axi_ctrl->
 				share_ctrl->outpath.out0.ch0]);
@@ -5732,6 +5935,11 @@
 				share_ctrl->outpath.out0.ch1]);
 		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+			msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[axi_ctrl->
 				share_ctrl->outpath.out0.ch0]);
@@ -5745,6 +5953,10 @@
 
 		if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY) {
+			msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch1),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[axi_ctrl->
 				share_ctrl->outpath.out1.ch0]);
@@ -5753,6 +5965,11 @@
 				share_ctrl->outpath.out1.ch1]);
 		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+			msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch1 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out1.ch2),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 				vfe32_AXI_WM_CFG[axi_ctrl->
 				share_ctrl->outpath.out1.ch0]);
@@ -5765,36 +5982,47 @@
 		}
 		break;
 	}
-	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		axi_ctrl->share_ctrl->outpath.out2.capture_cnt =
+						vfe_params.capture_count;
+		axi_ctrl->share_ctrl->rdi0_capture_count =
+						vfe_params.capture_count;
+		msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out2.ch0),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
 			outpath.out2.ch0]);
-	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+	}
+	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		axi_ctrl->share_ctrl->outpath.out3.capture_cnt =
+						vfe_params.capture_count;
+		axi_ctrl->share_ctrl->rdi1_capture_count =
+						vfe_params.capture_count;
+		msm_camera_io_w((
+				0x1 << axi_ctrl->share_ctrl->outpath.out3.ch0),
+				axi_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
 		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
 			outpath.out3.ch0]);
+	}
 
-	irq_mask1 =
-		msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
-			VFE_IRQ_MASK_1);
+	axi_enable_irq(axi_ctrl->share_ctrl);
 
 	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
-		irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
 		if (!atomic_cmpxchg(
 			&axi_ctrl->share_ctrl->rdi0_update_ack_pending,
 				0, 1))
 			reg_update |= 0x2;
 	}
 	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
-		irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
 		if (!atomic_cmpxchg(
 			&axi_ctrl->share_ctrl->rdi1_update_ack_pending,
 				0, 1))
 			reg_update |= 0x4;
 	}
-	msm_camera_io_w(irq_mask1, axi_ctrl->share_ctrl->vfebase +
-		VFE_IRQ_MASK_1);
-	if (operation_mode) {
+
+	if (vfe_mode) {
 		if (!atomic_cmpxchg(
 			&axi_ctrl->share_ctrl->pix0_update_ack_pending,
 				0, 1))
@@ -5806,54 +6034,62 @@
 			VFE_REG_UPDATE_CMD);
 	axi_ctrl->share_ctrl->operation_mode |=
 		axi_ctrl->share_ctrl->current_mode;
-	axi_enable_irq(axi_ctrl->share_ctrl);
 }
 
 void axi_stop(struct msm_cam_media_controller *pmctl,
 	struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
 {
 	uint32_t reg_update = 0;
-	uint32_t operation_mode =
+	uint32_t vfe_mode =
 	axi_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
 		VFE_OUTPUTS_RDI1);
-
 	switch (vfe_params.cmd_type) {
 	case AXI_CMD_PREVIEW:
 	case AXI_CMD_CAPTURE:
 	case AXI_CMD_RAW_CAPTURE:
 	case AXI_CMD_ZSL:
+		axi_ctrl->share_ctrl->cmd_type = vfe_params.cmd_type;
 		break;
 	case AXI_CMD_RECORD:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 		return;
 	case AXI_CMD_LIVESHOT:
-		msm_camio_bus_scale_cfg(
-		pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+		if (!axi_ctrl->share_ctrl->dual_enabled)
+			msm_camio_bus_scale_cfg(
+			pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
 		return;
 	default:
 		return;
 	}
 
 	if (axi_ctrl->share_ctrl->stop_immediately) {
-		axi_disable_irq(axi_ctrl->share_ctrl);
+		axi_disable_irq(axi_ctrl->share_ctrl,
+			axi_ctrl->share_ctrl->current_mode);
 		axi_stop_process(axi_ctrl->share_ctrl);
 		return;
 	}
 
 	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+		msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
+				outpath.out2.ch0]);
 		if (!atomic_cmpxchg(
 			&axi_ctrl->share_ctrl->rdi0_update_ack_pending,
 				0, 2))
 			reg_update |= 0x2;
 	}
 	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+		msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
+			vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
+				outpath.out3.ch0]);
 		if (!atomic_cmpxchg(
 			&axi_ctrl->share_ctrl->rdi1_update_ack_pending,
 				0, 2))
 			reg_update |= 0x4;
 	}
-	if (operation_mode) {
+	if (vfe_mode) {
 		if (!atomic_cmpxchg(
 			&axi_ctrl->share_ctrl->pix0_update_ack_pending,
 				0, 2))
@@ -6083,8 +6319,15 @@
 		axi_stop(pmctl, axi_ctrl, vfe_params);
 		}
 		break;
-	case CMD_AXI_RESET:
-		axi_reset(axi_ctrl);
+	case CMD_AXI_RESET: {
+		struct msm_camera_vfe_params_t vfe_params;
+		if (copy_from_user(&vfe_params,
+				(void __user *)(vfecmd.value),
+				sizeof(struct msm_camera_vfe_params_t))) {
+				return -EFAULT;
+		}
+		axi_reset(axi_ctrl, vfe_params);
+		}
 		break;
 	case CMD_AXI_ABORT:
 		if (copy_from_user(&axi_ctrl->share_ctrl->sync_abort,
@@ -6151,19 +6394,44 @@
 		if ((axi_ctrl->share_ctrl->outpath.out0.capture_cnt == 0)
 				&& (axi_ctrl->share_ctrl->outpath.out1.
 				capture_cnt == 0)) {
-			msm_camera_io_w_mb(
-				CAMIF_COMMAND_STOP_IMMEDIATELY,
-				axi_ctrl->share_ctrl->vfebase +
-				VFE_CAMIF_COMMAND);
-			axi_disable_irq(axi_ctrl->share_ctrl);
+			uint32_t mode =
+				(axi_ctrl->share_ctrl->operation_mode &
+				~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
+			uint16_t output_mode =
+			axi_ctrl->share_ctrl->comp_output_mode &
+				~(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2);
+			if (!axi_ctrl->share_ctrl->dual_enabled)
+				msm_camera_io_w_mb(
+					CAMIF_COMMAND_STOP_IMMEDIATELY,
+					axi_ctrl->share_ctrl->vfebase +
+					VFE_CAMIF_COMMAND);
+			axi_disable_wm_irq(axi_ctrl->share_ctrl, output_mode);
+			axi_disable_irq(axi_ctrl->share_ctrl, mode);
 			vfe32_send_isp_msg(&axi_ctrl->subdev,
 				axi_ctrl->share_ctrl->vfeFrameId,
 				MSG_ID_PIX0_UPDATE_ACK);
-			vfe32_send_isp_msg(&axi_ctrl->subdev,
-				axi_ctrl->share_ctrl->vfeFrameId,
-				MSG_ID_SNAPSHOT_DONE);
+			axi_ctrl->share_ctrl->outpath.out0.
+				capture_cnt = -1;
+			axi_ctrl->share_ctrl->outpath.out1.
+				capture_cnt = -1;
+			axi_ctrl->share_ctrl->comp_output_mode &=
+				(VFE32_OUTPUT_MODE_TERTIARY1|
+				VFE32_OUTPUT_MODE_TERTIARY2);
 		}
 	}
+
+	if (axi_ctrl->share_ctrl->outpath.out2.capture_cnt == 0) {
+		axi_ctrl->share_ctrl->comp_output_mode &=
+				~VFE32_OUTPUT_MODE_TERTIARY1;
+		axi_ctrl->share_ctrl->outpath.out2.capture_cnt = -1;
+	}
+
+	if (axi_ctrl->share_ctrl->outpath.out3.capture_cnt == 0) {
+		axi_ctrl->share_ctrl->comp_output_mode &=
+				~VFE32_OUTPUT_MODE_TERTIARY2;
+		axi_ctrl->share_ctrl->outpath.out3.capture_cnt = -1;
+	}
 }
 
 static int msm_axi_buf_cfg(struct v4l2_subdev *sd, void __user *arg)
@@ -6218,8 +6486,16 @@
 {
 	int rc = -ENOIOCTLCMD;
 	switch (cmd) {
-	case VIDIOC_MSM_AXI_INIT:
-		rc = msm_axi_subdev_init(sd);
+	case VIDIOC_MSM_AXI_INIT: {
+		uint8_t dual_enabled;
+		if (copy_from_user(&dual_enabled,
+				(void __user *)(arg),
+				sizeof(uint8_t))) {
+				rc = -EFAULT;
+				break;
+		}
+		rc = msm_axi_subdev_init(sd, dual_enabled);
+		}
 		break;
 	case VIDIOC_MSM_AXI_CFG:
 		rc = msm_axi_config(sd, arg);
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/video/msm/vfe/msm_vfe32.h
index 985493e..f985221 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.h
+++ b/drivers/media/video/msm/vfe/msm_vfe32.h
@@ -782,7 +782,7 @@
 	int8_t ch0;
 	int8_t ch1;
 	int8_t ch2;
-	uint32_t  capture_cnt;
+	int32_t  capture_cnt;
 	uint32_t  frame_drop_cnt;
 	struct msm_free_buf ping;
 	struct msm_free_buf pong;
@@ -959,6 +959,9 @@
 	int8_t stop_ack_pending;
 	enum vfe_output_state liveshot_state;
 	uint32_t vfe_capture_count;
+	int32_t rdi0_capture_count;
+	int32_t rdi1_capture_count;
+	uint8_t update_counter;
 
 	uint32_t operation_mode;     /* streaming or snapshot */
 	uint32_t current_mode;
@@ -969,6 +972,7 @@
 	uint8_t sync_abort;
 	uint16_t cmd_type;
 	uint8_t vfe_reset_flag;
+	uint8_t dual_enabled;
 
 	uint8_t axi_ref_cnt;
 	uint16_t comp_output_mode;
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.c b/drivers/media/video/msm/vfe/msm_vfe40.c
index 1297379..e958241 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40.c
+++ b/drivers/media/video/msm/vfe/msm_vfe40.c
@@ -806,7 +806,7 @@
 		vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
 	msm_camera_io_w(0x800080,
 		vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
-	msm_camera_io_w(0xFFFFF,
+	msm_camera_io_w(0x198FFFFF,
 		vfe40_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
 
 	msm_camera_io_w(0,
@@ -1289,6 +1289,12 @@
 			vfe40_ctrl->share_ctrl->vfebase +
 			VFE_REG_UPDATE_CMD);
 
+	msm_camera_io_w_mb(0x00003fff,
+			vfe40_ctrl->share_ctrl->vfebase +
+			V40_AXI_BUS_CMD_OFF);
+	msm_camera_io_w_mb(1,
+			vfe40_ctrl->share_ctrl->vfebase +
+			V40_BUS_PM_CMD);
 	if (vfe_operation_mode) {
 		msm_camera_io_w_mb(1, vfe40_ctrl->share_ctrl->vfebase +
 			VFE_CAMIF_COMMAND);
@@ -1345,8 +1351,6 @@
 	vfe40_ctrl->share_ctrl->start_ack_pending = TRUE;
 	vfe40_start_common(vfe40_ctrl);
 
-	msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x18C);
-	msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x188);
 	return 0;
 }
 static int vfe40_capture_raw(
@@ -1381,12 +1385,9 @@
 
 	vfe40_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
 
-	vfe40_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
 
 	vfe40_start_common(vfe40_ctrl);
 	/* for debug */
-	msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x18C);
-	msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x188);
 	return 0;
 }
 
@@ -1639,7 +1640,7 @@
 	outch = vfe40_get_ch(path, axi_ctrl->share_ctrl);
 	if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
 		/* Configure Preview Ping Pong */
-		pr_info("%s Configure ping/pong address for %d",
+		pr_info("%s Configure ping/pong address for %d\n",
 						__func__, path);
 		vfe40_put_ch_ping_addr(
 			axi_ctrl->share_ctrl->vfebase, outch->ch0,
@@ -3153,7 +3154,6 @@
 		irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
 			VFE_WM_OFFSET));
 	}
-
 	msm_camera_io_w_mb(reg_update,
 		share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	msm_camera_io_w(irq_mask, share_ctrl->vfebase +
@@ -3326,7 +3326,6 @@
 				msm_camera_io_w(0, share_ctrl->vfebase +
 					vfe40_AXI_WM_CFG[
 				share_ctrl->outpath.out0.ch1]);
-
 				share_ctrl->liveshot_state = VFE_STATE_STOPPED;
 				msm_camera_io_w_mb(1, share_ctrl->vfebase +
 				VFE_REG_UPDATE_CMD);
@@ -3387,11 +3386,10 @@
 				msm_camera_io_w_mb
 				(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
 					share_ctrl->vfebase +
-				VFE_CAMIF_COMMAND);
+					VFE_CAMIF_COMMAND);
 				vfe40_ctrl->snapshot_frame_cnt = -1;
 				vfe40_ctrl->frame_skip_cnt = 31;
-					vfe40_ctrl->frame_skip_pattern =
-								0xffffffff;
+				vfe40_ctrl->frame_skip_pattern = 0xffffffff;
 			} /*if snapshot count is 0*/
 		} /*if frame is not being dropped*/
 		vfe40_ctrl->snapshot_frame_cnt++;
@@ -3607,6 +3605,8 @@
 static void vfe40_process_common_error_irq(
 	struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
 {
+	if (errStatus & VFE40_IMASK_BUS_BDG_HALT_ACK)
+		pr_err("vfe40_irq: BUS BDG HALT ACK\n");
 
 	if (errStatus & VFE40_IMASK_IMG_MAST_0_BUS_OVFL)
 		pr_err("vfe40_irq: image master 0 bus overflow\n");
@@ -5455,9 +5455,14 @@
 
 	if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE40_OUTPUT_MODE_PRIMARY) {
-		irq_comp_mask |= (
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
-			0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
+		if (vfe_params.cmd_type == AXI_CMD_RAW_CAPTURE) {
+			irq_comp_mask |=
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0;
+		} else {
+			irq_comp_mask |= (
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+				0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
+		}
 		irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
 	} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 			   VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
@@ -5551,12 +5556,21 @@
 	default:
 		if (axi_ctrl->share_ctrl->outpath.output_mode &
 			VFE40_OUTPUT_MODE_PRIMARY) {
-			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out0.ch0]);
-			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
-				vfe40_AXI_WM_CFG[axi_ctrl->
-				share_ctrl->outpath.out0.ch1]);
+			if (vfe_params.cmd_type == AXI_CMD_RAW_CAPTURE) {
+				msm_camera_io_w(1,
+					axi_ctrl->share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch0]);
+			} else {
+				msm_camera_io_w(1,
+					axi_ctrl->share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[axi_ctrl
+					->share_ctrl->outpath.out0.ch0]);
+				msm_camera_io_w(1,
+					axi_ctrl->share_ctrl->vfebase +
+					vfe40_AXI_WM_CFG[axi_ctrl->
+					share_ctrl->outpath.out0.ch1]);
+			}
 		} else if (axi_ctrl->share_ctrl->outpath.output_mode &
 				VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
 			msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
@@ -5592,6 +5606,7 @@
 		}
 		break;
 	}
+
 	if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
 		msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
 			vfe40_AXI_WM_CFG[axi_ctrl->share_ctrl->
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.h b/drivers/media/video/msm/vfe/msm_vfe40.h
index 5b73751..8201d18 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40.h
+++ b/drivers/media/video/msm/vfe/msm_vfe40.h
@@ -204,6 +204,7 @@
 #define V40_AXI_OUT_LEN           344
 #define V40_AXI_CFG_LEN           71
 
+#define V40_BUS_PM_CMD            0x00000270
 #define V40_FOV_ENC_OFF           0x00000854
 #define V40_FOV_ENC_LEN           16
 #define V40_FOV_VIEW_OFF          0x00000864
@@ -719,7 +720,7 @@
 #define VFE40_IMASK_ERROR_ONLY_0  0x0
 /* when normal case, don't want to block error status. */
 /* bit 0-21 are error irq bits */
-#define VFE40_IMASK_COMMON_ERROR_ONLY_1       0x0000FE00
+#define VFE40_IMASK_COMMON_ERROR_ONLY_1       0x0000FF00
 #define VFE40_IMASK_VFE_ERROR_ONLY_1          0x00FF01FF
 #define VFE40_IMASK_CAMIF_ERROR               (0x00000001<<0)
 #define VFE40_IMASK_BHIST_OVWR                (0x00000001<<1)
@@ -729,6 +730,7 @@
 #define VFE40_IMASK_REALIGN_BUF_CB_OVFL       (0x00000001<<5)
 #define VFE40_IMASK_REALIGN_BUF_CR_OVFL       (0x00000001<<6)
 #define VFE40_IMASK_VIOLATION                 (0x00000001<<7)
+#define VFE40_IMASK_BUS_BDG_HALT_ACK          (0x00000001<<8)
 #define VFE40_IMASK_IMG_MAST_0_BUS_OVFL       (0x00000001<<9)
 #define VFE40_IMASK_IMG_MAST_1_BUS_OVFL       (0x00000001<<10)
 #define VFE40_IMASK_IMG_MAST_2_BUS_OVFL       (0x00000001<<11)
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
index 15c38af..9deae65 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
@@ -1561,6 +1561,11 @@
 	}
 		return 0;
 
+	case CMD_AXI_START:
+	case CMD_AXI_STOP:
+	case CMD_AXI_RESET:
+		return 0;
+
 	case CMD_CONFIG_FREE_BUF_ADDR: {
 		int path = *((int *)cmd->value);
 		struct buf_info *outch = vfe2x_get_ch(path);
@@ -1853,9 +1858,6 @@
 						flags);
 				if (op_mode & SNAPSHOT_MASK_MODE) {
 					vfe2x_ctrl->stop_pending = 0;
-					vfe2x_send_isp_msg(vfe2x_ctrl,
-						msgs_map[MSG_STOP_ACK].
-						isp_id);
 					spin_unlock_irqrestore(
 							&vfe2x_ctrl->table_lock,
 							flags);
diff --git a/drivers/media/video/msm_vidc/Makefile b/drivers/media/video/msm_vidc/Makefile
index e145229..2a1f40f 100644
--- a/drivers/media/video/msm_vidc/Makefile
+++ b/drivers/media/video/msm_vidc/Makefile
@@ -4,5 +4,6 @@
 				msm_vdec.o \
 				msm_venc.o \
 				msm_smem.o \
+				msm_vidc_debug.o \
 				vidc_hal.o \
 				vidc_hal_interrupt_handler.o \
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index b7b12cb..156a721 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <mach/iommu_domains.h>
 #include "msm_smem.h"
+#include "msm_vidc_debug.h"
 
 struct smem_client {
 	int mem_type;
@@ -27,19 +28,20 @@
 {
 	int rc;
 	if (!iova || !buffer_size || !hndl || !clnt) {
-		pr_err("Invalid params: %p, %p, %p, %p\n",
+		dprintk(VIDC_ERR, "Invalid params: %p, %p, %p, %p\n",
 				clnt, hndl, iova, buffer_size);
 		return -EINVAL;
 	}
 	if (align < 4096)
 		align = 4096;
-	pr_debug("\n In %s  domain: %d, Partition: %d\n",
-		__func__, domain_num, partition_num);
+	dprintk(VIDC_DBG, "domain: %d, partition: %d\n",
+		domain_num, partition_num);
 	rc = ion_map_iommu(clnt, hndl, domain_num, partition_num, align,
 			0, iova, buffer_size, UNCACHED, 0);
 	if (rc)
-		pr_err("ion_map_iommu failed(%d).domain: %d,partition: %d\n",
-				rc, domain_num, partition_num);
+		dprintk(VIDC_ERR,
+		"ion_map_iommu failed(%d).domain: %d,partition: %d\n",
+		rc, domain_num, partition_num);
 
 	return rc;
 }
@@ -61,14 +63,14 @@
 	int rc = 0;
 	hndl = ion_import_dma_buf(client->clnt, fd);
 	if (IS_ERR_OR_NULL(hndl)) {
-		pr_err("Failed to get handle: %p, %d, %d, %p\n",
+		dprintk(VIDC_ERR, "Failed to get handle: %p, %d, %d, %p\n",
 				client, fd, offset, hndl);
 		rc = -ENOMEM;
 		goto fail_import_fd;
 	}
 	rc = ion_handle_get_flags(client->clnt, hndl, &ionflag);
 	if (rc) {
-		pr_err("Failed to get ion flags: %d", rc);
+		dprintk(VIDC_ERR, "Failed to get ion flags: %d", rc);
 		goto fail_map;
 	}
 	mem->kvaddr = NULL;
@@ -77,7 +79,7 @@
 	rc = get_device_address(client->clnt, hndl, mem->domain,
 		mem->partition_num, 4096, &iova, &buffer_size, ionflag);
 	if (rc) {
-		pr_err("Failed to get device address: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to get device address: %d\n", rc);
 		goto fail_device_address;
 	}
 
@@ -85,7 +87,7 @@
 	mem->smem_priv = hndl;
 	mem->device_addr = iova;
 	mem->size = buffer_size;
-	pr_err("NOTE: Buffer device address: 0x%lx, size: %d\n",
+	dprintk(VIDC_DBG, "NOTE: Buffer device address: 0x%lx, size: %d\n",
 		mem->device_addr, mem->size);
 	return rc;
 fail_device_address:
@@ -114,12 +116,13 @@
 	if (align < 4096)
 		align = 4096;
 	size = (size + 4095) & (~4095);
-	pr_debug("\n in %s domain: %d, Partition: %d\n",
-		__func__, domain, partition);
+	dprintk(VIDC_DBG, "domain: %d, partition: %d\n",
+		domain, partition);
 	hndl = ion_alloc(client->clnt, size, align, ionflags);
 	if (IS_ERR_OR_NULL(hndl)) {
-		pr_err("Failed to allocate shared memory = %p, %d, %d, 0x%lx\n",
-				client, size, align, ionflags);
+		dprintk(VIDC_ERR,
+		"Failed to allocate shared memory = %p, %d, %d, 0x%lx\n",
+		client, size, align, ionflags);
 		rc = -ENOMEM;
 		goto fail_shared_mem_alloc;
 	}
@@ -130,7 +133,8 @@
 	if (map_kernel) {
 		mem->kvaddr = ion_map_kernel(client->clnt, hndl, 0);
 		if (!mem->kvaddr) {
-			pr_err("Failed to map shared mem in kernel\n");
+			dprintk(VIDC_ERR,
+				"Failed to map shared mem in kernel\n");
 			rc = -EIO;
 			goto fail_map;
 		}
@@ -140,11 +144,13 @@
 	rc = get_device_address(client->clnt, hndl, mem->domain,
 		mem->partition_num, align, &iova, &buffer_size, UNCACHED);
 	if (rc) {
-		pr_err("Failed to get device address: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to get device address: %d\n",
+			rc);
 		goto fail_device_address;
 	}
 	mem->device_addr = iova;
-	pr_err("NOTE: device_address = 0x%lx, kvaddr = 0x%p, size = %d\n",
+	dprintk(VIDC_DBG,
+		"device_address = 0x%lx, kvaddr = 0x%p, size = %d\n",
 		mem->device_addr, mem->kvaddr, size);
 	mem->size = size;
 	return rc;
@@ -172,7 +178,7 @@
 	struct ion_client *client = NULL;
 	client = msm_ion_client_create(-1, "video_client");
 	if (!client)
-		pr_err("Failed to create smem client\n");
+		dprintk(VIDC_ERR, "Failed to create smem client\n");
 	return client;
 };
 
@@ -188,12 +194,12 @@
 	int rc = 0;
 	struct msm_smem *mem;
 	if (fd < 0) {
-		pr_err("Invalid fd: %d\n", fd);
+		dprintk(VIDC_ERR, "Invalid fd: %d\n", fd);
 		return NULL;
 	}
 	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem) {
-		pr_err("Failed to allocte shared mem\n");
+		dprintk(VIDC_ERR, "Failed to allocte shared mem\n");
 		return NULL;
 	}
 	switch (client->mem_type) {
@@ -202,12 +208,12 @@
 			domain, partition, mem);
 		break;
 	default:
-		pr_err("Mem type not supported\n");
+		dprintk(VIDC_ERR, "Mem type not supported\n");
 		rc = -EINVAL;
 		break;
 	}
 	if (rc) {
-		pr_err("Failed to allocate shared memory\n");
+		dprintk(VIDC_ERR, "Failed to allocate shared memory\n");
 		kfree(mem);
 		mem = NULL;
 	}
@@ -229,7 +235,7 @@
 	struct smem_client *client = clt;
 	int rc;
 	if (!client || !mem) {
-		pr_err("Invalid  client/handle passed\n");
+		dprintk(VIDC_ERR, "Invalid  client/handle passed\n");
 		return -EINVAL;
 	}
 	switch (client->mem_type) {
@@ -237,7 +243,7 @@
 		rc = ion_mem_clean_invalidate(client, mem);
 		break;
 	default:
-		pr_err("Mem type not supported\n");
+		dprintk(VIDC_ERR, "Mem type not supported\n");
 		rc = -EINVAL;
 		break;
 	}
@@ -253,7 +259,7 @@
 		clnt = ion_new_client();
 		break;
 	default:
-		pr_err("Mem type not supported\n");
+		dprintk(VIDC_ERR, "Mem type not supported\n");
 		break;
 	}
 	if (clnt) {
@@ -263,7 +269,8 @@
 			client->clnt = clnt;
 		}
 	} else {
-		pr_err("Failed to create new client: mtype = %d\n", mtype);
+		dprintk(VIDC_ERR, "Failed to create new client: mtype = %d\n",
+			mtype);
 	}
 	return client;
 };
@@ -276,16 +283,17 @@
 	struct msm_smem *mem;
 	client = clt;
 	if (!client) {
-		pr_err("Invalid  client passed\n");
+		dprintk(VIDC_ERR, "Invalid  client passed\n");
 		return NULL;
 	}
 	if (!size) {
-		pr_err("No need to allocate memory of size: %d\n", size);
+		dprintk(VIDC_ERR, "No need to allocate memory of size: %d\n",
+			size);
 		return NULL;
 	}
 	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem) {
-		pr_err("Failed to allocate shared mem\n");
+		dprintk(VIDC_ERR, "Failed to allocate shared mem\n");
 		return NULL;
 	}
 	switch (client->mem_type) {
@@ -294,12 +302,12 @@
 			domain, partition, mem, map_kernel);
 		break;
 	default:
-		pr_err("Mem type not supported\n");
+		dprintk(VIDC_ERR, "Mem type not supported\n");
 		rc = -EINVAL;
 		break;
 	}
 	if (rc) {
-		pr_err("Failed to allocate shared memory\n");
+		dprintk(VIDC_ERR, "Failed to allocate shared memory\n");
 		kfree(mem);
 		mem = NULL;
 	}
@@ -310,7 +318,7 @@
 {
 	struct smem_client *client = clt;
 	if (!client || !mem) {
-		pr_err("Invalid  client/handle passed\n");
+		dprintk(VIDC_ERR, "Invalid  client/handle passed\n");
 		return;
 	}
 	switch (client->mem_type) {
@@ -318,7 +326,7 @@
 		free_ion_mem(client, mem);
 		break;
 	default:
-		pr_err("Mem type not supported\n");
+		dprintk(VIDC_ERR, "Mem type not supported\n");
 		break;
 	}
 	kfree(mem);
@@ -328,7 +336,7 @@
 {
 	struct smem_client *client = clt;
 	if (!client) {
-		pr_err("Invalid  client passed\n");
+		dprintk(VIDC_ERR, "Invalid  client passed\n");
 		return;
 	}
 	switch (client->mem_type) {
@@ -336,7 +344,7 @@
 		ion_delete_client(client);
 		break;
 	default:
-		pr_err("Mem type not supported\n");
+		dprintk(VIDC_ERR, "Mem type not supported\n");
 		break;
 	}
 	kfree(client);
diff --git a/drivers/media/video/msm_vidc/msm_smem.h b/drivers/media/video/msm_vidc/msm_smem.h
index 37816e1..c109abd 100644
--- a/drivers/media/video/msm_vidc/msm_smem.h
+++ b/drivers/media/video/msm_vidc/msm_smem.h
@@ -14,7 +14,7 @@
 #define _MSM_SMEM_H_
 
 #include <linux/types.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 enum smem_type {
 	SMEM_ION,
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 882d03e..170322c 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -26,6 +26,7 @@
 #include <mach/iommu_domains.h>
 #include <media/msm_vidc.h>
 #include "msm_vidc_internal.h"
+#include "msm_vidc_debug.h"
 #include "vidc_hal_api.h"
 #include "msm_smem.h"
 
@@ -46,7 +47,7 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
 		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 414700000,
+		.ab = 138200000,
 		.ib = 1222000000,
 	},
 };
@@ -55,7 +56,7 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
 		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 940000000,
+		.ab = 414700000,
 		.ib = 1222000000,
 	},
 };
@@ -64,7 +65,7 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
 		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 1880000000,
+		.ab = 940000000,
 		.ib = 2444000000U,
 	},
 };
@@ -110,7 +111,7 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
 		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 456200000,
+		.ab = 176900000,
 		.ib = 1556640000,
 	},
 };
@@ -119,7 +120,7 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
 		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 864800000,
+		.ab = 456200000,
 		.ib = 1556640000,
 	},
 };
@@ -128,8 +129,8 @@
 	{
 		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
 		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 1729600000,
-		.ib = 3113280000U,
+		.ab = 864800000,
+		.ib = 1556640000,
 	},
 };
 
@@ -491,7 +492,7 @@
 	struct buffer_info *temp;
 	struct buffer_info *ret = NULL;
 	if (!list || fd < 0) {
-		pr_err("%s Invalid input\n", __func__);
+		dprintk(VIDC_ERR, "Invalid input\n");
 		goto err_invalid_input;
 	}
 	if (!list_empty(list)) {
@@ -501,7 +502,8 @@
 			|| CONTAINS(buff_off, size, temp->buff_off)
 			|| OVERLAPS(buff_off, size,
 				temp->buff_off, temp->size))) {
-				pr_err("This memory region is already mapped\n");
+				dprintk(VIDC_WARN,
+				"This memory region is already mapped\n");
 				ret = temp;
 				break;
 			}
@@ -517,13 +519,13 @@
 	struct buffer_info *temp;
 	struct buffer_info *ret = NULL;
 	if (!list || fd < 0) {
-		pr_err("%s Invalid input\n", __func__);
+		dprintk(VIDC_ERR, "Invalid input\n");
 		goto err_invalid_input;
 	}
 	if (!list_empty(list)) {
 		list_for_each_entry(temp, list, list) {
 			if (temp && temp->fd == fd)  {
-				pr_err("Found same fd buffer\n");
+				dprintk(VIDC_ERR, "Found same fd buffer\n");
 				ret = temp;
 				break;
 			}
@@ -543,20 +545,22 @@
 	struct msm_v4l2_vid_inst *v4l2_inst = kzalloc(sizeof(*v4l2_inst),
 						GFP_KERNEL);
 	if (!v4l2_inst) {
-		pr_err("Failed to allocate memory for this instance\n");
+		dprintk(VIDC_ERR,
+			"Failed to allocate memory for this instance\n");
 		rc = -ENOMEM;
 		goto fail_nomem;
 	}
 	v4l2_inst->mem_client = msm_smem_new_client(SMEM_ION);
 	if (!v4l2_inst->mem_client) {
-		pr_err("Failed to create memory client\n");
+		dprintk(VIDC_ERR, "Failed to create memory client\n");
 		rc = -ENOMEM;
 		goto fail_mem_client;
 	}
 	rc = msm_vidc_open(&v4l2_inst->vidc_inst, core->id, vid_dev->type);
 	if (rc) {
-		pr_err("Failed to create video instance, core: %d, type = %d\n",
-			core->id, vid_dev->type);
+		dprintk(VIDC_ERR,
+		"Failed to create video instance, core: %d, type = %d\n",
+		core->id, vid_dev->type);
 		rc = -ENOMEM;
 		goto fail_open;
 	}
@@ -655,13 +659,14 @@
 				plane.reserved[0] = bi->fd;
 				plane.reserved[1] = bi->buff_off;
 				plane.length = bi->size;
-				plane.m.userptr = bi->uvaddr;
+				plane.m.userptr = bi->device_addr;
 				buffer_info.m.planes = &plane;
 				buffer_info.length = 1;
-				pr_info("Releasing buffer: %d, %d, %d\n",
-				buffer_info.m.planes[0].reserved[0],
-				buffer_info.m.planes[0].reserved[1],
-				buffer_info.m.planes[0].length);
+				dprintk(VIDC_DBG,
+					"Releasing buffer: %d, %d, %d\n",
+					buffer_info.m.planes[0].reserved[0],
+					buffer_info.m.planes[0].reserved[1],
+					buffer_info.m.planes[0].length);
 				rc = msm_vidc_release_buf(&v4l2_inst->vidc_inst,
 					&buffer_info);
 				list_del(&bi->list);
@@ -687,7 +692,7 @@
 	vidc_inst = get_vidc_inst(file, fh);
 	v4l2_inst = get_v4l2_inst(file, fh);
 	if (!v4l2_inst->mem_client) {
-		pr_err("Failed to get memory client\n");
+		dprintk(VIDC_ERR, "Failed to get memory client\n");
 		rc = -ENOMEM;
 		goto exit;
 	}
@@ -697,13 +702,14 @@
 				b->m.planes[i].reserved[1],
 				b->m.planes[i].length);
 		if (binfo) {
-			pr_err("This memory region has already been prepared\n");
+			dprintk(VIDC_WARN,
+				"This memory region has already been prepared\n");
 			rc = -EINVAL;
 			goto exit;
 		}
 		binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
 		if (!binfo) {
-			pr_err("Out of memory\n");
+			dprintk(VIDC_ERR, "Out of memory\n");
 			rc = -ENOMEM;
 			goto exit;
 		}
@@ -725,7 +731,8 @@
 			vidc_inst->core->resources.io_map[NS_MAP].domain,
 			0);
 			if (!handle) {
-				pr_err("Failed to get device buffer address\n");
+				dprintk(VIDC_ERR,
+					"Failed to get device buffer address\n");
 				kfree(binfo);
 				goto exit;
 			}
@@ -737,7 +744,7 @@
 			binfo->device_addr =
 				handle->device_addr + binfo->buff_off;
 			binfo->handle = handle;
-			pr_debug("Registering buffer: %d, %d, %d\n",
+			dprintk(VIDC_DBG, "Registering buffer: %d, %d, %d\n",
 					b->m.planes[i].reserved[0],
 					b->m.planes[i].reserved[1],
 					b->m.planes[i].length);
@@ -766,7 +773,8 @@
 				b->m.planes[i].reserved[1],
 				b->m.planes[i].length);
 		if (!binfo) {
-			pr_err("This buffer is not registered: %d, %d, %d\n",
+			dprintk(VIDC_ERR,
+				"This buffer is not registered: %d, %d, %d\n",
 				b->m.planes[i].reserved[0],
 				b->m.planes[i].reserved[1],
 				b->m.planes[i].length);
@@ -774,13 +782,14 @@
 			goto err_invalid_buff;
 		}
 		b->m.planes[i].m.userptr = binfo->device_addr;
-		pr_debug("Queueing device address = 0x%x\n",
+		dprintk(VIDC_DBG, "Queueing device address = 0x%x\n",
 				binfo->device_addr);
 		if (binfo->handle) {
 			rc = msm_smem_clean_invalidate(v4l2_inst->mem_client,
 					binfo->handle);
 			if (rc) {
-				pr_err("Failed to clean caches: %d\n", rc);
+				dprintk(VIDC_ERR,
+					"Failed to clean caches: %d\n", rc);
 				goto err_invalid_buff;
 			}
 		}
@@ -892,21 +901,24 @@
 	size_t sz = 0;
 	struct device_node *np = pdev->dev.of_node;
 	if (!of_get_property(np, name, &len)) {
-		pr_err("Failed to read %s from device tree\n",
+		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
 			name);
 		goto fail_read;
 	}
 	sz = len / sizeof(u32);
 	if (sz <= 0) {
-		pr_err("%s not specified in device tree\n", name);
+		dprintk(VIDC_ERR, "%s not specified in device tree\n",
+			name);
 		goto fail_read;
 	}
 	if (sz > size) {
-		pr_err("Not enough memory to store %s values\n", name);
+		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)) {
-		pr_err("error while reading %s from device tree\n",
+		dprintk(VIDC_ERR,
+			"error while reading %s from device tree\n",
 			name);
 		goto fail_read;
 	}
@@ -939,7 +951,8 @@
 				io_map[i].addr_range,
 				(sizeof(io_map[i].addr_range)/sizeof(u32)));
 		if (!len) {
-			pr_err("Error in reading cp address range\n");
+			dprintk(VIDC_ERR,
+				"Error in reading cp address range\n");
 			rc = -EINVAL;
 			break;
 		}
@@ -959,15 +972,15 @@
 		layout.partitions = &partition[0];
 		layout.client_name = io_map[i].name;
 		layout.domain_flags = 0;
-		pr_debug("Registering domain 1 with: %lx, %lx, %s\n",
+		dprintk(VIDC_DBG, "Registering domain 1 with: %lx, %lx, %s\n",
 			partition[0].start, partition[0].size,
 			layout.client_name);
-		pr_debug("Registering domain 2 with: %lx, %lx, %s\n",
+		dprintk(VIDC_DBG, "Registering domain 2 with: %lx, %lx, %s\n",
 			partition[1].start, partition[1].size,
 			layout.client_name);
 		io_map[i].domain = msm_register_domain(&layout);
 		if (io_map[i].domain < 0) {
-			pr_err("Failed to register cp domain\n");
+			dprintk(VIDC_ERR, "Failed to register cp domain\n");
 			rc = -EINVAL;
 			break;
 		}
@@ -987,7 +1000,7 @@
 	int rc = 0;
 	struct core_clock *clock;
 	if (!core) {
-		pr_err("Invalid params: %p\n", core);
+		dprintk(VIDC_ERR, "Invalid params: %p\n", core);
 		return -EINVAL;
 	}
 	clock = core->resources.clock;
@@ -1004,13 +1017,14 @@
 		"load-freq-tbl", (u32 *)clock[VCODEC_CLK].load_freq_tbl,
 		(sizeof(clock[VCODEC_CLK].load_freq_tbl)/sizeof(u32)));
 	clock[VCODEC_CLK].count /= 2;
-	pr_err("NOTE: Count = %d\n", clock[VCODEC_CLK].count);
+	dprintk(VIDC_DBG, "count = %d\n", clock[VCODEC_CLK].count);
 	if (!clock[VCODEC_CLK].count) {
-		pr_err("Failed to read clock frequency\n");
+		dprintk(VIDC_ERR, "Failed to read clock frequency\n");
 		goto fail_init_clocks;
 	}
 	for (i = 0; i <	clock[VCODEC_CLK].count; i++) {
-		pr_err("NOTE: load = %d, freq = %d\n",
+		dprintk(VIDC_DBG,
+				"load = %d, freq = %d\n",
 				clock[VCODEC_CLK].load_freq_tbl[i].load,
 				clock[VCODEC_CLK].load_freq_tbl[i].freq
 			  );
@@ -1021,7 +1035,8 @@
 		if (!cl->clk) {
 			cl->clk = devm_clk_get(&pdev->dev, cl->name);
 			if (IS_ERR_OR_NULL(cl->clk)) {
-				pr_err("Failed to get clock: %s\n", cl->name);
+				dprintk(VIDC_ERR,
+					"Failed to get clock: %s\n", cl->name);
 				rc = PTR_ERR(cl->clk);
 				break;
 			}
@@ -1042,7 +1057,7 @@
 {
 	int i;
 	if (!core) {
-		pr_err("Invalid args\n");
+		dprintk(VIDC_ERR, "Invalid args\n");
 		return;
 	}
 	for (i = 0; i < VCODEC_MAX_CLKS; i++)
@@ -1060,7 +1075,7 @@
 		return -EINVAL;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		pr_err("Failed to get IORESOURCE_MEM\n");
+		dprintk(VIDC_ERR, "Failed to get IORESOURCE_MEM\n");
 		rc = -ENODEV;
 		goto core_init_failed;
 	}
@@ -1068,7 +1083,7 @@
 	core->register_size = resource_size(res);
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
-		pr_err("Failed to get IORESOURCE_IRQ\n");
+		dprintk(VIDC_ERR, "Failed to get IORESOURCE_IRQ\n");
 		rc = -ENODEV;
 		goto core_init_failed;
 	}
@@ -1084,37 +1099,37 @@
 	}
 	rc = msm_vidc_init_clocks(pdev, core);
 	if (rc) {
-		pr_err("Failed to init clocks\n");
+		dprintk(VIDC_ERR, "Failed to init clocks\n");
 		rc = -ENODEV;
 		goto core_init_failed;
 	}
 	core->resources.bus_info.ddr_handle[MSM_VIDC_ENCODER] =
 		msm_bus_scale_register_client(&enc_ddr_bus_data);
 	if (!core->resources.bus_info.ddr_handle[MSM_VIDC_ENCODER]) {
-		pr_err("Failed to register bus scale client\n");
+		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
 		goto fail_register_enc_ddr_bus;
 	}
 	core->resources.bus_info.ddr_handle[MSM_VIDC_DECODER] =
 		msm_bus_scale_register_client(&dec_ddr_bus_data);
 	if (!core->resources.bus_info.ddr_handle[MSM_VIDC_DECODER]) {
-		pr_err("Failed to register bus scale client\n");
+		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
 		goto fail_register_dec_ddr_bus;
 	}
 	core->resources.bus_info.ocmem_handle[MSM_VIDC_ENCODER] =
 		msm_bus_scale_register_client(&enc_ocmem_bus_data);
 	if (!core->resources.bus_info.ocmem_handle[MSM_VIDC_ENCODER]) {
-		pr_err("Failed to register bus scale client\n");
+		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
 		goto fail_register_enc_ocmem;
 	}
 	core->resources.bus_info.ocmem_handle[MSM_VIDC_DECODER] =
 		msm_bus_scale_register_client(&dec_ocmem_bus_data);
 	if (!core->resources.bus_info.ocmem_handle[MSM_VIDC_DECODER]) {
-		pr_err("Failed to register bus scale client\n");
+		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
 		goto fail_register_dec_ocmem;
 	}
 	rc = register_iommu_domains(pdev, core);
 	if (rc) {
-		pr_err("Failed to register iommu domains: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
 		goto fail_register_domains;
 	}
 	ocmem = &core->resources.ocmem;
@@ -1122,8 +1137,8 @@
 	ocmem->handle =
 		ocmem_notifier_register(OCMEM_VIDEO, &ocmem->vidc_ocmem_nb);
 	if (!ocmem->handle) {
-		pr_warn("Failed to register OCMEM notifier.");
-		pr_warn(" Performance will be impacted\n");
+		dprintk(VIDC_WARN, "Failed to register OCMEM notifier.");
+		dprintk(VIDC_WARN, " Performance will be impacted\n");
 	}
 	return rc;
 fail_register_domains:
@@ -1149,21 +1164,21 @@
 	int rc = 0;
 	struct msm_vidc_core *core;
 	unsigned long flags;
-	char debugfs_name[MAX_DEBUGFS_NAME];
 	core = kzalloc(sizeof(*core), GFP_KERNEL);
 	if (!core || !vidc_driver) {
-		pr_err("Failed to allocate memory for device core\n");
+		dprintk(VIDC_ERR,
+			"Failed to allocate memory for device core\n");
 		rc = -ENOMEM;
 		goto err_no_mem;
 	}
 	rc = msm_vidc_initialize_core(pdev, core);
 	if (rc) {
-		pr_err("Failed to init core\n");
+		dprintk(VIDC_ERR, "Failed to init core\n");
 		goto err_v4l2_register;
 	}
 	rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
 	if (rc) {
-		pr_err("Failed to register v4l2 device\n");
+		dprintk(VIDC_ERR, "Failed to register v4l2 device\n");
 		goto err_v4l2_register;
 	}
 	core->vdev[MSM_VIDC_DECODER].vdev.release =
@@ -1174,7 +1189,7 @@
 	rc = video_register_device(&core->vdev[MSM_VIDC_DECODER].vdev,
 					VFL_TYPE_GRABBER, BASE_DEVICE_NUMBER);
 	if (rc) {
-		pr_err("Failed to register video decoder device");
+		dprintk(VIDC_ERR, "Failed to register video decoder device");
 		goto err_dec_register;
 	}
 	video_set_drvdata(&core->vdev[MSM_VIDC_DECODER].vdev, core);
@@ -1187,7 +1202,7 @@
 	rc = video_register_device(&core->vdev[MSM_VIDC_ENCODER].vdev,
 				VFL_TYPE_GRABBER, BASE_DEVICE_NUMBER + 1);
 	if (rc) {
-		pr_err("Failed to register video encoder device");
+		dprintk(VIDC_ERR, "Failed to register video encoder device");
 		goto err_enc_register;
 	}
 	video_set_drvdata(&core->vdev[MSM_VIDC_ENCODER].vdev, core);
@@ -1195,14 +1210,14 @@
 			core->register_base, core->register_size, core->irq,
 			&handle_cmd_response);
 	if (!core->device) {
-		pr_err("Failed to create interrupt handler");
+		dprintk(VIDC_ERR, "Failed to create interrupt handler");
 		goto err_cores_exceeded;
 	}
 
 	spin_lock_irqsave(&vidc_driver->lock, flags);
 	if (vidc_driver->num_cores  + 1 > MSM_VIDC_CORES_MAX) {
 		spin_unlock_irqrestore(&vidc_driver->lock, flags);
-		pr_err("Maximum cores already exist, core_no = %d\n",
+		dprintk(VIDC_ERR, "Maximum cores already exist, core_no = %d\n",
 				vidc_driver->num_cores);
 		goto err_cores_exceeded;
 	}
@@ -1210,9 +1225,8 @@
 	core->id = vidc_driver->num_cores++;
 	list_add_tail(&core->list, &vidc_driver->cores);
 	spin_unlock_irqrestore(&vidc_driver->lock, flags);
-	snprintf(debugfs_name, MAX_DEBUGFS_NAME, "core%d", core->id);
-	core->debugfs_root = debugfs_create_dir(debugfs_name,
-						vidc_driver->debugfs_root);
+	core->debugfs_root = msm_vidc_debugfs_init_core(
+		core, vidc_driver->debugfs_root);
 	pdev->dev.platform_data = core;
 	return rc;
 
@@ -1271,7 +1285,8 @@
 	vidc_driver = kzalloc(sizeof(*vidc_driver),
 						GFP_KERNEL);
 	if (!vidc_driver) {
-		pr_err("Failed to allocate memroy for msm_vidc_drv\n");
+		dprintk(VIDC_ERR,
+			"Failed to allocate memroy for msm_vidc_drv\n");
 		return -ENOMEM;
 	}
 
@@ -1279,11 +1294,13 @@
 	spin_lock_init(&vidc_driver->lock);
 	vidc_driver->debugfs_root = debugfs_create_dir("msm_vidc", NULL);
 	if (!vidc_driver->debugfs_root)
-		pr_err("Failed to create debugfs for msm_vidc\n");
+		dprintk(VIDC_ERR,
+			"Failed to create debugfs for msm_vidc\n");
 
 	rc = platform_driver_register(&msm_vidc_driver);
 	if (rc) {
-		pr_err("Failed to register platform driver\n");
+		dprintk(VIDC_ERR,
+			"Failed to register platform driver\n");
 		kfree(vidc_driver);
 		vidc_driver = NULL;
 	}
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index c0f8014..be2e848 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -17,6 +17,7 @@
 #include "msm_vidc_common.h"
 #include "vidc_hal_api.h"
 #include "msm_smem.h"
+#include "msm_vidc_debug.h"
 
 #define MSM_VDEC_DVC_NAME "msm_vdec_8974"
 #define MAX_PLANES 1
@@ -228,6 +229,14 @@
 		.type = OUTPUT_PORT,
 	},
 	{
+		.name = "VC1 SP",
+		.description = "VC-1 compressed format G",
+		.fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
+		.num_planes = 1,
+		.get_frame_size = get_frame_size_compressed,
+		.type = OUTPUT_PORT,
+	},
+	{
 		.name = "H264",
 		.description = "H264 compressed format",
 		.fourcc = V4L2_PIX_FMT_H264,
@@ -275,13 +284,14 @@
 	struct vb2_queue *q;
 	q = msm_comm_get_vb2q(inst, i);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", i);
+		dprintk(VIDC_ERR,
+			"Failed to find buffer queue for type = %d\n", i);
 		return -EINVAL;
 	}
-	pr_debug("Calling streamon\n");
+	dprintk(VIDC_DBG, "Calling streamon\n");
 	rc = vb2_streamon(q, i);
 	if (rc)
-		pr_err("streamon failed on port: %d\n", i);
+		dprintk(VIDC_ERR, "streamon failed on port: %d\n", i);
 	return rc;
 }
 
@@ -292,13 +302,14 @@
 
 	q = msm_comm_get_vb2q(inst, i);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", i);
+		dprintk(VIDC_ERR,
+			"Failed to find buffer queue for type = %d\n", i);
 		return -EINVAL;
 	}
-	pr_debug("Calling streamoff\n");
+	dprintk(VIDC_DBG, "Calling streamoff\n");
 	rc = vb2_streamoff(q, i);
 	if (rc)
-		pr_err("streamoff failed on port: %d\n", i);
+		dprintk(VIDC_ERR, "streamoff failed on port: %d\n", i);
 	return rc;
 }
 
@@ -313,7 +324,7 @@
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		for (i = 0; i < b->length; i++) {
-			pr_err("device_addr = %ld, size = %d\n",
+			dprintk(VIDC_DBG, "device_addr = %ld, size = %d\n",
 				b->m.planes[i].m.userptr,
 				b->m.planes[i].length);
 			buffer_info.buffer_size = b->m.planes[i].length;
@@ -328,7 +339,8 @@
 				inst->core->resources.io_map[NS_MAP].domain,
 				0, 0);
 				if (!inst->extradata_handle) {
-					pr_err("Failed to allocate extradta memory\n");
+					dprintk(VIDC_ERR,
+						"Failed to allocate extradta memory\n");
 					rc = -ENOMEM;
 					break;
 				}
@@ -339,13 +351,14 @@
 			rc = vidc_hal_session_set_buffers((void *)inst->session,
 					&buffer_info);
 			if (rc) {
-				pr_err("vidc_hal_session_set_buffers failed");
+				dprintk(VIDC_ERR,
+					"vidc_hal_session_set_buffers failed\n");
 				break;
 			}
 		}
 		break;
 	default:
-		pr_err("Buffer type not recognized: %d\n", b->type);
+		dprintk(VIDC_ERR, "Buffer type not recognized: %d\n", b->type);
 		break;
 	}
 	return rc;
@@ -363,7 +376,8 @@
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		for (i = 0; i < b->length; i++) {
-			pr_debug("Release device_addr = %ld, size = %d\n",
+			dprintk(VIDC_DBG,
+				"Release device_addr = %ld, size = %d\n",
 				b->m.planes[i].m.userptr,
 				b->m.planes[i].length);
 			buffer_info.buffer_size = b->m.planes[i].length;
@@ -376,11 +390,12 @@
 			rc = vidc_hal_session_release_buffers(
 				(void *)inst->session, &buffer_info);
 			if (rc)
-				pr_err("vidc_hal_session_release_buffers failed");
+				dprintk(VIDC_ERR,
+					"vidc_hal_session_release_buffers failed\n");
 		}
 		break;
 	default:
-		pr_err("Buffer type not recognized: %d\n", b->type);
+		dprintk(VIDC_ERR, "Buffer type not recognized: %d\n", b->type);
 		break;
 	}
 	return rc;
@@ -392,12 +407,13 @@
 	int rc = 0;
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", b->type);
+		dprintk(VIDC_ERR, "Failed to find buffer queue for type = %d\n"
+			, b->type);
 		return -EINVAL;
 	}
 	rc = vb2_qbuf(q, b);
 	if (rc)
-		pr_err("Failed to qbuf, %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
 	return rc;
 }
 int msm_vdec_dqbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
@@ -406,12 +422,13 @@
 	int rc = 0;
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", b->type);
+		dprintk(VIDC_ERR, "Failed to find buffer queue for type = %d\n"
+			, b->type);
 		return -EINVAL;
 	}
 	rc = vb2_dqbuf(q, b, true);
 	if (rc)
-		pr_err("Failed to dqbuf, %d\n", rc);
+		dprintk(VIDC_WARN, "Failed to dqbuf, %d\n", rc);
 	return rc;
 }
 
@@ -420,18 +437,20 @@
 	struct vb2_queue *q = NULL;
 	int rc = 0;
 	if (!inst || !b) {
-		pr_err("Invalid input, inst = %p, buffer = %p\n", inst, b);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, buffer = %p\n", inst, b);
 		return -EINVAL;
 	}
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", b->type);
+		dprintk(VIDC_ERR, "Failed to find buffer queue for type = %d\n"
+			, b->type);
 		return -EINVAL;
 	}
 
 	rc = vb2_reqbufs(q, b);
 	if (rc)
-		pr_err("Failed to get reqbufs, %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to get reqbufs, %d\n", rc);
 	return rc;
 }
 
@@ -441,7 +460,8 @@
 	int rc = 0;
 	int i;
 	if (!inst || !f) {
-		pr_err("Invalid input, inst = %p, format = %p\n", inst, f);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, format = %p\n", inst, f);
 		return -EINVAL;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
@@ -464,7 +484,7 @@
 				inst->prop.width);
 		}
 	} else {
-		pr_err("Buf type not recognized, type = %d\n",
+		dprintk(VIDC_ERR, "Buf type not recognized, type = %d\n",
 					f->type);
 		rc = -EINVAL;
 	}
@@ -477,7 +497,8 @@
 	int rc = 0;
 	int i;
 	if (!inst || !f) {
-		pr_err("Invalid input, inst = %p, format = %p\n", inst, f);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, format = %p\n", inst, f);
 		return -EINVAL;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
@@ -487,8 +508,9 @@
 			ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
 			CAPTURE_PORT);
 		if (fmt && fmt->type != CAPTURE_PORT) {
-			pr_err("Format: %d not supported on CAPTURE port\n",
-					f->fmt.pix_mp.pixelformat);
+			dprintk(VIDC_ERR,
+				"Format: %d not supported on CAPTURE"
+				"port\n", f->fmt.pix_mp.pixelformat);
 			rc = -EINVAL;
 			goto err_invalid_fmt;
 		}
@@ -499,21 +521,26 @@
 		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
 		frame_sz.width = inst->prop.width;
 		frame_sz.height = inst->prop.height;
-		pr_debug("width = %d, height = %d\n",
-				frame_sz.width, frame_sz.height);
+		dprintk(VIDC_DBG,
+			"width = %d, height = %d\n",
+			frame_sz.width, frame_sz.height);
 		rc = vidc_hal_session_set_property((void *)inst->session,
 				HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
-			pr_err("Failed to set hal property for framesize\n");
+			dprintk(VIDC_ERR,
+				"Failed to set hal property for framesize\n");
 			goto err_invalid_fmt;
 		}
 	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		inst->prop.width = f->fmt.pix_mp.width;
+		inst->prop.height = f->fmt.pix_mp.height;
 		fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
 			ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
 			OUTPUT_PORT);
 		if (fmt && fmt->type != OUTPUT_PORT) {
-			pr_err("Format: %d not supported on OUTPUT port\n",
-					f->fmt.pix_mp.pixelformat);
+			dprintk(VIDC_ERR,
+				"Format: %d not supported on OUTPUT port\n",
+				f->fmt.pix_mp.pixelformat);
 			rc = -EINVAL;
 			goto err_invalid_fmt;
 		}
@@ -530,13 +557,13 @@
 		if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 			rc = msm_comm_try_state(inst, MSM_VIDC_OPEN);
 			if (rc) {
-				pr_err("Failed to open instance\n");
+				dprintk(VIDC_ERR, "Failed to open instance\n");
 				goto err_invalid_fmt;
 			}
 		}
 	} else {
-		pr_err("Buf type not recognized, type = %d\n",
-					f->type);
+		dprintk(VIDC_ERR,
+			"Buf type not recognized, type = %d\n", f->type);
 		rc = -EINVAL;
 	}
 err_invalid_fmt:
@@ -546,7 +573,8 @@
 int msm_vdec_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap)
 {
 	if (!inst || !cap) {
-		pr_err("Invalid input, inst = %p, cap = %p\n", inst, cap);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, cap = %p\n", inst, cap);
 		return -EINVAL;
 	}
 	strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver));
@@ -565,7 +593,8 @@
 	const struct msm_vidc_format *fmt = NULL;
 	int rc = 0;
 	if (!inst || !f) {
-		pr_err("Invalid input, inst = %p, f = %p\n", inst, f);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, f = %p\n", inst, f);
 		return -EINVAL;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
@@ -583,7 +612,7 @@
 				sizeof(f->description));
 		f->pixelformat = fmt->fourcc;
 	} else {
-		pr_err("No more formats found\n");
+		dprintk(VIDC_WARN, "No more formats found\n");
 		rc = -EINVAL;
 	}
 	return rc;
@@ -600,7 +629,7 @@
 	unsigned long flags;
 	struct hal_buffer_requirements *bufreq;
 	if (!q || !q->drv_priv) {
-		pr_err("Invalid input, q = %p\n", q);
+		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
@@ -616,16 +645,16 @@
 		}
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-		pr_debug("Getting bufreqs on capture plane\n");
+		dprintk(VIDC_DBG, "Getting bufreqs on capture plane\n");
 		rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
 		if (rc) {
-			pr_err("Failed to open instance\n");
+			dprintk(VIDC_ERR, "Failed to open instance\n");
 			break;
 		}
-
 		rc = msm_comm_try_get_bufreqs(inst);
 		if (rc) {
-			pr_err("Failed to get buffer requirements: %d\n", rc);
+			dprintk(VIDC_ERR,
+				"Failed to get buffer requirements: %d\n", rc);
 			break;
 		}
 		*num_planes = 1;
@@ -649,8 +678,7 @@
 		else
 			bufreq->buffer_count_actual = *num_buffers ;
 		spin_unlock_irqrestore(&inst->lock, flags);
-
-		pr_debug("count =  %d, size = %d, alignment = %d\n",
+		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,
 				inst->buff_req.buffer[1].buffer_alignment);
@@ -661,7 +689,7 @@
 
 		break;
 	default:
-		pr_err("Invalid q type = %d\n", q->type);
+		dprintk(VIDC_ERR, "Invalid q type = %d\n", q->type);
 		rc = -EINVAL;
 		break;
 	}
@@ -674,23 +702,28 @@
 	unsigned long flags;
 	struct vb2_buf_entry *temp;
 	struct list_head *ptr, *next;
+	inst->in_reconfig = false;
 	rc = msm_comm_set_scratch_buffers(inst);
 	if (rc) {
-		pr_err("Failed to set scratch buffers: %d\n", rc);
+		dprintk(VIDC_ERR,
+			"Failed to set scratch buffers: %d\n", rc);
 		goto fail_start;
 	}
 	rc = msm_comm_set_persist_buffers(inst);
 	if (rc) {
-		pr_err("Failed to set persist buffers: %d\n", rc);
+		dprintk(VIDC_ERR,
+			"Failed to set persist buffers: %d\n", rc);
 		goto fail_start;
 	}
-	if (msm_comm_scale_clocks(inst->core, inst->session_type))
-		pr_warn("Failed to scale clocks. Performance might be impacted\n");
+	if (msm_comm_scale_clocks(inst->core, inst->session_type)) {
+		dprintk(VIDC_WARN,
+			"Failed to scale clocks. Performance might be impacted\n");
+	}
 
 	rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
 	if (rc) {
-		pr_err("Failed to move inst: %p to start done state\n",
-			inst);
+		dprintk(VIDC_ERR,
+			"Failed to move inst: %p to start done state\n", inst);
 		goto fail_start;
 	}
 
@@ -700,7 +733,8 @@
 			temp = list_entry(ptr, struct vb2_buf_entry, list);
 			rc = msm_comm_qbuf(temp->vb);
 			if (rc) {
-				pr_err("Failed to qbuf to hardware\n");
+				dprintk(VIDC_ERR,
+					"Failed to qbuf to hardware\n");
 				break;
 			}
 			list_del(&temp->list);
@@ -718,11 +752,12 @@
 	struct msm_vidc_inst *inst;
 	int rc = 0;
 	if (!q || !q->drv_priv) {
-		pr_err("Invalid input, q = %p\n", q);
+		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
-	pr_debug("Streamon called on: %d capability\n", q->type);
+	dprintk(VIDC_DBG,
+		"Streamon called on: %d capability\n", q->type);
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		if (inst->vb2_bufq[CAPTURE_PORT].streaming)
@@ -733,7 +768,7 @@
 			rc = start_streaming(inst);
 		break;
 	default:
-		pr_err("Q-type is not supported: %d\n", q->type);
+		dprintk(VIDC_ERR, "Q-type is not supported: %d\n", q->type);
 		rc = -EINVAL;
 		break;
 	}
@@ -745,11 +780,11 @@
 	struct msm_vidc_inst *inst;
 	int rc = 0;
 	if (!q || !q->drv_priv) {
-		pr_err("Invalid input, q = %p\n", q);
+		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
-	pr_debug("Streamoff called on: %d capability\n", q->type);
+	dprintk(VIDC_DBG, "Streamoff called on: %d capability\n", q->type);
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		if (!inst->vb2_bufq[CAPTURE_PORT].streaming)
@@ -762,16 +797,20 @@
 				MSM_VIDC_RELEASE_RESOURCES_DONE);
 		break;
 	default:
-		pr_err("Q-type is not supported: %d\n", q->type);
+		dprintk(VIDC_ERR,
+			"Q-type is not supported: %d\n", q->type);
 		rc = -EINVAL;
 		break;
 	}
-	if (msm_comm_scale_clocks(inst->core, inst->session_type))
-		pr_warn("Failed to scale clocks. Power might be impacted\n");
+	if (msm_comm_scale_clocks(inst->core, inst->session_type)) {
+		dprintk(VIDC_WARN,
+			"Failed to scale clocks. Power might be impacted\n");
+	}
 
 	if (rc)
-		pr_err("Failed to move inst: %p, cap = %d to state: %d\n",
-				inst, q->type, MSM_VIDC_RELEASE_RESOURCES_DONE);
+		dprintk(VIDC_ERR,
+			"Failed to move inst: %p, cap = %d to state: %d\n",
+			inst, q->type, MSM_VIDC_RELEASE_RESOURCES_DONE);
 	return rc;
 }
 
@@ -780,70 +819,26 @@
 	int rc;
 	rc = msm_comm_qbuf(vb);
 	if (rc)
-		pr_err("Failed to queue buffer: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to queue buffer: %d\n", rc);
 }
 
 int msm_vdec_cmd(struct msm_vidc_inst *inst, struct v4l2_decoder_cmd *dec)
 {
 	int rc = 0;
-	bool ip_flush = false,
-	     op_flush = false;
-
 	switch (dec->cmd) {
 	case V4L2_DEC_QCOM_CMD_FLUSH:
-		mutex_lock(&inst->sync_lock);
-		ip_flush = dec->flags & V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT;
-		op_flush = dec->flags & V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
-		/* Only support flush on decoder (for now)*/
-		if (inst->session_type == MSM_VIDC_ENCODER) {
-			pr_err("Buffer flushing not supported for encoder\n");
-			rc = -ENOTSUPP;
-			mutex_unlock(&inst->sync_lock);
-			break;
-		}
-
-		/* Certain types of flushes aren't supported such as: */
-		/* 1) Input only flush */
-		if (ip_flush && !op_flush) {
-			pr_err("Input only flush not supported\n");
-			rc = -ENOTSUPP;
-			mutex_unlock(&inst->sync_lock);
-			break;
-		}
-
-		/* 2) Output only flush when in reconfig */
-		if (!ip_flush && op_flush && !inst->in_reconfig) {
-			pr_err("Output only flush only supported when reconfiguring\n");
-			rc = -ENOTSUPP;
-			mutex_unlock(&inst->sync_lock);
-			break;
-		}
-
-		/* Finally flush */
-		if (op_flush && ip_flush)
-			rc = vidc_hal_session_flush(inst->session,
-					HAL_FLUSH_ALL);
-		else if (ip_flush)
-			rc = vidc_hal_session_flush(inst->session,
-					HAL_FLUSH_INPUT);
-		else if (op_flush)
-			rc = vidc_hal_session_flush(inst->session,
-					HAL_FLUSH_OUTPUT);
-		mutex_unlock(&inst->sync_lock);
+		rc = msm_comm_flush(inst, dec->flags);
 		break;
 	case V4L2_DEC_CMD_STOP:
 		rc = msm_comm_try_state(inst, MSM_VIDC_CLOSE_DONE);
-		if (rc)
-			pr_err("Failed to close instance\n");
 		break;
 	default:
-		pr_err("Unknown Decoder Command\n");
+		dprintk(VIDC_ERR, "Unknown Decoder Command\n");
 		rc = -ENOTSUPP;
 		goto exit;
 	}
-
 	if (rc) {
-		pr_err("Failed to exec decoder cmd %d\n", dec->cmd);
+		dprintk(VIDC_ERR, "Failed to exec decoder cmd %d\n", dec->cmd);
 		goto exit;
 	}
 exit:
@@ -867,7 +862,7 @@
 {
 	int rc = 0;
 	if (!inst) {
-		pr_err("Invalid input = %p\n", inst);
+		dprintk(VIDC_ERR, "Invalid input = %p\n", inst);
 		return -EINVAL;
 	}
 	inst->fmts[OUTPUT_PORT] = &vdec_formats[1];
@@ -894,8 +889,8 @@
 	rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
 
 	if (rc) {
-		pr_err("Failed to move inst: %p to start done state\n",
-				inst);
+		dprintk(VIDC_ERR,
+			"Failed to move inst: %p to start done state\n", inst);
 		goto failed_open_done;
 	}
 
@@ -954,16 +949,17 @@
 		break;
 		}
 	if (property_id) {
-		pr_debug("Control: HAL property=%d,ctrl_id=%d,ctrl_value=%d\n",
-			   property_id,
-			   msm_vdec_ctrls[control_idx].id,
-			   control.value);
+		dprintk(VIDC_DBG,
+			"Control: HAL property=%d,ctrl_id=%d,ctrl_value=%d\n",
+			property_id,
+			msm_vdec_ctrls[control_idx].id,
+			control.value);
 			rc = vidc_hal_session_set_property((void *)
 				inst->session, property_id,
 					pdata);
 		}
 	if (rc)
-		pr_err("Failed to set hal property for framesize\n");
+		dprintk(VIDC_ERR, "Failed to set hal property for framesize\n");
 
 failed_open_done:
 
@@ -1002,7 +998,7 @@
 	ret_val = v4l2_ctrl_handler_init(&inst->ctrl_handler, NUM_CTRLS);
 
 	if (ret_val) {
-		pr_err("CTRL ERR: Control handler init failed, %d\n",
+		dprintk(VIDC_ERR, "CTRL ERR: Control handler init failed, %d\n",
 				inst->ctrl_handler.error);
 		return ret_val;
 	}
@@ -1050,7 +1046,8 @@
 	}
 	ret_val = inst->ctrl_handler.error;
 	if (ret_val)
-		pr_err("CTRL ERR: Error adding ctrls to ctrl handle, %d\n",
-				inst->ctrl_handler.error);
+		dprintk(VIDC_ERR,
+			"Error adding ctrls to ctrl handle, %d\n",
+			inst->ctrl_handler.error);
 	return ret_val;
 }
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 1b1a0c5..6c0f224 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -16,11 +16,12 @@
 #include "msm_vidc_common.h"
 #include "vidc_hal_api.h"
 #include "msm_smem.h"
+#include "msm_vidc_debug.h"
 
 #define MSM_VENC_DVC_NAME "msm_venc_8974"
 #define DEFAULT_HEIGHT 720
 #define DEFAULT_WIDTH 1280
-#define MIN_NUM_OUTPUT_BUFFERS 2
+#define MIN_NUM_OUTPUT_BUFFERS 4
 #define MAX_NUM_OUTPUT_BUFFERS 8
 #define MIN_BIT_RATE 64000
 #define MAX_BIT_RATE 160000000
@@ -565,7 +566,7 @@
 	struct hal_frame_size frame_sz;
 	unsigned long flags;
 	if (!q || !q->drv_priv) {
-		pr_err("Invalid input, q = %p\n", q);
+		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
@@ -583,37 +584,40 @@
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
 		if (rc) {
-			pr_err("Failed to open instance\n");
+			dprintk(VIDC_ERR, "Failed to open instance\n");
 			break;
 		}
 		frame_sz.buffer_type = HAL_BUFFER_INPUT;
 		frame_sz.width = inst->prop.width;
 		frame_sz.height = inst->prop.height;
-		pr_debug("width = %d, height = %d\n",
+		dprintk(VIDC_DBG, "width = %d, height = %d\n",
 				frame_sz.width, frame_sz.height);
 		rc = vidc_hal_session_set_property((void *)inst->session,
 				HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
-			pr_err("Failed to set framesize for Output port\n");
+			dprintk(VIDC_ERR,
+				"Failed to set framesize for Output port\n");
 			break;
 		}
 		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
 		rc = vidc_hal_session_set_property((void *)inst->session,
 				HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
-			pr_err("Failed to set framesize for Capture port\n");
+			dprintk(VIDC_ERR,
+				"Failed to set hal property for framesize\n");
 			break;
 		}
 		rc = msm_comm_try_get_bufreqs(inst);
 		if (rc) {
-			pr_err("Failed to get buffer requirements: %d\n", rc);
+			dprintk(VIDC_ERR,
+				"Failed to get buffer requirements: %d\n", rc);
 			break;
 		}
 		*num_planes = 1;
 		spin_lock_irqsave(&inst->lock, flags);
 		*num_buffers = inst->buff_req.buffer[0].buffer_count_actual;
 		spin_unlock_irqrestore(&inst->lock, flags);
-		pr_debug("size = %d, alignment = %d, count = %d\n",
+		dprintk(VIDC_DBG, "size = %d, alignment = %d, count = %d\n",
 				inst->buff_req.buffer[0].buffer_size,
 				inst->buff_req.buffer[0].buffer_alignment,
 				inst->buff_req.buffer[0].buffer_count_actual);
@@ -624,7 +628,7 @@
 
 		break;
 	default:
-		pr_err("Invalid q type = %d\n", q->type);
+		dprintk(VIDC_ERR, "Invalid q type = %d\n", q->type);
 		rc = -EINVAL;
 		break;
 	}
@@ -639,26 +643,29 @@
 	struct list_head *ptr, *next;
 	rc = msm_comm_try_get_bufreqs(inst);
 	if (rc) {
-		pr_err("Failed to get Buffer Requirements : %d\n", rc);
+		dprintk(VIDC_ERR,
+			"Failed to get Buffer Requirements : %d\n", rc);
 		goto fail_start;
 	}
 	rc = msm_comm_set_scratch_buffers(inst);
 	if (rc) {
-		pr_err("Failed to set scratch buffers: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to set scratch buffers: %d\n", rc);
 		goto fail_start;
 	}
 	rc = msm_comm_set_persist_buffers(inst);
 	if (rc) {
-		pr_err("Failed to set persist buffers: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to set persist buffers: %d\n", rc);
 		goto fail_start;
 	}
-	if (msm_comm_scale_clocks(inst->core, inst->session_type))
-		pr_warn("Failed to scale clocks. Performance might be impacted\n");
+	if (msm_comm_scale_clocks(inst->core, inst->session_type)) {
+		dprintk(VIDC_WARN,
+			"Failed to scale clocks. Performance might be impacted\n");
+	}
 
 	rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
 	if (rc) {
-		pr_err("Failed to move inst: %p to start done state\n",
-				inst);
+		dprintk(VIDC_ERR,
+			"Failed to move inst: %p to start done state\n", inst);
 		goto fail_start;
 	}
 	spin_lock_irqsave(&inst->lock, flags);
@@ -667,7 +674,8 @@
 			temp = list_entry(ptr, struct vb2_buf_entry, list);
 			rc = msm_comm_qbuf(temp->vb);
 			if (rc) {
-				pr_err("Failed to qbuf to hardware\n");
+				dprintk(VIDC_ERR,
+					"Failed to qbuf to hardware\n");
 				break;
 			}
 			list_del(&temp->list);
@@ -685,11 +693,11 @@
 	struct msm_vidc_inst *inst;
 	int rc = 0;
 	if (!q || !q->drv_priv) {
-		pr_err("Invalid input, q = %p\n", q);
+		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
-	pr_debug("Streamon called on: %d capability\n", q->type);
+	dprintk(VIDC_DBG, "Streamon called on: %d capability\n", q->type);
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		if (inst->vb2_bufq[CAPTURE_PORT].streaming)
@@ -700,7 +708,7 @@
 			rc = start_streaming(inst);
 		break;
 	default:
-		pr_err("Q-type is not supported: %d\n", q->type);
+		dprintk(VIDC_ERR, "Q-type is not supported: %d\n", q->type);
 		rc = -EINVAL;
 		break;
 	}
@@ -712,11 +720,11 @@
 	struct msm_vidc_inst *inst;
 	int rc = 0;
 	if (!q || !q->drv_priv) {
-		pr_err("Invalid input, q = %p\n", q);
+		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
-	pr_debug("Streamoff called on: %d capability\n", q->type);
+	dprintk(VIDC_DBG, "Streamoff called on: %d capability\n", q->type);
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		break;
@@ -724,16 +732,19 @@
 		rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
 		break;
 	default:
-		pr_err("Q-type is not supported: %d\n", q->type);
+		dprintk(VIDC_ERR, "Q-type is not supported: %d\n", q->type);
 		rc = -EINVAL;
 		break;
 	}
-	if (msm_comm_scale_clocks(inst->core, inst->session_type))
-		pr_warn("Failed to scale clocks. Power might be impacted\n");
+	if (msm_comm_scale_clocks(inst->core, inst->session_type)) {
+		dprintk(VIDC_WARN,
+			"Failed to scale clocks. Power might be impacted\n");
+	}
 
 	if (rc)
-		pr_err("Failed to move inst: %p, cap = %d to state: %d\n",
-				inst, q->type, MSM_VIDC_CLOSE_DONE);
+		dprintk(VIDC_ERR,
+			"Failed to move inst: %p, cap = %d to state: %d\n",
+			inst, q->type, MSM_VIDC_CLOSE_DONE);
 	return rc;
 }
 
@@ -742,7 +753,7 @@
 	int rc;
 	rc = msm_comm_qbuf(vb);
 	if (rc)
-		pr_err("Failed to queue buffer: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to queue buffer: %d\n", rc);
 }
 
 static const struct vb2_ops msm_venc_vb2q_ops = {
@@ -774,7 +785,6 @@
 	struct hal_intra_refresh intra_refresh;
 	struct hal_multi_slice_control multi_slice_control;
 	struct hal_h264_db_control h264_db_control;
-	u32 control_idx = 0;
 	u32 property_id = 0;
 	u32 property_val = 0;
 	void *pdata;
@@ -782,8 +792,8 @@
 					struct msm_vidc_inst, ctrl_handler);
 	rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
 	if (rc) {
-		pr_err("Failed to move inst: %p to start done state\n",
-				inst);
+		dprintk(VIDC_ERR,
+			"Failed to move inst: %p to start done state\n", inst);
 		goto failed_open_done;
 	}
 	control.id = ctrl->id;
@@ -939,7 +949,7 @@
 		venc_h264_profile_level.profile = control.value;
 		profile_level.level = venc_h264_profile_level.level;
 		pdata = &profile_level;
-		pr_debug("\nprofile: %d\n",
+		dprintk(VIDC_DBG, "\nprofile: %d\n",
 			   profile_level.profile);
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
@@ -1003,7 +1013,7 @@
 		profile_level.profile = venc_h264_profile_level.profile;
 		pdata = &profile_level;
 		pdata = &profile_level;
-		pr_debug("\nLevel: %d\n",
+		dprintk(VIDC_DBG, "\nLevel: %d\n",
 			   profile_level.level);
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE:
@@ -1187,24 +1197,25 @@
 			HAL_PARAM_VENC_H264_DEBLOCK_CONTROL;
 		h264_db_control.slice_alpha_offset = control.value;
 		pdata = &h264_db_control;
+		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
 		property_id =
 			HAL_PARAM_VENC_H264_DEBLOCK_CONTROL;
 		h264_db_control.slice_beta_offset = control.value;
 		pdata = &h264_db_control;
+		break;
 	default:
 		break;
 	}
 	if (property_id) {
-		pr_debug("Control: HAL property=%d,ctrl_id=%d,ctrl_value=%d\n",
+		dprintk(VIDC_DBG, "Control: HAL property=%d,ctrl_value=%d\n",
 				property_id,
-				msm_venc_ctrls[control_idx].id,
 				control.value);
 		rc = vidc_hal_session_set_property((void *)inst->session,
 				property_id, pdata);
 	}
 	if (rc)
-		pr_err("Failed to set hal property for framesize\n");
+		dprintk(VIDC_ERR, "Failed to set hal property for framesize\n");
 failed_open_done:
 	return rc;
 }
@@ -1228,7 +1239,7 @@
 {
 	int rc = 0;
 	if (!inst) {
-		pr_err("Invalid input = %p\n", inst);
+		dprintk(VIDC_ERR, "Invalid input = %p\n", inst);
 		return -EINVAL;
 	}
 	inst->fmts[CAPTURE_PORT] = &venc_formats[1];
@@ -1251,16 +1262,25 @@
 int msm_venc_cmd(struct msm_vidc_inst *inst, struct v4l2_encoder_cmd *enc)
 {
 	int rc = 0;
-	rc = msm_comm_try_state(inst, MSM_VIDC_CLOSE_DONE);
+	switch (enc->cmd) {
+	case V4L2_ENC_QCOM_CMD_FLUSH:
+		rc = msm_comm_flush(inst, enc->flags);
+		break;
+	case V4L2_ENC_CMD_STOP:
+		rc = msm_comm_try_state(inst, MSM_VIDC_CLOSE_DONE);
+		break;
+	}
 	if (rc)
-		pr_err("Failed to close instance\n");
+		dprintk(VIDC_ERR,
+			"Command: %d failed with rc = %d\n", enc->cmd, rc);
 	return rc;
 }
 
 int msm_venc_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap)
 {
 	if (!inst || !cap) {
-		pr_err("Invalid input, inst = %p, cap = %p\n", inst, cap);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, cap = %p\n", inst, cap);
 		return -EINVAL;
 	}
 	strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver));
@@ -1279,7 +1299,8 @@
 	const struct msm_vidc_format *fmt = NULL;
 	int rc = 0;
 	if (!inst || !f) {
-		pr_err("Invalid input, inst = %p, f = %p\n", inst, f);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, f = %p\n", inst, f);
 		return -EINVAL;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
@@ -1297,7 +1318,7 @@
 				sizeof(f->description));
 		f->pixelformat = fmt->fourcc;
 	} else {
-		pr_err("No more formats found\n");
+		dprintk(VIDC_ERR, "No more formats found\n");
 		rc = -EINVAL;
 	}
 	return rc;
@@ -1309,7 +1330,8 @@
 	int rc = 0;
 	int i;
 	if (!inst || !f) {
-		pr_err("Invalid input, inst = %p, format = %p\n", inst, f);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, format = %p\n", inst, f);
 		return -EINVAL;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
@@ -1317,8 +1339,9 @@
 			ARRAY_SIZE(venc_formats), f->fmt.pix_mp.pixelformat,
 			CAPTURE_PORT);
 		if (fmt && fmt->type != CAPTURE_PORT) {
-			pr_err("Format: %d not supported on CAPTURE port\n",
-					f->fmt.pix_mp.pixelformat);
+			dprintk(VIDC_ERR,
+				"Format: %d not supported on CAPTURE port\n",
+				f->fmt.pix_mp.pixelformat);
 			rc = -EINVAL;
 			goto exit;
 		}
@@ -1329,8 +1352,9 @@
 			ARRAY_SIZE(venc_formats), f->fmt.pix_mp.pixelformat,
 			OUTPUT_PORT);
 		if (fmt && fmt->type != OUTPUT_PORT) {
-			pr_err("Format: %d not supported on OUTPUT port\n",
-					f->fmt.pix_mp.pixelformat);
+			dprintk(VIDC_ERR,
+				"Format: %d not supported on OUTPUT port\n",
+				f->fmt.pix_mp.pixelformat);
 			rc = -EINVAL;
 			goto exit;
 		}
@@ -1347,12 +1371,12 @@
 		if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 			rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
 			if (rc) {
-				pr_err("Failed to open instance\n");
+				dprintk(VIDC_ERR, "Failed to open instance\n");
 				goto exit;
 			}
 		}
 	} else {
-		pr_err("Buf type not recognized, type = %d\n",
+		dprintk(VIDC_ERR, "Buf type not recognized, type = %d\n",
 					f->type);
 		rc = -EINVAL;
 	}
@@ -1366,7 +1390,8 @@
 	int rc = 0;
 	int i;
 	if (!inst || !f) {
-		pr_err("Invalid input, inst = %p, format = %p\n", inst, f);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, format = %p\n", inst, f);
 		return -EINVAL;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
@@ -1385,8 +1410,8 @@
 					inst->prop.width);
 		}
 	} else {
-		pr_err("Buf type not recognized, type = %d\n",
-					f->type);
+		dprintk(VIDC_ERR,
+			"Buf type not recognized, type = %d\n",	f->type);
 		rc = -EINVAL;
 	}
 	return rc;
@@ -1397,18 +1422,20 @@
 	struct vb2_queue *q = NULL;
 	int rc = 0;
 	if (!inst || !b) {
-		pr_err("Invalid input, inst = %p, buffer = %p\n", inst, b);
+		dprintk(VIDC_ERR,
+			"Invalid input, inst = %p, buffer = %p\n", inst, b);
 		return -EINVAL;
 	}
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", b->type);
+		dprintk(VIDC_ERR,
+		"Failed to find buffer queue for type = %d\n", b->type);
 		return -EINVAL;
 	}
 
 	rc = vb2_reqbufs(q, b);
 	if (rc)
-		pr_err("Failed to get reqbufs, %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to get reqbufs, %d\n", rc);
 	return rc;
 }
 
@@ -1424,7 +1451,8 @@
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		for (i = 0; i < b->length; i++) {
-			pr_debug("device_addr = %ld, size = %d\n",
+			dprintk(VIDC_DBG,
+				"device_addr = %ld, size = %d\n",
 				b->m.planes[i].m.userptr,
 				b->m.planes[i].length);
 			buffer_info.buffer_size = b->m.planes[i].length;
@@ -1437,11 +1465,13 @@
 			rc = vidc_hal_session_set_buffers((void *)inst->session,
 					&buffer_info);
 			if (rc)
-				pr_err("vidc_hal_session_set_buffers failed");
+				dprintk(VIDC_ERR,
+					"vidc_hal_session_set_buffers failed");
 		}
 		break;
 	default:
-		pr_err("Buffer type not recognized: %d\n", b->type);
+		dprintk(VIDC_ERR,
+			"Buffer type not recognized: %d\n", b->type);
 		break;
 	}
 	return rc;
@@ -1453,12 +1483,13 @@
 	int rc = 0;
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", b->type);
+		dprintk(VIDC_ERR,
+			"Failed to find buffer queue for type = %d\n", b->type);
 		return -EINVAL;
 	}
 	rc = vb2_qbuf(q, b);
 	if (rc)
-		pr_err("Failed to qbuf, %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
 	return rc;
 }
 
@@ -1468,12 +1499,13 @@
 	int rc = 0;
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", b->type);
+		dprintk(VIDC_ERR,
+			"Failed to find buffer queue for type = %d\n", b->type);
 		return -EINVAL;
 	}
 	rc = vb2_dqbuf(q, b, true);
 	if (rc)
-		pr_err("Failed to dqbuf, %d\n", rc);
+		dprintk(VIDC_DBG, "Failed to dqbuf, %d\n", rc);
 	return rc;
 }
 
@@ -1483,13 +1515,14 @@
 	struct vb2_queue *q;
 	q = msm_comm_get_vb2q(inst, i);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", i);
+		dprintk(VIDC_ERR,
+			"Failed to find buffer queue for type = %d\n", i);
 		return -EINVAL;
 	}
-	pr_debug("Calling streamon\n");
+	dprintk(VIDC_DBG, "Calling streamon\n");
 	rc = vb2_streamon(q, i);
 	if (rc)
-		pr_err("streamon failed on port: %d\n", i);
+		dprintk(VIDC_ERR, "streamon failed on port: %d\n", i);
 	return rc;
 }
 
@@ -1499,13 +1532,14 @@
 	struct vb2_queue *q;
 	q = msm_comm_get_vb2q(inst, i);
 	if (!q) {
-		pr_err("Failed to find buffer queue for type = %d\n", i);
+		dprintk(VIDC_ERR,
+			"Failed to find buffer queue for type = %d\n", i);
 		return -EINVAL;
 	}
-	pr_debug("Calling streamoff\n");
+	dprintk(VIDC_DBG, "Calling streamoff on port: %d\n", i);
 	rc = vb2_streamoff(q, i);
 	if (rc)
-		pr_err("streamoff failed on port: %d\n", i);
+		dprintk(VIDC_ERR, "streamoff failed on port: %d\n", i);
 	return rc;
 }
 
@@ -1517,7 +1551,7 @@
 	int ret_val = 0;
 	ret_val = v4l2_ctrl_handler_init(&inst->ctrl_handler, NUM_CTRLS);
 	if (ret_val) {
-		pr_err("CTRL ERR: Control handler init failed, %d\n",
+		dprintk(VIDC_ERR, "CTRL ERR: Control handler init failed, %d\n",
 			inst->ctrl_handler.error);
 		return ret_val;
 	}
@@ -1559,7 +1593,8 @@
 	}
 	ret_val = inst->ctrl_handler.error;
 	if (ret_val)
-		pr_err("CTRL ERR: Error adding ctrls to ctrl handle, %d\n",
-				inst->ctrl_handler.error);
+		dprintk(VIDC_ERR,
+			"CTRL ERR: Error adding ctrls to ctrl handle, %d\n",
+			inst->ctrl_handler.error);
 	return ret_val;
 }
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 7c9b6db..449dab2 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -14,10 +14,12 @@
 #include <linux/slab.h>
 #include <media/msm_vidc.h>
 #include "msm_vidc_internal.h"
+#include "msm_vidc_debug.h"
 #include "msm_vdec.h"
 #include "msm_venc.h"
 #include "msm_vidc_common.h"
 #include "msm_smem.h"
+#include <linux/delay.h>
 
 int msm_vidc_poll(void *instance, struct file *filp,
 		struct poll_table_struct *wait)
@@ -215,7 +217,7 @@
 	} else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		q = &inst->vb2_bufq[OUTPUT_PORT];
 	} else {
-		pr_err("buf_type = %d not recognised\n", type);
+		dprintk(VIDC_ERR, "buf_type = %d not recognised\n", type);
 		return -EINVAL;
 	}
 	q->type = type;
@@ -239,13 +241,14 @@
 	int i = 0;
 	if (core_id >= MSM_VIDC_CORES_MAX ||
 			session_type >= MSM_VIDC_MAX_DEVICES) {
-		pr_err("Invalid input, core_id = %d, session = %d\n",
+		dprintk(VIDC_ERR, "Invalid input, core_id = %d, session = %d\n",
 			core_id, session_type);
 		goto err_invalid_core;
 	}
 	core = get_vidc_core(core_id);
 	if (!core) {
-		pr_err("Failed to find core for core_id = %d\n", core_id);
+		dprintk(VIDC_ERR,
+			"Failed to find core for core_id = %d\n", core_id);
 		goto err_invalid_core;
 	}
 
@@ -263,7 +266,7 @@
 	}
 	inst->mem_client = msm_smem_new_client(SMEM_ION);
 	if (!inst->mem_client) {
-		pr_err("Failed to create memory client\n");
+		dprintk(VIDC_ERR, "Failed to create memory client\n");
 		goto fail_mem_client;
 	}
 	if (session_type == MSM_VIDC_DECODER) {
@@ -276,20 +279,25 @@
 	rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
 			session_type);
 	if (rc) {
-		pr_err("Failed to initialize vb2 queue on capture port\n");
+		dprintk(VIDC_ERR,
+			"Failed to initialize vb2 queue on capture port\n");
 		goto fail_init;
 	}
 	rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
 			session_type);
 	if (rc) {
-		pr_err("Failed to initialize vb2 queue on capture port\n");
+		dprintk(VIDC_ERR,
+			"Failed to initialize vb2 queue on capture port\n");
 		goto fail_init;
 	}
 	rc = msm_comm_try_state(inst, MSM_VIDC_CORE_INIT);
 	if (rc) {
-		pr_err("Failed to move video instance to init state\n");
+		dprintk(VIDC_ERR,
+			"Failed to move video instance to init state\n");
 		goto fail_init;
 	}
+	inst->debugfs_root =
+		msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
 	spin_lock_irqsave(&core->lock, flags);
 	list_add_tail(&inst->list, &core->instances);
 	spin_unlock_irqrestore(&core->lock, flags);
@@ -341,6 +349,7 @@
 			msm_smem_free(inst->mem_client, inst->extradata_handle);
 		spin_unlock_irqrestore(&inst->lock, flags);
 		msm_smem_delete_client(inst->mem_client);
+		debugfs_remove_recursive(inst->debugfs_root);
 	}
 }
 
@@ -361,8 +370,9 @@
 	mutex_unlock(&core->sync_lock);
 	rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
 	if (rc)
-		pr_err("Failed to move video instance to uninit state\n");
+		dprintk(VIDC_ERR,
+			"Failed to move video instance to uninit state\n");
 	cleanup_instance(inst);
-	pr_debug("Closed the instance\n");
+	dprintk(VIDC_DBG, "Closed the instance\n");
 	return 0;
 }
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 3f7e333..5b83cfb 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -22,6 +22,7 @@
 #include "msm_vidc_common.h"
 #include "vidc_hal_api.h"
 #include "msm_smem.h"
+#include "msm_vidc_debug.h"
 
 #define HW_RESPONSE_TIMEOUT (5 * 60 * 1000)
 
@@ -62,11 +63,13 @@
 {
 	int num_rows = sizeof(bus_table)/(sizeof(u32));
 	int i;
-	for (i = num_rows - 1; i > 0; i--) {
+	if (!load)
+		return 0;
+	for (i = num_rows - 1; i > 1; i--) {
 		if (load >= bus_table[i])
 			break;
 	}
-	pr_debug("Required bus = %d\n", i);
+	dprintk(VIDC_DBG, "Required bus = %d\n", i);
 	return i;
 }
 
@@ -77,7 +80,7 @@
 	int num_mbs_per_sec = 0;
 	unsigned long flags;
 	if (!core) {
-		pr_err("Invalid args: %p\n", core);
+		dprintk(VIDC_ERR, "Invalid args: %p\n", core);
 		return -EINVAL;
 	}
 	list_for_each_entry(inst, &core->instances, list) {
@@ -105,7 +108,7 @@
 			break;
 		ret = table[i].freq;
 	}
-	pr_debug("Required clock rate = %lu\n", ret);
+	dprintk(VIDC_INFO, "Required clock rate = %lu\n", ret);
 	return ret;
 }
 
@@ -114,7 +117,7 @@
 	int load;
 	int rc = 0;
 	if (!core || type >= MSM_VIDC_MAX_DEVICES) {
-		pr_err("Invalid args: %p, %d\n", core, type);
+		dprintk(VIDC_ERR, "Invalid args: %p, %d\n", core, type);
 		return -EINVAL;
 	}
 	load = msm_comm_get_load(core, type);
@@ -122,14 +125,14 @@
 			core->resources.bus_info.ddr_handle[type],
 			get_bus_vector(load));
 	if (rc) {
-		pr_err("Failed to scale bus: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
 		goto fail_scale_bus;
 	}
 	rc = msm_bus_scale_client_update_request(
 			core->resources.bus_info.ocmem_handle[type],
 			get_bus_vector(load));
 	if (rc) {
-		pr_err("Failed to scale bus: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
 		goto fail_scale_bus;
 	}
 fail_scale_bus:
@@ -142,7 +145,7 @@
 	int found = 0;
 	unsigned long flags;
 	if (core_id > MSM_VIDC_CORES_MAX) {
-		pr_err("Core id = %d is greater than max = %d\n",
+		dprintk(VIDC_ERR, "Core id = %d is greater than max = %d\n",
 			core_id, MSM_VIDC_CORES_MAX);
 		return NULL;
 	}
@@ -170,13 +173,15 @@
 		dev = msm_iommu_get_ctx(io_map->ctx);
 		domain = msm_get_iommu_domain(io_map->domain);
 		if (IS_ERR_OR_NULL(domain)) {
-			pr_err("Failed to get domain: %s\n", io_map->name);
+			dprintk(VIDC_ERR,
+				"Failed to get domain: %s\n", io_map->name);
 			rc = PTR_ERR(domain);
 			break;
 		}
 		rc = iommu_attach_device(domain, dev);
 		if (rc) {
-			pr_err("IOMMU attach failed: %s\n", io_map->name);
+			dprintk(VIDC_ERR,
+				"IOMMU attach failed: %s\n", io_map->name);
 			break;
 		}
 	}
@@ -200,7 +205,7 @@
 	struct iommu_info *io_map;
 	int i;
 	if (!core) {
-		pr_err("Invalid paramter: %p\n", core);
+		dprintk(VIDC_ERR, "Invalid paramter: %p\n", core);
 		return;
 	}
 	for (i = 0; i < MAX_MAP; i++) {
@@ -217,7 +222,7 @@
 {
 	int i, k = 0;
 	if (!fmt || index < 0) {
-		pr_err("Invalid inputs, fmt = %p, index = %d\n",
+		dprintk(VIDC_ERR, "Invalid inputs, fmt = %p, index = %d\n",
 						fmt, index);
 		return NULL;
 	}
@@ -229,7 +234,7 @@
 		k++;
 	}
 	if (i == size) {
-		pr_err("Format not found\n");
+		dprintk(VIDC_WARN, "Format not found\n");
 		return NULL;
 	}
 	return &fmt[i];
@@ -239,7 +244,7 @@
 {
 	int i;
 	if (!fmt) {
-		pr_err("Invalid inputs, fmt = %p\n", fmt);
+		dprintk(VIDC_ERR, "Invalid inputs, fmt = %p\n", fmt);
 		return NULL;
 	}
 	for (i = 0; i < size; i++) {
@@ -247,7 +252,7 @@
 				break;
 	}
 	if (i == size) {
-		pr_err("Format not found\n");
+		dprintk(VIDC_WARN, "Format not found\n");
 		return NULL;
 	}
 	return &fmt[i];
@@ -270,20 +275,21 @@
 	struct vidc_hal_sys_init_done *sys_init_msg;
 	int index = SYS_MSG_INDEX(cmd);
 	if (!response) {
-		pr_err("Failed to get valid response for sys init\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for sys init\n");
 		return;
 	}
 	core = get_vidc_core(response->device_id);
 	if (!core) {
-		pr_err("Wrong device_id received\n");
+		dprintk(VIDC_ERR, "Wrong device_id received\n");
 		return;
 	}
-	pr_debug("index = %d\n", index);
-	pr_debug("ptr = %p\n", &(core->completions[index]));
+	dprintk(VIDC_DBG, "index = %d\n", index);
+	dprintk(VIDC_DBG, "ptr = %p\n", &(core->completions[index]));
 	complete(&(core->completions[index]));
 	sys_init_msg = response->data;
 	if (!sys_init_msg) {
-		pr_err("sys_init_done message not proper\n");
+		dprintk(VIDC_ERR, "sys_init_done message not proper\n");
 		return;
 	}
 }
@@ -294,12 +300,13 @@
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_core *core;
 	if (!response) {
-		pr_err("Failed to get valid response for sys init\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for sys init\n");
 		return;
 	}
 	core = get_vidc_core(response->device_id);
 	if (!core) {
-		pr_err("Wrong device_id received\n");
+		dprintk(VIDC_ERR, "Wrong device_id received\n");
 		return;
 	}
 	complete(&core->completions[SYS_MSG_INDEX(cmd)]);
@@ -310,7 +317,7 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&inst->lock, flags);
-	pr_debug("Moved inst: %p from state: %d to state: %d\n",
+	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);
@@ -320,7 +327,7 @@
 		struct msm_vidc_inst *inst)
 {
 	if (!inst) {
-		pr_err("Invalid(%p) instance id\n", inst);
+		dprintk(VIDC_ERR, "Invalid(%p) instance id\n", inst);
 		return -EINVAL;
 	}
 	complete(&inst->completions[SESSION_MSG_INDEX(cmd)]);
@@ -335,7 +342,7 @@
 		&inst->completions[SESSION_MSG_INDEX(cmd)],
 		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
 	if (!rc) {
-		pr_err("Wait interrupted or timeout: %d\n", rc);
+		dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
 		rc = -EIO;
 	} else {
 		rc = 0;
@@ -350,10 +357,11 @@
 {
 	int rc = 0;
 	if (IS_ALREADY_IN_STATE(flipped_state, desired_state)) {
-		pr_err("inst: %p is already in state: %d\n", inst, inst->state);
+		dprintk(VIDC_INFO, "inst: %p is already in state: %d\n",
+						inst, inst->state);
 		goto err_same_state;
 	}
-	pr_debug("Waiting for hal_cmd: %d\n", hal_cmd);
+	dprintk(VIDC_DBG, "Waiting for hal_cmd: %d\n", hal_cmd);
 	rc = wait_for_sess_signal_receipt(inst, hal_cmd);
 	if (!rc)
 		change_inst_state(inst, desired_state);
@@ -369,7 +377,8 @@
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
 	} else {
-		pr_err("Failed to get valid response for session init\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for session init\n");
 	}
 }
 
@@ -401,7 +410,8 @@
 		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 		return;
 	} else {
-		pr_err("Failed to get valid response for event_change\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for event_change\n");
 	}
 }
 
@@ -412,7 +422,8 @@
 	unsigned long flags;
 	int i;
 	if (!response || !response->data) {
-		pr_err("Failed to get valid response for prop info\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for prop info\n");
 		return;
 	}
 	inst = (struct msm_vidc_inst *)response->session_id;
@@ -421,7 +432,8 @@
 			sizeof(struct buffer_requirements));
 	spin_unlock_irqrestore(&inst->lock, flags);
 	for (i = 0; i < 8; i++) {
-		pr_err("NOTE: buffer type: %d, count : %d, size: %d\n",
+		dprintk(VIDC_DBG,
+			"buffer type: %d, count : %d, size: %d\n",
 			inst->buff_req.buffer[i].buffer_type,
 			inst->buff_req.buffer[i].buffer_count_actual,
 			inst->buff_req.buffer[i].buffer_size);
@@ -436,7 +448,8 @@
 	if (response)
 		inst = (struct msm_vidc_inst *)response->session_id;
 	else
-		pr_err("Failed to get valid response for load resource\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for load resource\n");
 }
 
 static void handle_start_done(enum command_response cmd, void *data)
@@ -447,7 +460,8 @@
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
 	} else {
-		pr_err("Failed to get valid response for start\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for start\n");
 	}
 }
 
@@ -459,7 +473,8 @@
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
 	} else {
-		pr_err("Failed to get valid response for stop\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for stop\n");
 	}
 }
 
@@ -471,7 +486,8 @@
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
 	} else {
-		pr_err("Failed to get valid response for release resource\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for release resource\n");
 	}
 }
 
@@ -486,7 +502,7 @@
 		dqevent.id = 0;
 		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 	} else {
-		pr_err("Failed to get valid response for flush\n");
+		dprintk(VIDC_ERR, "Failed to get valid response for flush\n");
 	}
 }
 
@@ -503,7 +519,8 @@
 		dqevent.id = 0;
 		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 	} else {
-		pr_err("Failed to get valid response for session close\n");
+		dprintk(VIDC_ERR,
+			"Failed to get valid response for session close\n");
 	}
 }
 
@@ -513,7 +530,7 @@
 	struct vb2_buffer *vb = NULL;
 	int found = 0;
 	if (!q) {
-		pr_err("Invalid parameter\n");
+		dprintk(VIDC_ERR, "Invalid parameter\n");
 		return NULL;
 	}
 	list_for_each_entry(vb, &q->queued_list, queued_entry) {
@@ -523,7 +540,8 @@
 		}
 	}
 	if (!found) {
-		pr_err("Failed to find the buffer in queued list: %d, %d\n",
+		dprintk(VIDC_ERR,
+			"Failed to find the buffer in queued list: %d, %d\n",
 			dev_addr, q->type);
 		vb = NULL;
 	}
@@ -535,7 +553,7 @@
 	struct msm_vidc_cb_data_done *response = data;
 	struct vb2_buffer *vb;
 	if (!response) {
-		pr_err("Invalid response from vidc_hal\n");
+		dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
 		return;
 	}
 	vb = response->clnt_data;
@@ -550,7 +568,7 @@
 	struct vb2_buffer *vb;
 	struct vidc_hal_fbd *fill_buf_done;
 	if (!response) {
-		pr_err("Invalid response from vidc_hal\n");
+		dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
 		return;
 	}
 	inst = (struct msm_vidc_inst *)response->session_id;
@@ -569,9 +587,16 @@
 			vb->v4l2_buf.timestamp =
 				ns_to_timeval(time_usec * NSEC_PER_USEC);
 		}
+		vb->v4l2_buf.flags = 0;
 
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
 			vb->v4l2_buf.flags |= V4L2_BUF_FLAG_EOS;
+		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
+			vb->v4l2_buf.flags &= ~V4L2_QCOM_BUF_FLAG_CODECCONFIG;
+
+		if (!inst->fbd_count)
+			vb->v4l2_buf.flags = V4L2_BUF_FLAG_KEYFRAME;
+		++inst->fbd_count;
 
 		switch (fill_buf_done->picture_type) {
 		case HAL_PICTURE_IDR:
@@ -589,9 +614,11 @@
 			/* Do we need to care about these? */
 		case HAL_FRAME_YUV:
 			break;
+		default:
+			break;
 		}
 
-		pr_debug("Filled length = %d; flags %x\n",
+		dprintk(VIDC_DBG, "Filled length = %d; flags %x\n",
 				vb->v4l2_planes[0].bytesused,
 				vb->v4l2_buf.flags);
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
@@ -625,9 +652,34 @@
 	}
 }
 
+static void  handle_seq_hdr_done(enum command_response cmd, void *data)
+{
+	struct msm_vidc_cb_data_done *response = data;
+	struct msm_vidc_inst *inst;
+	struct vb2_buffer *vb;
+	struct vidc_hal_fbd *fill_buf_done;
+	if (!response) {
+		pr_err("Invalid response from vidc_hal\n");
+		return;
+	}
+	inst = (struct msm_vidc_inst *)response->session_id;
+	fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
+	vb = get_vb_from_device_addr(&inst->vb2_bufq[CAPTURE_PORT],
+		(u32)fill_buf_done->packet_buffer1);
+	if (vb)
+		vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
+
+	vb->v4l2_buf.flags = V4L2_QCOM_BUF_FLAG_CODECCONFIG;
+
+	dprintk(VIDC_DBG, "Filled length = %d; flags %x\n",
+				vb->v4l2_planes[0].bytesused,
+				vb->v4l2_buf.flags);
+	vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+}
+
 void handle_cmd_response(enum command_response cmd, void *data)
 {
-	pr_debug("Command response = %d\n", cmd);
+	dprintk(VIDC_DBG, "Command response = %d\n", cmd);
 	switch (cmd) {
 	case SYS_INIT_DONE:
 		handle_sys_init_done(cmd, data);
@@ -668,8 +720,11 @@
 	case SESSION_FLUSH_DONE:
 		handle_session_flush(cmd, data);
 		break;
+	case SESSION_GET_SEQ_HDR_DONE:
+		handle_seq_hdr_done(cmd, data);
+		break;
 	default:
-		pr_err("response unhandled\n");
+		dprintk(VIDC_ERR, "response unhandled\n");
 		break;
 	}
 }
@@ -679,22 +734,22 @@
 	int num_mbs_per_sec;
 	int rc = 0;
 	if (!core) {
-		pr_err("Invalid args: %p\n", core);
+		dprintk(VIDC_ERR, "Invalid args: %p\n", core);
 		return -EINVAL;
 	}
-	num_mbs_per_sec = msm_comm_get_load(core, MSM_VIDC_ENCODER);
+	num_mbs_per_sec = 2 * msm_comm_get_load(core, MSM_VIDC_ENCODER);
 	num_mbs_per_sec += msm_comm_get_load(core, MSM_VIDC_DECODER);
-	pr_debug("num_mbs_per_sec = %d\n", num_mbs_per_sec);
+	dprintk(VIDC_INFO, "num_mbs_per_sec = %d\n", num_mbs_per_sec);
 	rc = clk_set_rate(core->resources.clock[VCODEC_CLK].clk,
 			get_clock_rate(&core->resources.clock[VCODEC_CLK],
 				num_mbs_per_sec));
 	if (rc) {
-		pr_err("Failed to set clock rate: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);
 		goto fail_clk_set_rate;
 	}
 	rc = msm_comm_scale_bus(core, type);
 	if (rc)
-		pr_err("Failed to scale bus bandwidth\n");
+		dprintk(VIDC_ERR, "Failed to scale bus bandwidth\n");
 fail_clk_set_rate:
 	return rc;
 }
@@ -705,17 +760,17 @@
 	struct core_clock *cl;
 	int rc = 0;
 	if (!core) {
-		pr_err("Invalid params: %p\n", core);
+		dprintk(VIDC_ERR, "Invalid params: %p\n", core);
 		return -EINVAL;
 	}
 	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
 		cl = &core->resources.clock[i];
 		rc = clk_prepare_enable(cl->clk);
 		if (rc) {
-			pr_err("Failed to enable clocks\n");
+			dprintk(VIDC_ERR, "Failed to enable clocks\n");
 			goto fail_clk_enable;
 		} else {
-			pr_err("Clock: %s enabled\n", cl->name);
+			dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
 		}
 	}
 	return rc;
@@ -732,7 +787,7 @@
 	int i;
 	struct core_clock *cl;
 	if (!core) {
-		pr_err("Invalid params: %p\n", core);
+		dprintk(VIDC_ERR, "Invalid params: %p\n", core);
 		return;
 	}
 	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
@@ -745,7 +800,7 @@
 {
 	int rc = 0;
 	if (!core) {
-		pr_err("Invalid paramter: %p\n", core);
+		dprintk(VIDC_ERR, "Invalid paramter: %p\n", core);
 		return -EINVAL;
 	}
 
@@ -753,20 +808,20 @@
 		core->resources.fw.cookie = pil_get("venus");
 
 	if (IS_ERR_OR_NULL(core->resources.fw.cookie)) {
-		pr_err("Failed to download firmware\n");
+		dprintk(VIDC_ERR, "Failed to download firmware\n");
 		rc = -ENOMEM;
 		goto fail_pil_get;
 	}
 
 	rc = msm_comm_enable_clks(core);
 	if (rc) {
-		pr_err("Failed to enable clocks: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to enable clocks: %d\n", rc);
 		goto fail_enable_clks;
 	}
 
 	rc = msm_comm_iommu_attach(core);
 	if (rc) {
-		pr_err("Failed to attach iommu");
+		dprintk(VIDC_ERR, "Failed to attach iommu");
 		goto fail_iommu_attach;
 	}
 	return rc;
@@ -782,7 +837,7 @@
 static void msm_comm_unload_fw(struct msm_vidc_core *core)
 {
 	if (!core) {
-		pr_err("Invalid paramter: %p\n", core);
+		dprintk(VIDC_ERR, "Invalid paramter: %p\n", core);
 		return;
 	}
 	if (core->resources.fw.cookie) {
@@ -808,7 +863,7 @@
 	struct vidc_resource_hdr rhdr;
 	int rc = 0;
 	if (!core || !ocmem) {
-		pr_err("Invalid params, core:%p, ocmem: %p\n",
+		dprintk(VIDC_ERR, "Invalid params, core:%p, ocmem: %p\n",
 			core, ocmem);
 		return -EINVAL;
 	}
@@ -817,10 +872,10 @@
 	rhdr.size =	ocmem->len;
 	rc = vidc_hal_core_set_resource(core->device, &rhdr, ocmem);
 	if (rc) {
-		pr_err("Failed to set OCMEM on driver\n");
+		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
 		goto ocmem_set_failed;
 	}
-	pr_debug("OCMEM set, addr = %lx, size: %ld\n",
+	dprintk(VIDC_DBG, "OCMEM set, addr = %lx, size: %ld\n",
 		ocmem->addr, ocmem->len);
 ocmem_set_failed:
 	return rc;
@@ -831,7 +886,7 @@
 	struct vidc_resource_hdr rhdr;
 	int rc = 0;
 	if (!core || !core->resources.ocmem.buf) {
-		pr_err("Invalid params, core:%p\n",	core);
+		dprintk(VIDC_ERR, "Invalid params, core:%p\n",	core);
 		return -EINVAL;
 	}
 	rhdr.resource_id = VIDC_RESOURCE_OCMEM;
@@ -840,14 +895,14 @@
 		&core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)]);
 	rc = vidc_hal_core_release_resource(core->device, &rhdr);
 	if (rc) {
-		pr_err("Failed to set OCMEM on driver\n");
+		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
 		goto release_ocmem_failed;
 	}
 	rc = wait_for_completion_timeout(
 		&core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)],
 		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
 	if (!rc) {
-		pr_err("Wait interrupted or timeout: %d\n", rc);
+		dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
 		rc = -EIO;
 		goto release_ocmem_failed;
 	}
@@ -859,49 +914,48 @@
 		unsigned long size)
 {
 	int rc = 0;
-	unsigned long flags;
 	struct ocmem_buf *ocmem_buffer;
+	mutex_lock(&core->sync_lock);
 	if (!core || !size) {
-		pr_err("Invalid param, core: %p, size: %lu\n", core, size);
+		dprintk(VIDC_ERR,
+			"Invalid param, core: %p, size: %lu\n", core, size);
 		return -EINVAL;
 	}
-	spin_lock_irqsave(&core->lock, flags);
 	ocmem_buffer = core->resources.ocmem.buf;
 	if (!ocmem_buffer ||
 		ocmem_buffer->len < size) {
 		ocmem_buffer = ocmem_allocate_nb(OCMEM_VIDEO, size);
 		if (IS_ERR_OR_NULL(ocmem_buffer)) {
-			pr_err("ocmem_allocate_nb failed: %d\n",
+			dprintk(VIDC_ERR,
+				"ocmem_allocate_nb failed: %d\n",
 				(u32) ocmem_buffer);
 			rc = -ENOMEM;
 		}
 		core->resources.ocmem.buf = ocmem_buffer;
 		rc = msm_comm_set_ocmem(core, ocmem_buffer);
 		if (rc) {
-			pr_err("Failed to set ocmem: %d\n", rc);
+			dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
 			goto ocmem_set_failed;
 		}
 	} else
-		pr_debug("OCMEM is enough. reqd: %lu, available: %lu\n",
+		dprintk(VIDC_DBG,
+			"OCMEM is enough. reqd: %lu, available: %lu\n",
 			size, ocmem_buffer->len);
 
 ocmem_set_failed:
-	spin_unlock_irqrestore(&core->lock, flags);
+	mutex_unlock(&core->sync_lock);
 	return rc;
 }
 
 static int msm_comm_free_ocmem(struct msm_vidc_core *core)
 {
 	int rc = 0;
-	unsigned long flags;
-	spin_lock_irqsave(&core->lock, flags);
 	if (core->resources.ocmem.buf) {
 		rc = ocmem_free(OCMEM_VIDEO, core->resources.ocmem.buf);
 		if (rc)
-			pr_err("Failed to free ocmem\n");
+			dprintk(VIDC_ERR, "Failed to free ocmem\n");
 	}
 	core->resources.ocmem.buf = NULL;
-	spin_unlock_irqrestore(&core->lock, flags);
 	return rc;
 }
 
@@ -916,7 +970,7 @@
 	if (event == OCMEM_ALLOC_GROW) {
 		ocmem = container_of(this, struct on_chip_mem, vidc_ocmem_nb);
 		if (!ocmem) {
-			pr_err("Wrong handler passed\n");
+			dprintk(VIDC_ERR, "Wrong handler passed\n");
 			rc = NOTIFY_BAD;
 			goto bad_notfier;
 		}
@@ -925,7 +979,7 @@
 		core = container_of(resources,
 			struct msm_vidc_core, resources);
 		if (msm_comm_set_ocmem(core, buff)) {
-			pr_err("Failed to set ocmem: %d\n", rc);
+			dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
 			goto ocmem_set_failed;
 		}
 		rc = NOTIFY_OK;
@@ -942,16 +996,16 @@
 	int rc = 0;
 	mutex_lock(&core->sync_lock);
 	if (core->state >= VIDC_CORE_INIT_DONE) {
-		pr_err("Video core: %d is already in state: %d\n",
+		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
 				core->id, core->state);
 		goto core_already_inited;
 	}
-	pr_debug("Waiting for SYS_INIT_DONE\n");
+	dprintk(VIDC_DBG, "Waiting for SYS_INIT_DONE\n");
 	rc = wait_for_completion_timeout(
 		&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)],
 		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
 	if (!rc) {
-		pr_err("Wait interrupted or timeout: %d\n", rc);
+		dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
 		rc = -EIO;
 		goto exit;
 	} else {
@@ -959,7 +1013,7 @@
 		core->state = VIDC_CORE_INIT_DONE;
 		spin_unlock_irqrestore(&core->lock, flags);
 	}
-	pr_debug("SYS_INIT_DONE!!!\n");
+	dprintk(VIDC_DBG, "SYS_INIT_DONE!!!\n");
 core_already_inited:
 	change_inst_state(inst, MSM_VIDC_CORE_INIT_DONE);
 	rc = 0;
@@ -975,25 +1029,25 @@
 	unsigned long flags;
 	mutex_lock(&core->sync_lock);
 	if (core->state >= VIDC_CORE_INIT) {
-		pr_err("Video core: %d is already in state: %d\n",
+		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
 				core->id, core->state);
 		goto core_already_inited;
 	}
 	rc = msm_comm_scale_clocks(core, inst->session_type);
 	if (rc) {
-		pr_err("Failed to set clock rate: %d\n", rc);
+		dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);
 		goto fail_load_fw;
 	}
 	rc = msm_comm_load_fw(core);
 	if (rc) {
-		pr_err("Failed to load video firmware\n");
+		dprintk(VIDC_ERR, "Failed to load video firmware\n");
 		goto fail_load_fw;
 	}
 	init_completion(&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)]);
 	rc = vidc_hal_core_init(core->device,
 		core->resources.io_map[NS_MAP].domain);
 	if (rc) {
-		pr_err("Failed to init core, id = %d\n", core->id);
+		dprintk(VIDC_ERR, "Failed to init core, id = %d\n", core->id);
 		goto fail_core_init;
 	}
 	spin_lock_irqsave(&core->lock, flags);
@@ -1017,20 +1071,22 @@
 	unsigned long flags;
 	mutex_lock(&core->sync_lock);
 	if (core->state == VIDC_CORE_UNINIT) {
-		pr_err("Video core: %d is already in state: %d\n",
+		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
 				core->id, core->state);
 		goto core_already_uninited;
 	}
 	if (msm_comm_scale_clocks(core, inst->session_type)) {
-		pr_warn("Failed to scale clocks while closing\n");
-		pr_warn("Power might be impacted\n");
+		dprintk(VIDC_WARN, "Failed to scale clocks while closing\n");
+		dprintk(VIDC_WARN, "Power might be impacted\n");
 	}
 	if (list_empty(&core->instances)) {
 		msm_comm_unset_ocmem(core);
 		msm_comm_free_ocmem(core);
+		dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
 		rc = vidc_hal_core_release(core->device);
 		if (rc) {
-			pr_err("Failed to release core, id = %d\n", core->id);
+			dprintk(VIDC_ERR, "Failed to release core, id = %d\n",
+							core->id);
 			goto exit;
 		}
 		spin_lock_irqsave(&core->lock, flags);
@@ -1056,7 +1112,7 @@
 		domain = HAL_VIDEO_DOMAIN_DECODER;
 		break;
 	default:
-		pr_err("Wrong domain\n");
+		dprintk(VIDC_ERR, "Wrong domain\n");
 		domain = HAL_UNUSED_DOMAIN;
 		break;
 	}
@@ -1066,7 +1122,7 @@
 static enum hal_video_codec get_hal_codec_type(int fourcc)
 {
 	enum hal_video_codec codec;
-	pr_debug("codec in %s is 0x%x", __func__, fourcc);
+	dprintk(VIDC_DBG, "codec is 0x%x", fourcc);
 	switch (fourcc) {
 	case V4L2_PIX_FMT_H264:
 	case V4L2_PIX_FMT_H264_NO_SC:
@@ -1102,7 +1158,7 @@
 		  HAL_VIDEO_CODEC_VP6
 		  HAL_VIDEO_CODEC_VP7*/
 	default:
-		pr_err("Wrong codec: %d\n", fourcc);
+		dprintk(VIDC_ERR, "Wrong codec: %d\n", fourcc);
 		codec = HAL_UNUSED_CODEC;
 	}
 	return codec;
@@ -1114,7 +1170,8 @@
 	int rc = 0;
 	int fourcc = 0;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_OPEN)) {
-		pr_err("inst: %p is already in state: %d\n", inst, inst->state);
+		dprintk(VIDC_INFO, "inst: %p is already in state: %d\n",
+						inst, inst->state);
 		goto exit;
 	}
 	if (inst->session_type == MSM_VIDC_DECODER) {
@@ -1122,7 +1179,7 @@
 	} else if (inst->session_type == MSM_VIDC_ENCODER) {
 		fourcc = inst->fmts[CAPTURE_PORT]->fourcc;
 	} else {
-		pr_err("Invalid session\n");
+		dprintk(VIDC_ERR, "Invalid session\n");
 		return -EINVAL;
 	}
 	init_completion(
@@ -1131,11 +1188,14 @@
 					get_hal_domain(inst->session_type),
 					get_hal_codec_type(fourcc));
 	if (!inst->session) {
-		pr_err("Failed to call session init for: %d, %d, %d, %d\n",
-				(int)inst->core->device, (int)inst,
-				inst->session_type, fourcc);
+		dprintk(VIDC_ERR,
+			"Failed to call session init for: %d, %d, %d, %d\n",
+			(int)inst->core->device, (int)inst,
+			inst->session_type, fourcc);
 		goto exit;
 	}
+	inst->ftb_count = 0;
+	inst->fbd_count = 0;
 	change_inst_state(inst, MSM_VIDC_OPEN);
 exit:
 	return rc;
@@ -1147,17 +1207,20 @@
 	int rc = 0;
 	u32 ocmem_sz = 0;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
-		pr_err("inst: %p is already in state: %d\n", inst, inst->state);
+		dprintk(VIDC_INFO, "inst: %p is already in state: %d\n",
+						inst, inst->state);
 		goto exit;
 	}
 	ocmem_sz = get_ocmem_requirement(inst->prop.height, inst->prop.width);
 	rc = msm_comm_alloc_ocmem(inst->core, ocmem_sz);
 	if (rc)
-		pr_warn("Failed to allocate OCMEM. Performance will be impacted\n");
+		dprintk(VIDC_WARN,
+			"Failed to allocate OCMEM. Performance will be impacted\n");
 
 	rc = vidc_hal_session_load_res((void *) inst->session);
 	if (rc) {
-		pr_err("Failed to send load resources\n");
+		dprintk(VIDC_ERR,
+			"Failed to send load resources\n");
 		goto exit;
 	}
 	change_inst_state(inst, MSM_VIDC_LOAD_RESOURCES);
@@ -1169,14 +1232,17 @@
 {
 	int rc = 0;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) {
-		pr_err("inst: %p is already in state: %d\n", inst, inst->state);
+		dprintk(VIDC_INFO,
+			"inst: %p is already in state: %d\n",
+			inst, inst->state);
 		goto exit;
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_START_DONE)]);
 	rc = vidc_hal_session_start((void *) inst->session);
 	if (rc) {
-		pr_err("Failed to send load resources\n");
+		dprintk(VIDC_ERR,
+			"Failed to send load resources\n");
 		goto exit;
 	}
 	change_inst_state(inst, MSM_VIDC_START);
@@ -1188,15 +1254,17 @@
 {
 	int rc = 0;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) {
-		pr_err("inst: %p is already in state: %d\n", inst, inst->state);
+		dprintk(VIDC_INFO,
+			"inst: %p is already in state: %d\n",
+			inst, inst->state);
 		goto exit;
 	}
-	pr_debug("Send Stop to hal\n");
+	dprintk(VIDC_DBG, "Send Stop to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_STOP_DONE)]);
 	rc = vidc_hal_session_stop((void *) inst->session);
 	if (rc) {
-		pr_err("Failed to send stop\n");
+		dprintk(VIDC_ERR, "Failed to send stop\n");
 		goto exit;
 	}
 	change_inst_state(inst, MSM_VIDC_STOP);
@@ -1208,15 +1276,19 @@
 {
 	int rc = 0;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) {
-		pr_err("inst: %p is already in state: %d\n", inst, inst->state);
+		dprintk(VIDC_INFO,
+			"inst: %p is already in state: %d\n",
+			inst, inst->state);
 		goto exit;
 	}
-	pr_debug("Send release res to hal\n");
+	dprintk(VIDC_DBG,
+		"Send release res to hal\n");
 	init_completion(
 	&inst->completions[SESSION_MSG_INDEX(SESSION_RELEASE_RESOURCE_DONE)]);
 	rc = vidc_hal_session_release_res((void *) inst->session);
 	if (rc) {
-		pr_err("Failed to send load resources\n");
+		dprintk(VIDC_ERR,
+			"Failed to send load resources\n");
 		goto exit;
 	}
 	change_inst_state(inst, MSM_VIDC_RELEASE_RESOURCES);
@@ -1228,15 +1300,19 @@
 {
 	int rc = 0;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) {
-		pr_err("inst: %p is already in state: %d\n", inst, inst->state);
+		dprintk(VIDC_INFO,
+			"inst: %p is already in state: %d\n",
+						inst, inst->state);
 		goto exit;
 	}
-	pr_debug("Send session close to hal\n");
+	dprintk(VIDC_DBG,
+		"Send session close to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_END_DONE)]);
 	rc = vidc_hal_session_end((void *) inst->session);
 	if (rc) {
-		pr_err("Failed to send load resources\n");
+		dprintk(VIDC_ERR,
+			"Failed to send load resources\n");
 		goto exit;
 	}
 	change_inst_state(inst, MSM_VIDC_OPEN);
@@ -1249,10 +1325,12 @@
 	int rc = 0;
 	int flipped_state;
 	if (!inst) {
-		pr_err("Invalid instance pointer = %p\n", inst);
+		dprintk(VIDC_ERR,
+			"Invalid instance pointer = %p\n", inst);
 		return -EINVAL;
 	}
-	pr_debug("Trying to move inst: %p from: 0x%x to 0x%x\n",
+	dprintk(VIDC_DBG,
+		"Trying to move inst: %p from: 0x%x to 0x%x\n",
 				inst, inst->state, state);
 	mutex_lock(&inst->sync_lock);
 	flipped_state = inst->state;
@@ -1268,7 +1346,8 @@
 		flipped_state &= 0xFFFE;
 		flipped_state = flipped_state - 1;
 	}
-	pr_debug("flipped_state = 0x%x\n", flipped_state);
+	dprintk(VIDC_DBG,
+		"flipped_state = 0x%x\n", flipped_state);
 	switch (flipped_state) {
 	case MSM_VIDC_CORE_UNINIT_DONE:
 	case MSM_VIDC_CORE_INIT:
@@ -1311,7 +1390,7 @@
 				SESSION_STOP_DONE);
 		if (rc || state <= inst->state)
 			break;
-		pr_debug("Moving to Stop Done state\n");
+		dprintk(VIDC_DBG, "Moving to Stop Done state\n");
 	case MSM_VIDC_RELEASE_RESOURCES:
 		rc = msm_vidc_release_res(flipped_state, inst);
 		if (rc || state <= inst->state)
@@ -1322,7 +1401,8 @@
 			SESSION_RELEASE_RESOURCE_DONE);
 		if (rc || state <= inst->state)
 			break;
-		pr_debug("Moving to release resources done state\n");
+		dprintk(VIDC_DBG,
+			"Moving to release resources done state\n");
 	case MSM_VIDC_CLOSE:
 		rc = msm_comm_session_close(flipped_state, inst);
 		if (rc || state <= inst->state)
@@ -1333,18 +1413,19 @@
 		if (rc || state <= inst->state)
 			break;
 	case MSM_VIDC_CORE_UNINIT:
-		pr_debug("***************Sending core uninit\n");
+		dprintk(VIDC_DBG, "Sending core uninit\n");
 		rc = msm_vidc_deinit_core(inst);
 		if (rc || state == inst->state)
 			break;
 	default:
-		pr_err("State not recognized: %d\n", flipped_state);
+		dprintk(VIDC_ERR, "State not recognized\n");
 		rc = -EINVAL;
 		break;
 	}
 	mutex_unlock(&inst->sync_lock);
 	if (rc)
-		pr_err("Failed to move from state: %d to %d\n",
+		dprintk(VIDC_ERR,
+			"Failed to move from state: %d to %d\n",
 			inst->state, state);
 	return rc;
 }
@@ -1361,24 +1442,23 @@
 	inst = q->drv_priv;
 
 	if (!inst || !vb) {
-		pr_err("Invalid input: %p, %p\n", inst, vb);
+		dprintk(VIDC_ERR, "Invalid input: %p, %p\n", inst, vb);
 		return -EINVAL;
 	}
 	if (inst->state != MSM_VIDC_START_DONE) {
 			entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 			if (!entry) {
-				pr_err("Out of memory\n");
+				dprintk(VIDC_ERR, "Out of memory\n");
 				goto err_no_mem;
 			}
 			entry->vb = vb;
-			pr_debug("Queueing buffer in pendingq\n");
+			dprintk(VIDC_DBG, "Queueing buffer in pendingq\n");
 			spin_lock_irqsave(&inst->lock, flags);
 			list_add_tail(&entry->list, &inst->pendingq);
 			spin_unlock_irqrestore(&inst->lock, flags);
 	} else {
 		int64_t time_usec = timeval_to_ns(&vb->v4l2_buf.timestamp);
 		do_div(time_usec, NSEC_PER_USEC);
-
 		memset(&frame_data, 0 , sizeof(struct vidc_frame_data));
 		frame_data.alloc_len = vb->v4l2_planes[0].length;
 		frame_data.filled_len = vb->v4l2_planes[0].bytesused;
@@ -1390,21 +1470,24 @@
 			frame_data.buffer_type = HAL_BUFFER_INPUT;
 			if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_EOS) {
 				frame_data.flags |= HAL_BUFFERFLAG_EOS;
-				pr_debug("Received EOS on output capability\n");
+				dprintk(VIDC_DBG,
+					"Received EOS on output capability\n");
 			}
 
 			if (vb->v4l2_buf.flags &
 					V4L2_QCOM_BUF_FLAG_CODECCONFIG) {
 				frame_data.flags |= HAL_BUFFERFLAG_CODECCONFIG;
-				pr_debug("Received CODECCONFIG on output capability\n");
+				dprintk(VIDC_DBG,
+					"Received CODECCONFIG on output cap\n");
 			}
-
-			pr_debug("Sending etb to hal: Alloc: %d :filled: %d\n",
+			dprintk(VIDC_DBG,
+				"Sending etb to hal: Alloc: %d :filled: %d\n",
 				frame_data.alloc_len, frame_data.filled_len);
 			rc = vidc_hal_session_etb((void *) inst->session,
 					&frame_data);
-			pr_debug("Sent etb to HAL\n");
+			dprintk(VIDC_DBG, "Sent etb to HAL\n");
 		} else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+			struct vidc_seq_hdr seq_hdr;
 			frame_data.filled_len = 0;
 			frame_data.buffer_type = HAL_BUFFER_OUTPUT;
 			if (inst->extradata_handle) {
@@ -1413,20 +1496,38 @@
 			} else {
 				frame_data.extradata_addr = 0;
 			}
-			pr_debug("Sending ftb to hal..: Alloc: %d :filled: %d",
+			dprintk(VIDC_DBG,
+				"Sending ftb to hal: Alloc: %d :filled: %d",
 				frame_data.alloc_len, frame_data.filled_len);
-			pr_debug(" extradata_addr: %d\n",
+			dprintk(VIDC_DBG,
+				" extradata_addr: %d\n",
 				frame_data.extradata_addr);
-			rc = vidc_hal_session_ftb((void *) inst->session,
-					&frame_data);
+			if (!inst->ftb_count &&
+			   inst->session_type == MSM_VIDC_ENCODER) {
+				seq_hdr.seq_hdr = (u8 *) vb->v4l2_planes[0].
+					m.userptr;
+				seq_hdr.seq_hdr_len = vb->v4l2_planes[0].length;
+				rc = vidc_hal_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 = vidc_hal_session_ftb((void *)
+					inst->session, &frame_data);
+			}
+			inst->ftb_count++;
 		} else {
-			pr_err("This capability is not supported: %d\n",
+			dprintk(VIDC_ERR,
+				"This capability is not supported: %d\n",
 				q->type);
 			rc = -EINVAL;
 		}
 	}
 	if (rc)
-		pr_err("Failed to queue buffer\n");
+		dprintk(VIDC_ERR, "Failed to queue buffer\n");
 err_no_mem:
 	return rc;
 }
@@ -1439,14 +1540,15 @@
 		&inst->completions[SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)]);
 	rc = vidc_hal_session_get_buf_req((void *) inst->session);
 	if (rc) {
-		pr_err("Failed to get property\n");
+		dprintk(VIDC_ERR, "Failed to get property\n");
 		goto exit;
 	}
 	rc = wait_for_completion_timeout(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)],
 		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
 	if (!rc) {
-		pr_err("Wait interrupted or timeout: %d\n", rc);
+		dprintk(VIDC_ERR,
+			"Wait interrupted or timeout: %d\n", rc);
 		rc = -EIO;
 		goto exit;
 	}
@@ -1467,10 +1569,10 @@
 	struct hal_buffer_requirements *scratch_buf =
 		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_SCRATCH];
 	int i;
-
-	pr_debug("scratch: num = %d, size = %d\n",
-			scratch_buf->buffer_count_actual,
-			scratch_buf->buffer_size);
+	dprintk(VIDC_DBG,
+		"scratch: num = %d, size = %d\n",
+		scratch_buf->buffer_count_actual,
+		scratch_buf->buffer_size);
 	spin_lock_irqsave(&inst->lock, flags);
 	if (!list_empty(&inst->internalbufs)) {
 		list_for_each_safe(ptr, next, &inst->internalbufs) {
@@ -1490,13 +1592,14 @@
 				inst->core->resources.io_map[NS_MAP].domain,
 				0, 0);
 			if (!handle) {
-				pr_err("Failed to allocate scratch memory\n");
+				dprintk(VIDC_ERR,
+					"Failed to allocate scratch memory\n");
 				rc = -ENOMEM;
 				goto err_no_mem;
 			}
 			binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
 			if (!binfo) {
-				pr_err("Out of memory\n");
+				dprintk(VIDC_ERR, "Out of memory\n");
 				rc = -ENOMEM;
 				goto fail_kzalloc;
 			}
@@ -1508,7 +1611,8 @@
 			rc = vidc_hal_session_set_buffers(
 					(void *) inst->session,	&buffer_info);
 			if (rc) {
-				pr_err("vidc_hal_session_set_buffers failed");
+				dprintk(VIDC_ERR,
+					"vidc_hal_session_set_buffers failed");
 				goto fail_set_buffers;
 			}
 			spin_lock_irqsave(&inst->lock, flags);
@@ -1535,11 +1639,13 @@
 	struct hal_buffer_requirements *persist_buf =
 		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_PERSIST];
 	int i;
-	pr_debug("persist: num = %d, size = %d\n",
+	dprintk(VIDC_DBG,
+		"persist: num = %d, size = %d\n",
 		persist_buf->buffer_count_actual,
 		persist_buf->buffer_size);
 	if (!list_empty(&inst->persistbufs)) {
-		pr_err("Persist buffers already allocated\n");
+		dprintk(VIDC_ERR,
+			"Persist buffers already allocated\n");
 		return rc;
 	}
 
@@ -1550,13 +1656,14 @@
 				inst->core->resources.io_map[NS_MAP].domain,
 				0, 0);
 			if (!handle) {
-				pr_err("Failed to allocate persist memory\n");
+				dprintk(VIDC_ERR,
+					"Failed to allocate persist memory\n");
 				rc = -ENOMEM;
 				goto err_no_mem;
 			}
 			binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
 			if (!binfo) {
-				pr_err("Out of memory\n");
+				dprintk(VIDC_ERR, "Out of memory\n");
 				rc = -ENOMEM;
 				goto fail_kzalloc;
 			}
@@ -1568,7 +1675,8 @@
 			rc = vidc_hal_session_set_buffers(
 				(void *) inst->session, &buffer_info);
 			if (rc) {
-				pr_err("vidc_hal_session_set_buffers failed");
+				dprintk(VIDC_ERR,
+					"vidc_hal_session_set_buffers failed");
 				goto fail_set_buffers;
 			}
 			spin_lock_irqsave(&inst->lock, flags);
@@ -1584,3 +1692,27 @@
 err_no_mem:
 	return rc;
 }
+
+int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
+{
+	int rc =  0;
+	bool ip_flush = false;
+	bool op_flush = false;
+	ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
+	op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
+
+	if (ip_flush && !op_flush) {
+		dprintk(VIDC_WARN, "Input only flush not supported\n");
+		return 0;
+	}
+	mutex_lock(&inst->sync_lock);
+	if (inst->in_reconfig && !ip_flush && op_flush) {
+		rc = vidc_hal_session_flush(inst->session,
+				HAL_FLUSH_OUTPUT);
+	} else {
+		rc = vidc_hal_session_flush(inst->session,
+				HAL_FLUSH_ALL);
+	}
+	mutex_unlock(&inst->sync_lock);
+	return rc;
+}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.h b/drivers/media/video/msm_vidc/msm_vidc_common.h
index 69e466e..69aa53a 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.h
@@ -31,6 +31,7 @@
 int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst);
 int msm_comm_qbuf(struct vb2_buffer *vb);
 int msm_comm_scale_clocks(struct msm_vidc_core *core, enum session_type type);
+int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags);
 #define IS_PRIV_CTRL(idx) (\
 		(V4L2_CTRL_ID2CLASS(idx) == V4L2_CTRL_CLASS_MPEG) && \
 		V4L2_CTRL_DRIVER_PRIV(idx))
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.c b/drivers/media/video/msm_vidc/msm_vidc_debug.c
new file mode 100644
index 0000000..7921f84
--- /dev/null
+++ b/drivers/media/video/msm_vidc/msm_vidc_debug.c
@@ -0,0 +1,186 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_vidc_debug.h"
+
+#define MAX_DBG_BUF_SIZE 4096
+int msm_vidc_debug;
+
+struct debug_buffer {
+	char ptr[MAX_DBG_BUF_SIZE];
+	char *curr;
+	u32 filled_size;
+};
+
+static struct debug_buffer dbg_buf;
+
+#define INIT_DBG_BUF(__buf) ({ \
+	__buf.curr = __buf.ptr;\
+	__buf.filled_size = 0; \
+})
+
+static int core_info_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static u32 write_str(struct debug_buffer *buffer, const char *fmt, ...)
+{
+	va_list args;
+	u32 size;
+	va_start(args, fmt);
+	size = vscnprintf(buffer->curr, MAX_DBG_BUF_SIZE - 1, fmt, args);
+	va_end(args);
+	buffer->curr += size;
+	buffer->filled_size += size;
+	return size;
+}
+
+static ssize_t core_info_read(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct msm_vidc_core *core = file->private_data;
+	int i = 0;
+	if (!core) {
+		dprintk(VIDC_ERR, "Invalid params, core: %p\n", core);
+		return 0;
+	}
+	INIT_DBG_BUF(dbg_buf);
+	write_str(&dbg_buf, "===============================\n");
+	write_str(&dbg_buf, "CORE %d: 0x%p\n", core->id, core);
+	write_str(&dbg_buf, "===============================\n");
+	write_str(&dbg_buf, "state: %d\n", core->state);
+	write_str(&dbg_buf, "base addr: 0x%x\n", core->base_addr);
+	write_str(&dbg_buf, "register_base: 0x%x\n", core->register_base);
+	write_str(&dbg_buf, "register_size: %u\n", core->register_size);
+	write_str(&dbg_buf, "irq: %u\n", core->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)]) ?
+			"pending" : "done");
+	}
+	return simple_read_from_buffer(buf, count, ppos,
+			dbg_buf.ptr, dbg_buf.filled_size);
+}
+
+static const struct file_operations core_info_fops = {
+	.open = core_info_open,
+	.read = core_info_read,
+};
+
+struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core,
+		struct dentry *parent)
+{
+	struct dentry *dir = NULL;
+	char debugfs_name[MAX_DEBUGFS_NAME];
+	if (!core) {
+		dprintk(VIDC_ERR, "Invalid params, core: %p\n", core);
+		goto failed_create_dir;
+	}
+	msm_vidc_debug = 0;
+	snprintf(debugfs_name, MAX_DEBUGFS_NAME, "core%d", core->id);
+	dir = debugfs_create_dir(debugfs_name, parent);
+	if (!dir) {
+		dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n");
+		goto failed_create_dir;
+	}
+	if (!debugfs_create_file("info", S_IRUGO, dir, core, &core_info_fops)) {
+		dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+		goto failed_create_dir;
+	}
+	if (!debugfs_create_u32("debug_level", S_IRUGO | S_IWUSR,
+			parent,	&msm_vidc_debug)) {
+		dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+		goto failed_create_dir;
+	}
+failed_create_dir:
+	return dir;
+}
+
+static int inst_info_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t inst_info_read(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct msm_vidc_inst *inst = file->private_data;
+	int i, j;
+	if (!inst) {
+		dprintk(VIDC_ERR, "Invalid params, core: %p\n", inst);
+		return 0;
+	}
+	INIT_DBG_BUF(dbg_buf);
+	write_str(&dbg_buf, "===============================\n");
+	write_str(&dbg_buf, "INSTANCE: 0x%p (%s)\n", inst,
+		inst->session_type == MSM_VIDC_ENCODER ? "Encoder" : "Decoder");
+	write_str(&dbg_buf, "===============================\n");
+	write_str(&dbg_buf, "core: 0x%p\n", inst->core);
+	write_str(&dbg_buf, "height: %d\n", inst->prop.height);
+	write_str(&dbg_buf, "width: %d\n", inst->prop.width);
+	write_str(&dbg_buf, "state: %d\n", inst->state);
+	write_str(&dbg_buf, "-----------Formats-------------\n");
+	for (i = 0; i < MAX_PORT_NUM; i++) {
+		write_str(&dbg_buf, "capability: %s\n", i == OUTPUT_PORT ?
+			"Output" : "Capture");
+		write_str(&dbg_buf, "name : %s\n", inst->fmts[i]->name);
+		write_str(&dbg_buf, "planes : %d\n", inst->fmts[i]->num_planes);
+		write_str(
+		&dbg_buf, "type: %s\n", inst->fmts[i]->type == OUTPUT_PORT ?
+		"Output" : "Capture");
+		for (j = 0; j < inst->fmts[i]->num_planes; j++)
+			write_str(&dbg_buf, "size for plane %d: %u\n", j,
+			inst->fmts[i]->get_frame_size(j,
+			inst->prop.height, inst->prop.width));
+	}
+	write_str(&dbg_buf, "-------------------------------\n");
+	for (i = SESSION_MSG_START; i < SESSION_MSG_END; i++) {
+		write_str(&dbg_buf, "completions[%d]: %s\n", i,
+		completion_done(&inst->completions[SESSION_MSG_INDEX(i)]) ?
+		"pending" : "done");
+	}
+	return simple_read_from_buffer(buf, count, ppos,
+		dbg_buf.ptr, dbg_buf.filled_size);
+}
+
+static const struct file_operations inst_info_fops = {
+	.open = inst_info_open,
+	.read = inst_info_read,
+};
+
+struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst,
+		struct dentry *parent)
+{
+	struct dentry *dir = NULL;
+	char debugfs_name[MAX_DEBUGFS_NAME];
+	if (!inst) {
+		dprintk(VIDC_ERR, "Invalid params, inst: %p\n", inst);
+		goto failed_create_dir;
+	}
+	snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%p", inst);
+	dir = debugfs_create_dir(debugfs_name, parent);
+	if (!dir) {
+		dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n");
+		goto failed_create_dir;
+	}
+	if (!debugfs_create_file("info", S_IRUGO, dir, inst, &inst_info_fops)) {
+		dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+		goto failed_create_dir;
+	}
+
+failed_create_dir:
+	return dir;
+}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.h b/drivers/media/video/msm_vidc/msm_vidc_debug.h
new file mode 100644
index 0000000..b7928e9
--- /dev/null
+++ b/drivers/media/video/msm_vidc/msm_vidc_debug.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MSM_VIDC_DEBUG__
+#define __MSM_VIDC_DEBUG__
+#include <linux/debugfs.h>
+#include "msm_vidc_internal.h"
+
+#define VIDC_DBG_TAG "msm_vidc: %d: "
+
+enum vidc_msg_prio {
+	VIDC_ERR,
+	VIDC_WARN,
+	VIDC_INFO,
+	VIDC_DBG,
+};
+
+extern int msm_vidc_debug;
+#define dprintk(level, fmt, arg...)	\
+	do {							\
+		if (msm_vidc_debug >= level) \
+			printk(KERN_DEBUG VIDC_DBG_TAG fmt, \
+				level, ## arg); \
+	} while (0)
+
+struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core,
+		struct dentry *parent);
+struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst,
+		struct dentry *parent);
+
+#endif
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 29ed6dc..55aec74 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -243,6 +243,10 @@
 	bool in_reconfig;
 	u32 reconfig_width;
 	u32 reconfig_height;
+	struct dentry *debugfs_root;
+	u32 ftb_count;
+	u32 fbd_count;
+	struct vb2_buffer *vb2_seq_hdr;
 };
 
 extern struct msm_vidc_drv *vidc_driver;
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 2021ec6..12ba874 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -21,6 +21,7 @@
 #include <asm/memory.h>
 #include "vidc_hal.h"
 #include "vidc_hal_io.h"
+#include "msm_vidc_debug.h"
 
 #define FIRMWARE_SIZE			0X00A00000
 #define REG_ADDR_OFFSET_BITMASK	0x000FFFFF
@@ -37,7 +38,7 @@
 	u8 i;
 
 	if (!packet) {
-		HAL_MSG_ERROR("Invalid Param: %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Param");
 		return;
 	}
 
@@ -129,26 +130,25 @@
 	u32 *write_ptr;
 
 	if (!info || !packet || !rx_req_is_set) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params");
 		return -EINVAL;
 	}
 
 	qinfo =	(struct vidc_iface_q_info *) info;
-	HAL_MSG_LOW("In %s: ", __func__);
 	hal_virtio_modify_cmd_packet(packet);
 
 	queue = (struct hfi_queue_header *) qinfo->q_hdr;
 
 	if (!queue) {
-		HAL_MSG_ERROR("queue not present");
+		dprintk(VIDC_ERR, "queue not present");
 		return -ENOENT;
 	}
 
 	packet_size_in_words = (*(u32 *)packet) >> 2;
-	HAL_MSG_LOW("Packet_size in words: %d", packet_size_in_words);
+	dprintk(VIDC_DBG, "Packet_size in words: %d", packet_size_in_words);
 
 	if (packet_size_in_words == 0) {
-		HAL_MSG_ERROR("Zero packet size");
+		dprintk(VIDC_ERR, "Zero packet size");
 		return -ENODATA;
 	}
 
@@ -157,10 +157,10 @@
 	empty_space = (queue->qhdr_write_idx >=  read_idx) ?
 		(queue->qhdr_q_size - (queue->qhdr_write_idx -  read_idx)) :
 		(read_idx - queue->qhdr_write_idx);
-	HAL_MSG_LOW("Empty_space: %d", empty_space);
+	dprintk(VIDC_DBG, "Empty_space: %d", empty_space);
 	if (empty_space <= packet_size_in_words) {
 		queue->qhdr_tx_req =  1;
-		HAL_MSG_ERROR("Insufficient size (%d) to write (%d)",
+		dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)",
 					  empty_space, packet_size_in_words);
 		return -ENOTEMPTY;
 	}
@@ -170,7 +170,7 @@
 	new_write_idx = (queue->qhdr_write_idx + packet_size_in_words);
 	write_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
 		(queue->qhdr_write_idx << 2));
-	HAL_MSG_LOW("Write Ptr: %d", (u32) write_ptr);
+	dprintk(VIDC_DBG, "Write Ptr: %d", (u32) write_ptr);
 	if (new_write_idx < queue->qhdr_q_size) {
 		memcpy(write_ptr, packet, packet_size_in_words << 2);
 	} else {
@@ -183,7 +183,7 @@
 	}
 	queue->qhdr_write_idx = new_write_idx;
 	*rx_req_is_set = (1 == queue->qhdr_rx_req) ? 1 : 0;
-	HAL_MSG_LOW("Out %s: ", __func__);
+	dprintk(VIDC_DBG, "Out : ");
 	return 0;
 }
 
@@ -193,7 +193,7 @@
 	struct hal_session *sess;
 
 	if (!packet) {
-		HAL_MSG_ERROR("Invalid Param: %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Param: ");
 		return;
 	}
 
@@ -248,16 +248,15 @@
 	struct vidc_iface_q_info *qinfo;
 
 	if (!info || !packet || !pb_tx_req_is_set) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	}
 
 	qinfo =	(struct vidc_iface_q_info *) info;
-	HAL_MSG_LOW("In %s: ", __func__);
 	queue = (struct hfi_queue_header *) qinfo->q_hdr;
 
 	if (!queue) {
-		HAL_MSG_ERROR("Queue memory is not allocated\n");
+		dprintk(VIDC_ERR, "Queue memory is not allocated\n");
 		return -ENOMEM;
 	}
 
@@ -270,14 +269,14 @@
 	read_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
 				(queue->qhdr_read_idx << 2));
 	packet_size_in_words = (*read_ptr) >> 2;
-	HAL_MSG_LOW("packet_size_in_words: %d", packet_size_in_words);
+	dprintk(VIDC_DBG, "packet_size_in_words: %d", packet_size_in_words);
 	if (packet_size_in_words == 0) {
-		HAL_MSG_ERROR("Zero packet size");
+		dprintk(VIDC_ERR, "Zero packet size");
 		return -ENODATA;
 	}
 
 	new_read_idx = queue->qhdr_read_idx + packet_size_in_words;
-	HAL_MSG_LOW("Read Ptr: %d", (u32) new_read_idx);
+	dprintk(VIDC_DBG, "Read Ptr: %d", (u32) new_read_idx);
 	if (new_read_idx < queue->qhdr_q_size) {
 		memcpy(packet, read_ptr,
 			packet_size_in_words << 2);
@@ -299,7 +298,7 @@
 
 	*pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0;
 	hal_virtio_modify_msg_packet(packet);
-	HAL_MSG_LOW("Out %s: ", __func__);
+	dprintk(VIDC_DBG, "Out : ");
 	return 0;
 }
 
@@ -311,25 +310,25 @@
 	int rc = 0;
 
 	if (!mem || !clnt || !size) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	}
 	vmem = (struct vidc_mem_addr *)mem;
-	HAL_MSG_HIGH("start to alloc: size:%d, Flags: %d", size, flags);
+	dprintk(VIDC_WARN, "start to alloc: size:%d, Flags: %d", size, flags);
 
 	alloc  = msm_smem_alloc(clnt, size, align, flags, domain, 1, 1);
-	HAL_MSG_LOW("Alloc done");
+	dprintk(VIDC_DBG, "Alloc done");
 	if (!alloc) {
-		HAL_MSG_HIGH("Alloc fail in %s", __func__);
+		dprintk(VIDC_ERR, "Alloc failed\n");
 		rc = -ENOMEM;
 		goto fail_smem_alloc;
 	}
 	rc = msm_smem_clean_invalidate(clnt, alloc);
 	if (rc) {
-		pr_err("NOTE: Failed to clean caches\n");
+		dprintk(VIDC_ERR, "NOTE: Failed to clean caches\n");
 		goto fail_clean_cache;
 	}
-	HAL_MSG_MEDIUM("vidc_hal_alloc:ptr=%p,size=%d",
+	dprintk(VIDC_DBG, "vidc_hal_alloc:ptr=%p,size=%d",
 			alloc->kvaddr, size);
 	vmem->mem_size = alloc->size;
 	vmem->mem_data = alloc;
@@ -370,7 +369,7 @@
 	}
 
 	hwiosymaddr = ((u32)base_addr + (hwiosymaddr));
-	HAL_MSG_LOW("Base addr: 0x%x, written to: 0x%x, Value: 0x%x...",
+	dprintk(VIDC_DBG, "Base addr: 0x%x, written to: 0x%x, Value: 0x%x...",
 			(u32)base_addr, hwiosymaddr, value);
 	writel_relaxed(value, hwiosymaddr);
 	wmb();
@@ -390,14 +389,14 @@
 	int result = -EPERM;
 
 	if (!device || !pkt) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	}
 
 	spin_lock(&device->write_lock);
 	q_info = &device->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
 	if (!q_info) {
-		HAL_MSG_ERROR("cannot write to shared Q's");
+		dprintk(VIDC_ERR, "cannot write to shared Q's");
 		goto err_q_write;
 	}
 
@@ -408,7 +407,7 @@
 				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
 		result = 0;
 	} else {
-		HAL_MSG_ERROR("vidc_hal_iface_cmdq_write:queue_full");
+		dprintk(VIDC_ERR, "vidc_hal_iface_cmdq_write:queue_full");
 	}
 err_q_write:
 	spin_unlock(&device->write_lock);
@@ -422,13 +421,13 @@
 	struct vidc_iface_q_info *q_info;
 
 	if (!pkt) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	}
 	spin_lock(&device->read_lock);
 	if (device->iface_queues[VIDC_IFACEQ_MSGQ_IDX].
 		q_array.align_virtual_addr == 0) {
-		HAL_MSG_ERROR("cannot read from shared MSG Q's");
+		dprintk(VIDC_ERR, "cannot read from shared MSG Q's");
 		rc = -ENODATA;
 		goto read_error;
 	}
@@ -441,7 +440,7 @@
 				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
 		rc = 0;
 	} else {
-		HAL_MSG_ERROR("vidc_hal_iface_msgq_read:queue_empty");
+		dprintk(VIDC_INFO, "vidc_hal_iface_msgq_read:queue_empty");
 		rc = -ENODATA;
 	}
 read_error:
@@ -456,13 +455,13 @@
 	struct vidc_iface_q_info *q_info;
 
 	if (!pkt) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	}
 	spin_lock(&device->read_lock);
 	if (device->iface_queues[VIDC_IFACEQ_DBGQ_IDX].
 		q_array.align_virtual_addr == 0) {
-		HAL_MSG_ERROR("cannot read from shared DBG Q's");
+		dprintk(VIDC_ERR, "cannot read from shared DBG Q's");
 		rc = -ENODATA;
 		goto dbg_error;
 	}
@@ -474,7 +473,7 @@
 			1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
 		rc = 0;
 	} else {
-		HAL_MSG_MEDIUM("vidc_hal_iface_dbgq_read:queue_empty");
+		dprintk(VIDC_INFO, "vidc_hal_iface_dbgq_read:queue_empty");
 		rc = -ENODATA;
 	}
 dbg_error:
@@ -529,7 +528,7 @@
 					dev->hal_client,
 			VIDC_IFACEQ_TABLE_SIZE, 1, SMEM_UNCACHED, domain);
 	if (rc) {
-		HAL_MSG_ERROR("%s:iface_q_table_alloc_fail", __func__);
+		dprintk(VIDC_ERR, "iface_q_table_alloc_fail");
 		return -ENOMEM;
 	}
 	q_tbl_hdr = (struct hfi_queue_table_header *)
@@ -549,8 +548,7 @@
 				dev->hal_client, VIDC_IFACEQ_QUEUE_SIZE,
 				1, SMEM_UNCACHED, domain);
 		if (rc) {
-			HAL_MSG_ERROR("%s:iface_q_table_alloc[%d]_fail",
-						__func__, i);
+			dprintk(VIDC_ERR, "iface_q_table_alloc[%d]_fail", i);
 			vidc_hal_interface_queues_release(dev);
 			return -ENOMEM;
 		} else {
@@ -591,22 +589,55 @@
 static int vidc_hal_core_start_cpu(struct hal_device *device)
 {
 	u32 ctrl_status = 0, count = 0, rc = 0;
+	int max_tries = 100;
 	write_register(device->hal_data->register_base_addr,
 			VIDC_WRAPPER_INTR_MASK, 0, 0);
 	write_register(device->hal_data->register_base_addr,
 			VIDC_CPU_CS_SCIACMDARG3, 1, 0);
-	while (!ctrl_status && count < 25) {
+	while (!ctrl_status && count < max_tries) {
 		ctrl_status = read_register(
 		device->hal_data->register_base_addr,
 		VIDC_CPU_CS_SCIACMDARG0);
 		usleep_range(500, 1000);
 		count++;
 	}
-	if (count >= 25)
+	if (count >= max_tries)
 		rc = -ETIME;
 	return rc;
 }
 
+static void set_vbif_registers(struct hal_device *device)
+{
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00000FFF, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_OUT_AXI_AOOO, 0x0FFF0FFF, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VENUS_VBIF_CLK_ON, 1, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_RD_LIM_CONF0, 0x10101001, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_RD_LIM_CONF1, 0x10101010, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_RD_LIM_CONF2, 0x10101010, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_RD_LIM_CONF3, 0x00000010, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_WR_LIM_CONF0, 0x1010100f, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_WR_LIM_CONF1, 0x10101010, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_WR_LIM_CONF2, 0x10101010, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_WR_LIM_CONF3, 0x00000010, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_OUT_RD_LIM_CONF0, 0x00001010, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_OUT_WR_LIM_CONF0, 0x00001010, 0);
+	write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_ARB_CTL, 0x00000030, 0);
+}
+
 int vidc_hal_core_init(void *device, int domain)
 {
 	struct hfi_cmd_sys_init_packet pkt;
@@ -616,7 +647,7 @@
 	if (device) {
 		dev = device;
 	} else {
-		HAL_MSG_ERROR("%s:invalid device", __func__);
+		dprintk(VIDC_ERR, "Invalid device");
 		return -ENODEV;
 	}
 	enable_irq(dev->hal_data->irq);
@@ -627,34 +658,34 @@
 	/*Disable Dynamic clock gating for Venus VBIF*/
 	write_register(dev->hal_data->register_base_addr,
 				   VIDC_VENUS_VBIF_CLK_ON, 1, 0);
-
+	set_vbif_registers(dev);
 	if (!dev->hal_client) {
 		dev->hal_client = msm_smem_new_client(SMEM_ION);
 		if (dev->hal_client == NULL) {
-			HAL_MSG_ERROR("Failed to alloc ION_Client");
+			dprintk(VIDC_ERR, "Failed to alloc ION_Client");
 			rc = -ENODEV;
 			goto err_no_mem;
 		}
 
-		HAL_MSG_ERROR("Device_Virt_Address : 0x%x,"
+		dprintk(VIDC_DBG, "Device_Virt_Address : 0x%x,"
 		"Register_Virt_Addr: 0x%x",
 		dev->hal_data->device_base_addr,
 		(u32) dev->hal_data->register_base_addr);
 
 		rc = vidc_hal_interface_queues_init(dev, domain);
 		if (rc) {
-			HAL_MSG_ERROR("failed to init queues");
+			dprintk(VIDC_ERR, "failed to init queues");
 			rc = -ENOMEM;
 			goto err_no_mem;
 		}
 	} else {
-		HAL_MSG_ERROR("hal_client exists");
+		dprintk(VIDC_ERR, "hal_client exists");
 		rc = -EEXIST;
 		goto err_no_mem;
 	}
 	rc = vidc_hal_core_start_cpu(dev);
 	if (rc) {
-		HAL_MSG_ERROR("Failed to start core");
+		dprintk(VIDC_ERR, "Failed to start core");
 		rc = -ENODEV;
 		goto err_no_dev;
 	}
@@ -679,14 +710,14 @@
 	if (device) {
 		dev = device;
 	} else {
-		HAL_MSG_ERROR("%s:invalid device", __func__);
+		dprintk(VIDC_ERR, "invalid device");
 		return -ENODEV;
 	}
 	write_register(dev->hal_data->register_base_addr,
 		VIDC_CPU_CS_SCIACMDARG3, 0, 0);
 	disable_irq_nosync(dev->hal_data->irq);
 	vidc_hal_interface_queues_release(dev);
-	HAL_MSG_INFO("\nHAL exited\n");
+	dprintk(VIDC_INFO, "HAL exited\n");
 	return 0;
 }
 
@@ -699,7 +730,7 @@
 	if (device) {
 		dev = device;
 	} else {
-		HAL_MSG_ERROR("%s:invalid device", __func__);
+		dprintk(VIDC_ERR, "invalid device");
 		return -ENODEV;
 	}
 	pkt.size = sizeof(struct hfi_cmd_sys_pc_prep_packet);
@@ -723,11 +754,11 @@
 	if ((intr_status & VIDC_WRAPPER_INTR_STATUS_A2H_BMSK) ||
 		(intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) {
 		device->intr_status |= intr_status;
-		HAL_MSG_ERROR("INTERRUPT for device: 0x%x: "
+		dprintk(VIDC_DBG, "INTERRUPT for device: 0x%x: "
 			"times: %d interrupt_status: %d",
 			(u32) device, ++device->reg_count, intr_status);
 	} else {
-		HAL_MSG_ERROR("SPURIOUS_INTR for device: 0x%x: "
+		dprintk(VIDC_WARN, "SPURIOUS_INTR for device: 0x%x: "
 			"times: %d interrupt_status: %d",
 			(u32) device, ++device->spur_count, intr_status);
 	}
@@ -735,7 +766,7 @@
 			VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
 	write_register(device->hal_data->register_base_addr,
 			VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
-	HAL_MSG_ERROR("Cleared WRAPPER/A2H interrupt");
+	dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
 }
 
 int vidc_hal_core_set_resource(void *device,
@@ -747,7 +778,7 @@
 	struct hal_device *dev;
 
 	if (!device || !resource_hdr || !resource_value) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "set_res: Invalid Params");
 		return -EINVAL;
 	} else {
 		dev = device;
@@ -777,8 +808,8 @@
 		break;
 	}
 	default:
-		HAL_MSG_INFO("In %s called for resource %d",
-					 __func__, resource_hdr->resource_id);
+		dprintk(VIDC_INFO, "Invalid res_id in set_res %d",
+						resource_hdr->resource_id);
 		break;
 	}
 	return rc;
@@ -792,7 +823,7 @@
 	struct hal_device *dev;
 
 	if (!device || !resource_hdr) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Inv-Params in rel_res");
 		return -EINVAL;
 	} else {
 		dev = device;
@@ -817,7 +848,7 @@
 	if (device) {
 		dev = device;
 	} else {
-		HAL_MSG_ERROR("%s:invalid device", __func__);
+		dprintk(VIDC_ERR, "invalid device");
 		return -ENODEV;
 	}
 	pkt.size = sizeof(struct hfi_cmd_sys_ping_packet);
@@ -856,7 +887,8 @@
 		buffer = HFI_BUFFER_INTERNAL_PERSIST;
 		break;
 	default:
-		HAL_MSG_ERROR("Invalid buffer type : 0x%x\n", hal_buffer);
+		dprintk(VIDC_ERR, "Invalid buffer :0x%x\n",
+				hal_buffer);
 		buffer = 0;
 		break;
 	}
@@ -871,13 +903,13 @@
 	struct hal_session *session;
 
 	if (!sess || !pdata) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params");
 		return -EINVAL;
 	} else {
 		session = sess;
 	}
 
-	HAL_MSG_INFO("IN func: %s, with property id: %d", __func__, ptype);
+	dprintk(VIDC_INFO, "in set_prop,with prop id: 0x%x", ptype);
 	pkt->size = sizeof(struct hfi_cmd_session_set_property_packet);
 	pkt->packet_type = HFI_CMD_SESSION_SET_PROPERTY;
 	pkt->session_id = (u32) session;
@@ -979,7 +1011,7 @@
 			(struct hal_nal_stream_format_supported *)pdata;
 		pkt->rg_property_data[0] =
 			HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT;
-		HAL_MSG_ERROR("\ndata is :%d",
+		dprintk(VIDC_DBG, "data is :%d",
 				prop->nal_stream_format_supported);
 		switch (prop->nal_stream_format_supported) {
 		case HAL_NAL_FORMAT_STARTCODES:
@@ -1003,7 +1035,7 @@
 				HFI_NAL_FORMAT_FOUR_BYTE_LENGTH;
 			break;
 		default:
-			HAL_MSG_ERROR("Invalid nal format: 0x%x",
+			dprintk(VIDC_ERR, "Invalid nal format: 0x%x",
 				  prop->nal_stream_format_supported);
 			break;
 		}
@@ -1023,7 +1055,7 @@
 			pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DISPLAY;
 			break;
 		default:
-			HAL_MSG_ERROR("invalid output order: 0x%x",
+			dprintk(VIDC_ERR, "invalid output order: 0x%x",
 						  *data);
 			break;
 		}
@@ -1110,7 +1142,7 @@
 			pkt->rg_property_data[1] = HFI_DIVX_FORMAT_6;
 			break;
 		default:
-			HAL_MSG_ERROR("Invalid divx format: 0x%x", *data);
+			dprintk(VIDC_ERR, "Invalid divx format: 0x%x", *data);
 			break;
 		}
 		pkt->size += sizeof(u32) * 2;
@@ -1199,13 +1231,15 @@
 				hfi->cabac_model = HFI_H264_CABAC_MODEL_2;
 				break;
 			default:
-				HAL_MSG_ERROR("Invalid cabac model 0x%x",
-							  prop->entropy_mode);
+				dprintk(VIDC_ERR,
+					"Invalid cabac model 0x%x",
+					prop->entropy_mode);
 				break;
 			}
 		break;
 		default:
-			HAL_MSG_ERROR("Invalid entropy selected: 0x%x",
+			dprintk(VIDC_ERR,
+				"Invalid entropy selected: 0x%x",
 				prop->cabac_model);
 			break;
 		}
@@ -1215,11 +1249,11 @@
 	}
 	case HAL_PARAM_VENC_RATE_CONTROL:
 	{
-		u32 *rc_mode;
+		u32 *rc;
 		pkt->rg_property_data[0] =
 			HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
-		rc_mode = (u32 *)pdata;
-		switch ((enum hal_rate_control) *rc_mode) {
+		rc = (u32 *)pdata;
+		switch ((enum hal_rate_control) *rc) {
 		case HAL_RATE_CONTROL_OFF:
 		pkt->rg_property_data[1] = HFI_RATE_CONTROL_OFF;
 			break;
@@ -1236,7 +1270,7 @@
 		pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_VFR;
 			break;
 		default:
-			HAL_MSG_ERROR("Invalid Rate control setting: 0x%x",
+			dprintk(VIDC_ERR, "Invalid Rate control setting: 0x%x",
 						  (int) pdata);
 			break;
 		}
@@ -1286,7 +1320,7 @@
 			hfi->mode = HFI_H264_DB_MODE_ALL_BOUNDARY;
 			break;
 		default:
-			HAL_MSG_ERROR("Invalid deblocking mode: 0x%x",
+			dprintk(VIDC_ERR, "Invalid deblocking mode: 0x%x",
 						  prop->mode);
 			break;
 		}
@@ -1354,7 +1388,7 @@
 			hfi->mode = HFI_INTRA_REFRESH_RANDOM;
 			break;
 		default:
-			HAL_MSG_ERROR("Invalid intra refresh setting: 0x%x",
+			dprintk(VIDC_ERR, "Invalid intra refresh setting: 0x%x",
 				prop->mode);
 			break;
 		}
@@ -1387,7 +1421,7 @@
 			hfi->multi_slice = HFI_MULTI_SLICE_BY_BYTE_COUNT;
 			break;
 		default:
-			HAL_MSG_ERROR("Invalid slice settings: 0x%x",
+			dprintk(VIDC_ERR, "Invalid slice settings: 0x%x",
 				prop->multi_slice);
 			break;
 		}
@@ -1437,7 +1471,7 @@
 	case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
 	case HAL_PARAM_VENC_LOW_LATENCY:
 	default:
-		HAL_MSG_INFO("DEFAULT: Calling 0x%x", ptype);
+		dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
 		break;
 	}
 	if (vidc_hal_iface_cmdq_write(session->device, pkt))
@@ -1451,12 +1485,12 @@
 	struct hal_session *session;
 
 	if (!sess || !pdata) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	} else {
 		session = sess;
 	}
-	HAL_MSG_INFO("IN func: %s, with property id: %d", __func__, ptype);
+	dprintk(VIDC_INFO, "IN func: , with property id: %d", ptype);
 
 	switch (ptype) {
 	case HAL_CONFIG_FRAME_RATE:
@@ -1562,7 +1596,7 @@
 	case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
 	case HAL_PARAM_VENC_LOW_LATENCY:
 	default:
-		HAL_MSG_INFO("DEFAULT: Calling 0x%x", ptype);
+		dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
 		break;
 	}
 	return 0;
@@ -1578,7 +1612,7 @@
 	if (device) {
 		dev = device;
 	} else {
-		HAL_MSG_ERROR("%s:invalid device", __func__);
+		dprintk(VIDC_ERR, ":invalid device");
 		return NULL;
 	}
 
@@ -1611,7 +1645,7 @@
 	if (session_id) {
 		session = session_id;
 	} else {
-		HAL_MSG_ERROR("%s:invalid session", __func__);
+		dprintk(VIDC_ERR, ":invalid session");
 		return -ENODEV;
 	}
 
@@ -1647,7 +1681,7 @@
 	struct hal_session *session;
 
 	if (!sess || !buffer_info) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	} else {
 		session = sess;
@@ -1694,7 +1728,7 @@
 		pkt->buffer_type = buffer;
 	else
 		return -EINVAL;
-	HAL_MSG_INFO("set buffers: 0x%x", buffer_info->buffer_type);
+	dprintk(VIDC_INFO, "set buffers: 0x%x", buffer_info->buffer_type);
 	if (vidc_hal_iface_cmdq_write(session->device, pkt))
 		rc = -ENOTEMPTY;
 	return rc;
@@ -1711,7 +1745,7 @@
 	struct hal_session *session;
 
 	if (!sess || !buffer_info) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	} else {
 		session = sess;
@@ -1755,7 +1789,7 @@
 		pkt->buffer_type = buffer;
 	else
 		return -EINVAL;
-	HAL_MSG_INFO("Release buffers: 0x%x", buffer_info->buffer_type);
+	dprintk(VIDC_INFO, "Release buffers: 0x%x", buffer_info->buffer_type);
 	if (vidc_hal_iface_cmdq_write(session->device, pkt))
 		rc = -ENOTEMPTY;
 	return rc;
@@ -1803,7 +1837,7 @@
 	struct hal_session *session;
 
 	if (!sess || !input_frame) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	} else {
 		session = sess;
@@ -1825,7 +1859,7 @@
 		pkt.filled_len = input_frame->filled_len;
 		pkt.input_tag = input_frame->clnt_data;
 		pkt.packet_buffer = (u8 *) input_frame->device_addr;
-		HAL_MSG_ERROR("### Q DECODER INPUT BUFFER ###");
+		dprintk(VIDC_DBG, "Q DECODER INPUT BUFFER");
 		if (vidc_hal_iface_cmdq_write(session->device, &pkt))
 			rc = -ENOTEMPTY;
 	} else {
@@ -1846,7 +1880,7 @@
 		pkt.filled_len = input_frame->filled_len;
 		pkt.input_tag = input_frame->clnt_data;
 		pkt.packet_buffer = (u8 *) input_frame->device_addr;
-		HAL_MSG_ERROR("### Q ENCODER INPUT BUFFER ###");
+		dprintk(VIDC_DBG, "Q ENCODER INPUT BUFFER");
 		if (vidc_hal_iface_cmdq_write(session->device, &pkt))
 			rc = -ENOTEMPTY;
 	}
@@ -1861,7 +1895,7 @@
 	struct hal_session *session;
 
 	if (!sess || !output_frame) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	} else {
 		session = sess;
@@ -1878,7 +1912,7 @@
 	pkt.extra_data_buffer =
 		(u8 *) output_frame->extradata_addr;
 
-	HAL_MSG_INFO("### Q OUTPUT BUFFER ###");
+	dprintk(VIDC_INFO, "### Q OUTPUT BUFFER ###");
 	if (vidc_hal_iface_cmdq_write(session->device, &pkt))
 		rc = -ENOTEMPTY;
 	return rc;
@@ -1893,7 +1927,7 @@
 	struct hal_session *session;
 
 	if (!sess || !seq_hdr) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	} else {
 		session = sess;
@@ -1920,7 +1954,7 @@
 	struct hal_session *session;
 
 	if (!sess || !seq_hdr) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return -EINVAL;
 	} else {
 		session = sess;
@@ -1947,7 +1981,7 @@
 	if (sess) {
 		session = sess;
 	} else {
-		HAL_MSG_ERROR("%s:invalid session", __func__);
+		dprintk(VIDC_ERR, ":invalid session");
 		return -ENODEV;
 	}
 
@@ -1970,7 +2004,7 @@
 	if (sess) {
 		session = sess;
 	} else {
-		HAL_MSG_ERROR("%s:invalid session", __func__);
+		dprintk(VIDC_ERR, ":invalid session");
 		return -ENODEV;
 	}
 
@@ -1991,7 +2025,7 @@
 		pkt.flush_type = HFI_FLUSH_ALL;
 		break;
 	default:
-		HAL_MSG_ERROR("Invalid flush mode: 0x%x\n", flush_mode);
+		dprintk(VIDC_ERR, "Invalid flush mode: 0x%x\n", flush_mode);
 		break;
 	}
 	if (vidc_hal_iface_cmdq_write(session->device, &pkt))
@@ -2038,12 +2072,12 @@
 						FIRMWARE_SIZE))) {
 				return 0;
 			} else {
-				HAL_MSG_INFO("Device not registered");
+				dprintk(VIDC_INFO, "Device not registered");
 				return -EINVAL;
 			}
 		}
 	} else {
-		HAL_MSG_INFO("no device Registered");
+		dprintk(VIDC_INFO, "no device Registered");
 	}
 	return -EINVAL;
 }
@@ -2053,9 +2087,9 @@
 	struct hal_device *device = list_first_entry(
 		&hal_ctxt.dev_head, struct hal_device, list);
 
-	HAL_MSG_INFO(" GOT INTERRUPT %s() ", __func__);
+	dprintk(VIDC_INFO, " GOT INTERRUPT () ");
 	if (!device->callback) {
-		HAL_MSG_ERROR("No callback function	"
+		dprintk(VIDC_ERR, "No callback function	"
 					  "to process interrupt: %p\n", device);
 		return;
 	}
@@ -2068,10 +2102,10 @@
 static irqreturn_t vidc_hal_isr(int irq, void *dev)
 {
 	struct hal_device *device = dev;
-	HAL_MSG_MEDIUM("\n vidc_hal_isr() %d ", irq);
+	dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
 	disable_irq_nosync(irq);
 	queue_work(device->vidc_workq, &vidc_hal_work);
-	HAL_MSG_MEDIUM("\n vidc_hal_isr() %d ", irq);
+	dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
 	return IRQ_HANDLED;
 }
 
@@ -2085,19 +2119,19 @@
 
 	if (device_id || !reg_base || !reg_size ||
 			!irq || !callback) {
-		HAL_MSG_ERROR("Invalid Paramters");
+		dprintk(VIDC_ERR, "Invalid Paramters");
 		return NULL;
 	} else {
-		HAL_MSG_INFO("entered %s, device_id: %d", __func__, device_id);
+		dprintk(VIDC_INFO, "entered , device_id: %d", device_id);
 	}
 
 	if (vidc_hal_check_core_registered(hal_ctxt, fw_base_addr,
 						reg_base, reg_size, irq)) {
-		HAL_MSG_LOW("HAL_DATA will be assigned now");
+		dprintk(VIDC_DBG, "HAL_DATA will be assigned now");
 		hal = (struct hal_data *)
 			kzalloc(sizeof(struct hal_data), GFP_KERNEL);
 		if (!hal) {
-			HAL_MSG_ERROR("Failed to alloc");
+			dprintk(VIDC_ERR, "Failed to alloc");
 			return NULL;
 		}
 		hal->irq = irq;
@@ -2105,20 +2139,21 @@
 		hal->register_base_addr =
 			ioremap_nocache(reg_base, reg_size);
 		if (!hal->register_base_addr) {
-			HAL_MSG_ERROR("could not map reg addr %d of size %d",
-						  reg_base, reg_size);
+			dprintk(VIDC_ERR,
+				"could not map reg addr %d of size %d",
+				reg_base, reg_size);
 			goto err_map;
 		}
 		INIT_LIST_HEAD(&hal_ctxt.dev_head);
 	} else {
-		HAL_MSG_ERROR("Core present/Already added");
+		dprintk(VIDC_ERR, "Core present/Already added");
 		return NULL;
 	}
 
 	hdevice = (struct hal_device *)
 			kzalloc(sizeof(struct hal_device), GFP_KERNEL);
 	if (!hdevice) {
-		HAL_MSG_ERROR("failed to allocate new device");
+		dprintk(VIDC_ERR, "failed to allocate new device");
 		goto err_map;
 	}
 
@@ -2132,14 +2167,14 @@
 	hdevice->vidc_workq = create_singlethread_workqueue(
 		"msm_vidc_workerq");
 	if (!hdevice->vidc_workq) {
-		HAL_MSG_ERROR("%s: create workq failed\n", __func__);
+		dprintk(VIDC_ERR, ": create workq failed\n");
 		goto error_createq;
 	}
 
 	rc = request_irq(irq, vidc_hal_isr, IRQF_TRIGGER_HIGH,
 			"msm_vidc", hdevice);
 	if (unlikely(rc)) {
-		HAL_MSG_ERROR("%s() :request_irq failed\n", __func__);
+		dprintk(VIDC_ERR, "() :request_irq failed\n");
 		goto error_irq_fail;
 	}
 	disable_irq_nosync(irq);
diff --git a/drivers/media/video/msm_vidc/vidc_hal.h b/drivers/media/video/msm_vidc/vidc_hal.h
index 8e7c3d3..c586172 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.h
+++ b/drivers/media/video/msm_vidc/vidc_hal.h
@@ -20,20 +20,6 @@
 #include "msm_smem.h"
 #include "vidc_hal_helper.h"
 
-#ifdef HAL_MSG_LOG
-#define HAL_MSG_LOW(x...)		pr_info(KERN_INFO x)
-#define HAL_MSG_MEDIUM(x...)	pr_info(KERN_INFO x)
-#define HAL_MSG_HIGH(x...)		pr_info(KERN_INFO x)
-#else
-#define HAL_MSG_LOW(x...)
-#define HAL_MSG_MEDIUM(x...)
-#define HAL_MSG_HIGH(x...)
-#endif
-
-#define HAL_MSG_ERROR(x...)		pr_err(KERN_INFO x)
-#define HAL_MSG_FATAL(x...)		pr_err(KERN_INFO x)
-#define HAL_MSG_INFO(x...)		pr_info(KERN_INFO x)
-
 #define HFI_MASK_QHDR_TX_TYPE			0xFF000000
 #define HFI_MASK_QHDR_RX_TYPE			0x00FF0000
 #define HFI_MASK_QHDR_PRI_TYPE			0x0000FF00
diff --git a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c b/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
index 364faa9..795024d 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
+++ b/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include "vidc_hal.h"
+#include "msm_vidc_debug.h"
 
 static enum vidc_status vidc_map_hal_err_status(int hfi_err)
 {
@@ -81,10 +82,10 @@
 	struct hfi_frame_size frame_sz;
 	u8 *data_ptr;
 	int prop_id;
-	HAL_MSG_LOW("RECEIVED:EVENT_NOTIFY");
+	dprintk(VIDC_DBG, "RECEIVED:EVENT_NOTIFY");
 	if (sizeof(struct hfi_msg_event_notify_packet)
 		> pkt->size) {
-		HAL_MSG_ERROR("hal_process_session_init_done:bad_pkt_size");
+		dprintk(VIDC_ERR, "hal_process_session_init_done:bad_pkt_size");
 		return;
 	}
 
@@ -139,30 +140,30 @@
 static void hal_process_event_notify(struct hal_device *device,
 	struct hfi_msg_event_notify_packet *pkt)
 {
-	HAL_MSG_LOW("RECVD:EVENT_NOTIFY");
+	dprintk(VIDC_DBG, "RECVD:EVENT_NOTIFY");
 
 	if (!device || !pkt ||
 		pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params");
 		return;
 	}
 
 	switch (pkt->event_id) {
 	case HFI_EVENT_SYS_ERROR:
-		HAL_MSG_INFO("HFI_EVENT_SYS_ERROR");
+		dprintk(VIDC_INFO, "HFI_EVENT_SYS_ERROR");
 		break;
 	case HFI_EVENT_SESSION_ERROR:
-		HAL_MSG_INFO("HFI_EVENT_SESSION_ERROR");
+		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_ERROR");
 		break;
 	case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
-		HAL_MSG_INFO("HFI_EVENT_SESSION_SEQUENCE_CHANGED");
+		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED");
 		hal_process_sess_evt_seq_changed(device, pkt);
 		break;
 	case HFI_EVENT_SESSION_PROPERTY_CHANGED:
-		HAL_MSG_INFO("HFI_EVENT_SESSION_PROPERTY_CHANGED");
+		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED");
 		break;
 	default:
-		HAL_MSG_INFO("hal_process_event_notify:unkown_event_id");
+		dprintk(VIDC_INFO, "hal_process_event_notify:unkown_event_id");
 		break;
 	}
 }
@@ -177,9 +178,9 @@
 	int prop_id;
 	enum vidc_status status = VIDC_ERR_NONE;
 
-	HAL_MSG_LOW("RECEIVED:SYS_INIT_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SYS_INIT_DONE");
 	if (sizeof(struct hfi_msg_sys_init_done_packet) > pkt->size) {
-		HAL_MSG_ERROR("hal_process_sys_init_done:bad_pkt_size: %d",
+		dprintk(VIDC_ERR, "hal_process_sys_init_done:bad_pkt_size: %d",
 				pkt->size);
 		return;
 	}
@@ -188,7 +189,7 @@
 
 	if (!status) {
 		if (pkt->num_properties == 0) {
-			HAL_MSG_ERROR("hal_process_sys_init_done:"
+			dprintk(VIDC_ERR, "hal_process_sys_init_done:"
 						"no_properties");
 			status = VIDC_ERR_FAIL;
 			goto err_no_prop;
@@ -198,7 +199,7 @@
 			hfi_msg_sys_init_done_packet) + sizeof(u32);
 
 		if (rem_bytes == 0) {
-			HAL_MSG_ERROR("hal_process_sys_init_done:"
+			dprintk(VIDC_ERR, "hal_process_sys_init_done:"
 						"missing_prop_info");
 			status = VIDC_ERR_FAIL;
 			goto err_no_prop;
@@ -231,7 +232,7 @@
 				break;
 			}
 			default:
-				HAL_MSG_ERROR("hal_process_sys_init_done:"
+				dprintk(VIDC_ERR, "hal_process_sys_init_done:"
 							"bad_prop_id");
 				status = VIDC_ERR_BAD_PARAM;
 				break;
@@ -259,11 +260,12 @@
 	enum vidc_status status = VIDC_ERR_NONE;
 	u32 pkt_size;
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	HAL_MSG_ERROR("RECEIVED:SYS_RELEASE_RESOURCE_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SYS_RELEASE_RESOURCE_DONE");
 	pkt_size = sizeof(struct hfi_msg_sys_release_resource_done_packet);
 	if (pkt_size > pkt->size) {
-		HAL_MSG_ERROR("hal_process_sys_rel_resource_done:bad size:%d",
-				pkt->size);
+		dprintk(VIDC_ERR,
+			"hal_process_sys_rel_resource_done:bad size:%d",
+			pkt->size);
 		return;
 	}
 	status = vidc_map_hal_err_status((u32)pkt->error_type);
@@ -290,14 +292,15 @@
 	u32 req_bytes;
 	enum vidc_status rc = VIDC_ERR_NONE;
 
-	HAL_MSG_LOW("Entered %s", __func__);
+	dprintk(VIDC_DBG, "Entered ");
 	req_bytes = prop->size - sizeof(
 	struct hfi_msg_session_property_info_packet);
 
 	if (req_bytes == 0 || (req_bytes % sizeof(
 		struct hfi_buffer_requirements))) {
-		HAL_MSG_ERROR("hal_process_sess_get_prop_buf_req:bad_pkt_size:"
-					" %d", req_bytes);
+		dprintk(VIDC_ERR,
+			"hal_process_sess_get_prop_buf_req:bad_pkt_size: %d",
+			req_bytes);
 		return;
 	}
 
@@ -309,11 +312,11 @@
 			buffer_count_actual)
 			|| (hfi_buf_req->buffer_alignment == 0)
 			|| (hfi_buf_req->buffer_size == 0)) {
-			HAL_MSG_ERROR("hal_process_sess_get_prop_buf_req:"
+			dprintk(VIDC_ERR, "hal_process_sess_get_prop_buf_req:"
 						"bad_buf_req");
 			rc = VIDC_ERR_FAIL;
 		}
-		HAL_MSG_LOW("got buffer requirements for: %d",
+		dprintk(VIDC_DBG, "got buffer requirements for: %d",
 					hfi_buf_req->buffer_type);
 		switch (hfi_buf_req->buffer_type) {
 		case HFI_BUFFER_INPUT:
@@ -362,8 +365,9 @@
 				HAL_BUFFER_INTERNAL_PERSIST;
 			break;
 		default:
-			HAL_MSG_ERROR("%s: bad_buffer_type: %d",
-				__func__, hfi_buf_req->buffer_type);
+			dprintk(VIDC_ERR,
+			"hal_process_sess_get_prop_buf_req: bad_buffer_type: %d",
+			hfi_buf_req->buffer_type);
 			break;
 		}
 		req_bytes -= sizeof(struct hfi_buffer_requirements);
@@ -377,15 +381,16 @@
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct buffer_requirements buff_req;
 
-	HAL_MSG_INFO("Received SESSION_PROPERTY_INFO");
+	dprintk(VIDC_DBG, "Received SESSION_PROPERTY_INFO");
 
 	if (pkt->size < sizeof(struct hfi_msg_session_property_info_packet)) {
-		HAL_MSG_ERROR("hal_process_session_prop_info:bad_pkt_size");
+		dprintk(VIDC_ERR, "hal_process_session_prop_info:bad_pkt_size");
 		return;
 	}
 
 	if (pkt->num_properties == 0) {
-		HAL_MSG_ERROR("hal_process_session_prop_info:no_properties");
+		dprintk(VIDC_ERR,
+			"hal_process_session_prop_info:no_properties");
 		return;
 	}
 
@@ -404,7 +409,7 @@
 		device->callback(SESSION_PROPERTY_INFO, &cmd_done);
 		break;
 	default:
-		HAL_MSG_ERROR("hal_process_session_prop_info:"
+		dprintk(VIDC_ERR, "hal_process_session_prop_info:"
 					"unknown_prop_id: %d",
 				pkt->rg_property_data[0]);
 		break;
@@ -417,10 +422,10 @@
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct vidc_hal_session_init_done session_init_done;
 
-	HAL_MSG_LOW("RECEIVED:SESSION_INIT_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_INIT_DONE");
 	if (sizeof(struct hfi_msg_sys_session_init_done_packet)
 		> pkt->size) {
-		HAL_MSG_ERROR("hal_process_session_init_done:bad_pkt_size");
+		dprintk(VIDC_ERR, "hal_process_session_init_done:bad_pkt_size");
 		return;
 	}
 
@@ -445,11 +450,11 @@
 	struct hfi_msg_session_load_resources_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
-	HAL_MSG_LOW("RECEIVED:SESSION_LOAD_RESOURCES_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_LOAD_RESOURCES_DONE");
 
 	if (sizeof(struct hfi_msg_session_load_resources_done_packet) !=
 		pkt->size) {
-		HAL_MSG_ERROR("hal_process_session_load_res_done:"
+		dprintk(VIDC_ERR, "hal_process_session_load_res_done:"
 		" bad packet size: %d", pkt->size);
 		return;
 	}
@@ -470,10 +475,10 @@
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
-	HAL_MSG_LOW("RECEIVED:SESSION_FLUSH_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_FLUSH_DONE");
 
 	if (sizeof(struct hfi_msg_session_flush_done_packet) != pkt->size) {
-		HAL_MSG_ERROR("hal_process_session_flush_done: "
+		dprintk(VIDC_ERR, "hal_process_session_flush_done: "
 		"bad packet size: %d", pkt->size);
 		return;
 	}
@@ -493,11 +498,11 @@
 {
 	struct msm_vidc_cb_data_done data_done;
 
-	HAL_MSG_LOW("RECEIVED:SESSION_ETB_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_ETB_DONE");
 
 	if (!pkt || pkt->size !=
 		sizeof(struct hfi_msg_session_empty_buffer_done_packet)) {
-		HAL_MSG_ERROR("hal_process_session_etb_done:bad_pkt_size");
+		dprintk(VIDC_ERR, "hal_process_session_etb_done:bad_pkt_size");
 		return;
 	}
 
@@ -525,13 +530,13 @@
 	struct hal_session *session;
 
 	if (!msg_hdr) {
-		HAL_MSG_ERROR("Invalid Params in %s", __func__);
+		dprintk(VIDC_ERR, "Invalid Params in ");
 		return;
 	}
 
 	session = (struct hal_session *)
 		((struct hal_session *)	pack->session_id)->session_id;
-	HAL_MSG_ERROR("RECEIVED:SESSION_FTB_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_FTB_DONE");
 
 	memset(&data_done, 0, sizeof(struct msm_vidc_cb_data_done));
 
@@ -542,11 +547,13 @@
 		if (sizeof(struct
 			hfi_msg_session_fill_buffer_done_compressed_packet)
 			!= pkt->size) {
-			HAL_MSG_ERROR("%s: bad_pkt_size", __func__);
+			dprintk(VIDC_ERR,
+				"hal_process_session_ftb_done: bad_pkt_size");
 			return;
 		} else if (pkt->error_type != HFI_ERR_NONE) {
-			HAL_MSG_ERROR("%s: got buffer back with error %x",
-					__func__, pkt->error_type);
+			dprintk(VIDC_ERR,
+				"got buffer back with error %x",
+				pkt->error_type);
 			/* Proceed with the FBD */
 		}
 
@@ -570,6 +577,8 @@
 		data_done.output_done.packet_buffer1 = pkt->packet_buffer;
 		data_done.output_done.extra_data_buffer =
 			pkt->extra_data_buffer;
+		dprintk(VIDC_DBG, "FBD: Received buf: %p, of len: %d\n",
+				   pkt->packet_buffer, pkt->filled_len);
 	} else if (is_decoder == 1) {
 		struct hfi_msg_session_fbd_uncompressed_plane0_packet *pkt =
 		(struct	hfi_msg_session_fbd_uncompressed_plane0_packet *)
@@ -577,7 +586,7 @@
 		if (sizeof(struct
 		hfi_msg_session_fbd_uncompressed_plane0_packet)
 		> pkt->size) {
-			HAL_MSG_ERROR("hal_process_session_ftb_done:"
+			dprintk(VIDC_ERR, "hal_process_session_ftb_done:"
 						"bad_pkt_size");
 			return;
 		}
@@ -623,11 +632,11 @@
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
-	HAL_MSG_LOW("RECEIVED:SESSION_START_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_START_DONE");
 
 	if (!pkt || pkt->size !=
 		sizeof(struct hfi_msg_session_start_done_packet)) {
-		HAL_MSG_ERROR("hal_process_session_start_done:"
+		dprintk(VIDC_ERR, "hal_process_session_start_done:"
 		"bad packet/packet size: %d", pkt->size);
 		return;
 	}
@@ -647,11 +656,11 @@
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
-	HAL_MSG_LOW("RECEIVED:SESSION_STOP_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_STOP_DONE");
 
 	if (!pkt || pkt->size !=
 		sizeof(struct hfi_msg_session_stop_done_packet)) {
-		HAL_MSG_ERROR("hal_process_session_stop_done:"
+		dprintk(VIDC_ERR, "hal_process_session_stop_done:"
 		"bad packet/packet size: %d", pkt->size);
 		return;
 	}
@@ -671,11 +680,11 @@
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
-	HAL_MSG_LOW("RECEIVED:SESSION_RELEASE_RESOURCES_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_RELEASE_RESOURCES_DONE");
 
 	if (!pkt || pkt->size !=
 		sizeof(struct hfi_msg_session_release_resources_done_packet)) {
-		HAL_MSG_ERROR("hal_process_session_rel_res_done:"
+		dprintk(VIDC_ERR, "hal_process_session_rel_res_done:"
 		"bad packet/packet size: %d", pkt->size);
 		return;
 	}
@@ -697,18 +706,18 @@
 	struct list_head *curr, *next;
 	struct hal_session *sess_close;
 
-	HAL_MSG_LOW("RECEIVED:SESSION_END_DONE");
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_END_DONE");
 
 	if (!pkt || pkt->size !=
 		sizeof(struct hfi_msg_sys_session_end_done_packet)) {
-		HAL_MSG_ERROR("hal_process_session_end_done: "
+		dprintk(VIDC_ERR, "hal_process_session_end_done: "
 		"bad packet/packet size: %d", pkt->size);
 		return;
 	}
 
 	list_for_each_safe(curr, next, &device->sess_head) {
 		sess_close = list_entry(curr, struct hal_session, list);
-		HAL_MSG_MEDIUM("deleted the session: 0x%x",
+		dprintk(VIDC_INFO, "deleted the session: 0x%x",
 					   sess_close->session_id);
 		list_del(&sess_close->list);
 		kfree(sess_close);
@@ -724,18 +733,40 @@
 	device->callback(SESSION_END_DONE, &cmd_done);
 }
 
+static void hal_process_session_get_seq_hdr_done(struct hal_device *device,
+	struct hfi_msg_session_get_sequence_header_done_packet *pkt)
+{
+	struct msm_vidc_cb_data_done data_done;
+	if (!pkt || pkt->size !=
+		sizeof(struct
+		hfi_msg_session_get_sequence_header_done_packet)) {
+		dprintk(VIDC_ERR, "bad packet/packet size: %d", pkt->size);
+		return;
+	}
+	memset(&data_done, 0, sizeof(struct msm_vidc_cb_data_done));
+	data_done.device_id = device->device_id;
+	data_done.size = sizeof(struct msm_vidc_cb_data_done);
+	data_done.session_id =
+		((struct hal_session *) pkt->session_id)->session_id;
+	data_done.status = vidc_map_hal_err_status((u32)pkt->error_type);
+	data_done.output_done.packet_buffer1 = pkt->sequence_header;
+	data_done.output_done.filled_len1 = pkt->header_len;
+	dprintk(VIDC_INFO, "seq_hdr: %p, Length: %d",
+		   pkt->sequence_header, pkt->header_len);
+	device->callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
+}
+
 static void hal_process_msg_packet(struct hal_device *device,
 	struct vidc_hal_msg_pkt_hdr *msg_hdr)
 {
 	if (!device || !msg_hdr || msg_hdr->size <
 		VIDC_IFACEQ_MIN_PKT_SIZE) {
-		HAL_MSG_ERROR("hal_process_msg_packet:bad"
+		dprintk(VIDC_ERR, "hal_process_msg_packet:bad"
 			"packet/packet size: %d", msg_hdr->size);
 		return;
 	}
 
-	HAL_MSG_ERROR("Received: 0x%x in %s", msg_hdr->packet, __func__);
-
+	dprintk(VIDC_INFO, "Received: 0x%x in ", msg_hdr->packet);
 	switch (msg_hdr->packet) {
 	case HFI_MSG_EVENT_NOTIFY:
 		hal_process_event_notify(device,
@@ -799,8 +830,13 @@
 			(struct hfi_msg_sys_release_resource_done_packet *)
 			msg_hdr);
 		break;
+	case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
+		hal_process_session_get_seq_hdr_done(device, (struct
+			hfi_msg_session_get_sequence_header_done_packet
+			 *) msg_hdr);
+		break;
 	default:
-		HAL_MSG_ERROR("UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
+		dprintk(VIDC_ERR, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
 		break;
 	}
 }
@@ -809,13 +845,13 @@
 {
 	u8 packet[VIDC_IFACEQ_MED_PKT_SIZE];
 
-	HAL_MSG_INFO("############vidc_hal_response_handler\n");
+	dprintk(VIDC_INFO, "#####vidc_hal_response_handler#####\n");
 	if (device) {
 		while (!vidc_hal_iface_msgq_read(device, packet)) {
 			hal_process_msg_packet(device,
 				(struct vidc_hal_msg_pkt_hdr *)	packet);
 		}
 	} else {
-		HAL_MSG_ERROR("SPURIOUS_INTERRUPT");
+		dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
 	}
 }
diff --git a/drivers/media/video/msm_vidc/vidc_hal_io.h b/drivers/media/video/msm_vidc/vidc_hal_io.h
index c1058e6..c4b1e0c 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_io.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_io.h
@@ -16,13 +16,12 @@
 
 #include <linux/io.h>
 
+#define VENUS_VCODEC_SS_CLOCK_HALT     0x0000000C
+#define VENUS_VPP_CORE_SW_RESET        0x00042004
+#define VENUS_VPP_CTRL_CTRL_RESET      0x00041008
+
 #define VIDC_VBIF_BASE_OFFS			0x00080000
 #define VIDC_VBIF_VERSION			(VIDC_VBIF_BASE_OFFS + 0x00)
-#define VIDC_VBIF_ADDR_TRANS_EN		(VIDC_VBIF_BASE_OFFS + 0x10)
-#define VIDC_VBIF_AT_OLD_BASE		(VIDC_VBIF_BASE_OFFS + 0x14)
-#define VIDC_VBIF_AT_OLD_HIGH		(VIDC_VBIF_BASE_OFFS + 0x18)
-#define VIDC_VBIF_AT_NEW_BASE		(VIDC_VBIF_BASE_OFFS + 0x20)
-#define VIDC_VBIF_AT_NEW_HIGH		(VIDC_VBIF_BASE_OFFS + 0x28)
 
 #define VIDC_CPU_BASE_OFFS			0x000C0000
 #define VIDC_CPU_CS_BASE_OFFS		(VIDC_CPU_BASE_OFFS + 0x00012000)
@@ -98,7 +97,38 @@
 #define VIDC_WRAPPER_AXI_HALT		(VIDC_WRAPPER_BASE_OFFS + 0x2008)
 #define VIDC_WRAPPER_AXI_HALT_STATUS	(VIDC_WRAPPER_BASE_OFFS + 0x200C)
 #define VIDC_WRAPPER_CPU_CGC_DIS	(VIDC_WRAPPER_BASE_OFFS + 0x2010)
-#define VIDC_VENUS_VBIF_CLK_ON		0x80004
+#define VIDC_VENUS_VBIF_CLK_ON		(VIDC_VBIF_BASE_OFFS + 0x4)
+#define VIDC_VBIF_IN_RD_LIM_CONF0       (VIDC_VBIF_BASE_OFFS + 0xB0)
+#define VIDC_VBIF_IN_RD_LIM_CONF1       (VIDC_VBIF_BASE_OFFS + 0xB4)
+#define VIDC_VBIF_IN_RD_LIM_CONF2       (VIDC_VBIF_BASE_OFFS + 0xB8)
+#define VIDC_VBIF_IN_RD_LIM_CONF3       (VIDC_VBIF_BASE_OFFS + 0xBC)
+#define VIDC_VBIF_IN_WR_LIM_CONF0       (VIDC_VBIF_BASE_OFFS + 0xC0)
+#define VIDC_VBIF_IN_WR_LIM_CONF1       (VIDC_VBIF_BASE_OFFS + 0xC4)
+#define VIDC_VBIF_IN_WR_LIM_CONF2       (VIDC_VBIF_BASE_OFFS + 0xC8)
+#define VIDC_VBIF_IN_WR_LIM_CONF3       (VIDC_VBIF_BASE_OFFS + 0xCC)
+#define VIDC_VBIF_OUT_RD_LIM_CONF0      (VIDC_VBIF_BASE_OFFS + 0xD0)
+#define VIDC_VBIF_OUT_WR_LIM_CONF0      (VIDC_VBIF_BASE_OFFS + 0xD4)
+#define VIDC_VBIF_DDR_OUT_MAX_BURST     (VIDC_VBIF_BASE_OFFS + 0xD8)
+#define VIDC_VBIF_OCMEM_OUT_MAX_BURST   (VIDC_VBIF_BASE_OFFS + 0xDC)
+#define VIDC_VBIF_DDR_ARB_CONF0         (VIDC_VBIF_BASE_OFFS + 0xF4)
+#define VIDC_VBIF_DDR_ARB_CONF1         (VIDC_VBIF_BASE_OFFS + 0xF8)
+#define VIDC_VBIF_ROUND_ROBIN_QOS_ARB   (VIDC_VBIF_BASE_OFFS + 0x124)
+#define VIDC_VBIF_OUT_AXI_AOOO_EN       (VIDC_VBIF_BASE_OFFS + 0x178)
+#define VIDC_VBIF_OUT_AXI_AOOO          (VIDC_VBIF_BASE_OFFS + 0x17C)
+#define VIDC_VBIF_ARB_CTL               (VIDC_VBIF_BASE_OFFS + 0xF0)
+#define VIDC_VBIF_OUT_AXI_AMEMTYPE_CONF0 (VIDC_VBIF_BASE_OFFS + 0x160)
+#define VIDC_VBIF_OUT_AXI_AMEMTYPE_CONF1 (VIDC_VBIF_BASE_OFFS + 0x164)
+#define VIDC_VBIF_ADDR_TRANS_EN         (VIDC_VBIF_BASE_OFFS + 0xC00)
+#define VIDC_VBIF_AT_OLD_BASE           (VIDC_VBIF_BASE_OFFS + 0xC04)
+#define VIDC_VBIF_AT_OLD_HIGH           (VIDC_VBIF_BASE_OFFS + 0xC08)
+#define VIDC_VBIF_AT_NEW_BASE           (VIDC_VBIF_BASE_OFFS + 0xC10)
+#define VIDC_VBIF_AT_NEW_HIGH           (VIDC_VBIF_BASE_OFFS + 0xC18)
+
+#define VIDC_VENUS0_VENUS_WRAPPER_VBIF_REQ_PRIORITY \
+	(VIDC_WRAPPER_BASE_OFFS + 0x20)
+#define VIDC_VENUS0_VENUS_WRAPPER_VBIF_PRIORITY_LEVEL \
+	(VIDC_WRAPPER_BASE_OFFS + 0x24)
+#define VIDC_VENUS_VBIF_REQ_PRIORITY    (VIDC_WRAPPER_BASE_OFFS + 0x20)
+#define VIDC_VENUS_VBIF_PRIORITY_LEVEL  (VIDC_WRAPPER_BASE_OFFS + 0x24)
 
 #endif
-
diff --git a/drivers/media/video/msm_wfd/enc-subdev.h b/drivers/media/video/msm_wfd/enc-subdev.h
index 5873e62..00eb6da 100644
--- a/drivers/media/video/msm_wfd/enc-subdev.h
+++ b/drivers/media/video/msm_wfd/enc-subdev.h
@@ -14,7 +14,7 @@
 #ifndef _WFD_ENC_SUBDEV_
 #define _WFD_ENC_SUBDEV_
 
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <media/v4l2-subdev.h>
 #include <media/videobuf2-core.h>
 #define VENC_MAGIC_IOCTL 'V'
diff --git a/drivers/media/video/msm_wfd/wfd-ioctl.c b/drivers/media/video/msm_wfd/wfd-ioctl.c
index 232c202..8981c1a 100644
--- a/drivers/media/video/msm_wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm_wfd/wfd-ioctl.c
@@ -153,7 +153,7 @@
 		bool secure, struct mem_region *mregion)
 {
 	struct ion_handle *handle;
-	void *kvaddr, *phys_addr;
+	void *kvaddr = NULL, *phys_addr = NULL;
 	unsigned long size;
 	unsigned int alloc_regions = 0;
 	int rc;
@@ -209,7 +209,9 @@
 	return rc;
 alloc_fail:
 	if (!IS_ERR_OR_NULL(handle)) {
-		ion_unmap_kernel(client, handle);
+		if (!IS_ERR_OR_NULL(kvaddr))
+			ion_unmap_kernel(client, handle);
+
 		ion_free(client, handle);
 
 		mregion->kvaddr = NULL;
@@ -1308,7 +1310,10 @@
 
 	WFD_MSG_DBG("wfd_open: E\n");
 	wfd_dev = video_drvdata(filp);
-
+	if (!wfd_dev) {
+		rc = -EINVAL;
+		goto err_dev_busy;
+	}
 	mutex_lock(&wfd_dev->dev_lock);
 	if (wfd_dev->in_use) {
 		WFD_MSG_ERR("Device already in use.\n");
@@ -1321,7 +1326,7 @@
 	mutex_unlock(&wfd_dev->dev_lock);
 
 	inst = kzalloc(sizeof(struct wfd_inst), GFP_KERNEL);
-	if (!inst || !wfd_dev) {
+	if (!inst) {
 		WFD_MSG_ERR("Could not allocate memory for "
 			"wfd instance\n");
 		rc = -ENOMEM;
@@ -1379,6 +1384,9 @@
 	v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
 				MDP_CLOSE, (void *)inst->mdp_inst);
 err_mdp_open:
+	mutex_lock(&wfd_dev->dev_lock);
+	wfd_dev->in_use = false;
+	mutex_unlock(&wfd_dev->dev_lock);
 	kfree(inst);
 err_dev_busy:
 	return rc;
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index cb33550..28abb36 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -1222,7 +1222,7 @@
 		rc = init_motion_buf(c_data);
 		if (rc < 0)
 			goto free_res;
-		if (c_data->vp_action.nr_param.mode) {
+		if (dev->nr_param.mode) {
 			rc = init_nr_buf(c_data);
 			if (rc < 0)
 				goto s_on_deinit_m_buf;
@@ -1311,7 +1311,7 @@
 		if (rc < 0)
 			goto free_res;
 
-		if (c_data->vp_action.nr_param.mode) {
+		if (dev->nr_param.mode) {
 			rc = init_nr_buf(c_data);
 			if (rc < 0)
 				goto s_on_deinit_m_buf;
@@ -1344,7 +1344,7 @@
 	return 0;
 
 s_on_deinit_nr_buf:
-	if (c_data->vp_action.nr_param.mode)
+	if (dev->nr_param.mode)
 		deinit_nr_buf(c_data);
 s_on_deinit_m_buf:
 	deinit_motion_buf(c_data);
@@ -1439,7 +1439,7 @@
 			return rc;
 
 		deinit_motion_buf(c_data);
-		if (c_data->vp_action.nr_param.mode)
+		if (dev->nr_param.mode)
 			deinit_nr_buf(c_data);
 		atomic_set(&c_data->dev->vp_enabled, 0);
 		return rc;
@@ -1487,7 +1487,7 @@
 			return rc;
 
 		deinit_motion_buf(c_data);
-		if (c_data->vp_action.nr_param.mode)
+		if (dev->nr_param.mode)
 			deinit_nr_buf(c_data);
 		atomic_set(&c_data->dev->vc_enabled, 0);
 		atomic_set(&c_data->dev->vp_enabled, 0);
@@ -1549,7 +1549,7 @@
 
 		if (c_data->streaming != 0 &&
 				(!(!((struct nr_param *) arg)->mode) !=
-				!(!(c_data->vp_action.nr_param.mode)))) {
+				!(!(dev->nr_param.mode)))) {
 			pr_err("ERR: Trying to toggle on/off while VP is already running");
 			return -EBUSY;
 		}
@@ -1562,20 +1562,20 @@
 			return ret;
 		}
 		param = (struct nr_param *) arg;
-		c_data->vp_action.nr_param = *param;
+		dev->nr_param = *param;
 		if (param->mode == NR_AUTO)
-			s_default_nr_val(&c_data->vp_action.nr_param);
-		c_data->vp_action.nr_update = true;
+			s_default_nr_val(&dev->nr_param);
+		dev->nr_update = true;
 		spin_unlock_irqrestore(&c_data->cap_slock, flags);
 		break;
 	case VCAPIOC_NR_G_PARAMS:
-		*((struct nr_param *)arg) = c_data->vp_action.nr_param;
-		if (c_data->vp_action.nr_param.mode != NR_DISABLE) {
+		*((struct nr_param *)arg) = dev->nr_param;
+		if (dev->nr_param.mode != NR_DISABLE) {
 			if (c_data->streaming)
 				nr_g_param(c_data, (struct nr_param *) arg);
 			else
 				(*(struct nr_param *) arg) =
-					c_data->vp_action.nr_param;
+					dev->nr_param;
 		}
 		break;
 	case VCAPIOC_S_NUM_VC_BUF:
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 1825352..78e108f 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -145,26 +145,31 @@
 
 	v4l2_evt.id = 0;
 	if (irq & 0x8000200) {
+		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
 		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
 			VCAP_VC_PIX_ERR_EVENT;
 		v4l2_event_queue(dev->vfd, &v4l2_evt);
 	}
 	if (irq & 0x40000200) {
+		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
 		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
 			VCAP_VC_LINE_ERR_EVENT;
 		v4l2_event_queue(dev->vfd, &v4l2_evt);
 	}
 	if (irq & 0x20000200) {
+		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
 		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
 			VCAP_VC_VSYNC_ERR_EVENT;
 		v4l2_event_queue(dev->vfd, &v4l2_evt);
 	}
 	if (irq & 0x00000800) {
+		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
 		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
 			VCAP_VC_NPL_OFLOW_ERR_EVENT;
 		v4l2_event_queue(dev->vfd, &v4l2_evt);
 	}
 	if (irq & 0x00000400) {
+		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
 		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
 			VCAP_VC_LBUF_OFLOW_ERR_EVENT;
 		v4l2_event_queue(dev->vfd, &v4l2_evt);
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 12b3208..139de28 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -169,11 +169,10 @@
 	}
 }
 
-void update_nr_value(struct vcap_client_data *c_data)
+void update_nr_value(struct vcap_dev *dev)
 {
-	struct vcap_dev *dev = c_data->dev;
 	struct nr_param *par;
-	par = &c_data->vp_action.nr_param;
+	par = &dev->nr_param;
 	if (par->mode == NR_MANUAL) {
 		writel_relaxed(par->window << 24 | par->decay_ratio << 20,
 			VCAP_VP_NR_CONFIG);
@@ -190,7 +189,7 @@
 			par->chroma.blend_limit_ratio << 0,
 			VCAP_VP_NR_CHROMA_CONFIG);
 	}
-	c_data->vp_action.nr_update = false;
+	dev->nr_update = false;
 }
 
 static void vp_wq_fnc(struct work_struct *work)
@@ -222,8 +221,8 @@
 	writel_relaxed(0x40000000, VCAP_VP_REDUCT_AVG_MOTION2);
 
 	spin_lock_irqsave(&dev->vp_client->cap_slock, flags);
-	if (vp_act->nr_update == true)
-		update_nr_value(dev->vp_client);
+	if (dev->nr_update == true)
+		update_nr_value(dev);
 	spin_unlock_irqrestore(&dev->vp_client->cap_slock, flags);
 
 	/* Queue the done buffers */
@@ -244,7 +243,7 @@
 #endif
 
 	/* Cycle Buffers*/
-	if (vp_work->cd->vp_action.nr_param.mode) {
+	if (dev->nr_param.mode) {
 		if (vp_act->bufNR.nr_pos == TM1_BUF)
 			vp_act->bufNR.nr_pos = BUF_NOT_IN_USE;
 
@@ -558,7 +557,7 @@
 	}
 
 	c_data->vp_action.bufNR.nr_handle = handle;
-	update_nr_value(c_data);
+	update_nr_value(dev);
 
 	c_data->vp_action.bufNR.paddr = paddr;
 	rc = readl_relaxed(VCAP_VP_NR_CONFIG2);
@@ -598,27 +597,27 @@
 		return 0;
 
 	/* Verify values in range */
-	if (param->window < VP_NR_MAX_WINDOW)
+	if (param->window > VP_NR_MAX_WINDOW)
 		return -EINVAL;
-	if (param->luma.max_blend_ratio < VP_NR_MAX_RATIO)
+	if (param->luma.max_blend_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->luma.scale_diff_ratio < VP_NR_MAX_RATIO)
+	if (param->luma.scale_diff_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->luma.diff_limit_ratio < VP_NR_MAX_RATIO)
+	if (param->luma.diff_limit_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->luma.scale_motion_ratio < VP_NR_MAX_RATIO)
+	if (param->luma.scale_motion_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->luma.blend_limit_ratio < VP_NR_MAX_RATIO)
+	if (param->luma.blend_limit_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->chroma.max_blend_ratio < VP_NR_MAX_RATIO)
+	if (param->chroma.max_blend_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->chroma.scale_diff_ratio < VP_NR_MAX_RATIO)
+	if (param->chroma.scale_diff_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->chroma.diff_limit_ratio < VP_NR_MAX_RATIO)
+	if (param->chroma.diff_limit_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->chroma.scale_motion_ratio < VP_NR_MAX_RATIO)
+	if (param->chroma.scale_motion_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
-	if (param->chroma.blend_limit_ratio < VP_NR_MAX_RATIO)
+	if (param->chroma.blend_limit_ratio > VP_NR_MAX_RATIO)
 		return -EINVAL;
 	return 0;
 }
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8c392fc..464f19f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -248,7 +248,7 @@
 
 config MARIMBA_CORE
 	tristate "Marimba Core"
-	depends on I2C && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A)
+	depends on I2C && (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM7X27A || ARCH_MSM8960)
 	default n
 	help
 	  Enables the Marimba Core driver. The core driver provides
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index 712a772..9815f6e 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -34,7 +34,7 @@
 #define REG_IRQ_BASE            0x1BB
 
 #define REG_SPK_BASE		0x253
-#define REG_SPK_REGISTERS	3
+#define REG_SPK_REGISTERS	6
 
 #define REG_TEMP_ALARM_CTRL	0x01B
 #define REG_TEMP_ALARM_PWM	0x09B
@@ -293,7 +293,7 @@
 	[0] = {
 		.name   = PM8XXX_SPK_DEV_NAME,
 		.start  = REG_SPK_BASE,
-		.end    = REG_SPK_BASE + REG_SPK_REGISTERS,
+		.end    = REG_SPK_BASE + REG_SPK_REGISTERS - 1,
 		.flags  = IORESOURCE_IO,
 	},
 };
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index 022cfb6..70f4cd5 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -815,8 +815,8 @@
 		if (pwm_chip->is_lpg_supported) {
 			if (pwm->dtest_mode_supported)
 				pm8xxx_pwm_set_dtest(pwm, 1);
-			rc = pm8xxx_pwm_bank_enable(pwm, 1);
 			pm8xxx_pwm_bank_sel(pwm);
+			rc = pm8xxx_pwm_bank_enable(pwm, 1);
 			pm8xxx_pwm_start(pwm, 1, 0);
 		} else {
 			pm8xxx_pwm_enable(pwm);
@@ -1065,9 +1065,9 @@
 		if (pwm->dtest_mode_supported)
 			pm8xxx_pwm_set_dtest(pwm, 1);
 
+		pm8xxx_pwm_bank_sel(pwm);
 		pm8xxx_pwm_bank_enable(pwm, 1);
 
-		pm8xxx_pwm_bank_sel(pwm);
 		pm8xxx_pwm_start(pwm, 1, 1);
 	} else {
 		if (pwm->dtest_mode_supported)
diff --git a/drivers/mfd/pm8xxx-spk.c b/drivers/mfd/pm8xxx-spk.c
index 7ce6b50..8ba7372 100644
--- a/drivers/mfd/pm8xxx-spk.c
+++ b/drivers/mfd/pm8xxx-spk.c
@@ -22,8 +22,11 @@
 #include <linux/mfd/pm8xxx/spk.h>
 
 #define PM8XXX_SPK_CTL1_REG_OFF		0
-#define PM8XXX_SPK_TEST_REG_1_OFF	1
-#define PM8XXX_SPK_TEST_REG_2_OFF	2
+#define PM8XXX_SPK_CTL2_REG_OFF		1
+#define PM8XXX_SPK_CTL3_REG_OFF		2
+#define PM8XXX_SPK_CTL4_REG_OFF		3
+#define PM8XXX_SPK_TEST_REG_1_OFF	4
+#define PM8XXX_SPK_TEST_REG_2_OFF	5
 
 #define PM8XXX_SPK_BANK_SEL		4
 #define PM8XXX_SPK_BANK_WRITE		0x80
@@ -194,6 +197,7 @@
 {
 	const struct pm8xxx_spk_platform_data *pdata = pdev->dev.platform_data;
 	int ret = 0;
+	u8 value = 0;
 
 	if (!pdata) {
 		pr_err("missing platform data\n");
@@ -236,6 +240,23 @@
 		if (ret < 0)
 			goto err_handle;
 	}
+	value = ((the_spk_chip->pdata.cd_ng_threshold << 5) |
+		the_spk_chip->pdata.cd_nf_preamp_bias << 3);
+	pr_debug("Setting SPK_CTL2_REG = %02x\n", value);
+	pm8xxx_spk_write(PM8XXX_SPK_CTL2_REG_OFF, value);
+
+	value = ((the_spk_chip->pdata.cd_ng_hold << 5) |
+		(the_spk_chip->pdata.cd_ng_max_atten << 1) |
+		the_spk_chip->pdata.noise_mute);
+	pr_debug("Setting SPK_CTL3_REG = %02x\n", value);
+	pm8xxx_spk_write(PM8XXX_SPK_CTL3_REG_OFF, value);
+
+	value = ((the_spk_chip->pdata.cd_ng_decay_rate << 5) |
+		(the_spk_chip->pdata.cd_ng_attack_rate << 3) |
+		the_spk_chip->pdata.cd_delay << 2);
+	pr_debug("Setting SPK_CTL4_REG = %02x\n", value);
+	pm8xxx_spk_write(PM8XXX_SPK_CTL4_REG_OFF, value);
+
 	return pm8xxx_spk_config();
 err_handle:
 	pr_err("pm8xxx_spk_probe failed."
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 35ae29a..0ea843c 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -253,6 +253,18 @@
 	},
 };
 
+static struct wcd9xx_codec_type {
+	u8 byte[4];
+	struct mfd_cell *dev;
+	int size;
+} wcd9xxx_codecs[] = {
+	{{0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs)},
+	{{0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs)},
+	{{0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs)},
+	{{0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs)},
+	{{0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs)},
+};
+
 static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
 {
 	wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
@@ -298,6 +310,53 @@
 		wcd9xxx->reset_gpio = 0;
 	}
 }
+static int wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx,
+					struct mfd_cell **wcd9xxx_dev,
+					int *wcd9xxx_dev_size)
+{
+	struct wcd9xx_codec_type *cdc = wcd9xxx_codecs;
+	int index;
+	int ret;
+	index = WCD9XXX_A_CHIP_ID_BYTE_0;
+	while (index <= WCD9XXX_A_CHIP_ID_BYTE_3) {
+		ret = wcd9xxx_reg_read(wcd9xxx, index);
+		if (ret < 0)
+			goto exit;
+		wcd9xxx->idbyte[index-WCD9XXX_A_CHIP_ID_BYTE_0] = (u8)ret;
+		pr_debug("%s: wcd9xx read = %x, byte = %x\n", __func__, ret,
+			index);
+		index++;
+	}
+
+	/* Read codec version */
+	ret = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
+	if (ret < 0)
+		goto exit;
+	wcd9xxx->version = (u8)ret & 0x1F;
+
+	while (cdc < (cdc + ARRAY_SIZE(wcd9xxx_codecs)) && cdc != NULL) {
+		if ((cdc->byte[0] == wcd9xxx->idbyte[0]) &&
+		    (cdc->byte[1] == wcd9xxx->idbyte[1]) &&
+		    (cdc->byte[2] == wcd9xxx->idbyte[2]) &&
+		    (cdc->byte[3] == wcd9xxx->idbyte[3])) {
+			pr_info("%s: codec is %s", __func__, cdc->dev->name);
+			*wcd9xxx_dev = cdc->dev;
+			*wcd9xxx_dev_size = cdc->size;
+			break;
+		}
+		cdc++;
+	}
+	if (*wcd9xxx_dev == NULL || *wcd9xxx_dev_size == 0)
+		ret = -ENODEV;
+	pr_info("%s: Read codec idbytes & version\n"
+		"byte_0[%08x] byte_1[%08x] byte_2[%08x]\n"
+		" byte_3[%08x] version = %x\n", __func__,
+		wcd9xxx->idbyte[0], wcd9xxx->idbyte[1],
+		wcd9xxx->idbyte[2], wcd9xxx->idbyte[3],
+		wcd9xxx->version);
+exit:
+	return ret;
+}
 
 static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx, int irq)
 {
@@ -326,39 +385,11 @@
 			goto err;
 		}
 	}
+	ret = wcd9xxx_check_codec_type(wcd9xxx, &wcd9xxx_dev,
+					&wcd9xxx_dev_size);
 
-	wcd9xxx->idbyte_0 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0);
-	wcd9xxx->idbyte_1 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_1);
-	wcd9xxx->idbyte_2 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2);
-	wcd9xxx->idbyte_3 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_3);
-
-	wcd9xxx->version = wcd9xxx_reg_read(wcd9xxx,
-			WCD9XXX_A_CHIP_VERSION) & 0x1F;
-	pr_info("%s : Codec version %u initialized\n",
-		__func__, wcd9xxx->version);
-	pr_info("idbyte_0[%08x] idbyte_1[%08x] idbyte_2[%08x] idbyte_3[%08x]\n",
-		wcd9xxx->idbyte_0, wcd9xxx->idbyte_1,
-		wcd9xxx->idbyte_2, wcd9xxx->idbyte_3);
-
-	if (wcd9xxx->idbyte_0 == 0x2 && wcd9xxx->idbyte_1 == 0x0 &&
-		   wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) {
-		wcd9xxx_dev = tabla_devs;
-		wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
-	} else if (wcd9xxx->idbyte_0 == 0x1 && wcd9xxx->idbyte_1 == 0x0 &&
-		   wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) {
-		wcd9xxx_dev = tabla1x_devs;
-		wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
-	} else if (wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
-		   wcd9xxx->idbyte_2 == 0x2 && wcd9xxx->idbyte_3 == 0x1) {
-		wcd9xxx_dev = taiko_devs;
-		wcd9xxx_dev_size = ARRAY_SIZE(taiko_devs);
-	} else if ((wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
-		   wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) ||
-		   (wcd9xxx->idbyte_0 == 0x1 && wcd9xxx->idbyte_1 == 0x0 &&
-		   wcd9xxx->idbyte_2 == 0x1 && wcd9xxx->idbyte_3 == 0x1)) {
-		wcd9xxx_dev = sitar_devs;
-		wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
-	}
+	if (ret < 0)
+		goto err_irq;
 	ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
 			      NULL, 0);
 	if (ret != 0) {
@@ -772,9 +803,9 @@
 		goto err_device_init;
 	}
 
-	if ((wcd9xxx->idbyte_0 == 0x2) || (wcd9xxx->idbyte_0 == 0x1))
+	if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
 		i2c_mode = TABLA_I2C_MODE;
-	else if (wcd9xxx->idbyte_0 == 0x0)
+	else if (wcd9xxx->idbyte[0] == 0x0)
 		i2c_mode = SITAR_I2C_MODE;
 
 	ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 696f16d..d6d209b 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -28,7 +28,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/io.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/qseecom.h>
@@ -147,7 +147,6 @@
 
 static int qsee_bw_count;
 static int qsee_sfpb_bw_count;
-static struct clk *qseecom_bus_clk;
 static uint32_t qsee_perf_client;
 
 struct qseecom_registered_listener_list {
@@ -773,7 +772,8 @@
 	bool unload = false;
 	bool found_app = false;
 
-	if (qseecom.qseos_version == QSEOS_VERSION_14) {
+	if ((qseecom.qseos_version == QSEOS_VERSION_14) &&
+				(data->client.app_id > 0)) {
 		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
 		list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
 								list) {
@@ -784,7 +784,7 @@
 					break;
 				} else {
 					ptr_app->ref_cnt--;
-					pr_warn("Can't unload app with id %d (it is inuse)\n",
+					pr_warn("Can't unload app(%d) inuse\n",
 							ptr_app->app_id);
 					break;
 				}
@@ -792,10 +792,11 @@
 		}
 		spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
 								flags);
-	}
-	if (found_app == false)  {
-		pr_err("Cannot find app with id = %d\n", data->client.app_id);
-		return -EINVAL;
+		if (found_app == false) {
+			pr_err("Cannot find app with id = %d\n",
+						data->client.app_id);
+			return -EINVAL;
+		}
 	}
 
 	if ((unload) && (qseecom.qseos_version == QSEOS_VERSION_14)) {
@@ -1199,11 +1200,6 @@
 
 	switch (clk_type) {
 	case CLK_DFAB:
-		/* Check if the clk is valid */
-		if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
-			pr_warn("qseecom bus clock is null or error");
-			return -EINVAL;
-		}
 		mutex_lock(&qsee_bw_mutex);
 		if (!qsee_bw_count) {
 			ret = msm_bus_scale_client_update_request(
@@ -1245,11 +1241,6 @@
 
 	switch (clk_type) {
 	case CLK_DFAB:
-		/* Check if the DFAB clk is valid */
-		if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
-			pr_warn("qseecom bus clock is null or error");
-			return;
-		}
 		mutex_lock(&qsee_bw_mutex);
 		if (qsee_bw_count > 0) {
 			if (qsee_bw_count-- == 1) {
@@ -1731,7 +1722,6 @@
 	uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
 
 	qsee_bw_count = 0;
-	qseecom_bus_clk = NULL;
 	qsee_perf_client = 0;
 
 	rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
@@ -1799,17 +1789,8 @@
 		qsee_perf_client = msm_bus_scale_register_client(
 						qseecom_platform_support);
 
-		if (!qsee_perf_client) {
+		if (!qsee_perf_client)
 			pr_err("Unable to register bus client\n");
-		} else {
-			qseecom_bus_clk = clk_get(class_dev, "bus_clk");
-			if (IS_ERR(qseecom_bus_clk)) {
-				qseecom_bus_clk = NULL;
-			} else if (qseecom_bus_clk != NULL) {
-				pr_debug("Enabled DFAB clock");
-				clk_set_rate(qseecom_bus_clk, 64000000);
-			}
-		}
 	}
 	return 0;
 
@@ -1853,8 +1834,6 @@
 
 static void __devexit qseecom_exit(void)
 {
-	clk_put(qseecom_bus_clk);
-
 	device_destroy(driver_class, qseecom_device_no);
 	class_destroy(driver_class);
 	unregister_chrdev_region(qseecom_device_no, 1);
diff --git a/drivers/misc/tsif.c b/drivers/misc/tsif.c
index 7e59c98..1ff4468 100644
--- a/drivers/misc/tsif.c
+++ b/drivers/misc/tsif.c
@@ -32,7 +32,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>          /* kfree, kzalloc */
 #include <linux/gpio.h>
-
 #include <mach/dma.h>
 #include <mach/msm_tsif.h>
 
@@ -273,36 +272,6 @@
 /* ===clocks end=== */
 /* ===gpio begin=== */
 
-static void tsif_gpios_free(const struct msm_gpio *table, int size)
-{
-	int i;
-	const struct msm_gpio *g;
-	for (i = size-1; i >= 0; i--) {
-		g = table + i;
-		gpio_free(GPIO_PIN(g->gpio_cfg));
-	}
-}
-
-static int tsif_gpios_request(const struct msm_gpio *table, int size)
-{
-	int rc;
-	int i;
-	const struct msm_gpio *g;
-	for (i = 0; i < size; i++) {
-		g = table + i;
-		rc = gpio_request(GPIO_PIN(g->gpio_cfg), g->label);
-		if (rc) {
-			pr_err("gpio_request(%d) <%s> failed: %d\n",
-			       GPIO_PIN(g->gpio_cfg), g->label ?: "?", rc);
-			goto err;
-		}
-	}
-	return 0;
-err:
-	tsif_gpios_free(table, i);
-	return rc;
-}
-
 static int tsif_gpios_disable(const struct msm_gpio *table, int size)
 {
 	int rc = 0;
@@ -357,19 +326,14 @@
 
 static int tsif_gpios_request_enable(const struct msm_gpio *table, int size)
 {
-	int rc = tsif_gpios_request(table, size);
-	if (rc)
-		return rc;
+	int rc;
 	rc = tsif_gpios_enable(table, size);
-	if (rc)
-		tsif_gpios_free(table, size);
 	return rc;
 }
 
 static void tsif_gpios_disable_free(const struct msm_gpio *table, int size)
 {
 	tsif_gpios_disable(table, size);
-	tsif_gpios_free(table, size);
 }
 
 static int tsif_start_gpios(struct msm_tsif_device *tsif_device)
@@ -1029,6 +993,7 @@
 
 	struct msm_tsif_platform_data *pdata =
 		tsif_device->pdev->dev.platform_data;
+
 	dev_info(&tsif_device->pdev->dev, "%s\n", __func__);
 	if (tsif_device->state != tsif_state_stopped)
 		return -EAGAIN;
@@ -1039,14 +1004,6 @@
 	}
 	tsif_device->state = tsif_state_running;
 
-	/* make sure the GPIO's are set up */
-	rc = tsif_start_gpios(tsif_device);
-	if (rc) {
-		dev_err(&tsif_device->pdev->dev, "failed to start GPIOs\n");
-		tsif_dma_exit(tsif_device);
-		return rc;
-	}
-
 	/*
 	 * DMA should be scheduled prior to TSIF hardware initialization,
 	 * otherwise "bus error" will be reported by Data Mover
@@ -1062,9 +1019,20 @@
 	rc = tsif_start_hw(tsif_device);
 	if (rc) {
 		dev_err(&tsif_device->pdev->dev, "Unable to start HW\n");
-		tsif_stop_gpios(tsif_device);
 		tsif_dma_exit(tsif_device);
 		tsif_clock(tsif_device, 0);
+		disable_irq(tsif_device->irq);
+		return rc;
+	}
+
+	/* make sure the GPIO's are set up */
+	rc = tsif_start_gpios(tsif_device);
+	if (rc) {
+		dev_err(&tsif_device->pdev->dev, "failed to start GPIOs\n");
+		tsif_stop_hw(tsif_device);
+		tsif_dma_exit(tsif_device);
+		tsif_clock(tsif_device, 0);
+		disable_irq(tsif_device->irq);
 		return rc;
 	}
 
@@ -1073,11 +1041,16 @@
 		dev_err(&tsif_device->pdev->dev,
 			"Runtime PM: Unable to wake up the device, rc = %d\n",
 			result);
+		tsif_stop_gpios(tsif_device);
+		tsif_stop_hw(tsif_device);
+		tsif_dma_exit(tsif_device);
+		tsif_clock(tsif_device, 0);
+		disable_irq(tsif_device->irq);
 		return result;
 	}
 
 	wake_lock(&tsif_device->wake_lock);
-	return rc;
+	return 0;
 }
 
 static int action_close(struct msm_tsif_device *tsif_device)
@@ -1094,7 +1067,7 @@
 	 * there are any outstanding reads on the bus, and if we
 	 * stop the TSIF too quickly, it can cause a bus error.
 	 */
-	msleep(100);
+	msleep(250);
 
 	/* now we can stop the core */
 	tsif_stop_hw(tsif_device);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 87dbd8b..b153b27 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1159,15 +1159,16 @@
 	if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
 		*c |= MCI_CSPM_DATCMD;
 
-	/* Check if AUTO CMD19 is required or not? */
+	/* Check if AUTO CMD19/CMD21 is required or not? */
 	if (host->tuning_needed &&
-		!(host->mmc->ios.timing == MMC_TIMING_MMC_HS200)) {
-
+		(host->en_auto_cmd19 || host->en_auto_cmd21)) {
 		/*
 		 * For open ended block read operation (without CMD23),
-		 * AUTO_CMD19 bit should be set while sending the READ command.
+		 * AUTO_CMD19/AUTO_CMD21 bit should be set while sending
+		 * the READ command.
 		 * For close ended block read operation (with CMD23),
-		 * AUTO_CMD19 bit should be set while sending CMD23.
+		 * AUTO_CMD19/AUTO_CMD21 bit should be set while sending
+		 * CMD23.
 		 */
 		if ((cmd->opcode == MMC_SET_BLOCK_COUNT &&
 			host->curr.mrq->cmd->opcode ==
@@ -1176,7 +1177,12 @@
 			(cmd->opcode == MMC_READ_SINGLE_BLOCK ||
 			cmd->opcode == MMC_READ_MULTIPLE_BLOCK))) {
 			msmsdcc_enable_cdr_cm_sdc4_dll(host);
-			*c |= MCI_CSPM_AUTO_CMD19;
+			if (host->en_auto_cmd19 &&
+			    host->mmc->ios.timing == MMC_TIMING_UHS_SDR104)
+				*c |= MCI_CSPM_AUTO_CMD19;
+			else if (host->en_auto_cmd21 &&
+			    host->mmc->ios.timing == MMC_TIMING_MMC_HS200)
+				*c |= MCI_CSPM_AUTO_CMD21;
 		}
 	}
 
@@ -4814,6 +4820,63 @@
 	return count;
 }
 
+static inline void set_auto_cmd_setting(struct device *dev,
+					 const char *buf,
+					 bool is_cmd19)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	unsigned int long flags;
+	int temp;
+
+	if (!kstrtou32(buf, 0, &temp)) {
+		spin_lock_irqsave(&host->lock, flags);
+		if (is_cmd19)
+			host->en_auto_cmd19 = !!temp;
+		else
+			host->en_auto_cmd21 = !!temp;
+		spin_unlock_irqrestore(&host->lock, flags);
+	}
+}
+
+static ssize_t
+show_enable_auto_cmd19(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct msmsdcc_host *host = mmc_priv(mmc);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", host->en_auto_cmd19);
+}
+
+static ssize_t
+store_enable_auto_cmd19(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	set_auto_cmd_setting(dev, buf, true);
+
+	return count;
+}
+
+static ssize_t
+show_enable_auto_cmd21(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct msmsdcc_host *host = mmc_priv(mmc);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", host->en_auto_cmd21);
+}
+
+static ssize_t
+store_enable_auto_cmd21(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	set_auto_cmd_setting(dev, buf, false);
+
+	return count;
+}
+
 #ifdef CONFIG_HAS_EARLYSUSPEND
 static void msmsdcc_early_suspend(struct early_suspend *h)
 {
@@ -5959,8 +6022,42 @@
 	ret = device_create_file(&pdev->dev, &host->idle_timeout);
 	if (ret)
 		goto remove_polling_file;
+
+	if (!is_auto_cmd19(host))
+		goto add_auto_cmd21_atrr;
+
+	/* Sysfs entry for AUTO CMD19 control */
+	host->auto_cmd19_attr.show = show_enable_auto_cmd19;
+	host->auto_cmd19_attr.store = store_enable_auto_cmd19;
+	sysfs_attr_init(&host->auto_cmd19_attr.attr);
+	host->auto_cmd19_attr.attr.name = "enable_auto_cmd19";
+	host->auto_cmd19_attr.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(&pdev->dev, &host->auto_cmd19_attr);
+	if (ret)
+		goto remove_idle_timeout_file;
+
+ add_auto_cmd21_atrr:
+	if (!is_auto_cmd21(host))
+		goto exit;
+
+	/* Sysfs entry for AUTO CMD21 control */
+	host->auto_cmd21_attr.show = show_enable_auto_cmd21;
+	host->auto_cmd21_attr.store = store_enable_auto_cmd21;
+	sysfs_attr_init(&host->auto_cmd21_attr.attr);
+	host->auto_cmd21_attr.attr.name = "enable_auto_cmd21";
+	host->auto_cmd21_attr.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(&pdev->dev, &host->auto_cmd21_attr);
+	if (ret)
+		goto remove_auto_cmd19_attr_file;
+
+ exit:
 	return 0;
 
+ remove_auto_cmd19_attr_file:
+	if (is_auto_cmd19(host))
+		device_remove_file(&pdev->dev, &host->auto_cmd19_attr);
+ remove_idle_timeout_file:
+	device_remove_file(&pdev->dev, &host->idle_timeout);
  remove_polling_file:
 	if (!plat->status_irq)
 		device_remove_file(&pdev->dev, &host->polling);
@@ -6041,6 +6138,10 @@
 	DBG(host, "Removing SDCC device = %d\n", pdev->id);
 	plat = host->plat;
 
+	if (is_auto_cmd19(host))
+		device_remove_file(&pdev->dev, &host->auto_cmd19_attr);
+	if (is_auto_cmd21(host))
+		device_remove_file(&pdev->dev, &host->auto_cmd21_attr);
 	device_remove_file(&pdev->dev, &host->max_bus_bw);
 	if (!plat->status_irq)
 		device_remove_file(&pdev->dev, &host->polling);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 236785d..5779491 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -65,6 +65,7 @@
 #define MCI_CSPM_CCSENABLE	(1 << 14)
 #define MCI_CSPM_CCSDISABLE	(1 << 15)
 #define MCI_CSPM_AUTO_CMD19	(1 << 16)
+#define MCI_CSPM_AUTO_CMD21	(1 << 21)
 
 
 #define MMCIRESPCMD		0x010
@@ -401,6 +402,8 @@
 	bool io_pad_pwr_switch;
 	bool tuning_in_progress;
 	bool tuning_needed;
+	bool en_auto_cmd19;
+	bool en_auto_cmd21;
 	bool sdio_gpio_lpm;
 	bool irq_wake_enabled;
 	struct pm_qos_request pm_qos_req_dma;
@@ -417,9 +420,15 @@
 	struct device_attribute	max_bus_bw;
 	struct device_attribute	polling;
 	struct device_attribute idle_timeout;
+	struct device_attribute auto_cmd19_attr;
+	struct device_attribute auto_cmd21_attr;
 };
 
-#define MSMSDCC_VERSION_MASK	0xFFFF
+#define MSMSDCC_VERSION_STEP_MASK	0x0000FFFF
+#define MSMSDCC_VERSION_MINOR_MASK	0x0FFF0000
+#define MSMSDCC_VERSION_MINOR_SHIFT	16
+#define MSMSDCC_VERSION_MAJOR_MASK	0xF0000000
+#define MSMSDCC_VERSION_MAJOR_SHIFT	28
 #define MSMSDCC_DMA_SUP	(1 << 0)
 #define MSMSDCC_SPS_BAM_SUP	(1 << 1)
 #define MSMSDCC_SOFT_RESET	(1 << 2)
@@ -429,6 +438,8 @@
 #define MSMSDCC_SW_RST_CFG	(1 << 6)
 #define MSMSDCC_WAIT_FOR_TX_RX	(1 << 7)
 #define MSMSDCC_IO_PAD_PWR_SWITCH	(1 << 8)
+#define MSMSDCC_AUTO_CMD19	(1 << 9)
+#define MSMSDCC_AUTO_CMD21	(1 << 10)
 
 #define set_hw_caps(h, val)		((h)->hw_caps |= val)
 #define is_sps_mode(h)			((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -440,11 +451,15 @@
 #define is_sw_reset_save_config(h)	((h)->hw_caps & MSMSDCC_SW_RST_CFG)
 #define is_wait_for_tx_rx_active(h)	((h)->hw_caps & MSMSDCC_WAIT_FOR_TX_RX)
 #define is_io_pad_pwr_switch(h)	((h)->hw_caps & MSMSDCC_IO_PAD_PWR_SWITCH)
+#define is_auto_cmd19(h)		((h)->hw_caps & MSMSDCC_AUTO_CMD19)
+#define is_auto_cmd21(h)		((h)->hw_caps & MSMSDCC_AUTO_CMD21)
 
 /* Set controller capabilities based on version */
 static inline void set_default_hw_caps(struct msmsdcc_host *host)
 {
 	u32 version;
+	u16 step, minor;
+
 	/*
 	 * Lookup the Controller Version, to identify the supported features
 	 * Version number read as 0 would indicate SDCC3 or earlier versions.
@@ -455,14 +470,21 @@
 	if (!version)
 		return;
 
-	version &= MSMSDCC_VERSION_MASK;
+	step = version & MSMSDCC_VERSION_STEP_MASK;
+	minor = (version & MSMSDCC_VERSION_MINOR_MASK) >>
+			MSMSDCC_VERSION_MINOR_SHIFT;
+
 	if (version) /* SDCC v4 and greater */
 		host->hw_caps |= MSMSDCC_AUTO_PROG_DONE |
 			MSMSDCC_SOFT_RESET | MSMSDCC_REG_WR_ACTIVE
-			| MSMSDCC_WAIT_FOR_TX_RX | MSMSDCC_IO_PAD_PWR_SWITCH;
+			| MSMSDCC_WAIT_FOR_TX_RX | MSMSDCC_IO_PAD_PWR_SWITCH
+			| MSMSDCC_AUTO_CMD19;
 
-	if (version >= 0x2D) /* SDCC v4 2.1.0 and greater */
-		host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_SW_RST_CFG;
+	if ((step == 0x18) && (minor >= 3))
+		host->hw_caps |= MSMSDCC_AUTO_CMD21;
+
+	if (version >= 0x2b) /* SDCC v4 2.1.0 and greater */
+		host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_AUTO_CMD21;
 }
 
 int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 5e313e9..a807354 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -23,8 +23,13 @@
 #include <linux/crc32.h>
 #include <linux/mii.h>
 #include <linux/eeprom_93cx6.h>
+#include <linux/ks8851.h>
 
 #include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #include "ks8851.h"
 
@@ -131,6 +136,10 @@
 	struct spi_transfer	spi_xfer1;
 	struct spi_transfer	spi_xfer2[2];
 
+	struct regulator	*vdd_io;
+	struct regulator	*vdd_phy;
+	int			rst_gpio;
+
 	struct eeprom_93cx6	eeprom;
 };
 
@@ -1415,6 +1424,66 @@
 #define ks8851_resume NULL
 #endif
 
+static int __devinit ks8851_init_hw(struct spi_device *spi,
+				    struct ks8851_net *ks)
+{
+	struct ks8851_pdata *pdata = spi->dev.platform_data;
+	struct device_node *dnode = spi->dev.of_node;
+	enum of_gpio_flags flags;
+	int ret;
+
+	ks->rst_gpio = -ENODEV;
+
+	if (dnode)
+		ks->rst_gpio = of_get_named_gpio_flags(dnode, "rst-gpio",
+						       0, &flags);
+	else if (pdata)
+		ks->rst_gpio = pdata->rst_gpio;
+
+	if (gpio_is_valid(ks->rst_gpio)) {
+		ret = gpio_request(ks->rst_gpio, "ks8851_rst");
+		if (ret) {
+			pr_err("ks8851 gpio_request failed: %d\n", ret);
+			return ret;
+		}
+
+		/* Make sure the chip is in reset state */
+		gpio_direction_output(ks->rst_gpio, 0);
+	}
+
+	ks->vdd_io = regulator_get(&spi->dev, "vdd-io");
+
+	if (IS_ERR(ks->vdd_io)) {
+		ret = PTR_ERR(ks->vdd_io);
+		goto fail_gpio;
+	}
+
+	ks->vdd_phy = regulator_get(&spi->dev, "vdd-phy");
+
+	if (IS_ERR(ks->vdd_phy)) {
+		regulator_put(ks->vdd_io);
+		ret = PTR_ERR(ks->vdd_phy);
+		goto fail_gpio;
+	}
+
+	regulator_enable(ks->vdd_io);
+	regulator_enable(ks->vdd_phy);
+
+	/* Wait for atleast 10ms after turning on regulator */
+	usleep_range(10000, 11000);
+
+	if (gpio_is_valid(ks->rst_gpio))
+		gpio_direction_output(ks->rst_gpio, 1);
+
+	return 0;
+
+fail_gpio:
+	if (gpio_is_valid(ks->rst_gpio))
+		gpio_free(ks->rst_gpio);
+
+	return ret;
+}
+
 static int __devinit ks8851_probe(struct spi_device *spi)
 {
 	struct net_device *ndev;
@@ -1430,6 +1499,10 @@
 
 	ks = netdev_priv(ndev);
 
+	ret = ks8851_init_hw(spi, ks);
+	if (ret)
+		goto err_init;
+
 	ks->netdev = ndev;
 	ks->spidev = spi;
 	ks->tx_space = 6144;
@@ -1530,6 +1603,20 @@
 
 err_id:
 err_irq:
+	if (gpio_is_valid(ks->rst_gpio))
+		gpio_free(ks->rst_gpio);
+
+	if (!IS_ERR(ks->vdd_io)) {
+		regulator_disable(ks->vdd_io);
+		regulator_put(ks->vdd_io);
+	}
+
+	if (!IS_ERR(ks->vdd_phy)) {
+		regulator_disable(ks->vdd_phy);
+		regulator_put(ks->vdd_phy);
+	}
+
+err_init:
 	free_netdev(ndev);
 	return ret;
 }
@@ -1541,6 +1628,19 @@
 	if (netif_msg_drv(priv))
 		dev_info(&spi->dev, "remove\n");
 
+	if (gpio_is_valid(priv->rst_gpio))
+		gpio_free(priv->rst_gpio);
+
+	if (!IS_ERR(priv->vdd_io)) {
+		regulator_disable(priv->vdd_io);
+		regulator_put(priv->vdd_io);
+	}
+
+	if (!IS_ERR(priv->vdd_phy)) {
+		regulator_disable(priv->vdd_phy);
+		regulator_put(priv->vdd_phy);
+	}
+
 	unregister_netdev(priv->netdev);
 	free_irq(spi->irq, priv);
 	free_netdev(priv->netdev);
@@ -1548,9 +1648,17 @@
 	return 0;
 }
 
+static struct of_device_id ks8851_match_table[] = {
+	{
+		.compatible = "micrel,ks8851",
+	},
+	{}
+};
+
 static struct spi_driver ks8851_driver = {
 	.driver = {
 		.name = "ks8851",
+		.of_match_table = ks8851_match_table,
 		.owner = THIS_MODULE,
 	},
 	.probe = ks8851_probe,
diff --git a/drivers/net/ethernet/msm/Kconfig b/drivers/net/ethernet/msm/Kconfig
index 095cb4d..3fced2d 100644
--- a/drivers/net/ethernet/msm/Kconfig
+++ b/drivers/net/ethernet/msm/Kconfig
@@ -18,7 +18,7 @@
 
 config MSM_RMNET_BAM
 	bool "RMNET BAM Driver"
-	depends on MSM_BAM_DMUX
+	depends on (MSM_BAM_DMUX && NET_SCHED && NET_SCH_HTB && NET_SCH_PRIO && NET_CLS_FW)
 	default n
 	help
 	  Implements RMNET over BAM interface.
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 914f4fb..5278324 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -295,7 +295,7 @@
 
 config WCNSS_CORE
 	tristate "Qualcomm WCNSS CORE driver"
-	depends on ARCH_MSM8960
+	depends on (ARCH_MSM8960 || ARCH_MSM8974)
 	select WIRELESS_EXT
 	select WEXT_PRIV
 	select WEXT_CORE
@@ -303,6 +303,18 @@
 	---help---
 	  Core driver for the Qualcomm WCNSS triple play connectivity subsystem
 
+config WCNSS_CORE_PRONTO
+	tristate "Qualcomm WCNSS Pronto Support"
+	depends on WCNSS_CORE
+	---help---
+	  Pronto Support for the Qualcomm WCNSS triple play connectivity subsystem
+
+config WCNSS_MEM_PRE_ALLOC
+	tristate "WCNSS pre-alloc memory support"
+	depends on WCNSS_CORE
+	---help---
+	  Pre-allocate memory for the WLAN driver module
+
 source "drivers/net/wireless/ath/Kconfig"
 source "drivers/net/wireless/b43/Kconfig"
 source "drivers/net/wireless/b43legacy/Kconfig"
diff --git a/drivers/net/wireless/wcnss/Makefile b/drivers/net/wireless/wcnss/Makefile
index c077848..613d477 100644
--- a/drivers/net/wireless/wcnss/Makefile
+++ b/drivers/net/wireless/wcnss/Makefile
@@ -1,6 +1,7 @@
 
 # Makefile for WCNSS triple-play driver
 
-wcnsscore-objs += wcnss_wlan.o wcnss_riva.o qcomwlan_secif.o
+wcnsscore-objs += wcnss_wlan.o qcomwlan_secif.o wcnss_vreg.o
 
 obj-$(CONFIG_WCNSS_CORE) += wcnsscore.o
+obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += wcnss_prealloc.o
diff --git a/drivers/net/wireless/wcnss/wcnss_prealloc.c b/drivers/net/wireless/wcnss/wcnss_prealloc.c
new file mode 100644
index 0000000..7d10657
--- /dev/null
+++ b/drivers/net/wireless/wcnss/wcnss_prealloc.c
@@ -0,0 +1,103 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/wcnss_wlan.h>
+
+static DEFINE_MUTEX(alloc_lock);
+
+struct wcnss_prealloc {
+	int occupied;
+	unsigned int size;
+	void *ptr;
+};
+
+/* pre-alloced mem for WLAN driver */
+static struct wcnss_prealloc wcnss_allocs[] = {
+	{0, 8  * 1024, NULL},
+	{0, 8  * 1024, NULL},
+	{0, 8  * 1024, NULL},
+	{0, 8  * 1024, NULL},
+	{0, 32 * 1024, NULL},
+	{0, 32 * 1024, NULL},
+	{0, 32 * 1024, NULL},
+	{0, 32 * 1024, NULL},
+	{0, 32 * 1024, NULL},
+	{0, 32 * 1024, NULL},
+	{0, 32 * 1024, NULL},
+	{0, 64 * 1024, NULL},
+	{0, 64 * 1024, NULL},
+};
+
+int wcnss_prealloc_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) {
+		wcnss_allocs[i].occupied = 0;
+		wcnss_allocs[i].ptr = kmalloc(wcnss_allocs[i].size, GFP_KERNEL);
+		if (wcnss_allocs[i].ptr == NULL)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void wcnss_prealloc_deinit(void)
+{
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++)
+		kfree(wcnss_allocs[i].ptr);
+}
+
+void *wcnss_prealloc_get(unsigned int size)
+{
+	int i = 0;
+
+	mutex_lock(&alloc_lock);
+	for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) {
+		if (wcnss_allocs[i].occupied)
+			continue;
+
+		if (wcnss_allocs[i].size > size) {
+			/* we found the slot */
+			wcnss_allocs[i].occupied = 1;
+			mutex_unlock(&alloc_lock);
+			return wcnss_allocs[i].ptr;
+		}
+	}
+	pr_err("wcnss: %s: prealloc not available\n", __func__);
+	mutex_unlock(&alloc_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(wcnss_prealloc_get);
+
+int wcnss_prealloc_put(void *ptr)
+{
+	int i = 0;
+
+	mutex_lock(&alloc_lock);
+	for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) {
+		if (wcnss_allocs[i].ptr == ptr) {
+			wcnss_allocs[i].occupied = 0;
+			mutex_unlock(&alloc_lock);
+			return 1;
+		}
+	}
+	mutex_unlock(&alloc_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(wcnss_prealloc_put);
diff --git a/drivers/net/wireless/wcnss/wcnss_prealloc.h b/drivers/net/wireless/wcnss/wcnss_prealloc.h
new file mode 100644
index 0000000..73ae6c6
--- /dev/null
+++ b/drivers/net/wireless/wcnss/wcnss_prealloc.h
@@ -0,0 +1,19 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _WCNSS_PRE_ALLOC_H_
+#define _WCNSS_PRE_ALLOC_H_
+
+int wcnss_prealloc_init(void);
+void wcnss_prealloc_deinit(void);
+
+#endif/* _WCNSS_PRE_ALLOC_H_ */
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.c b/drivers/net/wireless/wcnss/wcnss_riva.c
deleted file mode 100644
index 2d9ad82..0000000
--- a/drivers/net/wireless/wcnss/wcnss_riva.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/* 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 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/slab.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/regulator/consumer.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
-#include <linux/mfd/pm8xxx/gpio.h>
-#include <linux/wcnss_wlan.h>
-#include <linux/semaphore.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <mach/msm_xo.h>
-#include <mach/msm_iomap.h>
-
-
-static void __iomem *msm_riva_base;
-static struct msm_xo_voter *wlan_clock;
-static const char *id = "WLAN";
-static LIST_HEAD(power_on_lock_list);
-static DEFINE_MUTEX(list_lock);
-static DEFINE_SEMAPHORE(riva_power_on_lock);
-
-#define MSM_RIVA_PHYS                     0x03204000
-#define RIVA_PMU_CFG                      (msm_riva_base + 0x28)
-#define RIVA_PMU_CFG_IRIS_XO_CFG          BIT(3)
-#define RIVA_PMU_CFG_IRIS_XO_EN           BIT(4)
-#define RIVA_PMU_CFG_GC_BUS_MUX_SEL_TOP   BIT(5)
-#define RIVA_PMU_CFG_IRIS_XO_CFG_STS      BIT(6) /* 1: in progress, 0: done */
-
-#define RIVA_PMU_CFG_IRIS_XO_MODE         0x6
-#define RIVA_PMU_CFG_IRIS_XO_MODE_48      (3 << 1)
-
-#define VREG_NULL_CONFIG            0x0000
-#define VREG_GET_REGULATOR_MASK     0x0001
-#define VREG_SET_VOLTAGE_MASK       0x0002
-#define VREG_OPTIMUM_MODE_MASK      0x0004
-#define VREG_ENABLE_MASK            0x0008
-
-struct vregs_info {
-	const char * const name;
-	int state;
-	const int nominal_min;
-	const int low_power_min;
-	const int max_voltage;
-	const int uA_load;
-	struct regulator *regulator;
-};
-
-static struct vregs_info iris_vregs[] = {
-	{"iris_vddxo",  VREG_NULL_CONFIG, 1800000, 0, 1800000, 10000,  NULL},
-	{"iris_vddrfa", VREG_NULL_CONFIG, 1300000, 0, 1300000, 100000, NULL},
-	{"iris_vddpa",  VREG_NULL_CONFIG, 2900000, 0, 3000000, 515000, NULL},
-	{"iris_vdddig", VREG_NULL_CONFIG, 1200000, 0, 1225000, 10000,  NULL},
-};
-
-static struct vregs_info riva_vregs[] = {
-	{"riva_vddmx",  VREG_NULL_CONFIG, 1050000, 0, 1150000, 0,      NULL},
-	{"riva_vddcx",  VREG_NULL_CONFIG, 1050000, 0, 1150000, 0,      NULL},
-	{"riva_vddpx",  VREG_NULL_CONFIG, 1800000, 0, 1800000, 0,      NULL},
-};
-
-struct host_driver {
-	char name[20];
-	struct list_head list;
-};
-
-
-static int configure_iris_xo(struct device *dev, bool use_48mhz_xo, int on)
-{
-	u32 reg = 0;
-	int rc = 0;
-	struct clk *cxo = clk_get(dev, "cxo");
-	if (IS_ERR(cxo)) {
-		pr_err("Couldn't get cxo clock\n");
-		return PTR_ERR(cxo);
-	}
-
-	if (on) {
-		msm_riva_base = ioremap(MSM_RIVA_PHYS, SZ_256);
-		if (!msm_riva_base) {
-			pr_err("ioremap MSM_RIVA_PHYS failed\n");
-			goto fail;
-		}
-
-		/* Enable IRIS XO */
-		rc = clk_prepare_enable(cxo);
-		if (rc) {
-			pr_err("cxo enable failed\n");
-			goto fail;
-		}
-		writel_relaxed(0, RIVA_PMU_CFG);
-		reg = readl_relaxed(RIVA_PMU_CFG);
-		reg |= RIVA_PMU_CFG_GC_BUS_MUX_SEL_TOP |
-				RIVA_PMU_CFG_IRIS_XO_EN;
-		writel_relaxed(reg, RIVA_PMU_CFG);
-
-		/* Clear XO_MODE[b2:b1] bits. Clear implies 19.2 MHz TCXO */
-		reg &= ~(RIVA_PMU_CFG_IRIS_XO_MODE);
-
-		if (use_48mhz_xo)
-			reg |= RIVA_PMU_CFG_IRIS_XO_MODE_48;
-
-		writel_relaxed(reg, RIVA_PMU_CFG);
-
-		/* Start IRIS XO configuration */
-		reg |= RIVA_PMU_CFG_IRIS_XO_CFG;
-		writel_relaxed(reg, RIVA_PMU_CFG);
-
-		/* Wait for XO configuration to finish */
-		while (readl_relaxed(RIVA_PMU_CFG) &
-						RIVA_PMU_CFG_IRIS_XO_CFG_STS)
-			cpu_relax();
-
-		/* Stop IRIS XO configuration */
-		reg &= ~(RIVA_PMU_CFG_GC_BUS_MUX_SEL_TOP |
-				RIVA_PMU_CFG_IRIS_XO_CFG);
-		writel_relaxed(reg, RIVA_PMU_CFG);
-		clk_disable_unprepare(cxo);
-
-		if (!use_48mhz_xo) {
-			wlan_clock = msm_xo_get(MSM_XO_TCXO_A2, id);
-			if (IS_ERR(wlan_clock)) {
-				rc = PTR_ERR(wlan_clock);
-				pr_err("Failed to get MSM_XO_TCXO_A2 voter"
-							" (%d)\n", rc);
-				goto fail;
-			}
-
-			rc = msm_xo_mode_vote(wlan_clock, MSM_XO_MODE_ON);
-			if (rc < 0) {
-				pr_err("Configuring MSM_XO_MODE_ON failed"
-							" (%d)\n", rc);
-				goto msm_xo_vote_fail;
-			}
-		}
-	}  else {
-		if (wlan_clock != NULL && !use_48mhz_xo) {
-			rc = msm_xo_mode_vote(wlan_clock, MSM_XO_MODE_OFF);
-			if (rc < 0)
-				pr_err("Configuring MSM_XO_MODE_OFF failed"
-							" (%d)\n", rc);
-		}
-	}
-
-	/* Add some delay for XO to settle */
-	msleep(20);
-
-	clk_put(cxo);
-	return rc;
-
-msm_xo_vote_fail:
-	msm_xo_put(wlan_clock);
-
-fail:
-	clk_put(cxo);
-	return rc;
-}
-
-/* Helper routine to turn off all WCNSS vregs e.g. IRIS, Riva */
-static void wcnss_vregs_off(struct vregs_info regulators[], uint size)
-{
-	int i, rc = 0;
-
-	/* Regulators need to be turned off in the reverse order */
-	for (i = (size-1); i >= 0; i--) {
-		if (regulators[i].state == VREG_NULL_CONFIG)
-			continue;
-
-		/* Remove PWM mode */
-		if (regulators[i].state & VREG_OPTIMUM_MODE_MASK) {
-			rc = regulator_set_optimum_mode(
-					regulators[i].regulator, 0);
-			if (rc < 0)
-				pr_err("regulator_set_optimum_mode(%s) failed (%d)\n",
-						regulators[i].name, rc);
-		}
-
-		/* Set voltage to lowest level */
-		if (regulators[i].state & VREG_SET_VOLTAGE_MASK) {
-			rc = regulator_set_voltage(regulators[i].regulator,
-					regulators[i].low_power_min,
-					regulators[i].max_voltage);
-			if (rc)
-				pr_err("regulator_set_voltage(%s) failed (%d)\n",
-						regulators[i].name, rc);
-		}
-
-		/* Disable regulator */
-		if (regulators[i].state & VREG_ENABLE_MASK) {
-			rc = regulator_disable(regulators[i].regulator);
-			if (rc < 0)
-				pr_err("vreg %s disable failed (%d)\n",
-						regulators[i].name, rc);
-		}
-
-		/* Free the regulator source */
-		if (regulators[i].state & VREG_GET_REGULATOR_MASK)
-			regulator_put(regulators[i].regulator);
-
-		regulators[i].state = VREG_NULL_CONFIG;
-	}
-}
-
-/* Common helper routine to turn on all WCNSS vregs e.g. IRIS, Riva */
-static int wcnss_vregs_on(struct device *dev,
-		struct vregs_info regulators[], uint size)
-{
-	int i, rc = 0, reg_cnt;
-
-	for (i = 0; i < size; i++) {
-			/* Get regulator source */
-		regulators[i].regulator =
-			regulator_get(dev, regulators[i].name);
-		if (IS_ERR(regulators[i].regulator)) {
-			rc = PTR_ERR(regulators[i].regulator);
-				pr_err("regulator get of %s failed (%d)\n",
-					regulators[i].name, rc);
-				goto fail;
-		}
-		regulators[i].state |= VREG_GET_REGULATOR_MASK;
-		reg_cnt = regulator_count_voltages(regulators[i].regulator);
-		/* Set voltage to nominal. Exclude swtiches e.g. LVS */
-		if ((regulators[i].nominal_min || regulators[i].max_voltage)
-				&& (reg_cnt > 0)) {
-			rc = regulator_set_voltage(regulators[i].regulator,
-					regulators[i].nominal_min,
-					regulators[i].max_voltage);
-			if (rc) {
-				pr_err("regulator_set_voltage(%s) failed (%d)\n",
-						regulators[i].name, rc);
-				goto fail;
-			}
-			regulators[i].state |= VREG_SET_VOLTAGE_MASK;
-		}
-
-		/* Vote for PWM/PFM mode if needed */
-		if (regulators[i].uA_load && (reg_cnt > 0)) {
-			rc = regulator_set_optimum_mode(regulators[i].regulator,
-					regulators[i].uA_load);
-			if (rc < 0) {
-				pr_err("regulator_set_optimum_mode(%s) failed (%d)\n",
-						regulators[i].name, rc);
-				goto fail;
-			}
-			regulators[i].state |= VREG_OPTIMUM_MODE_MASK;
-		}
-
-		/* Enable the regulator */
-		rc = regulator_enable(regulators[i].regulator);
-		if (rc) {
-			pr_err("vreg %s enable failed (%d)\n",
-				regulators[i].name, rc);
-			goto fail;
-		}
-		regulators[i].state |= VREG_ENABLE_MASK;
-	}
-
-	return rc;
-
-fail:
-	wcnss_vregs_off(regulators, size);
-	return rc;
-
-}
-
-static void wcnss_iris_vregs_off(void)
-{
-	wcnss_vregs_off(iris_vregs, ARRAY_SIZE(iris_vregs));
-}
-
-static int wcnss_iris_vregs_on(struct device *dev)
-{
-	return wcnss_vregs_on(dev, iris_vregs, ARRAY_SIZE(iris_vregs));
-}
-
-static void wcnss_riva_vregs_off(void)
-{
-	wcnss_vregs_off(riva_vregs, ARRAY_SIZE(riva_vregs));
-}
-
-static int wcnss_riva_vregs_on(struct device *dev)
-{
-	return wcnss_vregs_on(dev, riva_vregs, ARRAY_SIZE(riva_vregs));
-}
-
-int wcnss_wlan_power(struct device *dev,
-		struct wcnss_wlan_config *cfg,
-		enum wcnss_opcode on)
-{
-	int rc = 0;
-
-	if (on) {
-		down(&riva_power_on_lock);
-		/* RIVA regulator settings */
-		rc = wcnss_riva_vregs_on(dev);
-		if (rc)
-			goto fail_riva_on;
-
-		/* IRIS regulator settings */
-		rc = wcnss_iris_vregs_on(dev);
-		if (rc)
-			goto fail_iris_on;
-
-		/* Configure IRIS XO */
-		rc = configure_iris_xo(dev, cfg->use_48mhz_xo,
-				WCNSS_WLAN_SWITCH_ON);
-		if (rc)
-			goto fail_iris_xo;
-		up(&riva_power_on_lock);
-
-	} else {
-		configure_iris_xo(dev, cfg->use_48mhz_xo,
-				WCNSS_WLAN_SWITCH_OFF);
-		wcnss_iris_vregs_off();
-		wcnss_riva_vregs_off();
-	}
-
-	return rc;
-
-fail_iris_xo:
-	wcnss_iris_vregs_off();
-
-fail_iris_on:
-	wcnss_riva_vregs_off();
-
-fail_riva_on:
-	up(&riva_power_on_lock);
-	return rc;
-}
-EXPORT_SYMBOL(wcnss_wlan_power);
-
-/*
- * During SSR Riva should not be 'powered on' until all the host drivers
- * finish their shutdown routines.  Host drivers use below APIs to
- * synchronize power-on. Riva will not be 'powered on' until all the
- * requests(to lock power-on) are freed.
- */
-int req_riva_power_on_lock(char *driver_name)
-{
-	struct host_driver *node;
-
-	if (!driver_name)
-		goto err;
-
-	node = kmalloc(sizeof(struct host_driver), GFP_KERNEL);
-	if (!node)
-		goto err;
-	strncpy(node->name, driver_name, sizeof(node->name));
-
-	mutex_lock(&list_lock);
-	/* Lock when the first request is added */
-	if (list_empty(&power_on_lock_list))
-		down(&riva_power_on_lock);
-	list_add(&node->list, &power_on_lock_list);
-	mutex_unlock(&list_lock);
-
-	return 0;
-
-err:
-	return -EINVAL;
-}
-EXPORT_SYMBOL(req_riva_power_on_lock);
-
-int free_riva_power_on_lock(char *driver_name)
-{
-	int ret = -1;
-	struct host_driver *node;
-
-	mutex_lock(&list_lock);
-	list_for_each_entry(node, &power_on_lock_list, list) {
-		if (!strncmp(node->name, driver_name, sizeof(node->name))) {
-			list_del(&node->list);
-			kfree(node);
-			ret = 0;
-			break;
-		}
-	}
-	/* unlock when the last host driver frees the lock */
-	if (list_empty(&power_on_lock_list))
-		up(&riva_power_on_lock);
-	mutex_unlock(&list_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL(free_riva_power_on_lock);
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
new file mode 100644
index 0000000..75c75a8
--- /dev/null
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -0,0 +1,503 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/mfd/pm8xxx/gpio.h>
+#include <linux/wcnss_wlan.h>
+#include <linux/semaphore.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <mach/msm_xo.h>
+#include <mach/msm_iomap.h>
+
+
+static void __iomem *msm_wcnss_base;
+static struct msm_xo_voter *wlan_clock;
+static const char *id = "WLAN";
+static LIST_HEAD(power_on_lock_list);
+static DEFINE_MUTEX(list_lock);
+static DEFINE_SEMAPHORE(wcnss_power_on_lock);
+
+#define MSM_RIVA_PHYS           0x03204000
+#define MSM_PRONTO_PHYS         0xfb21b000
+
+#define RIVA_PMU_OFFSET         0x28
+#define PRONTO_PMU_OFFSET       0x1004
+
+#define WCNSS_PMU_CFG_IRIS_XO_CFG          BIT(3)
+#define WCNSS_PMU_CFG_IRIS_XO_EN           BIT(4)
+#define WCNSS_PMU_CFG_GC_BUS_MUX_SEL_TOP   BIT(5)
+#define WCNSS_PMU_CFG_IRIS_XO_CFG_STS      BIT(6) /* 1: in progress, 0: done */
+
+#define WCNSS_PMU_CFG_IRIS_XO_MODE         0x6
+#define WCNSS_PMU_CFG_IRIS_XO_MODE_48      (3 << 1)
+
+#define VREG_NULL_CONFIG            0x0000
+#define VREG_GET_REGULATOR_MASK     0x0001
+#define VREG_SET_VOLTAGE_MASK       0x0002
+#define VREG_OPTIMUM_MODE_MASK      0x0004
+#define VREG_ENABLE_MASK            0x0008
+
+struct vregs_info {
+	const char * const name;
+	int state;
+	const int nominal_min;
+	const int low_power_min;
+	const int max_voltage;
+	const int uA_load;
+	struct regulator *regulator;
+};
+
+/* IRIS regulators for Riva hardware */
+static struct vregs_info iris_vregs_riva[] = {
+	{"iris_vddxo",  VREG_NULL_CONFIG, 1800000, 0, 1800000, 10000,  NULL},
+	{"iris_vddrfa", VREG_NULL_CONFIG, 1300000, 0, 1300000, 100000, NULL},
+	{"iris_vddpa",  VREG_NULL_CONFIG, 2900000, 0, 3000000, 515000, NULL},
+	{"iris_vdddig", VREG_NULL_CONFIG, 1200000, 0, 1225000, 10000,  NULL},
+};
+
+/* WCNSS regulators for Riva hardware */
+static struct vregs_info riva_vregs[] = {
+	/* Riva */
+	{"riva_vddmx",  VREG_NULL_CONFIG, 1050000, 0, 1150000, 0,      NULL},
+	{"riva_vddcx",  VREG_NULL_CONFIG, 1050000, 0, 1150000, 0,      NULL},
+	{"riva_vddpx",  VREG_NULL_CONFIG, 1800000, 0, 1800000, 0,      NULL},
+};
+
+/* IRIS regulators for Pronto hardware */
+static struct vregs_info iris_vregs_pronto[] = {
+	{"qcom,iris-vddxo",  VREG_NULL_CONFIG, 1800000, 0,
+		1800000, 10000,  NULL},
+	{"qcom,iris-vddrfa", VREG_NULL_CONFIG, 1300000, 0,
+		1300000, 100000, NULL},
+	{"qcom,iris-vddpa",  VREG_NULL_CONFIG, 2900000, 0,
+		3000000, 515000, NULL},
+	{"qcom,iris-vdddig", VREG_NULL_CONFIG, 1225000, 0,
+		1225000, 10000,  NULL},
+};
+
+/* WCNSS regulators for Pronto hardware */
+static struct vregs_info pronto_vregs[] = {
+	{"qcom,pronto-vddmx",  VREG_NULL_CONFIG, 950000,  0,
+		1150000, 0,    NULL},
+	{"qcom,pronto-vddcx",  VREG_NULL_CONFIG, 900000,  0,
+		1150000, 0,    NULL},
+	{"qcom,pronto-vddpx",  VREG_NULL_CONFIG, 1800000, 0,
+		1800000, 0,    NULL},
+};
+
+
+struct host_driver {
+	char name[20];
+	struct list_head list;
+};
+
+
+static int configure_iris_xo(struct device *dev, bool use_48mhz_xo, int on)
+{
+	u32 reg = 0;
+	int rc = 0;
+	int size = 0;
+	int pmu_offset = 0;
+	unsigned long wcnss_phys_addr;
+	void __iomem *pmu_conf_reg;
+	struct clk *clk;
+
+	if (wcnss_hardware_type() == WCNSS_PRONTO_HW) {
+		wcnss_phys_addr = MSM_PRONTO_PHYS;
+		pmu_offset = PRONTO_PMU_OFFSET;
+		size = 0x3000;
+
+		clk = clk_get(dev, "xo");
+		if (IS_ERR(clk)) {
+			pr_err("Couldn't get xo clock\n");
+			return PTR_ERR(clk);
+		}
+	} else {
+		wcnss_phys_addr = MSM_RIVA_PHYS;
+		pmu_offset = RIVA_PMU_OFFSET;
+		size = SZ_256;
+
+		clk = clk_get(dev, "cxo");
+		if (IS_ERR(clk)) {
+			pr_err("Couldn't get cxo clock\n");
+			return PTR_ERR(clk);
+		}
+	}
+
+	if (on) {
+		msm_wcnss_base = ioremap(wcnss_phys_addr, size);
+		if (!msm_wcnss_base) {
+			pr_err("ioremap wcnss physical failed\n");
+			goto fail;
+		}
+		pmu_conf_reg = msm_wcnss_base + pmu_offset;
+
+		/* Enable IRIS XO */
+		rc = clk_prepare_enable(clk);
+		if (rc) {
+			pr_err("clk enable failed\n");
+			goto fail;
+		}
+		writel_relaxed(0, pmu_conf_reg);
+		reg = readl_relaxed(pmu_conf_reg);
+		reg |= WCNSS_PMU_CFG_GC_BUS_MUX_SEL_TOP |
+				WCNSS_PMU_CFG_IRIS_XO_EN;
+		writel_relaxed(reg, pmu_conf_reg);
+
+		/* Clear XO_MODE[b2:b1] bits. Clear implies 19.2 MHz TCXO */
+		reg &= ~(WCNSS_PMU_CFG_IRIS_XO_MODE);
+
+		if (use_48mhz_xo)
+			reg |= WCNSS_PMU_CFG_IRIS_XO_MODE_48;
+
+		writel_relaxed(reg, pmu_conf_reg);
+
+		/* Start IRIS XO configuration */
+		reg |= WCNSS_PMU_CFG_IRIS_XO_CFG;
+		writel_relaxed(reg, pmu_conf_reg);
+
+		/* Wait for XO configuration to finish */
+		while (readl_relaxed(pmu_conf_reg) &
+						WCNSS_PMU_CFG_IRIS_XO_CFG_STS)
+			cpu_relax();
+
+		/* Stop IRIS XO configuration */
+		reg &= ~(WCNSS_PMU_CFG_GC_BUS_MUX_SEL_TOP |
+				WCNSS_PMU_CFG_IRIS_XO_CFG);
+		writel_relaxed(reg, pmu_conf_reg);
+		clk_disable_unprepare(clk);
+
+		if (!use_48mhz_xo) {
+			wlan_clock = msm_xo_get(MSM_XO_TCXO_A2, id);
+			if (IS_ERR(wlan_clock)) {
+				rc = PTR_ERR(wlan_clock);
+				pr_err("Failed to get MSM_XO_TCXO_A2 voter (%d)\n",
+						rc);
+				goto fail;
+			}
+
+			rc = msm_xo_mode_vote(wlan_clock, MSM_XO_MODE_ON);
+			if (rc < 0) {
+				pr_err("Configuring MSM_XO_MODE_ON failed (%d)\n",
+						rc);
+				goto msm_xo_vote_fail;
+			}
+		}
+	}  else {
+		if (wlan_clock != NULL && !use_48mhz_xo) {
+			rc = msm_xo_mode_vote(wlan_clock, MSM_XO_MODE_OFF);
+			if (rc < 0)
+				pr_err("Configuring MSM_XO_MODE_OFF failed (%d)\n",
+						rc);
+		}
+	}
+
+	/* Add some delay for XO to settle */
+	msleep(20);
+
+	clk_put(clk);
+	return rc;
+
+msm_xo_vote_fail:
+	msm_xo_put(wlan_clock);
+
+fail:
+	clk_put(clk);
+	return rc;
+}
+
+/* Helper routine to turn off all WCNSS & IRIS vregs */
+static void wcnss_vregs_off(struct vregs_info regulators[], uint size)
+{
+	int i, rc = 0;
+
+	/* Regulators need to be turned off in the reverse order */
+	for (i = (size-1); i >= 0; i--) {
+		if (regulators[i].state == VREG_NULL_CONFIG)
+			continue;
+
+		/* Remove PWM mode */
+		if (regulators[i].state & VREG_OPTIMUM_MODE_MASK) {
+			rc = regulator_set_optimum_mode(
+					regulators[i].regulator, 0);
+			if (rc < 0)
+				pr_err("regulator_set_optimum_mode(%s) failed (%d)\n",
+						regulators[i].name, rc);
+		}
+
+		/* Set voltage to lowest level */
+		if (regulators[i].state & VREG_SET_VOLTAGE_MASK) {
+			rc = regulator_set_voltage(regulators[i].regulator,
+					regulators[i].low_power_min,
+					regulators[i].max_voltage);
+			if (rc)
+				pr_err("regulator_set_voltage(%s) failed (%d)\n",
+						regulators[i].name, rc);
+		}
+
+		/* Disable regulator */
+		if (regulators[i].state & VREG_ENABLE_MASK) {
+			rc = regulator_disable(regulators[i].regulator);
+			if (rc < 0)
+				pr_err("vreg %s disable failed (%d)\n",
+						regulators[i].name, rc);
+		}
+
+		/* Free the regulator source */
+		if (regulators[i].state & VREG_GET_REGULATOR_MASK)
+			regulator_put(regulators[i].regulator);
+
+		regulators[i].state = VREG_NULL_CONFIG;
+	}
+}
+
+/* Common helper routine to turn on all WCNSS & IRIS vregs */
+static int wcnss_vregs_on(struct device *dev,
+		struct vregs_info regulators[], uint size)
+{
+	int i, rc = 0, reg_cnt;
+
+	for (i = 0; i < size; i++) {
+			/* Get regulator source */
+		regulators[i].regulator =
+			regulator_get(dev, regulators[i].name);
+		if (IS_ERR(regulators[i].regulator)) {
+			rc = PTR_ERR(regulators[i].regulator);
+				pr_err("regulator get of %s failed (%d)\n",
+					regulators[i].name, rc);
+				goto fail;
+		}
+		regulators[i].state |= VREG_GET_REGULATOR_MASK;
+		reg_cnt = regulator_count_voltages(regulators[i].regulator);
+		/* Set voltage to nominal. Exclude swtiches e.g. LVS */
+		if ((regulators[i].nominal_min || regulators[i].max_voltage)
+				&& (reg_cnt > 0)) {
+			rc = regulator_set_voltage(regulators[i].regulator,
+					regulators[i].nominal_min,
+					regulators[i].max_voltage);
+			if (rc) {
+				pr_err("regulator_set_voltage(%s) failed (%d)\n",
+						regulators[i].name, rc);
+				goto fail;
+			}
+			regulators[i].state |= VREG_SET_VOLTAGE_MASK;
+		}
+
+		/* Vote for PWM/PFM mode if needed */
+		if (regulators[i].uA_load && (reg_cnt > 0)) {
+			rc = regulator_set_optimum_mode(regulators[i].regulator,
+					regulators[i].uA_load);
+			if (rc < 0) {
+				pr_err("regulator_set_optimum_mode(%s) failed (%d)\n",
+						regulators[i].name, rc);
+				goto fail;
+			}
+			regulators[i].state |= VREG_OPTIMUM_MODE_MASK;
+		}
+
+		/* Enable the regulator */
+		rc = regulator_enable(regulators[i].regulator);
+		if (rc) {
+			pr_err("vreg %s enable failed (%d)\n",
+				regulators[i].name, rc);
+			goto fail;
+		}
+		regulators[i].state |= VREG_ENABLE_MASK;
+	}
+
+	return rc;
+
+fail:
+	wcnss_vregs_off(regulators, size);
+	return rc;
+
+}
+
+static void wcnss_iris_vregs_off(enum wcnss_hw_type hw_type)
+{
+	switch (hw_type) {
+	case WCNSS_RIVA_HW:
+		wcnss_vregs_off(iris_vregs_riva, ARRAY_SIZE(iris_vregs_riva));
+		break;
+	case WCNSS_PRONTO_HW:
+		wcnss_vregs_off(iris_vregs_pronto,
+				ARRAY_SIZE(iris_vregs_pronto));
+		break;
+	default:
+		pr_err("%s invalid hardware %d\n", __func__, hw_type);
+
+	}
+}
+
+static int wcnss_iris_vregs_on(struct device *dev, enum wcnss_hw_type hw_type)
+{
+	int ret = -1;
+
+	switch (hw_type) {
+	case WCNSS_RIVA_HW:
+		ret = wcnss_vregs_on(dev, iris_vregs_riva,
+				ARRAY_SIZE(iris_vregs_riva));
+		break;
+	case WCNSS_PRONTO_HW:
+		ret = wcnss_vregs_on(dev, iris_vregs_pronto,
+				ARRAY_SIZE(iris_vregs_pronto));
+		break;
+	default:
+		pr_err("%s invalid hardware %d\n", __func__, hw_type);
+	}
+	return ret;
+}
+
+static void wcnss_core_vregs_off(enum wcnss_hw_type hw_type)
+{
+	switch (hw_type) {
+	case WCNSS_RIVA_HW:
+		wcnss_vregs_off(riva_vregs, ARRAY_SIZE(riva_vregs));
+		break;
+	case WCNSS_PRONTO_HW:
+		wcnss_vregs_off(pronto_vregs, ARRAY_SIZE(pronto_vregs));
+		break;
+	default:
+		pr_err("%s invalid hardware %d\n", __func__, hw_type);
+	}
+
+}
+
+static int wcnss_core_vregs_on(struct device *dev, enum wcnss_hw_type hw_type)
+{
+	int ret = -1;
+
+	switch (hw_type) {
+	case WCNSS_RIVA_HW:
+		ret = wcnss_vregs_on(dev, riva_vregs, ARRAY_SIZE(riva_vregs));
+		break;
+	case WCNSS_PRONTO_HW:
+		ret = wcnss_vregs_on(dev, pronto_vregs,
+				ARRAY_SIZE(pronto_vregs));
+		break;
+	default:
+		pr_err("%s invalid hardware %d\n", __func__, hw_type);
+	}
+
+	return ret;
+
+}
+
+int wcnss_wlan_power(struct device *dev,
+		struct wcnss_wlan_config *cfg,
+		enum wcnss_opcode on)
+{
+	int rc = 0;
+	enum wcnss_hw_type hw_type = wcnss_hardware_type();
+
+	if (on) {
+		down(&wcnss_power_on_lock);
+		/* RIVA regulator settings */
+		rc = wcnss_core_vregs_on(dev, hw_type);
+		if (rc)
+			goto fail_wcnss_on;
+
+		/* IRIS regulator settings */
+		rc = wcnss_iris_vregs_on(dev, hw_type);
+		if (rc)
+			goto fail_iris_on;
+
+		/* Configure IRIS XO */
+		rc = configure_iris_xo(dev, cfg->use_48mhz_xo,
+				WCNSS_WLAN_SWITCH_ON);
+		if (rc)
+			goto fail_iris_xo;
+		up(&wcnss_power_on_lock);
+
+	} else {
+		configure_iris_xo(dev, cfg->use_48mhz_xo,
+				WCNSS_WLAN_SWITCH_OFF);
+		wcnss_iris_vregs_off(hw_type);
+		wcnss_core_vregs_off(hw_type);
+	}
+
+	return rc;
+
+fail_iris_xo:
+	wcnss_iris_vregs_off(hw_type);
+
+fail_iris_on:
+	wcnss_core_vregs_off(hw_type);
+
+fail_wcnss_on:
+	up(&wcnss_power_on_lock);
+	return rc;
+}
+EXPORT_SYMBOL(wcnss_wlan_power);
+
+/*
+ * During SSR WCNSS should not be 'powered on' until all the host drivers
+ * finish their shutdown routines.  Host drivers use below APIs to
+ * synchronize power-on. WCNSS will not be 'powered on' until all the
+ * requests(to lock power-on) are freed.
+ */
+int wcnss_req_power_on_lock(char *driver_name)
+{
+	struct host_driver *node;
+
+	if (!driver_name)
+		goto err;
+
+	node = kmalloc(sizeof(struct host_driver), GFP_KERNEL);
+	if (!node)
+		goto err;
+	strlcpy(node->name, driver_name, sizeof(node->name));
+
+	mutex_lock(&list_lock);
+	/* Lock when the first request is added */
+	if (list_empty(&power_on_lock_list))
+		down(&wcnss_power_on_lock);
+	list_add(&node->list, &power_on_lock_list);
+	mutex_unlock(&list_lock);
+
+	return 0;
+
+err:
+	return -EINVAL;
+}
+EXPORT_SYMBOL(wcnss_req_power_on_lock);
+
+int wcnss_free_power_on_lock(char *driver_name)
+{
+	int ret = -1;
+	struct host_driver *node;
+
+	mutex_lock(&list_lock);
+	list_for_each_entry(node, &power_on_lock_list, list) {
+		if (!strncmp(node->name, driver_name, sizeof(node->name))) {
+			list_del(&node->list);
+			kfree(node);
+			ret = 0;
+			break;
+		}
+	}
+	/* unlock when the last host driver frees the lock */
+	if (list_empty(&power_on_lock_list))
+		up(&wcnss_power_on_lock);
+	mutex_unlock(&list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(wcnss_free_power_on_lock);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 633809a..ac0a2fd 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -23,8 +23,13 @@
 #include <linux/gpio.h>
 #include <linux/wakelock.h>
 #include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <mach/peripheral-loader.h>
 #include <mach/msm_smd.h>
+#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
+#include "wcnss_prealloc.h"
+#endif
 
 #define DEVICE "wcnss_wlan"
 #define VERSION "1.01"
@@ -76,6 +81,7 @@
 	unsigned char	wcnss_version[WCNSS_VERSION_LEN];
 	unsigned int	serial_number;
 	int		thermal_mitigation;
+	enum wcnss_hw_type	wcnss_hw_type;
 	void		(*tm_notify)(struct device *, int);
 	struct wcnss_wlan_config wlan_config;
 	struct delayed_work wcnss_work;
@@ -225,11 +231,42 @@
 
 static void wcnss_post_bootup(struct work_struct *work)
 {
-	pr_info("%s: Cancel APPS vote for Iris & Riva\n", __func__);
+	pr_info("%s: Cancel APPS vote for Iris & WCNSS\n", __func__);
 
-	/* Since Riva is up, cancel any APPS vote for Iris & Riva VREGs  */
+	/* Since WCNSS is up, cancel any APPS vote for Iris & WCNSS VREGs  */
 	wcnss_wlan_power(&penv->pdev->dev, &penv->wlan_config,
 		WCNSS_WLAN_SWITCH_OFF);
+
+}
+
+static int
+wcnss_pronto_gpios_config(struct device *dev, bool enable)
+{
+	int rc = 0;
+	int i, j;
+	int WCNSS_WLAN_NUM_GPIOS = 5;
+
+	for (i = 0; i < WCNSS_WLAN_NUM_GPIOS; i++) {
+		int gpio = of_get_gpio(dev->of_node, i);
+		if (enable) {
+			rc = gpio_request(gpio, "wcnss_wlan");
+			if (rc) {
+				pr_err("WCNSS gpio_request %d err %d\n",
+					gpio, rc);
+				goto fail;
+			}
+		} else
+			gpio_free(gpio);
+	}
+
+	return rc;
+
+fail:
+	for (j = WCNSS_WLAN_NUM_GPIOS-1; j >= 0; j--) {
+		int gpio = of_get_gpio(dev->of_node, i);
+		gpio_free(gpio);
+	}
+	return rc;
 }
 
 static int
@@ -469,6 +506,15 @@
 }
 EXPORT_SYMBOL(wcnss_allow_suspend);
 
+int wcnss_hardware_type(void)
+{
+	if (penv)
+		return penv->wcnss_hw_type;
+	else
+		return -ENODEV;
+}
+EXPORT_SYMBOL(wcnss_hardware_type);
+
 static int wcnss_smd_tx(void *data, int len)
 {
 	int ret = 0;
@@ -551,6 +597,8 @@
 {
 	int ret;
 	struct qcom_wcnss_opts *pdata;
+	int has_pronto_hw = of_property_read_bool(pdev->dev.of_node,
+									"qcom,has_pronto_hw");
 
 	/* make sure we are only triggered once */
 	if (penv->triggered)
@@ -559,25 +607,36 @@
 
 	/* initialize the WCNSS device configuration */
 	pdata = pdev->dev.platform_data;
-	if (WCNSS_CONFIG_UNSPECIFIED == has_48mhz_xo)
-		has_48mhz_xo = pdata->has_48mhz_xo;
+	if (WCNSS_CONFIG_UNSPECIFIED == has_48mhz_xo) {
+		if (has_pronto_hw) {
+			has_48mhz_xo = of_property_read_bool(pdev->dev.of_node,
+										"qcom,has_48mhz_xo");
+			penv->wcnss_hw_type = WCNSS_PRONTO_HW;
+		} else {
+			penv->wcnss_hw_type = WCNSS_RIVA_HW;
+			has_48mhz_xo = pdata->has_48mhz_xo;
+		}
+	}
 	penv->wlan_config.use_48mhz_xo = has_48mhz_xo;
 
 	penv->thermal_mitigation = 0;
 	strlcpy(penv->wcnss_version, "INVALID", WCNSS_VERSION_LEN);
 
-	penv->gpios_5wire = platform_get_resource_byname(pdev, IORESOURCE_IO,
-							"wcnss_gpios_5wire");
-
-	/* allocate 5-wire GPIO resources */
-	if (!penv->gpios_5wire) {
-		dev_err(&pdev->dev, "insufficient IO resources\n");
-		ret = -ENOENT;
-		goto fail_gpio_res;
-	}
-
 	/* Configure 5 wire GPIOs */
-	ret = wcnss_gpios_config(penv->gpios_5wire, true);
+	if (!has_pronto_hw) {
+		penv->gpios_5wire = platform_get_resource_byname(pdev,
+					IORESOURCE_IO, "wcnss_gpios_5wire");
+
+		/* allocate 5-wire GPIO resources */
+		if (!penv->gpios_5wire) {
+			dev_err(&pdev->dev, "insufficient IO resources\n");
+			ret = -ENOENT;
+			goto fail_gpio_res;
+		}
+		ret = wcnss_gpios_config(penv->gpios_5wire, true);
+	} else
+		ret = wcnss_pronto_gpios_config(&pdev->dev, true);
+
 	if (ret) {
 		dev_err(&pdev->dev, "WCNSS gpios config failed.\n");
 		goto fail_gpio_res;
@@ -627,7 +686,10 @@
 	wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
 				WCNSS_WLAN_SWITCH_OFF);
 fail_power:
-	wcnss_gpios_config(penv->gpios_5wire, false);
+	if (has_pronto_hw)
+		ret = wcnss_pronto_gpios_config(&pdev->dev, false);
+	else
+		wcnss_gpios_config(penv->gpios_5wire, false);
 fail_gpio_res:
 	kfree(penv);
 	penv = NULL;
@@ -724,11 +786,21 @@
 	.resume		= wcnss_wlan_resume,
 };
 
+#ifdef CONFIG_WCNSS_CORE_PRONTO
+static struct of_device_id msm_wcnss_pronto_match[] = {
+	{.compatible = "qcom,wcnss_wlan"},
+	{}
+};
+#endif
+
 static struct platform_driver wcnss_wlan_driver = {
 	.driver = {
 		.name	= DEVICE,
 		.owner	= THIS_MODULE,
 		.pm	= &wcnss_wlan_pm_ops,
+#ifdef CONFIG_WCNSS_CORE_PRONTO
+		.of_match_table = msm_wcnss_pronto_match,
+#endif
 	},
 	.probe	= wcnss_wlan_probe,
 	.remove	= __devexit_p(wcnss_wlan_remove),
@@ -736,11 +808,19 @@
 
 static int __init wcnss_wlan_init(void)
 {
+	int ret = 0;
+
 	platform_driver_register(&wcnss_wlan_driver);
 	platform_driver_register(&wcnss_wlan_ctrl_driver);
 	platform_driver_register(&wcnss_ctrl_driver);
 
-	return 0;
+#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
+	ret = wcnss_prealloc_init();
+	if (ret < 0)
+		pr_err("wcnss: pre-allocation failed\n");
+#endif
+
+	return ret;
 }
 
 static void __exit wcnss_wlan_exit(void)
@@ -757,6 +837,9 @@
 	platform_driver_unregister(&wcnss_ctrl_driver);
 	platform_driver_unregister(&wcnss_wlan_ctrl_driver);
 	platform_driver_unregister(&wcnss_wlan_driver);
+#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
+	wcnss_prealloc_deinit();
+#endif
 }
 
 module_init(wcnss_wlan_init);
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index bf984b6..94e76d8 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -49,7 +49,7 @@
 	if (!gc) {
 		pr_debug("%s: gpio controller %s isn't registered\n",
 			 np->full_name, gpiospec.np->full_name);
-		ret = -ENODEV;
+		ret = -EPROBE_DEFER;
 		goto err1;
 	}
 
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 0119ebe..996456f 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -435,6 +435,14 @@
 		return -EINVAL;
 	}
 
+	/* mark the interrupts wakeable if they support linux-key */
+	if (cfg->key_code) {
+		enable_irq_wake(cfg->state_irq);
+		/* special handling for RESIN due to a hardware bug */
+		if (cfg->pon_type == PON_RESIN && cfg->support_reset)
+			enable_irq_wake(cfg->bark_irq);
+	}
+
 	return rc;
 }
 
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index e3be11d..f671ece 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -1369,8 +1369,8 @@
 	}
 
 	if (event_reg->callback) {
-		event_reg->callback(&sps_event->notify);
 		SPS_DBG("sps:trigger_event.using callback.");
+		event_reg->callback(&sps_event->notify);
 	}
 
 }
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index a263750..d8baa29 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -415,6 +415,14 @@
 	help
 	  Say Y here to enable support for pm8921 chip bms subdevice
 
+config BATTERY_BCL
+	tristate "Battery Current Limit driver"
+	help
+	  Say Y here to enable support for battery current limit
+	  device. The BCL driver will poll BMS if
+	  thermal daemon enables BCL.
+	  It will notify thermal daemon if IBat crosses Imax threshold.
+
 config CHARGER_SMB347
 	tristate "Summit Microelectronics SMB347 Battery Charger"
 	depends on I2C
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 007d75b..f84b527 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -58,3 +58,4 @@
 obj-$(CONFIG_PM8921_CHARGER)	+= pm8921-charger.o
 obj-$(CONFIG_LTC4088_CHARGER)	+= ltc4088-charger.o
 obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
+obj-$(CONFIG_BATTERY_BCL)	+= battery_current_limit.o
diff --git a/drivers/power/battery_current_limit.c b/drivers/power/battery_current_limit.c
new file mode 100644
index 0000000..d1750ec
--- /dev/null
+++ b/drivers/power/battery_current_limit.c
@@ -0,0 +1,534 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/power_supply.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#define BCL_DEV_NAME "battery_current_limit"
+#define BCL_NAME_LENGTH 20
+/*
+ * Default BCL poll interval 1000 msec
+ */
+#define BCL_POLL_INTERVAL 1000
+/*
+ * Mininum BCL poll interval 10 msec
+ */
+#define MIN_BCL_POLL_INTERVAL 10
+
+static const char bcl_type[] = "bcl";
+
+/*
+ * Battery Current Limit Enable or Not
+ */
+enum bcl_device_mode {
+	BCL_DEVICE_DISABLED = 0,
+	BCL_DEVICE_ENABLED,
+};
+
+/*
+ * Battery Current Limit IBat Imax Threshold Mode
+ */
+enum bcl_ibat_imax_threshold_mode {
+	BCL_IBAT_IMAX_THRESHOLD_DISABLED = 0,
+	BCL_IBAT_IMAX_THRESHOLD_ENABLED,
+};
+
+/*
+ * Battery Current Limit Ibat Imax Trip Type (High and Low Threshold)
+ */
+enum bcl_ibat_imax_threshold_type {
+	BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW = 0,
+	BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH,
+	BCL_IBAT_IMAX_THRESHOLD_TYPE_MAX,
+};
+
+/**
+ * BCL control block
+ *
+ */
+struct bcl_context {
+	/* BCL device */
+	struct device *dev;
+
+	/* BCL related config parameter */
+	/* BCL mode enable or not */
+	enum bcl_device_mode bcl_mode;
+	/* BCL Ibat/IMax Threshold Activate or Not */
+	enum bcl_ibat_imax_threshold_mode
+		bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_MAX];
+	/* BCL Ibat/IMax Threshold value in milli Amp */
+	int bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_MAX];
+	/* BCL Type */
+	char bcl_type[BCL_NAME_LENGTH];
+	/* BCL poll in usec */
+	int bcl_poll_interval_msec;
+
+	/* BCL realtime value based on poll */
+	/* BCL realtime ibat in milli Amp*/
+	int bcl_ibat_ma;
+	/* BCL realtime calculated imax in milli Amp*/
+	int bcl_imax_ma;
+	/* BCL realtime calculated ocv in uV*/
+	int bcl_ocv_uv;
+	/* BCL realtime vbat in mV*/
+	int bcl_vbat_mv;
+	/* BCL realtime rbat in mOhms*/
+	int bcl_rbat;
+	/* BCL period poll delay work structure  */
+	struct delayed_work     bcl_imax_work;
+
+};
+
+static struct bcl_context *gbcl;
+
+/*
+ * BCL imax calculation and trigger notification to user space
+ * if imax cross threshold
+ */
+static void bcl_calculate_imax_trigger(void)
+{
+	int ibatt_ua, vbatt_uv;
+	int imax_ma;
+	int ibatt_ma, vbatt_mv;
+	int imax_low_threshold;
+	int imax_high_threshold;
+	bool threshold_cross = false;
+	union power_supply_propval ret = {0,};
+	static struct power_supply *psy;
+
+	if (!gbcl) {
+		pr_err("called before initialization\n");
+		return;
+	}
+
+	if (psy == NULL) {
+		psy = power_supply_get_by_name("battery");
+		if (psy == NULL)
+			return;
+	}
+
+	if (psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &ret))
+		return;
+	ibatt_ua = ret.intval;
+
+	if (psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &ret))
+		return;
+	vbatt_uv = ret.intval;
+
+	if (psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &ret))
+		return;
+	imax_ma = ret.intval/1000;
+
+	ibatt_ma = ibatt_ua/1000;
+	vbatt_mv = vbatt_uv/1000;
+
+	gbcl->bcl_ibat_ma = ibatt_ma;
+	gbcl->bcl_imax_ma = imax_ma;
+	gbcl->bcl_vbat_mv = vbatt_mv;
+
+	if (gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+		== BCL_IBAT_IMAX_THRESHOLD_ENABLED) {
+		imax_high_threshold =
+		imax_ma - gbcl->bcl_threshold_value_ma
+			[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH];
+		if (ibatt_ma >= imax_high_threshold)
+			threshold_cross = true;
+	}
+
+	if (gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+		== BCL_IBAT_IMAX_THRESHOLD_ENABLED) {
+		imax_low_threshold =
+		imax_ma - gbcl->bcl_threshold_value_ma
+			[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW];
+		if (ibatt_ma <= imax_low_threshold)
+			threshold_cross = true;
+	}
+
+	if (threshold_cross) {
+		sysfs_notify(&gbcl->dev->kobj,
+				NULL, "type");
+	}
+}
+
+/*
+ * BCL imax work
+ */
+static void bcl_imax_work(struct work_struct *work)
+{
+	struct bcl_context *bcl = container_of(work,
+			struct bcl_context, bcl_imax_work.work);
+
+	if (gbcl->bcl_mode == BCL_DEVICE_ENABLED) {
+		bcl_calculate_imax_trigger();
+		/* restart the delay work for caculating imax */
+		schedule_delayed_work(&bcl->bcl_imax_work,
+			round_jiffies_relative(msecs_to_jiffies
+				(bcl->bcl_poll_interval_msec)));
+	}
+}
+
+/*
+ * Set BCL mode
+ */
+static void bcl_mode_set(enum bcl_device_mode mode)
+{
+	if (!gbcl)
+		return;
+
+	if (gbcl->bcl_mode == mode)
+		return;
+
+	if (gbcl->bcl_mode == BCL_DEVICE_DISABLED
+		&& mode == BCL_DEVICE_ENABLED) {
+		gbcl->bcl_mode = mode;
+		bcl_imax_work(&(gbcl->bcl_imax_work.work));
+		return;
+	} else if (gbcl->bcl_mode == BCL_DEVICE_ENABLED
+		&& mode == BCL_DEVICE_DISABLED) {
+		gbcl->bcl_mode = mode;
+		cancel_delayed_work_sync(&(gbcl->bcl_imax_work));
+		return;
+	}
+
+	return;
+}
+
+#define show_bcl(name, variable, format) \
+static ssize_t \
+name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+	if (gbcl) \
+		return snprintf(buf, PAGE_SIZE, format, gbcl->variable); \
+	else \
+		return  -EPERM; \
+}
+
+show_bcl(type, bcl_type, "%s\n")
+show_bcl(ibat, bcl_ibat_ma, "%d\n")
+show_bcl(imax, bcl_imax_ma, "%d\n")
+show_bcl(vbat, bcl_vbat_mv, "%d\n")
+show_bcl(rbat, bcl_rbat, "%d\n")
+show_bcl(ocv, bcl_ocv_uv, "%d\n")
+show_bcl(poll_interval, bcl_poll_interval_msec, "%d\n")
+
+static ssize_t
+mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	if (!gbcl)
+		return -EPERM;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+		gbcl->bcl_mode == BCL_DEVICE_ENABLED ? "enabled"
+			: "disabled");
+}
+
+static ssize_t
+mode_store(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	if (!gbcl)
+		return -EPERM;
+
+	if (!strncmp(buf, "enabled", 7))
+		bcl_mode_set(BCL_DEVICE_ENABLED);
+	else if (!strncmp(buf, "disabled", 8))
+		bcl_mode_set(BCL_DEVICE_DISABLED);
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static ssize_t
+ibat_imax_low_threshold_mode_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	if (!gbcl)
+		return -EPERM;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+		gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+		== BCL_IBAT_IMAX_THRESHOLD_ENABLED ? "enabled" : "disabled");
+}
+
+static ssize_t
+ibat_imax_low_threshold_mode_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	if (!gbcl)
+		return -EPERM;
+
+	if (!strncmp(buf, "enabled", 7))
+		gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+			= BCL_IBAT_IMAX_THRESHOLD_ENABLED;
+	else if (!strncmp(buf, "disabled", 8))
+		gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+			= BCL_IBAT_IMAX_THRESHOLD_DISABLED;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static ssize_t
+ibat_imax_low_threshold_value_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	if (!gbcl)
+		return -EPERM;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+	gbcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]);
+}
+
+static ssize_t
+ibat_imax_low_threshold_value_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int value;
+
+	if (!gbcl)
+		return -EPERM;
+
+	if (!sscanf(buf, "%d", &value))
+		return -EINVAL;
+
+	if (value < 0)
+		return -EINVAL;
+
+	gbcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+			= value;
+
+	return count;
+}
+
+static ssize_t
+ibat_imax_high_threshold_mode_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	if (!gbcl)
+		return -EPERM;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+		gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+		== BCL_IBAT_IMAX_THRESHOLD_ENABLED ? "enabled" : "disabled");
+}
+
+static ssize_t
+ibat_imax_high_threshold_mode_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	if (!gbcl)
+		return -EPERM;
+
+	if (!strncmp(buf, "enabled", 7))
+		gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+		= BCL_IBAT_IMAX_THRESHOLD_ENABLED;
+	else if (!strncmp(buf, "disabled", 8))
+		gbcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+		= BCL_IBAT_IMAX_THRESHOLD_DISABLED;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static ssize_t
+ibat_imax_high_threshold_value_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	if (!gbcl)
+		return -EPERM;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+	gbcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]);
+}
+
+static ssize_t
+ibat_imax_high_threshold_value_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int value;
+
+	if (!gbcl)
+		return -EPERM;
+
+	if (!sscanf(buf, "%d", &value))
+		return -EINVAL;
+
+	if (value < 0)
+		return -EINVAL;
+
+	gbcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+		= value;
+
+	return count;
+}
+
+static ssize_t
+poll_interval_store(struct device *dev,
+			struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	int value;
+
+	if (!gbcl)
+		return -EPERM;
+
+	if (!sscanf(buf, "%d", &value))
+		return -EINVAL;
+
+	if (value < MIN_BCL_POLL_INTERVAL)
+		return -EINVAL;
+
+	gbcl->bcl_poll_interval_msec = value;
+
+	return count;
+}
+
+/*
+ * BCL device attributes
+ */
+static struct device_attribute bcl_dev_attr[] = {
+	__ATTR(type, 0444, type_show, NULL),
+	__ATTR(ibat, 0444, ibat_show, NULL),
+	__ATTR(vbat, 0444, vbat_show, NULL),
+	__ATTR(rbat, 0444, rbat_show, NULL),
+	__ATTR(ocv, 0444, ocv_show, NULL),
+	__ATTR(imax, 0444, imax_show, NULL),
+	__ATTR(mode, 0644, mode_show, mode_store),
+	__ATTR(poll_interval, 0644,
+		poll_interval_show, poll_interval_store),
+	__ATTR(ibat_imax_low_threshold_mode, 0644,
+		ibat_imax_low_threshold_mode_show,
+		ibat_imax_low_threshold_mode_store),
+	__ATTR(ibat_imax_high_threshold_mode, 0644,
+		ibat_imax_high_threshold_mode_show,
+		ibat_imax_high_threshold_mode_store),
+	__ATTR(ibat_imax_low_threshold_value, 0644,
+		ibat_imax_low_threshold_value_show,
+		ibat_imax_low_threshold_value_store),
+	__ATTR(ibat_imax_high_threshold_value, 0644,
+		ibat_imax_high_threshold_value_show,
+		ibat_imax_high_threshold_value_store)
+};
+
+static int create_bcl_sysfs(struct bcl_context *bcl)
+{
+	int result = 0;
+	int num_attr = sizeof(bcl_dev_attr)/sizeof(struct device_attribute);
+	int i;
+
+	for (i = 0; i < num_attr; i++) {
+		result = device_create_file(bcl->dev, &bcl_dev_attr[i]);
+		if (result < 0)
+			return result;
+	}
+
+	return 0;
+}
+
+static void remove_bcl_sysfs(struct bcl_context *bcl)
+{
+	int num_attr = sizeof(bcl_dev_attr)/sizeof(struct device_attribute);
+	int i;
+
+	for (i = 0; i < num_attr; i++)
+		device_remove_file(bcl->dev, &bcl_dev_attr[i]);
+
+	return;
+}
+
+static int __devinit bcl_probe(struct platform_device *pdev)
+{
+	struct bcl_context *bcl;
+	int ret = 0;
+
+	bcl = kzalloc(sizeof(struct bcl_context), GFP_KERNEL);
+
+	if (!bcl) {
+		pr_err("Cannot allocate bcl_context\n");
+		return -ENOMEM;
+	}
+
+	gbcl = bcl;
+
+	/* For BCL */
+	/* Init default BCL params */
+	bcl->dev = &pdev->dev;
+	bcl->bcl_mode = BCL_DEVICE_DISABLED;
+	bcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW]
+		= BCL_IBAT_IMAX_THRESHOLD_DISABLED;
+	bcl->bcl_threshold_mode[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH]
+		= BCL_IBAT_IMAX_THRESHOLD_DISABLED;
+	bcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_LOW] = 0;
+	bcl->bcl_threshold_value_ma[BCL_IBAT_IMAX_THRESHOLD_TYPE_HIGH] = 0;
+	snprintf(bcl->bcl_type, BCL_NAME_LENGTH, "%s", bcl_type);
+	bcl->bcl_poll_interval_msec = BCL_POLL_INTERVAL;
+	ret = create_bcl_sysfs(bcl);
+	if (ret < 0) {
+		pr_err("Cannot create bcl sysfs\n");
+		kfree(bcl);
+		return ret;
+	}
+	platform_set_drvdata(pdev, bcl);
+	INIT_DELAYED_WORK(&bcl->bcl_imax_work, bcl_imax_work);
+
+	return 0;
+}
+
+static int __devexit bcl_remove(struct platform_device *pdev)
+{
+	remove_bcl_sysfs(gbcl);
+	kfree(gbcl);
+	gbcl = NULL;
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver bcl_driver = {
+	.probe	= bcl_probe,
+	.remove	= __devexit_p(bcl_remove),
+	.driver	= {
+		.name	= BCL_DEV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init bcl_init(void)
+{
+	return platform_driver_register(&bcl_driver);
+}
+
+static void __exit bcl_exit(void)
+{
+	platform_driver_unregister(&bcl_driver);
+}
+
+late_initcall(bcl_init);
+module_exit(bcl_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("battery current limit driver");
+MODULE_ALIAS("platform:" BCL_DEV_NAME);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index d08a71d..28b641d 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -32,6 +32,7 @@
 #include <mach/msm_hsusb.h>
 
 #define CHG_BUCK_CLOCK_CTRL	0x14
+#define CHG_BUCK_CLOCK_CTRL_8038	0xD
 
 #define PBL_ACCESS1		0x04
 #define PBL_ACCESS2		0x05
@@ -820,7 +821,7 @@
 					 temp);
 }
 
-#define PM8921_CHG_TTRKL_MASK	0x1F
+#define PM8921_CHG_TTRKL_MASK	0x3F
 #define PM8921_CHG_TTRKL_MIN	1
 #define PM8921_CHG_TTRKL_MAX	64
 static int pm_chg_ttrkl_max_set(struct pm8921_chg_chip *chip, int minutes)
@@ -1357,6 +1358,7 @@
 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_ENERGY_FULL,
@@ -1418,6 +1420,36 @@
 	return percent_soc;
 }
 
+static int get_prop_batt_current_max(struct pm8921_chg_chip *chip)
+{
+	int rbatt, ibatt_ua, vbatt_uv, ocv_uv;
+	int imax_ma;
+	int rc;
+
+	rbatt = pm8921_bms_get_rbatt();
+
+	if (rbatt < 0) {
+		rc = -ENXIO;
+		return rc;
+	}
+
+	rc =  pm8921_bms_get_simultaneous_battery_voltage_and_current
+			(&ibatt_ua, &vbatt_uv);
+
+	if (rc)
+		return rc;
+
+	ocv_uv = vbatt_uv + ibatt_ua*rbatt/1000;
+
+	imax_ma = (ocv_uv - chip->min_voltage_mv*1000)/rbatt;
+
+	if (imax_ma < 0)
+		imax_ma = 0;
+
+	return imax_ma*1000;
+
+}
+
 static int get_prop_batt_current(struct pm8921_chg_chip *chip)
 {
 	int result_ua, rc;
@@ -1571,6 +1603,9 @@
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 		val->intval = get_prop_batt_current(chip);
 		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		val->intval = get_prop_batt_current_max(chip);
+		break;
 	case POWER_SUPPLY_PROP_TEMP:
 		val->intval = get_prop_batt_temp(chip);
 		break;
@@ -2498,7 +2533,8 @@
 		reg_loop = pm_chg_get_regulation_loop(chip);
 		pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
 		if ((reg_loop & VIN_ACTIVE_BIT) &&
-			(usb_ma > USB_WALL_THRESHOLD_MA)) {
+			(usb_ma > USB_WALL_THRESHOLD_MA)
+			&& !charging_disabled) {
 			decrease_usb_ma_value(&usb_ma);
 			usb_target_ma = usb_ma;
 			/* end AICL here */
@@ -2548,7 +2584,8 @@
 		unplug_ovp_fet_open(chip);
 	}
 
-	if (!(reg_loop & VIN_ACTIVE_BIT) && (active_path & USB_ACTIVE_BIT)) {
+	if (!(reg_loop & VIN_ACTIVE_BIT) && (active_path & USB_ACTIVE_BIT)
+		&& !charging_disabled) {
 		/* only increase iusb_max if vin loop not active */
 		if (usb_ma < usb_target_ma) {
 			increase_usb_ma_value(&usb_ma);
@@ -3642,7 +3679,13 @@
 		return rc;
 	}
 	/* switch to a 3.2Mhz for the buck */
-	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CLOCK_CTRL, 0x15);
+	if (pm8xxx_get_revision(chip->dev->parent) >= PM8XXX_REVISION_8038_1p0)
+		rc = pm8xxx_writeb(chip->dev->parent,
+			CHG_BUCK_CLOCK_CTRL_8038, 0x15);
+	else
+		rc = pm8xxx_writeb(chip->dev->parent,
+			CHG_BUCK_CLOCK_CTRL, 0x15);
+
 	if (rc) {
 		pr_err("Failed to switch buck clk rc=%d\n", rc);
 		return rc;
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index 44fdbc1..0549593 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -71,11 +71,18 @@
 	QPNP_REGULATOR_SUBTYPE_N300		= 0x03,
 	QPNP_REGULATOR_SUBTYPE_N600		= 0x04,
 	QPNP_REGULATOR_SUBTYPE_N1200		= 0x05,
+	QPNP_REGULATOR_SUBTYPE_N600_ST		= 0x06,
+	QPNP_REGULATOR_SUBTYPE_N1200_ST		= 0x07,
 	QPNP_REGULATOR_SUBTYPE_P50		= 0x08,
 	QPNP_REGULATOR_SUBTYPE_P150		= 0x09,
 	QPNP_REGULATOR_SUBTYPE_P300		= 0x0A,
 	QPNP_REGULATOR_SUBTYPE_P600		= 0x0B,
 	QPNP_REGULATOR_SUBTYPE_P1200		= 0x0C,
+	QPNP_REGULATOR_SUBTYPE_LV_P50		= 0x28,
+	QPNP_REGULATOR_SUBTYPE_LV_P150		= 0x29,
+	QPNP_REGULATOR_SUBTYPE_LV_P300		= 0x2A,
+	QPNP_REGULATOR_SUBTYPE_LV_P600		= 0x2B,
+	QPNP_REGULATOR_SUBTYPE_LV_P1200		= 0x2C,
 	QPNP_REGULATOR_SUBTYPE_LV100		= 0x01,
 	QPNP_REGULATOR_SUBTYPE_LV300		= 0x02,
 	QPNP_REGULATOR_SUBTYPE_MV300		= 0x08,
@@ -978,11 +985,20 @@
 	QPNP_VREG_MAP(LDO,   N1200,    0,   0, LDO,    ldo,    nldo2,   10000),
 	QPNP_VREG_MAP(LDO,   N600,     1, INF, LDO,    ldo,    nldo3,   10000),
 	QPNP_VREG_MAP(LDO,   N1200,    1, INF, LDO,    ldo,    nldo3,   10000),
+	QPNP_VREG_MAP(LDO,   N600_ST,  0,   0, LDO,    ldo,    nldo2,   10000),
+	QPNP_VREG_MAP(LDO,   N1200_ST, 0,   0, LDO,    ldo,    nldo2,   10000),
+	QPNP_VREG_MAP(LDO,   N600_ST,  1, INF, LDO,    ldo,    nldo3,   10000),
+	QPNP_VREG_MAP(LDO,   N1200_ST, 1, INF, LDO,    ldo,    nldo3,   10000),
 	QPNP_VREG_MAP(LDO,   P50,      0, INF, LDO,    ldo,    pldo,     5000),
 	QPNP_VREG_MAP(LDO,   P150,     0, INF, LDO,    ldo,    pldo,    10000),
 	QPNP_VREG_MAP(LDO,   P300,     0, INF, LDO,    ldo,    pldo,    10000),
 	QPNP_VREG_MAP(LDO,   P600,     0, INF, LDO,    ldo,    pldo,    10000),
 	QPNP_VREG_MAP(LDO,   P1200,    0, INF, LDO,    ldo,    pldo,    10000),
+	QPNP_VREG_MAP(LDO,   LV_P50,   0, INF, LDO,    ldo,    pldo,     5000),
+	QPNP_VREG_MAP(LDO,   LV_P150,  0, INF, LDO,    ldo,    pldo,    10000),
+	QPNP_VREG_MAP(LDO,   LV_P300,  0, INF, LDO,    ldo,    pldo,    10000),
+	QPNP_VREG_MAP(LDO,   LV_P600,  0, INF, LDO,    ldo,    pldo,    10000),
+	QPNP_VREG_MAP(LDO,   LV_P1200, 0, INF, LDO,    ldo,    pldo,    10000),
 	QPNP_VREG_MAP(VS,    LV100,    0, INF, VS,     vs,     none,        0),
 	QPNP_VREG_MAP(VS,    LV300,    0, INF, VS,     vs,     none,        0),
 	QPNP_VREG_MAP(VS,    MV300,    0, INF, VS,     vs,     none,        0),
diff --git a/drivers/slimbus/Makefile b/drivers/slimbus/Makefile
index 436822d..674f057 100644
--- a/drivers/slimbus/Makefile
+++ b/drivers/slimbus/Makefile
@@ -2,4 +2,4 @@
 # Makefile for kernel slimbus framework.
 #
 obj-$(CONFIG_SLIMBUS)			+= slimbus.o
-obj-$(CONFIG_SLIMBUS_MSM_CTRL)		+= slim-msm-ctrl.o
+obj-$(CONFIG_SLIMBUS_MSM_CTRL)		+= slim-msm.o slim-msm-ctrl.o
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index f87a06a..6cddf2d 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -16,7 +16,6 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
 #include <linux/slimbus/slimbus.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
@@ -26,61 +25,11 @@
 #include <linux/of_slimbus.h>
 #include <mach/sps.h>
 #include <mach/qdsp6v2/apr.h>
-
-/* Per spec.max 40 bytes per received message */
-#define SLIM_RX_MSGQ_BUF_LEN	40
-
-#define SLIM_USR_MC_GENERIC_ACK		0x25
-#define SLIM_USR_MC_MASTER_CAPABILITY	0x0
-#define SLIM_USR_MC_REPORT_SATELLITE	0x1
-#define SLIM_USR_MC_ADDR_QUERY		0xD
-#define SLIM_USR_MC_ADDR_REPLY		0xE
-#define SLIM_USR_MC_DEFINE_CHAN		0x20
-#define SLIM_USR_MC_DEF_ACT_CHAN	0x21
-#define SLIM_USR_MC_CHAN_CTRL		0x23
-#define SLIM_USR_MC_RECONFIG_NOW	0x24
-#define SLIM_USR_MC_REQ_BW		0x28
-#define SLIM_USR_MC_CONNECT_SRC		0x2C
-#define SLIM_USR_MC_CONNECT_SINK	0x2D
-#define SLIM_USR_MC_DISCONNECT_PORT	0x2E
-
-/* MSM Slimbus peripheral settings */
-#define MSM_SLIM_PERF_SUMM_THRESHOLD	0x8000
-#define MSM_SLIM_NCHANS			32
-#define MSM_SLIM_NPORTS			24
-#define MSM_SLIM_AUTOSUSPEND		MSEC_PER_SEC
-
-/*
- * Need enough descriptors to receive present messages from slaves
- * if received simultaneously. Present message needs 3 descriptors
- * and this size will ensure around 10 simultaneous reports.
- */
-#define MSM_SLIM_DESC_NUM		32
-
-#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
-		((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
+#include "slim-msm.h"
 
 #define MSM_SLIM_NAME	"msm_slim_ctrl"
 #define SLIM_ROOT_FREQ 24576000
 
-#define MSM_CONCUR_MSG	8
-#define SAT_CONCUR_MSG	8
-#define DEF_WATERMARK	(8 << 1)
-#define DEF_ALIGN	0
-#define DEF_PACK	(1 << 6)
-#define ENABLE_PORT	1
-
-#define DEF_BLKSZ	0
-#define DEF_TRANSZ	0
-
-#define SAT_MAGIC_LSB	0xD9
-#define SAT_MAGIC_MSB	0xC5
-#define SAT_MSG_VER	0x1
-#define SAT_MSG_PROT	0x1
-#define MSM_SAT_SUCCSS	0x20
-#define MSM_MAX_NSATS	2
-#define MSM_MAX_SATCH	32
-
 #define QC_MFGID_LSB	0x2
 #define QC_MFGID_MSB	0x17
 #define QC_CHIPID_SL	0x10
@@ -88,82 +37,8 @@
 #define QC_DEVID_SAT2	0x4
 #define QC_DEVID_PGD	0x5
 #define QC_MSM_DEVS	5
-
-#define PGD_THIS_EE(r, v) ((v) ? PGD_THIS_EE_V2(r) : PGD_THIS_EE_V1(r))
-#define PGD_PORT(r, p, v) ((v) ? PGD_PORT_V2(r, p) : PGD_PORT_V1(r, p))
-#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r))
-
-#define PGD_THIS_EE_V2(r) (dev->base + (r ## _V2) + (dev->ee * 0x1000))
-#define PGD_PORT_V2(r, p) (dev->base + (r ## _V2) + ((p) * 0x1000))
-#define CFG_PORT_V2(r) ((r ## _V2))
-/* Component registers */
-enum comp_reg_v2 {
-	COMP_CFG_V2		= 4,
-	COMP_TRUST_CFG_V2	= 0x3000,
-};
-
-/* Manager PGD registers */
-enum pgd_reg_v2 {
-	PGD_CFG_V2		= 0x800,
-	PGD_STAT_V2		= 0x804,
-	PGD_INT_EN_V2		= 0x810,
-	PGD_INT_STAT_V2		= 0x814,
-	PGD_INT_CLR_V2		= 0x818,
-	PGD_OWN_EEn_V2		= 0x300C,
-	PGD_PORT_INT_EN_EEn_V2	= 0x5000,
-	PGD_PORT_INT_ST_EEn_V2	= 0x5004,
-	PGD_PORT_INT_CL_EEn_V2	= 0x5008,
-	PGD_PORT_CFGn_V2	= 0x14000,
-	PGD_PORT_STATn_V2	= 0x14004,
-	PGD_PORT_PARAMn_V2	= 0x14008,
-	PGD_PORT_BLKn_V2	= 0x1400C,
-	PGD_PORT_TRANn_V2	= 0x14010,
-	PGD_PORT_MCHANn_V2	= 0x14014,
-	PGD_PORT_PSHPLLn_V2	= 0x14018,
-	PGD_PORT_PC_CFGn_V2	= 0x8000,
-	PGD_PORT_PC_VALn_V2	= 0x8004,
-	PGD_PORT_PC_VFR_TSn_V2	= 0x8008,
-	PGD_PORT_PC_VFR_STn_V2	= 0x800C,
-	PGD_PORT_PC_VFR_CLn_V2	= 0x8010,
-	PGD_IE_STAT_V2		= 0x820,
-	PGD_VE_STAT_V2		= 0x830,
-};
-
-#define PGD_THIS_EE_V1(r) (dev->base + (r ## _V1) + (dev->ee * 16))
-#define PGD_PORT_V1(r, p) (dev->base + (r ## _V1) + ((p) * 32))
-#define CFG_PORT_V1(r) ((r ## _V1))
-/* Component registers */
-enum comp_reg_v1 {
-	COMP_CFG_V1		= 0,
-	COMP_TRUST_CFG_V1	= 0x14,
-};
-
-/* Manager PGD registers */
-enum pgd_reg_v1 {
-	PGD_CFG_V1		= 0x1000,
-	PGD_STAT_V1		= 0x1004,
-	PGD_INT_EN_V1		= 0x1010,
-	PGD_INT_STAT_V1		= 0x1014,
-	PGD_INT_CLR_V1		= 0x1018,
-	PGD_OWN_EEn_V1		= 0x1020,
-	PGD_PORT_INT_EN_EEn_V1	= 0x1030,
-	PGD_PORT_INT_ST_EEn_V1	= 0x1034,
-	PGD_PORT_INT_CL_EEn_V1	= 0x1038,
-	PGD_PORT_CFGn_V1	= 0x1080,
-	PGD_PORT_STATn_V1	= 0x1084,
-	PGD_PORT_PARAMn_V1	= 0x1088,
-	PGD_PORT_BLKn_V1	= 0x108C,
-	PGD_PORT_TRANn_V1	= 0x1090,
-	PGD_PORT_MCHANn_V1	= 0x1094,
-	PGD_PORT_PSHPLLn_V1	= 0x1098,
-	PGD_PORT_PC_CFGn_V1	= 0x1600,
-	PGD_PORT_PC_VALn_V1	= 0x1604,
-	PGD_PORT_PC_VFR_TSn_V1	= 0x1608,
-	PGD_PORT_PC_VFR_STn_V1	= 0x160C,
-	PGD_PORT_PC_VFR_CLn_V1	= 0x1610,
-	PGD_IE_STAT_V1		= 0x1700,
-	PGD_VE_STAT_V1		= 0x1710,
-};
+#define INIT_MX_RETRIES 10
+#define DEF_RETRY_MS	10
 
 /* Manager registers */
 enum mgr_reg {
@@ -175,6 +50,7 @@
 	MGR_INT_CLR	= 0x218,
 	MGR_TX_MSG	= 0x230,
 	MGR_RX_MSG	= 0x270,
+	MGR_IE_STAT	= 0x2F0,
 	MGR_VE_STAT	= 0x300,
 };
 
@@ -214,12 +90,6 @@
 	INTF_VE_STAT	= 0x640,
 };
 
-enum rsc_grp {
-	EE_MGR_RSC_GRP	= 1 << 10,
-	EE_NGD_2	= 2 << 6,
-	EE_NGD_1	= 0,
-};
-
 enum mgr_intr {
 	MGR_INT_RECFG_DONE	= 1 << 24,
 	MGR_INT_TX_NACKED_2	= 1 << 25,
@@ -236,118 +106,8 @@
 	INTR_WAKE	= 19,
 };
 
-enum msm_ctrl_state {
-	MSM_CTRL_AWAKE,
-	MSM_CTRL_SLEEPING,
-	MSM_CTRL_ASLEEP,
-};
-
-struct msm_slim_sps_bam {
-	u32			hdl;
-	void __iomem		*base;
-	int			irq;
-};
-
-struct msm_slim_endp {
-	struct sps_pipe			*sps;
-	struct sps_connect		config;
-	struct sps_register_event	event;
-	struct sps_mem_buffer		buf;
-	struct completion		*xcomp;
-	bool				connected;
-};
-
-struct msm_slim_ctrl {
-	struct slim_controller  ctrl;
-	struct slim_framer	framer;
-	struct device		*dev;
-	void __iomem		*base;
-	struct resource		*slew_mem;
-	u32			curr_bw;
-	u8			msg_cnt;
-	u32			tx_buf[10];
-	u8			rx_msgs[MSM_CONCUR_MSG][SLIM_RX_MSGQ_BUF_LEN];
-	spinlock_t		rx_lock;
-	int			head;
-	int			tail;
-	int			irq;
-	int			err;
-	int			ee;
-	struct completion	*wr_comp;
-	struct msm_slim_sat	*satd[MSM_MAX_NSATS];
-	struct msm_slim_endp	pipes[7];
-	struct msm_slim_sps_bam	bam;
-	struct msm_slim_endp	rx_msgq;
-	struct completion	rx_msgq_notify;
-	struct task_struct	*rx_msgq_thread;
-	struct clk		*rclk;
-	struct clk		*hclk;
-	struct mutex		tx_lock;
-	u8			pgdla;
-	bool			use_rx_msgqs;
-	int			pipe_b;
-	struct completion	reconf;
-	bool			reconf_busy;
-	bool			chan_active;
-	enum msm_ctrl_state	state;
-	int			nsats;
-	u32			ver;
-};
-
-struct msm_sat_chan {
-	u8 chan;
-	u16 chanh;
-	int req_rem;
-	int req_def;
-	bool reconf;
-};
-
-struct msm_slim_sat {
-	struct slim_device	satcl;
-	struct msm_slim_ctrl	*dev;
-	struct workqueue_struct *wq;
-	struct work_struct	wd;
-	u8			sat_msgs[SAT_CONCUR_MSG][40];
-	struct msm_sat_chan	*satch;
-	u8			nsatch;
-	bool			sent_capability;
-	bool			pending_reconf;
-	bool			pending_capability;
-	int			shead;
-	int			stail;
-	spinlock_t lock;
-};
-
 static struct msm_slim_sat *msm_slim_alloc_sat(struct msm_slim_ctrl *dev);
 
-static int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len)
-{
-	spin_lock(&dev->rx_lock);
-	if ((dev->tail + 1) % MSM_CONCUR_MSG == dev->head) {
-		spin_unlock(&dev->rx_lock);
-		dev_err(dev->dev, "RX QUEUE full!");
-		return -EXFULL;
-	}
-	memcpy((u8 *)dev->rx_msgs[dev->tail], (u8 *)buf, len);
-	dev->tail = (dev->tail + 1) % MSM_CONCUR_MSG;
-	spin_unlock(&dev->rx_lock);
-	return 0;
-}
-
-static int msm_slim_rx_dequeue(struct msm_slim_ctrl *dev, u8 *buf)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&dev->rx_lock, flags);
-	if (dev->tail == dev->head) {
-		spin_unlock_irqrestore(&dev->rx_lock, flags);
-		return -ENODATA;
-	}
-	memcpy(buf, (u8 *)dev->rx_msgs[dev->head], 40);
-	dev->head = (dev->head + 1) % MSM_CONCUR_MSG;
-	spin_unlock_irqrestore(&dev->rx_lock, flags);
-	return 0;
-}
-
 static int msm_sat_enqueue(struct msm_slim_sat *sat, u32 *buf, u8 len)
 {
 	struct msm_slim_ctrl *dev = sat->dev;
@@ -396,36 +156,6 @@
 	return false;
 }
 
-static int msm_slim_get_ctrl(struct msm_slim_ctrl *dev)
-{
-#ifdef CONFIG_PM_RUNTIME
-	int ref = 0;
-	int ret = pm_runtime_get_sync(dev->dev);
-	if (ret >= 0) {
-		ref = atomic_read(&dev->dev->power.usage_count);
-		if (ref <= 0) {
-			dev_err(dev->dev, "reference count -ve:%d", ref);
-			ret = -ENODEV;
-		}
-	}
-	return ret;
-#else
-	return -ENODEV;
-#endif
-}
-static void msm_slim_put_ctrl(struct msm_slim_ctrl *dev)
-{
-#ifdef CONFIG_PM_RUNTIME
-	int ref;
-	pm_runtime_mark_last_busy(dev->dev);
-	ref = atomic_read(&dev->dev->power.usage_count);
-	if (ref <= 0)
-		dev_err(dev->dev, "reference count mismatch:%d", ref);
-	else
-		pm_runtime_put(dev->dev);
-#endif
-}
-
 static struct msm_slim_sat *addr_to_sat(struct msm_slim_ctrl *dev, u8 laddr)
 {
 	struct msm_slim_sat *sat = NULL;
@@ -449,8 +179,34 @@
 			writel_relaxed(MGR_INT_TX_MSG_SENT,
 					dev->base + MGR_INT_CLR);
 		else {
+			u32 mgr_stat = readl_relaxed(dev->base + MGR_STATUS);
+			u32 mgr_ie_stat = readl_relaxed(dev->base +
+						MGR_IE_STAT);
+			u32 frm_stat = readl_relaxed(dev->base + FRM_STAT);
+			u32 frm_cfg = readl_relaxed(dev->base + FRM_CFG);
+			u32 frm_intr_stat = readl_relaxed(dev->base +
+						FRM_INT_STAT);
+			u32 frm_ie_stat = readl_relaxed(dev->base +
+						FRM_IE_STAT);
+			u32 intf_stat = readl_relaxed(dev->base + INTF_STAT);
+			u32 intf_intr_stat = readl_relaxed(dev->base +
+						INTF_INT_STAT);
+			u32 intf_ie_stat = readl_relaxed(dev->base +
+						INTF_IE_STAT);
+
 			writel_relaxed(MGR_INT_TX_NACKED_2,
 					dev->base + MGR_INT_CLR);
+			pr_err("TX Nack MGR dump:int_stat:0x%x, mgr_stat:0x%x",
+					stat, mgr_stat);
+			pr_err("TX Nack MGR dump:ie_stat:0x%x", mgr_ie_stat);
+			pr_err("TX Nack FRM dump:int_stat:0x%x, frm_stat:0x%x",
+					frm_intr_stat, frm_stat);
+			pr_err("TX Nack FRM dump:frm_cfg:0x%x, ie_stat:0x%x",
+					frm_cfg, frm_ie_stat);
+			pr_err("TX Nack INTF dump:intr_st:0x%x, intf_stat:0x%x",
+					intf_intr_stat, intf_stat);
+			pr_err("TX Nack INTF dump:ie_stat:0x%x", intf_ie_stat);
+
 			dev->err = -EIO;
 		}
 		/*
@@ -593,159 +349,6 @@
 	return IRQ_HANDLED;
 }
 
-static int
-msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep)
-{
-	int ret;
-	struct sps_pipe *endpoint;
-	struct sps_connect *config = &ep->config;
-
-	/* Allocate the endpoint */
-	endpoint = sps_alloc_endpoint();
-	if (!endpoint) {
-		dev_err(dev->dev, "sps_alloc_endpoint failed\n");
-		return -ENOMEM;
-	}
-
-	/* Get default connection configuration for an endpoint */
-	ret = sps_get_config(endpoint, config);
-	if (ret) {
-		dev_err(dev->dev, "sps_get_config failed 0x%x\n", ret);
-		goto sps_config_failed;
-	}
-
-	ep->sps = endpoint;
-	return 0;
-
-sps_config_failed:
-	sps_free_endpoint(endpoint);
-	return ret;
-}
-
-static void
-msm_slim_free_endpoint(struct msm_slim_endp *ep)
-{
-	sps_free_endpoint(ep->sps);
-	ep->sps = NULL;
-}
-
-static int msm_slim_sps_mem_alloc(
-		struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem, u32 len)
-{
-	dma_addr_t phys;
-
-	mem->size = len;
-	mem->min_size = 0;
-	mem->base = dma_alloc_coherent(dev->dev, mem->size, &phys, GFP_KERNEL);
-
-	if (!mem->base) {
-		dev_err(dev->dev, "dma_alloc_coherent(%d) failed\n", len);
-		return -ENOMEM;
-	}
-
-	mem->phys_base = phys;
-	memset(mem->base, 0x00, mem->size);
-	return 0;
-}
-
-static void
-msm_slim_sps_mem_free(struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem)
-{
-	dma_free_coherent(dev->dev, mem->size, mem->base, mem->phys_base);
-	mem->size = 0;
-	mem->base = NULL;
-	mem->phys_base = 0;
-}
-
-static void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn)
-{
-	u32 set_cfg = DEF_WATERMARK | DEF_ALIGN | DEF_PACK | ENABLE_PORT;
-	u32 int_port = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
-					dev->ver));
-	writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pn, dev->ver));
-	writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pn, dev->ver));
-	writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pn, dev->ver));
-	writel_relaxed((int_port | 1 << pn) , PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
-								dev->ver));
-	/* Make sure that port registers are updated before returning */
-	mb();
-}
-
-static int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
-{
-	struct msm_slim_endp *endpoint = &dev->pipes[pn];
-	struct sps_connect *cfg = &endpoint->config;
-	u32 stat;
-	int ret = sps_get_config(dev->pipes[pn].sps, cfg);
-	if (ret) {
-		dev_err(dev->dev, "sps pipe-port get config error%x\n", ret);
-		return ret;
-	}
-	cfg->options = SPS_O_DESC_DONE | SPS_O_ERROR |
-				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
-
-	if (dev->pipes[pn].connected) {
-		ret = sps_set_config(dev->pipes[pn].sps, cfg);
-		if (ret) {
-			dev_err(dev->dev, "sps pipe-port set config erro:%x\n",
-						ret);
-			return ret;
-		}
-	}
-
-	stat = readl_relaxed(PGD_PORT(PGD_PORT_STATn, (pn + dev->pipe_b),
-					dev->ver));
-	if (dev->ctrl.ports[pn].flow == SLIM_SRC) {
-		cfg->destination = dev->bam.hdl;
-		cfg->source = SPS_DEV_HANDLE_MEM;
-		cfg->dest_pipe_index = ((stat & (0xFF << 4)) >> 4);
-		cfg->src_pipe_index = 0;
-		dev_dbg(dev->dev, "flow src:pipe num:%d",
-					cfg->dest_pipe_index);
-		cfg->mode = SPS_MODE_DEST;
-	} else {
-		cfg->source = dev->bam.hdl;
-		cfg->destination = SPS_DEV_HANDLE_MEM;
-		cfg->src_pipe_index = ((stat & (0xFF << 4)) >> 4);
-		cfg->dest_pipe_index = 0;
-		dev_dbg(dev->dev, "flow dest:pipe num:%d",
-					cfg->src_pipe_index);
-		cfg->mode = SPS_MODE_SRC;
-	}
-	/* Space for desciptor FIFOs */
-	cfg->desc.size = MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec);
-	cfg->config = SPS_CONFIG_DEFAULT;
-	ret = sps_connect(dev->pipes[pn].sps, cfg);
-	if (!ret) {
-		dev->pipes[pn].connected = true;
-		msm_hw_set_port(dev, pn + dev->pipe_b);
-	}
-	return ret;
-}
-
-static u32 *msm_get_msg_buf(struct slim_controller *ctrl, int len)
-{
-	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
-	/*
-	 * Currently we block a transaction until the current one completes.
-	 * In case we need multiple transactions, use message Q
-	 */
-	return dev->tx_buf;
-}
-
-static int msm_send_msg_buf(struct slim_controller *ctrl, u32 *buf, u8 len)
-{
-	int i;
-	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
-	for (i = 0; i < (len + 3) >> 2; i++) {
-		dev_dbg(dev->dev, "TX data:0x%x\n", buf[i]);
-		writel_relaxed(buf[i], dev->base + MGR_TX_MSG + (i * 4));
-	}
-	/* Guarantee that message is sent before returning */
-	mb();
-	return 0;
-}
-
 static int msm_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
 {
 	DECLARE_COMPLETION_ONSTACK(done);
@@ -791,7 +394,7 @@
 		}
 	}
 	txn->rl--;
-	pbuf = msm_get_msg_buf(ctrl, txn->rl);
+	pbuf = msm_get_msg_buf(dev, txn->rl);
 	dev->wr_comp = NULL;
 	dev->err = 0;
 
@@ -861,9 +464,10 @@
 		mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION)
 		dev->reconf_busy = true;
 	dev->wr_comp = &done;
-	msm_send_msg_buf(ctrl, pbuf, txn->rl);
+	msm_send_msg_buf(dev, pbuf, txn->rl, MGR_TX_MSG);
 	timeout = wait_for_completion_timeout(&done, HZ);
-
+	if (!timeout)
+		dev->wr_comp = NULL;
 	if (mc == SLIM_MSG_MC_RECONFIGURE_NOW) {
 		if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
 					SLIM_MSG_CLK_PAUSE_SEQ_FLG)) &&
@@ -903,15 +507,30 @@
 	return timeout ? dev->err : -ETIMEDOUT;
 }
 
+static void msm_slim_wait_retry(struct msm_slim_ctrl *dev)
+{
+	int msec_per_frm = 0;
+	int sfr_per_sec;
+	/* Wait for 1 superframe, or default time and then retry */
+	sfr_per_sec = dev->framer.superfreq /
+			(1 << (SLIM_MAX_CLK_GEAR - dev->ctrl.clkgear));
+	if (sfr_per_sec)
+		msec_per_frm = MSEC_PER_SEC / sfr_per_sec;
+	if (msec_per_frm < DEF_RETRY_MS)
+		msec_per_frm = DEF_RETRY_MS;
+	msleep(msec_per_frm);
+}
 static int msm_set_laddr(struct slim_controller *ctrl, const u8 *ea,
 				u8 elen, u8 laddr)
 {
 	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
-	DECLARE_COMPLETION_ONSTACK(done);
-	int timeout;
+	struct completion done;
+	int timeout, ret, retries = 0;
 	u32 *buf;
+retry_laddr:
+	init_completion(&done);
 	mutex_lock(&dev->tx_lock);
-	buf = msm_get_msg_buf(ctrl, 9);
+	buf = msm_get_msg_buf(dev, 9);
 	buf[0] = SLIM_MSG_ASM_FIRST_WORD(9, SLIM_MSG_MT_CORE,
 					SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS,
 					SLIM_MSG_DEST_LOGICALADDR,
@@ -920,10 +539,27 @@
 	buf[2] = laddr;
 
 	dev->wr_comp = &done;
-	msm_send_msg_buf(ctrl, buf, 9);
+	ret = msm_send_msg_buf(dev, buf, 9, MGR_TX_MSG);
 	timeout = wait_for_completion_timeout(&done, HZ);
+	if (!timeout)
+		dev->err = -ETIMEDOUT;
+	if (dev->err) {
+		ret = dev->err;
+		dev->err = 0;
+		dev->wr_comp = NULL;
+	}
 	mutex_unlock(&dev->tx_lock);
-	return timeout ? dev->err : -ETIMEDOUT;
+	if (ret) {
+		pr_err("set LADDR:0x%x failed:ret:%d, retrying", laddr, ret);
+		if (retries < INIT_MX_RETRIES) {
+			msm_slim_wait_retry(dev);
+			retries++;
+			goto retry_laddr;
+		} else {
+			pr_err("set LADDR failed after retrying:ret:%d", ret);
+		}
+	}
+	return ret;
 }
 
 static int msm_clk_pause_wakeup(struct slim_controller *ctrl)
@@ -947,74 +583,6 @@
 	return 0;
 }
 
-static int msm_config_port(struct slim_controller *ctrl, u8 pn)
-{
-	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
-	struct msm_slim_endp *endpoint;
-	int ret = 0;
-	if (ctrl->ports[pn].req == SLIM_REQ_HALF_DUP ||
-		ctrl->ports[pn].req == SLIM_REQ_MULTI_CH)
-		return -EPROTONOSUPPORT;
-	if (pn >= (MSM_SLIM_NPORTS - dev->pipe_b))
-		return -ENODEV;
-
-	endpoint = &dev->pipes[pn];
-	ret = msm_slim_init_endpoint(dev, endpoint);
-	dev_dbg(dev->dev, "sps register bam error code:%x\n", ret);
-	return ret;
-}
-
-static enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr,
-				u8 pn, u8 **done_buf, u32 *done_len)
-{
-	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctr);
-	struct sps_iovec sio;
-	int ret;
-	if (done_len)
-		*done_len = 0;
-	if (done_buf)
-		*done_buf = NULL;
-	if (!dev->pipes[pn].connected)
-		return SLIM_P_DISCONNECT;
-	ret = sps_get_iovec(dev->pipes[pn].sps, &sio);
-	if (!ret) {
-		if (done_len)
-			*done_len = sio.size;
-		if (done_buf)
-			*done_buf = (u8 *)sio.addr;
-	}
-	dev_dbg(dev->dev, "get iovec returned %d\n", ret);
-	return SLIM_P_INPROGRESS;
-}
-
-static int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, u8 *iobuf,
-			u32 len, struct completion *comp)
-{
-	struct sps_register_event sreg;
-	int ret;
-	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
-	if (pn >= 7)
-		return -ENODEV;
-
-
-	ctrl->ports[pn].xcomp = comp;
-	sreg.options = (SPS_EVENT_DESC_DONE|SPS_EVENT_ERROR);
-	sreg.mode = SPS_TRIGGER_WAIT;
-	sreg.xfer_done = comp;
-	sreg.callback = NULL;
-	sreg.user = &ctrl->ports[pn];
-	ret = sps_register_event(dev->pipes[pn].sps, &sreg);
-	if (ret) {
-		dev_dbg(dev->dev, "sps register event error:%x\n", ret);
-		return ret;
-	}
-	ret = sps_transfer_one(dev->pipes[pn].sps, (u32)iobuf, len, NULL,
-				SPS_IOVEC_FLAG_INT);
-	dev_dbg(dev->dev, "sps submit xfer error code:%x\n", ret);
-
-	return ret;
-}
-
 static int msm_sat_define_ch(struct msm_slim_sat *sat, u8 *buf, u8 len, u8 mc)
 {
 	struct msm_slim_ctrl *dev = sat->dev;
@@ -1154,6 +722,8 @@
 				msm_sat_enqueue(sat, (u32 *)buf, len);
 				queue_work(sat->wq, &sat->wd);
 			}
+			if (ret)
+				pr_err("assign laddr failed, error:%d", ret);
 		} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
 				mc == SLIM_MSG_MC_REPLY_VALUE) {
 			u8 tid = buf[3];
@@ -1196,7 +766,7 @@
 		bool gen_ack = false;
 		u8 tid;
 		u8 wbuf[8];
-		int i;
+		int i, retries = 0;
 		txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
 		txn.dt = SLIM_MSG_DEST_LOGICALADDR;
 		txn.ec = 0;
@@ -1209,7 +779,6 @@
 
 		if (mt == SLIM_MSG_MT_CORE &&
 			mc == SLIM_MSG_MC_REPORT_PRESENT) {
-			u8 laddr;
 			u8 e_addr[6];
 			for (i = 0; i < 6; i++)
 				e_addr[i] = buf[7-i];
@@ -1219,8 +788,6 @@
 				if (satv >= 0)
 					sat->pending_capability = true;
 			}
-			slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
-			sat->satcl.laddr = laddr;
 			/*
 			 * Since capability message is already sent, present
 			 * message will indicate subsystem hosting this
@@ -1232,7 +799,7 @@
 				for (i = 0; i < sat->nsatch; i++) {
 					if (sat->satch[i].reconf) {
 						pr_err("SSR, sat:%d, rm ch:%d",
-							laddr,
+							sat->satcl.laddr,
 							sat->satch[i].chan);
 						slim_control_ch(&sat->satcl,
 							sat->satch[i].chanh,
@@ -1284,8 +851,21 @@
 			wbuf[3] = SAT_MSG_PROT;
 			txn.wbuf = wbuf;
 			txn.len = 4;
-			sat->sent_capability = true;
-			msm_xfer_msg(&dev->ctrl, &txn);
+			ret = msm_xfer_msg(&dev->ctrl, &txn);
+			if (ret) {
+				pr_err("capability for:0x%x fail:%d, retry:%d",
+						sat->satcl.laddr, ret, retries);
+				if (retries < INIT_MX_RETRIES) {
+					msm_slim_wait_retry(dev);
+					retries++;
+					goto send_capability;
+				} else {
+					pr_err("failed after all retries:%d",
+							ret);
+				}
+			} else {
+				sat->sent_capability = true;
+			}
 			break;
 		case SLIM_USR_MC_ADDR_QUERY:
 			memcpy(&wbuf[1], &buf[4], 6);
@@ -1326,7 +906,7 @@
 			ret = slim_reconfigure_now(&sat->satcl);
 			for (i = 0; i < sat->nsatch; i++) {
 				struct msm_sat_chan *sch = &sat->satch[i];
-				if (sch->req_rem) {
+				if (sch->req_rem && sch->reconf) {
 					if (!ret) {
 						slim_dealloc_ch(&sat->satcl,
 								sch->chanh);
@@ -1447,95 +1027,6 @@
 	return sat;
 }
 
-static void
-msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
-{
-	u32 *buf = ev->data.transfer.user;
-	struct sps_iovec *iovec = &ev->data.transfer.iovec;
-
-	/*
-	 * Note the virtual address needs to be offset by the same index
-	 * as the physical address or just pass in the actual virtual address
-	 * if the sps_mem_buffer is not needed.  Note that if completion is
-	 * used, the virtual address won't be available and will need to be
-	 * calculated based on the offset of the physical address
-	 */
-	if (ev->event_id == SPS_EVENT_DESC_DONE) {
-
-		pr_debug("buf = 0x%p, data = 0x%x\n", buf, *buf);
-
-		pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
-			iovec->addr, iovec->size, iovec->flags);
-
-	} else {
-		dev_err(dev->dev, "%s: unknown event %d\n",
-					__func__, ev->event_id);
-	}
-}
-
-static void msm_slim_rx_msgq_cb(struct sps_event_notify *notify)
-{
-	struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)notify->user;
-	msm_slim_rx_msgq_event(dev, notify);
-}
-
-/* Queue up Rx message buffer */
-static inline int
-msm_slim_post_rx_msgq(struct msm_slim_ctrl *dev, int ix)
-{
-	int ret;
-	u32 flags = SPS_IOVEC_FLAG_INT;
-	struct msm_slim_endp *endpoint = &dev->rx_msgq;
-	struct sps_mem_buffer *mem = &endpoint->buf;
-	struct sps_pipe *pipe = endpoint->sps;
-
-	/* Rx message queue buffers are 4 bytes in length */
-	u8 *virt_addr = mem->base + (4 * ix);
-	u32 phys_addr = mem->phys_base + (4 * ix);
-
-	pr_debug("index:%d, phys:0x%x, virt:0x%p\n", ix, phys_addr, virt_addr);
-
-	ret = sps_transfer_one(pipe, phys_addr, 4, virt_addr, flags);
-	if (ret)
-		dev_err(dev->dev, "transfer_one() failed 0x%x, %d\n", ret, ix);
-
-	return ret;
-}
-
-static inline int
-msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset)
-{
-	struct msm_slim_endp *endpoint = &dev->rx_msgq;
-	struct sps_mem_buffer *mem = &endpoint->buf;
-	struct sps_pipe *pipe = endpoint->sps;
-	struct sps_iovec iovec;
-	int index;
-	int ret;
-
-	ret = sps_get_iovec(pipe, &iovec);
-	if (ret) {
-		dev_err(dev->dev, "sps_get_iovec() failed 0x%x\n", ret);
-		goto err_exit;
-	}
-
-	pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
-		iovec.addr, iovec.size, iovec.flags);
-	BUG_ON(iovec.addr < mem->phys_base);
-	BUG_ON(iovec.addr >= mem->phys_base + mem->size);
-
-	/* Calculate buffer index */
-	index = (iovec.addr - mem->phys_base) / 4;
-	*(data + offset) = *((u32 *)mem->base + index);
-
-	pr_debug("buf = 0x%p, data = 0x%x\n", (u32 *)mem->base + index, *data);
-
-	/* Add buffer back to the queue */
-	(void)msm_slim_post_rx_msgq(dev, index);
-
-err_exit:
-	return ret;
-}
-
 static int msm_slim_rx_msgq_thread(void *data)
 {
 	struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
@@ -1600,219 +1091,6 @@
 	return 0;
 }
 
-static int __devinit msm_slim_init_rx_msgq(struct msm_slim_ctrl *dev)
-{
-	int i, ret;
-	u32 pipe_offset;
-	struct msm_slim_endp *endpoint = &dev->rx_msgq;
-	struct sps_connect *config = &endpoint->config;
-	struct sps_mem_buffer *descr = &config->desc;
-	struct sps_mem_buffer *mem = &endpoint->buf;
-	struct completion *notify = &dev->rx_msgq_notify;
-
-	struct sps_register_event sps_error_event; /* SPS_ERROR */
-	struct sps_register_event sps_descr_event; /* DESCR_DONE */
-
-	init_completion(notify);
-	if (!dev->use_rx_msgqs)
-		goto rx_thread_create;
-
-	/* Allocate the endpoint */
-	ret = msm_slim_init_endpoint(dev, endpoint);
-	if (ret) {
-		dev_err(dev->dev, "init_endpoint failed 0x%x\n", ret);
-		goto sps_init_endpoint_failed;
-	}
-
-	/* Get the pipe indices for the message queues */
-	pipe_offset = (readl_relaxed(dev->base + MGR_STATUS) & 0xfc) >> 2;
-	dev_dbg(dev->dev, "Message queue pipe offset %d\n", pipe_offset);
-
-	config->mode = SPS_MODE_SRC;
-	config->source = dev->bam.hdl;
-	config->destination = SPS_DEV_HANDLE_MEM;
-	config->src_pipe_index = pipe_offset;
-	config->options = SPS_O_DESC_DONE | SPS_O_ERROR |
-				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
-
-	/* Allocate memory for the FIFO descriptors */
-	ret = msm_slim_sps_mem_alloc(dev, descr,
-				MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec));
-	if (ret) {
-		dev_err(dev->dev, "unable to allocate SPS descriptors\n");
-		goto alloc_descr_failed;
-	}
-
-	ret = sps_connect(endpoint->sps, config);
-	if (ret) {
-		dev_err(dev->dev, "sps_connect failed 0x%x\n", ret);
-		goto sps_connect_failed;
-	}
-
-	/* Register completion for DESC_DONE */
-	init_completion(notify);
-	memset(&sps_descr_event, 0x00, sizeof(sps_descr_event));
-
-	sps_descr_event.mode = SPS_TRIGGER_CALLBACK;
-	sps_descr_event.options = SPS_O_DESC_DONE;
-	sps_descr_event.user = (void *)dev;
-	sps_descr_event.xfer_done = notify;
-
-	ret = sps_register_event(endpoint->sps, &sps_descr_event);
-	if (ret) {
-		dev_err(dev->dev, "sps_connect() failed 0x%x\n", ret);
-		goto sps_reg_event_failed;
-	}
-
-	/* Register callback for errors */
-	memset(&sps_error_event, 0x00, sizeof(sps_error_event));
-	sps_error_event.mode = SPS_TRIGGER_CALLBACK;
-	sps_error_event.options = SPS_O_ERROR;
-	sps_error_event.user = (void *)dev;
-	sps_error_event.callback = msm_slim_rx_msgq_cb;
-
-	ret = sps_register_event(endpoint->sps, &sps_error_event);
-	if (ret) {
-		dev_err(dev->dev, "sps_connect() failed 0x%x\n", ret);
-		goto sps_reg_event_failed;
-	}
-
-	/* Allocate memory for the message buffer(s), N descrs, 4-byte mesg */
-	ret = msm_slim_sps_mem_alloc(dev, mem, MSM_SLIM_DESC_NUM * 4);
-	if (ret) {
-		dev_err(dev->dev, "dma_alloc_coherent failed\n");
-		goto alloc_buffer_failed;
-	}
-
-	/*
-	 * Call transfer_one for each 4-byte buffer
-	 * Use (buf->size/4) - 1 for the number of buffer to post
-	 */
-
-	/* Setup the transfer */
-	for (i = 0; i < (MSM_SLIM_DESC_NUM - 1); i++) {
-		ret = msm_slim_post_rx_msgq(dev, i);
-		if (ret) {
-			dev_err(dev->dev, "post_rx_msgq() failed 0x%x\n", ret);
-			goto sps_transfer_failed;
-		}
-	}
-
-rx_thread_create:
-	/* Fire up the Rx message queue thread */
-	dev->rx_msgq_thread = kthread_run(msm_slim_rx_msgq_thread, dev,
-					MSM_SLIM_NAME "_rx_msgq_thread");
-	if (!dev->rx_msgq_thread) {
-		dev_err(dev->dev, "Failed to start Rx message queue thread\n");
-		/* Tear-down BAMs or return? */
-		if (!dev->use_rx_msgqs)
-			return -EIO;
-		else
-			ret = -EIO;
-	} else
-		return 0;
-
-sps_transfer_failed:
-	msm_slim_sps_mem_free(dev, mem);
-alloc_buffer_failed:
-	memset(&sps_error_event, 0x00, sizeof(sps_error_event));
-	sps_register_event(endpoint->sps, &sps_error_event);
-sps_reg_event_failed:
-	sps_disconnect(endpoint->sps);
-sps_connect_failed:
-	msm_slim_sps_mem_free(dev, descr);
-alloc_descr_failed:
-	msm_slim_free_endpoint(endpoint);
-sps_init_endpoint_failed:
-	dev->use_rx_msgqs = 0;
-	return ret;
-}
-
-/* Registers BAM h/w resource with SPS driver and initializes msgq endpoints */
-static int __devinit
-msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem)
-{
-	int i, ret;
-	u32 bam_handle;
-	struct sps_bam_props bam_props = {0};
-
-	static struct sps_bam_sec_config_props sec_props = {
-		.ees = {
-			[0] = {		/* LPASS */
-				.vmid = 0,
-				.pipe_mask = 0xFFFF98,
-			},
-			[1] = {		/* Krait Apps */
-				.vmid = 1,
-				.pipe_mask = 0x3F000007,
-			},
-			[2] = {		/* Modem */
-				.vmid = 2,
-				.pipe_mask = 0x00000060,
-			},
-		},
-	};
-
-	bam_props.ee = dev->ee;
-	bam_props.virt_addr = dev->bam.base;
-	bam_props.phys_addr = bam_mem->start;
-	bam_props.irq = dev->bam.irq;
-	bam_props.manage = SPS_BAM_MGR_LOCAL;
-	bam_props.summing_threshold = MSM_SLIM_PERF_SUMM_THRESHOLD;
-
-	bam_props.sec_config = SPS_BAM_SEC_DO_CONFIG;
-	bam_props.p_sec_config_props = &sec_props;
-
-	bam_props.options = SPS_O_DESC_DONE | SPS_O_ERROR |
-				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
-
-	/* First 7 bits are for message Qs */
-	for (i = 7; i < 32; i++) {
-		/* Check what pipes are owned by Apps. */
-		if ((sec_props.ees[dev->ee].pipe_mask >> i) & 0x1)
-			break;
-	}
-	dev->pipe_b = i - 7;
-
-	/* Register the BAM device with the SPS driver */
-	ret = sps_register_bam_device(&bam_props, &bam_handle);
-	if (ret) {
-		dev_err(dev->dev, "disabling BAM: reg-bam failed 0x%x\n", ret);
-		dev->use_rx_msgqs = 0;
-		goto init_rx_msgq;
-	}
-	dev->bam.hdl = bam_handle;
-	dev_dbg(dev->dev, "SLIM BAM registered, handle = 0x%x\n", bam_handle);
-
-init_rx_msgq:
-	ret = msm_slim_init_rx_msgq(dev);
-	if (ret)
-		dev_err(dev->dev, "msm_slim_init_rx_msgq failed 0x%x\n", ret);
-	if (ret && bam_handle) {
-		sps_deregister_bam_device(bam_handle);
-		dev->bam.hdl = 0L;
-	}
-	return ret;
-}
-
-static void msm_slim_sps_exit(struct msm_slim_ctrl *dev)
-{
-	if (dev->use_rx_msgqs) {
-		struct msm_slim_endp *endpoint = &dev->rx_msgq;
-		struct sps_connect *config = &endpoint->config;
-		struct sps_mem_buffer *descr = &config->desc;
-		struct sps_mem_buffer *mem = &endpoint->buf;
-		struct sps_register_event sps_event;
-		memset(&sps_event, 0x00, sizeof(sps_event));
-		msm_slim_sps_mem_free(dev, mem);
-		sps_register_event(endpoint->sps, &sps_event);
-		sps_disconnect(endpoint->sps);
-		msm_slim_sps_mem_free(dev, descr);
-		msm_slim_free_endpoint(endpoint);
-		sps_deregister_bam_device(dev->bam.hdl);
-	}
-}
-
 static void msm_slim_prg_slew(struct platform_device *pdev,
 				struct msm_slim_ctrl *dev)
 {
@@ -1978,12 +1256,20 @@
 	else
 		clk_prepare_enable(dev->hclk);
 
-	ret = msm_slim_sps_init(dev, bam_mem);
+	ret = msm_slim_sps_init(dev, bam_mem, MGR_STATUS);
 	if (ret != 0) {
 		dev_err(dev->dev, "error SPS init\n");
 		goto err_sps_init_failed;
 	}
 
+	/* Fire up the Rx message queue thread */
+	dev->rx_msgq_thread = kthread_run(msm_slim_rx_msgq_thread, dev,
+					MSM_SLIM_NAME "_rx_msgq_thread");
+	if (IS_ERR(dev->rx_msgq_thread)) {
+		ret = PTR_ERR(dev->rx_msgq_thread);
+		dev_err(dev->dev, "Failed to start Rx message queue thread\n");
+		goto err_thread_create_failed;
+	}
 
 	dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
 	dev->framer.superfreq =
@@ -2109,6 +1395,8 @@
 err_clk_get_failed:
 	kfree(dev->satd);
 err_request_irq_failed:
+	kthread_stop(dev->rx_msgq_thread);
+err_thread_create_failed:
 	msm_slim_sps_exit(dev);
 err_sps_init_failed:
 	if (dev->hclk) {
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
new file mode 100644
index 0000000..8a1ea84
--- /dev/null
+++ b/drivers/slimbus/slim-msm.c
@@ -0,0 +1,578 @@
+/* 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 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/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/slimbus/slimbus.h>
+#include <mach/sps.h>
+#include "slim-msm.h"
+
+int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len)
+{
+	spin_lock(&dev->rx_lock);
+	if ((dev->tail + 1) % MSM_CONCUR_MSG == dev->head) {
+		spin_unlock(&dev->rx_lock);
+		dev_err(dev->dev, "RX QUEUE full!");
+		return -EXFULL;
+	}
+	memcpy((u8 *)dev->rx_msgs[dev->tail], (u8 *)buf, len);
+	dev->tail = (dev->tail + 1) % MSM_CONCUR_MSG;
+	spin_unlock(&dev->rx_lock);
+	return 0;
+}
+
+int msm_slim_rx_dequeue(struct msm_slim_ctrl *dev, u8 *buf)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dev->rx_lock, flags);
+	if (dev->tail == dev->head) {
+		spin_unlock_irqrestore(&dev->rx_lock, flags);
+		return -ENODATA;
+	}
+	memcpy(buf, (u8 *)dev->rx_msgs[dev->head], 40);
+	dev->head = (dev->head + 1) % MSM_CONCUR_MSG;
+	spin_unlock_irqrestore(&dev->rx_lock, flags);
+	return 0;
+}
+
+int msm_slim_get_ctrl(struct msm_slim_ctrl *dev)
+{
+#ifdef CONFIG_PM_RUNTIME
+	int ref = 0;
+	int ret = pm_runtime_get_sync(dev->dev);
+	if (ret >= 0) {
+		ref = atomic_read(&dev->dev->power.usage_count);
+		if (ref <= 0) {
+			dev_err(dev->dev, "reference count -ve:%d", ref);
+			ret = -ENODEV;
+		}
+	}
+	return ret;
+#else
+	return -ENODEV;
+#endif
+}
+void msm_slim_put_ctrl(struct msm_slim_ctrl *dev)
+{
+#ifdef CONFIG_PM_RUNTIME
+	int ref;
+	pm_runtime_mark_last_busy(dev->dev);
+	ref = atomic_read(&dev->dev->power.usage_count);
+	if (ref <= 0)
+		dev_err(dev->dev, "reference count mismatch:%d", ref);
+	else
+		pm_runtime_put(dev->dev);
+#endif
+}
+
+int msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep)
+{
+	int ret;
+	struct sps_pipe *endpoint;
+	struct sps_connect *config = &ep->config;
+
+	/* Allocate the endpoint */
+	endpoint = sps_alloc_endpoint();
+	if (!endpoint) {
+		dev_err(dev->dev, "sps_alloc_endpoint failed\n");
+		return -ENOMEM;
+	}
+
+	/* Get default connection configuration for an endpoint */
+	ret = sps_get_config(endpoint, config);
+	if (ret) {
+		dev_err(dev->dev, "sps_get_config failed 0x%x\n", ret);
+		goto sps_config_failed;
+	}
+
+	ep->sps = endpoint;
+	return 0;
+
+sps_config_failed:
+	sps_free_endpoint(endpoint);
+	return ret;
+}
+
+void msm_slim_free_endpoint(struct msm_slim_endp *ep)
+{
+	sps_free_endpoint(ep->sps);
+	ep->sps = NULL;
+}
+
+int msm_slim_sps_mem_alloc(
+		struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem, u32 len)
+{
+	dma_addr_t phys;
+
+	mem->size = len;
+	mem->min_size = 0;
+	mem->base = dma_alloc_coherent(dev->dev, mem->size, &phys, GFP_KERNEL);
+
+	if (!mem->base) {
+		dev_err(dev->dev, "dma_alloc_coherent(%d) failed\n", len);
+		return -ENOMEM;
+	}
+
+	mem->phys_base = phys;
+	memset(mem->base, 0x00, mem->size);
+	return 0;
+}
+
+void
+msm_slim_sps_mem_free(struct msm_slim_ctrl *dev, struct sps_mem_buffer *mem)
+{
+	dma_free_coherent(dev->dev, mem->size, mem->base, mem->phys_base);
+	mem->size = 0;
+	mem->base = NULL;
+	mem->phys_base = 0;
+}
+
+void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn)
+{
+	u32 set_cfg = DEF_WATERMARK | DEF_ALIGN | DEF_PACK | ENABLE_PORT;
+	u32 int_port = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
+					dev->ver));
+	writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pn, dev->ver));
+	writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pn, dev->ver));
+	writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pn, dev->ver));
+	writel_relaxed((int_port | 1 << pn) , PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
+								dev->ver));
+	/* Make sure that port registers are updated before returning */
+	mb();
+}
+
+int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn)
+{
+	struct msm_slim_endp *endpoint = &dev->pipes[pn];
+	struct sps_connect *cfg = &endpoint->config;
+	u32 stat;
+	int ret = sps_get_config(dev->pipes[pn].sps, cfg);
+	if (ret) {
+		dev_err(dev->dev, "sps pipe-port get config error%x\n", ret);
+		return ret;
+	}
+	cfg->options = SPS_O_DESC_DONE | SPS_O_ERROR |
+				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+
+	if (dev->pipes[pn].connected) {
+		ret = sps_set_config(dev->pipes[pn].sps, cfg);
+		if (ret) {
+			dev_err(dev->dev, "sps pipe-port set config erro:%x\n",
+						ret);
+			return ret;
+		}
+	}
+
+	stat = readl_relaxed(PGD_PORT(PGD_PORT_STATn, (pn + dev->pipe_b),
+					dev->ver));
+	if (dev->ctrl.ports[pn].flow == SLIM_SRC) {
+		cfg->destination = dev->bam.hdl;
+		cfg->source = SPS_DEV_HANDLE_MEM;
+		cfg->dest_pipe_index = ((stat & (0xFF << 4)) >> 4);
+		cfg->src_pipe_index = 0;
+		dev_dbg(dev->dev, "flow src:pipe num:%d",
+					cfg->dest_pipe_index);
+		cfg->mode = SPS_MODE_DEST;
+	} else {
+		cfg->source = dev->bam.hdl;
+		cfg->destination = SPS_DEV_HANDLE_MEM;
+		cfg->src_pipe_index = ((stat & (0xFF << 4)) >> 4);
+		cfg->dest_pipe_index = 0;
+		dev_dbg(dev->dev, "flow dest:pipe num:%d",
+					cfg->src_pipe_index);
+		cfg->mode = SPS_MODE_SRC;
+	}
+	/* Space for desciptor FIFOs */
+	cfg->desc.size = MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec);
+	cfg->config = SPS_CONFIG_DEFAULT;
+	ret = sps_connect(dev->pipes[pn].sps, cfg);
+	if (!ret) {
+		dev->pipes[pn].connected = true;
+		msm_hw_set_port(dev, pn + dev->pipe_b);
+	}
+	return ret;
+}
+
+int msm_config_port(struct slim_controller *ctrl, u8 pn)
+{
+	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+	struct msm_slim_endp *endpoint;
+	int ret = 0;
+	if (ctrl->ports[pn].req == SLIM_REQ_HALF_DUP ||
+		ctrl->ports[pn].req == SLIM_REQ_MULTI_CH)
+		return -EPROTONOSUPPORT;
+	if (pn >= (MSM_SLIM_NPORTS - dev->pipe_b))
+		return -ENODEV;
+
+	endpoint = &dev->pipes[pn];
+	ret = msm_slim_init_endpoint(dev, endpoint);
+	dev_dbg(dev->dev, "sps register bam error code:%x\n", ret);
+	return ret;
+}
+
+enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr,
+				u8 pn, u8 **done_buf, u32 *done_len)
+{
+	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctr);
+	struct sps_iovec sio;
+	int ret;
+	if (done_len)
+		*done_len = 0;
+	if (done_buf)
+		*done_buf = NULL;
+	if (!dev->pipes[pn].connected)
+		return SLIM_P_DISCONNECT;
+	ret = sps_get_iovec(dev->pipes[pn].sps, &sio);
+	if (!ret) {
+		if (done_len)
+			*done_len = sio.size;
+		if (done_buf)
+			*done_buf = (u8 *)sio.addr;
+	}
+	dev_dbg(dev->dev, "get iovec returned %d\n", ret);
+	return SLIM_P_INPROGRESS;
+}
+
+int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, u8 *iobuf,
+			u32 len, struct completion *comp)
+{
+	struct sps_register_event sreg;
+	int ret;
+	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+	if (pn >= 7)
+		return -ENODEV;
+
+
+	ctrl->ports[pn].xcomp = comp;
+	sreg.options = (SPS_EVENT_DESC_DONE|SPS_EVENT_ERROR);
+	sreg.mode = SPS_TRIGGER_WAIT;
+	sreg.xfer_done = comp;
+	sreg.callback = NULL;
+	sreg.user = &ctrl->ports[pn];
+	ret = sps_register_event(dev->pipes[pn].sps, &sreg);
+	if (ret) {
+		dev_dbg(dev->dev, "sps register event error:%x\n", ret);
+		return ret;
+	}
+	ret = sps_transfer_one(dev->pipes[pn].sps, (u32)iobuf, len, NULL,
+				SPS_IOVEC_FLAG_INT);
+	dev_dbg(dev->dev, "sps submit xfer error code:%x\n", ret);
+
+	return ret;
+}
+
+int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg)
+{
+	int i;
+	for (i = 0; i < (len + 3) >> 2; i++) {
+		dev_dbg(dev->dev, "TX data:0x%x\n", buf[i]);
+		writel_relaxed(buf[i], dev->base + tx_reg + (i * 4));
+	}
+	/* Guarantee that message is sent before returning */
+	mb();
+	return 0;
+}
+
+u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len)
+{
+	/*
+	 * Currently we block a transaction until the current one completes.
+	 * In case we need multiple transactions, use message Q
+	 */
+	return dev->tx_buf;
+}
+
+static void
+msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
+{
+	u32 *buf = ev->data.transfer.user;
+	struct sps_iovec *iovec = &ev->data.transfer.iovec;
+
+	/*
+	 * Note the virtual address needs to be offset by the same index
+	 * as the physical address or just pass in the actual virtual address
+	 * if the sps_mem_buffer is not needed.  Note that if completion is
+	 * used, the virtual address won't be available and will need to be
+	 * calculated based on the offset of the physical address
+	 */
+	if (ev->event_id == SPS_EVENT_DESC_DONE) {
+
+		pr_debug("buf = 0x%p, data = 0x%x\n", buf, *buf);
+
+		pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
+			iovec->addr, iovec->size, iovec->flags);
+
+	} else {
+		dev_err(dev->dev, "%s: unknown event %d\n",
+					__func__, ev->event_id);
+	}
+}
+
+static void msm_slim_rx_msgq_cb(struct sps_event_notify *notify)
+{
+	struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)notify->user;
+	msm_slim_rx_msgq_event(dev, notify);
+}
+
+/* Queue up Rx message buffer */
+static int msm_slim_post_rx_msgq(struct msm_slim_ctrl *dev, int ix)
+{
+	int ret;
+	u32 flags = SPS_IOVEC_FLAG_INT;
+	struct msm_slim_endp *endpoint = &dev->rx_msgq;
+	struct sps_mem_buffer *mem = &endpoint->buf;
+	struct sps_pipe *pipe = endpoint->sps;
+
+	/* Rx message queue buffers are 4 bytes in length */
+	u8 *virt_addr = mem->base + (4 * ix);
+	u32 phys_addr = mem->phys_base + (4 * ix);
+
+	pr_debug("index:%d, phys:0x%x, virt:0x%p\n", ix, phys_addr, virt_addr);
+
+	ret = sps_transfer_one(pipe, phys_addr, 4, virt_addr, flags);
+	if (ret)
+		dev_err(dev->dev, "transfer_one() failed 0x%x, %d\n", ret, ix);
+
+	return ret;
+}
+
+int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset)
+{
+	struct msm_slim_endp *endpoint = &dev->rx_msgq;
+	struct sps_mem_buffer *mem = &endpoint->buf;
+	struct sps_pipe *pipe = endpoint->sps;
+	struct sps_iovec iovec;
+	int index;
+	int ret;
+
+	ret = sps_get_iovec(pipe, &iovec);
+	if (ret) {
+		dev_err(dev->dev, "sps_get_iovec() failed 0x%x\n", ret);
+		goto err_exit;
+	}
+
+	pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
+		iovec.addr, iovec.size, iovec.flags);
+	BUG_ON(iovec.addr < mem->phys_base);
+	BUG_ON(iovec.addr >= mem->phys_base + mem->size);
+
+	/* Calculate buffer index */
+	index = (iovec.addr - mem->phys_base) / 4;
+	*(data + offset) = *((u32 *)mem->base + index);
+
+	pr_debug("buf = 0x%p, data = 0x%x\n", (u32 *)mem->base + index, *data);
+
+	/* Add buffer back to the queue */
+	(void)msm_slim_post_rx_msgq(dev, index);
+
+err_exit:
+	return ret;
+}
+
+static int msm_slim_init_rx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg)
+{
+	int i, ret;
+	u32 pipe_offset;
+	struct msm_slim_endp *endpoint = &dev->rx_msgq;
+	struct sps_connect *config = &endpoint->config;
+	struct sps_mem_buffer *descr = &config->desc;
+	struct sps_mem_buffer *mem = &endpoint->buf;
+	struct completion *notify = &dev->rx_msgq_notify;
+
+	struct sps_register_event sps_error_event; /* SPS_ERROR */
+	struct sps_register_event sps_descr_event; /* DESCR_DONE */
+
+	init_completion(notify);
+	if (!dev->use_rx_msgqs)
+		return 0;
+
+	/* Allocate the endpoint */
+	ret = msm_slim_init_endpoint(dev, endpoint);
+	if (ret) {
+		dev_err(dev->dev, "init_endpoint failed 0x%x\n", ret);
+		goto sps_init_endpoint_failed;
+	}
+
+	/* Get the pipe indices for the message queues */
+	pipe_offset = (readl_relaxed(dev->base + pipe_reg) & 0xfc) >> 2;
+	dev_dbg(dev->dev, "Message queue pipe offset %d\n", pipe_offset);
+
+	config->mode = SPS_MODE_SRC;
+	config->source = dev->bam.hdl;
+	config->destination = SPS_DEV_HANDLE_MEM;
+	config->src_pipe_index = pipe_offset;
+	config->options = SPS_O_DESC_DONE | SPS_O_ERROR |
+				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+
+	/* Allocate memory for the FIFO descriptors */
+	ret = msm_slim_sps_mem_alloc(dev, descr,
+				MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec));
+	if (ret) {
+		dev_err(dev->dev, "unable to allocate SPS descriptors\n");
+		goto alloc_descr_failed;
+	}
+
+	ret = sps_connect(endpoint->sps, config);
+	if (ret) {
+		dev_err(dev->dev, "sps_connect failed 0x%x\n", ret);
+		goto sps_connect_failed;
+	}
+
+	memset(&sps_descr_event, 0x00, sizeof(sps_descr_event));
+
+	sps_descr_event.mode = SPS_TRIGGER_CALLBACK;
+	sps_descr_event.options = SPS_O_DESC_DONE;
+	sps_descr_event.user = (void *)dev;
+	sps_descr_event.xfer_done = notify;
+
+	ret = sps_register_event(endpoint->sps, &sps_descr_event);
+	if (ret) {
+		dev_err(dev->dev, "sps_connect() failed 0x%x\n", ret);
+		goto sps_reg_event_failed;
+	}
+
+	/* Register callback for errors */
+	memset(&sps_error_event, 0x00, sizeof(sps_error_event));
+	sps_error_event.mode = SPS_TRIGGER_CALLBACK;
+	sps_error_event.options = SPS_O_ERROR;
+	sps_error_event.user = (void *)dev;
+	sps_error_event.callback = msm_slim_rx_msgq_cb;
+
+	ret = sps_register_event(endpoint->sps, &sps_error_event);
+	if (ret) {
+		dev_err(dev->dev, "sps_connect() failed 0x%x\n", ret);
+		goto sps_reg_event_failed;
+	}
+
+	/* Allocate memory for the message buffer(s), N descrs, 4-byte mesg */
+	ret = msm_slim_sps_mem_alloc(dev, mem, MSM_SLIM_DESC_NUM * 4);
+	if (ret) {
+		dev_err(dev->dev, "dma_alloc_coherent failed\n");
+		goto alloc_buffer_failed;
+	}
+
+	/*
+	 * Call transfer_one for each 4-byte buffer
+	 * Use (buf->size/4) - 1 for the number of buffer to post
+	 */
+
+	/* Setup the transfer */
+	for (i = 0; i < (MSM_SLIM_DESC_NUM - 1); i++) {
+		ret = msm_slim_post_rx_msgq(dev, i);
+		if (ret) {
+			dev_err(dev->dev, "post_rx_msgq() failed 0x%x\n", ret);
+			goto sps_transfer_failed;
+		}
+	}
+
+	return 0;
+
+sps_transfer_failed:
+	msm_slim_sps_mem_free(dev, mem);
+alloc_buffer_failed:
+	memset(&sps_error_event, 0x00, sizeof(sps_error_event));
+	sps_register_event(endpoint->sps, &sps_error_event);
+sps_reg_event_failed:
+	sps_disconnect(endpoint->sps);
+sps_connect_failed:
+	msm_slim_sps_mem_free(dev, descr);
+alloc_descr_failed:
+	msm_slim_free_endpoint(endpoint);
+sps_init_endpoint_failed:
+	dev->use_rx_msgqs = 0;
+	return ret;
+}
+
+/* Registers BAM h/w resource with SPS driver and initializes msgq endpoints */
+int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
+			u32 pipe_reg)
+{
+	int i, ret;
+	u32 bam_handle;
+	struct sps_bam_props bam_props = {0};
+
+	static struct sps_bam_sec_config_props sec_props = {
+		.ees = {
+			[0] = {		/* LPASS */
+				.vmid = 0,
+				.pipe_mask = 0xFFFF98,
+			},
+			[1] = {		/* Krait Apps */
+				.vmid = 1,
+				.pipe_mask = 0x3F000007,
+			},
+			[2] = {		/* Modem */
+				.vmid = 2,
+				.pipe_mask = 0x00000060,
+			},
+		},
+	};
+
+	bam_props.ee = dev->ee;
+	bam_props.virt_addr = dev->bam.base;
+	bam_props.phys_addr = bam_mem->start;
+	bam_props.irq = dev->bam.irq;
+	bam_props.manage = SPS_BAM_MGR_LOCAL;
+	bam_props.summing_threshold = MSM_SLIM_PERF_SUMM_THRESHOLD;
+
+	bam_props.sec_config = SPS_BAM_SEC_DO_CONFIG;
+	bam_props.p_sec_config_props = &sec_props;
+
+	bam_props.options = SPS_O_DESC_DONE | SPS_O_ERROR |
+				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+
+	/* First 7 bits are for message Qs */
+	for (i = 7; i < 32; i++) {
+		/* Check what pipes are owned by Apps. */
+		if ((sec_props.ees[dev->ee].pipe_mask >> i) & 0x1)
+			break;
+	}
+	dev->pipe_b = i - 7;
+
+	/* Register the BAM device with the SPS driver */
+	ret = sps_register_bam_device(&bam_props, &bam_handle);
+	if (ret) {
+		dev_err(dev->dev, "disabling BAM: reg-bam failed 0x%x\n", ret);
+		dev->use_rx_msgqs = 0;
+		goto init_rx_msgq;
+	}
+	dev->bam.hdl = bam_handle;
+	dev_dbg(dev->dev, "SLIM BAM registered, handle = 0x%x\n", bam_handle);
+
+init_rx_msgq:
+	ret = msm_slim_init_rx_msgq(dev, pipe_reg);
+	if (ret)
+		dev_err(dev->dev, "msm_slim_init_rx_msgq failed 0x%x\n", ret);
+	if (ret && bam_handle) {
+		sps_deregister_bam_device(bam_handle);
+		dev->bam.hdl = 0L;
+	}
+	return ret;
+}
+
+void msm_slim_sps_exit(struct msm_slim_ctrl *dev)
+{
+	if (dev->use_rx_msgqs) {
+		struct msm_slim_endp *endpoint = &dev->rx_msgq;
+		struct sps_connect *config = &endpoint->config;
+		struct sps_mem_buffer *descr = &config->desc;
+		struct sps_mem_buffer *mem = &endpoint->buf;
+		struct sps_register_event sps_event;
+		memset(&sps_event, 0x00, sizeof(sps_event));
+		msm_slim_sps_mem_free(dev, mem);
+		sps_register_event(endpoint->sps, &sps_event);
+		sps_disconnect(endpoint->sps);
+		msm_slim_sps_mem_free(dev, descr);
+		msm_slim_free_endpoint(endpoint);
+		sps_deregister_bam_device(dev->bam.hdl);
+	}
+}
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
new file mode 100644
index 0000000..f68475a
--- /dev/null
+++ b/drivers/slimbus/slim-msm.h
@@ -0,0 +1,251 @@
+/* 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 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 _SLIM_MSM_H
+#define _SLIM_MSM_H
+/* Per spec.max 40 bytes per received message */
+#define SLIM_RX_MSGQ_BUF_LEN	40
+
+#define SLIM_USR_MC_GENERIC_ACK		0x25
+#define SLIM_USR_MC_MASTER_CAPABILITY	0x0
+#define SLIM_USR_MC_REPORT_SATELLITE	0x1
+#define SLIM_USR_MC_ADDR_QUERY		0xD
+#define SLIM_USR_MC_ADDR_REPLY		0xE
+#define SLIM_USR_MC_DEFINE_CHAN		0x20
+#define SLIM_USR_MC_DEF_ACT_CHAN	0x21
+#define SLIM_USR_MC_CHAN_CTRL		0x23
+#define SLIM_USR_MC_RECONFIG_NOW	0x24
+#define SLIM_USR_MC_REQ_BW		0x28
+#define SLIM_USR_MC_CONNECT_SRC		0x2C
+#define SLIM_USR_MC_CONNECT_SINK	0x2D
+#define SLIM_USR_MC_DISCONNECT_PORT	0x2E
+
+#define MSM_SLIM_AUTOSUSPEND		MSEC_PER_SEC
+
+/*
+ * Messages that can be received simultaneously:
+ * Client reads, LPASS master responses, announcement messages
+ * Receive upto 10 messages simultaneously.
+ */
+#define MSM_SLIM_DESC_NUM		32
+
+/* MSM Slimbus peripheral settings */
+#define MSM_SLIM_PERF_SUMM_THRESHOLD	0x8000
+#define MSM_SLIM_NPORTS			24
+#define MSM_SLIM_NCHANS			32
+
+#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
+		((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
+
+#define MSM_CONCUR_MSG	8
+#define SAT_CONCUR_MSG	8
+#define DEF_WATERMARK	(8 << 1)
+#define DEF_ALIGN	0
+#define DEF_PACK	(1 << 6)
+#define ENABLE_PORT	1
+
+#define DEF_BLKSZ	0
+#define DEF_TRANSZ	0
+
+#define SAT_MAGIC_LSB	0xD9
+#define SAT_MAGIC_MSB	0xC5
+#define SAT_MSG_VER	0x1
+#define SAT_MSG_PROT	0x1
+#define MSM_SAT_SUCCSS	0x20
+#define MSM_MAX_NSATS	2
+#define MSM_MAX_SATCH	32
+
+#define PGD_THIS_EE(r, v) ((v) ? PGD_THIS_EE_V2(r) : PGD_THIS_EE_V1(r))
+#define PGD_PORT(r, p, v) ((v) ? PGD_PORT_V2(r, p) : PGD_PORT_V1(r, p))
+#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r))
+
+#define PGD_THIS_EE_V2(r) (dev->base + (r ## _V2) + (dev->ee * 0x1000))
+#define PGD_PORT_V2(r, p) (dev->base + (r ## _V2) + ((p) * 0x1000))
+#define CFG_PORT_V2(r) ((r ## _V2))
+/* Component registers */
+enum comp_reg_v2 {
+	COMP_CFG_V2		= 4,
+	COMP_TRUST_CFG_V2	= 0x3000,
+};
+
+/* Manager PGD registers */
+enum pgd_reg_v2 {
+	PGD_CFG_V2		= 0x800,
+	PGD_STAT_V2		= 0x804,
+	PGD_INT_EN_V2		= 0x810,
+	PGD_INT_STAT_V2		= 0x814,
+	PGD_INT_CLR_V2		= 0x818,
+	PGD_OWN_EEn_V2		= 0x300C,
+	PGD_PORT_INT_EN_EEn_V2	= 0x5000,
+	PGD_PORT_INT_ST_EEn_V2	= 0x5004,
+	PGD_PORT_INT_CL_EEn_V2	= 0x5008,
+	PGD_PORT_CFGn_V2	= 0x14000,
+	PGD_PORT_STATn_V2	= 0x14004,
+	PGD_PORT_PARAMn_V2	= 0x14008,
+	PGD_PORT_BLKn_V2	= 0x1400C,
+	PGD_PORT_TRANn_V2	= 0x14010,
+	PGD_PORT_MCHANn_V2	= 0x14014,
+	PGD_PORT_PSHPLLn_V2	= 0x14018,
+	PGD_PORT_PC_CFGn_V2	= 0x8000,
+	PGD_PORT_PC_VALn_V2	= 0x8004,
+	PGD_PORT_PC_VFR_TSn_V2	= 0x8008,
+	PGD_PORT_PC_VFR_STn_V2	= 0x800C,
+	PGD_PORT_PC_VFR_CLn_V2	= 0x8010,
+	PGD_IE_STAT_V2		= 0x820,
+	PGD_VE_STAT_V2		= 0x830,
+};
+
+#define PGD_THIS_EE_V1(r) (dev->base + (r ## _V1) + (dev->ee * 16))
+#define PGD_PORT_V1(r, p) (dev->base + (r ## _V1) + ((p) * 32))
+#define CFG_PORT_V1(r) ((r ## _V1))
+/* Component registers */
+enum comp_reg_v1 {
+	COMP_CFG_V1		= 0,
+	COMP_TRUST_CFG_V1	= 0x14,
+};
+
+/* Manager PGD registers */
+enum pgd_reg_v1 {
+	PGD_CFG_V1		= 0x1000,
+	PGD_STAT_V1		= 0x1004,
+	PGD_INT_EN_V1		= 0x1010,
+	PGD_INT_STAT_V1		= 0x1014,
+	PGD_INT_CLR_V1		= 0x1018,
+	PGD_OWN_EEn_V1		= 0x1020,
+	PGD_PORT_INT_EN_EEn_V1	= 0x1030,
+	PGD_PORT_INT_ST_EEn_V1	= 0x1034,
+	PGD_PORT_INT_CL_EEn_V1	= 0x1038,
+	PGD_PORT_CFGn_V1	= 0x1080,
+	PGD_PORT_STATn_V1	= 0x1084,
+	PGD_PORT_PARAMn_V1	= 0x1088,
+	PGD_PORT_BLKn_V1	= 0x108C,
+	PGD_PORT_TRANn_V1	= 0x1090,
+	PGD_PORT_MCHANn_V1	= 0x1094,
+	PGD_PORT_PSHPLLn_V1	= 0x1098,
+	PGD_PORT_PC_CFGn_V1	= 0x1600,
+	PGD_PORT_PC_VALn_V1	= 0x1604,
+	PGD_PORT_PC_VFR_TSn_V1	= 0x1608,
+	PGD_PORT_PC_VFR_STn_V1	= 0x160C,
+	PGD_PORT_PC_VFR_CLn_V1	= 0x1610,
+	PGD_IE_STAT_V1		= 0x1700,
+	PGD_VE_STAT_V1		= 0x1710,
+};
+
+enum msm_ctrl_state {
+	MSM_CTRL_AWAKE,
+	MSM_CTRL_SLEEPING,
+	MSM_CTRL_ASLEEP,
+};
+
+struct msm_slim_sps_bam {
+	u32			hdl;
+	void __iomem		*base;
+	int			irq;
+};
+
+struct msm_slim_endp {
+	struct sps_pipe			*sps;
+	struct sps_connect		config;
+	struct sps_register_event	event;
+	struct sps_mem_buffer		buf;
+	struct completion		*xcomp;
+	bool				connected;
+};
+
+struct msm_slim_ctrl {
+	struct slim_controller  ctrl;
+	struct slim_framer	framer;
+	struct device		*dev;
+	void __iomem		*base;
+	struct resource		*slew_mem;
+	u32			curr_bw;
+	u8			msg_cnt;
+	u32			tx_buf[10];
+	u8			rx_msgs[MSM_CONCUR_MSG][SLIM_RX_MSGQ_BUF_LEN];
+	spinlock_t		rx_lock;
+	int			head;
+	int			tail;
+	int			irq;
+	int			err;
+	int			ee;
+	struct completion	*wr_comp;
+	struct msm_slim_sat	*satd[MSM_MAX_NSATS];
+	struct msm_slim_endp	pipes[7];
+	struct msm_slim_sps_bam	bam;
+	struct msm_slim_endp	rx_msgq;
+	struct completion	rx_msgq_notify;
+	struct task_struct	*rx_msgq_thread;
+	struct clk		*rclk;
+	struct clk		*hclk;
+	struct mutex		tx_lock;
+	u8			pgdla;
+	bool			use_rx_msgqs;
+	int			pipe_b;
+	struct completion	reconf;
+	bool			reconf_busy;
+	bool			chan_active;
+	enum msm_ctrl_state	state;
+	int			nsats;
+	u32			ver;
+};
+
+struct msm_sat_chan {
+	u8 chan;
+	u16 chanh;
+	int req_rem;
+	int req_def;
+	bool reconf;
+};
+
+struct msm_slim_sat {
+	struct slim_device	satcl;
+	struct msm_slim_ctrl	*dev;
+	struct workqueue_struct *wq;
+	struct work_struct	wd;
+	u8			sat_msgs[SAT_CONCUR_MSG][40];
+	struct msm_sat_chan	*satch;
+	u8			nsatch;
+	bool			sent_capability;
+	bool			pending_reconf;
+	bool			pending_capability;
+	int			shead;
+	int			stail;
+	spinlock_t lock;
+};
+
+enum rsc_grp {
+	EE_MGR_RSC_GRP	= 1 << 10,
+	EE_NGD_2	= 2 << 6,
+	EE_NGD_1	= 0,
+};
+
+
+int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len);
+int msm_slim_rx_dequeue(struct msm_slim_ctrl *dev, u8 *buf);
+int msm_slim_get_ctrl(struct msm_slim_ctrl *dev);
+void msm_slim_put_ctrl(struct msm_slim_ctrl *dev);
+int msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep);
+void msm_slim_free_endpoint(struct msm_slim_endp *ep);
+void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn);
+int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn);
+int msm_config_port(struct slim_controller *ctrl, u8 pn);
+enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr,
+				u8 pn, u8 **done_buf, u32 *done_len);
+int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, u8 *iobuf,
+			u32 len, struct completion *comp);
+int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg);
+u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len);
+int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset);
+int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
+			u32 pipe_reg);
+void msm_slim_sps_exit(struct msm_slim_ctrl *dev);
+#endif
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 8dce000..da2a30d 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -983,6 +983,15 @@
 				ret = -ETIMEDOUT;
 			} else
 				ret = 0;
+		} else if (ret < 0 && !msg->comp) {
+			struct slim_msg_txn *txn;
+			dev_err(&ctrl->dev, "slimbus Read error");
+			mutex_lock(&ctrl->m_ctrl);
+			txn = ctrl->txnt[tid];
+			/* Invalidate the transaction */
+			ctrl->txnt[tid] = NULL;
+			mutex_unlock(&ctrl->m_ctrl);
+			kfree(txn);
 		}
 
 	} else
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 4a79f76..c26da60 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1298,6 +1298,7 @@
 		container_of(work, struct msm_spi, work_data);
 	unsigned long        flags;
 	u32                  status_error = 0;
+	int                  rc = 0;
 
 	mutex_lock(&dd->core_lock);
 
@@ -1308,6 +1309,21 @@
 	if (dd->use_rlock)
 		remote_mutex_lock(&dd->r_lock);
 
+	/* Configure the spi clk, miso, mosi and cs gpio */
+	if (dd->pdata->gpio_config) {
+		rc = dd->pdata->gpio_config();
+		if (rc) {
+			dev_err(dd->dev,
+					"%s: error configuring GPIOs\n",
+					__func__);
+			status_error = 1;
+		}
+	}
+
+	rc = msm_spi_request_gpios(dd);
+	if (rc)
+		status_error = 1;
+
 	clk_prepare_enable(dd->clk);
 	clk_prepare_enable(dd->pclk);
 	msm_spi_enable_irqs(dd);
@@ -1339,6 +1355,12 @@
 	clk_disable_unprepare(dd->clk);
 	clk_disable_unprepare(dd->pclk);
 
+	/* Free  the spi clk, miso, mosi, cs gpio */
+	if (!rc && dd->pdata && dd->pdata->gpio_release)
+		dd->pdata->gpio_release();
+	if (!rc)
+		msm_spi_free_gpios(dd);
+
 	if (dd->use_rlock)
 		remote_mutex_unlock(&dd->r_lock);
 
@@ -1425,6 +1447,24 @@
 	if (dd->use_rlock)
 		remote_mutex_lock(&dd->r_lock);
 
+	/* Configure the spi clk, miso, mosi, cs gpio */
+	if (dd->pdata->gpio_config) {
+		rc = dd->pdata->gpio_config();
+		if (rc) {
+			dev_err(&spi->dev,
+					"%s: error configuring GPIOs\n",
+					__func__);
+			rc = -ENXIO;
+			goto err_setup_gpio;
+		}
+	}
+
+	rc = msm_spi_request_gpios(dd);
+	if (rc) {
+		rc = -ENXIO;
+		goto err_setup_gpio;
+	}
+
 	clk_prepare_enable(dd->clk);
 	clk_prepare_enable(dd->pclk);
 
@@ -1457,10 +1497,15 @@
 	clk_disable_unprepare(dd->clk);
 	clk_disable_unprepare(dd->pclk);
 
+	/* Free  the spi clk, miso, mosi, cs gpio */
+	if (dd->pdata && dd->pdata->gpio_release)
+		dd->pdata->gpio_release();
+	msm_spi_free_gpios(dd);
+
+err_setup_gpio:
 	if (dd->use_rlock)
 		remote_mutex_unlock(&dd->r_lock);
 	mutex_unlock(&dd->core_lock);
-
 err_setup_exit:
 	return rc;
 }
@@ -1897,22 +1942,9 @@
 			dd->use_dma = 1;
 			master->dma_alignment =	dma_get_cache_alignment();
 		}
-
-skip_dma_resources:
-		if (pdata->gpio_config) {
-			rc = pdata->gpio_config();
-			if (rc) {
-				dev_err(&pdev->dev,
-					"%s: error configuring GPIOs\n",
-					__func__);
-				goto err_probe_gpio;
-			}
-		}
 	}
 
-	rc = msm_spi_request_gpios(dd);
-	if (rc)
-		goto err_probe_gpio;
+skip_dma_resources:
 
 	spin_lock_init(&dd->queue_lock);
 	mutex_init(&dd->core_lock);
@@ -1951,8 +1983,8 @@
 
 		dd->use_rlock = 1;
 		dd->pm_lat = pdata->pm_lat;
-		pm_qos_add_request(&qos_req_list, PM_QOS_CPU_DMA_LATENCY, 
-					    	 PM_QOS_DEFAULT_VALUE);
+		pm_qos_add_request(&qos_req_list, PM_QOS_CPU_DMA_LATENCY,
+					PM_QOS_DEFAULT_VALUE);
 	}
 
 	mutex_lock(&dd->core_lock);
@@ -2082,10 +2114,6 @@
 err_probe_reqmem:
 	destroy_workqueue(dd->workqueue);
 err_probe_workq:
-	msm_spi_free_gpios(dd);
-err_probe_gpio:
-	if (pdata && pdata->gpio_release)
-		pdata->gpio_release();
 err_probe_res:
 	spi_master_put(master);
 err_probe_exit:
@@ -2112,7 +2140,6 @@
 
 	/* Wait for transactions to end, or time out */
 	wait_event_interruptible(dd->continue_suspend, !dd->transfer_pending);
-	msm_spi_free_gpios(dd);
 
 suspend_exit:
 	return 0;
@@ -2129,7 +2156,6 @@
 	if (!dd)
 		goto resume_exit;
 
-	BUG_ON(msm_spi_request_gpios(dd) != 0);
 	dd->suspended = 0;
 resume_exit:
 	return 0;
@@ -2143,17 +2169,13 @@
 {
 	struct spi_master *master = platform_get_drvdata(pdev);
 	struct msm_spi    *dd = spi_master_get_devdata(master);
-	struct msm_spi_platform_data *pdata = pdev->dev.platform_data;
 
 	pm_qos_remove_request(&qos_req_list);
 	spi_debugfs_exit(dd);
 	sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
 
 	msm_spi_teardown_dma(dd);
-	if (pdata && pdata->gpio_release)
-		pdata->gpio_release();
 
-	msm_spi_free_gpios(dd);
 	clk_put(dd->clk);
 	clk_put(dd->pclk);
 	destroy_workqueue(dd->workqueue);
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 8724138..c32978e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -21,7 +21,6 @@
 
 config MSM_QPNP_INT
 	depends on SPARSE_IRQ
-	depends on ARCH_MSM8974
 	depends on SPMI
 	depends on OF_SPMI
 	bool "MSM QPNP INT"
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index ae1eff8..45429a1 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -638,6 +638,12 @@
 		return -ENODEV;
 	pmic_arb->channel = (u8)prop;
 
+	ret = irq_set_irq_wake(pmic_arb->pic_irq, 1);
+	if (unlikely(ret)) {
+		pr_err("Unable to set wakeup irq, err=%d\n", ret);
+		return -ENODEV;
+	}
+
 	pmic_arb->dev = &pdev->dev;
 	platform_set_drvdata(pdev, pmic_arb);
 	spmi_set_ctrldata(&pmic_arb->controller, pmic_arb);
@@ -679,6 +685,7 @@
 	spmi_del_controller(&pmic_arb->controller);
 err_add_controller:
 	platform_set_drvdata(pdev, NULL);
+	irq_set_irq_wake(pmic_arb->pic_irq, 0);
 	return ret;
 }
 
@@ -686,7 +693,7 @@
 {
 	struct spmi_pmic_arb_dev *pmic_arb = platform_get_drvdata(pdev);
 
-	free_irq(pmic_arb->pic_irq, pmic_arb);
+	irq_set_irq_wake(pmic_arb->pic_irq, 0);
 	platform_set_drvdata(pdev, NULL);
 	spmi_del_controller(&pmic_arb->controller);
 	return 0;
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index daf0564..0c49a89 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -682,20 +682,6 @@
 	return IRQ_HANDLED;
 }
 
-static void tsens8960_sensor_mode_init(void)
-{
-	unsigned int reg_cntl = 0;
-
-	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
-	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MDM_9615 ||
-			tmdev->hw_type == APQ_8064) {
-		writel_relaxed(reg_cntl &
-				~((((1 << tmdev->tsens_num_sensor) - 1) >> 1)
-				<< (TSENS_SENSOR0_SHIFT + 1)), TSENS_CNTL_ADDR);
-		tmdev->sensor[TSENS_MAIN_SENSOR].mode = THERMAL_DEVICE_ENABLED;
-	}
-}
-
 #ifdef CONFIG_PM
 static int tsens_suspend(struct device *dev)
 {
@@ -1018,11 +1004,8 @@
 			rc = -ENODEV;
 			goto fail;
 		}
-		tmdev->sensor[i].mode = THERMAL_DEVICE_DISABLED;
 	}
 
-	tsens8960_sensor_mode_init();
-
 	rc = request_irq(TSENS_UPPER_LOWER_INT, tsens_isr,
 		IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
 	if (rc < 0) {
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index b97ea1c..7169dc0 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -155,6 +155,7 @@
 	int				calib_len;
 	struct resource			*res_tsens_mem;
 	struct resource			*res_calib_mem;
+	struct work_struct		tsens_work;
 	struct tsens_tm_device_sensor	sensor[0];
 };
 
@@ -428,9 +429,10 @@
 					NULL, "type");
 }
 
-static irqreturn_t tsens_isr(int irq, void *data)
+static void tsens_scheduler_fn(struct work_struct *work)
 {
-	struct tsens_tm_device *tm = data;
+	struct tsens_tm_device *tm = container_of(work, struct tsens_tm_device,
+						tsens_work);
 	unsigned int i, status, threshold;
 	unsigned int sensor_status_addr, sensor_status_ctrl_addr;
 
@@ -464,6 +466,12 @@
 		sensor_status_ctrl_addr += TSENS_SN_ADDR_OFFSET;
 	}
 	mb();
+}
+
+static irqreturn_t tsens_isr(int irq, void *data)
+{
+	schedule_work(&tmdev->tsens_work);
+
 	return IRQ_HANDLED;
 }
 
@@ -523,8 +531,8 @@
 			tmdev->sensor[i].calib_data_point1 = 492;
 		}
 		goto compute_intercept_slope;
-	} else if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB ||
-				TSENS_TWO_POINT_CALIB) {
+	} else if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) ||
+			(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
 		tsens_base1_data = (calib_data[0] & TSENS_BASE1_MASK);
 		tsens0_point1 = (calib_data[0] & TSENS0_POINT1_MASK) >>
 							TSENS0_POINT1_SHIFT;
@@ -600,8 +608,8 @@
 		(((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens10_point1;
 	}
 
-	if (tsens_calibration_mode == (TSENS_ONE_POINT_CALIB_OPTION_2 ||
-					TSENS_TWO_POINT_CALIB)) {
+	if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
+			(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
 		tmdev->sensor[0].calib_data_point1 =
 		((((tsens_base1_data) + tsens0_point1) << 2) |
 						TSENS_BIT_APPEND);
@@ -884,6 +892,8 @@
 	}
 	platform_set_drvdata(pdev, tmdev);
 
+	INIT_WORK(&tmdev->tsens_work, tsens_scheduler_fn);
+
 	return 0;
 fail:
 	if (tmdev->tsens_calib_addr)
diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c
index 50238f3..ec04369 100644
--- a/drivers/thermal/pm8xxx-tm.c
+++ b/drivers/thermal/pm8xxx-tm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -65,10 +65,11 @@
 
 struct pm8xxx_tm_chip {
 	struct pm8xxx_tm_core_data	cdata;
-	struct work_struct		irq_work;
+	struct delayed_work		irq_work;
 	struct device			*dev;
 	struct thermal_zone_device	*tz_dev;
 	unsigned long			temp;
+	unsigned int			prev_stage;
 	enum thermal_device_mode	mode;
 	unsigned int			thresh;
 	unsigned int			stage;
@@ -82,6 +83,9 @@
 	SOFTWARE_OVERRIDE_ENABLED,
 };
 
+/* Delay between TEMP_STAT IRQ going high and status value changing in ms. */
+#define STATUS_REGISTER_DELAY_MS	40
+
 static inline int pm8xxx_tm_read_ctrl(struct pm8xxx_tm_chip *chip, u8 *reg)
 {
 	int rc;
@@ -312,6 +316,10 @@
 	if (!chip)
 		return -EINVAL;
 
+	/* Mask software override requests if they are not allowed. */
+	if (!chip->cdata.allow_software_override)
+		mode = THERMAL_DEVICE_DISABLED;
+
 	if (mode != chip->mode) {
 		if (mode == THERMAL_DEVICE_ENABLED)
 			pm8xxx_tm_shutdown_override(chip,
@@ -421,31 +429,18 @@
 
 static void pm8xxx_tm_work(struct work_struct *work)
 {
+	struct delayed_work *dwork
+		= container_of(work, struct delayed_work, work);
 	struct pm8xxx_tm_chip *chip
-		= container_of(work, struct pm8xxx_tm_chip, irq_work);
-	int rc;
+		= container_of(dwork, struct pm8xxx_tm_chip, irq_work);
+	unsigned long temp = 0;
+	int rc, stage, thresh;
 	u8 reg;
 
 	rc = pm8xxx_tm_read_ctrl(chip, &reg);
 	if (rc < 0)
 		goto bail;
 
-	if (chip->cdata.adc_type == PM8XXX_TM_ADC_NONE) {
-		rc = pm8xxx_tm_update_temp_no_adc(chip);
-		if (rc < 0)
-			goto bail;
-		pr_info("%s: Temp Alarm - stage=%u, threshold=%u, "
-			"temp=%lu mC\n", chip->cdata.tm_name, chip->stage,
-			chip->thresh, chip->temp);
-	} else {
-		chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK)
-				>> TEMP_ALARM_CTRL_STATUS_SHIFT;
-		chip->thresh = (reg & TEMP_ALARM_CTRL_THRESH_MASK)
-				>> TEMP_ALARM_CTRL_THRESH_SHIFT;
-		pr_info("%s: Temp Alarm - stage=%u, threshold=%u\n",
-			chip->cdata.tm_name, chip->stage, chip->thresh);
-	}
-
 	/* Clear status bits. */
 	if (reg & (TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD)) {
 		reg &= ~(TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD
@@ -454,24 +449,47 @@
 		pm8xxx_tm_write_ctrl(chip, reg);
 	}
 
+	stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK)
+		>> TEMP_ALARM_CTRL_STATUS_SHIFT;
+	thresh = (reg & TEMP_ALARM_CTRL_THRESH_MASK)
+		>> TEMP_ALARM_CTRL_THRESH_SHIFT;
+
 	thermal_zone_device_update(chip->tz_dev);
 
-	/* Notify user space */
-	if (chip->mode == THERMAL_DEVICE_ENABLED)
-		kobject_uevent(&chip->tz_dev->device.kobj, KOBJ_CHANGE);
+	if (stage != chip->prev_stage) {
+		chip->prev_stage = stage;
+
+		switch (chip->cdata.adc_type) {
+		case PM8XXX_TM_ADC_NONE:
+			rc = pm8xxx_tz_get_temp_no_adc(chip->tz_dev, &temp);
+			break;
+		case PM8XXX_TM_ADC_PM8058_ADC:
+			rc = pm8xxx_tz_get_temp_pm8058_adc(chip->tz_dev, &temp);
+			break;
+		case PM8XXX_TM_ADC_PM8XXX_ADC:
+			rc = pm8xxx_tz_get_temp_pm8xxx_adc(chip->tz_dev, &temp);
+			break;
+		}
+		if (rc < 0)
+			goto bail;
+
+		pr_crit("%s: PMIC Temp Alarm - stage=%u, threshold=%u, temp=%lu mC\n",
+			chip->cdata.tm_name, stage, thresh, temp);
+
+		/* Notify user space */
+		sysfs_notify(&chip->tz_dev->device.kobj, NULL, "type");
+	}
 
 bail:
-	enable_irq(chip->tempstat_irq);
-	enable_irq(chip->overtemp_irq);
+	return;
 }
 
 static irqreturn_t pm8xxx_tm_isr(int irq, void *data)
 {
 	struct pm8xxx_tm_chip *chip = data;
 
-	disable_irq_nosync(chip->tempstat_irq);
-	disable_irq_nosync(chip->overtemp_irq);
-	schedule_work(&chip->irq_work);
+	schedule_delayed_work(&chip->irq_work,
+		msecs_to_jiffies(STATUS_REGISTER_DELAY_MS) + 1);
 
 	return IRQ_HANDLED;
 }
@@ -610,7 +628,7 @@
 	chip->mode = THERMAL_DEVICE_DISABLED;
 	thermal_zone_device_update(chip->tz_dev);
 
-	INIT_WORK(&chip->irq_work, pm8xxx_tm_work);
+	INIT_DELAYED_WORK(&chip->irq_work, pm8xxx_tm_work);
 
 	rc = request_irq(chip->tempstat_irq, pm8xxx_tm_isr, IRQF_TRIGGER_RISING,
 		chip->cdata.irq_name_temp_stat, chip);
@@ -635,7 +653,7 @@
 err_free_irq_tempstat:
 	free_irq(chip->tempstat_irq, chip);
 err_cancel_work:
-	cancel_work_sync(&chip->irq_work);
+	cancel_delayed_work_sync(&chip->irq_work);
 err_free_tz:
 	thermal_zone_device_unregister(chip->tz_dev);
 err_fail_adc:
@@ -651,7 +669,7 @@
 
 	if (chip) {
 		platform_set_drvdata(pdev, NULL);
-		cancel_work_sync(&chip->irq_work);
+		cancel_delayed_work_sync(&chip->irq_work);
 		free_irq(chip->overtemp_irq, chip);
 		free_irq(chip->tempstat_irq, chip);
 		pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 3f4d87b..4a9c9a3 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -174,7 +174,7 @@
 #define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE
 #define UARTDM_RX_BUF_SIZE 512
 #define RETRY_TIMEOUT 5
-#define UARTDM_NR 5
+#define UARTDM_NR 256
 
 static struct dentry *debug_base;
 static struct msm_hs_port q_uart_port[UARTDM_NR];
@@ -2025,6 +2025,8 @@
 	msm_serial_debugfs_init(msm_uport, pdev->id);
 
 	uport->line = pdev->id;
+	if (pdata != NULL && pdata->userid && pdata->userid <= UARTDM_NR)
+		uport->line = pdata->userid;
 	return uart_add_one_port(&msm_hs_driver, uport);
 }
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 66ba02b..b8f9563 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1473,6 +1473,8 @@
 	atomic_inc(&urb->use_count);
 	atomic_inc(&urb->dev->urbnum);
 	usbmon_urb_submit(&hcd->self, urb);
+	if (hcd->driver->log_urb)
+		hcd->driver->log_urb(urb, "S", urb->status);
 
 	/* NOTE requirements on root-hub callers (usbfs and the hub
 	 * driver, for now):  URBs' urb->transfer_buffer must be
@@ -1495,6 +1497,8 @@
 
 	if (unlikely(status)) {
 		usbmon_urb_submit_error(&hcd->self, urb, status);
+		if (hcd->driver->log_urb)
+			hcd->driver->log_urb(urb, "E", status);
 		urb->hcpriv = NULL;
 		INIT_LIST_HEAD(&urb->urb_list);
 		atomic_dec(&urb->use_count);
@@ -1597,11 +1601,10 @@
 
 	unmap_urb_for_dma(hcd, urb);
 	usbmon_urb_complete(&hcd->self, urb, status);
+	if (hcd->driver->log_urb)
+		hcd->driver->log_urb(urb, "C", status);
 	usb_unanchor_urb(urb);
 
-	if (hcd->driver->log_urb_complete)
-		hcd->driver->log_urb_complete(urb, "C", status);
-
 	/* pass ownership to the completion handler */
 	urb->status = status;
 	urb->complete (urb);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 6917b2d..b71bd3e 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -34,6 +34,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <mach/rpm-regulator.h>
+#include <mach/msm_bus.h>
 
 #include "dwc3_otg.h"
 #include "core.h"
@@ -103,10 +104,12 @@
  */
 #define QSCRATCH_REG_OFFSET	(0x000F8800)
 #define QSCRATCH_GENERAL_CFG	(QSCRATCH_REG_OFFSET + 0x08)
+#define HS_PHY_CTRL_REG		(QSCRATCH_REG_OFFSET + 0x10)
 #define CHARGING_DET_CTRL_REG	(QSCRATCH_REG_OFFSET + 0x18)
 #define CHARGING_DET_OUTPUT_REG	(QSCRATCH_REG_OFFSET + 0x1C)
 #define ALT_INTERRUPT_EN_REG	(QSCRATCH_REG_OFFSET + 0x20)
 #define HS_PHY_IRQ_STAT_REG	(QSCRATCH_REG_OFFSET + 0x24)
+#define SS_PHY_CTRL_REG		(QSCRATCH_REG_OFFSET + 0x30)
 
 struct dwc3_msm_req_complete {
 	struct list_head list_item;
@@ -147,6 +150,8 @@
 	struct delayed_work	chg_work;
 	enum usb_chg_state	chg_state;
 	u8			dcd_retries;
+	u32			bus_perf_client;
+	struct msm_bus_scale_pdata	*bus_scale_table;
 };
 
 #define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -1224,6 +1229,8 @@
 
 static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
 {
+	int ret;
+
 	dev_dbg(mdwc->dev, "%s: entering lpm\n", __func__);
 
 	if (atomic_read(&mdwc->in_lpm)) {
@@ -1238,6 +1245,13 @@
 	dwc3_ssusb_ldo_enable(0);
 	wake_unlock(&mdwc->wlock);
 
+	if (mdwc->bus_perf_client) {
+		ret = msm_bus_scale_client_update_request(
+						mdwc->bus_perf_client, 0);
+		if (ret)
+			dev_err(mdwc->dev, "Failed to reset bus bw vote\n");
+	}
+
 	atomic_set(&mdwc->in_lpm, 1);
 	dev_info(mdwc->dev, "DWC3 in low power mode\n");
 
@@ -1246,6 +1260,8 @@
 
 static int dwc3_msm_resume(struct dwc3_msm *mdwc)
 {
+	int ret;
+
 	dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
 
 	if (!atomic_read(&mdwc->in_lpm)) {
@@ -1253,6 +1269,13 @@
 		return 0;
 	}
 
+	if (mdwc->bus_perf_client) {
+		ret = msm_bus_scale_client_update_request(
+						mdwc->bus_perf_client, 1);
+		if (ret)
+			dev_err(mdwc->dev, "Failed to vote for bus scaling\n");
+	}
+
 	wake_lock(&mdwc->wlock);
 	clk_prepare_enable(mdwc->ref_clk);
 	clk_prepare_enable(mdwc->core_clk);
@@ -1573,6 +1596,27 @@
 	msm->resource_size = resource_size(res);
 	msm->dwc3 = dwc3;
 
+	/* SSPHY Initialization: Use ref_clk from pads and set its parameters */
+	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+	msleep(30);
+	/* Assert SSPHY reset */
+	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+	usleep_range(2000, 2200);
+	/* De-assert SSPHY reset - power and ref_clock must be ON */
+	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+	usleep_range(2000, 2200);
+	/* Ref clock must be stable now, enable ref clock for HS mode */
+	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+	usleep_range(2000, 2200);
+	/*
+	 * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
+	 * and disable RETENTION (power-on default is ENABLED)
+	 */
+	dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+	usleep_range(2000, 2200);
+	/* Disable (bypass) VBUS filter */
+	dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x38);
+
 	pm_runtime_set_active(msm->dev);
 
 	if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
@@ -1604,6 +1648,18 @@
 		goto put_pdev;
 	}
 
+	msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+	if (!msm->bus_scale_table) {
+		dev_err(&pdev->dev, "bus scaling is disabled\n");
+	} else {
+		msm->bus_perf_client =
+			msm_bus_scale_register_client(msm->bus_scale_table);
+		ret = msm_bus_scale_client_update_request(
+						msm->bus_perf_client, 1);
+		if (ret)
+			dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
+	}
+
 	/* Reset the DBM */
 	dwc3_msm_dbm_soft_reset(1);
 	usleep_range(1000, 1200);
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 90de7a4..a50f76b 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -50,7 +50,7 @@
 	 * space, see dwc3_probe in core.c.
 	 * However, the offsets are given starting from xHCI address space.
 	 */
-	return readl_relaxed(base + (offset - DWC3_GLOBALS_REGS_START));
+	return readl(base + (offset - DWC3_GLOBALS_REGS_START));
 }
 
 static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
@@ -60,7 +60,7 @@
 	 * space, see dwc3_probe in core.c.
 	 * However, the offsets are given starting from xHCI address space.
 	 */
-	writel_relaxed(value, base + (offset - DWC3_GLOBALS_REGS_START));
+	writel(value, base + (offset - DWC3_GLOBALS_REGS_START));
 }
 
 #endif /* __DRIVERS_USB_DWC3_IO_H */
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 23f6ea3..a6eb335 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -30,6 +30,8 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/android.h>
 
+#include <mach/diag_dload.h>
+
 #include "gadget_chips.h"
 
 /*
@@ -163,6 +165,7 @@
 	struct list_head list_item;
 };
 
+struct dload_struct __iomem *diag_dload;
 static struct class *android_class;
 static struct list_head android_dev_list;
 static int android_dev_count;
@@ -173,6 +176,7 @@
 						(struct android_dev *dev);
 static void free_android_config(struct android_dev *dev,
 				struct android_configuration *conf);
+static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum);
 
 /* string IDs are assigned dynamically */
 #define STRING_MANUFACTURER_IDX		0
@@ -741,8 +745,12 @@
 		notify = NULL;
 		name = strsep(&b, ",");
 		/* Allow only first diag channel to update pid and serial no */
-		if (dev->pdata && !once++)
-			notify = dev->pdata->update_pid_and_serial_num;
+		if (!once++) {
+			if (dev->pdata && dev->pdata->update_pid_and_serial_num)
+				notify = dev->pdata->update_pid_and_serial_num;
+			else
+				notify = usb_diag_update_pid_and_serial_num;
+		}
 
 		if (name) {
 			err = diag_function_add(c, name, notify);
@@ -2239,10 +2247,49 @@
 	kfree(conf);
 }
 
+static int usb_diag_update_pid_and_serial_num(u32 pid, const char *snum)
+{
+	struct dload_struct local_diag_dload = { 0 };
+	int *src, *dst, i;
+
+	if (!diag_dload) {
+		pr_debug("%s: unable to update PID and serial_no\n", __func__);
+		return -ENODEV;
+	}
+
+	pr_debug("%s: dload:%p pid:%x serial_num:%s\n",
+				__func__, diag_dload, pid, snum);
+
+	/* update pid */
+	local_diag_dload.magic_struct.pid = PID_MAGIC_ID;
+	local_diag_dload.pid = pid;
+
+	/* update serial number */
+	if (!snum) {
+		local_diag_dload.magic_struct.serial_num = 0;
+		memset(&local_diag_dload.serial_number, 0,
+				SERIAL_NUMBER_LENGTH);
+	} else {
+		local_diag_dload.magic_struct.serial_num = SERIAL_NUM_MAGIC_ID;
+		strlcpy((char *)&local_diag_dload.serial_number, snum,
+				SERIAL_NUMBER_LENGTH);
+	}
+
+	/* Copy to shared struct (accesses need to be 32 bit aligned) */
+	src = (int *)&local_diag_dload;
+	dst = (int *)diag_dload;
+
+	for (i = 0; i < sizeof(*diag_dload) / 4; i++)
+		*dst++ = *src++;
+
+	return 0;
+}
+
 static int __devinit android_probe(struct platform_device *pdev)
 {
 	struct android_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct android_dev *android_dev;
+	struct resource *res;
 	int ret = 0;
 
 	if (!android_class) {
@@ -2277,6 +2324,19 @@
 	else
 		composite_driver.usb_core_id = 0; /*To backward compatibility*/
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res) {
+		diag_dload = devm_ioremap(&pdev->dev, res->start,
+							resource_size(res));
+		if (!diag_dload) {
+			dev_err(&pdev->dev, "ioremap failed\n");
+			ret = -ENOMEM;
+			goto err_dev;
+		}
+	} else {
+		dev_dbg(&pdev->dev, "failed to get mem resource\n");
+	}
+
 	ret = android_create_device(android_dev, composite_driver.usb_core_id);
 	if (ret) {
 		pr_err("%s(): android_create_device failed\n", __func__);
@@ -2355,8 +2415,17 @@
 	},
 };
 
+static struct of_device_id usb_android_dt_match[] = {
+	{	.compatible = "qcom,android-usb",
+	},
+	{}
+};
+
 static struct platform_driver android_platform_driver = {
-	.driver = { .name = "android_usb"},
+	.driver = {
+		.name = "android_usb",
+		.of_match_table = usb_android_dt_match,
+	},
 	.probe = android_probe,
 	.remove = android_remove,
 	.id_table = android_id_table,
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
index 6faaf78..b0b9468 100644
--- a/drivers/usb/gadget/ci13xxx_msm_hsic.c
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -67,6 +67,7 @@
 	struct work_struct	suspend_w;
 	struct msm_hsic_peripheral_platform_data *pdata;
 	enum usb_vdd_type	vdd_type;
+	bool connected;
 };
 
 static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
@@ -381,7 +382,7 @@
 	 */
 	mb();
 
-	if (!mhsic->pdata->core_clk_always_on_workaround) {
+	if (!mhsic->pdata->core_clk_always_on_workaround || !mhsic->connected) {
 		clk_disable(mhsic->iface_clk);
 		clk_disable(mhsic->core_clk);
 	}
@@ -438,7 +439,7 @@
 		dev_err(mhsic->dev, "%s failed to vote for TCXO %d\n",
 				__func__, ret);
 
-	if (!mhsic->pdata->core_clk_always_on_workaround) {
+	if (!mhsic->pdata->core_clk_always_on_workaround || !mhsic->connected) {
 		clk_enable(mhsic->iface_clk);
 		clk_enable(mhsic->core_clk);
 	}
@@ -598,22 +599,38 @@
 
 	switch (event) {
 	case CI13XXX_CONTROLLER_RESET_EVENT:
-		dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
+		dev_info(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
 		writel_relaxed(0, USB_AHBBURST);
 		writel_relaxed(0x08, USB_AHBMODE);
 		break;
 	case CI13XXX_CONTROLLER_CONNECT_EVENT:
-		dev_dbg(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
-		msm_hsic_start();
+		dev_info(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
+		msm_hsic_wakeup();
+		the_mhsic->connected = true;
 		break;
 	case CI13XXX_CONTROLLER_SUSPEND_EVENT:
-		dev_dbg(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
+		dev_info(dev, "CI13XXX_CONTROLLER_SUSPEND_EVENT received\n");
 		queue_work(mhsic->wq, &mhsic->suspend_w);
 		break;
 	case CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT:
-		dev_dbg(dev, "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
+		dev_info(dev, "CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT received\n");
 		msm_hsic_wakeup();
 		break;
+	case CI13XXX_CONTROLLER_UDC_STARTED_EVENT:
+		dev_info(dev, "CI13XXX_CONTROLLER_UDC_STARTED_EVENT received\n");
+		/*
+		 * UDC started, suspend the hsic device until it will be
+		 * connected by a pullup (CI13XXX_CONTROLLER_CONNECT_EVENT)
+		 * Before suspend, finish required configurations.
+		 */
+		hw_device_state(_udc->ep0out.qh.dma);
+		msm_hsic_start();
+		usleep(10000);
+
+		mhsic->connected = false;
+		pm_runtime_put_noidle(the_mhsic->dev);
+		pm_runtime_suspend(the_mhsic->dev);
+		break;
 	default:
 		dev_dbg(dev, "unknown ci13xxx_udc event\n");
 		break;
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 831e970..5b39336 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3205,6 +3205,11 @@
 	spin_unlock_irqrestore(udc->lock, flags);
 	if (retval || put)
 		pm_runtime_put_sync(&udc->gadget.dev);
+
+	if (udc->udc_driver->notify_event)
+			udc->udc_driver->notify_event(udc,
+				CI13XXX_CONTROLLER_UDC_STARTED_EVENT);
+
 	return retval;
 }
 
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 6527b76..3162e15 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -126,6 +126,8 @@
 #define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT	3
 #define CI13XXX_CONTROLLER_RESUME_EVENT	        4
 #define CI13XXX_CONTROLLER_DISCONNECT_EVENT	    5
+#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT	    6
+
 	void	(*notify_event) (struct ci13xxx *udc, unsigned event);
 };
 
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
index dcf307d..a740d95 100644
--- a/drivers/usb/gadget/f_qc_rndis.c
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -882,6 +882,11 @@
 
 	rndis_set_max_pkt_xfer(rndis->config, rndis->max_pkt_per_xfer);
 
+	/* In case of aggregated packets QC device will request
+	 * aliment to 4 (2^2).
+	 */
+	rndis_set_pkt_alignment_factor(rndis->config, 2);
+
 	/* NOTE:  all that is done without knowing or caring about
 	 * the network link ... which is unavailable to this code
 	 * until we're activated via set_alt().
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 1d0b6d4..aa9daf3 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -488,6 +488,8 @@
 		break;
 	case USB_GADGET_XPORT_HSIC:
 		break;
+	case USB_GADGET_XPORT_HSUART:
+		break;
 	case USB_GADGET_XPORT_NONE:
 		break;
 	default:
@@ -515,6 +517,8 @@
 		break;
 	case USB_GADGET_XPORT_HSIC:
 		break;
+	case USB_GADGET_XPORT_HSUART:
+		break;
 	case USB_GADGET_XPORT_NONE:
 		break;
 	default:
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 59ff8d7..02f044e 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -25,6 +25,10 @@
 #include "u_ether.h"
 #include "rndis.h"
 
+static bool rndis_multipacket_dl_disable;
+module_param(rndis_multipacket_dl_disable, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(rndis_multipacket_dl_disable,
+	"Disable RNDIS Multi-packet support in DownLink");
 
 /*
  * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
@@ -469,6 +473,8 @@
 				__func__, buf->MaxTransferSize,
 				rndis->port.multi_pkt_xfer ? "enabled" :
 							    "disabled");
+		if (rndis_multipacket_dl_disable)
+			rndis->port.multi_pkt_xfer = 0;
 	}
 //	spin_unlock(&dev->lock);
 }
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index e0520c7..801d24d 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -590,8 +590,9 @@
 		(params->dev->mtu
 		+ sizeof(struct ethhdr)
 		+ sizeof(struct rndis_packet_msg_type)
+
 		+ 22));
-	resp->PacketAlignmentFactor = cpu_to_le32(0);
+	resp->PacketAlignmentFactor = cpu_to_le32(params->pkt_alignment_factor);
 	resp->AFListOffset = cpu_to_le32(0);
 	resp->AFListSize = cpu_to_le32(0);
 
@@ -902,8 +903,8 @@
 			rndis_per_dev_params[i].used = 1;
 			rndis_per_dev_params[i].resp_avail = resp_avail;
 			rndis_per_dev_params[i].v = v;
-			rndis_per_dev_params[i].max_pkt_per_xfer =
-							TX_SKB_HOLD_THRESHOLD;
+			rndis_per_dev_params[i].max_pkt_per_xfer = 1;
+			rndis_per_dev_params[i].pkt_alignment_factor = 0;
 			pr_debug("%s: configNr = %d\n", __func__, i);
 			return i;
 		}
@@ -964,6 +965,14 @@
 	rndis_per_dev_params[configNr].max_pkt_per_xfer = max_pkt_per_xfer;
 }
 
+void rndis_set_pkt_alignment_factor(u8 configNr, u8 pkt_alignment_factor)
+{
+	pr_debug("%s:\n", __func__);
+
+	rndis_per_dev_params[configNr].pkt_alignment_factor =
+					pkt_alignment_factor;
+}
+
 void rndis_add_hdr(struct sk_buff *skb)
 {
 	struct rndis_packet_msg_type *header;
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 1f06c42..8a6a630 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -236,6 +236,7 @@
 
 	u32			vendorID;
 	u8			max_pkt_per_xfer;
+	u8			pkt_alignment_factor;
 	const char		*vendorDescr;
 	void			(*resp_avail)(void *v);
 	void			*v;
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index a9e5d91..45dfb87 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -640,26 +640,6 @@
 	clear_bit(BAM_CH_OPENED, &d->flags);
 }
 
-static void gbam2bam_disconnect_work(struct work_struct *w)
-{
-	struct gbam_port *port =
-			container_of(w, struct gbam_port, disconnect_w);
-	unsigned long		flags;
-
-	spin_lock_irqsave(&port->port_lock_ul, flags);
-	spin_lock(&port->port_lock_dl);
-	port->port_usb = 0;
-	spin_unlock(&port->port_lock_dl);
-	spin_unlock_irqrestore(&port->port_lock_ul, flags);
-
-	/* disable endpoints */
-	usb_ep_disable(port->gr->out);
-	usb_ep_disable(port->gr->in);
-
-	port->gr->in->driver_data = NULL;
-	port->gr->out->driver_data = NULL;
-}
-
 static void gbam_connect_work(struct work_struct *w)
 {
 	struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
@@ -699,29 +679,6 @@
 	struct bam_ch_info *d = &port->data_ch;
 	u32 sps_params;
 	int ret;
-	unsigned long flags;
-
-	ret = usb_ep_enable(port->gr->in);
-	if (ret) {
-		pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
-				__func__, port->gr->in);
-		return;
-	}
-	port->gr->in->driver_data = port;
-
-	ret = usb_ep_enable(port->gr->out);
-	if (ret) {
-		pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
-				__func__, port->gr->out);
-		port->gr->in->driver_data = 0;
-		return;
-	}
-	port->gr->out->driver_data = port;
-	spin_lock_irqsave(&port->port_lock_ul, flags);
-	spin_lock(&port->port_lock_dl);
-	port->port_usb = port->gr;
-	spin_unlock(&port->port_lock_dl);
-	spin_unlock_irqrestore(&port->port_lock_ul, flags);
 
 	ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
 						  &d->dst_pipe_idx);
@@ -916,7 +873,6 @@
 	spin_lock_init(&port->port_lock_dl);
 
 	INIT_WORK(&port->connect_w, gbam2bam_connect_work);
-	INIT_WORK(&port->disconnect_w, gbam2bam_disconnect_work);
 
 	/* data ch */
 	d = &port->data_ch;
@@ -1071,7 +1027,7 @@
 	d = &port->data_ch;
 	port->gr = gr;
 
-	if (trans == USB_GADGET_XPORT_BAM) {
+	if (trans == USB_GADGET_XPORT_BAM)
 		gbam_free_buffers(port);
 
 	spin_lock_irqsave(&port->port_lock_ul, flags);
@@ -1081,12 +1037,15 @@
 	spin_unlock(&port->port_lock_dl);
 	spin_unlock_irqrestore(&port->port_lock_ul, flags);
 
-		/* disable endpoints */
-		usb_ep_disable(gr->out);
-		usb_ep_disable(gr->in);
-	}
+	/* disable endpoints */
+	usb_ep_disable(gr->out);
+	usb_ep_disable(gr->in);
 
-	queue_work(gbam_wq, &port->disconnect_w);
+	gr->in->driver_data = NULL;
+	gr->out->driver_data = NULL;
+
+	if (trans == USB_GADGET_XPORT_BAM)
+		queue_work(gbam_wq, &port->disconnect_w);
 }
 
 int gbam_connect(struct grmnet *gr, u8 port_num,
@@ -1121,36 +1080,37 @@
 
 	d = &port->data_ch;
 
-	if (trans == USB_GADGET_XPORT_BAM) {
-		ret = usb_ep_enable(gr->in);
-		if (ret) {
-			pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
-					__func__, gr->in);
-			return ret;
-		}
-		gr->in->driver_data = port;
+	ret = usb_ep_enable(gr->in);
+	if (ret) {
+		pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
+			__func__, gr->in);
+		return ret;
+	}
+	gr->in->driver_data = port;
 
-		ret = usb_ep_enable(gr->out);
-		if (ret) {
-			pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
-					__func__, gr->out);
-			gr->in->driver_data = 0;
-			return ret;
-		}
-		gr->out->driver_data = port;
+	ret = usb_ep_enable(gr->out);
+	if (ret) {
+		pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
+			__func__, gr->out);
+		gr->in->driver_data = 0;
+		return ret;
+	}
+	gr->out->driver_data = port;
 
 	spin_lock_irqsave(&port->port_lock_ul, flags);
 	spin_lock(&port->port_lock_dl);
 	port->port_usb = gr;
 
+	if (trans == USB_GADGET_XPORT_BAM) {
 		d->to_host = 0;
 		d->to_modem = 0;
 		d->pending_with_bam = 0;
 		d->tohost_drp_cnt = 0;
 		d->tomodem_drp_cnt = 0;
+	}
+
 	spin_unlock(&port->port_lock_dl);
 	spin_unlock_irqrestore(&port->port_lock_ul, flags);
-	}
 
 	if (trans == USB_GADGET_XPORT_BAM2BAM) {
 		port->gr = gr;
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index fd10394..b84c74d 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -292,6 +292,10 @@
 				status = dev->unwrap(dev->port_usb,
 							skb,
 							&dev->rx_frames);
+				if (status == -EINVAL)
+					dev->net->stats.rx_errors++;
+				else if (status == -EOVERFLOW)
+					dev->net->stats.rx_over_errors++;
 			} else {
 				dev_kfree_skb_any(skb);
 				status = -ENOTCONN;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 2126ff0..fee7a09 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -35,6 +35,10 @@
 #include <linux/usb/msm_hsusb.h>
 #include <linux/gpio.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/pm_qos.h>
 
 #include <mach/msm_bus.h>
 #include <mach/clk.h>
@@ -49,9 +53,22 @@
 #define USB_REG_END_OFFSET 0x250
 
 static struct workqueue_struct  *ehci_wq;
+struct ehci_timer {
+#define GPT_LD(p)	((p) & 0x00FFFFFF)
+	u32	gptimer0_ld;
+#define GPT_RUN		BIT(31)
+#define GPT_RESET	BIT(30)
+#define GPT_MODE	BIT(24)
+#define GPT_CNT(p)	((p) & 0x00FFFFFF)
+	u32	gptimer0_ctrl;
+
+	u32	gptimer1_ld;
+	u32	gptimer1_ctrl;
+};
 
 struct msm_hsic_hcd {
 	struct ehci_hcd		ehci;
+	spinlock_t		wakeup_lock;
 	struct device		*dev;
 	struct clk		*ahb_clk;
 	struct clk		*core_clk;
@@ -73,12 +90,23 @@
 
 	struct work_struct	bus_vote_w;
 	bool			bus_vote;
+
+	/* gp timer */
+	struct ehci_timer __iomem *timer;
+	struct completion	gpt0_completion;
+	struct completion	rt_completion;
+	int			resume_status;
+	int			resume_again;
+
+	struct pm_qos_request pm_qos_req_dma;
 };
 
 struct msm_hsic_hcd *__mehci;
 
 static bool debug_bus_voting_enabled = true;
 
+static unsigned int enable_payload_log = 1;
+module_param(enable_payload_log, uint, S_IRUGO | S_IWUSR);
 static unsigned int enable_dbg_log = 1;
 module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
 /*by default log ep0 and efs sync ep*/
@@ -88,12 +116,13 @@
 module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
 
 /* Maximum debug message length */
-#define DBG_MSG_LEN   100UL
+#define DBG_MSG_LEN   128UL
 
 /* Maximum number of messages */
 #define DBG_MAX_MSG   256UL
 
 #define TIME_BUF_LEN  20
+#define HEX_DUMP_LEN  72
 
 enum event_type {
 	EVENT_UNDEF = -1,
@@ -104,20 +133,6 @@
 
 #define EVENT_STR_LEN	5
 
-static char *event_to_str(enum event_type e)
-{
-	switch (e) {
-	case URB_SUBMIT:
-		return "S";
-	case URB_COMPLETE:
-		return "C";
-	case EVENT_NONE:
-		return "NONE";
-	default:
-		return "UNDEF";
-	}
-}
-
 static enum event_type str_to_event(const char *name)
 {
 	if (!strncasecmp("S", name, EVENT_STR_LEN))
@@ -187,11 +202,36 @@
 	return 0;
 }
 
+static char *get_hex_data(char *dbuf, struct urb *urb, int event, int status)
+{
+	int ep_addr = urb->ep->desc.bEndpointAddress;
+	char *ubuf = urb->transfer_buffer;
+	size_t len = event ? \
+		urb->actual_length : urb->transfer_buffer_length;
+
+	if (status == -EINPROGRESS)
+		status = 0;
+
+	/*Only dump ep in completions and epout submissions*/
+	if (len && !status &&
+		(((ep_addr & USB_DIR_IN) && event) ||
+		(!(ep_addr & USB_DIR_IN) && !event))) {
+		if (len >= 32)
+			len = 32;
+		hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
+	} else {
+		dbuf = "";
+	}
+
+	return dbuf;
+}
+
 static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
 {
 	unsigned long flags;
 	int ep_addr;
 	char tbuf[TIME_BUF_LEN];
+	char dbuf[HEX_DUMP_LEN];
 
 	if (!enable_dbg_log)
 		return;
@@ -199,7 +239,7 @@
 	if (!urb) {
 		write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
 		scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
-			"%s: %s : %u\n", get_timestamp(tbuf), event, extra);
+			"%s: %s : %u", get_timestamp(tbuf), event, extra);
 		dbg_inc(&dbg_hsic_ctrl.idx);
 		write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
 		return;
@@ -215,7 +255,7 @@
 			write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
 			scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
 				DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
-				  "%02x %02x %04x %04x %04x  %u %d\n",
+				  "%02x %02x %04x %04x %04x  %u %d",
 				  get_timestamp(tbuf), event, urb,
 				  (ep_addr & USB_DIR_IN) ? "in" : "out",
 				  urb->setup_packet[0], urb->setup_packet[1],
@@ -225,14 +265,14 @@
 				  urb->setup_packet[4],
 				  (urb->setup_packet[7] << 8) |
 				  urb->setup_packet[6],
-				  urb->transfer_buffer_length, urb->status);
+				  urb->transfer_buffer_length, extra);
 
 			dbg_inc(&dbg_hsic_ctrl.idx);
 			write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
 		} else {
 			write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
 			scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
-				DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d\n",
+				DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d",
 				  get_timestamp(tbuf), event, urb,
 				  (ep_addr & USB_DIR_IN) ? "in" : "out",
 				  urb->actual_length, extra);
@@ -243,12 +283,13 @@
 	} else {
 		write_lock_irqsave(&dbg_hsic_data.lck, flags);
 		scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
-			  "%s: [%s : %p]:ep%d[%s]  %u %d\n",
+			  "%s: [%s : %p]:ep%d[%s]  %u %d %s",
 			  get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
 			  (ep_addr & USB_DIR_IN) ? "in" : "out",
 			  str_to_event(event) ? urb->actual_length :
-			  urb->transfer_buffer_length,
-			  str_to_event(event) ?  extra : urb->status);
+			  urb->transfer_buffer_length, extra,
+			  enable_payload_log ? get_hex_data(dbuf, urb,
+				  str_to_event(event), extra) : "");
 
 		dbg_inc(&dbg_hsic_data.idx);
 		write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
@@ -709,17 +750,20 @@
 	int cnt = 0, ret;
 	unsigned temp;
 	int min_vol, max_vol;
+	unsigned long flags;
 
 	if (!atomic_read(&mehci->in_lpm)) {
 		dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
 		return 0;
 	}
 
+	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);
 
 	wake_lock(&mehci->wlock);
 
@@ -805,9 +849,12 @@
 				__func__, ret);
 }
 
+#define STS_GPTIMER0_INTERRUPT	BIT(24)
 static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
 {
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+	u32			status;
 
 	if (atomic_read(&mehci->in_lpm)) {
 		disable_irq_nosync(hcd->irq);
@@ -817,14 +864,38 @@
 		return IRQ_HANDLED;
 	}
 
+	status = ehci_readl(ehci, &ehci->regs->status);
+
+	if (status & STS_GPTIMER0_INTERRUPT) {
+		int timeleft;
+
+		dbg_log_event(NULL, "FPR: gpt0_isr", 0);
+
+		timeleft = GPT_CNT(ehci_readl(ehci,
+						 &mehci->timer->gptimer1_ctrl));
+		if (timeleft) {
+			ehci_writel(ehci, ehci_readl(ehci,
+				&ehci->regs->command) | CMD_RUN,
+				&ehci->regs->command);
+		} else
+			mehci->resume_again = 1;
+
+		dbg_log_event(NULL, "FPR: timeleft", timeleft);
+
+		complete(&mehci->gpt0_completion);
+		ehci_writel(ehci, STS_GPTIMER0_INTERRUPT, &ehci->regs->status);
+	}
+
 	return ehci_irq(hcd);
 }
 
 static int ehci_hsic_reset(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
 	int retval;
 
+	mehci->timer = USB_HS_GPTIMER_BASE;
 	ehci->caps = USB_CAPLENGTH;
 	ehci->regs = USB_CAPLENGTH +
 		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
@@ -861,23 +932,204 @@
 	return 0;
 }
 
-static int ehci_hsic_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
-		gfp_t mem_flags)
-{
-	dbg_log_event(urb, event_to_str(URB_SUBMIT), 0);
-	return ehci_urb_enqueue(hcd, urb, mem_flags);
-}
-
 static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
 {
 	dbg_log_event(NULL, "Suspend RH", 0);
 	return ehci_bus_suspend(hcd);
 }
 
+#define RESUME_RETRY_LIMIT		3
+#define RESUME_SIGNAL_TIME_MS		(21 * 999)
+#define RESUME_SIGNAL_TIME_SOF_MS	(23 * 999)
+static int msm_hsic_resume_thread(void *data)
+{
+	struct msm_hsic_hcd *mehci = data;
+	struct usb_hcd *hcd = hsic_to_hcd(mehci);
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+	u32			temp;
+	unsigned long		resume_needed = 0;
+	int			retry_cnt = 0;
+	int			tight_resume = 0;
+	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
+
+	dbg_log_event(NULL, "Resume RH", 0);
+
+	/* keep delay between bus states */
+	if (time_before(jiffies, ehci->next_statechange))
+		usleep_range(5000, 5000);
+
+	spin_lock_irq(&ehci->lock);
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
+		spin_unlock_irq(&ehci->lock);
+		mehci->resume_status = -ESHUTDOWN;
+		complete(&mehci->rt_completion);
+		return 0;
+	}
+
+	if (unlikely(ehci->debug)) {
+		if (!dbgp_reset_prep())
+			ehci->debug = NULL;
+		else
+			dbgp_external_startup();
+	}
+
+	/* at least some APM implementations will try to deliver
+	 * IRQs right away, so delay them until we're ready.
+	 */
+	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+
+	/* re-init operational registers */
+	ehci_writel(ehci, 0, &ehci->regs->segment);
+	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
+	ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
+
+	/*CMD_RUN will be set after, PORT_RESUME gets cleared*/
+	if (ehci->resume_sof_bug)
+		ehci->command &= ~CMD_RUN;
+
+	/* restore CMD_RUN, framelist size, and irq threshold */
+	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+
+	/* manually resume the ports we suspended during bus_suspend() */
+resume_again:
+	if (retry_cnt >= RESUME_RETRY_LIMIT) {
+		pr_info("retry count(%d) reached max, resume in tight loop\n",
+					retry_cnt);
+		tight_resume = 1;
+	}
+
+
+	temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
+	temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+	if (test_bit(0, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) {
+		temp |= PORT_RESUME;
+		set_bit(0, &resume_needed);
+	}
+	dbg_log_event(NULL, "FPR: Set", temp);
+	ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
+
+	/* HSIC controller has a h/w bug due to which it can try to send SOFs
+	 * (start of frames) during port resume resulting in phy lockup. HSIC hw
+	 * controller in MSM clears FPR bit after driving the resume signal for
+	 * 20ms. Workaround is to stop SOFs before driving resume and then start
+	 * sending SOFs immediately. Need to send SOFs within 3ms of resume
+	 * completion otherwise peripheral may enter undefined state. As
+	 * usleep_range does not gurantee exact sleep time, GPTimer is used to
+	 * to time the resume sequence. If driver exceeds allowable time SOFs,
+	 * repeat the resume process.
+	 */
+	if (ehci->resume_sof_bug && resume_needed) {
+		if (!tight_resume) {
+			mehci->resume_again = 0;
+			ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_MS),
+					&mehci->timer->gptimer0_ld);
+			ehci_writel(ehci, GPT_RESET | GPT_RUN,
+					&mehci->timer->gptimer0_ctrl);
+			ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
+					&ehci->regs->intr_enable);
+
+			ehci_writel(ehci, GPT_LD(RESUME_SIGNAL_TIME_SOF_MS),
+					&mehci->timer->gptimer1_ld);
+			ehci_writel(ehci, GPT_RESET | GPT_RUN,
+				&mehci->timer->gptimer1_ctrl);
+
+			spin_unlock_irq(&ehci->lock);
+			if (pdata && pdata->swfi_latency)
+				pm_qos_update_request(&mehci->pm_qos_req_dma,
+					pdata->swfi_latency + 1);
+			wait_for_completion(&mehci->gpt0_completion);
+			if (pdata && pdata->swfi_latency)
+				pm_qos_update_request(&mehci->pm_qos_req_dma,
+					PM_QOS_DEFAULT_VALUE);
+			spin_lock_irq(&ehci->lock);
+		} else {
+			dbg_log_event(NULL, "FPR: Tightloop", 0);
+			/* do the resume in a tight loop */
+			handshake(ehci, &ehci->regs->port_status[0],
+				PORT_RESUME, 0, 22 * 1000);
+			ehci_writel(ehci, ehci_readl(ehci,
+				&ehci->regs->command) | CMD_RUN,
+				&ehci->regs->command);
+		}
+
+		if (mehci->resume_again) {
+			int temp;
+
+			dbg_log_event(NULL, "FPR: Re-Resume", retry_cnt);
+			pr_info("FPR: retry count: %d\n", retry_cnt);
+			spin_unlock_irq(&ehci->lock);
+			temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
+			temp &= ~PORT_RWC_BITS;
+			temp |= PORT_SUSPEND;
+			ehci_writel(ehci, temp, &ehci->regs->port_status[0]);
+			/* Keep the bus idle for 5ms so that peripheral
+			 * can detect and initiate suspend
+			 */
+			usleep_range(5000, 5000);
+			dbg_log_event(NULL,
+				"FPR: RResume",
+				ehci_readl(ehci, &ehci->regs->port_status[0]));
+			spin_lock_irq(&ehci->lock);
+			mehci->resume_again = 0;
+			retry_cnt++;
+			goto resume_again;
+		}
+	}
+
+	dbg_log_event(NULL, "FPR: RT-Done", 0);
+	mehci->resume_status = 1;
+	spin_unlock_irq(&ehci->lock);
+
+	complete(&mehci->rt_completion);
+
+	return 0;
+}
+
 static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
 {
-	dbg_log_event(NULL, "Resume RH", 0);
-	return ehci_bus_resume(hcd);
+	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+	u32			temp;
+	struct task_struct	*resume_thread = NULL;
+
+	mehci->resume_status = 0;
+	resume_thread = kthread_run(msm_hsic_resume_thread,
+			mehci, "hsic_resume_thread");
+	if (IS_ERR(resume_thread)) {
+		pr_err("Error creating resume thread:%lu\n",
+				PTR_ERR(resume_thread));
+		return PTR_ERR(resume_thread);
+	}
+
+	wait_for_completion(&mehci->rt_completion);
+
+	if (mehci->resume_status < 0)
+		return mehci->resume_status;
+
+	dbg_log_event(NULL, "FPR: Wokeup", 0);
+	spin_lock_irq(&ehci->lock);
+	(void) ehci_readl(ehci, &ehci->regs->command);
+
+	temp = 0;
+	if (ehci->async->qh_next.qh)
+		temp |= CMD_ASE;
+	if (ehci->periodic_sched)
+		temp |= CMD_PSE;
+	if (temp) {
+		ehci->command |= temp;
+		ehci_writel(ehci, ehci->command, &ehci->regs->command);
+	}
+
+	ehci->next_statechange = jiffies + msecs_to_jiffies(5);
+	hcd->state = HC_STATE_RUNNING;
+	ehci->rh_state = EHCI_RH_RUNNING;
+
+	/* Now we can safely re-enable irqs */
+	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+
+	spin_unlock_irq(&ehci->lock);
+
+	return 0;
 }
 
 static struct hc_driver msm_hsic_driver = {
@@ -900,7 +1152,7 @@
 	/*
 	 * managing i/o requests and associated device resources
 	 */
-	.urb_enqueue		= ehci_hsic_urb_enqueue,
+	.urb_enqueue		= ehci_urb_enqueue,
 	.urb_dequeue		= ehci_urb_dequeue,
 	.endpoint_disable	= ehci_endpoint_disable,
 	.endpoint_reset		= ehci_endpoint_reset,
@@ -925,7 +1177,7 @@
 	.bus_suspend		= ehci_hsic_bus_suspend,
 	.bus_resume		= ehci_hsic_bus_resume,
 
-	.log_urb_complete	= dbg_log_event,
+	.log_urb		= dbg_log_event,
 	.dump_regs		= dump_hsic_regs,
 
 	.enable_ulpi_control	= ehci_msm_enable_ulpi_control,
@@ -1032,11 +1284,13 @@
 
 	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);
 	}
+	spin_unlock(&mehci->wakeup_lock);
 
 	if (!atomic_read(&mehci->pm_usage_cnt)) {
 		atomic_set(&mehci->pm_usage_cnt, 1);
@@ -1292,6 +1546,8 @@
 	mehci->dev = &pdev->dev;
 	pdata = mehci->dev->platform_data;
 
+	spin_lock_init(&mehci->wakeup_lock);
+
 	mehci->ehci.susp_sof_bug = 1;
 	mehci->ehci.reset_sof_bug = 1;
 
@@ -1327,6 +1583,8 @@
 		goto deinit_clocks;
 	}
 
+	init_completion(&mehci->rt_completion);
+	init_completion(&mehci->gpt0_completion);
 	ret = msm_hsic_reset(mehci);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to initialize PHY\n");
@@ -1365,12 +1623,16 @@
 
 	/* configure wakeup irq */
 	if (mehci->wakeup_irq) {
+		/* In case if wakeup gpio is pulled high at this point
+		 * remote wakeup interrupt fires right after request_irq.
+		 * Remote wake up interrupt only needs to be enabled when
+		 * HSIC bus goes to suspend.
+		 */
+		irq_set_status_flags(mehci->wakeup_irq, IRQ_NOAUTOEN);
 		ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
 				IRQF_TRIGGER_HIGH,
 				"msm_hsic_wakeup", mehci);
-		if (!ret) {
-			disable_irq_nosync(mehci->wakeup_irq);
-		} else {
+		if (ret) {
 			dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
 					mehci->wakeup_irq, ret);
 			mehci->wakeup_irq = 0;
@@ -1397,6 +1659,10 @@
 
 	__mehci = mehci;
 
+	if (pdata && pdata->swfi_latency)
+		pm_qos_add_request(&mehci->pm_qos_req_dma,
+			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
+
 	/*
 	 * This pdev->dev is assigned parent of root-hub by USB core,
 	 * hence, runtime framework automatically calls this driver's
@@ -1432,6 +1698,10 @@
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
+
+	if (pdata && pdata->swfi_latency)
+		pm_qos_remove_request(&mehci->pm_qos_req_dma);
 
 	if (mehci->peripheral_status_irq)
 		free_irq(mehci->peripheral_status_irq, mehci);
diff --git a/drivers/usb/host/ehci-msm72k.c b/drivers/usb/host/ehci-msm72k.c
index 816e408..3e53c14 100644
--- a/drivers/usb/host/ehci-msm72k.c
+++ b/drivers/usb/host/ehci-msm72k.c
@@ -399,7 +399,7 @@
 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
 	ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
 
-	hcd->state = HC_STATE_RUNNING;
+	ehci->rh_state = EHCI_RH_RUNNING;
 
 	/*Enable appropriate Interrupts*/
 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 4c59eab..db49c07 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -128,9 +128,17 @@
 	else {
 		qtd = list_entry (qh->qtd_list.next,
 				struct ehci_qtd, qtd_list);
-		/* first qtd may already be partially processed */
-		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current)
+		/*
+		 * first qtd may already be partially processed.
+		 * If we come here during unlink, the QH overlay region
+		 * might have reference to the just unlinked qtd. The
+		 * qtd is updated in qh_completions(). Update the QH
+		 * overlay here.
+		 */
+		if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
+			qh->hw->hw_qtd_next = qtd->hw_next;
 			qtd = NULL;
+		}
 	}
 
 	if (qtd)
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index ba7658b..cad411d 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kref.h>
+#include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/ratelimit.h>
 #include <linux/uaccess.h>
@@ -38,6 +39,7 @@
 	__u8			out_epAddr;
 	int			err;
 	struct kref		kref;
+	struct mutex		ifc_mutex;
 	struct diag_bridge_ops	*ops;
 	struct platform_device	*pdev;
 
@@ -120,24 +122,34 @@
 
 	pr_debug("reading %d bytes", size);
 
-	if (!dev || !dev->ifc) {
+	if (!dev) {
 		pr_err("device is disconnected");
 		return -ENODEV;
 	}
 
+	mutex_lock(&dev->ifc_mutex);
+	if (!dev->ifc) {
+		ret = -ENODEV;
+		goto error;
+	}
+
 	if (!dev->ops) {
 		pr_err("bridge is not open");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto error;
 	}
 
 	if (!size) {
 		dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto error;
 	}
 
 	/* if there was a previous unrecoverable error, just quit */
-	if (dev->err)
-		return -ENODEV;
+	if (dev->err) {
+		ret = -ENODEV;
+		goto error;
+	}
 
 	kref_get(&dev->kref);
 
@@ -145,7 +157,7 @@
 	if (!urb) {
 		dev_err(&dev->ifc->dev, "unable to allocate urb\n");
 		ret = -ENOMEM;
-		goto error;
+		goto put_error;
 	}
 
 	ret = usb_autopm_get_interface(dev->ifc);
@@ -170,9 +182,11 @@
 
 free_error:
 	usb_free_urb(urb);
-error:
+put_error:
 	if (ret) /* otherwise this is done in the completion handler */
 		kref_put(&dev->kref, diag_bridge_delete);
+error:
+	mutex_unlock(&dev->ifc_mutex);
 	return ret;
 }
 EXPORT_SYMBOL(diag_bridge_read);
@@ -210,24 +224,34 @@
 
 	pr_debug("writing %d bytes", size);
 
-	if (!dev || !dev->ifc) {
+	if (!dev) {
 		pr_err("device is disconnected");
 		return -ENODEV;
 	}
 
+	mutex_lock(&dev->ifc_mutex);
+	if (!dev->ifc) {
+		ret = -ENODEV;
+		goto error;
+	}
+
 	if (!dev->ops) {
 		pr_err("bridge is not open");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto error;
 	}
 
 	if (!size) {
 		dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto error;
 	}
 
 	/* if there was a previous unrecoverable error, just quit */
-	if (dev->err)
-		return -ENODEV;
+	if (dev->err) {
+		ret = -ENODEV;
+		goto error;
+	}
 
 	kref_get(&dev->kref);
 
@@ -235,7 +259,7 @@
 	if (!urb) {
 		dev_err(&dev->ifc->dev, "unable to allocate urb\n");
 		ret = -ENOMEM;
-		goto error;
+		goto put_error;
 	}
 
 	ret = usb_autopm_get_interface(dev->ifc);
@@ -262,9 +286,11 @@
 
 free_error:
 	usb_free_urb(urb);
-error:
+put_error:
 	if (ret) /* otherwise this is done in the completion handler */
 		kref_put(&dev->kref, diag_bridge_delete);
+error:
+	mutex_unlock(&dev->ifc_mutex);
 	return ret;
 }
 EXPORT_SYMBOL(diag_bridge_write);
@@ -381,6 +407,7 @@
 	dev->udev = usb_get_dev(interface_to_usbdev(ifc));
 	dev->ifc = ifc;
 	kref_init(&dev->kref);
+	mutex_init(&dev->ifc_mutex);
 	init_usb_anchor(&dev->submitted);
 
 	ifc_desc = ifc->cur_altsetting;
@@ -422,7 +449,9 @@
 	dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
 
 	platform_device_unregister(dev->pdev);
+	mutex_lock(&dev->ifc_mutex);
 	dev->ifc = NULL;
+	mutex_unlock(&dev->ifc_mutex);
 	diag_bridge_debugfs_cleanup();
 	kref_put(&dev->kref, diag_bridge_delete);
 	usb_set_intfdata(ifc, NULL);
diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c
index be8b58b..8753c0d 100644
--- a/drivers/usb/misc/ks_bridge.c
+++ b/drivers/usb/misc/ks_bridge.c
@@ -441,8 +441,13 @@
 
 	pr_debug("status:%d actual:%d", urb->status, urb->actual_length);
 
+	/*non zero len of data received while unlinking urb*/
+	if (urb->status == -ENOENT && urb->actual_length > 0)
+		goto add_to_list;
+
 	if (urb->status < 0) {
-		if (urb->status != -ESHUTDOWN && urb->status != -ENOENT)
+		if (urb->status != -ESHUTDOWN && urb->status != -ENOENT
+				&& urb->status != -EPROTO)
 			pr_err_ratelimited("urb failed with err:%d",
 					urb->status);
 		ksb_free_data_pkt(pkt);
@@ -456,6 +461,7 @@
 		goto resubmit_urb;
 	}
 
+add_to_list:
 	spin_lock(&ksb->lock);
 	pkt->len = urb->actual_length;
 	list_add_tail(&pkt->list, &ksb->to_ks_list);
@@ -588,6 +594,7 @@
 	ksb->fs_dev = (struct miscdevice *)id->driver_info;
 	misc_register(ksb->fs_dev);
 
+	ifc->needs_remote_wakeup = 1;
 	usb_enable_autosuspend(ksb->udev);
 
 	pr_debug("usb dev connected");
@@ -601,7 +608,7 @@
 
 	dbg_log_event(ksb, "SUSPEND", 0, 0);
 
-	pr_info("read cnt: %d", ksb->alloced_read_pkts);
+	pr_debug("read cnt: %d", ksb->alloced_read_pkts);
 
 	usb_kill_anchored_urbs(&ksb->submitted);
 
@@ -650,6 +657,7 @@
 	spin_unlock_irqrestore(&ksb->lock, flags);
 
 	misc_deregister(ksb->fs_dev);
+	ifc->needs_remote_wakeup = 0;
 	usb_put_dev(ksb->udev);
 	ksb->ifc = NULL;
 	usb_set_intfdata(ifc, NULL);
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index 59ae13b..c78fd0c 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -990,10 +990,10 @@
 	}
 
 	ch_id--;
-	ctrl_bridge_disconnect(ch_id);
+	ctrl_bridge_disconnect(dev->id);
 	platform_device_unregister(dev->pdev);
 	usb_set_intfdata(intf, NULL);
-	__dev[ch_id] = NULL;
+	__dev[dev->id] = NULL;
 
 	cancel_work_sync(&dev->process_rx_w);
 	cancel_work_sync(&dev->kevent);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 65ddd4c..5637f19 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -67,6 +67,8 @@
 #define USB_PHY_VDD_DIG_VOL_MIN	1045000 /* uV */
 #define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */
 
+#define USB_SUSPEND_DELAY_TIME	(500 * HZ/1000) /* 500 msec */
+
 static DECLARE_COMPLETION(pmic_vbus_init);
 static struct msm_otg *the_msm_otg;
 static bool debug_aca_enabled;
@@ -686,7 +688,8 @@
 	if (aca_enabled())
 		return 0;
 
-	if (atomic_read(&motg->in_lpm) == suspend)
+	if (atomic_read(&motg->in_lpm) == suspend &&
+		!atomic_read(&motg->suspend_work_pending))
 		return 0;
 
 	if (suspend) {
@@ -705,7 +708,9 @@
 			if (!(motg->caps & ALLOW_LPM_ON_DEV_SUSPEND))
 				break;
 			set_bit(A_BUS_SUSPEND, &motg->inputs);
-			queue_work(system_nrt_wq, &motg->sm_work);
+			atomic_set(&motg->suspend_work_pending, 1);
+			queue_delayed_work(system_nrt_wq, &motg->suspend_work,
+				USB_SUSPEND_DELAY_TIME);
 			break;
 
 		default:
@@ -1039,6 +1044,7 @@
 static int msm_otg_notify_chg_type(struct msm_otg *motg)
 {
 	static int charger_type;
+
 	/*
 	 * TODO
 	 * Unify OTG driver charger types and power supply charger types
@@ -1061,7 +1067,14 @@
 	else
 		charger_type = POWER_SUPPLY_TYPE_BATTERY;
 
-	return pm8921_set_usb_power_supply_type(charger_type);
+	if (!psy) {
+		pr_err("No USB power supply registered!\n");
+		return -EINVAL;
+	}
+
+	pr_debug("setting usb power supply type %d\n", charger_type);
+	power_supply_set_supply_type(psy, charger_type);
+	return 0;
 }
 
 static int msm_otg_notify_power_supply(struct msm_otg *motg, unsigned mA)
@@ -2744,6 +2757,14 @@
 		queue_work(system_nrt_wq, &motg->sm_work);
 }
 
+static void msm_otg_suspend_work(struct work_struct *w)
+{
+	struct msm_otg *motg =
+		container_of(w, struct msm_otg, suspend_work.work);
+	atomic_set(&motg->suspend_work_pending, 0);
+	msm_otg_sm_work(&motg->sm_work);
+}
+
 static irqreturn_t msm_otg_irq(int irq, void *data)
 {
 	struct msm_otg *motg = data;
@@ -3429,6 +3450,11 @@
 		pdata = msm_otg_dt_to_pdata(pdev);
 		if (!pdata)
 			return -ENOMEM;
+
+		pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+		if (!pdata->bus_scale_table)
+			dev_dbg(&pdev->dev, "bus scaling is disabled\n");
+
 		ret = msm_otg_setup_devices(pdev, pdata->mode, true);
 		if (ret) {
 			dev_err(&pdev->dev, "devices setup failed\n");
@@ -3616,6 +3642,7 @@
 	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
 	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
 	INIT_DELAYED_WORK(&motg->pmic_id_status_work, msm_pmic_id_status_w);
+	INIT_DELAYED_WORK(&motg->suspend_work, msm_otg_suspend_work);
 	setup_timer(&motg->id_timer, msm_otg_id_timer_func,
 				(unsigned long) motg);
 	ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
@@ -3778,6 +3805,7 @@
 	msm_otg_debugfs_cleanup();
 	cancel_delayed_work_sync(&motg->chg_work);
 	cancel_delayed_work_sync(&motg->pmic_id_status_work);
+	cancel_delayed_work_sync(&motg->suspend_work);
 	cancel_work_sync(&motg->sm_work);
 
 	pm_runtime_resume(&pdev->dev);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 70685e7..6e3567f 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -53,7 +53,7 @@
 u32 mdp_max_clk = 200000000;
 
 static struct platform_device *mdp_init_pdev;
-static struct regulator *footswitch;
+static struct regulator *footswitch, *dsi_pll_vdda, *dsi_pll_vddio;
 static unsigned int mdp_footswitch_on;
 
 struct completion mdp_ppp_comp;
@@ -1537,6 +1537,7 @@
 				mdp_clk_disable_unprepare();
 		}
 	}
+	pr_debug("%s: on=%d cnt=%d\n", __func__, on, mdp_clk_cnt);
 	mutex_unlock(&mdp_suspend_mutex);
 }
 
@@ -2060,8 +2061,10 @@
 	int ret = 0;
 	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
 
+	pr_debug("%s:+\n", __func__);
 	mdp_histogram_ctrl_all(FALSE);
 
+	mdp_clk_ctrl(1);
 	if (mfd->panel.type == MIPI_CMD_PANEL)
 		mdp4_dsi_cmd_off(pdev);
 	else if (mfd->panel.type == MIPI_VIDEO_PANEL)
@@ -2074,9 +2077,11 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	ret = panel_next_off(pdev);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	mdp_clk_ctrl(0);
 
 	if (mdp_rev >= MDP_REV_41 && mfd->panel.type == MIPI_CMD_PANEL)
 		mdp_dsi_cmd_overlay_suspend(mfd);
+	pr_debug("%s:-\n", __func__);
 	return ret;
 }
 
@@ -2097,6 +2102,8 @@
 	struct msm_fb_data_type *mfd;
 	mfd = platform_get_drvdata(pdev);
 
+	pr_debug("%s:+\n", __func__);
+
 	if (mdp_rev >= MDP_REV_40) {
 		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 		mdp_clk_ctrl(1);
@@ -2126,8 +2133,8 @@
 	ret = panel_next_on(pdev);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
-
 	mdp_histogram_ctrl_all(TRUE);
+	pr_debug("%s:-\n", __func__);
 
 	return ret;
 }
@@ -2237,18 +2244,40 @@
 	}
 	disable_irq(mdp_irq);
 
+	dsi_pll_vdda = regulator_get(&pdev->dev, "dsi_pll_vdda");
+	if (IS_ERR(dsi_pll_vdda)) {
+		dsi_pll_vdda = NULL;
+	} else {
+		if (mdp_rev == MDP_REV_42 || mdp_rev == MDP_REV_44) {
+			ret = regulator_set_voltage(dsi_pll_vdda, 1200000,
+				1200000);
+			if (ret) {
+				pr_err("set_voltage failed for dsi_pll_vdda, ret=%d\n",
+					ret);
+			}
+		}
+	}
+
+	dsi_pll_vddio = regulator_get(&pdev->dev, "dsi_pll_vddio");
+	if (IS_ERR(dsi_pll_vddio)) {
+		dsi_pll_vddio = NULL;
+	} else {
+		if (mdp_rev == MDP_REV_42) {
+			ret = regulator_set_voltage(dsi_pll_vddio, 1800000,
+				1800000);
+			if (ret) {
+				pr_err("set_voltage failed for dsi_pll_vddio, ret=%d\n",
+					ret);
+			}
+		}
+	}
+
 	footswitch = regulator_get(&pdev->dev, "vdd");
-	if (IS_ERR(footswitch))
+	if (IS_ERR(footswitch)) {
 		footswitch = NULL;
-	else {
+	} else {
 		regulator_enable(footswitch);
 		mdp_footswitch_on = 1;
-
-		if (mdp_rev == MDP_REV_42 && !cont_splashScreen) {
-			regulator_disable(footswitch);
-			msleep(20);
-			regulator_enable(footswitch);
-		}
 	}
 
 	mdp_clk = clk_get(&pdev->dev, "core_clk");
@@ -2299,6 +2328,17 @@
 
 	MSM_FB_DEBUG("mdp_clk: mdp_clk=%d\n", (int)clk_get_rate(mdp_clk));
 #endif
+
+	if (mdp_rev == MDP_REV_42 && !cont_splashScreen) {
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		/* DSI Video Timing generator disable */
+		outpdw(MDP_BASE + 0xE0000, 0x0);
+		/* Clear MDP Interrupt Enable register */
+		outpdw(MDP_BASE + 0x50, 0x0);
+		/* Set Overlay Proc 0 to reset state */
+		outpdw(MDP_BASE + 0x10004, 0x3);
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
 	return 0;
 }
 
@@ -2317,6 +2357,7 @@
 	struct mipi_panel_info *mipi;
 #endif
 	static int contSplash_update_done;
+	char *cp;
 
 	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
 		mdp_init_pdev = pdev;
@@ -2391,7 +2432,44 @@
 	if (mdp_pdata) {
 		if (mdp_pdata->cont_splash_enabled) {
 			mfd->cont_splash_done = 0;
+
 			if (!contSplash_update_done) {
+				uint32 bpp = 3;
+				/*read panel wxh and calculate splash screen
+				size*/
+				mdp_pdata->splash_screen_size =
+						inpdw(MDP_BASE + 0x90004);
+				mdp_pdata->splash_screen_size =
+				(((mdp_pdata->splash_screen_size >> 16) &
+					0x00000FFF) * (
+					mdp_pdata->splash_screen_size &
+					0x00000FFF)) * bpp;
+
+				mdp_pdata->splash_screen_addr =
+						inpdw(MDP_BASE + 0x90008);
+
+				mfd->copy_splash_buf = dma_alloc_coherent(NULL,
+					mdp_pdata->splash_screen_size,
+					(dma_addr_t *) &(mfd->copy_splash_phys),
+					GFP_KERNEL);
+
+				if (!mfd->copy_splash_buf) {
+					pr_err("DMA ALLOC FAILED for SPLASH\n");
+					return -ENOMEM;
+				}
+				cp = (char *)ioremap(
+						mdp_pdata->splash_screen_addr,
+						mdp_pdata->splash_screen_size);
+				if (!cp) {
+					pr_err("IOREMAP FAILED for SPLASH\n");
+					return -ENOMEM;
+				}
+				memcpy(mfd->copy_splash_buf, cp,
+					mdp_pdata->splash_screen_size);
+
+				MDP_OUTP(MDP_BASE + 0x90008,
+						mfd->copy_splash_phys);
+
 				if (mfd->panel.type == MIPI_VIDEO_PANEL ||
 				    mfd->panel.type == LCDC_PANEL)
 					mdp_pipe_ctrl(MDP_CMD_BLOCK,
@@ -2767,6 +2845,17 @@
 		return;
 	}
 
+	if (dsi_pll_vddio)
+		regulator_enable(dsi_pll_vddio);
+
+	if (dsi_pll_vdda)
+		regulator_enable(dsi_pll_vdda);
+
+	mipi_dsi_prepare_clocks();
+	mipi_dsi_ahb_ctrl(1);
+	mipi_dsi_phy_ctrl(1);
+	mipi_dsi_clk_enable();
+
 	if (on && !mdp_footswitch_on) {
 		pr_debug("Enable MDP FS\n");
 		regulator_enable(footswitch);
@@ -2777,9 +2866,31 @@
 		mdp_footswitch_on = 0;
 	}
 
+	mipi_dsi_clk_disable();
+	mipi_dsi_phy_ctrl(0);
+	mipi_dsi_ahb_ctrl(0);
+	mipi_dsi_unprepare_clocks();
+
+	if (dsi_pll_vdda)
+		regulator_disable(dsi_pll_vdda);
+
+	if (dsi_pll_vddio)
+		regulator_disable(dsi_pll_vddio);
+
 	mutex_unlock(&mdp_suspend_mutex);
 }
 
+void mdp_free_splash_buffer(struct msm_fb_data_type *mfd)
+{
+	if (mfd->copy_splash_buf) {
+		dma_free_coherent(NULL,	mdp_pdata->splash_screen_size,
+			mfd->copy_splash_buf,
+			(dma_addr_t) mfd->copy_splash_phys);
+
+		mfd->copy_splash_buf = NULL;
+	}
+}
+
 #ifdef CONFIG_PM
 static void mdp_suspend_sub(void)
 {
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index af5a661..1397507 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -24,7 +24,7 @@
 #include <linux/msm_mdp.h>
 #include <linux/memory_alloc.h>
 #include <mach/hardware.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #ifdef CONFIG_MSM_BUS_SCALING
 #include <mach/msm_bus.h>
@@ -764,7 +764,7 @@
 int mdp_lcdc_on(struct platform_device *pdev);
 int mdp_lcdc_off(struct platform_device *pdev);
 void mdp_lcdc_update(struct msm_fb_data_type *mfd);
-
+void mdp_free_splash_buffer(struct msm_fb_data_type *mfd);
 #ifdef CONFIG_FB_MSM_MDP303
 int mdp_dsi_video_on(struct platform_device *pdev);
 int mdp_dsi_video_off(struct platform_device *pdev);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 054741f..6fc83df 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -480,7 +480,7 @@
 			struct mdp4_overlay_pipe *pipe);
 void mdp4_dmae_done_dtv(void);
 void mdp4_dtv_wait4vsync(int cndx, long long *vtime);
-void mdp4_dtv_vsync_ctrl(int cndx, int enable);
+void mdp4_dtv_vsync_ctrl(struct fb_info *info, int enable);
 void mdp4_dtv_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
 #else
 static inline void mdp4_overlay_dtv_start(void)
@@ -516,7 +516,7 @@
 {
     /* empty */
 }
-static inline void mdp4_dtv_vsync_ctrl(int cndx, long long *vtime)
+static inline void mdp4_dtv_vsync_ctrl(struct fb_info *info, int enable)
 {
     /* empty */
 }
@@ -548,7 +548,7 @@
 int mdp4_atv_off(struct platform_device *pdev);
 void mdp4_dsi_video_fxn_register(cmd_fxn_t fxn);
 void mdp4_dsi_video_overlay(struct msm_fb_data_type *mfd);
-void mdp4_lcdc_vsync_ctrl(int cndx, int enable);
+void mdp4_lcdc_vsync_ctrl(struct fb_info *info, int enable);
 void mdp4_overlay0_done_dsi_video(int cndx);
 void mdp4_overlay0_done_dsi_cmd(int cndx);
 void mdp4_primary_rdptr(void);
@@ -570,8 +570,8 @@
 void mdp4_mixer_blend_setup(int mixer);
 void mdp4_mixer_blend_cfg(int);
 struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage);
-void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
-void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe, int commit);
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe, int commit);
 void mdp4_mixer_pipe_cleanup(int mixer);
 int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
 void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
@@ -773,8 +773,8 @@
 void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime);
 void mdp4_dsi_cmd_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
 void mdp4_dsi_video_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
-void mdp4_dsi_cmd_vsync_ctrl(int cndx, int enable);
-void mdp4_dsi_video_vsync_ctrl(int cndx, int enable);
+void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info, int enable);
+void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable);
 #ifdef CONFIG_FB_MSM_MDP303
 static inline void mdp4_dsi_cmd_del_timer(void)
 {
@@ -822,10 +822,12 @@
 			struct mdp4_overlay_pipe *pipe)
 {
 }
-static inline void mdp4_dsi_cmd_vsync_ctrl(int cndx, int enable)
+static inline void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info,
+				int enable)
 {
 }
-static inline void mdp4_dsi_video_vsync_ctrl(int cndx, int enable)
+static inline void mdp4_dsi_video_vsync_ctrl(struct fb_info *info,
+				int enable)
 {
 }
 
@@ -923,6 +925,9 @@
 int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd,
 				struct mdp4_overlay_pipe *plist);
 void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, int flag);
+int mdp4_update_base_blend(struct msm_fb_data_type *mfd,
+				struct mdp_blend_cfg *mdp_blend_cfg);
+u32 mdp4_get_mixer_num(u32 panel_type);
 
 #ifndef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
 static inline void mdp4_writeback_dma_busy_wait(struct msm_fb_data_type *mfd)
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index c07b3a7..63f0aa1 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1652,7 +1652,7 @@
 }
 
 
-void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe, int commit)
 {
 	struct mdp4_overlay_pipe *pp;
 	int i, mixer;
@@ -1668,9 +1668,12 @@
 	}
 
 	ctrl->stage[mixer][pipe->mixer_stage] = pipe;	/* keep it */
+
+	if (commit)
+		mdp4_mixer_stage_commit(mixer);
 }
 
-void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe, int commit)
 {
 	struct mdp4_overlay_pipe *pp;
 	int i, mixer;
@@ -1683,7 +1686,8 @@
 			ctrl->stage[mixer][i] = NULL;  /* clear it */
 	}
 
-	mdp4_mixer_stage_commit(mixer);
+	if (commit || (mixer > 0 && !hdmi_prim_display))
+		mdp4_mixer_stage_commit(mixer);
 }
 /*
  * mixer0: rgb3: border color at register 0x15004, 0x15008
@@ -1744,7 +1748,7 @@
 
 	mdp4_overlay_reg_flush(bspipe, 1);
 	/* borderfill pipe as base layer */
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 }
 
 void mdp4_overlay_borderfill_stage_down(struct mdp4_overlay_pipe *pipe)
@@ -1798,13 +1802,13 @@
 
 	/* free borderfill pipe */
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp4_mixer_stage_down(pipe);
+	mdp4_mixer_stage_down(pipe, 0); /* commit will happen for bspipe up */
 	mdp4_overlay_pipe_free(pipe);
 
 	/* stage up base layer */
 	mdp4_overlay_reg_flush(bspipe, 1);
 	/* restore original base layer */
-	mdp4_mixer_stage_up(bspipe);
+	mdp4_mixer_stage_up(bspipe, 1);
 }
 
 
@@ -1926,7 +1930,7 @@
 	int i, off, ptype, alpha_drop = 0;
 	int d_alpha, s_alpha;
 	unsigned char *overlay_base;
-	uint32 c0, c1, c2;
+	uint32 c0, c1, c2, base_premulti;
 
 
 	d_pipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
@@ -1936,6 +1940,8 @@
 	}
 
 	blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE0];
+	base_premulti = ctrl->blend[mixer][MDP4_MIXER_STAGE_BASE].op &
+		MDP4_BLEND_FG_ALPHA_BG_CONST;
 	for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
 		blend->solidfill = 0;
 		blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
@@ -1976,9 +1982,13 @@
 		} else if (s_alpha) {
 			if (!alpha_drop) {
 				blend->op = MDP4_BLEND_BG_ALPHA_FG_PIXEL;
-				if (!(s_pipe->flags & MDP_BLEND_FG_PREMULT))
+				if ((!(s_pipe->flags & MDP_BLEND_FG_PREMULT)) &&
+						((i != MDP4_MIXER_STAGE0) ||
+							(!base_premulti)))
 					blend->op |=
 						MDP4_BLEND_FG_ALPHA_FG_PIXEL;
+				else
+					blend->fg_alpha = 0xff;
 			} else
 				blend->op = MDP4_BLEND_BG_ALPHA_FG_CONST;
 
@@ -1988,9 +1998,14 @@
 			if (ptype == OVERLAY_TYPE_VIDEO) {
 				blend->op = (MDP4_BLEND_FG_ALPHA_BG_PIXEL |
 					MDP4_BLEND_FG_INV_ALPHA);
-				if (!(s_pipe->flags & MDP_BLEND_FG_PREMULT))
+				if ((!(s_pipe->flags & MDP_BLEND_FG_PREMULT)) &&
+						((i != MDP4_MIXER_STAGE0) ||
+							(!base_premulti)))
 					blend->op |=
 						MDP4_BLEND_BG_ALPHA_BG_PIXEL;
+				else
+					blend->fg_alpha = 0xff;
+
 				blend->co3_sel = 0; /* use bg alpha */
 			} else {
 				/* s_pipe is rgb without alpha */
@@ -2463,6 +2478,11 @@
 		mfd->panel_info.type == MIPI_CMD_PANEL) ?
 		mfd->panel_info.mipi.dsi_pclk_rate :
 		mfd->panel_info.clk_rate;
+
+	if (mfd->panel_info.type == LVDS_PANEL &&
+		mfd->panel_info.lvds.channel_mode == LVDS_DUAL_CHANNEL_MODE)
+		pclk = pclk << 1;
+
 	if (!pclk) {
 		pipe->req_clk = mdp_max_clk;
 		pr_err("%s panel pixel clk is zero!\n", __func__);
@@ -2569,7 +2589,8 @@
 	 * required(FIR).
 	 */
 	if ((mfd->panel_info.lcdc.v_back_porch <= 4) &&
-	    (pipe->src_h != pipe->dst_h)) {
+	    (pipe->src_h != pipe->dst_h) &&
+	    (mfd->panel_info.lcdc.v_back_porch)) {
 		u32 clk = 0;
 		clk = 4 * (pclk >> shift) / mfd->panel_info.lcdc.v_back_porch;
 		clk <<= shift;
@@ -3080,7 +3101,7 @@
 			continue;
 		pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
 		mdp4_overlay_reg_flush(pipe, 1);
-		mdp4_mixer_stage_down(pipe);
+		mdp4_mixer_stage_down(pipe, 1);
 		mdp4_overlay_pipe_free(pipe);
 		cnt++;
 	}
@@ -3126,7 +3147,7 @@
 	}
 
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp4_mixer_stage_down(pipe);
+	mdp4_mixer_stage_down(pipe, 0);
 
 	if (pipe->mixer_num == MDP4_MIXER0) {
 		if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
@@ -3174,13 +3195,13 @@
 
 	if (!hdmi_prim_display && info->node == 0) {
 		if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
-			mdp4_dsi_video_vsync_ctrl(0, cmd);
+			mdp4_dsi_video_vsync_ctrl(info, cmd);
 		else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
-			mdp4_dsi_cmd_vsync_ctrl(0, cmd);
+			mdp4_dsi_cmd_vsync_ctrl(info, cmd);
 		else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
-			mdp4_lcdc_vsync_ctrl(0, cmd);
+			mdp4_lcdc_vsync_ctrl(info, cmd);
 	} else if (hdmi_prim_display || info->node == 1)
-		mdp4_dtv_vsync_ctrl(0, cmd);
+		mdp4_dtv_vsync_ctrl(info, cmd);
 
 	return 0;
 }
@@ -3253,7 +3274,7 @@
 	pr_debug("%s: pipe=%x ndx=%d num=%d used=%d\n", __func__,
 		(int) pipe, pipe->pipe_ndx, pipe->pipe_num, pipe->pipe_used);
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 }
 
 int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req)
@@ -3430,7 +3451,7 @@
 		mdp4_overlay_rgb_setup(pipe);	/* rgb pipe */
 	}
 
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 
 	if (pipe->mixer_num == MDP4_MIXER2) {
 		ctrl->mixer2_played++;
@@ -3589,7 +3610,7 @@
 void mdp4_v4l2_overlay_clear(struct mdp4_overlay_pipe *pipe)
 {
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp4_mixer_stage_down(pipe);
+	mdp4_mixer_stage_down(pipe, 1);
 	mdp4_overlay_pipe_free(pipe);
 }
 
@@ -3652,8 +3673,9 @@
 	if (ctrl->panel_mode & MDP4_PANEL_LCDC)
 		mdp4_overlay_reg_flush(pipe, 1);
 
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0); /* mixer stage commit commits this */
 	mdp4_mixer_stage_commit(pipe->mixer_num);
+
 #ifdef V4L2_VSYNC
 	/*
 	 * TODO: incorporate v4l2 into vsycn driven mechanism
@@ -3679,3 +3701,22 @@
 	mutex_unlock(&mfd->dma->ov_mutex);
 	return err;
 }
+int mdp4_update_base_blend(struct msm_fb_data_type *mfd,
+			struct mdp_blend_cfg *mdp_blend_cfg)
+{
+	int ret = 0;
+	u32 mixer_num;
+	struct blend_cfg *blend;
+	mixer_num = mdp4_get_mixer_num(mfd->panel_info.type);
+	if (!ctrl)
+		return -EPERM;
+	blend = &ctrl->blend[mixer_num][MDP4_MIXER_STAGE_BASE];
+	if (mdp_blend_cfg->is_premultiplied) {
+		blend->bg_alpha = 0xFF;
+		blend->op = MDP4_BLEND_FG_ALPHA_BG_CONST;
+	} else {
+		blend->op = MDP4_BLEND_FG_ALPHA_FG_PIXEL;
+		blend->bg_alpha = 0;
+	}
+	return ret;
+}
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index c133831..e67b244 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -115,8 +115,10 @@
 	mdp4_overlayproc_cfg(pipe);
 
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp4_mixer_stage_up(pipe);
+
+	mdp4_mixer_stage_up(pipe, 0);
 	mdp4_mixer_stage_commit(pipe->mixer_num);
+
 	if (ret == 0)
 		mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
@@ -139,7 +141,7 @@
 
 	/* dis-engage rgb2 from mixer1 */
 	if (atv_pipe) {
-		mdp4_mixer_stage_down(atv_pipe);
+		mdp4_mixer_stage_down(atv_pipe, 1);
 		mdp4_iommu_unmap(atv_pipe);
 	}
 
@@ -185,8 +187,9 @@
 	mdp4_overlay_mdp_perf_req(pipe, mfd);
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 	mdp4_overlay_rgb_setup(pipe);
+
 	mdp4_overlay_reg_flush(pipe, 0);
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 	mdp4_mixer_stage_commit(pipe->mixer_num);
 	printk(KERN_INFO "mdp4_atv_overlay: pipe=%x ndx=%d\n",
 					(int)pipe, pipe->pipe_ndx);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 6f78305..3320d11 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -39,7 +39,7 @@
 static int vsync_start_y_adjust = 4;
 
 #define MAX_CONTROLLER	1
-#define VSYNC_EXPIRE_TICK 4
+#define VSYNC_EXPIRE_TICK 8
 
 static struct vsycn_ctrl {
 	struct device *dev;
@@ -58,7 +58,7 @@
 	int blt_change;
 	int blt_free;
 	int blt_end;
-	int fake_vsync;
+	int uevent;
 	struct mutex update_lock;
 	struct completion ov_comp;
 	struct completion dmap_comp;
@@ -70,6 +70,7 @@
 	int vsync_enabled;
 	int clk_enabled;
 	int clk_control;
+	int new_update;
 	ktime_t vsync_time;
 	struct work_struct vsync_work;
 	struct work_struct clk_work;
@@ -293,7 +294,7 @@
 		/* Blt */
 		if (vctrl->blt_wait)
 			need_dmap_wait = 1;
-		else if (vctrl->ov_koff != vctrl->ov_done) {
+		if (vctrl->ov_koff != vctrl->ov_done) {
 			INIT_COMPLETION(vctrl->ov_comp);
 			need_ov_wait = 1;
 		}
@@ -379,26 +380,59 @@
 	return cnt;
 }
 
-void mdp4_dsi_cmd_vsync_ctrl(int cndx, int enable)
-{
-	struct vsycn_ctrl *vctrl;
+static void mdp4_overlay_update_dsi_cmd(struct msm_fb_data_type *mfd);
 
-	if (cndx >= MAX_CONTROLLER) {
-		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
-		return;
-	}
+void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info, int enable)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct vsycn_ctrl *vctrl;
+	unsigned long flags;
+	int clk_set_on = 0;
+	int cndx = 0;
 
 	vctrl = &vsync_ctrl_db[cndx];
 
-	if (enable && vctrl->fake_vsync) {
-		vctrl->fake_vsync = 0;
-		schedule_work(&vctrl->vsync_work);
+	pr_debug("%s: clk_enabled=%d vsycn_enabeld=%d req=%d\n", __func__,
+		vctrl->clk_enabled, vctrl->vsync_enabled, enable);
+
+	mutex_lock(&vctrl->update_lock);
+
+	if (vctrl->vsync_enabled == enable) {
+		mutex_unlock(&vctrl->update_lock);
+		return;
 	}
 
-	if (vctrl->vsync_enabled == enable)
-		return;
-
 	vctrl->vsync_enabled = enable;
+
+	if (enable) {
+		if (vctrl->clk_enabled == 0) {
+			pr_debug("%s: SET_CLK_ON\n", __func__);
+			mipi_dsi_clk_cfg(1);
+			mdp_clk_ctrl(1);
+			vctrl->clk_enabled = 1;
+			clk_set_on = 1;
+		}
+		spin_lock_irqsave(&vctrl->spin_lock, flags);
+		vctrl->clk_control = 0;
+		vctrl->expire_tick = 0;
+		vctrl->uevent = 1;
+		vctrl->new_update = 1;
+		if (clk_set_on) {
+			vsync_irq_enable(INTR_PRIMARY_RDPTR,
+						MDP_PRIM_RDPTR_TERM);
+		}
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+		mdp4_overlay_update_dsi_cmd(mfd);
+	} else {
+		spin_lock_irqsave(&vctrl->spin_lock, flags);
+		vctrl->clk_control = 1;
+		vctrl->uevent = 0;
+		if (vctrl->clk_enabled)
+			vctrl->expire_tick = VSYNC_EXPIRE_TICK;
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+	}
+	mutex_unlock(&vctrl->update_lock);
 }
 
 void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
@@ -479,13 +513,21 @@
 	pr_debug("%s: ISR, cpu=%d\n", __func__, smp_processor_id());
 	vctrl->rdptr_intr_tot++;
 	vctrl->vsync_time = ktime_get();
-	schedule_work(&vctrl->vsync_work);
 
 	spin_lock(&vctrl->spin_lock);
+	if (vctrl->uevent)
+		schedule_work(&vctrl->vsync_work);
+
 	if (vctrl->wait_vsync_cnt) {
 		complete(&vctrl->vsync_comp);
 		vctrl->wait_vsync_cnt = 0;
 	}
+
+	if (vctrl->expire_tick) {
+		vctrl->expire_tick--;
+		if (vctrl->expire_tick == 0)
+			schedule_work(&vctrl->clk_work);
+	}
 	spin_unlock(&vctrl->spin_lock);
 }
 
@@ -578,16 +620,19 @@
 {
 	struct vsycn_ctrl *vctrl =
 		container_of(work, typeof(*vctrl), clk_work);
+	unsigned long flags;
 
 	mutex_lock(&vctrl->update_lock);
-	if (vctrl->clk_control) {
-		if (vctrl->clk_enabled) {
-			mdp_clk_ctrl(0);
-			vctrl->clk_enabled = 0;
-			vctrl->fake_vsync = 1;
-		}
+	if (vctrl->clk_control && vctrl->clk_enabled) {
+		pr_debug("%s: SET_CLK_OFF\n", __func__);
+		mdp_clk_ctrl(0);
+		mipi_dsi_clk_cfg(0);
+		spin_lock_irqsave(&vctrl->spin_lock, flags);
+		vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
+		vctrl->clk_enabled = 0;
+		vctrl->clk_control = 0;
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 	}
-
 	mutex_unlock(&vctrl->update_lock);
 }
 
@@ -746,7 +791,7 @@
 	pipe->srcp0_addr = (uint32)src;
 }
 
-void mdp4_overlay_update_dsi_cmd(struct msm_fb_data_type *mfd)
+static void mdp4_overlay_update_dsi_cmd(struct msm_fb_data_type *mfd)
 {
 	int ptype;
 	struct mdp4_overlay_pipe *pipe;
@@ -760,30 +805,31 @@
 
 	vctrl = &vsync_ctrl_db[cndx];
 
-	/* MDP cmd block enable */
-	mdp_clk_ctrl(1);
+	if (vctrl->base_pipe == NULL) {
+		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
+		if (ptype < 0)
+			printk(KERN_INFO "%s: format2type failed\n", __func__);
+		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0);
+		if (pipe == NULL) {
+			printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
+			return;
+		}
+		pipe->pipe_used++;
+		pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
+		pipe->mixer_num  = MDP4_MIXER0;
+		pipe->src_format = mfd->fb_imgType;
+		mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_DSI_CMD);
+		ret = mdp4_overlay_format2pipe(pipe);
+		if (ret < 0)
+			printk(KERN_INFO "%s: format2type failed\n", __func__);
 
-	ptype = mdp4_overlay_format2type(mfd->fb_imgType);
-	if (ptype < 0)
-		printk(KERN_INFO "%s: format2type failed\n", __func__);
-	pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0);
-	if (pipe == NULL) {
-		printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
-		return;
+		vctrl->base_pipe = pipe; /* keep it */
+		mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
+		pipe->ov_blt_addr = 0;
+		pipe->dma_blt_addr = 0;
+	} else {
+		pipe = vctrl->base_pipe;
 	}
-	pipe->pipe_used++;
-	pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
-	pipe->mixer_num  = MDP4_MIXER0;
-	pipe->src_format = mfd->fb_imgType;
-	mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_DSI_CMD);
-	ret = mdp4_overlay_format2pipe(pipe);
-	if (ret < 0)
-		printk(KERN_INFO "%s: format2type failed\n", __func__);
-
-	vctrl->base_pipe = pipe; /* keep it */
-	mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
-	pipe->ov_blt_addr = 0;
-	pipe->dma_blt_addr = 0;
 
 	MDP_OUTP(MDP_BASE + 0x021c, 10); /* read pointer */
 
@@ -795,14 +841,13 @@
 	/* disable dsi trigger */
 	MDP_OUTP(MDP_BASE + 0x000a4, 0x00);
 
-
 	mdp4_overlay_setup_pipe_addr(mfd, pipe);
 
 	mdp4_overlay_rgb_setup(pipe);
 
 	mdp4_overlay_reg_flush(pipe, 1);
 
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 
 	mdp4_overlayproc_cfg(pipe);
 
@@ -810,9 +855,7 @@
 
 	mdp4_overlay_dmap_cfg(mfd, 0);
 
-	mdp4_mixer_stage_commit(pipe->mixer_num);
-	/* MDP cmd block disable */
-	mdp_clk_ctrl(0);
+	wmb();
 }
 
 /* 3D side by side */
@@ -880,7 +923,7 @@
 
 	mdp4_overlay_reg_flush(pipe, 1);
 
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 
 	mdp4_overlayproc_cfg(pipe);
 
@@ -916,7 +959,7 @@
 	struct msm_fb_data_type *mfd;
 	struct vsycn_ctrl *vctrl;
 
-	pr_info("%s+:\n", __func__);
+	pr_debug("%s+:\n", __func__);
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
@@ -925,15 +968,13 @@
 	vctrl->dev = mfd->fbi->dev;
 
 	mdp_clk_ctrl(1);
-	vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
-
-	if (vctrl->base_pipe == NULL)
-		mdp4_overlay_update_dsi_cmd(mfd);
+	mdp4_overlay_update_dsi_cmd(mfd);
+	mdp_clk_ctrl(0);
 
 	mdp4_iommu_attach();
 
 	atomic_set(&vctrl->suspend, 0);
-	pr_info("%s-:\n", __func__);
+	pr_debug("%s-:\n", __func__);
 
 
 	return ret;
@@ -947,7 +988,7 @@
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
 
-	pr_info("%s+:\n", __func__);
+	pr_debug("%s+:\n", __func__);
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
@@ -962,15 +1003,29 @@
 
 	/* sanity check, free pipes besides base layer */
 	mdp4_overlay_unset_mixer(pipe->mixer_num);
-	mdp4_mixer_stage_down(pipe);
+	mdp4_mixer_stage_down(pipe, 1);
 	mdp4_overlay_pipe_free(pipe);
 	vctrl->base_pipe = NULL;
 
-	vctrl->fake_vsync = 1;
+	if (vctrl->clk_enabled) {
+		/*
+		 * in case of suspend, vsycn_ctrl off is not
+		 * received from frame work which left clock on
+		 * then, clock need to be turned off here
+		 */
+		mdp_clk_ctrl(0);
+	}
+
+	vctrl->clk_enabled = 0;
+	vctrl->vsync_enabled = 0;
+	vctrl->clk_control = 0;
+	vctrl->expire_tick = 0;
+	vctrl->uevent = 0;
 
 	vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
 
-	pr_info("%s-:\n", __func__);
+
+	pr_debug("%s-:\n", __func__);
 
 	/*
 	 * footswitch off
@@ -1001,7 +1056,7 @@
 			mdp4_overlay_unset_mixer(pipe->mixer_num);
 			vctrl->base_pipe = NULL;
 		} else {
-			mdp4_mixer_stage_down(pipe);
+			mdp4_mixer_stage_down(pipe, 1);
 			mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 1);
 		}
 	}
@@ -1012,6 +1067,7 @@
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	unsigned long flags;
 	long long xx;
 
 	vctrl = &vsync_ctrl_db[cndx];
@@ -1019,13 +1075,31 @@
 	if (!mfd->panel_power_on)
 		return;
 
-	vctrl->clk_control = 0;
 	pipe = vctrl->base_pipe;
 	if (pipe == NULL) {
 		pr_err("%s: NO base pipe\n", __func__);
 		return;
 	}
 
+	mutex_lock(&vctrl->update_lock);
+	if (!vctrl->clk_enabled) {
+		pr_err("%s: mdp clocks disabled\n", __func__);
+		mutex_unlock(&vctrl->update_lock);
+		return;
+
+	}
+	mutex_unlock(&vctrl->update_lock);
+
+	spin_lock_irqsave(&vctrl->spin_lock, flags);
+	if (vctrl->expire_tick) {
+		/*
+		 * in the middle of shutting clocks down
+		 * delay to allow pan display to go through
+		 */
+		vctrl->expire_tick = VSYNC_EXPIRE_TICK;
+	}
+	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
 	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE) {
 		mdp4_mipi_vsync_enable(mfd, pipe, 0);
 		mdp4_overlay_setup_pipe_addr(mfd, pipe);
@@ -1033,13 +1107,12 @@
 	}
 
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
+
 	mutex_lock(&mfd->dma->ov_mutex);
 	mdp4_dsi_cmd_pipe_commit();
 	mutex_unlock(&mfd->dma->ov_mutex);
 
 	mdp4_dsi_cmd_wait4vsync(0, &xx);
-	vctrl->expire_tick = VSYNC_EXPIRE_TICK;
-	vctrl->clk_control = 1;
 
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 }
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index a461c3b..fcdccca 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -256,14 +256,10 @@
 	return cnt;
 }
 
-void mdp4_dsi_video_vsync_ctrl(int cndx, int enable)
+void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable)
 {
 	struct vsycn_ctrl *vctrl;
-
-	if (cndx >= MAX_CONTROLLER) {
-		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
-		return;
-	}
+	int cndx = 0;
 
 	vctrl = &vsync_ctrl_db[cndx];
 
@@ -557,8 +553,10 @@
 	mdp4_overlayproc_cfg(pipe);
 
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp4_mixer_stage_up(pipe);
+
+	mdp4_mixer_stage_up(pipe, 0);
 	mdp4_mixer_stage_commit(pipe->mixer_num);
+
 	/*
 	 * DSI timing setting
 	 */
@@ -646,6 +644,8 @@
 	struct msm_fb_data_type *mfd;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	unsigned long flags;
+	int need_wait = 0;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 	vctrl = &vsync_ctrl_db[cndx];
@@ -653,8 +653,16 @@
 
 	atomic_set(&vctrl->suspend, 1);
 
-	while (vctrl->wait_vsync_cnt)
-		msleep(20);	/* >= 17 ms */
+	msleep(20);	/* >= 17 ms */
+
+	if (pipe->ov_blt_addr) {
+		spin_lock_irqsave(&vctrl->spin_lock, flags);
+		if (vctrl->ov_koff != vctrl->ov_done)
+			need_wait = 1;
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+		if (need_wait)
+			mdp4_dsi_video_wait4ov(0);
+	}
 
 	mdp_histogram_ctrl_all(FALSE);
 
@@ -672,7 +680,7 @@
 			vctrl->base_pipe = NULL;
 		} else {
 			/* system suspending */
-			mdp4_mixer_stage_down(vctrl->base_pipe);
+			mdp4_mixer_stage_down(vctrl->base_pipe, 1);
 			mdp4_overlay_iommu_pipe_free(
 				vctrl->base_pipe->pipe_ndx, 1);
 		}
@@ -776,7 +784,7 @@
 
 	mdp4_overlay_reg_flush(pipe, 1);
 
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 
 	mdp4_mixer_stage_commit(pipe->mixer_num);
 
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index e131369..f3bd775 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -238,14 +238,10 @@
 	return cnt;
 }
 
-void mdp4_dtv_vsync_ctrl(int cndx, int enable)
+void mdp4_dtv_vsync_ctrl(struct fb_info *info, int enable)
 {
 	struct vsycn_ctrl *vctrl;
-
-	if (cndx >= MAX_CONTROLLER) {
-		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
-		return;
-	}
+	int cndx = 0;
 
 	vctrl = &vsync_ctrl_db[cndx];
 
@@ -586,7 +582,7 @@
 			/* pipe == rgb2 */
 			vctrl->base_pipe = NULL;
 		} else {
-			mdp4_mixer_stage_down(pipe);
+			mdp4_mixer_stage_down(pipe, 1);
 			mdp4_overlay_pipe_free(pipe);
 			vctrl->base_pipe = NULL;
 		}
@@ -730,8 +726,9 @@
 	}
 
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 	mdp4_mixer_stage_commit(pipe->mixer_num);
+
 	vctrl->base_pipe = pipe; /* keep it */
 }
 
@@ -901,7 +898,8 @@
 	temp_src_format = inpdw(rgb_base + 0x0050);
 	MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
 	mdp4_overlay_reg_flush(vctrl->base_pipe, 1);
-	mdp4_mixer_stage_up(vctrl->base_pipe);
+
+	mdp4_mixer_stage_up(vctrl->base_pipe, 0);
 	mdp4_mixer_stage_commit(vctrl->base_pipe->mixer_num);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index a2fabca..323a8fe 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -260,14 +260,10 @@
 	return cnt;
 }
 
-void mdp4_lcdc_vsync_ctrl(int cndx, int enable)
+void mdp4_lcdc_vsync_ctrl(struct fb_info *info, int enable)
 {
 	struct vsycn_ctrl *vctrl;
-
-	if (cndx >= MAX_CONTROLLER) {
-		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
-		return;
-	}
+	int cndx = 0;
 
 	vctrl = &vsync_ctrl_db[cndx];
 
@@ -530,7 +526,7 @@
 	mdp4_overlayproc_cfg(pipe);
 
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 
 
 	/*
@@ -635,6 +631,8 @@
 	struct msm_fb_data_type *mfd;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	unsigned long flags;
+	int need_wait = 0;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 	vctrl = &vsync_ctrl_db[cndx];
@@ -642,8 +640,16 @@
 
 	atomic_set(&vctrl->suspend, 1);
 
-	while (vctrl->wait_vsync_cnt)
-		msleep(20);	/* >= 17 ms */
+	msleep(20);	/* >= 17 ms */
+
+	if (pipe->ov_blt_addr) {
+		spin_lock_irqsave(&vctrl->spin_lock, flags);
+		if (vctrl->ov_koff != vctrl->ov_done)
+			need_wait = 1;
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+		if (need_wait)
+			mdp4_lcdc_wait4ov(0);
+	}
 
 	mdp_histogram_ctrl_all(FALSE);
 
@@ -661,7 +667,7 @@
 			vctrl->base_pipe = NULL;
 		} else {
 			/* system suspending */
-			mdp4_mixer_stage_down(vctrl->base_pipe);
+			mdp4_mixer_stage_down(vctrl->base_pipe, 1);
 			mdp4_overlay_iommu_pipe_free(
 				vctrl->base_pipe->pipe_ndx, 1);
 		}
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index e6ff9ef..be4a89a 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -236,7 +236,7 @@
 
 	mdp4_overlay_rgb_setup(pipe);
 
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 1);
 
 	mdp4_overlayproc_cfg(pipe);
 
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index 940aea8..487e5d5 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -181,7 +181,7 @@
 	else
 		pipe->srcp0_addr = (uint32)(buf + buf_offset);
 
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(pipe, 0);
 
 	mdp4_overlayproc_cfg(pipe);
 	mdp4_mixer_stage_commit(pipe->mixer_num);
@@ -276,6 +276,9 @@
 
 	writeback_pipe->ov_blt_addr = (ulong) (node ? node->addr : NULL);
 
+	/* free previous iommu at freelist back to pool */
+	mdp4_overlay_iommu_unmap_freelist(writeback_pipe->mixer_num);
+
 	if (!writeback_pipe->ov_blt_addr) {
 		pr_err("%s: no writeback buffer 0x%x, %p\n", __func__,
 			(unsigned int)writeback_pipe->ov_blt_addr, node);
@@ -292,6 +295,9 @@
 
 	mdp4_writeback_overlay_kickoff(mfd, pipe);
 
+	/* move current committed iommu to freelist */
+	mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
+
 	mutex_lock(&mfd->writeback_mutex);
 	list_add_tail(&node->active_entry, &mfd->writeback_busy_queue);
 	mutex_unlock(&mfd->writeback_mutex);
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 34ae716..359f37e 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -3091,3 +3091,16 @@
 error:
 	return ret;
 }
+u32 mdp4_get_mixer_num(u32 panel_type)
+{
+	u32 mixer_num;
+	if ((panel_type == TV_PANEL) ||
+			(panel_type == DTV_PANEL))
+		mixer_num = MDP4_MIXER1;
+	else if (panel_type == WRITEBACK_PANEL) {
+		mixer_num = MDP4_MIXER2;
+	} else {
+		mixer_num = MDP4_MIXER0;
+	}
+	return mixer_num;
+}
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index df57ee1..4b76e72 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -519,6 +519,8 @@
 		return;
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
+	if (!enable)
+		INIT_COMPLETION(vsync_cntrl.vsync_wait);
 	vsync_cntrl.vsync_irq_enabled = enable;
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
@@ -532,7 +534,6 @@
 		mdp_enable_irq(MDP_VSYNC_TERM);
 		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	} else {
-		INIT_COMPLETION(vsync_cntrl.vsync_wait);
 		wait_for_completion(&vsync_cntrl.vsync_wait);
 		mdp_disable_irq(MDP_VSYNC_TERM);
 	}
diff --git a/drivers/video/msm/mdp_dma_dsi_video.c b/drivers/video/msm/mdp_dma_dsi_video.c
index 09ae82f..a1f2b65 100644
--- a/drivers/video/msm/mdp_dma_dsi_video.c
+++ b/drivers/video/msm/mdp_dma_dsi_video.c
@@ -254,6 +254,8 @@
 		return;
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
+	if (!enable)
+		INIT_COMPLETION(vsync_cntrl.vsync_wait);
 	vsync_cntrl.vsync_irq_enabled = enable;
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
@@ -266,7 +268,6 @@
 		mdp_enable_irq(MDP_VSYNC_TERM);
 		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	} else {
-		INIT_COMPLETION(vsync_cntrl.vsync_wait);
 		wait_for_completion(&vsync_cntrl.vsync_wait);
 		mdp_disable_irq(MDP_VSYNC_TERM);
 	}
diff --git a/drivers/video/msm/mdp_dma_lcdc.c b/drivers/video/msm/mdp_dma_lcdc.c
index e1b78c2..10d60ab 100644
--- a/drivers/video/msm/mdp_dma_lcdc.c
+++ b/drivers/video/msm/mdp_dma_lcdc.c
@@ -335,6 +335,8 @@
 		return;
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
+	if (!enable)
+		INIT_COMPLETION(vsync_cntrl.vsync_wait);
 	vsync_cntrl.vsync_irq_enabled = enable;
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 
@@ -347,7 +349,6 @@
 		mdp_enable_irq(MDP_VSYNC_TERM);
 		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	} else {
-		INIT_COMPLETION(vsync_cntrl.vsync_wait);
 		wait_for_completion(&vsync_cntrl.vsync_wait);
 		mdp_disable_irq(MDP_VSYNC_TERM);
 	}
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 6bc21bc..ddb6dd9 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -16,4 +16,5 @@
 
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_tx.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_util.o
+obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_edid.o
 obj-$(CONFIG_FB_MSM_MDSS_WRITEBACK) += mdss_wb.o
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 886e8de..6f42565 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -14,6 +14,8 @@
 #ifndef MDSS_H
 #define MDSS_H
 
+#include <linux/msm_ion.h>
+#include <linux/msm_mdp.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
@@ -52,24 +54,26 @@
 
 	u32 mdp_irq_mask;
 
-	u32 clk_ena;
 	u32 suspend;
 	u32 timeout;
 
-	u32 fs_ena;
-	u32 vsync_ena;
+	u8 clk_ena;
+	u8 fs_ena;
+	u8 vsync_ena;
+	u8 eintf_ena;
 
-	u32 intf;
-	u32 eintf_ena;
 	u32 prim_ptype;
 	u32 res_init;
-	u32 pdev_lcnt;
 	u32 bus_hdl;
 
 	u32 smp_mb_cnt;
 	u32 smp_mb_size;
 	u32 *pipe_type_map;
 	u32 *mixer_type_map;
+
+	struct ion_client *iclient;
+	int iommu_domain;
+	int iommu_attached;
 };
 extern struct mdss_data_type *mdss_res;
 
@@ -91,4 +95,29 @@
 void mdss_enable_irq(struct mdss_hw *hw);
 void mdss_disable_irq(struct mdss_hw *hw);
 void mdss_disable_irq_nosync(struct mdss_hw *hw);
+
+static inline struct ion_client *mdss_get_ionclient(void)
+{
+	if (!mdss_res)
+		return NULL;
+	return mdss_res->iclient;
+}
+
+static inline int is_mdss_iommu_attached(void)
+{
+	if (!mdss_res)
+		return false;
+	return mdss_res->iommu_attached;
+}
+
+static inline int mdss_get_iommu_domain(void)
+{
+	if (!mdss_res)
+		return -ENODEV;
+
+	return mdss_res->iommu_domain;
+}
+
+int mdss_iommu_attach(void);
+int mdss_iommu_dettach(void);
 #endif /* MDSS_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 8c61be9..e685785 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -27,7 +27,6 @@
 static struct mdss_dsi_drv_pdata dsi_drv;
 
 static unsigned char *mdss_dsi_base;
-static unsigned char *mmss_cc_base;
 
 static int mdss_dsi_regulator_init(struct platform_device *pdev)
 {
@@ -170,6 +169,14 @@
 {
 	int ret = 0;
 	struct mdss_panel_info *pinfo;
+	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 -EINVAL;
+	}
 
 	pinfo = &pdata->panel_info;
 
@@ -178,7 +185,7 @@
 
 	mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
 
-	ret = dsi_drv.off(pdata);
+	ret = ctrl_pdata->off(pdata);
 	if (ret) {
 		pr_err("%s: Panel OFF failed\n", __func__);
 		return ret;
@@ -188,7 +195,7 @@
 	mdss_dsi_clk_disable(pdata);
 
 	/* disable dsi engine */
-	MIPI_OUTP(mdss_dsi_base + 0x0004, 0);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, 0);
 
 	spin_unlock_bh(&dsi_clk_lock);
 
@@ -214,14 +221,22 @@
 	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
 	u32 ystride, bpp, data;
 	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) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
 
 	pinfo = &pdata->panel_info;
 
-	MIPI_OUTP(mdss_dsi_base + 0x118, 1);
-	MIPI_OUTP(mdss_dsi_base + 0x118, 0);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x118, 1);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x118, 0);
 
-	mdss_dsi_phy_sw_reset(pdata);
-	mdss_dsi_phy_enable(pdata, 1);
+	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
+	mdss_dsi_phy_enable((ctrl_pdata->ctrl_base), 1);
 	mdss_dsi_phy_init(pdata);
 
 	mdss_dsi_prepare_clocks();
@@ -248,20 +263,20 @@
 		dummy_xres = pdata->panel_info.lcdc.xres_pad;
 		dummy_yres = pdata->panel_info.lcdc.yres_pad;
 
-		MIPI_OUTP(mdss_dsi_base + 0x24,
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24,
 			((hspw + hbp + width + dummy_xres) << 16 |
 			(hspw + hbp)));
-		MIPI_OUTP(mdss_dsi_base + 0x28,
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x28,
 			((vspw + vbp + height + dummy_yres) << 16 |
 			(vspw + vbp)));
-		MIPI_OUTP(mdss_dsi_base + 0x2C,
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
 			(vspw + vbp + height + dummy_yres +
 				vfp - 1) << 16 | (hspw + hbp +
 				width + dummy_xres + hfp - 1));
 
-		MIPI_OUTP(mdss_dsi_base + 0x30, (hspw << 16));
-		MIPI_OUTP(mdss_dsi_base + 0x34, 0);
-		MIPI_OUTP(mdss_dsi_base + 0x38, (vspw << 16));
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x30, (hspw << 16));
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x34, 0);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x38, (vspw << 16));
 
 	} else {		/* command mode */
 		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
@@ -277,13 +292,13 @@
 
 		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
 		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
-		MIPI_OUTP(mdss_dsi_base + 0x60, data);
-		MIPI_OUTP(mdss_dsi_base + 0x58, data);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x60, data);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data);
 
 		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
 		data = height << 16 | width;
-		MIPI_OUTP(mdss_dsi_base + 0x64, data);
-		MIPI_OUTP(mdss_dsi_base + 0x5C, data);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, data);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data);
 	}
 
 	mdss_dsi_host_init(mipi, pdata);
@@ -291,9 +306,9 @@
 	if (mipi->force_clk_lane_hs) {
 		u32 tmp;
 
-		tmp = MIPI_INP(mdss_dsi_base + 0xac);
+		tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac);
 		tmp |= (1<<28);
-		MIPI_OUTP(mdss_dsi_base + 0xac, tmp);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp);
 		wmb();
 	}
 
@@ -303,7 +318,7 @@
 		return ret;
 	}
 
-	ret = dsi_drv.on(pdata);
+	ret = ctrl_pdata->on(pdata);
 	if (ret) {
 		pr_err("%s: unable to initialize the panel\n", __func__);
 		return ret;
@@ -315,16 +330,6 @@
 	return ret;
 }
 
-unsigned char *mdss_dsi_get_base_adr(void)
-{
-	return mdss_dsi_base;
-}
-
-unsigned char *mdss_dsi_get_clk_base(void)
-{
-	return mmss_cc_base;
-}
-
 static int mdss_dsi_resource_initialized;
 
 static int __devinit mdss_dsi_probe(struct platform_device *pdev)
@@ -351,35 +356,17 @@
 			}
 		}
 
-		mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		if (!mdss_dsi_mres) {
-			pr_err("%s:%d unable to get the MDSS resources",
-				       __func__, __LINE__);
-			return -ENOMEM;
-		}
-		if (mdss_dsi_mres) {
-			mmss_cc_base = ioremap(mdss_dsi_mres->start,
-				resource_size(mdss_dsi_mres));
-			if (!mmss_cc_base) {
-				pr_err("%s:%d unable to remap dsi resources",
-					       __func__, __LINE__);
-				return -ENOMEM;
-			}
-		}
-
 		rc = mdss_dsi_regulator_init(pdev);
 		if (rc) {
 			dev_err(&pdev->dev,
 				"%s: failed to init regulator, rc=%d\n",
 							__func__, rc);
 			iounmap(mdss_dsi_base);
-			iounmap(mmss_cc_base);
 			return rc;
 		}
 
 		if (mdss_dsi_clk_init(pdev)) {
 			iounmap(mdss_dsi_base);
-			iounmap(mmss_cc_base);
 			return -EPERM;
 		}
 
@@ -390,7 +377,6 @@
 				"%s: failed to add child nodes, rc=%d\n",
 							__func__, rc);
 			iounmap(mdss_dsi_base);
-			iounmap(mmss_cc_base);
 			return rc;
 		}
 
@@ -415,13 +401,14 @@
 struct device dsi_dev;
 
 int dsi_panel_device_register(struct platform_device *pdev,
-			      struct mdss_panel_common_pdata *panel_data)
+			      struct mdss_panel_common_pdata *panel_data,
+			      char backlight_ctrl)
 {
 	struct mipi_panel_info *mipi;
 	int rc;
 	u8 lanes = 0, bpp;
 	u32 h_period, v_period, dsi_pclk_rate;
-	struct mdss_panel_data *pdata = NULL;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
 	h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
 			+ (panel_data->panel_info.lcdc.h_back_porch)
@@ -487,35 +474,34 @@
 		dsi_pclk_rate = 35000000;
 	mipi->dsi_pclk_rate = dsi_pclk_rate;
 
-	dsi_drv.on = panel_data->on;
-	dsi_drv.off = panel_data->off;
-
-	/*
-	 * data chain
-	 */
-	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-	if (!pdata)
+	ctrl_pdata = devm_kzalloc(&pdev->dev,
+		sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
+	if (!ctrl_pdata)
 		return -ENOMEM;
 
-	pdata->on = mdss_dsi_on;
-	pdata->off = mdss_dsi_off;
-	memcpy(&(pdata->panel_info), &(panel_data->panel_info),
-	       sizeof(struct mdss_panel_info));
+	(ctrl_pdata->panel_data).on = mdss_dsi_on;
+	(ctrl_pdata->panel_data).off = mdss_dsi_off;
+	memcpy(&((ctrl_pdata->panel_data).panel_info),
+				&(panel_data->panel_info),
+				       sizeof(struct mdss_panel_info));
 
-	pdata->dsi_base = mdss_dsi_base;
-	pdata->mmss_cc_base = mmss_cc_base;
-	pdata->set_backlight = panel_data->bl_ctrl;
-
+	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->bl_ctrl) = backlight_ctrl;
 	/*
 	 * register in mdp driver
 	 */
-	rc = mdss_register_panel(pdata);
+	rc = mdss_register_panel(&(ctrl_pdata->panel_data));
 	if (rc) {
 		dev_err(&pdev->dev, "unable to register MIPI DSI panel\n");
-		devm_kfree(&pdev->dev, pdata);
+		devm_kfree(&pdev->dev, ctrl_pdata);
 		return rc;
 	}
 
+	ctrl_pdata->on = panel_data->on;
+	ctrl_pdata->off = panel_data->off;
+
 	pr_debug("%s: Panal data initialized\n", __func__);
 	return 0;
 }
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 6acb8d5..e6fd910 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -80,6 +80,7 @@
 	BL_PWM,
 	BL_WLED,
 	BL_DCS_CMD,
+	UNKNOWN_CTRL,
 };
 
 #define DSI_NON_BURST_SYNCH_PULSE	0
@@ -247,18 +248,26 @@
 	struct mdss_panel_info panel_info;
 	int (*on) (struct mdss_panel_data *pdata);
 	int (*off) (struct mdss_panel_data *pdata);
-	void (*bl_ctrl) (u32 bl_level);
+	void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
 };
 
 struct mdss_dsi_drv_pdata {
 	struct regulator *vdd_vreg;
 	struct regulator *vdd_io_vreg;
 	struct regulator *dsi_vreg;
+};
+
+struct mdss_dsi_ctrl_pdata {
 	int (*on) (struct mdss_panel_data *pdata);
 	int (*off) (struct mdss_panel_data *pdata);
+	struct mdss_panel_data panel_data;
+	unsigned char *ctrl_base;
+	char bl_ctrl;
 };
+
 int dsi_panel_device_register(struct platform_device *pdev,
-			      struct mdss_panel_common_pdata *panel_data);
+			      struct mdss_panel_common_pdata *panel_data,
+			      char bl_ctrl);
 
 char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
 char *mdss_dsi_buf_init(struct dsi_buf *dp);
@@ -271,7 +280,7 @@
 int mdss_dsi_cmd_dma_tx(struct dsi_buf *dp,
 				struct mdss_panel_data *pdata);
 int mdss_dsi_cmd_reg_tx(u32 data,
-				struct mdss_panel_data *pdata);
+				unsigned char *ctrl_base);
 int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
 			struct dsi_buf *tp, struct dsi_buf *rp,
 			struct dsi_cmd_desc *cmds, int len);
@@ -293,6 +302,7 @@
 void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);
 
 irqreturn_t mdss_dsi_isr(int irq, void *ptr);
+void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
 
 void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata);
 int mdss_dsi_clk_div_config(u8 bpp, u8 lanes,
@@ -301,10 +311,9 @@
 void mdss_dsi_clk_deinit(struct device *dev);
 void mdss_dsi_prepare_clocks(void);
 void mdss_dsi_unprepare_clocks(void);
-unsigned char *mdss_dsi_get_base_adr(void);
 void mdss_dsi_panel_reset(int enable);
-void mdss_dsi_phy_enable(struct mdss_panel_data *pdata, int on);
+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(struct mdss_panel_data *pdata);
+void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base);
 
 #endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index a9cf61e..e47891e 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -21,6 +21,8 @@
 #include <linux/slab.h>
 #include <linux/iopoll.h>
 
+#include <mach/iommu_domains.h>
+
 #include "mdss.h"
 #include "mdss_dsi.h"
 
@@ -46,6 +48,11 @@
 	spin_lock_init(&dsi_clk_lock);
 }
 
+void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+	mdss_dsi_hw.ptr = (void *)(ctrl_pdata);
+}
+
 void mdss_dsi_enable_irq(void)
 {
 	unsigned long flags;
@@ -56,6 +63,7 @@
 		spin_unlock_irqrestore(&dsi_irq_lock, flags);
 		return;
 	}
+
 	mdss_enable_irq(&mdss_dsi_hw);
 	dsi_irq_enabled = 1;
 	/* TO DO: Check whether MDSS IRQ is enabled */
@@ -654,6 +662,14 @@
 {
 	u32 dsi_ctrl, intr_ctrl;
 	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) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
 
 	pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
 
@@ -674,7 +690,7 @@
 		data |= ((pinfo->traffic_mode & 0x03) << 8);
 		data |= ((pinfo->dst_format & 0x03) << 4); /* 2 bits */
 		data |= (pinfo->vc & 0x03);
-		MIPI_OUTP((pdata->dsi_base) + 0x0010, data);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0010, data);
 
 		data = 0;
 		data |= ((pinfo->rgb_swap & 0x07) << 12);
@@ -684,7 +700,7 @@
 			data |= BIT(4);
 		if (pinfo->r_sel)
 			data |= BIT(0);
-		MIPI_OUTP((pdata->dsi_base) + 0x0020, data);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0020, data);
 	} else if (pinfo->mode == DSI_CMD_MODE) {
 		data = 0;
 		data |= ((pinfo->interleave_max & 0x0f) << 20);
@@ -696,7 +712,7 @@
 		if (pinfo->r_sel)
 			data |= BIT(4);
 		data |= (pinfo->dst_format & 0x0f);	/* 4 bits */
-		MIPI_OUTP((pdata->dsi_base) + 0x003c, data);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x003c, data);
 
 		/* DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL */
 		data = pinfo->wr_mem_continue & 0x0ff;
@@ -704,7 +720,7 @@
 		data |= (pinfo->wr_mem_start & 0x0ff);
 		if (pinfo->insert_dcs_cmd)
 			data |= BIT(16);
-		MIPI_OUTP((pdata->dsi_base) + 0x0044, data);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0044, data);
 	} else
 		pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode);
 
@@ -727,7 +743,7 @@
 
 	/* from frame buffer, low power mode */
 	/* DSI_COMMAND_MODE_DMA_CTRL */
-	MIPI_OUTP((pdata->dsi_base) + 0x3C, 0x14000000);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x3C, 0x14000000);
 
 	data = 0;
 	if (pinfo->te_sel)
@@ -735,59 +751,82 @@
 	data |= pinfo->mdp_trigger << 4;/* cmd mdp trigger */
 	data |= pinfo->dma_trigger;	/* cmd dma trigger */
 	data |= (pinfo->stream & 0x01) << 8;
-	MIPI_OUTP((pdata->dsi_base) + 0x0084, data); /* DSI_TRIG_CTRL */
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0084,
+				data); /* DSI_TRIG_CTRL */
 
 	/* DSI_LAN_SWAP_CTRL */
-	MIPI_OUTP((pdata->dsi_base) + 0x00b0, pinfo->dlane_swap);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x00b0, pinfo->dlane_swap);
 
 	/* clock out ctrl */
 	data = pinfo->t_clk_post & 0x3f;	/* 6 bits */
 	data <<= 8;
 	data |= pinfo->t_clk_pre & 0x3f;	/*  6 bits */
 	/* DSI_CLKOUT_TIMING_CTRL */
-	MIPI_OUTP((pdata->dsi_base) + 0xc4, data);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xc4, data);
 
 	data = 0;
 	if (pinfo->rx_eot_ignore)
 		data |= BIT(4);
 	if (pinfo->tx_eot_append)
 		data |= BIT(0);
-	MIPI_OUTP((pdata->dsi_base) + 0x00cc, data); /* DSI_EOT_PACKET_CTRL */
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x00cc,
+				data); /* DSI_EOT_PACKET_CTRL */
 
 
 	/* allow only ack-err-status  to generate interrupt */
 	/* DSI_ERR_INT_MASK0 */
-	MIPI_OUTP((pdata->dsi_base) + 0x010c, 0x13ff3fe0);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x010c, 0x13ff3fe0);
 
 	intr_ctrl |= DSI_INTR_ERROR_MASK;
-	MIPI_OUTP((pdata->dsi_base) + 0x0110, intr_ctrl); /* DSI_INTL_CTRL */
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110,
+				intr_ctrl); /* DSI_INTL_CTRL */
 
 	/* turn esc, byte, dsi, pclk, sclk, hclk on */
-	MIPI_OUTP((pdata->dsi_base) + 0x11c, 0x23f); /* DSI_CLK_CTRL */
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x11c,
+					0x23f); /* DSI_CLK_CTRL */
 
 	dsi_ctrl |= BIT(0);	/* enable dsi */
-	MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
 
 	wmb();
 }
 
 void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata)
 {
-	u32 data = MIPI_INP((pdata->dsi_base) + 0x3c);
+	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) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+	data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x3c);
 
 	if (mode == 0)
 		data &= ~BIT(26);
 	else
 		data |= BIT(26);
 
-	MIPI_OUTP((pdata->dsi_base) + 0x3c, data);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x3c, data);
 }
 
 void mdss_dsi_sw_reset(struct mdss_panel_data *pdata)
 {
-	MIPI_OUTP((pdata->dsi_base) + 0x118, 0x01);
+	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;
+	}
+
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x118, 0x01);
 	wmb();
-	MIPI_OUTP((pdata->dsi_base) + 0x118, 0x00);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x118, 0x00);
 	wmb();
 }
 
@@ -799,38 +838,54 @@
 	u32 status;
 	u32 sleep_us = 1000;
 	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) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
 
 	/* Check for CMD_MODE_DMA_BUSY */
-	if (readl_poll_timeout(((pdata->dsi_base) + 0x0008),
+	if (readl_poll_timeout(((ctrl_pdata->ctrl_base) + 0x0008),
 			   status,
 			   ((status & 0x02) == 0),
 			       sleep_us, timeout_us))
 		pr_info("%s: DSI status=%x failed\n", __func__, status);
 
 	/* Check for x_HS_FIFO_EMPTY */
-	if (readl_poll_timeout(((pdata->dsi_base) + 0x000c),
+	if (readl_poll_timeout(((ctrl_pdata->ctrl_base) + 0x000c),
 			   status,
 			   ((status & 0x11111000) == 0x11111000),
 			       sleep_us, timeout_us))
 		pr_info("%s: FIFO status=%x failed\n", __func__, status);
 
-	dsi_ctrl = MIPI_INP((pdata->dsi_base) + 0x0004);
+	dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
 	if (enable)
 		dsi_ctrl |= 0x01;
 	else
 		dsi_ctrl &= ~0x01;
 
-	MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
 	wmb();
 }
 
 void mdss_dsi_op_mode_config(int mode,
 			     struct mdss_panel_data *pdata)
 {
-
 	u32 dsi_ctrl, intr_ctrl;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	dsi_ctrl = MIPI_INP((pdata->dsi_base) + 0x0004);
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+	if (!ctrl_pdata) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+
+	dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
 	dsi_ctrl &= ~0x07;
 	if (mode == DSI_VIDEO_MODE) {
 		dsi_ctrl |= 0x03;
@@ -843,8 +898,9 @@
 
 	pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
 
-	MIPI_OUTP((pdata->dsi_base) + 0x0110, intr_ctrl); /* DSI_INTL_CTRL */
-	MIPI_OUTP((pdata->dsi_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();
 }
 
@@ -863,23 +919,31 @@
 {
 	u32 status;
 	int timeout_us = 10000;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	MIPI_OUTP((pdata->dsi_base) + 0x098, 0x01);	/* trigger */
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+	if (!ctrl_pdata) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x098, 0x01);	/* trigger */
 	wmb();
 
 	/* Check for CMD_MODE_DMA_BUSY */
-	if (readl_poll_timeout(((pdata->dsi_base) + 0x0008),
+	if (readl_poll_timeout(((ctrl_pdata->ctrl_base) + 0x0008),
 				status, ((status & 0x0010) == 0),
 				0, timeout_us))
 		pr_info("%s: DSI status=%x failed\n", __func__, status);
 
-	mdss_dsi_ack_err_status((pdata->dsi_base));
+	mdss_dsi_ack_err_status((ctrl_pdata->ctrl_base));
 
 	pr_debug("%s: BTA done, status = %d\n", __func__, status);
 }
 
 int mdss_dsi_cmd_reg_tx(u32 data,
-			struct mdss_panel_data *pdata)
+			unsigned char *ctrl_base)
 {
 	int i;
 	char *bp;
@@ -891,14 +955,14 @@
 
 	pr_debug("\n");
 
-	MIPI_OUTP((pdata->dsi_base) + 0x0084, 0x04);/* sw trigger */
-	MIPI_OUTP((pdata->dsi_base) + 0x0004, 0x135);
+	MIPI_OUTP(ctrl_base + 0x0084, 0x04);/* sw trigger */
+	MIPI_OUTP(ctrl_base + 0x0004, 0x135);
 
 	wmb();
 
-	MIPI_OUTP((pdata->dsi_base) + 0x03c, data);
+	MIPI_OUTP(ctrl_base + 0x03c, data);
 	wmb();
-	MIPI_OUTP((pdata->dsi_base) + 0x090, 0x01);	/* trigger */
+	MIPI_OUTP(ctrl_base + 0x090, 0x01);	/* trigger */
 	wmb();
 
 	udelay(300);
@@ -917,17 +981,25 @@
 	u32 dsi_ctrl, ctrl;
 	int i, video_mode;
 	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) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
 
 	/* turn on cmd mode
 	* for video mode, do not send cmds more than
 	* one pixel line, since it only transmit it
 	* during BLLP.
 	*/
-	dsi_ctrl = MIPI_INP((pdata->dsi_base) + 0x0004);
+	dsi_ctrl = MIPI_INP((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((pdata->dsi_base) + 0x0004, ctrl);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, ctrl);
 	}
 
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
@@ -952,8 +1024,8 @@
 	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
 
 	if (video_mode)
-		MIPI_OUTP((pdata->dsi_base) + 0x0004, dsi_ctrl); /* restore */
-
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
+					dsi_ctrl); /* restore */
 	return cnt;
 }
 
@@ -984,6 +1056,14 @@
 	int cnt, len, diff, pkt_size;
 	unsigned long flag;
 	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) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
 
 	if (pdata->panel_info.mipi.no_max_pkt_size)
 		rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
@@ -1093,6 +1173,15 @@
 	int len;
 	int i;
 	char *bp;
+	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) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
 
 	bp = tp->data;
 
@@ -1102,26 +1191,43 @@
 
 	pr_debug("\n");
 
-	len = tp->len;
-	len += 3;
-	len &= ~0x03;	/* multipled by 4 */
+	len = ALIGN(tp->len, 4);
+	size = ALIGN(tp->len, SZ_4K);
 
-	tp->dmap = dma_map_single(&dsi_dev, tp->data, len, DMA_TO_DEVICE);
-	if (dma_mapping_error(&dsi_dev, tp->dmap))
+	tp->dmap = dma_map_single(&dsi_dev, tp->data, size, DMA_TO_DEVICE);
+	if (dma_mapping_error(&dsi_dev, tp->dmap)) {
 		pr_err("%s: dmap mapp failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	if (is_mdss_iommu_attached()) {
+		int ret = msm_iommu_map_contig_buffer(tp->dmap,
+					mdss_get_iommu_domain(), 0,
+					size, SZ_4K, 0, &(addr));
+		if (IS_ERR_VALUE(ret)) {
+			pr_err("unable to map dma memory to iommu(%d)\n", ret);
+			return -ENOMEM;
+		}
+	} else {
+		addr = tp->dmap;
+	}
 
 	INIT_COMPLETION(dsi_dma_comp);
 
-	MIPI_OUTP((pdata->dsi_base) + 0x048, tp->dmap);
-	MIPI_OUTP((pdata->dsi_base) + 0x04c, len);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x048, addr);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04c, len);
 	wmb();
 
-	MIPI_OUTP((pdata->dsi_base) + 0x090, 0x01);	/* trigger */
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x090, 0x01);	/* trigger */
 	wmb();
 
 	wait_for_completion(&dsi_dma_comp);
 
-	dma_unmap_single(&dsi_dev, tp->dmap, len, DMA_TO_DEVICE);
+	if (is_mdss_iommu_attached())
+		msm_iommu_unmap_contig_buffer(addr, mdss_get_iommu_domain(),
+					      0, size);
+
+	dma_unmap_single(&dsi_dev, tp->dmap, size, DMA_TO_DEVICE);
 	tp->dmap = 0;
 	return tp->len;
 }
@@ -1131,6 +1237,14 @@
 {
 	u32 *lp, data;
 	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) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
 
 	lp = (u32 *)rp->data;
 	cnt = rlen;
@@ -1145,7 +1259,7 @@
 
 
 	for (i = 0; i < cnt; i++) {
-		data = (u32)MIPI_INP((pdata->dsi_base) + off);
+		data = (u32)MIPI_INP((ctrl_pdata->ctrl_base) + off);
 		*lp++ = ntohl(data);	/* to network byte order */
 		off -= 4;
 		rp->len += sizeof(*lp);
@@ -1228,8 +1342,10 @@
 {
 	u32 isr;
 	unsigned char *dsi_base;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata =
+			(struct mdss_dsi_ctrl_pdata *)ptr;
 
-	dsi_base = mdss_dsi_get_base_adr();
+	dsi_base = ctrl_pdata->ctrl_base;
 	if (!dsi_base)
 		pr_err("%s:%d DSI base adr no Initialized",
 				       __func__, __LINE__);
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index e4b1867..63ad5cc 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -33,7 +33,6 @@
 static int num_of_off_cmds;
 static char *on_cmds, *off_cmds;
 
-static char bl_ctrl;
 DEFINE_LED_TRIGGER(bl_led_trigger);
 
 static struct mdss_dsi_phy_ctrl phy_params;
@@ -78,10 +77,20 @@
 	}
 }
 
-static void mdss_dsi_panel_bl_ctrl(u32 bl_level)
+static void mdss_dsi_panel_bl_ctrl(struct mdss_panel_data *pdata,
+							u32 bl_level)
 {
-	if (bl_ctrl) {
-		switch (bl_ctrl) {
+	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->bl_ctrl) {
+		switch (ctrl_pdata->bl_ctrl) {
 		case BL_WLED:
 			led_trigger_event(bl_led_trigger, bl_level);
 			break;
@@ -139,7 +148,8 @@
 }
 
 static int mdss_panel_parse_dt(struct platform_device *pdev,
-			    struct mdss_panel_common_pdata *panel_data)
+			       struct mdss_panel_common_pdata *panel_data,
+			       char *bl_ctrl)
 {
 	struct device_node *np = pdev->dev.of_node;
 	u32 res[6], tmp;
@@ -236,7 +246,7 @@
 	if (!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;
+		*bl_ctrl = BL_WLED;
 	}
 
 	rc = of_property_read_u32_array(np,
@@ -481,6 +491,7 @@
 	int rc = 0;
 	static struct mdss_panel_common_pdata vendor_pdata;
 	static const char *panel_name;
+	char bl_ctrl = UNKNOWN_CTRL;
 
 	if (pdev->dev.parent == NULL) {
 		pr_err("%s: parent device missing\n", __func__);
@@ -498,15 +509,15 @@
 	else
 		pr_info("%s: Panel Name = %s\n", __func__, panel_name);
 
-	rc = mdss_panel_parse_dt(pdev, &vendor_pdata);
+	rc = mdss_panel_parse_dt(pdev, &vendor_pdata, &bl_ctrl);
 	if (rc)
 		return rc;
 
 	vendor_pdata.on = mdss_dsi_panel_on;
 	vendor_pdata.off = mdss_dsi_panel_off;
-	vendor_pdata.bl_ctrl = mdss_dsi_panel_bl_ctrl;
+	vendor_pdata.bl_fnc = mdss_dsi_panel_bl_ctrl;
 
-	rc = dsi_panel_device_register(pdev, &vendor_pdata);
+	rc = dsi_panel_device_register(pdev, &vendor_pdata, bl_ctrl);
 	if (rc)
 		return rc;
 
@@ -528,8 +539,8 @@
 
 static int __init mdss_dsi_panel_init(void)
 {
-	mdss_dsi_buf_alloc(&dsi_panel_tx_buf, DSI_BUF_SIZE);
-	mdss_dsi_buf_alloc(&dsi_panel_rx_buf, DSI_BUF_SIZE);
+	mdss_dsi_buf_alloc(&dsi_panel_tx_buf, ALIGN(DSI_BUF_SIZE, SZ_4K));
+	mdss_dsi_buf_alloc(&dsi_panel_rx_buf, ALIGN(DSI_BUF_SIZE, SZ_4K));
 
 	return platform_driver_register(&this_driver);
 }
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 1f83b2b..06d8769 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -144,9 +144,9 @@
 	return ret;
 }
 
-static DEVICE_ATTR(mdss_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
+static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
 static struct attribute *mdss_fb_attrs[] = {
-	&dev_attr_mdss_fb_type.attr,
+	&dev_attr_msm_fb_type.attr,
 	NULL,
 };
 
@@ -204,9 +204,6 @@
 	mfd->panel_info.frame_count = 0;
 	mfd->bl_level = 0;
 	mfd->fb_imgType = MDP_RGBA_8888;
-	mfd->iclient = msm_ion_client_create(-1, pdev->name);
-	if (IS_ERR(mfd->iclient))
-		mfd->iclient = NULL;
 
 	mfd->pdev = pdev;
 
@@ -220,6 +217,14 @@
 	if (rc)
 		return rc;
 
+	/*
+	 * todo: Currently mfd keeps a full copy of panel data rather than
+	 *       pointer to it.
+	 *       Following line shares the fbi with panel drivers for their
+	 *       sysfs or any external communications with the panel driver.
+	 */
+	pdata->panel_info.fbi = fbi;
+
 	rc = pm_runtime_set_active(mfd->fbi->dev);
 	if (rc < 0)
 		pr_err("pm_runtime: fail to set active.\n");
@@ -426,7 +431,7 @@
 			return;
 		}
 		mfd->bl_level = bkl_lvl;
-		pdata->set_backlight(mfd->bl_level);
+		pdata->set_backlight(pdata, mfd->bl_level);
 		bl_level_old = mfd->bl_level;
 		mutex_unlock(&mfd->lock);
 	}
@@ -441,7 +446,7 @@
 		if ((pdata) && (pdata->set_backlight)) {
 			mutex_lock(&mfd->lock);
 			mfd->bl_level = unset_bl_level;
-			pdata->set_backlight(mfd->bl_level);
+			pdata->set_backlight(pdata, mfd->bl_level);
 			bl_level_old = unset_bl_level;
 			mutex_unlock(&mfd->lock);
 			bl_updated = 1;
@@ -592,7 +597,7 @@
 	size *= mfd->fb_page;
 
 	if (mfd->index == 0) {
-		struct ion_client *iclient = mfd->iclient;
+		struct ion_client *iclient = mdss_get_ionclient();
 
 		if (iclient) {
 			mfd->ihdl = ion_alloc(iclient, size, SZ_4K,
@@ -606,6 +611,14 @@
 
 			virt = ion_map_kernel(iclient, mfd->ihdl, 0);
 			ion_phys(iclient, mfd->ihdl, &phys, &size);
+
+			if (is_mdss_iommu_attached()) {
+				ion_map_iommu(iclient, mfd->ihdl,
+					      mdss_get_iommu_domain(),
+					      0, SZ_4K, 0, &mfd->iova,
+					      (unsigned long *) &size,
+					      0, 0);
+			}
 		} else {
 			virt = dma_alloc_coherent(NULL, size,
 					(dma_addr_t *) &phys, GFP_KERNEL);
@@ -789,6 +802,20 @@
 	mfd->var_yres = var->yres;
 	mfd->var_pixclock = var->pixclock;
 
+	if (panel_info->type == MIPI_VIDEO_PANEL) {
+		var->reserved[4] = panel_info->mipi.frame_rate;
+	} else {
+		var->reserved[4] = panel_info->clk_rate /
+			((panel_info->lcdc.h_back_porch +
+			  panel_info->lcdc.h_front_porch +
+			  panel_info->lcdc.h_pulse_width +
+			  panel_info->xres) *
+			 (panel_info->lcdc.v_back_porch +
+			  panel_info->lcdc.v_front_porch +
+			  panel_info->lcdc.v_pulse_width +
+			  panel_info->yres));
+	}
+
 	/* id field for fb app  */
 
 	id = (int *)&mfd->panel;
@@ -1110,6 +1137,31 @@
 	return 0;
 }
 
+static int mdss_fb_handle_pp_ioctl(void __user *argp)
+{
+	int ret;
+	struct msmfb_mdp_pp mdp_pp;
+	u32 copyback = 0;
+
+	ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
+	if (ret)
+		return ret;
+
+	switch (mdp_pp.op) {
+	case mdp_op_pa_cfg:
+		ret = mdss_mdp_pa_config(&mdp_pp.data.pa_cfg_data,
+				&copyback);
+		break;
+	default:
+		pr_err("Unsupported request to MDP_PP IOCTL.\n");
+		ret = -EINVAL;
+		break;
+	}
+	if ((ret == 0) && copyback)
+		ret = copy_to_user(argp, &mdp_pp, sizeof(struct msmfb_mdp_pp));
+	return ret;
+}
+
 static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
 			 unsigned long arg)
 {
@@ -1136,6 +1188,10 @@
 			return ret;
 		break;
 
+	case MSMFB_MDP_PP:
+		ret = mdss_fb_handle_pp_ioctl(argp);
+		break;
+
 	default:
 		if (mfd->ioctl_handler)
 			ret = mfd->ioctl_handler(mfd, cmd, argp);
@@ -1208,6 +1264,7 @@
 int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num)
 {
 	struct fb_info *info;
+	struct msm_fb_data_type *mfd;
 
 	if (fb_num > MAX_FBI_LIST)
 		return -EINVAL;
@@ -1216,8 +1273,16 @@
 	if (!info)
 		return -ENOENT;
 
-	*start = info->fix.smem_start;
+	mfd = (struct msm_fb_data_type *)info->par;
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->iova)
+		*start = mfd->iova;
+	else
+		*start = info->fix.smem_start;
 	*len = info->fix.smem_len;
+
 	return 0;
 }
 EXPORT_SYMBOL(mdss_fb_get_phys_info);
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index ab140fe..a10e5e4 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -14,7 +14,7 @@
 #ifndef MDSS_FB_H
 #define MDSS_FB_H
 
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <linux/list.h>
 #include <linux/msm_mdp.h>
 #include <linux/types.h>
@@ -76,8 +76,10 @@
 			     struct mdp_histogram *hist);
 
 	struct ion_handle *ihdl;
+	unsigned long iova;
 	void *cursor_buf;
-	void *cursor_buf_phys;
+	unsigned long cursor_buf_phys;
+	unsigned long cursor_buf_iova;
 
 	u32 bl_level;
 	struct mutex lock;
@@ -89,10 +91,10 @@
 	u32 var_pixclock;
 
 	u32 mdp_fb_page_protection;
-	struct ion_client *iclient;
 
 	struct mdss_mdp_ctl *ctl;
 	struct mdss_mdp_wb *wb;
+	struct list_head overlay_list;
 };
 
 int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
new file mode 100644
index 0000000..f720a2f
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -0,0 +1,1420 @@
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/types.h>
+#include <mach/board.h>
+#include "mdss_hdmi_edid.h"
+
+#define DBC_START_OFFSET 4
+#define HDMI_VSDB_3D_DATA_OFFSET(vsd) \
+	(!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
+
+struct hdmi_edid_sink_data {
+	u32 disp_mode_list[HDMI_VFRMT_MAX];
+	u32 disp_3d_mode_list[HDMI_VFRMT_MAX];
+	u32 disp_multi_3d_mode_list[16];
+	u32 disp_multi_3d_mode_list_cnt;
+	u32 num_of_elements;
+	u32 preferred_video_format;
+};
+
+struct hdmi_edid_ctrl {
+	u8 pt_scan_info;
+	u8 it_scan_info;
+	u8 ce_scan_info;
+	u16 physical_address;
+	u32 video_resolution; /* selected by user */
+	u32 sink_mode; /* HDMI or DVI */
+	u8 speaker_allocation_block;
+	u8 audio_data_block_cnt;
+	u16 audio_latency;
+	u16 video_latency;
+	u32 present_3d;
+
+	struct hdmi_edid_sink_data sink_data;
+	struct hdmi_edid_init_data init_data;
+};
+
+/* The Logic ID for HDMI TX Core. Currently only support 1 HDMI TX Core. */
+struct hdmi_edid_video_mode_property_type {
+	u32	video_code;
+	u32	active_h;
+	u32	active_v;
+	u32	interlaced;
+	u32	total_h;
+	u32	total_blank_h;
+	u32	total_v;
+	u32	total_blank_v;
+	/* Must divide by 1000 to get the frequency */
+	u32	freq_h;
+	/* Must divide by 1000 to get the frequency */
+	u32	freq_v;
+	/* Must divide by 1000 to get the frequency */
+	u32	pixel_freq;
+	/* Must divide by 1000 to get the frequency */
+	u32	refresh_rate;
+	u32	aspect_ratio_4_3;
+};
+
+/* LUT is sorted from lowest Active H to highest Active H - ease searching */
+static struct hdmi_edid_video_mode_property_type
+	hdmi_edid_disp_mode_lut[] = {
+
+	/* All 640 H Active */
+	{HDMI_VFRMT_640x480p60_4_3, 640, 480, false, 800, 160, 525, 45,
+	 31465, 59940, 25175, 59940, true},
+	{HDMI_VFRMT_640x480p60_4_3, 640, 480, false, 800, 160, 525, 45,
+	 31500, 60000, 25200, 60000, true},
+
+	/* All 720 H Active */
+	{HDMI_VFRMT_720x576p50_4_3,  720, 576, false, 864, 144, 625, 49,
+	 31250, 50000, 27000, 50000, true},
+	{HDMI_VFRMT_720x480p60_4_3,  720, 480, false, 858, 138, 525, 45,
+	 31465, 59940, 27000, 59940, true},
+	{HDMI_VFRMT_720x480p60_4_3,  720, 480, false, 858, 138, 525, 45,
+	 31500, 60000, 27030, 60000, true},
+	{HDMI_VFRMT_720x576p100_4_3, 720, 576, false, 864, 144, 625, 49,
+	 62500, 100000, 54000, 100000, true},
+	{HDMI_VFRMT_720x480p120_4_3, 720, 480, false, 858, 138, 525, 45,
+	 62937, 119880, 54000, 119880, true},
+	{HDMI_VFRMT_720x480p120_4_3, 720, 480, false, 858, 138, 525, 45,
+	 63000, 120000, 54054, 120000, true},
+	{HDMI_VFRMT_720x576p200_4_3, 720, 576, false, 864, 144, 625, 49,
+	 125000, 200000, 108000, 200000, true},
+	{HDMI_VFRMT_720x480p240_4_3, 720, 480, false, 858, 138, 525, 45,
+	 125874, 239760, 108000, 239000, true},
+	{HDMI_VFRMT_720x480p240_4_3, 720, 480, false, 858, 138, 525, 45,
+	 126000, 240000, 108108, 240000, true},
+
+	/* All 1280 H Active */
+	{HDMI_VFRMT_1280x720p50_16_9,  1280, 720, false, 1980, 700, 750, 30,
+	 37500, 50000, 74250, 50000, false},
+	{HDMI_VFRMT_1280x720p60_16_9,  1280, 720, false, 1650, 370, 750, 30,
+	 44955, 59940, 74176, 59940, false},
+	{HDMI_VFRMT_1280x720p60_16_9,  1280, 720, false, 1650, 370, 750, 30,
+	 45000, 60000, 74250, 60000, false},
+	{HDMI_VFRMT_1280x720p100_16_9, 1280, 720, false, 1980, 700, 750, 30,
+	 75000, 100000, 148500, 100000, false},
+	{HDMI_VFRMT_1280x720p120_16_9, 1280, 720, false, 1650, 370, 750, 30,
+	 89909, 119880, 148352, 119880, false},
+	{HDMI_VFRMT_1280x720p120_16_9, 1280, 720, false, 1650, 370, 750, 30,
+	 90000, 120000, 148500, 120000, false},
+
+	/* All 1440 H Active */
+	{HDMI_VFRMT_1440x576i50_4_3, 1440, 576, true,  1728, 288, 625, 24,
+	 15625, 50000, 27000, 50000, true},
+	{HDMI_VFRMT_720x288p50_4_3,  1440, 288, false, 1728, 288, 312, 24,
+	 15625, 50080, 27000, 50000, true},
+	{HDMI_VFRMT_720x288p50_4_3,  1440, 288, false, 1728, 288, 313, 25,
+	 15625, 49920, 27000, 50000, true},
+	{HDMI_VFRMT_720x288p50_4_3,  1440, 288, false, 1728, 288, 314, 26,
+	 15625, 49761, 27000, 50000, true},
+	{HDMI_VFRMT_1440x576p50_4_3, 1440, 576, false, 1728, 288, 625, 49,
+	 31250, 50000, 54000, 50000, true},
+	{HDMI_VFRMT_1440x480i60_4_3, 1440, 480, true,  1716, 276, 525, 22,
+	 15734, 59940, 27000, 59940, true},
+	{HDMI_VFRMT_1440x240p60_4_3, 1440, 240, false, 1716, 276, 262, 22,
+	 15734, 60054, 27000, 59940, true},
+	{HDMI_VFRMT_1440x240p60_4_3, 1440, 240, false, 1716, 276, 263, 23,
+	 15734, 59826, 27000, 59940, true},
+	{HDMI_VFRMT_1440x480p60_4_3, 1440, 480, false, 1716, 276, 525, 45,
+	 31469, 59940, 54000, 59940, true},
+	{HDMI_VFRMT_1440x480i60_4_3, 1440, 480, true,  1716, 276, 525, 22,
+	 15750, 60000, 27027, 60000, true},
+	{HDMI_VFRMT_1440x240p60_4_3, 1440, 240, false, 1716, 276, 262, 22,
+	 15750, 60115, 27027, 60000, true},
+	{HDMI_VFRMT_1440x240p60_4_3, 1440, 240, false, 1716, 276, 263, 23,
+	 15750, 59886, 27027, 60000, true},
+	{HDMI_VFRMT_1440x480p60_4_3, 1440, 480, false, 1716, 276, 525, 45,
+	 31500, 60000, 54054, 60000, true},
+	{HDMI_VFRMT_1440x576i100_4_3, 1440, 576, true,  1728, 288, 625, 24,
+	 31250, 100000, 54000, 100000, true},
+	{HDMI_VFRMT_1440x480i120_4_3, 1440, 480, true,  1716, 276, 525, 22,
+	 31469, 119880, 54000, 119880, true},
+	{HDMI_VFRMT_1440x480i120_4_3, 1440, 480, true,  1716, 276, 525, 22,
+	 31500, 120000, 54054, 120000, true},
+	{HDMI_VFRMT_1440x576i200_4_3, 1440, 576, true,  1728, 288, 625, 24,
+	 62500, 200000, 108000, 200000, true},
+	{HDMI_VFRMT_1440x480i240_4_3, 1440, 480, true,  1716, 276, 525, 22,
+	 62937, 239760, 108000, 239000, true},
+	{HDMI_VFRMT_1440x480i240_4_3, 1440, 480, true,  1716, 276, 525, 22,
+	 63000, 240000, 108108, 240000, true},
+
+	/* All 1920 H Active */
+	{HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, false, 2200, 280, 1125,
+	 45, 67433, 59940, 148352, 59940, false},
+	{HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, true,  2200, 280, 1125,
+	 45, 67500, 60000, 148500, 60000, false},
+	{HDMI_VFRMT_1920x1080p50_16_9, 1920, 1080, false, 2640, 720, 1125,
+	 45, 56250, 50000, 148500, 50000, false},
+	{HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, false, 2750, 830, 1125,
+	 45, 26973, 23976, 74176, 24000, false},
+	{HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, false, 2750, 830, 1125,
+	 45, 27000, 24000, 74250, 24000, false},
+	{HDMI_VFRMT_1920x1080p25_16_9, 1920, 1080, false, 2640, 720, 1125,
+	 45, 28125, 25000, 74250, 25000, false},
+	{HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, false, 2200, 280, 1125,
+	 45, 33716, 29970, 74176, 30000, false},
+	{HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, false, 2200, 280, 1125,
+	 45, 33750, 30000, 74250, 30000, false},
+	{HDMI_VFRMT_1920x1080i50_16_9, 1920, 1080, true,  2304, 384, 1250,
+	 85, 31250, 50000, 72000, 50000, false},
+	{HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, true,  2200, 280, 1125,
+	 22, 33716, 59940, 74176, 59940, false},
+	{HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, true,  2200, 280, 1125,
+	 22, 33750, 60000, 74250, 60000, false},
+	{HDMI_VFRMT_1920x1080i100_16_9, 1920, 1080, true,  2640, 720, 1125,
+	 22, 56250, 100000, 148500, 100000, false},
+	{HDMI_VFRMT_1920x1080i120_16_9, 1920, 1080, true,  2200, 280, 1125,
+	 22, 67432, 119880, 148352, 119980, false},
+	{HDMI_VFRMT_1920x1080i120_16_9, 1920, 1080, true,  2200, 280, 1125,
+	 22, 67500, 120000, 148500, 120000, false},
+
+	/* All 2880 H Active */
+	{HDMI_VFRMT_2880x576i50_4_3, 2880, 576, true,  3456, 576, 625, 24,
+	 15625, 50000, 54000, 50000, true},
+	{HDMI_VFRMT_2880x288p50_4_3, 2880, 576, false, 3456, 576, 312, 24,
+	 15625, 50080, 54000, 50000, true},
+	{HDMI_VFRMT_2880x288p50_4_3, 2880, 576, false, 3456, 576, 313, 25,
+	 15625, 49920, 54000, 50000, true},
+	{HDMI_VFRMT_2880x288p50_4_3, 2880, 576, false, 3456, 576, 314, 26,
+	 15625, 49761, 54000, 50000, true},
+	{HDMI_VFRMT_2880x576p50_4_3, 2880, 576, false, 3456, 576, 625, 49,
+	 31250, 50000, 108000, 50000, true},
+	{HDMI_VFRMT_2880x480i60_4_3, 2880, 480, true,  3432, 552, 525, 22,
+	 15734, 59940, 54000, 59940, true},
+	{HDMI_VFRMT_2880x240p60_4_3, 2880, 480, false, 3432, 552, 262, 22,
+	 15734, 60054, 54000, 59940, true},
+	{HDMI_VFRMT_2880x240p60_4_3, 2880, 480, false, 3432, 552, 263, 23,
+	 15734, 59940, 54000, 59940, true},
+	{HDMI_VFRMT_2880x480p60_4_3, 2880, 480, false, 3432, 552, 525, 45,
+	 31469, 59940, 108000, 59940, true},
+	{HDMI_VFRMT_2880x480i60_4_3, 2880, 480, true,  3432, 552, 525, 22,
+	 15750, 60000, 54054, 60000, true},
+	{HDMI_VFRMT_2880x240p60_4_3, 2880, 240, false, 3432, 552, 262, 22,
+	 15750, 60115, 54054, 60000, true},
+	{HDMI_VFRMT_2880x240p60_4_3, 2880, 240, false, 3432, 552, 262, 23,
+	 15750, 59886, 54054, 60000, true},
+	{HDMI_VFRMT_2880x480p60_4_3, 2880, 480, false, 3432, 552, 525, 45,
+	 31500, 60000, 108108, 60000, true},
+};
+
+static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+	int i;
+	struct hdmi_edid_ctrl *edid_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_EDID);
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	buf[0] = 0;
+	if (edid_ctrl->sink_data.num_of_elements) {
+		u32 *video_mode = edid_ctrl->sink_data.disp_mode_list;
+		for (i = 0; i < edid_ctrl->sink_data.num_of_elements; ++i) {
+			if (ret > 0)
+				ret += snprintf(buf+ret, PAGE_SIZE-ret, ",%d",
+					*video_mode++ + 1);
+			else
+				ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
+					*video_mode++ + 1);
+		}
+	} else {
+		ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
+			edid_ctrl->video_resolution+1);
+	}
+
+	DEV_DBG("%s: '%s'\n", __func__, buf);
+	ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
+
+	return ret;
+} /* hdmi_edid_sysfs_rda_modes */
+static DEVICE_ATTR(edid_modes, S_IRUGO, hdmi_edid_sysfs_rda_modes, NULL);
+
+static ssize_t hdmi_edid_sysfs_rda_physical_address(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct hdmi_edid_ctrl *edid_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_EDID);
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", edid_ctrl->physical_address);
+	DEV_DBG("%s: '%d'\n", __func__, edid_ctrl->physical_address);
+
+	return ret;
+} /* hdmi_edid_sysfs_rda_physical_address */
+static DEVICE_ATTR(pa, S_IRUGO, hdmi_edid_sysfs_rda_physical_address, NULL);
+
+static ssize_t hdmi_edid_sysfs_rda_scan_info(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct hdmi_edid_ctrl *edid_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_EDID);
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snprintf(buf, PAGE_SIZE, "%d, %d, %d\n", edid_ctrl->pt_scan_info,
+		edid_ctrl->it_scan_info, edid_ctrl->ce_scan_info);
+	DEV_DBG("%s: '%s'\n", __func__, buf);
+
+	return ret;
+} /* hdmi_edid_sysfs_rda_scan_info */
+static DEVICE_ATTR(scan_info, S_IRUGO, hdmi_edid_sysfs_rda_scan_info, NULL);
+
+static ssize_t hdmi_edid_sysfs_rda_3d_modes(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+	int i;
+	char buff_3d[128];
+	struct hdmi_edid_ctrl *edid_ctrl =
+		hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_EDID);
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	buf[0] = 0;
+	if (edid_ctrl->sink_data.num_of_elements) {
+		u32 *video_mode = edid_ctrl->sink_data.disp_mode_list;
+		u32 *video_3d_mode = edid_ctrl->sink_data.disp_3d_mode_list;
+
+		for (i = 0; i < edid_ctrl->sink_data.num_of_elements; ++i) {
+			ret = hdmi_get_video_3d_fmt_2string(*video_3d_mode++,
+				buff_3d);
+			if (ret > 0)
+				ret += snprintf(buf+ret, PAGE_SIZE-ret,
+					",%d=%s", *video_mode++ + 1,
+					buff_3d);
+			else
+				ret += snprintf(buf+ret, PAGE_SIZE-ret,
+					"%d=%s", *video_mode++ + 1,
+					buff_3d);
+		}
+	} else {
+		ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
+			edid_ctrl->video_resolution+1);
+	}
+
+	DEV_DBG("%s: '%s'\n", __func__, buf);
+	ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
+
+	return ret;
+} /* hdmi_edid_sysfs_rda_3d_modes */
+static DEVICE_ATTR(edid_3d_modes, S_IRUGO, hdmi_edid_sysfs_rda_3d_modes, NULL);
+
+static struct attribute *hdmi_edid_fs_attrs[] = {
+	&dev_attr_edid_modes.attr,
+	&dev_attr_pa.attr,
+	&dev_attr_scan_info.attr,
+	&dev_attr_edid_3d_modes.attr,
+	NULL,
+};
+
+static struct attribute_group hdmi_edid_fs_attrs_group = {
+	.attrs = hdmi_edid_fs_attrs,
+};
+
+static int hdmi_edid_read_block(struct hdmi_edid_ctrl *edid_ctrl, int block,
+	u8 *edid_buf)
+{
+	const u8 *b = NULL;
+	u32 ndx, check_sum, print_len;
+	int block_size = 0x80;
+	int i, status;
+	struct hdmi_tx_ddc_data ddc_data;
+	b = edid_buf;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	do {
+		DEV_DBG("EDID: reading block(%d) with block-size=%d\n",
+			block, block_size);
+		for (i = 0; i < 0x80; i += block_size) {
+			/*Read EDID twice with 32bit alighnment too */
+			if (block < 2) {
+				memset(&ddc_data, 0, sizeof(ddc_data));
+				ddc_data.dev_addr = 0xA0;
+				ddc_data.offset   = block*0x80 + i;
+				ddc_data.data_buf = edid_buf+i;
+				ddc_data.data_len = block_size;
+				ddc_data.retry    = 1;
+				ddc_data.what     = "EDID";
+				ddc_data.no_align = false;
+
+				status = hdmi_ddc_read(
+					edid_ctrl->init_data.ddc_ctrl,
+					&ddc_data);
+			} else {
+				memset(&ddc_data, 0, sizeof(ddc_data));
+				ddc_data.dev_addr    = 0xA0;
+				ddc_data.offset      = block*0x80 + i;
+				ddc_data.data_buf    = edid_buf+i;
+				ddc_data.data_len    = block_size;
+				ddc_data.request_len = block_size;
+				ddc_data.retry       = 1;
+				ddc_data.what        = "EDID";
+
+				status = hdmi_ddc_read_seg(
+					edid_ctrl->init_data.ddc_ctrl,
+					&ddc_data);
+			}
+			if (status)
+				break;
+		}
+
+		block_size /= 2;
+	} while (status && (block_size >= 16));
+
+	if (status)
+		goto error;
+
+	/* Calculate checksum */
+	check_sum = 0;
+	for (ndx = 0; ndx < 0x80; ++ndx)
+		check_sum += edid_buf[ndx];
+
+	if (check_sum & 0xFF) {
+		DEV_ERR("%s: failed CHECKSUM (read:%x, expected:%x)\n",
+			__func__, (u8)edid_buf[0x7F], (u8)check_sum);
+		for (ndx = 0; ndx < 0x100; ndx += 4)
+			DEV_DBG("EDID[%02x-%02x] %02x %02x %02x %02x\n",
+				ndx, ndx+3,
+				b[ndx+0], b[ndx+1], b[ndx+2], b[ndx+3]);
+		status = -EPROTO;
+		goto error;
+	}
+
+	print_len = 0x80;
+	for (ndx = 0; ndx < print_len; ndx += 16)
+		DEV_DBG("EDID[%02x-%02x] %02x %02x %02x %02x\n",
+			ndx, ndx+3,
+			b[ndx+0], b[ndx+1], b[ndx+2], b[ndx+3]);
+
+error:
+	return status;
+} /* hdmi_edid_read_block */
+
+static const u8 *hdmi_edid_find_block(const u8 *in_buf, u32 start_offset,
+	u8 type, u8 *len)
+{
+	/* the start of data block collection, start of Video Data Block */
+	u32 offset = start_offset;
+	u32 end_dbc_offset = in_buf[2];
+
+	*len = 0;
+
+	/*
+	 * * edid buffer 1, byte 2 being 4 means no non-DTD/Data block
+	 *   collection present.
+	 * * edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block
+	 *   collection present and no DTD data present.
+	 */
+	if ((end_dbc_offset == 0) || (end_dbc_offset == 4)) {
+		DEV_WARN("EDID: no DTD or non-DTD data present\n");
+		return NULL;
+	}
+
+	while (offset < end_dbc_offset) {
+		u8 block_len = in_buf[offset] & 0x1F;
+		if ((in_buf[offset] >> 5) == type) {
+			*len = block_len;
+			DEV_DBG("%s: EDID: block=%d found @ %d w/ length=%d\n",
+				__func__, type, offset, block_len);
+
+			return in_buf + offset;
+		}
+		offset += 1 + block_len;
+	}
+	DEV_WARN("%s: EDID: type=%d block not found in EDID block\n",
+		__func__, type);
+
+	return NULL;
+} /* hdmi_edid_find_block */
+
+static void hdmi_edid_extract_extended_data_blocks(
+	struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf)
+{
+	u8 len = 0;
+	u32 start_offset = DBC_START_OFFSET;
+	u8 const *etag = NULL;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	/* A Tage code of 7 identifies extended data blocks */
+	etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+
+	while (etag != NULL) {
+		/* The extended data block should at least be 2 bytes long */
+		if (len < 2) {
+			DEV_DBG("%s: data block of len < 2 bytes. Ignor...\n",
+				__func__);
+		} else {
+			/*
+			 * The second byte of the extended data block has the
+			 * extended tag code
+			 */
+			switch (etag[1]) {
+			case 0:
+				/* Video Capability Data Block */
+				DEV_DBG("%s: EDID: VCDB=%02X %02X\n", __func__,
+					etag[1], etag[2]);
+
+				/*
+				 * Check if the sink specifies underscan
+				 * support for:
+				 * BIT 5: preferred video format
+				 * BIT 3: IT video format
+				 * BIT 1: CE video format
+				 */
+				edid_ctrl->pt_scan_info =
+					(etag[2] & (BIT(4) | BIT(5))) >> 4;
+				edid_ctrl->it_scan_info =
+					(etag[2] & (BIT(3) | BIT(2))) >> 2;
+				edid_ctrl->ce_scan_info =
+					etag[2] & (BIT(1) | BIT(0));
+				DEV_DBG("%s: Scan Info (pt|it|ce): (%d|%d|%d)",
+					__func__,
+					edid_ctrl->pt_scan_info,
+					edid_ctrl->it_scan_info,
+					edid_ctrl->ce_scan_info);
+				break;
+			default:
+				DEV_DBG("%s: Tag Code %d not supported\n",
+					__func__, etag[1]);
+				break;
+			}
+		}
+
+		/* There could be more that one extended data block */
+		start_offset = etag - in_buf + len + 1;
+		etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+	}
+} /* hdmi_edid_extract_extended_data_blocks */
+
+static void hdmi_edid_extract_3d_present(struct hdmi_edid_ctrl *edid_ctrl,
+	const u8 *in_buf)
+{
+	u8 len, offset;
+	const u8 *vsd = NULL;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
+
+	edid_ctrl->present_3d = 0;
+	if (vsd == NULL || len < 9) {
+		DEV_DBG("%s: blk-id 3 not found or not long enough\n",
+			__func__);
+		return;
+	}
+
+	offset = HDMI_VSDB_3D_DATA_OFFSET(vsd);
+	DEV_DBG("%s: EDID: 3D present @ %d = %02x\n", __func__,
+		offset, vsd[offset]);
+
+	if (vsd[offset] >> 7) { /* 3D format indication present */
+		DEV_INFO("%s: EDID: 3D present, 3D-len=%d\n", __func__,
+			vsd[offset+1] & 0x1F);
+		edid_ctrl->present_3d = 1;
+	}
+} /* hdmi_edid_extract_3d_present */
+
+static void hdmi_edid_extract_audio_data_blocks(
+	struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf)
+{
+	u8 len;
+	const u8 *sad = NULL;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	sad = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 1, &len);
+	if (sad == NULL)
+		return;
+
+	edid_ctrl->audio_data_block_cnt = 0;
+	while (len >= 3 && edid_ctrl->audio_data_block_cnt < 16) {
+		DEV_DBG("%s: ch=%d fmt=%d sampling=0x%02x bitdepth=0x%02x\n",
+			__func__, (sad[1]&0x7)+1, sad[1]>>3, sad[2], sad[3]);
+
+		++edid_ctrl->audio_data_block_cnt;
+		len -= 3;
+		sad += 3;
+	}
+} /* hdmi_edid_extract_audio_data_blocks */
+
+static void hdmi_edid_extract_speaker_allocation_data(
+	struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf)
+{
+	u8 len;
+	const u8 *sad = NULL;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	sad = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 4, &len);
+	if (sad == NULL)
+		return;
+
+	edid_ctrl->speaker_allocation_block = sad[1];
+	DEV_DBG("%s: EDID: speaker alloc data SP byte = %08x %s%s%s%s%s%s%s\n",
+		__func__, sad[1],
+		(sad[1] & BIT(0)) ? "FL/FR," : "",
+		(sad[1] & BIT(1)) ? "LFE," : "",
+		(sad[1] & BIT(2)) ? "FC," : "",
+		(sad[1] & BIT(3)) ? "RL/RR," : "",
+		(sad[1] & BIT(4)) ? "RC," : "",
+		(sad[1] & BIT(5)) ? "FLC/FRC," : "",
+		(sad[1] & BIT(6)) ? "RLC/RRC," : "");
+} /* hdmi_edid_extract_speaker_allocation_data */
+
+static void hdmi_edid_extract_latency_fields(struct hdmi_edid_ctrl *edid_ctrl,
+	const u8 *in_buf)
+{
+	u8 len;
+	const u8 *vsd = NULL;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
+
+	if (vsd == NULL || len < 12 || !(vsd[8] & BIT(7))) {
+		edid_ctrl->video_latency = (u16)-1;
+		edid_ctrl->audio_latency = (u16)-1;
+		DEV_DBG("%s: EDID: No audio/video latency present\n", __func__);
+	} else {
+		edid_ctrl->video_latency = vsd[9];
+		edid_ctrl->audio_latency = vsd[10];
+		DEV_DBG("%s: EDID: video-latency=%04x, audio-latency=%04x\n",
+			__func__, edid_ctrl->video_latency,
+			edid_ctrl->audio_latency);
+	}
+} /* hdmi_edid_extract_latency_fields */
+
+static u32 hdmi_edid_extract_ieee_reg_id(struct hdmi_edid_ctrl *edid_ctrl,
+	const u8 *in_buf)
+{
+	u8 len;
+	const u8 *vsd = NULL;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return 0;
+	}
+
+	vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
+	if (vsd == NULL)
+		return 0;
+
+	DEV_DBG("%s: EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n", __func__,
+		((u32)vsd[4] << 8) + (u32)vsd[5], (u32)vsd[7] * 5);
+
+	edid_ctrl->physical_address = ((u16)vsd[4] << 8) + (u16)vsd[5];
+
+	return ((u32)vsd[3] << 16) + ((u32)vsd[2] << 8) + (u32)vsd[1];
+} /* hdmi_edid_extract_ieee_reg_id */
+
+static void hdmi_edid_extract_vendor_id(const u8 *in_buf,
+	char *vendor_id)
+{
+	u32 id_codes = ((u32)in_buf[8] << 8) + in_buf[9];
+
+	vendor_id[0] = 'A' - 1 + ((id_codes >> 10) & 0x1F);
+	vendor_id[1] = 'A' - 1 + ((id_codes >> 5) & 0x1F);
+	vendor_id[2] = 'A' - 1 + (id_codes & 0x1F);
+	vendor_id[3] = 0;
+} /* hdmi_edid_extract_vendor_id */
+
+static u32 hdmi_edid_check_header(const u8 *edid_buf)
+{
+	return (edid_buf[0] == 0x00) && (edid_buf[1] == 0xff)
+		&& (edid_buf[2] == 0xff) && (edid_buf[3] == 0xff)
+		&& (edid_buf[4] == 0xff) && (edid_buf[5] == 0xff)
+		&& (edid_buf[6] == 0xff) && (edid_buf[7] == 0x00);
+} /* hdmi_edid_check_header */
+
+static void hdmi_edid_detail_desc(const u8 *data_buf, u32 *disp_mode)
+{
+	u32	aspect_ratio_4_3    = false;
+	u32	interlaced          = false;
+	u32	active_h            = 0;
+	u32	active_v            = 0;
+	u32	blank_h             = 0;
+	u32	blank_v             = 0;
+	u32	ndx                 = 0;
+	u32	max_num_of_elements = 0;
+	u32	img_size_h          = 0;
+	u32	img_size_v          = 0;
+
+	/*
+	 * * See VESA Spec
+	 * * EDID_TIMING_DESC_UPPER_H_NIBBLE[0x4]: Relative Offset to the
+	 *   EDID detailed timing descriptors - Upper 4 bit for each H
+	 *   active/blank field
+	 * * EDID_TIMING_DESC_H_ACTIVE[0x2]: Relative Offset to the EDID
+	 *   detailed timing descriptors - H active
+	 */
+	active_h = ((((u32)data_buf[0x4] >> 0x4) & 0xF) << 8)
+		| data_buf[0x2];
+
+	/*
+	 * EDID_TIMING_DESC_H_BLANK[0x3]: Relative Offset to the EDID detailed
+	 *   timing descriptors - H blank
+	 */
+	blank_h = (((u32)data_buf[0x4] & 0xF) << 8)
+		| data_buf[0x3];
+
+	/*
+	 * * EDID_TIMING_DESC_UPPER_V_NIBBLE[0x7]: Relative Offset to the
+	 *   EDID detailed timing descriptors - Upper 4 bit for each V
+	 *   active/blank field
+	 * * EDID_TIMING_DESC_V_ACTIVE[0x5]: Relative Offset to the EDID
+	 *   detailed timing descriptors - V active
+	 */
+	active_v = ((((u32)data_buf[0x7] >> 0x4) & 0xF) << 8)
+		| data_buf[0x5];
+
+	/*
+	 * EDID_TIMING_DESC_V_BLANK[0x6]: Relative Offset to the EDID
+	 * detailed timing descriptors - V blank
+	 */
+	blank_v = (((u32)data_buf[0x7] & 0xF) << 8)
+		| data_buf[0x6];
+
+	/*
+	 * * EDID_TIMING_DESC_IMAGE_SIZE_UPPER_NIBBLE[0xE]: Relative Offset
+	 *   to the EDID detailed timing descriptors - Image Size upper
+	 *   nibble V and H
+	 * * EDID_TIMING_DESC_H_IMAGE_SIZE[0xC]: Relative Offset to the EDID
+	 *   detailed timing descriptors - H image size
+	 * * EDID_TIMING_DESC_V_IMAGE_SIZE[0xD]: Relative Offset to the EDID
+	 *   detailed timing descriptors - V image size
+	 */
+	img_size_h = ((((u32)data_buf[0xE] >> 0x4) & 0xF) << 8)
+		| data_buf[0xC];
+	img_size_v = (((u32)data_buf[0xE] & 0xF) << 8)
+		| data_buf[0xD];
+
+	/*
+	 * aspect ratio as 4:3 if within specificed range , rathaer than being
+	 * absolute value
+	 */
+	aspect_ratio_4_3 = (abs(img_size_h * 3 - img_size_v * 4) < 5) ? 1 : 0;
+
+	max_num_of_elements = sizeof(hdmi_edid_disp_mode_lut)
+		/ sizeof(*hdmi_edid_disp_mode_lut);
+
+	/*
+	 * EDID_TIMING_DESC_INTERLACE[0x11:7]: Relative Offset to the EDID
+	 * detailed timing descriptors - Interlace flag
+	 */
+	DEV_DBG("%s: Interlaced mode byte data_buf[0x11]=[%x]\n", __func__,
+		data_buf[0x11]);
+
+	/*
+	 * CEA 861-D: interlaced bit is bit[7] of byte[0x11]
+	 */
+	interlaced = (data_buf[0x11] & 0x80) >> 7;
+
+	DEV_DBG("%s: A[%ux%u] B[%ux%u] V[%ux%u] %s\n", __func__,
+		active_h, active_v, blank_h, blank_v, img_size_h, img_size_v,
+		interlaced ? "i" : "p");
+
+	*disp_mode = HDMI_VFRMT_FORCE_32BIT;
+	while (ndx < max_num_of_elements) {
+		const struct hdmi_edid_video_mode_property_type *edid =
+			hdmi_edid_disp_mode_lut + ndx;
+
+		if ((interlaced    == edid->interlaced)    &&
+			(active_h  == edid->active_h)      &&
+			(blank_h   == edid->total_blank_h) &&
+			(blank_v   == edid->total_blank_v) &&
+			((active_v == edid->active_v) ||
+			(active_v  == (edid->active_v + 1)))) {
+			if (edid->aspect_ratio_4_3 && !aspect_ratio_4_3)
+				/* Aspect ratio 16:9 */
+				*disp_mode = edid->video_code + 1;
+			else
+				/* Aspect ratio 4:3 */
+				*disp_mode = edid->video_code;
+
+			DEV_DBG("%s: mode found:%d\n", __func__, *disp_mode);
+			break;
+		}
+		++ndx;
+	}
+	if (ndx == max_num_of_elements)
+		DEV_INFO("%s: *no mode* found\n", __func__);
+} /* hdmi_edid_detail_desc */
+
+static void hdmi_edid_add_sink_3d_format(struct hdmi_edid_sink_data *sink_data,
+	u32 video_format, u32 video_3d_format)
+{
+	char string[128];
+	u32 added = false;
+	int i;
+
+	for (i = 0; i < sink_data->num_of_elements; ++i) {
+		if (sink_data->disp_mode_list[i] == video_format) {
+			sink_data->disp_3d_mode_list[i] |= video_3d_format;
+			added = true;
+			break;
+		}
+	}
+
+	hdmi_get_video_3d_fmt_2string(video_3d_format, string);
+
+	DEV_DBG("%s: EDID[3D]: format: %d [%s], %s %s\n", __func__,
+		video_format, hdmi_get_video_fmt_2string(video_format),
+		string, added ? "added" : "NOT added");
+} /* hdmi_edid_add_sink_3d_format */
+
+static void hdmi_edid_add_sink_video_format(
+	struct hdmi_edid_sink_data *sink_data, u32 video_format)
+{
+	const struct hdmi_disp_mode_timing_type *timing =
+		hdmi_get_supported_mode(video_format);
+	u32 supported = timing != NULL;
+
+	if (video_format >= HDMI_VFRMT_MAX) {
+		DEV_ERR("%s: video format: %s is not supported\n", __func__,
+			hdmi_get_video_fmt_2string(video_format));
+		return;
+	}
+
+	DEV_DBG("%s: EDID: format: %d [%s], %s\n", __func__,
+		video_format, hdmi_get_video_fmt_2string(video_format),
+		supported ? "Supported" : "Not-Supported");
+
+	if (supported) {
+		/* todo: MHL */
+		sink_data->disp_mode_list[sink_data->num_of_elements++] =
+			video_format;
+	}
+} /* hdmi_edid_add_sink_video_format */
+
+static void hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
+	struct hdmi_edid_sink_data *sink_data, u32 num_of_cea_blocks)
+{
+	u8 len, offset, present_multi_3d, hdmi_vic_len, hdmi_3d_len;
+	u16 structure_all, structure_mask;
+	const u8 *vsd = num_of_cea_blocks ?
+		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
+				3, &len) : NULL;
+	int i;
+
+	offset = HDMI_VSDB_3D_DATA_OFFSET(vsd);
+	present_multi_3d = (vsd[offset] & 0x60) >> 5;
+
+	offset += 1;
+	hdmi_vic_len = (vsd[offset] >> 5) & 0x7;
+	hdmi_3d_len = vsd[offset] & 0x1F;
+	DEV_DBG("%s: EDID[3D]: HDMI_VIC_LEN = %d, HDMI_3D_LEN = %d\n", __func__,
+		hdmi_vic_len, hdmi_3d_len);
+
+	offset += (hdmi_vic_len + 1);
+	if (present_multi_3d == 1 || present_multi_3d == 2) {
+		DEV_DBG("%s: EDID[3D]: multi 3D present (%d)\n", __func__,
+			present_multi_3d);
+		/* 3d_structure_all */
+		structure_all = (vsd[offset] << 8) | vsd[offset + 1];
+		offset += 2;
+		hdmi_3d_len -= 2;
+		if (present_multi_3d == 2) {
+			/* 3d_structure_mask */
+			structure_mask = (vsd[offset] << 8) | vsd[offset + 1];
+			offset += 2;
+			hdmi_3d_len -= 2;
+		} else
+			structure_mask = 0xffff;
+
+		i = 0;
+		while (i < 16) {
+			if (i >= sink_data->disp_multi_3d_mode_list_cnt)
+				break;
+
+			if (!(structure_mask & BIT(i))) {
+				++i;
+				continue;
+			}
+
+			/* BIT0: FRAME PACKING */
+			if (structure_all & BIT(0))
+				hdmi_edid_add_sink_3d_format(sink_data,
+					sink_data->
+					disp_multi_3d_mode_list[i],
+					FRAME_PACKING);
+
+			/* BIT6: TOP AND BOTTOM */
+			if (structure_all & BIT(6))
+				hdmi_edid_add_sink_3d_format(sink_data,
+					sink_data->
+					disp_multi_3d_mode_list[i],
+					TOP_AND_BOTTOM);
+
+			/* BIT8: SIDE BY SIDE HALF */
+			if (structure_all & BIT(8))
+				hdmi_edid_add_sink_3d_format(sink_data,
+					sink_data->
+					disp_multi_3d_mode_list[i],
+					SIDE_BY_SIDE_HALF);
+
+			++i;
+		}
+	}
+
+	i = 0;
+	while (hdmi_3d_len > 0) {
+		DEV_DBG("%s: EDID[3D]: 3D_Structure_%d @ %d: %02x\n", __func__,
+			i + 1, offset, vsd[offset]);
+
+		if ((vsd[offset] >> 4) >=
+			sink_data->disp_multi_3d_mode_list_cnt) {
+			if ((vsd[offset] & 0x0F) >= 8) {
+				offset += 1;
+				hdmi_3d_len -= 1;
+				DEV_DBG("%s:EDID[3D]:3D_Detail_%d @ %d: %02x\n",
+					__func__, i + 1, offset,
+					vsd[offset]);
+			}
+			i += 1;
+			offset += 1;
+			hdmi_3d_len -= 1;
+			continue;
+		}
+
+		switch (vsd[offset] & 0x0F) {
+		case 0:
+			/* 0000b: FRAME PACKING */
+			hdmi_edid_add_sink_3d_format(sink_data,
+				sink_data->
+				disp_multi_3d_mode_list[vsd[offset] >> 4],
+				FRAME_PACKING);
+			break;
+		case 6:
+			/* 0110b: TOP AND BOTTOM */
+			hdmi_edid_add_sink_3d_format(sink_data,
+				sink_data->
+				disp_multi_3d_mode_list[vsd[offset] >> 4],
+				TOP_AND_BOTTOM);
+			break;
+		case 8:
+			/* 1000b: SIDE BY SIDE HALF */
+			hdmi_edid_add_sink_3d_format(sink_data,
+				sink_data->
+				disp_multi_3d_mode_list[vsd[offset] >> 4],
+				SIDE_BY_SIDE_HALF);
+			break;
+		}
+		if ((vsd[offset] & 0x0F) >= 8) {
+			offset += 1;
+			hdmi_3d_len -= 1;
+			DEV_DBG("%s: EDID[3D]: 3D_Detail_%d @ %d: %02x\n",
+				__func__, i + 1, offset,
+				vsd[offset]);
+		}
+		i += 1;
+		offset += 1;
+		hdmi_3d_len -= 1;
+	}
+} /* hdmi_edid_get_display_vsd_3d_mode */
+
+static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl,
+	const u8 *data_buf, u32 num_of_cea_blocks)
+{
+	u8 i = 0;
+	u32 video_format = HDMI_VFRMT_640x480p60_4_3;
+	u32 has480p = false;
+	u8 len;
+	const u8 *edid_blk0 = NULL;
+	const u8 *edid_blk1 = NULL;
+	const u8 *svd = NULL;
+	u32 has60hz_mode = false;
+	u32 has50hz_mode = false;
+	struct hdmi_edid_sink_data *sink_data = NULL;
+
+	if (!edid_ctrl || !data_buf) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	edid_blk0 = &data_buf[0x0];
+	edid_blk1 = &data_buf[0x80];
+	svd = num_of_cea_blocks ?
+		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET, 2,
+			&len) : NULL;
+
+	sink_data = &edid_ctrl->sink_data;
+
+	sink_data->num_of_elements = 0;
+	sink_data->disp_multi_3d_mode_list_cnt = 0;
+	if (svd != NULL) {
+		++svd;
+		for (i = 0; i < len; ++i, ++svd) {
+			/*
+			 * Subtract 1 because it is zero based in the driver,
+			 * while the Video identification code is 1 based in the
+			 * CEA_861D spec
+			 */
+			video_format = (*svd & 0x7F) - 1;
+			hdmi_edid_add_sink_video_format(sink_data,
+				video_format);
+			/* Make a note of the preferred video format */
+			if (i == 0)
+				sink_data->preferred_video_format =
+					video_format;
+
+			if (i < 16) {
+				sink_data->disp_multi_3d_mode_list[i]
+					= video_format;
+				sink_data->disp_multi_3d_mode_list_cnt++;
+			}
+
+			if (video_format <= HDMI_VFRMT_1920x1080p60_16_9 ||
+				video_format == HDMI_VFRMT_2880x480p60_4_3 ||
+				video_format == HDMI_VFRMT_2880x480p60_16_9)
+				has60hz_mode = true;
+
+			if ((video_format >= HDMI_VFRMT_720x576p50_4_3 &&
+				video_format <= HDMI_VFRMT_1920x1080p50_16_9) ||
+				video_format == HDMI_VFRMT_2880x576p50_4_3 ||
+				video_format == HDMI_VFRMT_2880x576p50_16_9 ||
+				video_format == HDMI_VFRMT_1920x1250i50_16_9)
+				has50hz_mode = true;
+
+			if (video_format == HDMI_VFRMT_640x480p60_4_3)
+				has480p = true;
+		}
+	} else if (!num_of_cea_blocks) {
+		/* Detailed timing descriptors */
+		u32 desc_offset = 0;
+		/*
+		 * * Maximum 4 timing descriptor in block 0 - No CEA
+		 *   extension in this case
+		 * * EDID_FIRST_TIMING_DESC[0x36] - 1st detailed timing
+		 *   descriptor
+		 * * EDID_DETAIL_TIMING_DESC_BLCK_SZ[0x12] - Each detailed
+		 *   timing descriptor has block size of 18
+		 */
+		while (4 > i && 0 != edid_blk0[0x36+desc_offset]) {
+			hdmi_edid_detail_desc(edid_blk0+0x36+desc_offset,
+				&video_format);
+
+			DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
+				__func__, __LINE__,
+				hdmi_get_video_fmt_2string(video_format));
+
+			hdmi_edid_add_sink_video_format(sink_data,
+				video_format);
+
+			if (video_format == HDMI_VFRMT_640x480p60_4_3)
+				has480p = true;
+
+			/* Make a note of the preferred video format */
+			if (i == 0) {
+				sink_data->preferred_video_format =
+					video_format;
+			}
+			desc_offset += 0x12;
+			++i;
+		}
+	} else if (1 == num_of_cea_blocks) {
+		u32 desc_offset = 0;
+
+		/*
+		 * Read from both block 0 and block 1
+		 * Read EDID block[0] as above
+		 */
+		while (4 > i && 0 != edid_blk0[0x36+desc_offset]) {
+			hdmi_edid_detail_desc(edid_blk0+0x36+desc_offset,
+				&video_format);
+
+			DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
+				__func__, __LINE__,
+				hdmi_get_video_fmt_2string(video_format));
+
+			hdmi_edid_add_sink_video_format(sink_data,
+				video_format);
+
+			if (video_format == HDMI_VFRMT_640x480p60_4_3)
+				has480p = true;
+
+			/* Make a note of the preferred video format */
+			if (i == 0) {
+				sink_data->preferred_video_format =
+					video_format;
+			}
+			desc_offset += 0x12;
+			++i;
+		}
+
+		/*
+		 * * Parse block 1 - CEA extension byte offset of first
+		 *   detailed timing generation - offset is relevant to
+		 *   the offset of block 1
+		 * * EDID_CEA_EXTENSION_FIRST_DESC[0x82]: Offset to CEA
+		 *   extension first timing desc - indicate the offset of
+		 *   the first detailed timing descriptor
+		 * * EDID_BLOCK_SIZE = 0x80  Each page size in the EDID ROM
+		 */
+		desc_offset = edid_blk1[0x02];
+		while (0 != edid_blk1[desc_offset]) {
+			hdmi_edid_detail_desc(edid_blk1+desc_offset,
+				&video_format);
+
+			DEV_DBG("[%s:%d] Block-1 Adding vid fmt = [%s]\n",
+				__func__, __LINE__,
+				hdmi_get_video_fmt_2string(video_format));
+
+			hdmi_edid_add_sink_video_format(sink_data,
+				video_format);
+			if (video_format == HDMI_VFRMT_640x480p60_4_3)
+				has480p = true;
+
+			/* Make a note of the preferred video format */
+			if (i == 0) {
+				sink_data->preferred_video_format =
+					video_format;
+			}
+			desc_offset += 0x12;
+			++i;
+		}
+	}
+
+	/* mandaroty 3d format */
+	if (edid_ctrl->present_3d) {
+		if (has60hz_mode) {
+			hdmi_edid_add_sink_3d_format(sink_data,
+				HDMI_VFRMT_1920x1080p24_16_9,
+				FRAME_PACKING | TOP_AND_BOTTOM);
+			hdmi_edid_add_sink_3d_format(sink_data,
+				HDMI_VFRMT_1280x720p60_16_9,
+				FRAME_PACKING | TOP_AND_BOTTOM);
+			hdmi_edid_add_sink_3d_format(sink_data,
+				HDMI_VFRMT_1920x1080i60_16_9,
+				SIDE_BY_SIDE_HALF);
+		}
+
+		if (has50hz_mode) {
+			hdmi_edid_add_sink_3d_format(sink_data,
+				HDMI_VFRMT_1920x1080p24_16_9,
+				FRAME_PACKING | TOP_AND_BOTTOM);
+			hdmi_edid_add_sink_3d_format(sink_data,
+				HDMI_VFRMT_1280x720p50_16_9,
+				FRAME_PACKING | TOP_AND_BOTTOM);
+			hdmi_edid_add_sink_3d_format(sink_data,
+				HDMI_VFRMT_1920x1080i50_16_9,
+				SIDE_BY_SIDE_HALF);
+		}
+
+		/* 3d format described in Vendor Specific Data */
+		hdmi_edid_get_display_vsd_3d_mode(data_buf, sink_data,
+			num_of_cea_blocks);
+	}
+
+	/*
+	 * Need to add default 640 by 480 timings, in case not described
+	 * in the EDID structure.
+	 * All DTV sink devices should support this mode
+	 */
+	if (!has480p)
+		hdmi_edid_add_sink_video_format(sink_data,
+			HDMI_VFRMT_640x480p60_4_3);
+} /* hdmi_edid_get_display_mode */
+
+int hdmi_edid_read(void *input)
+{
+	/* EDID_BLOCK_SIZE[0x80] Each page size in the EDID ROM */
+	u8 edid_buf[0x80 * 4];
+	u32 cea_extension_ver = 0;
+	u32 num_of_cea_blocks = 0;
+	u32 ieee_reg_id = 0;
+	u32 i = 1;
+	int status = 0;
+	char vendor_id[5];
+	struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	edid_ctrl->pt_scan_info = 0;
+	edid_ctrl->it_scan_info = 0;
+	edid_ctrl->ce_scan_info = 0;
+	edid_ctrl->present_3d = 0;
+	memset(&edid_ctrl->sink_data, 0, sizeof(edid_ctrl->sink_data));
+	memset(edid_buf, 0, sizeof(edid_buf));
+
+	status = hdmi_edid_read_block(edid_ctrl, 0, edid_buf);
+	if (status || !hdmi_edid_check_header(edid_buf)) {
+		if (!status)
+			status = -EPROTO;
+		DEV_ERR("%s: blk0 fail:%d[%02x%02x%02x%02x%02x%02x%02x%02x]\n",
+			__func__, status,
+			edid_buf[0], edid_buf[1], edid_buf[2], edid_buf[3],
+			edid_buf[4], edid_buf[5], edid_buf[6], edid_buf[7]);
+		goto error;
+	}
+	hdmi_edid_extract_vendor_id(edid_buf, vendor_id);
+
+	/* EDID_CEA_EXTENSION_FLAG[0x7E] - CEC extension byte */
+	num_of_cea_blocks = edid_buf[0x7E];
+	DEV_DBG("%s: No. of CEA blocks is  [%u]\n", __func__,
+		num_of_cea_blocks);
+	/* Find out any CEA extension blocks following block 0 */
+	switch (num_of_cea_blocks) {
+	case 0: /* No CEA extension */
+		edid_ctrl->sink_mode = false;
+		DEV_DBG("HDMI DVI mode: %s\n",
+			edid_ctrl->sink_mode ? "no" : "yes");
+		break;
+	case 1: /* Read block 1 */
+		status = hdmi_edid_read_block(edid_ctrl, 1, &edid_buf[0x80]);
+		if (status) {
+			DEV_ERR("%s: ddc read block(1) failed: %d\n", __func__,
+				status);
+			goto error;
+		}
+		if (edid_buf[0x80] != 2)
+			num_of_cea_blocks = 0;
+		if (num_of_cea_blocks) {
+			ieee_reg_id =
+				hdmi_edid_extract_ieee_reg_id(edid_ctrl,
+					edid_buf+0x80);
+			if (ieee_reg_id == 0x0c03)
+				edid_ctrl->sink_mode = true;
+			else
+				edid_ctrl->sink_mode = false;
+
+			hdmi_edid_extract_latency_fields(edid_ctrl,
+				edid_buf+0x80);
+			hdmi_edid_extract_speaker_allocation_data(
+				edid_ctrl, edid_buf+0x80);
+			hdmi_edid_extract_audio_data_blocks(edid_ctrl,
+				edid_buf+0x80);
+			hdmi_edid_extract_3d_present(edid_ctrl,
+				edid_buf+0x80);
+			hdmi_edid_extract_extended_data_blocks(edid_ctrl,
+				edid_buf+0x80);
+		}
+		break;
+	case 2:
+	case 3:
+	case 4:
+		for (i = 1; i <= num_of_cea_blocks; i++) {
+			if (!(i % 2)) {
+				status = hdmi_edid_read_block(
+					edid_ctrl, i, edid_buf+0x00);
+				if (status) {
+					DEV_ERR("%s: read blk(%d) failed:%d\n",
+						__func__, i, status);
+					goto error;
+				}
+			} else {
+				status = hdmi_edid_read_block(
+					edid_ctrl, i, edid_buf+0x80);
+				if (status) {
+					DEV_ERR("%s: read blk(%d) failed:%d\n",
+						__func__, i, status);
+					goto error;
+				}
+			}
+		}
+		break;
+	default:
+		DEV_ERR("%s: ddc read failed, not supported multi-blocks: %d\n",
+			__func__, num_of_cea_blocks);
+		status = -EPROTO;
+		goto error;
+	}
+
+	if (num_of_cea_blocks) {
+		/* EDID_CEA_EXTENSION_VERSION[0x81]: Offset to CEA extension
+		 * version number - v1,v2,v3 (v1 is seldom, v2 is obsolete,
+		 * v3 most common) */
+		cea_extension_ver = edid_buf[0x81];
+	}
+
+	/* EDID_VERSION[0x12] - EDID Version */
+	/* EDID_REVISION[0x13] - EDID Revision */
+	DEV_INFO("%s: V=%d.%d #CEABlks=%d[V%d] ID=%s IEEE=%04x Ext=0x%02x\n",
+		__func__, edid_buf[0x12], edid_buf[0x13],
+		num_of_cea_blocks, cea_extension_ver, vendor_id, ieee_reg_id,
+		edid_buf[0x80]);
+
+	hdmi_edid_get_display_mode(edid_ctrl, edid_buf, num_of_cea_blocks);
+
+	return 0;
+
+error:
+	edid_ctrl->sink_data.num_of_elements = 1;
+	edid_ctrl->sink_data.disp_mode_list[0] = edid_ctrl->video_resolution;
+
+	return status;
+} /* hdmi_edid_read */
+
+/*
+ * If the sink specified support for both underscan/overscan then, by default,
+ * set the underscan bit. Only checking underscan support for preferred
+ * format and cea formats.
+ */
+u8 hdmi_edid_get_sink_scaninfo(void *input, u32 resolution)
+{
+	u8 scaninfo = 0;
+	int use_ce_scan_info = true;
+	struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		goto end;
+	}
+
+	if (resolution == edid_ctrl->sink_data.preferred_video_format) {
+		use_ce_scan_info = false;
+		switch (edid_ctrl->pt_scan_info) {
+		case 0:
+			/*
+			 * Need to use the info specified for the corresponding
+			 * IT or CE format
+			 */
+			DEV_DBG("%s: No underscan info for preferred V fmt\n",
+				__func__);
+			use_ce_scan_info = true;
+			break;
+		case 3:
+			DEV_DBG("%s: Set underscan bit for preferred V fmt\n",
+				__func__);
+			scaninfo = BIT(1);
+			break;
+		default:
+			DEV_DBG("%s: Underscan not set for preferred V fmt\n",
+				__func__);
+			break;
+		}
+	}
+
+	if (use_ce_scan_info) {
+		if (3 == edid_ctrl->ce_scan_info) {
+			DEV_DBG("%s: Setting underscan bit for CE video fmt\n",
+				__func__);
+			scaninfo |= BIT(1);
+		} else {
+			DEV_DBG("%s: Not setting underscan bit for CE V fmt\n",
+				__func__);
+		}
+	}
+
+end:
+	return scaninfo;
+} /* hdmi_edid_get_sink_scaninfo */
+
+u32 hdmi_edid_get_sink_mode(void *input)
+{
+	struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return 0;
+	}
+
+	return edid_ctrl->sink_mode;
+} /* hdmi_edid_get_sink_mode */
+
+void hdmi_edid_set_video_resolution(void *input, u32 resolution)
+{
+	struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+	if (!edid_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	edid_ctrl->video_resolution = resolution;
+
+	if (1 == edid_ctrl->sink_data.num_of_elements)
+		edid_ctrl->sink_data.disp_mode_list[0] = resolution;
+} /* hdmi_edid_set_video_resolution */
+
+void hdmi_edid_deinit(void *input)
+{
+	struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+	if (edid_ctrl) {
+		sysfs_remove_group(edid_ctrl->init_data.sysfs_kobj,
+			&hdmi_edid_fs_attrs_group);
+		kfree(edid_ctrl);
+	}
+} /* hdmi_edid_deinit */
+
+void *hdmi_edid_init(struct hdmi_edid_init_data *init_data)
+{
+	struct hdmi_edid_ctrl *edid_ctrl = NULL;
+
+	if (!init_data || !init_data->base ||
+		!init_data->mutex || !init_data->sysfs_kobj ||
+		!init_data->ddc_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		goto error;
+	}
+
+	edid_ctrl = kzalloc(sizeof(*edid_ctrl), GFP_KERNEL);
+	if (!edid_ctrl) {
+		DEV_ERR("%s: Out of memory\n", __func__);
+		goto error;
+	}
+
+	edid_ctrl->init_data = *init_data;
+	edid_ctrl->sink_mode = false;
+
+	if (sysfs_create_group(init_data->sysfs_kobj,
+		&hdmi_edid_fs_attrs_group)) {
+		DEV_ERR("%s: EDID sysfs create failed\n", __func__);
+		kfree(edid_ctrl);
+		edid_ctrl = NULL;
+	}
+
+error:
+	return (void *)edid_ctrl;
+} /* hdmi_edid_deinit */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.h b/drivers/video/msm/mdss/mdss_hdmi_edid.h
new file mode 100644
index 0000000..d10ae49
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.h
@@ -0,0 +1,33 @@
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __HDMI_EDID_H__
+#define __HDMI_EDID_H__
+
+#include "mdss_hdmi_util.h"
+
+struct hdmi_edid_init_data {
+	void __iomem *base;
+	struct mutex *mutex;
+	struct kobject *sysfs_kobj;
+
+	struct hdmi_tx_ddc_ctrl *ddc_ctrl;
+};
+
+int hdmi_edid_read(void *edid_ctrl);
+u8 hdmi_edid_get_sink_scaninfo(void *edid_ctrl, u32 resolution);
+u32 hdmi_edid_get_sink_mode(void *edid_ctrl);
+void hdmi_edid_set_video_resolution(void *edid_ctrl, u32 resolution);
+void hdmi_edid_deinit(void *edid_ctrl);
+void *hdmi_edid_init(struct hdmi_edid_init_data *init_data);
+
+#endif /* __HDMI_EDID_H__ */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 6317069..9278029 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -24,12 +24,24 @@
 
 #include "mdss_fb.h"
 #include "mdss_hdmi_tx.h"
+#include "mdss_hdmi_edid.h"
 #include "mdss.h"
 #include "mdss_panel.h"
 
 #define DRV_NAME "hdmi-tx"
 #define COMPATIBLE_NAME "qcom,hdmi-tx"
 
+#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_1920x1080p60_16_9;
+
+/* HDMI PHY/PLL bit field macros */
+#define SW_RESET BIT(2)
+#define SW_RESET_PLL BIT(0)
+
+#define IFRAME_CHECKSUM_32(d)			\
+	((d & 0xff) + ((d >> 8) & 0xff) +	\
+	((d >> 16) & 0xff) + ((d >> 24) & 0xff))
+
+static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
 static irqreturn_t hdmi_tx_isr(int irq, void *data);
 
 struct mdss_hw hdmi_tx_hw = {
@@ -48,6 +60,37 @@
 	}
 } /* hdmi_pm_name */
 
+static u8 hdmi_tx_avi_iframe_lut[][16] = {
+/*	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*/
+	{0x18,	0x18,	0x28,	0x28,	0x28,	 0x28,	0x28,	0x28,	0x28,
+	 0x28,	0x28,	0x28,	0x28,	0x18, 0x28, 0x18}, /*01*/
+	{0x00,	0x04,	0x04,	0x04,	0x04,	 0x04,	0x04,	0x04,	0x04,
+	 0x04,	0x04,	0x04,	0x04,	0x88, 0x00, 0x04}, /*02*/
+	{0x02,	0x06,	0x11,	0x15,	0x04,	 0x13,	0x10,	0x05,	0x1F,
+	 0x14,	0x20,	0x22,	0x21,	0x01, 0x03, 0x11}, /*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,	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*/
+	{0xE1,	0xE1,	0x41,	0x41,	0xD1,	 0xd1,	0x39,	0x39,	0x39,
+	 0x39,	0x39,	0x39,	0x39,	0xe1, 0xE1, 0x41}, /*07*/
+	{0x01,	0x01,	0x02,	0x02,	0x02,	 0x02,	0x04,	0x04,	0x04,
+	 0x04,	0x04,	0x04,	0x04,	0x01, 0x01, 0x02}, /*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,	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*/
+	{0x02,	0x02,	0x02,	0x02,	0x05,	 0x05,	0x07,	0x07,	0x07,
+	 0x07,	0x07,	0x07,	0x07,	0x02, 0x02, 0x02}  /*12*/
+};
+
 static const char *hdmi_tx_clk_name(u32 clk)
 {
 	switch (clk) {
@@ -68,6 +111,298 @@
 	}
 } /* hdmi_tx_io_name */
 
+static struct hdmi_tx_ctrl *hdmi_tx_get_drvdata_from_panel_data(
+	struct mdss_panel_data *mpd)
+{
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+
+	if (mpd) {
+		hdmi_ctrl = container_of(mpd, struct hdmi_tx_ctrl, panel_data);
+		if (hdmi_ctrl) {
+			hdmi_ctrl->pixel_clk =
+				mpd->panel_info.fbi->var.pixclock;
+			hdmi_ctrl->xres = mpd->panel_info.fbi->var.xres;
+			hdmi_ctrl->yres = mpd->panel_info.fbi->var.yres;
+		} else {
+			DEV_ERR("%s: hdmi_ctrl = NULL\n", __func__);
+		}
+	} else {
+		DEV_ERR("%s: mdss_panel_data = NULL\n", __func__);
+	}
+	return hdmi_ctrl;
+} /* hdmi_tx_get_drvdata_from_panel_data */
+
+static struct hdmi_tx_ctrl *hdmi_tx_get_drvdata_from_sysfs_dev(
+	struct device *device)
+{
+	struct msm_fb_data_type *mfd = NULL;
+	struct mdss_panel_data *panel_data = NULL;
+	struct fb_info *fbi = dev_get_drvdata(device);
+
+	if (fbi) {
+		mfd = (struct msm_fb_data_type *)fbi->par;
+		panel_data = dev_get_platdata(&mfd->pdev->dev);
+
+		return hdmi_tx_get_drvdata_from_panel_data(panel_data);
+	} else {
+		DEV_ERR("%s: fbi = NULL\n", __func__);
+		return NULL;
+	}
+} /* hdmi_tx_get_drvdata_from_sysfs_dev */
+
+/* todo: Fix this. Right now this is declared in hdmi_util.h */
+void *hdmi_get_featuredata_from_sysfs_dev(struct device *device,
+	u32 feature_type)
+{
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+
+	if (!device || feature_type > HDMI_TX_FEAT_MAX) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return NULL;
+	}
+
+	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(device);
+	if (hdmi_ctrl)
+		return hdmi_ctrl->feature_data[feature_type];
+	else
+		return NULL;
+
+} /* hdmi_tx_get_featuredata_from_sysfs_dev */
+EXPORT_SYMBOL(hdmi_get_featuredata_from_sysfs_dev);
+
+static ssize_t hdmi_tx_sysfs_rda_connected(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hdmi_ctrl->mutex);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->hpd_state);
+	DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->hpd_state);
+	mutex_unlock(&hdmi_ctrl->mutex);
+
+	return ret;
+} /* hdmi_tx_sysfs_rda_connected */
+
+static ssize_t hdmi_tx_sysfs_rda_fake_hpd(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hdmi_ctrl->mutex);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->hpd_state);
+	DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->hpd_state);
+	mutex_unlock(&hdmi_ctrl->mutex);
+
+	return ret;
+} /* hdmi_tx_sysfs_rda_fake_hpd */
+
+static ssize_t hdmi_tx_sysfs_wta_fake_hpd(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int fake_hpd, rc = 0;
+	ssize_t ret = strnlen(buf, PAGE_SIZE);
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+
+	DEV_DBG("%s:\n", __func__);
+	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = kstrtoint(buf, 10, &fake_hpd);
+	if (rc) {
+		DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		return rc;
+	}
+
+	mutex_lock(&hdmi_ctrl->mutex);
+	DEV_INFO("%s: fake_hpd=%d\n", __func__, fake_hpd);
+	if (fake_hpd) {
+		hdmi_ctrl->hpd_state = true;
+
+		/* todo: Remove this once HPD line is available in HW */
+		DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
+		if (kobject_uevent(hdmi_ctrl->kobj, KOBJ_ONLINE))
+			DEV_ERR("%s: failed sending online event\n", __func__);
+		switch_set_state(&hdmi_ctrl->sdev, 1);
+		DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
+			hdmi_ctrl->sdev.state);
+	} else {
+		hdmi_ctrl->hpd_state = false;
+
+		/* todo: Remove this once HPD line is available in HW */
+		DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
+		if (kobject_uevent(hdmi_ctrl->kobj, KOBJ_OFFLINE))
+			DEV_ERR("%s: failed sending online event\n", __func__);
+		switch_set_state(&hdmi_ctrl->sdev, 0);
+		DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
+			hdmi_ctrl->sdev.state);
+	}
+	mutex_unlock(&hdmi_ctrl->mutex);
+
+	return ret;
+} /* hdmi_tx_sysfs_wta_fake_hpd */
+
+static ssize_t hdmi_tx_sysfs_rda_hpd(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->hpd_feature_on);
+	DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->hpd_feature_on);
+
+	return ret;
+} /* hdmi_tx_sysfs_rda_hpd */
+
+static ssize_t hdmi_tx_sysfs_wta_hpd(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int hpd, rc = 0;
+	ssize_t ret = strnlen(buf, PAGE_SIZE);
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+
+	DEV_DBG("%s:\n", __func__);
+	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = kstrtoint(buf, 10, &hpd);
+	if (rc) {
+		DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		return rc;
+	}
+
+	/* todo: Remove this once HPD line is available in HW */
+	if (0) {
+		if (0 == hpd && hdmi_ctrl->hpd_feature_on) {
+			rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
+		} else if (1 == hpd && !hdmi_ctrl->hpd_feature_on) {
+			rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
+		} else {
+			rc = -EPERM;
+			ret = rc;
+		}
+	}
+
+	if (!rc) {
+		hdmi_ctrl->hpd_feature_on =
+			(~hdmi_ctrl->hpd_feature_on) & BIT(0);
+		DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->hpd_feature_on);
+	} else {
+		DEV_DBG("%s: '%d' (unchanged)\n", __func__,
+			hdmi_ctrl->hpd_feature_on);
+	}
+
+	return ret;
+} /* hdmi_tx_sysfs_wta_hpd */
+
+static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
+static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd,
+	hdmi_tx_sysfs_wta_hpd);
+static DEVICE_ATTR(fake_hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_fake_hpd,
+	hdmi_tx_sysfs_wta_fake_hpd);
+
+static struct attribute *hdmi_tx_fs_attrs[] = {
+	&dev_attr_connected.attr,
+	&dev_attr_hpd.attr,
+	&dev_attr_fake_hpd.attr,
+	NULL,
+};
+static struct attribute_group hdmi_tx_fs_attrs_group = {
+	.attrs = hdmi_tx_fs_attrs,
+};
+
+static int hdmi_tx_sysfs_create(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int rc;
+	struct mdss_panel_info *pinfo = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -ENODEV;
+	}
+	pinfo = &hdmi_ctrl->panel_data.panel_info;
+
+	rc = sysfs_create_group(&pinfo->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;
+	DEV_DBG("%s: sysfs group %p\n", __func__, hdmi_ctrl->kobj);
+
+	kobject_uevent(hdmi_ctrl->kobj, KOBJ_ADD);
+	DEV_DBG("%s: kobject_uevent(KOBJ_ADD)\n", __func__);
+
+	return 0;
+} /* hdmi_tx_sysfs_create */
+
+static void hdmi_tx_sysfs_remove(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+	if (hdmi_ctrl->kobj)
+		sysfs_remove_group(hdmi_ctrl->kobj, &hdmi_tx_fs_attrs_group);
+	hdmi_ctrl->kobj = NULL;
+} /* hdmi_tx_sysfs_remove */
+
+/* Enable HDMI features */
+static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	struct hdmi_edid_init_data edid_init_data;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	edid_init_data.base = hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base;
+	edid_init_data.mutex = &hdmi_ctrl->mutex;
+	edid_init_data.sysfs_kobj = hdmi_ctrl->kobj;
+	edid_init_data.ddc_ctrl = &hdmi_ctrl->ddc_ctrl;
+
+	hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] =
+		hdmi_edid_init(&edid_init_data);
+	if (!hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) {
+		DEV_ERR("%s: hdmi_edid_init failed\n", __func__);
+		return -EPERM;
+	}
+	hdmi_edid_set_video_resolution(
+		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID],
+		hdmi_ctrl->video_resolution);
+
+	return 0;
+} /* hdmi_tx_init_features */
+
 static inline u32 hdmi_tx_is_controller_on(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	return HDMI_REG_R_ND(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
@@ -138,11 +473,76 @@
 	hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p60_16_9);
 } /* hdmi_tx_setup_video_mode_lut */
 
+static inline struct clk *hdmi_tx_get_clk(struct hdmi_tx_platform_data *pdata,
+	u32 clk_idx)
+{
+	if (!pdata || clk_idx > HDMI_TX_MAX_CLK) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return NULL;
+	}
+
+	return pdata->clk[clk_idx];
+} /* hdmi_tx_get_clk */
+
+static int hdmi_tx_clk_set_rate(struct hdmi_tx_platform_data *pdata,
+	u32 clk_idx, unsigned long clk_rate)
+{
+	int rc = 0;
+	struct clk *clk = NULL;
+
+	if (!pdata) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	clk = hdmi_tx_get_clk(pdata, clk_idx);
+	if (clk) {
+		rc = clk_set_rate(clk, clk_rate);
+		if (IS_ERR_VALUE(rc))
+			DEV_ERR("%s: failed rc=%d\n", __func__, rc);
+		else
+			DEV_DBG("%s: name='%s' rate=%lu\n", __func__,
+				hdmi_tx_clk_name(clk_idx), clk_rate);
+	} else {
+		DEV_ERR("%s: FAILED: invalid clk_idx=%d\n", __func__, clk_idx);
+		rc = -EINVAL;
+	}
+
+	return rc;
+} /* hdmi_tx_clk_set_rate */
+
+static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int status;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!hdmi_tx_is_controller_on(hdmi_ctrl)) {
+		DEV_ERR("%s: failed: HDMI controller is off", __func__);
+		status = -ENXIO;
+		goto error;
+	}
+
+	hdmi_ddc_config(&hdmi_ctrl->ddc_ctrl);
+
+	status = hdmi_edid_read(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
+	if (!status)
+		DEV_DBG("%s: hdmi_edid_read success\n", __func__);
+	else
+		DEV_ERR("%s: hdmi_edid_read failed\n", __func__);
+
+error:
+	return status;
+} /* hdmi_tx_read_sink_info */
+
 static void hdmi_tx_hpd_state_work(struct work_struct *work)
 {
 	u32 hpd_state = false;
 	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
-	struct hdmi_tx_io_data *io = NULL;
+	struct dss_io_data *io = NULL;
 
 	hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, hpd_state_work);
 	if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
@@ -181,7 +581,6 @@
 	}
 
 	hdmi_ctrl->hpd_stable = 1;
-	DEV_INFO("HDMI HPD: event detected\n");
 
 	/*
 	 *todo: Revisit cable chg detected condition when HPD support is ready
@@ -190,6 +589,8 @@
 	mutex_unlock(&hdmi_ctrl->mutex);
 
 	if (hpd_state) {
+		/* todo: what if EDID read fails? */
+		hdmi_tx_read_sink_info(hdmi_ctrl);
 		DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
 		kobject_uevent(hdmi_ctrl->kobj, KOBJ_ONLINE);
 		switch_set_state(&hdmi_ctrl->sdev, 1);
@@ -235,7 +636,432 @@
 	return 0;
 } /* hdmi_tx_check_capability */
 
-/* todo: revisit when new HPD debouncing logic is available */
+static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int rc = 0;
+	const struct hdmi_disp_mode_timing_type *timing = NULL;
+	struct hdmi_tx_platform_data *pdata = NULL;
+	u32 format = DEFAULT_VIDEO_RESOLUTION;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	pdata = &hdmi_ctrl->pdata;
+
+	DEV_DBG("%s: Resolution wanted=%dx%d\n", __func__, hdmi_ctrl->xres,
+		hdmi_ctrl->yres);
+	switch (hdmi_ctrl->xres) {
+	default:
+	case 640:
+		format = HDMI_VFRMT_640x480p60_4_3;
+		break;
+	case 720:
+		format = (hdmi_ctrl->yres == 480)
+			? HDMI_VFRMT_720x480p60_16_9
+			: HDMI_VFRMT_720x576p50_16_9;
+		break;
+	case 1280:
+		if (hdmi_ctrl->frame_rate == 50000)
+			format = HDMI_VFRMT_1280x720p50_16_9;
+		else
+			format = HDMI_VFRMT_1280x720p60_16_9;
+		break;
+	case 1440:
+		/* interlaced has half of y res. */
+		format = (hdmi_ctrl->yres == 240)
+			? HDMI_VFRMT_1440x480i60_16_9
+			: HDMI_VFRMT_1440x576i50_16_9;
+		break;
+	case 1920:
+		if (hdmi_ctrl->yres == 540) {/* interlaced */
+			format = HDMI_VFRMT_1920x1080i60_16_9;
+		} else if (hdmi_ctrl->yres == 1080) {
+			if (hdmi_ctrl->frame_rate == 50000)
+				format = HDMI_VFRMT_1920x1080p50_16_9;
+			else if (hdmi_ctrl->frame_rate == 24000)
+				format = HDMI_VFRMT_1920x1080p24_16_9;
+			else if (hdmi_ctrl->frame_rate == 25000)
+				format = HDMI_VFRMT_1920x1080p25_16_9;
+			else if (hdmi_ctrl->frame_rate == 30000)
+				format = HDMI_VFRMT_1920x1080p30_16_9;
+			else
+				format = HDMI_VFRMT_1920x1080p60_16_9;
+		}
+		break;
+	}
+
+	if (hdmi_ctrl->video_resolution != format)
+		DEV_DBG("%s: switching %s => %s", __func__,
+			hdmi_get_video_fmt_2string(
+			hdmi_ctrl->video_resolution),
+			hdmi_get_video_fmt_2string(format));
+	else
+		DEV_DBG("resolution %s", hdmi_get_video_fmt_2string(
+			hdmi_ctrl->video_resolution));
+
+	timing = hdmi_get_supported_mode(format);
+	if (!timing) {
+		DEV_ERR("%s: invalid video fmt=%d\n", __func__,
+			hdmi_ctrl->video_resolution);
+		rc = -EPERM;
+		goto end;
+	}
+
+	/*
+	 * extpclk is driven by hdmi phy pll. This phy pll programming requires
+	 * hdmi_ahb_clk. So enable it and then disable.
+	 */
+	rc = clk_prepare_enable(pdata->clk[HDMI_TX_AHB_CLK]);
+	if (rc) {
+		DEV_ERR("%s: failed to enable '%s' clk\n", __func__,
+			hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
+		goto end;
+	}
+	rc = hdmi_tx_clk_set_rate(pdata, HDMI_TX_EXTP_CLK,
+		timing->pixel_freq * 1000);
+	if (rc) {
+		DEV_ERR("%s: FAILED: '%s' clk set rate\n", __func__,
+			hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
+		clk_disable_unprepare(pdata->clk[HDMI_TX_AHB_CLK]);
+		goto end;
+	}
+	clk_disable_unprepare(pdata->clk[HDMI_TX_AHB_CLK]);
+
+	hdmi_ctrl->video_resolution = format;
+	hdmi_edid_set_video_resolution(
+		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], format);
+
+end:
+	return rc;
+} /* hdmi_tx_set_video_fmt */
+
+static void hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
+	int video_format)
+{
+	u32 total_v   = 0;
+	u32 total_h   = 0;
+	u32 start_h   = 0;
+	u32 end_h     = 0;
+	u32 start_v   = 0;
+	u32 end_v     = 0;
+	struct dss_io_data *io = NULL;
+
+	const struct hdmi_disp_mode_timing_type *timing =
+		hdmi_get_supported_mode(video_format);
+	if (timing == NULL) {
+		DEV_ERR("%s: video format not supported: %d\n", __func__,
+			video_format);
+		return;
+	}
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: Core io is not initialized\n", __func__);
+		return;
+	}
+
+	total_h = timing->active_h + timing->front_porch_h +
+		timing->back_porch_h + timing->pulse_width_h - 1;
+	total_v = timing->active_v + timing->front_porch_v +
+		timing->back_porch_v + timing->pulse_width_v - 1;
+	HDMI_REG_W(io->base, HDMI_TOTAL,
+		((total_v << 16) & 0x0FFF0000) |
+		((total_h << 0) & 0x00000FFF));
+
+	start_h = timing->back_porch_h + timing->pulse_width_h;
+	end_h   = (total_h + 1) - timing->front_porch_h;
+	HDMI_REG_W(io->base, HDMI_ACTIVE_H,
+		((end_h << 16) & 0x0FFF0000) |
+		((start_h << 0) & 0x00000FFF));
+
+	start_v = timing->back_porch_v + timing->pulse_width_v - 1;
+	end_v   = total_v - timing->front_porch_v;
+	HDMI_REG_W(io->base, HDMI_ACTIVE_V,
+		((end_v << 16) & 0x0FFF0000) |
+		((start_v << 0) & 0x00000FFF));
+
+	if (timing->interlaced) {
+		HDMI_REG_W(io->base, HDMI_V_TOTAL_F2,
+			((total_v + 1) << 0) & 0x00000FFF);
+
+		HDMI_REG_W(io->base, HDMI_ACTIVE_V_F2,
+			(((start_v + 1) << 0) & 0x00000FFF) |
+			(((end_v + 1) << 16) & 0x0FFF0000));
+	} else {
+		HDMI_REG_W(io->base, HDMI_V_TOTAL_F2, 0);
+		HDMI_REG_W(io->base, HDMI_ACTIVE_V_F2, 0);
+	}
+
+	HDMI_REG_W(io->base, HDMI_FRAME_CTRL,
+		((timing->interlaced << 31) & 0x80000000) |
+		((timing->active_low_h << 29) & 0x20000000) |
+		((timing->active_low_v << 28) & 0x10000000));
+} /* hdmi_tx_video_setup */
+
+static void hdmi_tx_set_avi_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int i, mode = 0;
+	u8 avi_iframe[16]; /* two header + length + 13 data */
+	u8 checksum;
+	u32 sum, regVal;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: Core io is not initialized\n", __func__);
+		return;
+	}
+
+	switch (hdmi_ctrl->video_resolution) {
+	case HDMI_VFRMT_720x480p60_4_3:
+		mode = 0;
+		break;
+	case HDMI_VFRMT_720x480i60_16_9:
+		mode = 1;
+		break;
+	case HDMI_VFRMT_720x576p50_16_9:
+		mode = 2;
+		break;
+	case HDMI_VFRMT_720x576i50_16_9:
+		mode = 3;
+		break;
+	case HDMI_VFRMT_1280x720p60_16_9:
+		mode = 4;
+		break;
+	case HDMI_VFRMT_1280x720p50_16_9:
+		mode = 5;
+		break;
+	case HDMI_VFRMT_1920x1080p60_16_9:
+		mode = 6;
+		break;
+	case HDMI_VFRMT_1920x1080i60_16_9:
+		mode = 7;
+		break;
+	case HDMI_VFRMT_1920x1080p50_16_9:
+		mode = 8;
+		break;
+	case HDMI_VFRMT_1920x1080i50_16_9:
+		mode = 9;
+		break;
+	case HDMI_VFRMT_1920x1080p24_16_9:
+		mode = 10;
+		break;
+	case HDMI_VFRMT_1920x1080p30_16_9:
+		mode = 11;
+		break;
+	case HDMI_VFRMT_1920x1080p25_16_9:
+		mode = 12;
+		break;
+	case HDMI_VFRMT_640x480p60_4_3:
+		mode = 13;
+		break;
+	case HDMI_VFRMT_720x480p60_16_9:
+		mode = 14;
+		break;
+	case HDMI_VFRMT_720x576p50_4_3:
+		mode = 15;
+		break;
+	default:
+		DEV_INFO("%s: mode %d not supported\n", __func__,
+			hdmi_ctrl->video_resolution);
+		return;
+	}
+
+	/* InfoFrame Type = 82 */
+	avi_iframe[0]  = 0x82;
+	/* Version = 2 */
+	avi_iframe[1]  = 2;
+	/* Length of AVI InfoFrame = 13 */
+	avi_iframe[2]  = 13;
+
+	/* Data Byte 01: 0 Y1 Y0 A0 B1 B0 S1 S0 */
+	avi_iframe[3]  = hdmi_tx_avi_iframe_lut[0][mode];
+	avi_iframe[3] |= hdmi_edid_get_sink_scaninfo(
+		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID],
+		hdmi_ctrl->video_resolution);
+
+	/* Data Byte 02: C1 C0 M1 M0 R3 R2 R1 R0 */
+	avi_iframe[4]  = hdmi_tx_avi_iframe_lut[1][mode];
+	/* Data Byte 03: ITC EC2 EC1 EC0 Q1 Q0 SC1 SC0 */
+	avi_iframe[5]  = hdmi_tx_avi_iframe_lut[2][mode];
+	/* Data Byte 04: 0 VIC6 VIC5 VIC4 VIC3 VIC2 VIC1 VIC0 */
+	avi_iframe[6]  = hdmi_tx_avi_iframe_lut[3][mode];
+	/* Data Byte 05: 0 0 0 0 PR3 PR2 PR1 PR0 */
+	avi_iframe[7]  = hdmi_tx_avi_iframe_lut[4][mode];
+	/* Data Byte 06: LSB Line No of End of Top Bar */
+	avi_iframe[8]  = hdmi_tx_avi_iframe_lut[5][mode];
+	/* Data Byte 07: MSB Line No of End of Top Bar */
+	avi_iframe[9]  = hdmi_tx_avi_iframe_lut[6][mode];
+	/* Data Byte 08: LSB Line No of Start of Bottom Bar */
+	avi_iframe[10] = hdmi_tx_avi_iframe_lut[7][mode];
+	/* Data Byte 09: MSB Line No of Start of Bottom Bar */
+	avi_iframe[11] = hdmi_tx_avi_iframe_lut[8][mode];
+	/* Data Byte 10: LSB Pixel Number of End of Left Bar */
+	avi_iframe[12] = hdmi_tx_avi_iframe_lut[9][mode];
+	/* Data Byte 11: MSB Pixel Number of End of Left Bar */
+	avi_iframe[13] = hdmi_tx_avi_iframe_lut[10][mode];
+	/* Data Byte 12: LSB Pixel Number of Start of Right Bar */
+	avi_iframe[14] = hdmi_tx_avi_iframe_lut[11][mode];
+	/* Data Byte 13: MSB Pixel Number of Start of Right Bar */
+	avi_iframe[15] = hdmi_tx_avi_iframe_lut[12][mode];
+
+	sum = 0;
+	for (i = 0; i < 16; i++)
+		sum += avi_iframe[i];
+	sum &= 0xFF;
+	sum = 256 - sum;
+	checksum = (u8) sum;
+
+	regVal = avi_iframe[5];
+	regVal = regVal << 8 | avi_iframe[4];
+	regVal = regVal << 8 | avi_iframe[3];
+	regVal = regVal << 8 | checksum;
+	HDMI_REG_W(io->base, HDMI_AVI_INFO0, regVal);
+
+	regVal = avi_iframe[9];
+	regVal = regVal << 8 | avi_iframe[8];
+	regVal = regVal << 8 | avi_iframe[7];
+	regVal = regVal << 8 | avi_iframe[6];
+	HDMI_REG_W(io->base, HDMI_AVI_INFO1, regVal);
+
+	regVal = avi_iframe[13];
+	regVal = regVal << 8 | avi_iframe[12];
+	regVal = regVal << 8 | avi_iframe[11];
+	regVal = regVal << 8 | avi_iframe[10];
+	HDMI_REG_W(io->base, HDMI_AVI_INFO2, regVal);
+
+	regVal = avi_iframe[1];
+	regVal = regVal << 16 | avi_iframe[15];
+	regVal = regVal << 8 | avi_iframe[14];
+	HDMI_REG_W(io->base, HDMI_AVI_INFO3, regVal);
+
+	/* 0x3 for AVI InfFrame enable (every frame) */
+	HDMI_REG_W(io->base, HDMI_INFOFRAME_CTRL0,
+		HDMI_REG_R(io->base, HDMI_INFOFRAME_CTRL0) |
+		0x00000003L);
+} /* hdmi_tx_set_avi_infoframe */
+
+static void hdmi_tx_set_spd_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	u32 packet_header  = 0;
+	u32 check_sum      = 0;
+	u32 packet_payload = 0;
+	u32 packet_control = 0;
+
+	u8 *vendor_name = NULL;
+	u8 *product_description = NULL;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: Core io is not initialized\n", __func__);
+		return;
+	}
+
+	vendor_name = hdmi_ctrl->spd_vendor_name;
+	product_description = hdmi_ctrl->spd_product_description;
+
+	/* Setup Packet header and payload */
+	/*
+	 * 0x83 InfoFrame Type Code
+	 * 0x01 InfoFrame Version Number
+	 * 0x19 Length of Source Product Description InfoFrame
+	 */
+	packet_header  = 0x83 | (0x01 << 8) | (0x19 << 16);
+	HDMI_REG_W(io->base, HDMI_GENERIC1_HDR, packet_header);
+	check_sum += IFRAME_CHECKSUM_32(packet_header);
+
+	packet_payload = (vendor_name[3] & 0x7f)
+		| ((vendor_name[4] & 0x7f) << 8)
+		| ((vendor_name[5] & 0x7f) << 16)
+		| ((vendor_name[6] & 0x7f) << 24);
+	HDMI_REG_W(io->base, HDMI_GENERIC1_1, packet_payload);
+	check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+	/* Product Description (7-bit ASCII code) */
+	packet_payload = (vendor_name[7] & 0x7f)
+		| ((product_description[0] & 0x7f) << 8)
+		| ((product_description[1] & 0x7f) << 16)
+		| ((product_description[2] & 0x7f) << 24);
+	HDMI_REG_W(io->base, HDMI_GENERIC1_2, packet_payload);
+	check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+	packet_payload = (product_description[3] & 0x7f)
+		| ((product_description[4] & 0x7f) << 8)
+		| ((product_description[5] & 0x7f) << 16)
+		| ((product_description[6] & 0x7f) << 24);
+	HDMI_REG_W(io->base, HDMI_GENERIC1_3, packet_payload);
+	check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+	packet_payload = (product_description[7] & 0x7f)
+		| ((product_description[8] & 0x7f) << 8)
+		| ((product_description[9] & 0x7f) << 16)
+		| ((product_description[10] & 0x7f) << 24);
+	HDMI_REG_W(io->base, HDMI_GENERIC1_4, packet_payload);
+	check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+	packet_payload = (product_description[11] & 0x7f)
+		| ((product_description[12] & 0x7f) << 8)
+		| ((product_description[13] & 0x7f) << 16)
+		| ((product_description[14] & 0x7f) << 24);
+	HDMI_REG_W(io->base, HDMI_GENERIC1_5, packet_payload);
+	check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+	/*
+	 * Source Device Information
+	 * 00h unknown
+	 * 01h Digital STB
+	 * 02h DVD
+	 * 03h D-VHS
+	 * 04h HDD Video
+	 * 05h DVC
+	 * 06h DSC
+	 * 07h Video CD
+	 * 08h Game
+	 * 09h PC general
+	 */
+	packet_payload = (product_description[15] & 0x7f) | 0x00 << 8;
+	HDMI_REG_W(io->base, HDMI_GENERIC1_6, packet_payload);
+	check_sum += IFRAME_CHECKSUM_32(packet_payload);
+
+	/* Vendor Name (7bit ASCII code) */
+	packet_payload = ((vendor_name[0] & 0x7f) << 8)
+		| ((vendor_name[1] & 0x7f) << 16)
+		| ((vendor_name[2] & 0x7f) << 24);
+	check_sum += IFRAME_CHECKSUM_32(packet_payload);
+	packet_payload |= ((0x100 - (0xff & check_sum)) & 0xff);
+	HDMI_REG_W(io->base, HDMI_GENERIC1_0, packet_payload);
+
+	/*
+	 * GENERIC1_LINE | GENERIC1_CONT | GENERIC1_SEND
+	 * Setup HDMI TX generic packet control
+	 * Enable this packet to transmit every frame
+	 * Enable HDMI TX engine to transmit Generic packet 1
+	 */
+	packet_control = HDMI_REG_R_ND(io->base, HDMI_GEN_PKT_CTRL);
+	packet_control |= ((0x1 << 24) | (1 << 5) | (1 << 4));
+	HDMI_REG_W(io->base, HDMI_GEN_PKT_CTRL, packet_control);
+} /* hdmi_tx_set_spd_infoframe */
+
+/* todo: revisit when new HPD debouncing logic is avialble */
 static void hdmi_tx_hpd_state_timer(unsigned long data)
 {
 	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;
@@ -246,59 +1072,577 @@
 		DEV_ERR("%s: invalid input\n", __func__);
 } /* hdmi_tx_hpd_state_timer */
 
-static inline struct clk *hdmi_tx_get_clk(struct hdmi_tx_platform_data *pdata,
-	u32 clk_idx)
+static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
 {
-	if (!pdata || clk_idx > HDMI_TX_MAX_CLK) {
+	u32 reg_val = 0;
+
+	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
-		return NULL;
+		return;
 	}
 
-	return pdata->clk[clk_idx];
-} /* hdmi_tx_get_clk */
+	if (power_on) {
+		/* ENABLE */
+		reg_val |= BIT(0); /* Enable the block */
+		if (hdmi_edid_get_sink_mode(
+			hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) == 0) {
+			if (hdmi_ctrl->present_hdcp)
+				/* HDMI Encryption */
+				reg_val |= BIT(2);
+			reg_val |= BIT(1);
+		} else {
+			if (hdmi_ctrl->present_hdcp)
+				/* HDMI_Encryption_ON */
+				reg_val |= BIT(1) | BIT(2);
+			else
+				reg_val |= BIT(1);
+		}
+	} else {
+		reg_val = BIT(1);
+	}
 
-static int hdmi_tx_clk_set_rate(struct hdmi_tx_platform_data *pdata,
-	u32 clk_idx, unsigned long clk_rate)
+	HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base, HDMI_CTRL,
+		reg_val);
+
+	DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
+		power_on ? "Enable" : "Disable", reg_val);
+} /* hdmi_tx_set_mode */
+
+static int hdmi_tx_clk_update(struct hdmi_tx_platform_data *pdata, u32 clk_idx,
+	u32 enable)
 {
 	int rc = 0;
-	struct clk *clk = NULL;
+	struct clk *clk = hdmi_tx_get_clk(pdata, clk_idx);
 
-	if (!pdata) {
-		DEV_ERR("%s: invalid input\n", __func__);
-		return -EINVAL;
-	}
-
-	clk = hdmi_tx_get_clk(pdata, clk_idx);
 	if (clk) {
-		rc = clk_set_rate(clk, clk_rate);
-		if (IS_ERR_VALUE(rc))
-			DEV_ERR("%s: failed rc=%d\n", __func__, rc);
-		else
-			DEV_DBG("%s: clk=%d rate=%lu\n", __func__,
-				clk_idx, clk_rate);
+		DEV_DBG("%s: clk=%d en=%d\n", __func__, clk_idx, enable);
+		if (enable) {
+			rc = clk_prepare_enable(clk);
+			if (rc)
+				DEV_ERR("%s: clk=%d enable failed\n",
+				__func__, clk_idx);
+		} else {
+			clk_disable_unprepare(clk);
+		}
 	} else {
-		DEV_ERR("%s: FAILED: invalid clk_idx=%d\n", __func__, clk_idx);
+		DEV_ERR("%s: FAILED: invalid input for clk='%s'\n", __func__,
+			hdmi_tx_clk_name(clk_idx));
 		rc = -EINVAL;
 	}
 
 	return rc;
-} /* hdmi_tx_clk_set_rate */
+} /* hdmi_tx_clk_update */
 
-static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
+/* Note: Before accessing extpclk, always make sure that hdmi_ahb_clk is on */
+static int hdmi_tx_clk_ctrl_update(struct hdmi_tx_platform_data *pdata, int on)
 {
-	return 0;
-} /* hdmi_tx_power_on */
+	int  rc = 0;
+	DEV_DBG("%s: HDMI Clk: %s\n", __func__, on ? "Enable" : "Disable");
+
+	rc = hdmi_tx_clk_update(pdata, HDMI_TX_APP_CLK, on);
+	if (on && rc) {
+		DEV_ERR("%s: '%s' on failed\n", __func__,
+			hdmi_tx_clk_name(HDMI_TX_APP_CLK));
+		goto fail_hdmi_app_clk;
+	}
+	if (on) {
+		rc = hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, on);
+		if (rc) {
+			DEV_ERR("%s: '%s' on failed\n", __func__,
+				hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
+			goto fail_hdmi_ahb_clk;
+		}
+		rc = hdmi_tx_clk_update(pdata, HDMI_TX_EXTP_CLK, on);
+		if (rc) {
+			DEV_ERR("%s: '%s' on failed\n", __func__,
+				hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
+			goto fail_hdmi_extp_clk;
+		}
+	} else {
+		hdmi_tx_clk_update(pdata, HDMI_TX_EXTP_CLK, on);
+		hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, on);
+	}
+	return rc;
+
+fail_hdmi_extp_clk:
+	hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, 0);
+fail_hdmi_ahb_clk:
+	hdmi_tx_clk_update(pdata, HDMI_TX_APP_CLK, 0);
+fail_hdmi_app_clk:
+	return rc;
+} /* hdmi_tx_clk_ctrl_update */
+
+static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl,
+	enum hdmi_tx_power_module_type module, int config)
+{
+	int rc = 0;
+	struct dss_module_power *power_data = NULL;
+
+	if (!hdmi_ctrl || module >= HDMI_TX_MAX_PM) {
+		DEV_ERR("%s: Error: invalid input\n", __func__);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	power_data = &hdmi_ctrl->pdata.power_data[module];
+	if (!power_data) {
+		DEV_ERR("%s: Error: invalid power data\n", __func__);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (config)
+		rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
+			power_data->vreg_config, power_data->num_vreg, 1);
+	else
+		rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
+			power_data->vreg_config, power_data->num_vreg, 0);
+
+	if (rc)
+		DEV_ERR("%s: Failed to %s %s vreg. Error=%d\n",
+			__func__, config ? "config" : "deconfig",
+			hdmi_pm_name(module), rc);
+
+exit:
+	return rc;
+} /* hdmi_tx_config_power */
+
+static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
+	enum hdmi_tx_power_module_type module, int enable)
+{
+	int rc = 0;
+	struct dss_module_power *power_data = NULL;
+
+	if (!hdmi_ctrl || module >= HDMI_TX_MAX_PM) {
+		DEV_ERR("%s: Error: invalid input\n", __func__);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	power_data = &hdmi_ctrl->pdata.power_data[module];
+	if (!power_data) {
+		DEV_ERR("%s: Error: invalid power data\n", __func__);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	if (enable) {
+		rc = msm_dss_enable_vreg(power_data->vreg_config,
+			power_data->num_vreg, 1);
+		if (rc) {
+			DEV_ERR("%s: Failed to enable %s vreg. Error=%d\n",
+				__func__, hdmi_pm_name(module), rc);
+			goto error;
+		}
+
+		rc = msm_dss_enable_gpio(power_data->gpio_config,
+			power_data->num_gpio, enable);
+		if (rc) {
+			DEV_ERR("%s: Failed to enable %s gpio. Error=%d\n",
+				__func__, hdmi_pm_name(module), rc);
+			goto disable_vreg;
+		}
+	} else {
+		msm_dss_enable_gpio(power_data->gpio_config,
+			power_data->num_gpio, 0);
+		msm_dss_enable_vreg(power_data->vreg_config,
+			power_data->num_vreg, 0);
+	}
+
+	return rc;
+
+disable_vreg:
+	msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0);
+error:
+	return rc;
+} /* hdmi_tx_enable_power */
+
+static void hdmi_tx_core_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CEC_PM, 0);
+	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CORE_PM, 0);
+} /* hdmi_tx_core_off */
+
+static int hdmi_tx_core_on(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int rc = 0;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CORE_PM, 1);
+	if (rc) {
+		DEV_ERR("%s: core hdmi_msm_enable_power failed rc = %d\n",
+			__func__, rc);
+		goto error;
+	}
+	rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CEC_PM, 1);
+	if (rc) {
+		DEV_ERR("%s: cec hdmi_msm_enable_power failed rc = %d\n",
+			__func__, rc);
+		goto disable_core_power;
+	}
+
+	return rc;
+disable_core_power:
+	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CORE_PM, 0);
+error:
+	return rc;
+} /* hdmi_tx_core_on */
+
+static void hdmi_tx_phy_reset(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	unsigned int phy_reset_polarity = 0x0;
+	unsigned int pll_reset_polarity = 0x0;
+	unsigned int val;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: io not inititalized\n", __func__);
+		return;
+	}
+
+	val = HDMI_REG_R_ND(io->base, HDMI_PHY_CTRL);
+
+	phy_reset_polarity = val >> 3 & 0x1;
+	pll_reset_polarity = val >> 1 & 0x1;
+
+	if (phy_reset_polarity == 0)
+		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET);
+	else
+		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val & (~SW_RESET));
+
+	if (pll_reset_polarity == 0)
+		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET_PLL);
+	else
+		HDMI_REG_W_ND(io->base,
+			HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
+
+	if (phy_reset_polarity == 0)
+		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val & (~SW_RESET));
+	else
+		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET);
+
+	if (pll_reset_polarity == 0)
+		HDMI_REG_W_ND(io->base,
+			HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
+	else
+		HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET_PLL);
+} /* hdmi_tx_phy_reset */
+
+static void hdmi_tx_init_phy(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_PHY_IO];
+	if (!io->base) {
+		DEV_ERR("%s: Core io is not initialized\n", __func__);
+		return;
+	}
+
+	HDMI_REG_W_ND(io->base, HDMI_PHY_ANA_CFG0, 0x1B);
+	HDMI_REG_W_ND(io->base, HDMI_PHY_ANA_CFG1, 0xF2);
+	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_CFG0, 0x0);
+	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN0, 0x0);
+	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN1, 0x0);
+	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN2, 0x0);
+	HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN3, 0x0);
+
+	HDMI_REG_W_ND(io->base, HDMI_PHY_PD_CTRL1, 0x20);
+} /* hdmi_tx_init_phy */
+
+static void hdmi_tx_powerdown_phy(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	HDMI_REG_W_ND(hdmi_ctrl->pdata.io[HDMI_TX_PHY_IO].base,
+		HDMI_PHY_PD_CTRL0, 0x7F);
+} /* hdmi_tx_powerdown_phy */
+
+static int hdmi_tx_start(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int rc = 0;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+	/* todo: Audio */
+
+	hdmi_tx_set_mode(hdmi_ctrl, false);
+	mutex_lock(&hdmi_ctrl->mutex);
+	rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 1);
+	if (rc) {
+		DEV_ERR("%s: hdmi_tx_clk_enable failed.\n", __func__);
+		mutex_unlock(&hdmi_ctrl->mutex);
+		return rc;
+	}
+	mutex_unlock(&hdmi_ctrl->mutex);
+
+	hdmi_tx_init_phy(hdmi_ctrl);
+	HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
+		HDMI_USEC_REFTIMER, 0x0001001B);
+
+	hdmi_tx_set_mode(hdmi_ctrl, true);
+
+	hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution);
+	/* todo: Audio */
+	hdmi_tx_set_avi_infoframe(hdmi_ctrl);
+	/* todo: CONFIG_FB_MSM_HDMI_3D */
+	hdmi_tx_set_spd_infoframe(hdmi_ctrl);
+
+	/* Set IRQ for HPD */
+	HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
+		HDMI_HPD_INT_CTRL, 4 | (hdmi_ctrl->hpd_state ? 0 : 2));
+
+	/* todo: HDCP/CEC */
+
+	DEV_INFO("%s: HDMI Core: Initialized\n", __func__);
+
+	return rc;
+} /* hdmi_tx_start */
 
 static int hdmi_tx_power_off(struct mdss_panel_data *panel_data)
 {
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_panel_data(panel_data);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	DEV_INFO("%s: power: OFF (audio off, Reset Core)\n", __func__);
+	/* todo: Audio */
+	hdmi_tx_powerdown_phy(hdmi_ctrl);
+	hdmi_ctrl->panel_power_on = false;
+
+	mutex_lock(&hdmi_ctrl->mutex);
+	if (hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 0))
+		DEV_ERR("%s: hdmi_tx_clk_disable failed.\n", __func__);
+	mutex_unlock(&hdmi_ctrl->mutex);
+
+	hdmi_tx_core_off(hdmi_ctrl);
+
 	return 0;
 } /* hdmi_tx_power_off */
 
+static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
+{
+	int rc = 0;
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_panel_data(panel_data);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = hdmi_tx_core_on(hdmi_ctrl);
+	if (rc) {
+		DEV_ERR("%s: hdmi_msm_core_on failed\n", __func__);
+		return rc;
+	}
+
+	DEV_INFO("power: ON (%dx%d %ld)\n", hdmi_ctrl->xres, hdmi_ctrl->yres,
+		hdmi_ctrl->pixel_clk);
+
+	rc = hdmi_tx_set_video_fmt(hdmi_ctrl);
+	if (rc) {
+		DEV_ERR("%s: cannot set video_fmt.rc=%d\n", __func__, rc);
+		hdmi_tx_core_off(hdmi_ctrl);
+		return rc;
+	}
+
+	mutex_lock(&hdmi_ctrl->mutex);
+	hdmi_ctrl->panel_power_on = true;
+
+	/* todo: check hdmi_tx_is_controller_on when hpd is on */
+	if (hdmi_ctrl->hpd_state) {
+		DEV_DBG("%s: Turning HDMI on\n", __func__);
+		mutex_unlock(&hdmi_ctrl->mutex);
+		rc = hdmi_tx_start(hdmi_ctrl);
+		if (rc) {
+			DEV_ERR("%s: hdmi_tx_start failed. rc=%d\n",
+				__func__, rc);
+			hdmi_tx_power_off(panel_data);
+			return rc;
+		}
+		/* todo: HDCP */
+	} else {
+		mutex_unlock(&hdmi_ctrl->mutex);
+	}
+
+	hdmi_reg_dump(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
+		hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].len, "HDMI-ON: ");
+
+	DEV_INFO("%s: HDMI=%s DVI= %s\n", __func__,
+		hdmi_tx_is_controller_on(hdmi_ctrl) ? "ON" : "OFF" ,
+		hdmi_tx_is_dvi_mode(hdmi_ctrl) ? "ON" : "OFF");
+
+	return 0;
+} /* hdmi_tx_power_on */
+
+static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int rc = 0;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (!hdmi_ctrl->hpd_initialized) {
+		DEV_DBG("%s: HPD is already OFF, returning\n", __func__);
+		return;
+	}
+
+	DEV_DBG("%s: (timer, 5V, IRQ off)\n", __func__);
+	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
+	mdss_disable_irq(&hdmi_tx_hw);
+
+	hdmi_tx_set_mode(hdmi_ctrl, false);
+
+	mutex_lock(&hdmi_ctrl->mutex);
+	rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 0);
+	if (rc)
+		DEV_INFO("%s: Failed to disable clock. Error=%d\n",
+			__func__, rc);
+	mutex_unlock(&hdmi_ctrl->mutex);
+
+	rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, 0);
+	if (rc)
+		DEV_INFO("%s: Failed to disable hpd power. Error=%d\n",
+			__func__, rc);
+
+	hdmi_ctrl->hpd_initialized = false;
+} /* hdmi_tx_hpd_off */
+
+static int hdmi_tx_hpd_on(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	u32 reg_val;
+	int rc = 0;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	if (hdmi_ctrl->hpd_initialized) {
+		DEV_DBG("%s: HPD is already ON\n", __func__);
+	} else {
+		rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, true);
+		if (rc) {
+			DEV_ERR("%s: Failed to enable hpd power. rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+
+		mutex_lock(&hdmi_ctrl->mutex);
+		rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, true);
+		if (rc) {
+			DEV_ERR("%s: Failed to enable clocks. rc=%d\n",
+				__func__, rc);
+			mutex_unlock(&hdmi_ctrl->mutex);
+			goto disable_hpd_power;
+		}
+		mutex_unlock(&hdmi_ctrl->mutex);
+
+		hdmi_reg_dump(io->base, io->len, "HDMI-INIT: ");
+
+		hdmi_tx_set_mode(hdmi_ctrl, false);
+		hdmi_tx_phy_reset(hdmi_ctrl);
+		hdmi_tx_set_mode(hdmi_ctrl, true);
+
+		HDMI_REG_W(io->base, HDMI_USEC_REFTIMER, 0x0001001B);
+
+		/* set timeout to 4.1ms (max) for hardware debounce */
+		reg_val = HDMI_REG_R(io->base, HDMI_HPD_CTRL) | 0x1FFF;
+
+		/* Toggle HPD circuit to trigger HPD sense */
+		HDMI_REG_W(io->base, HDMI_HPD_CTRL,
+			~(1 << 28) & reg_val);
+		HDMI_REG_W(io->base, HDMI_HPD_CTRL, (1 << 28) | reg_val);
+
+		hdmi_ctrl->hpd_initialized = true;
+
+		/* Check HPD State */
+		mdss_enable_irq(&hdmi_tx_hw);
+	}
+
+	/* Set HPD state machine: ensure at least 2 readouts */
+	mutex_lock(&hdmi_ctrl->mutex);
+	hdmi_ctrl->hpd_stable = 0;
+	hdmi_ctrl->hpd_prev_state = true;
+	hdmi_ctrl->hpd_state = false;
+	hdmi_ctrl->hpd_cable_chg_detected = true;
+	mutex_unlock(&hdmi_ctrl->mutex);
+	mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2);
+
+	return 0;
+
+disable_hpd_power:
+	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, false);
+
+	return rc;
+} /* hdmi_tx_hpd_on */
+
+static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on)
+{
+	int rc = 0;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	DEV_INFO("%s: %d\n", __func__, on);
+	if (on) {
+		rc = hdmi_tx_hpd_on(hdmi_ctrl);
+	} else {
+		hdmi_tx_hpd_off(hdmi_ctrl);
+		/* Set HDMI switch node to 0 on HPD feature disable */
+		switch_set_state(&hdmi_ctrl->sdev, 0);
+		DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
+			hdmi_ctrl->sdev.state);
+	}
+
+	return rc;
+} /* hdmi_tx_sysfs_enable_hpd */
+
 static irqreturn_t hdmi_tx_isr(int irq, void *data)
 {
 	u32 hpd_int_status;
 	u32 hpd_int_ctrl;
-	struct hdmi_tx_io_data *io = NULL;
+	struct dss_io_data *io = NULL;
 	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;
 
 	if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
@@ -339,6 +1683,9 @@
 		return IRQ_HANDLED;
 	}
 
+	if (!hdmi_ddc_isr(&hdmi_ctrl->ddc_ctrl))
+		return IRQ_HANDLED;
+
 	DEV_DBG("%s: HPD<Ctrl=%04x, State=%04x>\n", __func__, hpd_int_ctrl,
 		hpd_int_status);
 
@@ -400,26 +1747,6 @@
 	}
 	pdata->clk[HDMI_TX_EXTP_CLK] = clk;
 
-	/*
-	 * extpclk src is hdmi phy pll. This phy pll programming requires
-	 * hdmi_ahb_clk. So enable it and then disable.
-	 */
-	rc = clk_prepare_enable(pdata->clk[HDMI_TX_AHB_CLK]);
-	if (rc) {
-		DEV_ERR("%s: failed to enable '%s' clk\n", __func__,
-			hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
-		goto error;
-	}
-	rc = hdmi_tx_clk_set_rate(pdata, HDMI_TX_EXTP_CLK,
-		HDMI_TX_EXTP_CLK_DEFAULT);
-	if (rc) {
-		DEV_ERR("%s: FAILED: '%s' clk set rate\n", __func__,
-			hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
-		clk_disable_unprepare(pdata->clk[HDMI_TX_AHB_CLK]);
-		goto error;
-	}
-	clk_disable_unprepare(pdata->clk[HDMI_TX_AHB_CLK]);
-
 	return rc;
 
 error:
@@ -434,8 +1761,11 @@
 		return;
 	}
 
+	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID])
+		hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
+
 	switch_dev_unregister(&hdmi_ctrl->sdev);
-	del_timer(&hdmi_ctrl->hpd_state_timer);
+	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
 	if (hdmi_ctrl->workq)
 		destroy_workqueue(hdmi_ctrl->workq);
 	mutex_destroy(&hdmi_ctrl->mutex);
@@ -472,6 +1802,10 @@
 		goto fail_create_workq;
 	}
 
+	/* todo: May be move this ? */
+	hdmi_ctrl->ddc_ctrl.base = pdata->io[HDMI_TX_CORE_IO].base;
+	init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done);
+
 	INIT_WORK(&hdmi_ctrl->hpd_state_work, hdmi_tx_hpd_state_work);
 	init_timer(&hdmi_ctrl->hpd_state_timer);
 	hdmi_ctrl->hpd_state_timer.function = hdmi_tx_hpd_state_timer;
@@ -487,7 +1821,7 @@
 	return 0;
 
 fail_switch_dev:
-	del_timer(&hdmi_ctrl->hpd_state_timer);
+	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
 fail_create_workq:
 	if (hdmi_ctrl->workq)
 		destroy_workqueue(hdmi_ctrl->workq);
@@ -508,7 +1842,7 @@
 	hdmi_ctrl->panel_data.on = hdmi_tx_power_on;
 	hdmi_ctrl->panel_data.off = hdmi_tx_power_off;
 
-	hdmi_ctrl->video_resolution = HDMI_VFRMT_1920x1080p60_16_9;
+	hdmi_ctrl->video_resolution = DEFAULT_VIDEO_RESOLUTION;
 	rc = hdmi_tx_init_panel_info(hdmi_ctrl->video_resolution,
 		&hdmi_ctrl->panel_data.panel_info);
 	if (rc) {
@@ -525,6 +1859,84 @@
 	return rc;
 } /* hdmi_tx_register_panel */
 
+static void hdmi_tx_deinit_resource(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int i;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	/* CLK */
+	hdmi_tx_clk_deinit(&hdmi_ctrl->pdata);
+
+	/* VREG */
+	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--) {
+		if (hdmi_tx_config_power(hdmi_ctrl, i, 0))
+			DEV_ERR("%s: '%s' power deconfig fail\n",
+				__func__, hdmi_pm_name(i));
+	}
+
+	/* IO */
+	for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--) {
+		if (hdmi_ctrl->pdata.io[i].base)
+			iounmap(hdmi_ctrl->pdata.io[i].base);
+		hdmi_ctrl->pdata.io[i].base = NULL;
+		hdmi_ctrl->pdata.io[i].len = 0;
+	}
+} /* hdmi_tx_deinit_resource */
+
+static int hdmi_tx_init_resource(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int i, rc = 0;
+	struct hdmi_tx_platform_data *pdata = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = &hdmi_ctrl->pdata;
+
+	/* IO */
+	for (i = 0; i < HDMI_TX_MAX_IO; i++) {
+		rc = msm_dss_ioremap_byname(hdmi_ctrl->pdev, &pdata->io[i],
+			hdmi_tx_io_name(i));
+		if (rc) {
+			DEV_ERR("%s: '%s' remap failed\n", __func__,
+				hdmi_tx_io_name(i));
+			goto error;
+		}
+		DEV_INFO("%s: '%s': start = 0x%x, len=0x%x\n", __func__,
+			hdmi_tx_io_name(i), (u32)pdata->io[i].base,
+			pdata->io[i].len);
+	}
+
+	/* VREG */
+	for (i = 0; i < HDMI_TX_MAX_PM; i++) {
+		rc = hdmi_tx_config_power(hdmi_ctrl, i, 1);
+		if (rc) {
+			DEV_ERR("%s: '%s' power config failed.rc=%d\n",
+				__func__, hdmi_pm_name(i), rc);
+			goto error;
+		}
+	}
+
+	/* CLK */
+	rc = hdmi_tx_clk_init(hdmi_ctrl->pdev, pdata);
+	if (rc) {
+		DEV_ERR("%s: FAILED: clk init. rc=%d\n", __func__, rc);
+		goto error;
+	}
+
+	return rc;
+
+error:
+	hdmi_tx_deinit_resource(hdmi_ctrl);
+	return rc;
+} /* hdmi_tx_init_resource */
+
 static void hdmi_tx_put_dt_vreg_data(struct device *dev,
 	struct dss_module_power *module_power)
 {
@@ -806,7 +2218,6 @@
 		if (strnstr(st, mod_name, strlen(st))) {
 			ndx_mask |= BIT(i);
 			mod_gpio_total++;
-			continue;
 		}
 	}
 
@@ -863,47 +2274,6 @@
 	return rc;
 } /* hdmi_tx_get_dt_gpio_data */
 
-static struct resource *hdmi_tx_get_res_byname(struct platform_device *pdev,
-	unsigned int type, const char *name)
-{
-	struct resource *res = NULL;
-
-	res = platform_get_resource_byname(pdev, type, name);
-	if (!res)
-		DEV_ERR("%s: '%s' resource not found\n", __func__, name);
-
-	return res;
-} /* hdmi_tx_get_res_byname */
-
-static int hdmi_tx_ioremap_byname(struct platform_device *pdev,
-	struct hdmi_tx_io_data *io_data, u32 io_type)
-{
-	struct resource *res = NULL;
-
-	if (!pdev) {
-		DEV_ERR("%s: invalid input\n", __func__);
-		return -EINVAL;
-	}
-
-	res = hdmi_tx_get_res_byname(pdev, IORESOURCE_MEM,
-		hdmi_tx_io_name(io_type));
-	if (!res) {
-		DEV_ERR("%s: '%s' hdmi_tx_get_res_byname failed\n", __func__,
-			hdmi_tx_io_name(io_type));
-		return -ENODEV;
-	}
-
-	io_data->len = resource_size(res);
-	io_data->base = ioremap(res->start, io_data->len);
-	if (!io_data->base) {
-		DEV_ERR("%s: '%s' ioremap failed\n", __func__,
-			hdmi_tx_io_name(io_type));
-		return -EIO;
-	}
-
-	return 0;
-} /* hdmi_tx_ioremap_byname */
-
 static void hdmi_tx_put_dt_data(struct device *dev,
 	struct hdmi_tx_platform_data *pdata)
 {
@@ -913,20 +2283,11 @@
 		return;
 	}
 
-	hdmi_tx_clk_deinit(pdata);
-
 	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
 		hdmi_tx_put_dt_vreg_data(dev, &pdata->power_data[i]);
 
 	for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
 		hdmi_tx_put_dt_gpio_data(dev, &pdata->power_data[i]);
-
-	for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--) {
-		if (pdata->io[i].base)
-			iounmap(pdata->io[i].base);
-		pdata->io[i].base = NULL;
-		pdata->io[i].len = 0;
-	}
 } /* hdmi_tx_put_dt_data */
 
 static int hdmi_tx_get_dt_data(struct platform_device *pdev,
@@ -950,19 +2311,6 @@
 	}
 	DEV_DBG("%s: id=%d\n", __func__, pdev->id);
 
-	/* IO */
-	for (i = 0; i < HDMI_TX_MAX_IO; i++) {
-		rc = hdmi_tx_ioremap_byname(pdev, &pdata->io[i], i);
-		if (rc) {
-			DEV_ERR("%s: '%s' remap failed\n", __func__,
-				hdmi_tx_io_name(i));
-			goto error;
-		}
-		DEV_INFO("%s: '%s': start = 0x%x, len=0x%x\n", __func__,
-			hdmi_tx_io_name(i), (u32)pdata->io[i].base,
-			pdata->io[i].len);
-	}
-
 	/* GPIO */
 	for (i = 0; i < HDMI_TX_MAX_PM; i++) {
 		rc = hdmi_tx_get_dt_gpio_data(&pdev->dev,
@@ -985,13 +2333,6 @@
 		}
 	}
 
-	/* CLK */
-	rc = hdmi_tx_clk_init(pdev, pdata);
-	if (rc) {
-		DEV_ERR("%s: FAILED: clk init. rc=%d\n", __func__, rc);
-		goto error;
-	}
-
 	return rc;
 
 error:
@@ -1028,6 +2369,13 @@
 		goto failed_dt_data;
 	}
 
+	rc = hdmi_tx_init_resource(hdmi_ctrl);
+	if (rc) {
+		DEV_ERR("%s: FAILED: resource init. rc=%d\n",
+			__func__, rc);
+		goto failed_res_init;
+	}
+
 	rc = hdmi_tx_dev_init(hdmi_ctrl);
 	if (rc) {
 		DEV_ERR("%s: FAILED: hdmi_tx_dev_init. rc=%d\n", __func__, rc);
@@ -1040,11 +2388,28 @@
 		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;
+	}
+
 	return rc;
 
+failed_init_features:
+	hdmi_tx_sysfs_remove(hdmi_ctrl);
 failed_reg_panel:
 	hdmi_tx_dev_deinit(hdmi_ctrl);
 failed_dev_init:
+	hdmi_tx_deinit_resource(hdmi_ctrl);
+failed_res_init:
 	hdmi_tx_put_dt_data(&pdev->dev, &hdmi_ctrl->pdata);
 failed_dt_data:
 	devm_kfree(&pdev->dev, hdmi_ctrl);
@@ -1060,7 +2425,9 @@
 		return -ENODEV;
 	}
 
+	hdmi_tx_sysfs_remove(hdmi_ctrl);
 	hdmi_tx_dev_deinit(hdmi_ctrl);
+	hdmi_tx_deinit_resource(hdmi_ctrl);
 	hdmi_tx_put_dt_data(&pdev->dev, &hdmi_ctrl->pdata);
 	devm_kfree(&hdmi_ctrl->pdev->dev, hdmi_ctrl);
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 2e175ee..7e37d28 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -17,11 +17,6 @@
 #include "mdss_hdmi_util.h"
 #include "mdss_io_util.h"
 
-#define HDMI_TX_EXTP_CLK_DEFAULT 148500000
-#define HDMI_TX_EXTP_CLK_LOW     148500000
-#define HDMI_TX_EXTP_CLK_NOMINAL 297000000
-#define HDMI_TX_EXTP_CLK_TURBO   297000000 /* ToDo: Find correct value */
-
 enum hdmi_tx_clk_type {
 	HDMI_TX_AHB_CLK,
 	HDMI_TX_APP_CLK,
@@ -43,14 +38,9 @@
 	HDMI_TX_MAX_PM
 };
 
-struct hdmi_tx_io_data {
-	u32 len;
-	void __iomem *base;
-};
-
 struct hdmi_tx_platform_data {
 	/* Data filled from device tree nodes */
-	struct hdmi_tx_io_data io[HDMI_TX_MAX_IO];
+	struct dss_io_data io[HDMI_TX_MAX_IO];
 	struct dss_module_power power_data[HDMI_TX_MAX_PM];
 
 	/* clk and regulator handles */
@@ -88,6 +78,10 @@
 
 	u8 spd_vendor_name[8];
 	u8 spd_product_description[16];
+
+	struct hdmi_tx_ddc_ctrl ddc_ctrl;
+
+	void *feature_data[HDMI_TX_FEAT_MAX];
 };
 
 #endif /* __MDSS_HDMI_TX_H__ */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index e86f32b..3ba9f89 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -446,8 +446,8 @@
 const char *hdmi_get_single_video_3d_fmt_2string(u32 format)
 {
 	switch (format) {
-	case TOP_AND_BOTTOM: return "TAB";
-	case FRAME_PACKING: return "FP";
+	case TOP_AND_BOTTOM:	return "TAB";
+	case FRAME_PACKING:	return "FP";
 	case SIDE_BY_SIDE_HALF: return "SSH";
 	}
 	return "";
@@ -483,3 +483,625 @@
 
 	return len;
 } /* hdmi_get_video_3d_fmt_2string */
+
+static void hdmi_ddc_print_data(struct hdmi_tx_ddc_data *ddc_data,
+	const char *caller)
+{
+	if (!ddc_data) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	DEV_DBG("%s: buf=%p, d_len=0x%x, d_addr=0x%x, no_align=%d\n",
+		caller, ddc_data->data_buf, ddc_data->data_len,
+		ddc_data->dev_addr, ddc_data->no_align);
+	DEV_DBG("%s: offset=0x%x, req_len=0x%x, retry=%d, what=%s\n",
+		caller, ddc_data->offset, ddc_data->request_len,
+		ddc_data->retry, ddc_data->what);
+} /* hdmi_ddc_print_data */
+
+static int hdmi_ddc_clear_irq(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
+	char *what)
+{
+	u32 reg_val, time_out_count;
+
+	if (!ddc_ctrl || !ddc_ctrl->base) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	/* clear pending and enable interrupt */
+	time_out_count = 0xFFFF;
+	do {
+		--time_out_count;
+		/* Clear and Enable DDC interrupt */
+		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL,
+			BIT(2) | BIT(1));
+		reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
+	} while ((reg_val & BIT(0)) && time_out_count);
+
+	if (!time_out_count) {
+		DEV_ERR("%s[%s]: timedout\n", __func__, what);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+} /*hdmi_ddc_clear_irq */
+
+static int hdmi_ddc_read_retry(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
+	struct hdmi_tx_ddc_data *ddc_data)
+{
+	u32 reg_val, ndx, time_out_count;
+	int status = 0;
+	int log_retry_fail;
+
+	if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!ddc_data->data_buf) {
+		status = -EINVAL;
+		DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what);
+		goto error;
+	}
+
+	hdmi_ddc_print_data(ddc_data, __func__);
+
+	log_retry_fail = ddc_data->retry != 1;
+again:
+	status = hdmi_ddc_clear_irq(ddc_ctrl, ddc_data->what);
+	if (status)
+		goto error;
+
+	/* Ensure Device Address has LSB set to 0 to indicate Slave addr read */
+	ddc_data->dev_addr &= 0xFE;
+
+	/*
+	 * 1. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #1
+	 *    DATA_RW = 0x0 (write)
+	 *    DATA = linkAddress (primary link address and writing)
+	 *    INDEX = 0x0 (initial offset into buffer)
+	 *    INDEX_WRITE = 0x1 (setting initial offset)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+		BIT(31) | (ddc_data->dev_addr << 8));
+
+	/*
+	 * 2. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #2
+	 *    DATA_RW = 0x0 (write)
+	 *    DATA = offsetAddress
+	 *    INDEX = 0x0
+	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
+
+	/*
+	 * 3. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #3
+	 *    DATA_RW = 0x0 (write)
+	 *    DATA = linkAddress + 1 (primary link address 0x74 and reading)
+	 *    INDEX = 0x0
+	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+		(ddc_data->dev_addr | BIT(0)) << 8);
+
+	/* Data setup is complete, now setup the transaction characteristics */
+
+	/*
+	 * 4. Write to HDMI_I2C_TRANSACTION0 with the following fields set in
+	 *    order to handle characteristics of portion #1 and portion #2
+	 *    RW0 = 0x0 (write)
+	 *    START0 = 0x1 (insert START bit)
+	 *    STOP0 = 0x0 (do NOT insert STOP bit)
+	 *    CNT0 = 0x1 (single byte transaction excluding address)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+
+	/*
+	 * 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
+	 *    order to handle characteristics of portion #3
+	 *    RW1 = 0x1 (read)
+	 *    START1 = 0x1 (insert START bit)
+	 *    STOP1 = 0x1 (insert STOP bit)
+	 *    CNT1 = data_len   (it's 128 (0x80) for a blk read)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1,
+		BIT(0) | BIT(12) | BIT(13) | (ddc_data->request_len << 16));
+
+	/* Trigger the I2C transfer */
+
+	/*
+	 * 6. Write to HDMI_I2C_CONTROL to kick off the hardware.
+	 *    Note that NOTHING has been transmitted on the DDC lines up to this
+	 *    point.
+	 *    TRANSACTION_CNT = 0x1 (execute transaction0 followed by
+	 *    transaction1)
+	 *    SEND_RESET = Set to 1 to send reset sequence
+	 *    GO = 0x1 (kicks off hardware)
+	 */
+	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(20));
+
+	time_out_count = wait_for_completion_interruptible_timeout(
+		&ddc_ctrl->ddc_sw_done, HZ/2);
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, BIT(1));
+	if (!time_out_count) {
+		if (ddc_data->retry-- > 0) {
+			DEV_INFO("%s: failed timout, retry=%d\n", __func__,
+				ddc_data->retry);
+			goto again;
+		}
+		status = -ETIMEDOUT;
+		DEV_ERR("%s: timedout(7), Int Ctrl=%08x\n", __func__,
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+		DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
+			__func__,
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+		goto error;
+	}
+
+	/* Read DDC status */
+	reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+	reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
+
+	/* Check if any NACK occurred */
+	if (reg_val) {
+		/* SW_STATUS_RESET */
+		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+
+		if (ddc_data->retry == 1)
+			/* SOFT_RESET */
+			HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+
+		if (ddc_data->retry-- > 0) {
+			DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n",
+				__func__, ddc_data->what, reg_val,
+				ddc_data->retry);
+			DEV_DBG("%s: daddr=0x%02x,off=0x%02x,len=%d\n",
+				__func__, ddc_data->dev_addr,
+				ddc_data->offset, ddc_data->data_len);
+			goto again;
+		}
+		status = -EIO;
+		if (log_retry_fail) {
+			DEV_ERR("%s(%s): failed NACK=0x%08x\n",
+				__func__, ddc_data->what, reg_val);
+			DEV_ERR("%s: daddr=0x%02x,off=0x%02x,len=%d\n",
+				__func__, ddc_data->dev_addr,
+				ddc_data->offset, ddc_data->data_len);
+		}
+		goto error;
+	}
+
+	/*
+	 * 8. ALL data is now available and waiting in the DDC buffer.
+	 *    Read HDMI_I2C_DATA with the following fields set
+	 *    RW = 0x1 (read)
+	 *    DATA = BCAPS (this is field where data is pulled from)
+	 *    INDEX = 0x3 (where the data has been placed in buffer by hardware)
+	 *    INDEX_WRITE = 0x1 (explicitly define offset)
+	 */
+	/* Write this data to DDC buffer */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+		BIT(0) | (3 << 16) | BIT(31));
+
+	/* Discard first byte */
+	HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+	for (ndx = 0; ndx < ddc_data->data_len; ++ndx) {
+		reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+		ddc_data->data_buf[ndx] = (u8)((reg_val & 0x0000FF00) >> 8);
+	}
+
+	DEV_DBG("%s[%s] success\n", __func__, ddc_data->what);
+
+error:
+	return status;
+} /* hdmi_ddc_read_retry */
+
+void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
+{
+	if (!ddc_ctrl || !ddc_ctrl->base) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	/* Configure Pre-Scale multiplier & Threshold */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_SPEED, (10 << 16) | (2 << 0));
+
+	/*
+	 * Setting 31:24 bits : Time units to wait before timeout
+	 * when clock is being stalled by external sink device
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_SETUP, 0xFF000000);
+
+	/* Enable reference timer to 27 micro-seconds */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_REF, (1 << 16) | (27 << 0));
+} /* hdmi_ddc_config */
+
+int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
+{
+	int rc = -1;
+	u32 ddc_int_ctrl;
+
+	if (!ddc_ctrl || !ddc_ctrl->base) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ddc_int_ctrl = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
+	if ((ddc_int_ctrl & BIT(2)) && (ddc_int_ctrl & BIT(0))) {
+		/* SW_DONE INT occured, clr it */
+		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL,
+			ddc_int_ctrl | BIT(1));
+		complete(&ddc_ctrl->ddc_sw_done);
+		return 0;
+	}
+
+	DEV_DBG("%s: ddc_int_ctrl=%04x\n", __func__, ddc_int_ctrl);
+
+	return rc;
+} /* hdmi_ddc_isr */
+
+int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
+	struct hdmi_tx_ddc_data *ddc_data)
+{
+	int rc = 0;
+
+	if (!ddc_ctrl || !ddc_data) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = hdmi_ddc_read_retry(ddc_ctrl, ddc_data);
+	if (!rc)
+		return rc;
+
+	if (ddc_data->no_align) {
+		rc = hdmi_ddc_read_retry(ddc_ctrl, ddc_data);
+	} else {
+		ddc_data->request_len = 32 * ((ddc_data->data_len + 31) / 32);
+		rc = hdmi_ddc_read_retry(ddc_ctrl, ddc_data);
+	}
+
+	return rc;
+} /* hdmi_ddc_read */
+
+int hdmi_ddc_read_seg(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
+	struct hdmi_tx_ddc_data *ddc_data)
+{
+	int status = 0;
+	u32 reg_val, ndx, time_out_count;
+	int log_retry_fail;
+	int seg_addr = 0x60, seg_num = 0x01;
+
+	if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!ddc_data->data_buf) {
+		status = -EINVAL;
+		DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what);
+		goto error;
+	}
+
+	log_retry_fail = ddc_data->retry != 1;
+
+again:
+	status = hdmi_ddc_clear_irq(ddc_ctrl, ddc_data->what);
+	if (status)
+		goto error;
+
+	/* Ensure Device Address has LSB set to 0 to indicate Slave addr read */
+	ddc_data->dev_addr &= 0xFE;
+
+	/*
+	 * 1. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #1
+	 *    DATA_RW = 0x0 (write)
+	 *    DATA = linkAddress (primary link address and writing)
+	 *    INDEX = 0x0 (initial offset into buffer)
+	 *    INDEX_WRITE = 0x1 (setting initial offset)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, BIT(31) | (seg_addr << 8));
+
+	/*
+	 * 2. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #2
+	 *    DATA_RW = 0x0 (write)
+	 *    DATA = offsetAddress
+	 *    INDEX = 0x0
+	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, seg_num << 8);
+
+	/*
+	 * 3. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #3
+	 *    DATA_RW = 0x0 (write)
+	 *    DATA = linkAddress + 1 (primary link address 0x74 and reading)
+	 *    INDEX = 0x0
+	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->dev_addr << 8);
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+		(ddc_data->dev_addr | BIT(0)) << 8);
+
+	/* Data setup is complete, now setup the transaction characteristics */
+
+	/*
+	 * 4. Write to HDMI_I2C_TRANSACTION0 with the following fields set in
+	 *    order to handle characteristics of portion #1 and portion #2
+	 *    RW0 = 0x0 (write)
+	 *    START0 = 0x1 (insert START bit)
+	 *    STOP0 = 0x0 (do NOT insert STOP bit)
+	 *    CNT0 = 0x1 (single byte transaction excluding address)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+
+	/*
+	 * 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
+	 *    order to handle characteristics of portion #3
+	 *    RW1 = 0x1 (read)
+	 *    START1 = 0x1 (insert START bit)
+	 *    STOP1 = 0x1 (insert STOP bit)
+	 *    CNT1 = data_len   (it's 128 (0x80) for a blk read)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1, BIT(12) | BIT(16));
+
+	/*
+	 * 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
+	 *    order to handle characteristics of portion #3
+	 *    RW1 = 0x1 (read)
+	 *    START1 = 0x1 (insert START bit)
+	 *    STOP1 = 0x1 (insert STOP bit)
+	 *    CNT1 = data_len   (it's 128 (0x80) for a blk read)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS2,
+		BIT(0) | BIT(12) | BIT(13) | (ddc_data->request_len << 16));
+
+	/* Trigger the I2C transfer */
+
+	/*
+	 * 6. Write to HDMI_I2C_CONTROL to kick off the hardware.
+	 *    Note that NOTHING has been transmitted on the DDC lines up to this
+	 *    point.
+	 *    TRANSACTION_CNT = 0x2 (execute transaction0 followed by
+	 *    transaction1)
+	 *    GO = 0x1 (kicks off hardware)
+	 */
+	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(21));
+
+	time_out_count = wait_for_completion_interruptible_timeout(
+		&ddc_ctrl->ddc_sw_done, HZ/2);
+
+	reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
+	if (!time_out_count) {
+		if (ddc_data->retry-- > 0) {
+			DEV_INFO("%s: failed timout, retry=%d\n", __func__,
+				ddc_data->retry);
+			goto again;
+		}
+		status = -ETIMEDOUT;
+		DEV_ERR("%s: timedout(7), Int Ctrl=%08x\n", __func__,
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+		DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
+			__func__,
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+		goto error;
+	}
+
+	/* Read DDC status */
+	reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+	reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
+
+	/* Check if any NACK occurred */
+	if (reg_val) {
+		/* SW_STATUS_RESET */
+		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+		if (ddc_data->retry == 1)
+			/* SOFT_RESET */
+			HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+		if (ddc_data->retry-- > 0) {
+			DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n",
+				__func__, ddc_data->what, reg_val,
+				ddc_data->retry);
+			DEV_DBG("%s: daddr=0x%02x,off=0x%02x,len=%d\n",
+				__func__, ddc_data->dev_addr,
+				ddc_data->offset, ddc_data->data_len);
+			goto again;
+		}
+		status = -EIO;
+		if (log_retry_fail) {
+			DEV_ERR("%s(%s): failed NACK=0x%08x\n",
+				__func__, ddc_data->what, reg_val);
+			DEV_ERR("%s: daddr=0x%02x,off=0x%02x,len=%d\n",
+				__func__, ddc_data->dev_addr,
+				ddc_data->offset, ddc_data->data_len);
+		}
+		goto error;
+	}
+
+	/*
+	 * 8. ALL data is now available and waiting in the DDC buffer.
+	 *    Read HDMI_I2C_DATA with the following fields set
+	 *    RW = 0x1 (read)
+	 *    DATA = BCAPS (this is field where data is pulled from)
+	 *    INDEX = 0x5 (where the data has been placed in buffer by hardware)
+	 *    INDEX_WRITE = 0x1 (explicitly define offset)
+	 */
+	/* Write this data to DDC buffer */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+		BIT(0) | (5 << 16) | BIT(31));
+
+	/* Discard first byte */
+	HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+
+	for (ndx = 0; ndx < ddc_data->data_len; ++ndx) {
+		reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+		ddc_data->data_buf[ndx] = (u8) ((reg_val & 0x0000FF00) >> 8);
+	}
+
+	DEV_DBG("%s[%s] success\n", __func__, ddc_data->what);
+
+error:
+	return status;
+} /* hdmi_ddc_read_seg */
+
+int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
+	struct hdmi_tx_ddc_data *ddc_data)
+{
+	u32 reg_val, ndx;
+	int status = 0, retry = 10;
+	u32 time_out_count;
+
+	if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!ddc_data->data_buf) {
+		status = -EINVAL;
+		DEV_ERR("%s[%s]: invalid buf\n", __func__, ddc_data->what);
+		goto error;
+	}
+
+again:
+	status = hdmi_ddc_clear_irq(ddc_ctrl, ddc_data->what);
+	if (status)
+		goto error;
+
+	/* Ensure Device Address has LSB set to 0 to indicate Slave addr read */
+	ddc_data->dev_addr &= 0xFE;
+
+	/*
+	 * 1. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #1
+	 *    DATA_RW = 0x1 (write)
+	 *    DATA = linkAddress (primary link address and writing)
+	 *    INDEX = 0x0 (initial offset into buffer)
+	 *    INDEX_WRITE = 0x1 (setting initial offset)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+		BIT(31) | (ddc_data->dev_addr << 8));
+
+	/*
+	 * 2. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #2
+	 *    DATA_RW = 0x0 (write)
+	 *    DATA = offsetAddress
+	 *    INDEX = 0x0
+	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
+
+	/*
+	 * 3. Write to HDMI_I2C_DATA with the following fields set in order to
+	 *    handle portion #3
+	 *    DATA_RW = 0x0 (write)
+	 *    DATA = data_buf[ndx]
+	 *    INDEX = 0x0
+	 *    INDEX_WRITE = 0x0 (auto-increment by hardware)
+	 */
+	for (ndx = 0; ndx < ddc_data->data_len; ++ndx)
+		HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+			((u32)ddc_data->data_buf[ndx]) << 8);
+
+	/* Data setup is complete, now setup the transaction characteristics */
+
+	/*
+	 * 4. Write to HDMI_I2C_TRANSACTION0 with the following fields set in
+	 *    order to handle characteristics of portion #1 and portion #2
+	 *    RW0 = 0x0 (write)
+	 *    START0 = 0x1 (insert START bit)
+	 *    STOP0 = 0x0 (do NOT insert STOP bit)
+	 *    CNT0 = 0x1 (single byte transaction excluding address)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+
+	/*
+	 * 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
+	 *    order to handle characteristics of portion #3
+	 *    RW1 = 0x1 (read)
+	 *    START1 = 0x1 (insert START bit)
+	 *    STOP1 = 0x1 (insert STOP bit)
+	 *    CNT1 = data_len   (0xN (write N bytes of data))
+	 *    Byte count for second transition (excluding the first
+	 *    Byte which is usually the address)
+	 */
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1,
+		BIT(13) | ((ddc_data->data_len-1) << 16));
+
+	/* Trigger the I2C transfer */
+	/*
+	 * 6. Write to HDMI_I2C_CONTROL to kick off the hardware.
+	 *    Note that NOTHING has been transmitted on the DDC lines up to this
+	 *    point.
+	 *    TRANSACTION_CNT = 0x1 (execute transaction0 followed by
+	 *    transaction1)
+	 *    GO = 0x1 (kicks off hardware)
+	 */
+	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(20));
+
+	time_out_count = wait_for_completion_interruptible_timeout(
+		&ddc_ctrl->ddc_sw_done, HZ/2);
+
+	reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
+	HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
+	if (!time_out_count) {
+		if (retry-- > 0) {
+			DEV_INFO("%s[%s]: failed timout, retry=%d\n", __func__,
+				ddc_data->what, retry);
+			goto again;
+		}
+		status = -ETIMEDOUT;
+		DEV_ERR("%s[%s]: timedout, Int Ctrl=%08x\n",
+			__func__, ddc_data->what,
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+		DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
+			__func__,
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
+			HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+		goto error;
+	}
+
+	/* Read DDC status */
+	reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+	reg_val &= 0x00001000 | 0x00002000 | 0x00004000 | 0x00008000;
+
+	/* Check if any NACK occurred */
+	if (reg_val) {
+		if (retry > 1)
+			/* SW_STATUS_RESET */
+			HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+		else
+			/* SOFT_RESET */
+			HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+
+		if (retry-- > 0) {
+			DEV_DBG("%s[%s]: failed NACK=%08x, retry=%d\n",
+				__func__, ddc_data->what, reg_val, retry);
+			msleep(100);
+			goto again;
+		}
+		status = -EIO;
+		DEV_ERR("%s[%s]: failed NACK: %08x\n", __func__,
+			ddc_data->what, reg_val);
+		goto error;
+	}
+
+	DEV_DBG("%s[%s] success\n", __func__, ddc_data->what);
+
+error:
+	return status;
+} /* hdmi_ddc_write */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index ae6f16a..47515ba 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -369,6 +369,13 @@
 #define FRAME_PACKING		0x20
 #define SIDE_BY_SIDE_HALF	0x40
 
+enum hdmi_tx_feature_type {
+	HDMI_TX_FEAT_EDID,
+	HDMI_TX_FEAT_HDCP,
+	HDMI_TX_FEAT_CEC,
+	HDMI_TX_FEAT_MAX,
+};
+
 struct hdmi_disp_mode_timing_type {
 	u32	video_format;
 	u32	active_h;
@@ -389,6 +396,22 @@
 	u32	supported;
 };
 
+struct hdmi_tx_ddc_ctrl {
+	void __iomem *base;
+	struct completion ddc_sw_done;
+};
+
+struct hdmi_tx_ddc_data {
+	char *what;
+	u8 *data_buf;
+	u32 data_len;
+	u32 dev_addr;
+	u32 offset;
+	u32 request_len;
+	u32 no_align;
+	int retry;
+};
+
 void hdmi_reg_dump(void __iomem *base, u32 length, const char *prefix);
 const char *hdmi_reg_name(u32 offset);
 
@@ -397,4 +420,14 @@
 const char *hdmi_get_video_fmt_2string(u32 format);
 ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf);
 
+/* todo: Fix this. Right now this is defined in mdss_hdmi_tx.c */
+void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, u32 type);
+
+/* DDC */
+void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *);
+int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *);
+int hdmi_ddc_write(struct hdmi_tx_ddc_ctrl *, struct hdmi_tx_ddc_data *);
+int hdmi_ddc_read_seg(struct hdmi_tx_ddc_ctrl *, struct hdmi_tx_ddc_data *);
+int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *, struct hdmi_tx_ddc_data *);
+
 #endif /* __HDMI_UTIL_H__ */
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index 84f5909..65d08d3 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -14,6 +14,46 @@
 #include <linux/io.h>
 #include "mdss_io_util.h"
 
+static struct resource *msm_dss_get_res_byname(struct platform_device *pdev,
+	unsigned int type, const char *name)
+{
+	struct resource *res = NULL;
+
+	res = platform_get_resource_byname(pdev, type, name);
+	if (!res)
+		pr_err("%s: '%s' resource not found\n", __func__, name);
+
+	return res;
+}
+
+
+int msm_dss_ioremap_byname(struct platform_device *pdev,
+	struct dss_io_data *io_data, const char *name)
+{
+	struct resource *res = NULL;
+
+	if (!pdev || !io_data) {
+		pr_err("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	res = msm_dss_get_res_byname(pdev, IORESOURCE_MEM, name);
+	if (!res) {
+		pr_err("%s: '%s' msm_dss_get_res_byname failed\n",
+			__func__, name);
+		return -ENODEV;
+	}
+
+	io_data->len = resource_size(res);
+	io_data->base = ioremap(res->start, io_data->len);
+	if (!io_data->base) {
+		pr_err("%s: '%s' ioremap failed\n", __func__, name);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg,
 	int num_vreg, int config)
 {
@@ -25,10 +65,11 @@
 			curr_vreg = &in_vreg[i];
 			curr_vreg->vreg = regulator_get(dev,
 				curr_vreg->vreg_name);
-			if (IS_ERR(curr_vreg->vreg)) {
-				pr_err("%s: %s get failed\n",
+			rc = IS_ERR(curr_vreg->vreg);
+			if (rc) {
+				pr_err("%s: %s get failed. rc=%d\n",
 					 __func__,
-					 curr_vreg->vreg_name);
+					 curr_vreg->vreg_name, rc);
 				curr_vreg->vreg = NULL;
 				goto vreg_get_fail;
 			}
@@ -60,8 +101,7 @@
 	} else {
 		for (i = num_vreg-1; i >= 0; i--) {
 			curr_vreg = &in_vreg[i];
-			if (curr_vreg->vreg &&
-				regulator_is_enabled(curr_vreg->vreg)) {
+			if (curr_vreg->vreg) {
 				if (curr_vreg->type == DSS_REG_LDO) {
 					if (curr_vreg->optimum_voltage >= 0) {
 						regulator_set_optimum_mode(
@@ -94,7 +134,7 @@
 		curr_vreg = &in_vreg[i];
 		goto vreg_unconfig;
 	}
-	return -EPERM;
+	return rc;
 } /* msm_dss_config_vreg */
 
 int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg, int enable)
@@ -102,9 +142,10 @@
 	int i = 0, rc = 0;
 	if (enable) {
 		for (i = 0; i < num_vreg; i++) {
-			if (IS_ERR(in_vreg[i].vreg)) {
-				pr_err("%s: %s null regulator\n",
-					__func__, in_vreg[i].vreg_name);
+			rc = IS_ERR(in_vreg[i].vreg);
+			if (rc) {
+				pr_err("%s: %s regulator error. rc=%d\n",
+					__func__, in_vreg[i].vreg_name, rc);
 				goto disable_vreg;
 			}
 			rc = regulator_enable(in_vreg[i].vreg);
@@ -116,7 +157,8 @@
 		}
 	} else {
 		for (i = num_vreg-1; i >= 0; i--)
-			regulator_disable(in_vreg[i].vreg);
+			if (regulator_is_enabled(in_vreg[i].vreg))
+				regulator_disable(in_vreg[i].vreg);
 	}
 	return rc;
 
diff --git a/drivers/video/msm/mdss/mdss_io_util.h b/drivers/video/msm/mdss/mdss_io_util.h
index 791e44a..9671414 100644
--- a/drivers/video/msm/mdss/mdss_io_util.h
+++ b/drivers/video/msm/mdss/mdss_io_util.h
@@ -14,8 +14,14 @@
 #define __MDSS_IO_UTIL_H__
 
 #include <linux/gpio.h>
+#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 
+struct dss_io_data {
+	u32 len;
+	void __iomem *base;
+};
+
 enum dss_vreg_type {
 	DSS_REG_LDO,
 	DSS_REG_VS,
@@ -42,7 +48,10 @@
 	struct dss_gpio *gpio_config;
 };
 
+int msm_dss_ioremap_byname(struct platform_device *pdev,
+	struct dss_io_data *io_data, const char *name);
 int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable);
+int msm_dss_gpio_enable(struct dss_gpio *in_gpio, int num_gpio, int enable);
 int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg,
 	int num_vreg, int config);
 int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg,	int enable);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index ce55e71..3fb70bd 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/iommu.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/pm_runtime.h>
@@ -42,6 +43,8 @@
 #include <mach/hardware.h>
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
 
 #include "mdss.h"
 #include "mdss_fb.h"
@@ -92,6 +95,30 @@
 	.name = "mdss_mdp",
 };
 
+struct msm_iova_partition mdp_iommu_partitions[] = {
+	{
+		.start = SZ_128K,
+		.size = SZ_2G - SZ_128K,
+	},
+};
+struct msm_iova_layout mdp_iommu_layout = {
+	.client_name = "mdss_mdp",
+	.partitions = mdp_iommu_partitions,
+	.npartitions = ARRAY_SIZE(mdp_iommu_partitions),
+};
+
+struct {
+	char *name;
+	struct device *ctx;
+} mdp_iommu_ctx[] = {
+	{
+		.name = "mdp_0",
+	},
+	{
+		.name = "mdp_1",
+	}
+};
+
 struct mdss_hw mdss_mdp_hw = {
 	.hw_ndx = MDSS_HW_MDP,
 	.ptr = NULL,
@@ -584,6 +611,96 @@
 	return 0;
 }
 
+static int mdss_iommu_fault_handler(struct iommu_domain *domain,
+		struct device *dev, unsigned long iova, int flags)
+{
+	pr_err("MDP IOMMU page fault: iova 0x%lx\n", iova);
+	return 0;
+}
+
+int mdss_iommu_attach(void)
+{
+	struct iommu_domain *domain;
+	int i, domain_idx;
+
+	if (mdss_res->iommu_attached) {
+		pr_warn("mdp iommu already attached\n");
+		return 0;
+	}
+
+	domain_idx = mdss_get_iommu_domain();
+	domain = msm_get_iommu_domain(domain_idx);
+	if (!domain) {
+		pr_err("unable to get iommu domain(%d)\n", domain_idx);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mdp_iommu_ctx); i++) {
+		if (iommu_attach_device(domain, mdp_iommu_ctx[i].ctx)) {
+			WARN(1, "could not attach iommu domain %d to ctx %s\n",
+				domain_idx, mdp_iommu_ctx[i].name);
+			return -EINVAL;
+		}
+	}
+	mdss_res->iommu_attached = true;
+
+	return 0;
+}
+
+int mdss_iommu_dettach(void)
+{
+	struct iommu_domain *domain;
+	int i, domain_idx;
+
+	if (!mdss_res->iommu_attached) {
+		pr_warn("mdp iommu already dettached\n");
+		return 0;
+	}
+
+	domain_idx = mdss_get_iommu_domain();
+	domain = msm_get_iommu_domain(domain_idx);
+	if (!domain) {
+		pr_err("unable to get iommu domain(%d)\n", domain_idx);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mdp_iommu_ctx); i++)
+		iommu_detach_device(domain, mdp_iommu_ctx[i].ctx);
+	mdss_res->iommu_attached = false;
+
+	return 0;
+}
+
+int mdss_iommu_init(void)
+{
+	struct iommu_domain *domain;
+	int domain_idx, i;
+
+	domain_idx = msm_register_domain(&mdp_iommu_layout);
+	if (IS_ERR_VALUE(domain_idx))
+		return -EINVAL;
+
+	domain = msm_get_iommu_domain(domain_idx);
+	if (!domain) {
+		pr_err("unable to get iommu domain(%d)\n", domain_idx);
+		return -EINVAL;
+	}
+
+	iommu_set_fault_handler(domain, mdss_iommu_fault_handler);
+
+	for (i = 0; i < ARRAY_SIZE(mdp_iommu_ctx); i++) {
+		mdp_iommu_ctx[i].ctx = msm_iommu_get_ctx(mdp_iommu_ctx[i].name);
+		if (!mdp_iommu_ctx[i].ctx) {
+			pr_warn("unable to get iommu ctx(%s)\n",
+					mdp_iommu_ctx[i].name);
+			return -EINVAL;
+		}
+	}
+	mdss_res->iommu_domain = domain_idx;
+
+	return 0;
+}
+
 static int mdss_hw_init(struct mdss_data_type *mdata)
 {
 	char *base = mdata->vbif_base;
@@ -608,7 +725,7 @@
 
 static u32 mdss_mdp_res_init(struct mdss_data_type *mdata)
 {
-	u32 rc;
+	u32 rc = 0;
 
 	rc = mdss_mdp_irq_clk_setup(mdata);
 	if (rc)
@@ -639,6 +756,17 @@
 	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",
+				mdata->iclient);
+		mdata->iclient = NULL;
+	}
+
+	rc = mdss_iommu_init();
+	if (!IS_ERR_VALUE(rc))
+		mdss_iommu_attach();
+
 	rc = mdss_hw_init(mdata);
 
 	return rc;
@@ -718,10 +846,17 @@
 		pr_err("unable to initialize mdss mdp resources\n");
 		goto probe_done;
 	}
+	rc = mdss_mdp_pp_init(&pdev->dev);
+	if (rc) {
+		pr_err("unable to initialize mdss pp resources\n");
+		goto probe_done;
+	}
 	rc = mdss_mdp_bus_scale_register(mdata);
 probe_done:
-	if (IS_ERR_VALUE(rc))
+	if (IS_ERR_VALUE(rc)) {
 		mdss_res = NULL;
+		mdss_mdp_pp_term(&pdev->dev);
+	}
 
 	return rc;
 }
@@ -737,9 +872,11 @@
 	if (on && !mdss_res->fs_ena) {
 		pr_debug("Enable MDP FS\n");
 		regulator_enable(mdss_res->fs);
+		mdss_iommu_attach();
 		mdss_res->fs_ena = true;
 	} else if (!on && mdss_res->fs_ena) {
 		pr_debug("Disable MDP FS\n");
+		mdss_iommu_dettach();
 		regulator_disable(mdss_res->fs);
 		mdss_res->fs_ena = false;
 	}
@@ -812,6 +949,7 @@
 	if (!mdata)
 		return -ENODEV;
 	pm_runtime_disable(&pdev->dev);
+	mdss_mdp_pp_term(&pdev->dev);
 	mdss_mdp_bus_scale_unregister(mdata);
 	return 0;
 }
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index a282c3a..610c132 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -200,7 +200,6 @@
 	int p_need;
 	struct file *srcp_file;
 	struct ion_handle *srcp_ihdl;
-	struct ion_client *iclient;
 };
 
 struct mdss_mdp_data {
@@ -240,6 +239,9 @@
 	u32 params_changed;
 
 	unsigned long smp[MAX_PLANES];
+
+	struct mdss_mdp_data buffers[2];
+	struct list_head list;
 };
 
 struct mdss_mdp_writeback_arg {
@@ -276,6 +278,7 @@
 void mdss_mdp_footswitch_ctrl(int on);
 
 int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
+int mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd);
 int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
 
@@ -292,7 +295,7 @@
 int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
 
 int mdss_mdp_csc_setup(u32 block, u32 blk_idx, u32 tbl_idx, u32 csc_type);
-int mdss_mdp_dspp_setup(struct mdss_mdp_ctl *ctl, struct mdss_mdp_mixer *mixer);
+int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
 
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum);
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type);
@@ -301,7 +304,6 @@
 void mdss_mdp_pipe_unlock(struct mdss_mdp_pipe *pipe);
 
 int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
-int mdss_mdp_pipe_release_all(struct msm_fb_data_type *mfd);
 int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
 			     struct mdss_mdp_data *src_data);
 
@@ -311,10 +313,14 @@
 			     struct mdss_mdp_plane_sizes *ps);
 struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
 int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
-int mdss_mdp_get_img(struct ion_client *iclient, struct msmfb_data *img,
-		     struct mdss_mdp_img_data *data);
+int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data);
 
 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 21f4071..26fbca1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -20,8 +20,8 @@
 #include "mdss_fb.h"
 #include "mdss_mdp.h"
 
-/* 1.10 bus fudge factor */
-#define MDSS_MDP_BUS_FUDGE_FACTOR(val) ALIGN((((val) * 11) / 10), SZ_16M)
+/* 1.5 bus fudge factor */
+#define MDSS_MDP_BUS_FUDGE_FACTOR(val) ALIGN((((val) * 3) / 2), SZ_16M)
 /* 1.25 clock fudge factor */
 #define MDSS_MDP_CLK_FUDGE_FACTOR(val) (((val) * 5) / 4)
 
@@ -63,7 +63,6 @@
 		}
 	}
 	if (flags & MDSS_MDP_PERF_UPDATE_BUS) {
-		bus_ab_quota = MDSS_MDP_BUS_FUDGE_FACTOR(bus_ab_quota);
 		bus_ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR(bus_ib_quota);
 		mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
 	}
@@ -595,7 +594,7 @@
 
 	mutex_unlock(&ctl->lock);
 
-	mdss_mdp_pipe_release_all(mfd);
+	mdss_mdp_overlay_release_all(mfd);
 
 	if (!mfd->ref_cnt)
 		mdss_mdp_ctl_destroy(mfd);
@@ -808,9 +807,6 @@
 {
 	mixer->params_changed = 0;
 
-	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
-		mdss_mdp_dspp_setup(mixer->ctl, mixer);
-
 	/* skip mixer setup for rotator */
 	if (!mixer->rotator_mode)
 		mdss_mdp_mixer_setup(mixer->ctl, mixer);
@@ -864,6 +860,8 @@
 		ctl->flush_bits |= BIT(17);	/* CTL */
 	}
 
+	/* postprocessing setup, including dspp */
+	mdss_mdp_pp_setup(ctl);
 	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
 	wmb();
 	ctl->flush_bits = 0;
@@ -885,3 +883,30 @@
 
 	return ret;
 }
+
+int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id)
+{
+	int i;
+	struct mdss_mdp_ctl *ctl;
+	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];
+		if ((ctl->power_on) &&
+			(ctl->mfd->index == fb_num)) {
+			if (ctl->mixer_left) {
+				mixer_id[mixer_cnt] = ctl->mixer_left->num;
+				mixer_cnt++;
+			}
+			if (mixer_cnt && ctl->mixer_right) {
+				mixer_id[mixer_cnt] = ctl->mixer_right->num;
+				mixer_cnt++;
+			}
+			if (mixer_cnt)
+				break;
+		}
+	}
+	mutex_unlock(&mdss_mdp_ctl_lock);
+	return mixer_cnt;
+}
+
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 8825cc6..0139afd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -321,6 +321,10 @@
 	MDSS_MDP_MAX_DSPP
 };
 
+#define MDSS_MDP_REG_DSPP_OFFSET(pipe)	(0x4600 + ((pipe) * 0x400))
+#define MDSS_MDP_REG_DSPP_OP_MODE			0x000
+#define MDSS_MDP_REG_DSPP_PA_BASE			0x238
+
 enum mdss_mpd_intf_index {
 	MDSS_MDP_NO_INTF,
 	MDSS_MDP_INTF0,
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 1cb474d..e8e8163 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/uaccess.h>
 
+#include <mach/iommu_domains.h>
+
 #include "mdss_fb.h"
 #include "mdss_mdp.h"
 #include "mdss_mdp_rotator.h"
@@ -279,6 +281,9 @@
 			return -ENOMEM;
 		}
 
+		mutex_lock(&mfd->lock);
+		list_add(&pipe->list, &mfd->overlay_list);
+		mutex_unlock(&mfd->lock);
 		pipe->mixer = mixer;
 		pipe->mfd = mfd;
 	} else {
@@ -343,6 +348,79 @@
 	return ret;
 }
 
+static inline int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
+					   struct mdss_mdp_data *data,
+					   struct msmfb_data *planes,
+					   int num_planes)
+{
+	int i;
+
+	memset(data, 0, sizeof(*data));
+	for (i = 0; i < num_planes; i++) {
+		mdss_mdp_get_img(&planes[i], &data->p[i]);
+		if (data->p[0].len == 0)
+			break;
+	}
+
+	if (i != num_planes) {
+		for (; i >= 0; i--)
+			mdss_mdp_put_img(&data->p[i]);
+		return -ENOMEM;
+	}
+
+	data->num_planes = num_planes;
+
+	return 0;
+}
+
+static inline int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
+{
+	int i;
+	for (i = 0; i < data->num_planes && data->p[i].len; i++)
+		mdss_mdp_put_img(&data->p[i]);
+
+	data->num_planes = 0;
+
+	return 0;
+}
+
+static int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
+{
+	int ret;
+
+	if (ctl->mfd->kickoff_fnc)
+		ret = ctl->mfd->kickoff_fnc(ctl);
+	else
+		ret = mdss_mdp_display_commit(ctl, NULL);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	pr_debug("freeing previous buffers\n");
+
+	mutex_lock(&ctl->mfd->lock);
+	if (!list_empty(&ctl->mfd->overlay_list)) {
+		struct mdss_mdp_pipe *pipe;
+		struct mdss_mdp_data *data;
+		int buf_ndx;
+
+		list_for_each_entry(pipe, &ctl->mfd->overlay_list, list) {
+			buf_ndx = (pipe->play_cnt - 1) & 1; /* prev buffer */
+			data = &pipe->buffers[buf_ndx];
+
+			if (data->num_planes) {
+				pr_debug("free buffer ndx=%d pnum=%d\n",
+						buf_ndx, pipe->num);
+				mdss_mdp_overlay_free_buf(data);
+			}
+		}
+	}
+	mutex_unlock(&ctl->mfd->lock);
+
+	pr_debug("done freeing previous buffers\n");
+
+	return ret;
+}
+
 static int mdss_mdp_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
 {
 	struct mdss_mdp_pipe *pipe;
@@ -374,6 +452,9 @@
 			unset_ndx |= pipe_ndx;
 			pipe = mdss_mdp_pipe_get_locked(pipe_ndx);
 			if (pipe) {
+				mutex_lock(&mfd->lock);
+				list_del(&pipe->list);
+				mutex_unlock(&mfd->lock);
 				mdss_mdp_mixer_pipe_unstage(pipe);
 				cleanup_pipes[clean_cnt++] = pipe;
 			} else {
@@ -383,15 +464,51 @@
 	}
 
 	if (clean_cnt) {
-		ret = mfd->kickoff_fnc(mfd->ctl);
+		int j;
+		ret = mdss_mdp_overlay_kickoff(mfd->ctl);
 
-		for (i = 0; i < clean_cnt; i++)
-			mdss_mdp_pipe_destroy(cleanup_pipes[i]);
+		for (i = 0; i < clean_cnt; i++) {
+			pipe = cleanup_pipes[i];
+			for (j = 0; j < ARRAY_SIZE(pipe->buffers); j++)
+				mdss_mdp_overlay_free_buf(&pipe->buffers[i]);
+
+			mdss_mdp_pipe_destroy(pipe);
+		}
 	}
 
 	return ret;
 }
 
+int mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd)
+{
+	struct mdss_mdp_pipe *pipe;
+	u32 unset_ndx = 0;
+	int cnt = 0;
+
+	mutex_lock(&mfd->lock);
+	if (!list_empty(&mfd->overlay_list)) {
+		list_for_each_entry(pipe, &mfd->overlay_list, list) {
+			if (pipe->ndx & MDSS_MDP_ROT_SESSION_MASK) {
+				struct mdss_mdp_rotator_session *rot;
+				rot = mdss_mdp_rotator_session_get(pipe->ndx);
+				if (rot)
+					mdss_mdp_rotator_finish(rot);
+			} else {
+				unset_ndx |= pipe->ndx;
+				cnt++;
+			}
+		}
+	}
+	mutex_unlock(&mfd->lock);
+
+	if (unset_ndx) {
+		pr_debug("%d pipes need cleanup (%x)\n", cnt, unset_ndx);
+		mdss_mdp_overlay_unset(mfd, unset_ndx);
+	}
+
+	return 0;
+}
+
 static int mdss_mdp_overlay_play_wait(struct msm_fb_data_type *mfd,
 				      struct msmfb_overlay_data *req)
 {
@@ -400,41 +517,59 @@
 	if (!mfd || !mfd->ctl)
 		return -ENODEV;
 
-	ret = mfd->kickoff_fnc(mfd->ctl);
+	ret = mdss_mdp_overlay_kickoff(mfd->ctl);
 	if (!ret)
 		pr_err("error displaying\n");
 
 	return ret;
 }
 
-static int mdss_mdp_overlay_rotate(struct msmfb_overlay_data *req,
-				   struct mdss_mdp_data *src_data,
-				   struct mdss_mdp_data *dst_data)
+static int mdss_mdp_overlay_rotate(struct msm_fb_data_type *mfd,
+				   struct msmfb_overlay_data *req)
 {
 	struct mdss_mdp_rotator_session *rot;
+	struct mdss_mdp_data src_data, dst_data;
 	int ret;
 
+	ret = mdss_mdp_overlay_get_buf(mfd, &src_data, &req->data, 1);
+	if (ret) {
+		pr_err("src_data pmem error\n");
+		goto rotate_done;
+	}
+
+	ret = mdss_mdp_overlay_get_buf(mfd, &dst_data, &req->dst_data, 1);
+	if (ret) {
+		pr_err("dst_data pmem error\n");
+		goto rotate_done;
+	}
+
 	rot = mdss_mdp_rotator_session_get(req->id);
 	if (!rot) {
 		pr_err("invalid session id=%x\n", req->id);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto rotate_done;
 	}
 
-	ret = mdss_mdp_rotator_queue(rot, src_data, dst_data);
+	ret = mdss_mdp_rotator_queue(rot, &src_data, &dst_data);
 	if (ret) {
 		pr_err("rotator queue error session id=%x\n", req->id);
-		return ret;
+		goto rotate_done;
 	}
 
+rotate_done:
+	mdss_mdp_overlay_free_buf(&dst_data);
+	mdss_mdp_overlay_free_buf(&src_data);
+
 	return 0;
 }
 
-static int mdss_mdp_overlay_queue(struct msmfb_overlay_data *req,
-				  struct mdss_mdp_data *src_data)
+static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
+				  struct msmfb_overlay_data *req)
 {
-	struct mdss_mdp_pipe *pipe;
 	struct mdss_mdp_ctl *ctl;
-	int ret;
+	struct mdss_mdp_pipe *pipe;
+	struct mdss_mdp_data *src_data;
+	int ret, buf_ndx;
 
 	pipe = mdss_mdp_pipe_get_locked(req->id);
 	if (pipe == NULL) {
@@ -444,13 +579,23 @@
 
 	pr_debug("ov queue pnum=%d\n", pipe->num);
 
-	ret = mdss_mdp_pipe_queue_data(pipe, src_data);
+	buf_ndx = (pipe->play_cnt + 1) & 1; /* next buffer */
+	src_data = &pipe->buffers[buf_ndx];
+	mdss_mdp_overlay_free_buf(src_data);
+
+	ret = mdss_mdp_overlay_get_buf(mfd, src_data, &req->data, 1);
+	if (IS_ERR_VALUE(ret)) {
+		pr_err("src_data pmem error\n");
+	} else {
+		ret = mdss_mdp_pipe_queue_data(pipe, src_data);
+		if (IS_ERR_VALUE(ret))
+			mdss_mdp_overlay_free_buf(src_data);
+	}
 	ctl = pipe->mixer->ctl;
 	mdss_mdp_pipe_unlock(pipe);
 
 	if (ret == 0 && !(pipe->flags & MDP_OV_PLAY_NOWAIT))
-		ret = ctl->mfd->kickoff_fnc(ctl);
-
+		ret = mdss_mdp_overlay_kickoff(ctl);
 
 	return ret;
 }
@@ -458,41 +603,14 @@
 static int mdss_mdp_overlay_play(struct msm_fb_data_type *mfd,
 				 struct msmfb_overlay_data *req)
 {
-	struct mdss_mdp_data src_data;
 	int ret = 0;
 
-	if (mfd == NULL)
-		return -ENODEV;
-
 	pr_debug("play req id=%x\n", req->id);
 
-	memset(&src_data, 0, sizeof(src_data));
-	mdss_mdp_get_img(mfd->iclient, &req->data, &src_data.p[0]);
-	if (src_data.p[0].len == 0) {
-		pr_err("src data pmem error\n");
-		return -ENOMEM;
-	}
-	src_data.num_planes = 1;
-
-	if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
-		struct mdss_mdp_data dst_data;
-		memset(&dst_data, 0, sizeof(dst_data));
-
-		mdss_mdp_get_img(mfd->iclient, &req->dst_data, &dst_data.p[0]);
-		if (dst_data.p[0].len == 0) {
-			pr_err("dst data pmem error\n");
-			return -ENOMEM;
-		}
-		dst_data.num_planes = 1;
-
-		ret = mdss_mdp_overlay_rotate(req, &src_data, &dst_data);
-
-		mdss_mdp_put_img(&dst_data.p[0]);
-	} else {
-		ret = mdss_mdp_overlay_queue(req, &src_data);
-	}
-
-	mdss_mdp_put_img(&src_data.p[0]);
+	if (req->id & MDSS_MDP_ROT_SESSION_MASK)
+		ret = mdss_mdp_overlay_rotate(mfd, req);
+	else
+		ret = mdss_mdp_overlay_queue(mfd, req);
 
 	return ret;
 }
@@ -577,7 +695,18 @@
 	offset = fbi->var.xoffset * bpp +
 		 fbi->var.yoffset * fbi->fix.line_length;
 
-	data.p[0].addr = fbi->fix.smem_start + offset;
+	if (offset > fbi->fix.smem_len) {
+		pr_err("invalid fb offset=%u total length=%u\n",
+		       offset, fbi->fix.smem_len);
+		return;
+	}
+
+	if (is_mdss_iommu_attached())
+		data.p[0].addr = mfd->iova;
+	else
+		data.p[0].addr = fbi->fix.smem_start;
+
+	data.p[0].addr += offset;
 	data.p[0].len = fbi->fix.smem_len - offset;
 	data.num_planes = 1;
 
@@ -612,7 +741,7 @@
 	}
 
 	if (fbi->var.activate & FB_ACTIVATE_VBL)
-		mfd->kickoff_fnc(mfd->ctl);
+		mdss_mdp_overlay_kickoff(mfd->ctl);
 }
 
 static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t)
@@ -666,7 +795,7 @@
 	u32 blendcfg;
 	int off, ret = 0;
 
-	if (!mfd->cursor_buf) {
+	if (!mfd->cursor_buf && (cursor->set & FB_CUR_SETIMAGE)) {
 		mfd->cursor_buf = dma_alloc_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
 					(dma_addr_t *) &mfd->cursor_buf_phys,
 					GFP_KERNEL);
@@ -674,6 +803,19 @@
 			pr_err("can't allocate cursor buffer\n");
 			return -ENOMEM;
 		}
+
+		ret = msm_iommu_map_contig_buffer(mfd->cursor_buf_phys,
+						mdss_get_iommu_domain(), 0,
+						MDSS_MDP_CURSOR_SIZE, SZ_4K,
+						0, &(mfd->cursor_buf_iova));
+		if (IS_ERR_VALUE(ret)) {
+			dma_free_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
+					  mfd->cursor_buf,
+					  (dma_addr_t) mfd->cursor_buf_phys);
+			pr_err("unable to map cursor buffer to iommu(%d)\n",
+			       ret);
+			return -ENOMEM;
+		}
 	}
 
 	mixer = mdss_mdp_mixer_get(mfd->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
@@ -695,12 +837,17 @@
 				   (img->dy << 16) | img->dx);
 
 	if (cursor->set & FB_CUR_SETIMAGE) {
-		int calpha_en, transp_en, alpha, size;
+		int calpha_en, transp_en, alpha, size, cursor_addr;
 		ret = copy_from_user(mfd->cursor_buf, img->data,
 				     img->width * img->height * 4);
 		if (ret)
 			return ret;
 
+		if (is_mdss_iommu_attached())
+			cursor_addr = mfd->cursor_buf_iova;
+		else
+			cursor_addr = mfd->cursor_buf_phys;
+
 		if (img->bg_color == 0xffffffff)
 			transp_en = 0;
 		else
@@ -719,7 +866,7 @@
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_STRIDE,
 				   img->width * 4);
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_BASE_ADDR,
-				   mfd->cursor_buf_phys);
+				   cursor_addr);
 
 		wmb();
 
@@ -772,11 +919,6 @@
 	return 0;
 }
 
-static int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
-{
-	return mdss_mdp_display_commit(ctl, NULL);
-}
-
 static int mdss_mdp_overlay_ioctl_handler(struct msm_fb_data_type *mfd,
 					  u32 cmd, void __user *argp)
 {
@@ -897,8 +1039,8 @@
 
 	if (mfd->panel_info.type == WRITEBACK_PANEL)
 		mfd->kickoff_fnc = mdss_mdp_wb_kickoff;
-	else
-		mfd->kickoff_fnc = mdss_mdp_overlay_kickoff;
+
+	INIT_LIST_HEAD(&mfd->overlay_list);
 
 	return 0;
 }
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index c94068a..c936b7d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -272,35 +272,6 @@
 	return 0;
 }
 
-int mdss_mdp_pipe_release_all(struct msm_fb_data_type *mfd)
-{
-	struct mdss_mdp_pipe *pipe;
-	int i;
-
-	if (!mfd)
-		return -ENODEV;
-
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-	mutex_lock(&mdss_mdp_sspp_lock);
-	for (i = 0; i < MDSS_MDP_MAX_SSPP; i++) {
-		pipe = &mdss_mdp_pipe_list[i];
-		if (atomic_read(&pipe->ref_cnt) && pipe->mfd == mfd) {
-			pr_debug("release pnum=%d\n", pipe->num);
-			if (mdss_mdp_pipe_lock(pipe) == 0) {
-				mdss_mdp_mixer_pipe_unstage(pipe);
-				mdss_mdp_pipe_free(pipe);
-			} else {
-				pr_err("unable to lock pipe=%d for release",
-				       pipe->num);
-			}
-		}
-	}
-	mutex_unlock(&mdss_mdp_sspp_lock);
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-
-	return 0;
-}
-
 static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
 				       u32 reg, u32 val)
 {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index db840a8..7ab3b01 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -13,6 +13,7 @@
 
 #define pr_fmt(fmt)	"%s: " fmt, __func__
 
+#include "mdss_fb.h"
 #include "mdss_mdp.h"
 
 struct mdp_csc_cfg mdp_csc_convert[MDSS_MDP_MAX_CSC] = {
@@ -71,6 +72,27 @@
 #define CSC_LV_OFF	0x14
 #define CSC_POST_OFF	0xC
 
+#define MDSS_BLOCK_DISP_NUM	(MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0)
+
+struct pp_sts_type {
+	u32 pa_sts;
+};
+
+#define PP_FLAGS_DIRTY_PA	0x1
+
+#define PP_STS_ENABLE	0x1
+
+struct mdss_pp_res_type {
+	/* logical info */
+	u32 pp_disp_flags[MDSS_BLOCK_DISP_NUM];
+	struct mdp_pa_cfg_data pa_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	/* physical info */
+	struct pp_sts_type pp_dspp_sts[MDSS_MDP_MAX_DSPP];
+};
+
+static DEFINE_MUTEX(mdss_pp_mutex);
+static struct mdss_pp_res_type *mdss_pp_res;
+
 static int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
 				   struct mdp_csc_cfg *data)
 {
@@ -160,16 +182,147 @@
 	return mdss_mdp_csc_setup_data(block, blk_idx, tbl_idx, data);
 }
 
-int mdss_mdp_dspp_setup(struct mdss_mdp_ctl *ctl, struct mdss_mdp_mixer *mixer)
+static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
+		struct mdss_mdp_mixer *mixer)
 {
-	int dspp_num;
-
-	if (!ctl || !mixer)
-		return -EINVAL;
+	u32 flags, base, offset, dspp_num, opmode = 0;
+	struct mdp_pa_cfg_data *pa_config;
+	struct pp_sts_type *pp_sts;
 
 	dspp_num = mixer->num;
+	/* no corresponding dspp */
+	if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
+		(dspp_num >= MDSS_MDP_MAX_DSPP))
+		return 0;
 
-	ctl->flush_bits |= BIT(13 + dspp_num);	/* DSPP */
+	if (disp_num < MDSS_BLOCK_DISP_NUM)
+		flags = mdss_pp_res->pp_disp_flags[disp_num];
+	else
+		flags = 0;
+
+	/* nothing to update */
+	if (!flags)
+		return 0;
+	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
+	base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num);
+	if (flags & PP_FLAGS_DIRTY_PA) {
+		pa_config = &mdss_pp_res->pa_disp_cfg[disp_num];
+		if (pa_config->flags & MDP_PP_OPS_WRITE) {
+			offset = base + MDSS_MDP_REG_DSPP_PA_BASE;
+			MDSS_MDP_REG_WRITE(offset, pa_config->hue_adj);
+			offset += 4;
+			MDSS_MDP_REG_WRITE(offset, pa_config->sat_adj);
+			offset += 4;
+			MDSS_MDP_REG_WRITE(offset, pa_config->val_adj);
+			offset += 4;
+			MDSS_MDP_REG_WRITE(offset, pa_config->cont_adj);
+		}
+		if (pa_config->flags & MDP_PP_OPS_DISABLE)
+			pp_sts->pa_sts &= ~PP_STS_ENABLE;
+		else if (pa_config->flags & MDP_PP_OPS_ENABLE)
+			pp_sts->pa_sts |= PP_STS_ENABLE;
+	}
+	if (pp_sts->pa_sts & PP_STS_ENABLE)
+		opmode |= (1 << 20); /* PA_EN */
+	MDSS_MDP_REG_WRITE(base + MDSS_MDP_REG_DSPP_OP_MODE, opmode);
+	ctl->flush_bits |= BIT(13 + dspp_num); /* DSPP */
+	return 0;
+
+}
+int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl)
+{
+	u32 disp_num;
+	if ((!ctl->mfd) || (!mdss_pp_res))
+		return -EINVAL;
+
+	/* treat fb_num the same as block logical id*/
+	disp_num = ctl->mfd->index;
+
+	mutex_lock(&mdss_pp_mutex);
+	if (ctl->mixer_left)
+		pp_dspp_setup(disp_num, ctl, ctl->mixer_left);
+	if (ctl->mixer_right)
+		pp_dspp_setup(disp_num, ctl, ctl->mixer_right);
+	/* clear dirty flag */
+	if (disp_num < MDSS_BLOCK_DISP_NUM)
+		mdss_pp_res->pp_disp_flags[disp_num] = 0;
+	mutex_unlock(&mdss_pp_mutex);
 
 	return 0;
 }
+
+int mdss_mdp_pp_init(struct device *dev)
+{
+	int ret = 0;
+	mutex_lock(&mdss_pp_mutex);
+	if (!mdss_pp_res) {
+		mdss_pp_res = devm_kzalloc(dev, sizeof(*mdss_pp_res),
+				GFP_KERNEL);
+		if (mdss_pp_res == NULL) {
+			pr_err("%s mdss_pp_res allocation failed!", __func__);
+			ret = -ENOMEM;
+		}
+	}
+	mutex_unlock(&mdss_pp_mutex);
+	return ret;
+}
+void mdss_mdp_pp_term(struct device *dev)
+{
+	if (!mdss_pp_res) {
+		mutex_lock(&mdss_pp_mutex);
+		devm_kfree(dev, mdss_pp_res);
+		mdss_pp_res = NULL;
+		mutex_unlock(&mdss_pp_mutex);
+	}
+}
+
+int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config, u32 *copyback)
+{
+	int i, ret = 0;
+	u32 pa_offset, disp_num, mixer_cnt;
+	u32 mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+
+	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(config->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+
+	mutex_lock(&mdss_pp_mutex);
+	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+	if (config->flags & MDP_PP_OPS_READ) {
+		mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
+		if (!mixer_cnt) {
+			ret = -EPERM;
+			goto pa_config_exit;
+		}
+		/* only read the first mixer */
+		for (i = 0; i < mixer_cnt; i++) {
+			if (mixer_id[i] < MDSS_MDP_MAX_DSPP)
+				break;
+		}
+		if (i >= mixer_cnt) {
+			ret = -EPERM;
+			goto pa_config_exit;
+		}
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+		pa_offset = MDSS_MDP_REG_DSPP_OFFSET(mixer_id[i]) +
+			  MDSS_MDP_REG_DSPP_PA_BASE;
+
+		config->hue_adj = MDSS_MDP_REG_READ(pa_offset);
+		pa_offset += 4;
+		config->sat_adj = MDSS_MDP_REG_READ(pa_offset);
+		pa_offset += 4;
+		config->val_adj = MDSS_MDP_REG_READ(pa_offset);
+		pa_offset += 4;
+		config->cont_adj = MDSS_MDP_REG_READ(pa_offset);
+		*copyback = 1;
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	} else {
+		mdss_pp_res->pa_disp_cfg[disp_num] = *config;
+		mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_PA;
+	}
+
+pa_config_exit:
+	mutex_unlock(&mdss_pp_mutex);
+	return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 53cd378..57e8441 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -16,11 +16,14 @@
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/file.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
+#include <linux/iommu.h>
 #include <linux/msm_kgsl.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
+#include <mach/iommu_domains.h>
+
 #include "mdss_fb.h"
 #include "mdss_mdp.h"
 #include "mdss_mdp_formats.h"
@@ -284,33 +287,38 @@
 
 int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
 {
-	/* only source may use frame buffer */
+	struct ion_client *iclient = mdss_get_ionclient();
 	if (data->flags & MDP_MEMORY_ID_TYPE_FB) {
+		pr_debug("fb mem buf=0x%x\n", data->addr);
 		fput_light(data->srcp_file, data->p_need);
-		return 0;
-	}
-	if (data->srcp_file) {
+		data->srcp_file = NULL;
+	} else if (data->srcp_file) {
+		pr_debug("pmem buf=0x%x\n", data->addr);
 		put_pmem_file(data->srcp_file);
 		data->srcp_file = NULL;
-		return 0;
-	}
-	if (!IS_ERR_OR_NULL(data->srcp_ihdl)) {
-		ion_free(data->iclient, data->srcp_ihdl);
-		data->iclient = NULL;
+	} else if (!IS_ERR_OR_NULL(data->srcp_ihdl)) {
+		pr_debug("ion hdl=%p buf=0x%x\n", data->srcp_ihdl, data->addr);
+
+		if (is_mdss_iommu_attached())
+			ion_unmap_iommu(iclient, data->srcp_ihdl,
+					mdss_get_iommu_domain(), 0);
+
+		ion_free(iclient, data->srcp_ihdl);
 		data->srcp_ihdl = NULL;
-		return 0;
+	} else {
+		return -ENOMEM;
 	}
 
-	return -ENOMEM;
+	return 0;
 }
 
-int mdss_mdp_get_img(struct ion_client *iclient, struct msmfb_data *img,
-		     struct mdss_mdp_img_data *data)
+int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data)
 {
 	struct file *file;
 	int ret = -EINVAL;
 	int fb_num;
 	unsigned long *start, *len;
+	struct ion_client *iclient = mdss_get_ionclient();
 
 	start = (unsigned long *) &data->addr;
 	len = (unsigned long *) &data->len;
@@ -323,19 +331,46 @@
 					start, len);
 	} else if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
 		file = fget_light(img->memory_id, &data->p_need);
-		if (file && FB_MAJOR ==
-				MAJOR(file->f_dentry->d_inode->i_rdev)) {
-			data->srcp_file = file;
+		if (file == NULL) {
+			pr_err("invalid framebuffer file (%d)\n",
+					img->memory_id);
+			return -EINVAL;
+		}
+		data->srcp_file = file;
+
+		if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
 			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
 			ret = mdss_fb_get_phys_info(start, len, fb_num);
+			if (ret)
+				pr_err("mdss_fb_get_phys_info() failed\n");
+		} else {
+			pr_err("invalid FB_MAJOR\n");
+			ret = -1;
 		}
 	} else if (iclient) {
-		data->iclient = iclient;
 		data->srcp_ihdl = ion_import_dma_buf(iclient, img->memory_id);
-		if (IS_ERR_OR_NULL(data->srcp_ihdl))
-			return PTR_ERR(data->srcp_ihdl);
-		ret = ion_phys(iclient, data->srcp_ihdl,
-			       start, (size_t *) len);
+		if (IS_ERR_OR_NULL(data->srcp_ihdl)) {
+			pr_err("error on ion_import_fd\n");
+			ret = PTR_ERR(data->srcp_ihdl);
+			data->srcp_ihdl = NULL;
+			return ret;
+		}
+
+		if (is_mdss_iommu_attached()) {
+			ret = ion_map_iommu(iclient, data->srcp_ihdl,
+					    mdss_get_iommu_domain(),
+					    0, SZ_4K, 0, start, len, 0,
+					    ION_IOMMU_UNMAP_DELAYED);
+		} else {
+			ret = ion_phys(iclient, data->srcp_ihdl, start,
+				       (size_t *) len);
+		}
+
+		if (IS_ERR_VALUE(ret)) {
+			ion_free(iclient, data->srcp_ihdl);
+			pr_err("failed to map ion handle (%d)\n", ret);
+			return ret;
+		}
 	} else {
 		unsigned long vstart;
 		ret = get_pmem_file(img->memory_id, start, &vstart, len,
@@ -345,9 +380,11 @@
 	if (!ret && (img->offset < data->len)) {
 		data->addr += img->offset;
 		data->len -= img->offset;
+
+		pr_debug("mem=%d ihdl=%p buf=0x%x len=0x%x\n", img->memory_id,
+			 data->srcp_ihdl, data->addr, data->len);
 	} else {
-		mdss_mdp_put_img(data);
-		ret = -EINVAL;
+		return -EINVAL;
 	}
 
 	return ret;
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 26e459f..bd5f464 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -18,6 +18,10 @@
 #include <linux/major.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
+#include <linux/iommu.h>
+
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
 
 #include "mdss_mdp.h"
 #include "mdss_fb.h"
@@ -67,33 +71,46 @@
 	static struct ion_handle *ihdl;
 	static void *videomemory;
 	static ion_phys_addr_t mdss_wb_mem;
-	static struct mdss_mdp_data buffer = { .num_planes = 1,	};
-	struct fb_info *fbi;
-	size_t img_size;
+	static struct mdss_mdp_data mdss_wb_buffer = { .num_planes = 1, };
+	int rc;
 
-	fbi = mfd->fbi;
-	img_size = fbi->var.xres * fbi->var.yres * fbi->var.bits_per_pixel / 8;
+	if (IS_ERR_OR_NULL(ihdl)) {
+		struct fb_info *fbi;
+		size_t img_size;
+		struct ion_client *iclient = mdss_get_ionclient();
+		struct mdss_mdp_img_data *img = mdss_wb_buffer.p;
 
-	if (ihdl == NULL) {
-		ihdl = ion_alloc(mfd->iclient, img_size, SZ_4K,
+		fbi = mfd->fbi;
+		img_size = fbi->var.xres * fbi->var.yres *
+			fbi->var.bits_per_pixel / 8;
+
+
+		ihdl = ion_alloc(iclient, img_size, SZ_4K,
 				 ION_HEAP(ION_SF_HEAP_ID));
-		if (!IS_ERR_OR_NULL(ihdl)) {
-			videomemory = ion_map_kernel(mfd->iclient, ihdl, 0);
-			ion_phys(mfd->iclient, ihdl, &mdss_wb_mem, &img_size);
-		} else {
+		if (IS_ERR_OR_NULL(ihdl)) {
 			pr_err("unable to alloc fbmem from ion (%p)\n", ihdl);
-			ihdl = NULL;
+			return NULL;
 		}
+
+		videomemory = ion_map_kernel(iclient, ihdl, 0);
+		ion_phys(iclient, ihdl, &mdss_wb_mem, &img_size);
+
+		if (is_mdss_iommu_attached()) {
+			rc = ion_map_iommu(iclient, ihdl,
+					   mdss_get_iommu_domain(),
+					   0, SZ_4K, 0,
+					   (unsigned long *) &img->addr,
+					   (unsigned long *) &img->len,
+					   0, 0);
+		} else {
+			img->addr = mdss_wb_mem;
+			img->len = img_size;
+		}
+
+		pr_debug("ihdl=%p virt=%p phys=0x%lx iova=0x%x size=%u\n",
+			 ihdl, videomemory, mdss_wb_mem, img->addr, img_size);
 	}
-
-	if (mdss_wb_mem) {
-		buffer.p[0].addr = (u32) mdss_wb_mem;
-		buffer.p[0].len = img_size;
-
-		return &buffer;
-	}
-
-	return NULL;
+	return &mdss_wb_buffer;
 }
 #else
 static inline
@@ -266,7 +283,7 @@
 
 	node->buf_data.num_planes = 1;
 	buf = &node->buf_data.p[0];
-	ret = mdss_mdp_get_img(mfd->iclient, data, buf);
+	ret = mdss_mdp_get_img(data, buf);
 	if (IS_ERR_VALUE(ret)) {
 		pr_err("error getting buffer info\n");
 		goto register_fail;
@@ -394,6 +411,9 @@
 	if (!ctl || !ctl->mfd)
 		return -ENODEV;
 
+	if (!ctl->power_on)
+		return 0;
+
 	mutex_lock(&mdss_mdp_wb_buf_lock);
 	wb = ctl->mfd->wb;
 	if (wb) {
@@ -546,3 +566,9 @@
 	return mdss_mdp_wb_terminate(mfd);
 }
 EXPORT_SYMBOL(msm_fb_writeback_terminate);
+
+int msm_fb_get_iommu_domain(void)
+{
+	return mdss_get_iommu_domain();
+}
+EXPORT_SYMBOL(msm_fb_get_iommu_domain);
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 5d23548..f1a4e50 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -178,8 +178,8 @@
 
 struct mdss_panel_data {
 	struct mdss_panel_info panel_info;
-	void (*set_backlight) (u32 bl_level);
-	unsigned char *dsi_base;
+	void (*set_backlight) (struct mdss_panel_data *pdata,
+							u32 bl_level);
 	unsigned char *mmss_cc_base;
 
 	/* function entry chain */
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 9d9a366..545d53c 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -208,45 +208,45 @@
 	mdss_dsi_clk_on = 0;
 }
 
-void mdss_dsi_phy_sw_reset(struct mdss_panel_data *pdata)
+void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base)
 {
 	/* start phy sw reset */
-	MIPI_OUTP((pdata->dsi_base) + 0x12c, 0x0001);
+	MIPI_OUTP(ctrl_base + 0x12c, 0x0001);
 	wmb();
 	usleep(1);
 	/* end phy sw reset */
-	MIPI_OUTP((pdata->dsi_base) + 0x12c, 0x0000);
+	MIPI_OUTP(ctrl_base + 0x12c, 0x0000);
 	wmb();
 	usleep(1);
 }
 
-void mdss_dsi_phy_enable(struct mdss_panel_data *pdata, int on)
+void mdss_dsi_phy_enable(unsigned char *ctrl_base, int on)
 {
 	if (on) {
-		MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x006);
+		MIPI_OUTP(ctrl_base + 0x0220, 0x006);
 		usleep(10);
-		MIPI_OUTP((pdata->dsi_base) + 0x0268, 0x001);
+		MIPI_OUTP(ctrl_base + 0x0268, 0x001);
 		usleep(10);
-		MIPI_OUTP((pdata->dsi_base) + 0x0268, 0x000);
+		MIPI_OUTP(ctrl_base + 0x0268, 0x000);
 		usleep(10);
-		MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x007);
+		MIPI_OUTP(ctrl_base + 0x0220, 0x007);
 		wmb();
 
 		/* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x07e);
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x06e);
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x06c);
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x064);
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x065);
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x075);
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x077);
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x07f);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x07e);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x06e);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x06c);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x064);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x065);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x075);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x077);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x07f);
 		wmb();
 
 	} else {
-		MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x006);
+		MIPI_OUTP(ctrl_base + 0x0220, 0x006);
 		usleep(10);
-		MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x000);
+		MIPI_OUTP(ctrl_base + 0x0470, 0x000);
 		wmb();
 	}
 }
@@ -255,31 +255,39 @@
 {
 	struct mdss_dsi_phy_ctrl *pd;
 	int i, off, ln, offset;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	pd = (pdata->panel_info.mipi).dsi_phy_db;
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+	if (!ctrl_pdata) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+	pd = ((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db;
 
 	off = 0x0580;	/* phy regulator ctrl settings */
 	for (i = 0; i < 8; i++) {
-		MIPI_OUTP((pdata->dsi_base) + off, pd->regulator[i]);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->regulator[i]);
 		wmb();
 		off += 4;
 	}
 
 	off = 0x0440;	/* phy timing ctrl 0 - 11 */
 	for (i = 0; i < 12; i++) {
-		MIPI_OUTP((pdata->dsi_base) + off, pd->timing[i]);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->timing[i]);
 		wmb();
 		off += 4;
 	}
 
 	/* Strength ctrl 0 - 1 */
-	MIPI_OUTP((pdata->dsi_base) + 0x0484, pd->strength[0]);
-	MIPI_OUTP((pdata->dsi_base) + 0x0488, pd->strength[1]);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, pd->strength[0]);
+	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0488, pd->strength[1]);
 	wmb();
 
 	off = 0x04b4;	/* phy BIST ctrl 0 - 5 */
 	for (i = 0; i < 6; i++) {
-		MIPI_OUTP((pdata->dsi_base) + off, pd->bistCtrl[i]);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->bistCtrl[i]);
 		wmb();
 		off += 4;
 	}
@@ -290,7 +298,8 @@
 		off = 0x0300 + (ln * 0x40);
 		for (i = 0; i < 9; i++) {
 			offset = i + (ln * 9);
-			MIPI_OUTP((pdata->dsi_base) + off, pd->laneCfg[offset]);
+			MIPI_OUTP((ctrl_pdata->ctrl_base) + off,
+							pd->laneCfg[offset]);
 			wmb();
 			off += 4;
 		}
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
index be160c4..f3b8cd1 100644
--- a/drivers/video/msm/mhl/mhl_8334.c
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -531,40 +531,62 @@
 static int mhl_i2c_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
-	int ret = -ENODEV;
+	int ret;
+	struct msm_mhl_platform_data *tmp = client->dev.platform_data;
+	if (!tmp->mhl_enabled) {
+		ret = -ENODEV;
+		pr_warn("MHL feautre left disabled\n");
+		goto probe_early_exit;
+	}
 	mhl_msm_state->mhl_data = kzalloc(sizeof(struct msm_mhl_platform_data),
 		GFP_KERNEL);
 	if (!(mhl_msm_state->mhl_data)) {
 		ret = -ENOMEM;
 		pr_err("MHL I2C Probe failed - no mem\n");
-		goto probe_exit;
+		goto probe_early_exit;
 	}
 	mhl_msm_state->i2c_client = client;
-
 	spin_lock_init(&mhl_state_lock);
-
 	i2c_set_clientdata(client, mhl_msm_state);
 	mhl_msm_state->mhl_data = client->dev.platform_data;
 	pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
 		mhl_msm_state->mhl_data->irq);
 	msc_send_workqueue = create_workqueue("mhl_msc_cmd_queue");
 
-	if (!mhl_msm_state->mhl_data->mhl_enabled) {
-		pr_info("MHL Display not enabled\n");
-		return -ENODEV;
-	}
-
+	mhl_msm_state->cur_state = POWER_STATE_D0_MHL;
 	/* Init GPIO stuff here */
 	ret = mhl_sii_gpio_setup(1);
-	if (ret == -1) {
+	if (ret) {
 		pr_err("MHL: mhl_gpio_init has failed\n");
 		ret = -ENODEV;
+		goto probe_early_exit;
+	}
+	mhl_sii_power_on();
+	/* MHL SII 8334 chip specific init */
+	mhl_chip_init();
+	init_completion(&mhl_msm_state->rgnd_done);
+	/* Request IRQ stuff here */
+	pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
+		mhl_msm_state->mhl_data->irq);
+	ret = request_threaded_irq(mhl_msm_state->mhl_data->irq, NULL,
+				   &mhl_tx_isr,
+				 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+				 "mhl_tx_isr", mhl_msm_state);
+	if (ret) {
+		pr_err("request_threaded_irq failed, status: %d\n",
+			ret);
 		goto probe_exit;
+	} else {
+		pr_debug("request_threaded_irq succeeded\n");
 	}
 
-	mhl_sii_power_on();
+	INIT_WORK(&mhl_msm_state->mhl_msc_send_work, mhl_msc_send_work);
+	INIT_LIST_HEAD(&mhl_msm_state->list_cmd);
+	mhl_msm_state->msc_command_put_work = list_cmd_put;
+	mhl_msm_state->msc_command_get_work = list_cmd_get;
+	init_completion(&mhl_msm_state->msc_cmd_done);
 
-	pr_debug("I2C PROBE successful\n");
+	pr_debug("i2c probe successful\n");
 	return 0;
 
 probe_exit:
@@ -574,6 +596,7 @@
 		kfree(mhl_msm_state->mhl_data);
 		mhl_msm_state->mhl_data = NULL;
 	}
+probe_early_exit:
 	return ret;
 }
 
@@ -636,7 +659,6 @@
 		ret = -ENOMEM;
 		goto init_exit;
 	}
-
 	mhl_msm_state->i2c_client = NULL;
 	ret = i2c_add_driver(&mhl_sii_i2c_driver);
 	if (ret) {
@@ -645,6 +667,7 @@
 		goto init_exit;
 	} else {
 		if (mhl_msm_state->i2c_client == NULL) {
+			i2c_del_driver(&mhl_sii_i2c_driver);
 			pr_err("MHL: I2C driver add failed\n");
 			ret = -ENODEV;
 			goto init_exit;
@@ -652,36 +675,9 @@
 		pr_info("MHL: I2C driver added\n");
 	}
 
-	/* Request IRQ stuff here */
-	pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
-		mhl_msm_state->mhl_data->irq);
-	ret = request_threaded_irq(mhl_msm_state->mhl_data->irq, NULL,
-				   &mhl_tx_isr,
-				 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				 "mhl_tx_isr", mhl_msm_state);
-	if (ret != 0) {
-		pr_err("request_threaded_irq failed, status: %d\n",
-			ret);
-		ret = -EACCES; /* Error code???? */
-		goto init_exit;
-	} else
-		pr_debug("request_threaded_irq succeeded\n");
-
-	INIT_WORK(&mhl_msm_state->mhl_msc_send_work, mhl_msc_send_work);
-	mhl_msm_state->cur_state = POWER_STATE_D0_MHL;
-	INIT_LIST_HEAD(&mhl_msm_state->list_cmd);
-	mhl_msm_state->msc_command_put_work = list_cmd_put;
-	mhl_msm_state->msc_command_get_work = list_cmd_get;
-	init_completion(&mhl_msm_state->msc_cmd_done);
-
-	/* MHL SII 8334 chip specific init */
-	mhl_chip_init();
-	init_completion(&mhl_msm_state->rgnd_done);
 	return 0;
-
 init_exit:
 	pr_err("Exiting from the init with err\n");
-	i2c_del_driver(&mhl_sii_i2c_driver);
 	if (!mhl_msm_state) {
 		kfree(mhl_msm_state);
 		mhl_msm_state = NULL;
@@ -846,9 +842,6 @@
 	if (0x02 == rgnd_imp) {
 		pr_debug("MHL: MHL DEVICE!!!\n");
 		mhl_i2c_reg_modify(TX_PAGE_3, 0x0018, BIT0, BIT0);
-		/*
-		 * Handling the MHL event in driver
-		 */
 		mhl_msm_state->mhl_mode = TRUE;
 		if (notify_usb_online)
 			notify_usb_online(1);
@@ -985,8 +978,7 @@
 	uint8_t intr_5_stat;
 
 	/*
-	 * Clear INT 5 ??
-	 * Probably need to revisit this later
+	 * Clear INT 5
 	 * INTR5 is related to FIFO underflow/overflow reset
 	 * which is handled in 8334 by auto FIFO reset
 	 */
@@ -1464,6 +1456,7 @@
 }
 
 
+/* MSC, RCP, RAP messages - mandatory for compliance */
 static void mhl_cbus_isr(void)
 {
 	uint8_t regval;
@@ -1477,7 +1470,10 @@
 	if (regval == 0xff)
 		return;
 
-	/* clear all interrupts that were raised even if we did not process */
+	/*
+	 * clear all interrupts that were raised
+	 * even if we did not process
+	 */
 	if (regval)
 		mhl_i2c_reg_write(TX_PAGE_CBUS, 0x08, regval);
 
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
index 94c24ee..0c6ff79 100644
--- a/drivers/video/msm/mipi_NT35510.c
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -592,6 +592,7 @@
 static int __devinit mipi_nt35510_lcd_probe(struct platform_device *pdev)
 {
 	struct platform_device *pthisdev = NULL;
+	struct msm_fb_panel_data *pdata;
 	pr_debug("%s\n", __func__);
 
 	if (pdev->id == 0) {
@@ -601,6 +602,11 @@
 		return 0;
 	}
 
+	pdata = pdev->dev.platform_data;
+	if (mipi_nt35510_pdata && mipi_nt35510_pdata->rotate_panel()
+			&& pdata->panel_info.type == MIPI_CMD_PANEL)
+		pdata->panel_info.lcd.refx100 = 6200;
+
 	pthisdev = msm_fb_add_device(pdev);
 	mipi_nt35510_create_sysfs(pthisdev);
 
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index e6e8aca..7d534ed 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -79,6 +79,14 @@
 
 	mdp4_overlay_dsi_state_set(ST_DSI_SUSPEND);
 
+	/* make sure dsi clk is on so that
+	 * dcs commands can be sent
+	 */
+	mipi_dsi_clk_cfg(1);
+
+	/* make sure dsi_cmd_mdp is idle */
+	mipi_dsi_cmd_mdp_busy();
+
 	/*
 	 * Desctiption: change to DSI_CMD_MODE since it needed to
 	 * tx DCS dsiplay off comamnd to panel
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 2f691cf..0f37f6f 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -311,8 +311,6 @@
 void mipi_dsi_set_tear_off(struct msm_fb_data_type *mfd);
 void mipi_dsi_set_backlight(struct msm_fb_data_type *mfd, int level);
 void mipi_dsi_cmd_backlight_tx(struct dsi_buf *dp);
-void mipi_dsi_clk_enable(void);
-void mipi_dsi_clk_disable(void);
 void mipi_dsi_pre_kickoff_action(void);
 void mipi_dsi_post_kickoff_action(void);
 void mipi_dsi_pre_kickoff_add(struct dsi_kickoff_action *act);
@@ -326,16 +324,47 @@
 irqreturn_t mipi_dsi_isr(int irq, void *ptr);
 
 void mipi_set_tx_power_mode(int mode);
-void mipi_dsi_phy_ctrl(int on);
 void mipi_dsi_phy_init(int panel_ndx, struct msm_panel_info const *panel_info,
 	int target_type);
 int mipi_dsi_clk_div_config(uint8 bpp, uint8 lanes,
 			    uint32 *expected_dsi_pclk);
 int mipi_dsi_clk_init(struct platform_device *pdev);
 void mipi_dsi_clk_deinit(struct device *dev);
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+void mipi_dsi_clk_enable(void);
+void mipi_dsi_clk_disable(void);
 void mipi_dsi_prepare_clocks(void);
 void mipi_dsi_unprepare_clocks(void);
 void mipi_dsi_ahb_ctrl(u32 enable);
+void mipi_dsi_phy_ctrl(int on);
+#else
+static inline void mipi_dsi_clk_enable(void)
+{
+	/* empty */
+}
+void mipi_dsi_clk_disable(void)
+{
+	/* empty */
+}
+void mipi_dsi_prepare_clocks(void)
+{
+	/* empty */
+}
+void mipi_dsi_unprepare_clocks(void)
+{
+	/* empty */
+}
+void mipi_dsi_ahb_ctrl(u32 enable)
+{
+	/* empty */
+}
+void mipi_dsi_phy_ctrl(int on)
+{
+	/* empty */
+}
+#endif
+
 void cont_splash_clk_ctrl(int enable);
 void mipi_dsi_turn_on_clks(void);
 void mipi_dsi_turn_off_clks(void);
@@ -344,6 +373,7 @@
 int mipi_dsi_cmdlist_put(struct dcs_cmd_req *cmdreq);
 struct dcs_cmd_req *mipi_dsi_cmdlist_get(void);
 void mipi_dsi_cmdlist_commit(int from_mdp);
+void mipi_dsi_cmd_mdp_busy(void);
 
 #ifdef CONFIG_FB_MSM_MDP303
 void update_lane_config(struct msm_panel_info *pinfo);
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 39a071b..2b75193 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -1519,7 +1519,7 @@
 {
 	u32 status;
 	unsigned long flags;
-	int need_wait;
+	int need_wait = 0;
 
 	spin_lock_irqsave(&dsi_mdp_lock, flags);
 	status = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */
@@ -1604,10 +1604,12 @@
 		mipi_dsi_cmd_mdp_busy();
 	}
 
-	if (req->flags && CMD_REQ_RX)
+	mipi_dsi_clk_cfg(1);
+	if (req->flags & CMD_REQ_RX)
 		mipi_dsi_cmdlist_rx(req);
 	else
 		mipi_dsi_cmdlist_tx(req);
+	mipi_dsi_clk_cfg(0);
 
 	mutex_unlock(&cmd_mutex);
 }
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 827a951..9c55fe8 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -57,6 +57,11 @@
 static unsigned char *fbram_phys;
 static int fbram_size;
 static boolean bf_supported;
+/* Set backlight on resume after 50 ms after first
+ * pan display on the panel. This is to avoid panel specific
+ * transients during resume.
+ */
+unsigned long backlight_duration = (HZ/20);
 
 static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
 static int pdev_list_cnt;
@@ -330,6 +335,8 @@
 	sysfs_remove_group(&mfd->fbi->dev->kobj, &msm_fb_attr_group);
 }
 
+static void bl_workqueue_handler(struct work_struct *work);
+
 static int msm_fb_probe(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd;
@@ -368,6 +375,8 @@
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
+	INIT_DELAYED_WORK(&mfd->backlight_worker, bl_workqueue_handler);
+
 	if (!mfd)
 		return -ENODEV;
 
@@ -904,6 +913,7 @@
 			mfd->op_enable = FALSE;
 			curr_pwr_state = mfd->panel_power_on;
 			mfd->panel_power_on = FALSE;
+			cancel_delayed_work_sync(&mfd->backlight_worker);
 			bl_updated = 0;
 
 			msleep(16);
@@ -1699,13 +1709,28 @@
 
 DEFINE_SEMAPHORE(msm_fb_pan_sem);
 
+static void bl_workqueue_handler(struct work_struct *work)
+{
+	struct msm_fb_data_type *mfd = container_of(to_delayed_work(work),
+				struct msm_fb_data_type, backlight_worker);
+	struct msm_fb_panel_data *pdata = mfd->pdev->dev.platform_data;
+
+	if ((pdata) && (pdata->set_backlight) && (!bl_updated)) {
+		down(&mfd->sem);
+		mfd->bl_level = unset_bl_level;
+		pdata->set_backlight(mfd);
+		bl_level_old = unset_bl_level;
+		bl_updated = 1;
+		up(&mfd->sem);
+	}
+}
+
 static int msm_fb_pan_display(struct fb_var_screeninfo *var,
 			      struct fb_info *info)
 {
 	struct mdp_dirty_region dirty;
 	struct mdp_dirty_region *dirtyPtr = NULL;
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	struct msm_fb_panel_data *pdata;
 
 	/*
 	 * If framebuffer is 2, io pen display is not allowed.
@@ -1791,18 +1816,12 @@
 	mdp_dma_pan_update(info);
 	up(&msm_fb_pan_sem);
 
-	if (unset_bl_level && !bl_updated) {
-		pdata = (struct msm_fb_panel_data *)mfd->pdev->
-			dev.platform_data;
-		if ((pdata) && (pdata->set_backlight)) {
-			down(&mfd->sem);
-			mfd->bl_level = unset_bl_level;
-			pdata->set_backlight(mfd);
-			bl_level_old = unset_bl_level;
-			up(&mfd->sem);
-			bl_updated = 1;
-		}
-	}
+	if (unset_bl_level && !bl_updated)
+		schedule_delayed_work(&mfd->backlight_worker,
+				backlight_duration);
+
+	if (info->node == 0 && (mfd->cont_splash_done)) /* primary */
+		mdp_free_splash_buffer(mfd);
 
 	++mfd->panel_info.frame_count;
 	return 0;
@@ -2943,7 +2962,6 @@
 	int	ret;
 	struct msmfb_overlay_data req;
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	struct msm_fb_panel_data *pdata;
 
 	if (mfd->overlay_play_enable == 0)	/* nothing to do */
 		return 0;
@@ -2974,18 +2992,12 @@
 
 	ret = mdp4_overlay_play(info, &req);
 
-	if (unset_bl_level && !bl_updated) {
-		pdata = (struct msm_fb_panel_data *)mfd->pdev->
-			dev.platform_data;
-		if ((pdata) && (pdata->set_backlight)) {
-			down(&mfd->sem);
-			mfd->bl_level = unset_bl_level;
-			pdata->set_backlight(mfd);
-			bl_level_old = unset_bl_level;
-			up(&mfd->sem);
-			bl_updated = 1;
-		}
-	}
+	if (unset_bl_level && !bl_updated)
+		schedule_delayed_work(&mfd->backlight_worker,
+				backlight_duration);
+
+	if (info->node == 0 && (mfd->cont_splash_done)) /* primary */
+		mdp_free_splash_buffer(mfd);
 
 	return ret;
 }
@@ -3243,12 +3255,14 @@
 
 	if (notify == NOTIFY_UPDATE_START) {
 		INIT_COMPLETION(mfd->msmfb_update_notify);
-		wait_for_completion_interruptible(&mfd->msmfb_update_notify);
+		ret = wait_for_completion_interruptible_timeout(
+		&mfd->msmfb_update_notify, 4*HZ);
 	} else {
 		INIT_COMPLETION(mfd->msmfb_no_update_notify);
-		wait_for_completion_interruptible(&mfd->msmfb_no_update_notify);
+		ret = wait_for_completion_interruptible_timeout(
+		&mfd->msmfb_no_update_notify, 4*HZ);
 	}
-	return 0;
+	return (ret > 0) ? 0 : -1;
 }
 
 static int msmfb_handle_pp_ioctl(struct msm_fb_data_type *mfd,
@@ -3321,7 +3335,24 @@
 
 	return ret;
 }
-
+static int msmfb_handle_metadata_ioctl(struct msm_fb_data_type *mfd,
+				struct msmfb_metadata *metadata_ptr)
+{
+	int ret;
+	switch (metadata_ptr->op) {
+#ifdef CONFIG_FB_MSM_MDP40
+	case metadata_op_base_blend:
+		ret = mdp4_update_base_blend(mfd,
+						&metadata_ptr->data.blend_cfg);
+		break;
+#endif
+	default:
+		pr_warn("Unsupported request to MDP META IOCTL.\n");
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
 static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
 			unsigned long arg)
 {
@@ -3339,6 +3370,7 @@
 #endif
 	struct mdp_page_protection fb_page_protection;
 	struct msmfb_mdp_pp mdp_pp;
+	struct msmfb_metadata mdp_metadata;
 	int ret = 0;
 
 	switch (cmd) {
@@ -3638,6 +3670,13 @@
 		ret = msmfb_handle_pp_ioctl(mfd, &mdp_pp);
 		break;
 
+	case MSMFB_METADATA_SET:
+		ret = copy_from_user(&mdp_metadata, argp, sizeof(mdp_metadata));
+		if (ret)
+			return ret;
+		ret = msmfb_handle_metadata_ioctl(mfd, &mdp_metadata);
+		break;
+
 	default:
 		MSM_FB_INFO("MDP: unknown ioctl (cmd=%x) received!\n", cmd);
 		ret = -EINVAL;
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index ae5acf4..2896349 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -80,7 +80,7 @@
 	DISP_TARGET dest;
 	struct fb_info *fbi;
 
-	struct device *dev;
+	struct delayed_work backlight_worker;
 	boolean op_enable;
 	uint32 fb_imgType;
 	boolean sw_currently_refreshing;
@@ -187,6 +187,8 @@
 	u32 writeback_state;
 	bool writeback_active_cnt;
 	int cont_splash_done;
+	void *copy_splash_buf;
+	unsigned char *copy_splash_phys;
 };
 
 struct dentry *msm_fb_get_debugfs_root(void);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
index a2327d5..2af76f3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c
@@ -70,7 +70,6 @@
 	case VIDC_1080P_ERROR_MEM_ALLOCATION_FAILED:
 	case VIDC_1080P_ERROR_INSUFFICIENT_CONTEXT_SIZE:
 	case VIDC_1080P_ERROR_DIVIDE_BY_ZERO:
-	case VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY:
 	case VIDC_1080P_ERROR_DMA_TX_NOT_COMPLETE:
 	case VIDC_1080P_ERROR_VSP_NOT_READY:
 	case VIDC_1080P_ERROR_BUFFER_FULL_STATE:
@@ -242,6 +241,7 @@
 	case VIDC_1080P_ERROR_HEADER_NOT_FOUND:
 	case VIDC_1080P_ERROR_SLICE_PARSE_ERROR:
 	case VIDC_1080P_ERROR_NON_PAIRED_FIELD_NOT_SUPPORTED:
+	case VIDC_1080P_ERROR_DESCRIPTOR_BUFFER_EMPTY:
 		vcd_status = VCD_ERR_BITSTREAM_ERR;
 		DDL_MSG_ERROR("VIDC_BIT_STREAM_ERR");
 		break;
@@ -766,6 +766,6 @@
 	break;
 	}
 	if (string)
-		DDL_MSG_ERROR("Recoverable Error code = 0x%x : %s",
+		DDL_MSG_LOW("Recoverable Error code = 0x%x : %s",
 					  error_code, string);
 }
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index dfbee84..d4601f2 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  *
  */
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <mach/msm_memtypes.h>
 #include "vcd_ddl.h"
 #include "vcd_ddl_shared_mem.h"
@@ -471,7 +471,7 @@
 		ddl = ddl_context->current_ddl[1];
 	else {
 		DDL_MSG_LOW("STATE-CRITICAL-FRMRUN");
-		DDL_MSG_ERROR("Unexpected channel ID = %d", channel_id);
+		DDL_MSG_LOW("Unexpected channel ID = %d", channel_id);
 		ddl = NULL;
 	}
 	return ddl;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index c1e460f..4f19de9 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -364,7 +364,7 @@
 				ddl->command_channel);
 		} else {
 			u32 seq_hdr_only_frame = false;
-			u32 need_reconfig = false;
+			u32 need_reconfig = false, eos_present = 0;
 			struct vcd_frame_data *input_vcd_frm =
 				&ddl->input_frame.vcd_frm;
 			need_reconfig = ddl_check_reconfig(ddl);
@@ -380,15 +380,25 @@
 				input_vcd_frm->offset +=
 					seq_hdr_info.dec_frm_size;
 				input_vcd_frm->data_len = 0;
-				input_vcd_frm->flags |=
-					VCD_FRAME_FLAG_CODECCONFIG;
-				ddl->input_frame.frm_trans_end =
-					!need_reconfig;
-				ddl_context->ddl_callback(
+				eos_present =
+				input_vcd_frm->flags & VCD_FRAME_FLAG_EOS;
+				if (!eos_present) {
+					input_vcd_frm->flags |=
+						VCD_FRAME_FLAG_CODECCONFIG;
+					ddl->input_frame.frm_trans_end =
+						!need_reconfig;
+					ddl_context->ddl_callback(
 					VCD_EVT_RESP_INPUT_DONE,
 					VCD_S_SUCCESS, &ddl->input_frame,
 					sizeof(struct ddl_frame_data_tag),
 					(u32 *) ddl, ddl->client_data);
+				} else {
+					input_vcd_frm->flags &=
+					~(VCD_FRAME_FLAG_CODECCONFIG);
+					seq_hdr_only_frame = false;
+					pr_err("%s() Codec config buffer with eos\n",
+						__func__);
+				}
 			} else {
 				if (decoder->codec.codec ==
 					VCD_CODEC_VC1_RCV) {
@@ -1175,20 +1185,28 @@
 		&(decoder->dec_disp_info);
 	struct ddl_frame_data_tag *output_frame = &(ddl->output_frame);
 	struct vcd_frame_data *output_vcd_frm = &(output_frame->vcd_frm);
+	enum vidc_1080p_decode_frame frame_type = 0;
 	u32 vcd_status, free_luma_dpb = 0, disp_pict = 0, is_interlaced;
+	u32 idr_frame = 0, coded_frame = 0;
 	get_dec_op_done_data(dec_disp_info, decoder->output_order,
 		&output_vcd_frm->physical, &is_interlaced);
 	decoder->progressive_only = !(is_interlaced);
 	output_vcd_frm->frame = VCD_FRAME_YUV;
+	vidc_sm_get_displayed_picture_frame(&ddl->shared_mem
+		[ddl->command_channel], &disp_pict);
+	coded_frame = (disp_pict & 0x03);
+	idr_frame = (disp_pict & 0x20) >> 5;
+	if (idr_frame)
+		frame_type = VIDC_1080P_DECODE_FRAMETYPE_IDR;
+	else
+		frame_type = (disp_pict & 0x1c) >> 2;
 	if (decoder->codec.codec == VCD_CODEC_MPEG4 ||
 		decoder->codec.codec == VCD_CODEC_VC1 ||
 		decoder->codec.codec == VCD_CODEC_VC1_RCV ||
 		(decoder->codec.codec >= VCD_CODEC_DIVX_3 &&
 		decoder->codec.codec <= VCD_CODEC_XVID)) {
-		vidc_sm_get_displayed_picture_frame(&ddl->shared_mem
-		[ddl->command_channel], &disp_pict);
 		if (decoder->output_order == VCD_DEC_ORDER_DISPLAY) {
-			if (!disp_pict) {
+			if (!coded_frame) {
 				output_vcd_frm->frame = VCD_FRAME_NOTCODED;
 				vidc_sm_get_available_luma_dpb_address(
 					&ddl->shared_mem[ddl->command_channel],
@@ -1213,6 +1231,7 @@
 		DDL_MSG_ERROR("CORRUPTED_OUTPUT_BUFFER_ADDRESS");
 		ddl_hw_fatal_cb(ddl);
 	} else {
+		ddl_get_decoded_frame(output_vcd_frm, frame_type);
 		vidc_sm_get_metadata_status(&ddl->shared_mem
 			[ddl->command_channel],
 			&decoder->meta_data_exists);
@@ -1347,6 +1366,10 @@
 	case VIDC_1080P_DECODE_FRAMETYPE_OTHERS:
 		frame->frame = VCD_FRAME_YUV;
 	break;
+	case VIDC_1080P_DECODE_FRAMETYPE_IDR:
+		frame->flags |= VCD_FRAME_FLAG_SYNCFRAME;
+		frame->frame = VCD_FRAME_IDR;
+	break;
 	case VIDC_1080P_DECODE_FRAMETYPE_32BIT:
 	default:
 		DDL_MSG_ERROR("UNKNOWN-FRAMETYPE");
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 2d3bee3..596c86f 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -1879,7 +1879,6 @@
 		output_buf_req = &decoder->actual_output_buf_req;
 		input_buf_req = &decoder->actual_input_buf_req;
 		min_dpb = decoder->min_dpb_num;
-		y_cb_cr_size = decoder->y_cb_cr_size;
 		if ((decoder->buf_format.buffer_format ==
 			VCD_BUFFER_FORMAT_TILE_4x2) &&
 			(frame_size->height < MDP_MIN_TILE_HEIGHT)) {
@@ -1891,6 +1890,7 @@
 				&decoder->buf_format,
 				(!decoder->progressive_only),
 				decoder->hdr.decoding, NULL);
+			decoder->y_cb_cr_size = y_cb_cr_size;
 		} else
 			y_cb_cr_size = decoder->y_cb_cr_size;
 	}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index 416b497..8099234 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -45,7 +45,7 @@
 #define VIDC_SM_DISP_PIC_PROFILE_DISP_PIC_PROFILE_SHFT      0
 
 #define VIDC_SM_DISP_PIC_FRAME_TYPE_ADDR                    0x00c0
-#define VIDC_SM_DISP_PIC_FRAME_TYPE_BMSK                    0x00000003
+#define VIDC_SM_DISP_PIC_FRAME_TYPE_BMSK                    0x0000003f
 #define VIDC_SM_DISP_PIC_FRAME_TYPE_SHFT                    0
 
 #define VIDC_SM_FREE_LUMA_DPB_ADDR                          0x00c4
@@ -947,7 +947,7 @@
 				VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
 			break;
 		default:
-			DDL_MSG_HIGH("Incorrect Aspect Ratio.");
+			DDL_MSG_LOW("Incorrect Aspect Ratio.");
 			aspect_ratio_info->par_width    = 1;
 			aspect_ratio_info->par_height   = 1;
 			break;
@@ -1005,7 +1005,7 @@
 				VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
 			break;
 		default:
-			DDL_MSG_HIGH("Incorrect Aspect Ratio.");
+			DDL_MSG_LOW("Incorrect Aspect Ratio.");
 			aspect_ratio_info->par_width    = 1;
 			aspect_ratio_info->par_height   = 1;
 			break;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 90114f7..5897a33 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -427,7 +427,7 @@
 		time_data->ddl_t1 = act_time;
 		DDL_MSG_LOW("\n%s(): Start Time (%u)", func_name, act_time);
 	} else if (vidc_msg_timing) {
-		DDL_MSG_TIME("\n%s(): Timer already started! St(%u) Act(%u)",
+		DDL_MSG_LOW("\n%s(): Timer already started! St(%u) Act(%u)",
 			func_name, time_data->ddl_t1, act_time);
 	}
 }
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index 04bb160..978d1de 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -260,6 +260,12 @@
 		vidc_sm_set_mpeg4_profile_override(
 			&ddl->shared_mem[ddl->command_channel],
 			VIDC_SM_PROFILE_INFO_ASP);
+	if (VCD_CODEC_MPEG2 == decoder->codec.codec)
+		vidc_sm_set_mp2datadumpbuffer(
+			&ddl->shared_mem[ddl->command_channel],
+			DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+			ddl->codec_data.decoder.hw_bufs.extnuserdata),
+			DDL_KILO_BYTE(2));
 	if (VCD_CODEC_H264 == decoder->codec.codec)
 		vidc_sm_set_decoder_sei_enable(
 			&ddl->shared_mem[ddl->command_channel],
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c
index d399847..3c445bc 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c
@@ -520,8 +520,12 @@
 	u32 frame = 0;
 
 	VIDC_HWIO_IN(REG_760102, &frame);
-	*pe_frame = (enum vidc_1080p_decode_frame)
-		(frame & VIDC_1080P_SI_RG8_DECODE_FRAMETYPE_MASK);
+	if (frame & 0x10)
+		*pe_frame = (enum vidc_1080p_decode_frame)
+			VIDC_1080P_DECODE_FRAMETYPE_IDR;
+	else
+		*pe_frame = (enum vidc_1080p_decode_frame)
+			(frame & VIDC_1080P_SI_RG8_DECODE_FRAMETYPE_MASK);
 }
 
 void vidc_1080p_get_decode_frame_result(
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
index 7b8dc6f..22fcd1c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -277,6 +277,7 @@
 	VIDC_1080P_DECODE_FRAMETYPE_P          = 2,
 	VIDC_1080P_DECODE_FRAMETYPE_B          = 3,
 	VIDC_1080P_DECODE_FRAMETYPE_OTHERS     = 4,
+	VIDC_1080P_DECODE_FRAMETYPE_IDR        = 5,
 	VIDC_1080P_DECODE_FRAMETYPE_32BIT      = 0x7FFFFFFF
 };
 enum vidc_1080P_decode_frame_correct_type {
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 972160a..3ac396c 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -537,9 +537,9 @@
 	u32 enc_perf_level = 0, dec_perf_level = 0;
 	u32 bus_clk_index, client_type = 0;
 	int rc = 0;
-
-	if (dev_ctxt->turbo_mode_set)
-		return rc;
+	bool turbo_enabled = false;
+	bool turbo_supported =
+		!resource_context.vidc_platform_data->disable_turbo;
 
 	cctxt_itr = dev_ctxt->cctxt_list_head;
 	while (cctxt_itr) {
@@ -547,6 +547,9 @@
 			dec_perf_level += cctxt_itr->reqd_perf_lvl;
 		else
 			enc_perf_level += cctxt_itr->reqd_perf_lvl;
+
+		if (cctxt_itr->is_turbo_enabled)
+			turbo_enabled = true;
 		cctxt_itr = cctxt_itr->next;
 	}
 
@@ -563,15 +566,17 @@
 
 	if (dev_ctxt->reqd_perf_lvl + dev_ctxt->curr_perf_lvl == 0)
 		bus_clk_index = 2;
-	else if (resource_context.vidc_platform_data->disable_turbo
-						&& bus_clk_index == 3) {
-		VCDRES_MSG_ERROR("Warning: Turbo mode not supported "
-				" falling back to 1080p bus\n");
+	else if ((!turbo_supported || !turbo_enabled) && bus_clk_index == 3) {
+		if (!turbo_supported)
+			VCDRES_MSG_MED("Warning: Turbo mode not supported "\
+					" falling back to 1080p bus\n");
 		bus_clk_index = 2;
 	}
 
 	if (bus_clk_index == 3)
-		dev_ctxt->turbo_mode_set = 1;
+		dev_ctxt->turbo_mode_set = true;
+	else
+		dev_ctxt->turbo_mode_set = false;
 
 	bus_clk_index = (bus_clk_index << 1) + (client_type + 1);
 	VCDRES_MSG_LOW("%s(), bus_clk_index = %d", __func__, bus_clk_index);
@@ -587,21 +592,18 @@
 	struct vcd_dev_ctxt *dev_ctxt)
 {
 	u32 vidc_freq = 0;
+	bool turbo_supported =
+		!resource_context.vidc_platform_data->disable_turbo;
+
 	if (!pn_set_perf_lvl || !dev_ctxt) {
 		VCDRES_MSG_ERROR("%s(): NULL pointer! dev_ctxt(%p)\n",
 			__func__, dev_ctxt);
 		return false;
 	}
-	if (dev_ctxt->turbo_mode_set &&
-			(req_perf_lvl < RESTRK_1080P_TURBO_PERF_LEVEL)) {
-		VCDRES_MSG_MED("%s(): TURBO MODE!!\n", __func__);
-		return true;
-	}
 
 	VCDRES_MSG_LOW("%s(), req_perf_lvl = %d", __func__, req_perf_lvl);
 
-	if (resource_context.vidc_platform_data->disable_turbo
-			&& req_perf_lvl > RESTRK_1080P_MAX_PERF_LEVEL) {
+	if (!turbo_supported && req_perf_lvl > RESTRK_1080P_MAX_PERF_LEVEL) {
 		VCDRES_MSG_ERROR("%s(): Turbo not supported! dev_ctxt(%p)\n",
 			__func__, dev_ctxt);
 	}
@@ -631,10 +633,11 @@
 		*pn_set_perf_lvl = RESTRK_1080P_TURBO_PERF_LEVEL;
 	}
 
-	if (resource_context.vidc_platform_data->disable_turbo &&
-		*pn_set_perf_lvl == RESTRK_1080P_TURBO_PERF_LEVEL) {
-		VCDRES_MSG_ERROR("Warning: Turbo mode not supported "
-				" falling back to 1080p clocks\n");
+	if ((!turbo_supported || !dev_ctxt->turbo_mode_set) &&
+		 *pn_set_perf_lvl == RESTRK_1080P_TURBO_PERF_LEVEL) {
+		if (!turbo_supported)
+			VCDRES_MSG_ERROR("Warning: Turbo mode not supported "\
+					" falling back to 1080p clocks\n");
 		vidc_freq = vidc_clk_table[2];
 		*pn_set_perf_lvl = RESTRK_1080P_MAX_PERF_LEVEL;
 	}
@@ -956,27 +959,54 @@
 
 int res_trk_open_secure_session()
 {
-	int rc;
-
-	if (res_trk_check_for_sec_session() == 1) {
-		mutex_lock(&resource_context.secure_lock);
+	int rc, memtype;
+	if (!res_trk_check_for_sec_session()) {
+		pr_err("Secure sessions are not active\n");
+		return -EINVAL;
+	}
+	mutex_lock(&resource_context.secure_lock);
+	if (!resource_context.sec_clk_heap) {
 		pr_err("Securing...\n");
 		rc = res_trk_enable_iommu_clocks();
 		if (rc) {
 			pr_err("IOMMU clock enabled failed while open");
 			goto error_open;
 		}
-		msm_ion_secure_heap(ION_HEAP(resource_context.memtype));
-		msm_ion_secure_heap(ION_HEAP(resource_context.cmd_mem_type));
-
-		if (resource_context.vidc_platform_data->secure_wb_heap)
-			msm_ion_secure_heap(ION_HEAP(ION_CP_WB_HEAP_ID));
-
+		memtype = ION_HEAP(resource_context.memtype);
+		rc = msm_ion_secure_heap(memtype);
+		if (rc) {
+			pr_err("ION heap secure failed heap id %d rc %d\n",
+				   resource_context.memtype, rc);
+			goto disable_iommu_clks;
+		}
+		memtype = ION_HEAP(resource_context.cmd_mem_type);
+		rc = msm_ion_secure_heap(memtype);
+		if (rc) {
+			pr_err("ION heap secure failed heap id %d rc %d\n",
+				   resource_context.cmd_mem_type, rc);
+			goto unsecure_memtype_heap;
+		}
+		if (resource_context.vidc_platform_data->secure_wb_heap) {
+			memtype = ION_HEAP(ION_CP_WB_HEAP_ID);
+			rc = msm_ion_secure_heap(memtype);
+			if (rc) {
+				pr_err("WB_HEAP_ID secure failed rc %d\n", rc);
+				goto unsecure_cmd_heap;
+			}
+		}
+		resource_context.sec_clk_heap = 1;
 		res_trk_disable_iommu_clocks();
-		mutex_unlock(&resource_context.secure_lock);
 	}
+	mutex_unlock(&resource_context.secure_lock);
 	return 0;
+unsecure_cmd_heap:
+	msm_ion_unsecure_heap(ION_HEAP(resource_context.memtype));
+unsecure_memtype_heap:
+	msm_ion_unsecure_heap(ION_HEAP(resource_context.cmd_mem_type));
+disable_iommu_clks:
+	res_trk_disable_iommu_clocks();
 error_open:
+	resource_context.sec_clk_heap = 0;
 	mutex_unlock(&resource_context.secure_lock);
 	return rc;
 }
@@ -984,12 +1014,13 @@
 int res_trk_close_secure_session()
 {
 	int rc;
-	if (res_trk_check_for_sec_session() == 1) {
+	if (res_trk_check_for_sec_session() == 1 &&
+		resource_context.sec_clk_heap) {
 		pr_err("Unsecuring....\n");
 		mutex_lock(&resource_context.secure_lock);
 		rc = res_trk_enable_iommu_clocks();
 		if (rc) {
-			pr_err("IOMMU clock enabled failed while close");
+			pr_err("IOMMU clock enabled failed while close\n");
 			goto error_close;
 		}
 		msm_ion_unsecure_heap(ION_HEAP(resource_context.cmd_mem_type));
@@ -999,6 +1030,7 @@
 			msm_ion_unsecure_heap(ION_HEAP(ION_CP_WB_HEAP_ID));
 
 		res_trk_disable_iommu_clocks();
+		resource_context.sec_clk_heap = 0;
 		mutex_unlock(&resource_context.secure_lock);
 	}
 	return 0;
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
index 01999a4..a980230 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
@@ -14,7 +14,7 @@
 #define _VIDEO_720P_RESOURCE_TRACKER_H_
 
 #include <linux/regulator/consumer.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include "vcd_res_tracker_api.h"
 #ifdef CONFIG_MSM_BUS_SCALING
 #include <mach/msm_bus.h>
@@ -57,6 +57,7 @@
 	u32 mmu_clks_on;
 	u32 secure_session;
 	struct mutex secure_lock;
+	u32 sec_clk_heap;
 };
 
 #if DEBUG
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
index f8d9053..5f126fd 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h
@@ -13,7 +13,7 @@
 #ifndef _VIDEO_720P_RESOURCE_TRACKER_H_
 #define _VIDEO_720P_RESOURCE_TRACKER_H_
 #include <mach/board.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include "vcd_res_tracker_api.h"
 
 #define VCD_RESTRK_MIN_PERF_LEVEL 37900
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index f68265a..68bcd5c 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -2079,10 +2079,6 @@
 	mutex_unlock(&client_ctx->msg_queue_lock);
 	vcd_status = vcd_close(client_ctx->vcd_handle);
 
-	if (vcd_status) {
-		mutex_unlock(&vid_dec_device_p->lock);
-		return false;
-	}
 	client_ctx->user_ion_client = NULL;
 	memset((void *)client_ctx, 0, sizeof(struct video_client_ctx));
 	vid_dec_device_p->num_clients--;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index 8126a0e..ae97561 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -13,7 +13,7 @@
 #ifndef _VCD_CORE_H_
 #define _VCD_CORE_H_
 
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <media/msm/vcd_api.h>
 #include "vcd_ddl_api.h"
 
@@ -147,7 +147,7 @@
 	u32 reqd_perf_lvl;
 	u32 curr_perf_lvl;
 	u32 set_perf_lvl_pending;
-	u32 turbo_mode_set;
+	bool turbo_mode_set;
 };
 
 struct vcd_clnt_status {
@@ -214,6 +214,7 @@
 	u32 meta_mode;
 	int perf_set_by_client;
 	int secure;
+	bool is_turbo_enabled;
 };
 
 #define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index 53495e0..0d13028 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -759,7 +759,6 @@
 	client = dev_ctxt->cctxt_list_head;
 	dev_ctxt->cctxt_list_head = cctxt;
 	cctxt->next = client;
-	dev_ctxt->turbo_mode_set = 0;
 
 	*clnt_cctxt = cctxt;
 
@@ -858,7 +857,7 @@
 	} else {
 		VCD_MSG_ERROR("Unsupported API in client state %d",
 				  cctxt->clnt_state.state);
-
+		vcd_destroy_client_context(cctxt);
 		rc = VCD_ERR_BAD_STATE;
 	}
 
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index b97a58e..71e8df8 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -3051,6 +3051,7 @@
 {
 	u32 rc;
 	u32 res_trk_perf_level;
+	u32 turbo_perf_level;
 	if (!perf_level) {
 		VCD_MSG_ERROR("Invalid parameters\n");
 		return -EINVAL;
@@ -3060,10 +3061,13 @@
 		rc = -ENOTSUPP;
 		goto perf_level_not_supp;
 	}
+	turbo_perf_level = get_res_trk_perf_level(VCD_PERF_LEVEL_TURBO);
 	rc = vcd_set_perf_level(cctxt->dev_ctxt, res_trk_perf_level);
 	if (!rc) {
 		cctxt->reqd_perf_lvl = res_trk_perf_level;
 		cctxt->perf_set_by_client = 1;
+		if (res_trk_perf_level == turbo_perf_level)
+			cctxt->is_turbo_enabled = true;
 	}
 perf_level_not_supp:
 	return rc;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index a19d374..e76b0ae 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1167,6 +1167,8 @@
 
 struct work_struct;
 int kblockd_schedule_work(struct request_queue *q, struct work_struct *work);
+int kblockd_schedule_delayed_work(struct request_queue *q,
+			struct delayed_work *dwork, unsigned long delay);
 
 #ifdef CONFIG_BLK_CGROUP
 /*
diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h
index 56a6cdf..754f2f3 100644
--- a/include/linux/coresight-stm.h
+++ b/include/linux/coresight-stm.h
@@ -19,7 +19,6 @@
 	OST_ENTITY_TRACE_PRINTK		= 0x02,
 	OST_ENTITY_TRACE_MARKER		= 0x04,
 	OST_ENTITY_DEV_NODE		= 0x08,
-	OST_ENTITY_PRINTK		= 0x10,
 	OST_ENTITY_ALL			= 0x1F,
 };
 
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 04fcd88..0bdacffa 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,11 +30,6 @@
 #define CORESIGHT_COMPIDR2	(0xFF8)
 #define CORESIGHT_COMPIDR3	(0xFFC)
 
-/* DBGv7 with baseline CP14 registers implemented */
-#define ARM_DEBUG_ARCH_V7B	(0x3)
-/* DBGv7 with all CP14 registers implemented */
-#define ARM_DEBUG_ARCH_V7	(0x4)
-#define ARM_DEBUG_ARCH_V7_1	(0x5)
 #define ETM_ARCH_V3_3		(0x23)
 #define PFT_ARCH_V1_1		(0x31)
 
@@ -45,6 +40,7 @@
 };
 
 enum coresight_dev_type {
+	CORESIGHT_DEV_TYPE_NONE,
 	CORESIGHT_DEV_TYPE_SINK,
 	CORESIGHT_DEV_TYPE_LINK,
 	CORESIGHT_DEV_TYPE_LINKSINK,
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index c953613..45d51ce 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -689,7 +689,7 @@
 /* LOG CODES */
 
 #define LOG_0	0x0
-#define LOG_1	0x15A7
+#define LOG_1	0x1636
 #define LOG_2	0x0
 #define LOG_3	0x0
 #define LOG_4	0x4910
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 9cf2acf..076302b 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -13,9 +13,80 @@
 	int32_t physical;
 };
 
+struct epm_psoc_init_resp {
+	u8	cmd;
+	u8	version;
+	u8	compatible_ver;
+	u8	firm_ver[3];
+	u8	num_dev;
+	u8	num_channel;
+};
+
+struct epm_psoc_channel_configure {
+	u8		cmd;
+	u8		device_num;
+	uint32_t	channel_num;
+};
+
+struct epm_psoc_set_avg {
+	u8	cmd;
+	u8	avg_period;
+	u8	return_code;
+};
+
+struct epm_psoc_get_data {
+	u8		cmd;
+	u8		dev_num;
+	u8		chan_num;
+	uint32_t	timestamp_resp_value;
+	uint32_t	reading_value;
+};
+
+struct epm_psoc_get_buffered_data {
+	u8		cmd;
+	u8		dev_num;
+	u8		status_mask;
+	u8		chan_idx;
+	uint32_t	chan_mask;
+	uint32_t	timestamp_start;
+	uint32_t	timestamp_end;
+	u8		buff_data[48];
+};
+
+struct epm_psoc_system_time_stamp {
+	u8		cmd;
+	uint32_t	timestamp;
+};
+
+struct epm_psoc_set_channel {
+	u8		cmd;
+	u8		dev_num;
+	uint32_t	channel_mask;
+};
+
+struct epm_psoc_get_avg_buffered_switch_data {
+	u8		cmd;
+	u8		status;
+	uint32_t	timestamp_start;
+	uint32_t	channel_mask;
+	u8		avg_data[54];
+};
+
+struct epm_psoc_set_channel_switch {
+	u8		cmd;
+	u8		dev;
+	uint32_t	delay;
+};
+
+struct epm_psoc_set_vadc {
+	u8		cmd;
+	u8		vadc_dev;
+	uint32_t	vadc_voltage;
+};
+
 #ifdef __KERNEL__
 struct epm_chan_properties {
-	uint32_t resistorValue;
+	uint32_t resistorvalue;
 	uint32_t gain;
 };
 
@@ -41,4 +112,41 @@
 
 #define EPM_ADC_DEINIT		_IOR(EPM_ADC_IOCTL_CODE, 3,	\
 					     uint32_t)
+
+#define EPM_PSOC_ADC_INIT		_IOR(EPM_ADC_IOCTL_CODE, 4, \
+					struct epm_psoc_init_resp)
+
+#define EPM_PSOC_ADC_CHANNEL_ENABLE	_IOWR(EPM_ADC_IOCTL_CODE, 5, \
+					struct epm_psoc_channel_configure)
+
+#define EPM_PSOC_ADC_CHANNEL_DISABLE	_IOWR(EPM_ADC_IOCTL_CODE, 6, \
+					struct epm_psoc_channel_configure)
+
+#define EPM_PSOC_ADC_SET_AVERAGING	_IOWR(EPM_ADC_IOCTL_CODE, 7, \
+					struct epm_psoc_set_avg)
+
+#define EPM_PSOC_ADC_GET_LAST_MEASUREMENT	_IOWR(EPM_ADC_IOCTL_CODE, 8, \
+						struct epm_psoc_get_data)
+
+#define EPM_PSOC_ADC_GET_BUFFERED_DATA		_IOWR(EPM_ADC_IOCTL_CODE, 9, \
+					struct epm_psoc_get_buffered_data)
+
+#define EPM_PSOC_ADC_GET_SYSTEM_TIMESTAMP	_IOWR(EPM_ADC_IOCTL_CODE, 10, \
+					struct epm_psoc_system_time_stamp)
+
+#define EPM_PSOC_ADC_SET_SYSTEM_TIMESTAMP	_IOWR(EPM_ADC_IOCTL_CODE, 11, \
+					struct epm_psoc_system_time_stamp)
+
+#define EPM_PSOC_ADC_GET_AVERAGE_DATA		_IOWR(EPM_ADC_IOCTL_CODE, 12, \
+				struct epm_psoc_get_avg_buffered_switch_data)
+
+#define EPM_PSOC_SET_CHANNEL_SWITCH		_IOWR(EPM_ADC_IOCTL_CODE, 13, \
+					struct epm_psoc_set_channel_switch)
+
+#define EPM_PSOC_CLEAR_BUFFER			_IOWR(EPM_ADC_IOCTL_CODE, 14, \
+						uint32_t)
+
+#define EPM_PSOC_ADC_SET_VADC_REFERENCE		_IOWR(EPM_ADC_IOCTL_CODE, 15, \
+						struct epm_psoc_set_vadc)
+
 #endif /* __EPM_ADC_H */
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 2519270..6ac2835 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -704,6 +704,7 @@
 struct ion_allocation_data {
 	size_t len;
 	size_t align;
+	unsigned int heap_mask;
 	unsigned int flags;
 	struct ion_handle *handle;
 };
@@ -824,7 +825,7 @@
  * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle
  * filed set to the corresponding opaque handle.
  */
-#define ION_IOC_IMPORT		_IOWR(ION_IOC_MAGIC, 5, int)
+#define ION_IOC_IMPORT		_IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
 
 /**
  * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl
@@ -840,21 +841,21 @@
  *
  * Clean the caches of the handle specified.
  */
-#define ION_IOC_CLEAN_CACHES	_IOWR(ION_IOC_MAGIC, 7, \
+#define ION_IOC_CLEAN_CACHES	_IOWR(ION_IOC_MAGIC, 20, \
 						struct ion_flush_data)
 /**
  * DOC: ION_MSM_IOC_INV_CACHES - invalidate the caches
  *
  * Invalidate the caches of the handle specified.
  */
-#define ION_IOC_INV_CACHES	_IOWR(ION_IOC_MAGIC, 8, \
+#define ION_IOC_INV_CACHES	_IOWR(ION_IOC_MAGIC, 21, \
 						struct ion_flush_data)
 /**
  * DOC: ION_MSM_IOC_CLEAN_CACHES - clean and invalidate the caches
  *
  * Clean and invalidate the caches of the handle specified.
  */
-#define ION_IOC_CLEAN_INV_CACHES	_IOWR(ION_IOC_MAGIC, 9, \
+#define ION_IOC_CLEAN_INV_CACHES	_IOWR(ION_IOC_MAGIC, 22, \
 						struct ion_flush_data)
 
 /**
@@ -863,6 +864,6 @@
  * Gets the flags of the current handle which indicate cachability,
  * secure state etc.
  */
-#define ION_IOC_GET_FLAGS		_IOWR(ION_IOC_MAGIC, 10, \
+#define ION_IOC_GET_FLAGS		_IOWR(ION_IOC_MAGIC, 23, \
 						struct ion_flag_data)
 #endif /* _LINUX_ION_H */
diff --git a/include/linux/mfd/pm8xxx/spk.h b/include/linux/mfd/pm8xxx/spk.h
index 1155d2f..2905a1d 100644
--- a/include/linux/mfd/pm8xxx/spk.h
+++ b/include/linux/mfd/pm8xxx/spk.h
@@ -21,6 +21,14 @@
  */
 struct pm8xxx_spk_platform_data {
 	bool spk_add_enable;
+	int cd_ng_threshold;
+	int cd_nf_preamp_bias;
+	int cd_ng_hold;
+	int cd_ng_max_atten;
+	int noise_mute;
+	int cd_ng_decay_rate;
+	int cd_ng_attack_rate;
+	int cd_delay;
 };
 
 /*
diff --git a/include/linux/mfd/pm8xxx/tm.h b/include/linux/mfd/pm8xxx/tm.h
index 6974754..74b77ec 100644
--- a/include/linux/mfd/pm8xxx/tm.h
+++ b/include/linux/mfd/pm8xxx/tm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -22,21 +22,55 @@
 
 #define PM8XXX_TM_DEV_NAME	"pm8xxx-tm"
 
+/**
+ * enum pm8xxx_tm_adc_type - support ADC API types for PMIC thermal manager
+ * %PM8XXX_TM_ADC_NONE:		Do not call any ADC API and instead estimate
+ *				PMIC temerature based on over temperature stage.
+ * %PM8XXX_TM_ADC_PM8058_ADC:	Use the pmic8058-xoadc ADC API
+ * %PM8XXX_TM_ADC_PM8XXX_ADC:	Use the pm8xxx-adc ADC API
+ */
 enum pm8xxx_tm_adc_type {
-	PM8XXX_TM_ADC_NONE,	/* Estimates temp based on overload level. */
+	PM8XXX_TM_ADC_NONE,
 	PM8XXX_TM_ADC_PM8058_ADC,
 	PM8XXX_TM_ADC_PM8XXX_ADC,
 };
 
+/**
+ * struct pm8xxx_tm_core_data - PM8XXX thermal manager core data
+ * @tm_name:			Thermal zone name for the device
+ * @irq_name_temp_stat:		String name used to identify TEMP_STAT IRQ
+ * @irq_name_over_temp:		String name used to identify OVER_TEMP IRQ
+ * @reg_addr_temp_alarm_ctrl:	PMIC SSBI address for temp alarm control
+ *				register
+ * @reg_addr_temp_alarm_pwm:	PMIC SSBI address for temp alarm pwm register
+ * @adc_type:			Determines which ADC API to use in order to read
+ *				the PMIC die temperature.
+ * @adc_channel:		ADC channel identifier
+ *				If adc_type == PM8XXX_TM_ADC_PM8XXX_ADC, then
+ *				use a value from enum pm8xxx_adc_channels.
+ *				If adc_type == PM8XXX_TM_ADC_PM8058_ADC, then
+ *				use a channel value specified in
+ *				<linux/pmic8058-xoadc.h>
+ * @default_no_adc_temp:	Default temperature in millicelcius to report
+ *				while stage == 0 and stage has never been
+ *				greater than 0 if adc_type == PM8XXX_TM_ADC_NONE
+ * @allow_software_override:	true --> writing "enabled" to thermalfs mode
+ *				file results in software override of PMIC
+ *				automatic over temperature shutdown
+ *				false --> PMIC automatic over temperature
+ *				shutdown always enabled.  mode file cannot be
+ *				set to "enabled".
+ */
 struct pm8xxx_tm_core_data {
-	int				adc_channel;
-	unsigned long			default_no_adc_temp;
-	enum pm8xxx_tm_adc_type		adc_type;
-	u16				reg_addr_temp_alarm_ctrl;
-	u16				reg_addr_temp_alarm_pwm;
-	char				*tm_name;
-	char				*irq_name_temp_stat;
-	char				*irq_name_over_temp;
+	char			*tm_name;
+	char			*irq_name_temp_stat;
+	char			*irq_name_over_temp;
+	u16			reg_addr_temp_alarm_ctrl;
+	u16			reg_addr_temp_alarm_pwm;
+	enum pm8xxx_tm_adc_type	adc_type;
+	int			adc_channel;
+	unsigned long		default_no_adc_temp;
+	bool			allow_software_override;
 };
 
 #endif
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 105c2cb..f6d164d 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -157,10 +157,7 @@
 	int num_rx_port;
 	int num_tx_port;
 
-	u8 idbyte_0;
-	u8 idbyte_1;
-	u8 idbyte_2;
-	u8 idbyte_3;
+	u8 idbyte[4];
 };
 
 int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
diff --git a/include/linux/msm_audio_aac.h b/include/linux/msm_audio_aac.h
index 620e5ab..ee71c3e 100644
--- a/include/linux/msm_audio_aac.h
+++ b/include/linux/msm_audio_aac.h
@@ -60,6 +60,7 @@
 	unsigned short sbr_ps_on_flag;
 	unsigned short dual_mono_mode;
 	unsigned short channel_configuration;
+	unsigned short sample_rate;
 };
 
 struct msm_audio_aac_enc_config {
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 7afc896..2253655 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -367,6 +367,12 @@
     _IOW(KGSL_IOC_TYPE, 0x22, struct kgsl_bind_gmem_shadow)
 
 /* add a block of memory into the GPU address space */
+
+/*
+ * IOCTL_KGSL_SHAREDMEM_FROM_VMALLOC deprecated 09/2012
+ * use IOCTL_KGSL_GPUMEM_ALLOC instead
+ */
+
 struct kgsl_sharedmem_from_vmalloc {
 	unsigned int gpuaddr;	/*output param */
 	unsigned int hostptr;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index e7cbb79..d03ecfa 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -70,6 +70,7 @@
 #define MSMFB_MDP_PP _IOWR(MSMFB_IOCTL_MAGIC, 156, struct msmfb_mdp_pp)
 #define MSMFB_OVERLAY_VSYNC_CTRL _IOW(MSMFB_IOCTL_MAGIC, 160, unsigned int)
 #define MSMFB_VSYNC_CTRL  _IOW(MSMFB_IOCTL_MAGIC, 161, unsigned int)
+#define MSMFB_METADATA_SET  _IOW(MSMFB_IOCTL_MAGIC, 162, struct msmfb_metadata)
 #define FB_TYPE_3D_PANEL 0x10101010
 #define MDP_IMGTYPE2_START 0x10000
 #define MSMFB_DRIVER_VERSION	0xF9E8D701
@@ -271,8 +272,10 @@
 	struct msmfb_img img;
 };
 
+#define MDP_PP_OPS_ENABLE 0x1
 #define MDP_PP_OPS_READ 0x2
 #define MDP_PP_OPS_WRITE 0x4
+#define MDP_PP_OPS_DISABLE 0x8
 
 struct mdp_qseed_cfg {
 	uint32_t table_num;
@@ -354,12 +357,15 @@
 
 /*
 
-	mdp_block_type defines the identifiers for each of pipes in MDP 4.3
+	mdp_block_type defines the identifiers for pipes in MDP 4.3 and up
 
 	MDP_BLOCK_RESERVED is provided for backward compatibility and is
 	deprecated. It corresponds to DMA_P. So MDP_BLOCK_DMA_P should be used
 	instead.
 
+	MDP_LOGICAL_BLOCK_DISP_0 identifies the display pipe which fb0 uses,
+	same for others.
+
 */
 
 enum {
@@ -374,6 +380,9 @@
 	MDP_BLOCK_DMA_S,
 	MDP_BLOCK_DMA_E,
 	MDP_BLOCK_OVERLAY_2,
+	MDP_LOGICAL_BLOCK_DISP_0 = 0x1000,
+	MDP_LOGICAL_BLOCK_DISP_1,
+	MDP_LOGICAL_BLOCK_DISP_2,
 	MDP_BLOCK_MAX,
 };
 
@@ -466,12 +475,22 @@
 	uint32_t scale;
 };
 
+struct mdp_pa_cfg_data {
+	uint32_t block;
+	uint32_t flags;
+	uint32_t hue_adj;
+	uint32_t sat_adj;
+	uint32_t val_adj;
+	uint32_t cont_adj;
+};
+
 enum {
 	mdp_op_pcc_cfg,
 	mdp_op_csc_cfg,
 	mdp_op_lut_cfg,
 	mdp_op_qseed_cfg,
 	mdp_bl_scale_cfg,
+	mdp_op_pa_cfg,
 	mdp_op_max,
 };
 
@@ -483,10 +502,27 @@
 		struct mdp_lut_cfg_data lut_cfg_data;
 		struct mdp_qseed_cfg_data qseed_cfg_data;
 		struct mdp_bl_scale_data bl_scale_data;
+		struct mdp_pa_cfg_data pa_cfg_data;
 	} data;
 };
 
+enum {
+	metadata_op_none,
+	metadata_op_base_blend,
+	metadata_op_max
+};
 
+struct mdp_blend_cfg {
+	uint32_t is_premultiplied;
+};
+
+struct msmfb_metadata {
+	uint32_t op;
+	uint32_t flags;
+	union {
+		struct mdp_blend_cfg blend_cfg;
+	} data;
+};
 struct mdp_page_protection {
 	uint32_t page_protection;
 };
@@ -514,7 +550,7 @@
 };
 
 #ifdef __KERNEL__
-
+int msm_fb_get_iommu_domain(void);
 /* get the framebuffer physical address information */
 int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num,
 	int subsys_id);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index cb56293..647a7ef 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -140,6 +140,7 @@
 	POWER_SUPPLY_TYPE_USB_DCP,	/* Dedicated Charging Port */
 	POWER_SUPPLY_TYPE_USB_CDP,	/* Charging Downstream Port */
 	POWER_SUPPLY_TYPE_USB_ACA,	/* Accessory Charger Adapters */
+	POWER_SUPPLY_TYPE_BMS,		/* Battery Monitor System */
 };
 
 union power_supply_propval {
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 8468aa5..f74db80 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -175,17 +175,19 @@
 
 /**
  * enum qpnp_adc_channel_scaling_param - pre-scaling AMUX ratio.
- * %CHAN_PATH_SCALING1: ratio of {1, 1}
- * %CHAN_PATH_SCALING2: ratio of {1, 3}
- * %CHAN_PATH_SCALING3: ratio of {1, 4}
- * %CHAN_PATH_SCALING4: ratio of {1, 6}
+ * %CHAN_PATH_SCALING0: ratio of {1, 1}
+ * %CHAN_PATH_SCALING1: ratio of {1, 3}
+ * %CHAN_PATH_SCALING2: ratio of {1, 4}
+ * %CHAN_PATH_SCALING3: ratio of {1, 6}
+ * %CHAN_PATH_SCALING4: ratio of {1, 20}
  * %CHAN_PATH_NONE: Do not use this pre-scaling ratio type.
  *
  * The pre-scaling is applied for signals to be within the voltage range
  * of the ADC.
  */
 enum qpnp_adc_channel_scaling_param {
-	PATH_SCALING1 = 0,
+	PATH_SCALING0 = 0,
+	PATH_SCALING1,
 	PATH_SCALING2,
 	PATH_SCALING3,
 	PATH_SCALING4,
@@ -197,17 +199,21 @@
  *				   digital data relative to ADC reference.
  * %ADC_SCALE_DEFAULT: Default scaling to convert raw adc code to voltage.
  * %ADC_SCALE_BATT_THERM: Conversion to temperature based on btm parameters.
+ * %ADC_SCALE_THERM_100K_PULLUP: Returns temperature in degC.
+ *				 Uses a mapping table with 100K pullup.
  * %ADC_SCALE_PMIC_THERM: Returns result in milli degree's Centigrade.
- * %ADC_SCALE_XTERN_CHGR_CUR: Returns current across 0.1 ohm resistor.
  * %ADC_SCALE_XOTHERM: Returns XO thermistor voltage in degree's Centigrade.
+ * %ADC_SCALE_THERM_150K_PULLUP: Returns temperature in degC.
+ *				 Uses a mapping table with 150K pullup.
  * %ADC_SCALE_NONE: Do not use this scaling type.
  */
 enum qpnp_adc_scale_fn_type {
 	SCALE_DEFAULT = 0,
 	SCALE_BATT_THERM,
-	SCALE_PA_THERM,
+	SCALE_THERM_100K_PULLUP,
 	SCALE_PMIC_THERM,
 	SCALE_XOTHERM,
+	SCALE_THERM_150K_PULLUP,
 	SCALE_NONE,
 };
 
@@ -701,6 +707,109 @@
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
+/**
+ * qpnp_adc_scale_pmic_therm() - Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset. Performs the AMUX out as 2mV/K and returns
+ *		the temperature in milli degC.
+ * @adc_code:	pre-calibrated digital ouput of the ADC.
+ * @adc_prop:	adc properties of the qpnp adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	Individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	Physical result to be stored.
+ */
+int32_t qpnp_adc_scale_pmic_therm(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
+ * qpnp_adc_scale_batt_therm() - Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset. Returns the temperature in degC.
+ * @adc_code:	pre-calibrated digital ouput of the ADC.
+ * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	physical result to be stored.
+ */
+int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
+ * qpnp_adc_scale_batt_id() - Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset.
+ * @adc_code:	pre-calibrated digital ouput of the ADC.
+ * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	physical result to be stored.
+ */
+int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
+ * qpnp_adc_scale_tdkntcg_therm() - Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset. Returns the temperature of the xo therm in mili
+		degC.
+ * @adc_code:	pre-calibrated digital ouput of the ADC.
+ * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	physical result to be stored.
+ */
+int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
+ * qpnp_adc_scale_therm_pu1() - Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset. Returns the temperature of the therm in degC.
+ *		It uses a mapping table computed for a 150K pull-up.
+ *		Pull-up1 is an internal pull-up on the AMUX of 150K.
+ * @adc_code:	pre-calibrated digital ouput of the ADC.
+ * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	physical result to be stored.
+ */
+int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
+ * qpnp_adc_scale_therm_pu2() - Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset. Returns the temperature of the therm in degC.
+ *		It uses a mapping table computed for a 100K pull-up.
+ *		Pull-up2 is an internal pull-up on the AMUX of 100K.
+ * @adc_code:	pre-calibrated digital ouput of the ADC.
+ * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	physical result to be stored.
+ */
+int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
+ * qpnp_vadc_is_ready() - Clients can use this API to check if the
+ *			  device is ready to use.
+ * @result:	0 on success and -EPROBE_DEFER when probe for the device
+ *		has not occured.
+ */
+int32_t qpnp_vadc_is_ready(void);
 #else
 static inline int32_t qpnp_vadc_read(uint32_t channel,
 				struct qpnp_vadc_result *result)
@@ -712,8 +821,40 @@
 { return -ENXIO; }
 static inline int32_t qpnp_adc_scale_default(int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
-			const struct qpnp_adc_chan_properties *chan_prop,
-			struct qpnp_adc_chan_result *chan_rslt)
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_pmic_therm(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+{ return -ENXIO; }
+static inline int32_t qpnp_vadc_is_read(void)
 { return -ENXIO; }
 #endif
 
@@ -742,6 +883,13 @@
  */
 int32_t qpnp_iadc_get_offset(enum qpnp_iadc_channels channel,
 						int32_t *result);
+/**
+ * qpnp_iadc_is_ready() - Clients can use this API to check if the
+ *			  device is ready to use.
+ * @result:	0 on success and -EPROBE_DEFER when probe for the device
+ *		has not occured.
+ */
+int32_t qpnp_iadc_is_ready(void);
 #else
 static inline int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
 							int *result)
@@ -751,6 +899,8 @@
 static inline int32_t qpnp_iadc_get_offset(enum qpnp_iadc_channels channel,
 						int32_t *result)
 { return -ENXIO; }
+static inline int32_t qpnp_iadc_is_read(void)
+{ return -ENXIO; }
 #endif
 
 #endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5fb3719..2c9509d 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1819,6 +1819,7 @@
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_NPROC_EXCEEDED 0x00001000	/* set_user noticed that RLIMIT_NPROC was exceeded */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
+#define PF_WAKE_UP_IDLE 0x00004000	/* try to wake up on an idle CPU */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
@@ -1936,6 +1937,14 @@
 }
 #endif
 
+static inline void set_wake_up_idle(bool enabled)
+{
+	if (enabled)
+		current->flags |= PF_WAKE_UP_IDLE;
+	else
+		current->flags &= ~PF_WAKE_UP_IDLE;
+}
+
 #ifndef CONFIG_CPUMASK_OFFSTACK
 static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
 {
diff --git a/include/linux/sync.h b/include/linux/sync.h
index 943f414..4c00f04 100644
--- a/include/linux/sync.h
+++ b/include/linux/sync.h
@@ -24,6 +24,7 @@
 struct sync_timeline;
 struct sync_pt;
 struct sync_fence;
+struct seq_file;
 
 /**
  * struct sync_timeline_ops - sync object implementation ops
diff --git a/include/linux/topology.h b/include/linux/topology.h
index e26db03..92a89f0 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -166,7 +166,7 @@
 				| 1*SD_WAKE_AFFINE			\
 				| 0*SD_PREFER_LOCAL			\
 				| 0*SD_SHARE_CPUPOWER			\
-				| 0*SD_SHARE_PKG_RESOURCES		\
+				| 1*SD_SHARE_PKG_RESOURCES		\
 				| 0*SD_SERIALIZE			\
 				| sd_balance_for_package_power()	\
 				| sd_power_saving_flags()		\
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index dc13bd9..dd091cd 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -346,9 +346,8 @@
 	int	(*update_device)(struct usb_hcd *, struct usb_device *);
 	int	(*set_usb2_hw_lpm)(struct usb_hcd *, struct usb_device *, int);
 
-	/* to log completion events*/
-	void	(*log_urb_complete)(struct urb *urb, char * event,
-			unsigned extra);
+	/* to log submission/completion events*/
+	void	(*log_urb)(struct urb *urb, char *event, unsigned extra);
 	void	(*dump_regs)(struct usb_hcd *);
 	void	(*enable_ulpi_control)(struct usb_hcd *hcd, u32 linestate);
 	void	(*disable_ulpi_control)(struct usb_hcd *hcd);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 59ba64b..adcc450 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -328,10 +328,12 @@
 	bool sm_work_pending;
 	atomic_t pm_suspended;
 	atomic_t in_lpm;
+	atomic_t suspend_work_pending;
 	int async_int;
 	unsigned cur_power;
 	struct delayed_work chg_work;
 	struct delayed_work pmic_id_status_work;
+	struct delayed_work suspend_work;
 	enum usb_chg_state chg_state;
 	enum usb_chg_type chg_type;
 	u8 dcd_retries;
@@ -379,6 +381,7 @@
 	unsigned data;
 	struct msm_bus_scale_pdata *bus_scale_table;
 	unsigned log2_irq_thresh;
+	u32 swfi_latency;
 };
 
 struct msm_usb_host_platform_data {
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index a040d49..c8c2ed1 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -19,6 +19,7 @@
 #define USB_AHBBURST         (MSM_USB_BASE + 0x0090)
 #define USB_AHBMODE          (MSM_USB_BASE + 0x0098)
 #define USB_CAPLENGTH        (MSM_USB_BASE + 0x0100) /* 8 bit */
+#define USB_HS_GPTIMER_BASE  (MSM_USB_BASE + 0x80)
 
 #define USB_USBCMD           (MSM_USB_BASE + 0x0140)
 #define USB_USBSTS           (MSM_USB_BASE + 0x0144)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 78b5b84..7b5aa0b 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -2074,6 +2074,7 @@
 #define V4L2_ENC_CMD_STOP       (1)
 #define V4L2_ENC_CMD_PAUSE      (2)
 #define V4L2_ENC_CMD_RESUME     (3)
+#define V4L2_ENC_QCOM_CMD_FLUSH  (4)
 
 /* Flags for V4L2_ENC_CMD_STOP */
 #define V4L2_ENC_CMD_STOP_AT_GOP_END    (1 << 0)
@@ -2111,6 +2112,9 @@
 #define V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT  (1 << 0)
 #define V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE (1 << 1)
 
+#define V4L2_QCOM_CMD_FLUSH_OUTPUT  (1 << 0)
+#define V4L2_QCOM_CMD_FLUSH_CAPTURE (1 << 1)
+
 /* Play format requirements (returned by the driver): */
 
 /* The decoder has no special format requirements */
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 295be8f..d32bc57 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -21,6 +21,11 @@
 	WCNSS_WLAN_SWITCH_ON,
 };
 
+enum wcnss_hw_type {
+	WCNSS_RIVA_HW = 0,
+	WCNSS_PRONTO_HW,
+};
+
 struct wcnss_wlan_config {
 	int		use_48mhz_xo;
 };
@@ -44,13 +49,20 @@
 int wcnss_wlan_power(struct device *dev,
 				struct wcnss_wlan_config *cfg,
 				enum wcnss_opcode opcode);
-int req_riva_power_on_lock(char *driver_name);
-int free_riva_power_on_lock(char *driver_name);
+int wcnss_req_power_on_lock(char *driver_name);
+int wcnss_free_power_on_lock(char *driver_name);
 unsigned int wcnss_get_serial_number(void);
 void wcnss_flush_delayed_boot_votes(void);
 void wcnss_allow_suspend(void);
 void wcnss_prevent_suspend(void);
+int wcnss_hardware_type(void);
+void *wcnss_prealloc_get(unsigned int size);
+int wcnss_prealloc_put(void *ptr);
+
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
+/* WLAN driver uses these names */
+#define req_riva_power_on_lock(name) wcnss_req_power_on_lock(name)
+#define free_riva_power_on_lock(name) wcnss_free_power_on_lock(name)
 
 #endif /* _WCNSS_WLAN_H_ */
diff --git a/include/media/Kbuild b/include/media/Kbuild
index 2a21336..4b6e6a9 100644
--- a/include/media/Kbuild
+++ b/include/media/Kbuild
@@ -6,3 +6,4 @@
 header-y += msm_gemini.h
 header-y += msm_gestures.h
 header-y += msm_mercury.h
+header-y += msm_jpeg.h
diff --git a/include/media/msm/vidc_init.h b/include/media/msm/vidc_init.h
index c681213..f7d4e58 100644
--- a/include/media/msm/vidc_init.h
+++ b/include/media/msm/vidc_init.h
@@ -13,7 +13,7 @@
 
 #ifndef VIDC_INIT_H
 #define VIDC_INIT_H
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #include <media/msm/vidc_type.h>
 #include <media/msm/vcd_property.h>
 
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index f95230e..ed9af2c 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -28,7 +28,7 @@
 #include <linux/time.h>
 #endif
 
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #define BIT(nr)   (1UL << (nr))
 
@@ -229,6 +229,12 @@
 #define MSM_CAM_IOCTL_OEM \
 	_IOW(MSM_CAM_IOCTL_MAGIC, 65, struct sensor_cfg_data *)
 
+#define MSM_CAM_IOCTL_AXI_INIT \
+	_IOWR(MSM_CAM_IOCTL_MAGIC, 66, uint8_t *)
+
+#define MSM_CAM_IOCTL_AXI_RELEASE \
+	_IO(MSM_CAM_IOCTL_MAGIC, 67)
+
 struct v4l2_event_and_payload {
 	struct v4l2_event evt;
 	uint32_t payload_length;
@@ -1353,6 +1359,7 @@
 	uint8_t csi_lane_mask;
 	uint8_t csi_if;
 	uint8_t csid_core[2];
+	uint8_t csi_phy_sel;
 };
 
 struct msm_camera_csid_lut_params {
@@ -2010,7 +2017,7 @@
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 17, struct msm_mctl_pp_params *)
 
 #define VIDIOC_MSM_AXI_INIT \
-	_IO('V', BASE_VIDIOC_PRIVATE + 18)
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 18, uint8_t *)
 
 #define VIDIOC_MSM_AXI_RELEASE \
 	_IO('V', BASE_VIDIOC_PRIVATE + 19)
@@ -2043,7 +2050,7 @@
 struct msm_camera_vfe_params_t {
 	uint32_t operation_mode;
 	uint32_t capture_count;
-	uint32_t skip_abort;
+	uint8_t  skip_reset;
 	uint8_t  stop_immediately;
 	uint16_t port_info;
 	uint32_t inst_handle;
@@ -2208,7 +2215,8 @@
  *      ------------------------------------
  *      Bits    :  Purpose
  *      ------------------------------------
- *      31 - 24 :  Reserved.
+ *      31      :  is Dev ID valid?
+ *      30 - 24 :  Dev ID.
  *      23      :  is Image mode valid?
  *      22 - 16 :  Image mode.
  *      15      :  is MCTL PP inst idx valid?
@@ -2216,6 +2224,12 @@
  *      7       :  is Video inst idx valid?
  *      6 - 0   :  Video inst idx.
  */
+#define CLR_DEVID_MODE(handle)	(handle &= 0x00FFFFFF)
+#define SET_DEVID_MODE(handle, data)	\
+	(handle |= ((0x1 << 31) | ((data & 0x7F) << 24)))
+#define GET_DEVID_MODE(handle)	\
+	((handle & 0x80000000) ? ((handle & 0x7F000000) >> 24) : 0xFF)
+
 #define CLR_IMG_MODE(handle)	(handle &= 0xFF00FFFF)
 #define SET_IMG_MODE(handle, data)	\
 	(handle |= ((0x1 << 23) | ((data & 0x7F) << 16)))
diff --git a/include/media/msm_jpeg.h b/include/media/msm_jpeg.h
new file mode 100644
index 0000000..11c3247
--- /dev/null
+++ b/include/media/msm_jpeg.h
@@ -0,0 +1,119 @@
+#ifndef __LINUX_MSM_JPEG_H
+#define __LINUX_MSM_JPEG_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define OUTPUT_H2V1  0
+#define OUTPUT_H2V2  1
+#define OUTPUT_BYTE  6
+
+#define MSM_JPEG_IOCTL_MAGIC 'g'
+
+#define MSM_JPEG_IOCTL_GET_HW_VERSION \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 1, struct msm_jpeg_hw_cmd *)
+
+#define MSM_JPEG_IOCTL_RESET \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 2, struct msm_jpeg_ctrl_cmd *)
+
+#define MSM_JPEG_IOCTL_STOP \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 3, struct msm_jpeg_hw_cmds *)
+
+#define MSM_JPEG_IOCTL_START \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 4, struct msm_jpeg_hw_cmds *)
+
+#define MSM_JPEG_IOCTL_INPUT_BUF_ENQUEUE \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 5, struct msm_jpeg_buf *)
+
+#define MSM_JPEG_IOCTL_INPUT_GET \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 6, struct msm_jpeg_buf *)
+
+#define MSM_JPEG_IOCTL_INPUT_GET_UNBLOCK \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 7, int)
+
+#define MSM_JPEG_IOCTL_OUTPUT_BUF_ENQUEUE \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 8, struct msm_jpeg_buf *)
+
+#define MSM_JPEG_IOCTL_OUTPUT_GET \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 9, struct msm_jpeg_buf *)
+
+#define MSM_JPEG_IOCTL_OUTPUT_GET_UNBLOCK \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 10, int)
+
+#define MSM_JPEG_IOCTL_EVT_GET \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 11, struct msm_jpeg_ctrl_cmd *)
+
+#define MSM_JPEG_IOCTL_EVT_GET_UNBLOCK \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 12, int)
+
+#define MSM_JPEG_IOCTL_HW_CMD \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 13, struct msm_jpeg_hw_cmd *)
+
+#define MSM_JPEG_IOCTL_HW_CMDS \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 14, struct msm_jpeg_hw_cmds *)
+
+#define MSM_JPEG_IOCTL_TEST_DUMP_REGION \
+	_IOW(MSM_JPEG_IOCTL_MAGIC, 15, unsigned long)
+
+#define MSM_JPEG_MODE_REALTIME_ENCODE 0
+#define MSM_JPEG_MODE_OFFLINE_ENCODE 1
+#define MSM_JPEG_MODE_REALTIME_ROTATION 2
+#define MSM_JPEG_MODE_OFFLINE_ROTATION 3
+
+struct msm_jpeg_ctrl_cmd {
+	uint32_t type;
+	uint32_t len;
+	void     *value;
+};
+
+#define MSM_JPEG_EVT_RESET 0
+#define MSM_JPEG_EVT_SESSION_DONE	1
+#define MSM_JPEG_EVT_ERR 2
+
+struct msm_jpeg_buf {
+	uint32_t type;
+	int      fd;
+
+	void     *vaddr;
+
+	uint32_t y_off;
+	uint32_t y_len;
+	uint32_t framedone_len;
+
+	uint32_t cbcr_off;
+	uint32_t cbcr_len;
+
+	uint32_t num_of_mcu_rows;
+	uint32_t offset;
+};
+
+#define MSM_JPEG_HW_CMD_TYPE_READ      0
+#define MSM_JPEG_HW_CMD_TYPE_WRITE     1
+#define MSM_JPEG_HW_CMD_TYPE_WRITE_OR  2
+#define MSM_JPEG_HW_CMD_TYPE_UWAIT     3
+#define MSM_JPEG_HW_CMD_TYPE_MWAIT     4
+#define MSM_JPEG_HW_CMD_TYPE_MDELAY    5
+#define MSM_JPEG_HW_CMD_TYPE_UDELAY    6
+struct msm_jpeg_hw_cmd {
+
+	uint32_t type:4;
+
+	/* n microseconds of timeout for WAIT */
+	/* n microseconds of time for DELAY */
+	/* repeat n times for READ/WRITE */
+	/* max is 0xFFF, 4095 */
+	uint32_t n:12;
+	uint32_t offset:16;
+	uint32_t mask;
+	union {
+		uint32_t data;   /* for single READ/WRITE/WAIT, n = 1 */
+		uint32_t *pdata;   /* for multiple READ/WRITE/WAIT, n > 1 */
+	};
+};
+
+struct msm_jpeg_hw_cmds {
+	uint32_t m; /* number of elements in the hw_cmd array */
+	struct msm_jpeg_hw_cmd hw_cmd[1];
+};
+
+#endif /* __LINUX_MSM_JPEG_H */
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index ba705bd..db69518 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -660,7 +660,7 @@
 	IRIS_REGION_OTHER
 };
 
-#define STD_BUF_SIZE        (64)
+#define STD_BUF_SIZE        (128)
 
 enum iris_buf_t {
 	IRIS_BUF_SRCH_LIST,
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 81f7922..1e18c9e 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -119,8 +119,6 @@
 	struct ion_handle		*motionHandle;
 	void					*bufMotion;
 	struct nr_buffer		bufNR;
-	struct nr_param			nr_param;
-	bool					nr_update;
 };
 
 struct vp_work_t {
@@ -173,6 +171,9 @@
 	struct vp_work_t		vp_work;
 	struct vp_work_t		vc_to_vp_work;
 	struct vp_work_t		vp_to_vc_work;
+
+	struct nr_param			nr_param;
+	bool					nr_update;
 };
 
 struct vp_format_data {
diff --git a/include/media/videobuf2-msm-mem.h b/include/media/videobuf2-msm-mem.h
index 5285997..f80ddcd 100644
--- a/include/media/videobuf2-msm-mem.h
+++ b/include/media/videobuf2-msm-mem.h
@@ -17,7 +17,7 @@
 
 #include <media/videobuf2-core.h>
 #include <mach/iommu_domains.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 struct videobuf2_mapping {
 	unsigned int count;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e8c0bf3..544f3bf 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -355,6 +355,7 @@
 	__u8		auth;
 	void		*smp_conn;
 	struct timer_list smp_timer;
+	__u8		conn_valid;
 
 
 	void (*connect_cfm_cb)	(struct hci_conn *conn, u8 status);
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index b1ed9a4..8ccc9f4 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -92,7 +92,7 @@
 int afe_unregister_get_events(u16 port_id);
 int afe_rt_proxy_port_write(u32 buf_addr_p, u32 mem_map_handle, int bytes);
 int afe_rt_proxy_port_read(u32 buf_addr_p, u32 mem_map_handle, int bytes);
-int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
+int afe_port_start(u16 port_id, union afe_port_config *afe_config,
 	u32 rate);
 int afe_port_stop_nowait(int port_id);
 int afe_apply_gain(u16 port_id, u16 gain);
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 2a555b2..2ee5ff7 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -16,7 +16,7 @@
 #include <mach/msm_subsystem_map.h>
 #include <sound/apr_audio-v2.h>
 #include <linux/list.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #define IN                      0x000
 #define OUT                     0x001
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 323a228..4021d48 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -15,7 +15,7 @@
 #include <mach/qdsp6v2/apr.h>
 #include <sound/apr_audio.h>
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 #endif
 
 #define IN                      0x000
diff --git a/kernel/printk.c b/kernel/printk.c
index 90dfdde..4cf4670 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -41,7 +41,6 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/rculist.h>
-#include <linux/coresight-stm.h>
 
 #include <asm/uaccess.h>
 
@@ -960,8 +959,6 @@
 		}
 	}
 
-	stm_log(OST_ENTITY_PRINTK, printk_buf, printed_len);
-
 	/*
 	 * Copy the output into log_buf. If the caller didn't provide
 	 * the appropriate log prefix, we insert them here
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e955364..9885a9e 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2654,6 +2654,10 @@
 	if (target == prev_cpu && idle_cpu(prev_cpu))
 		return prev_cpu;
 
+	if (!(current->flags & PF_WAKE_UP_IDLE) &&
+	    !(p->flags & PF_WAKE_UP_IDLE))
+		return target;
+
 	/*
 	 * Otherwise, iterate the domains and find an elegible idle cpu.
 	 */
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 188df2c..9cf1b8b 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -34,6 +34,7 @@
 #include <linux/rculist.h>
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
+#include <linux/vmalloc.h>
 
 static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set)
 {
@@ -178,9 +179,14 @@
 	int nbytes = sizeof(struct gen_pool_chunk) +
 				(nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
 
-	chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
+	if (nbytes <= PAGE_SIZE)
+		chunk = kmalloc_node(nbytes, __GFP_ZERO, nid);
+	else
+		chunk = vmalloc(nbytes);
 	if (unlikely(chunk == NULL))
 		return -ENOMEM;
+	if (nbytes > PAGE_SIZE)
+		memset(chunk, 0, nbytes);
 
 	chunk->phys_addr = phys;
 	chunk->start_addr = virt;
@@ -235,14 +241,20 @@
 	int bit, end_bit;
 
 	list_for_each_safe(_chunk, _next_chunk, &pool->chunks) {
+		int nbytes;
 		chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
 		list_del(&chunk->next_chunk);
 
 		end_bit = (chunk->end_addr - chunk->start_addr) >> order;
+		nbytes = sizeof(struct gen_pool_chunk) +
+				(end_bit + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
 		bit = find_next_bit(chunk->bits, end_bit, 0);
 		BUG_ON(bit < end_bit);
 
-		kfree(chunk);
+		if (nbytes <= PAGE_SIZE)
+			kfree(chunk);
+		else
+			vfree(chunk);
 	}
 	kfree(pool);
 	return;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 0ade089..0704394 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -486,9 +486,7 @@
 
 	BT_DBG("conn %p mode %d", conn, conn->mode);
 
-	hci_dev_lock(conn->hdev);
 	hci_conn_enter_sniff_mode(conn);
-	hci_dev_unlock(conn->hdev);
 }
 
 static void hci_conn_rssi_update(struct work_struct *work)
@@ -543,6 +541,8 @@
 
 	conn->power_save = 1;
 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+	conn->conn_valid = true;
+	spin_lock_init(&conn->lock);
 	wake_lock_init(&conn->idle_lock, WAKE_LOCK_SUSPEND, "bt_idle");
 
 	switch (type) {
@@ -615,6 +615,10 @@
 
 	BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
 
+	spin_lock_bh(&conn->lock);
+	conn->conn_valid = false; /* conn data is being released */
+	spin_unlock_bh(&conn->lock);
+
 	/* Make sure no timers are running */
 	del_timer(&conn->idle_timer);
 	wake_lock_destroy(&conn->idle_lock);
@@ -852,7 +856,18 @@
 	if (type == ACL_LINK)
 		return acl;
 
+	/* type of connection already existing can be ESCO or SCO
+	 * so check for both types before creating new */
+
 	sco = hci_conn_hash_lookup_ba(hdev, type, dst);
+
+	if (!sco && type == ESCO_LINK) {
+		sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst);
+	} else if (!sco && type == SCO_LINK) {
+		/* this case can be practically not possible */
+		sco = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, dst);
+	}
+
 	if (!sco) {
 		sco = hci_conn_add(hdev, type, pkt_type, dst);
 		if (!sco) {
@@ -1063,9 +1078,13 @@
 
 timer:
 	if (hdev->idle_timeout > 0) {
-		mod_timer(&conn->idle_timer,
-			jiffies + msecs_to_jiffies(hdev->idle_timeout));
-		wake_lock(&conn->idle_lock);
+		spin_lock_bh(&conn->lock);
+		if (conn->conn_valid) {
+			mod_timer(&conn->idle_timer,
+				jiffies + msecs_to_jiffies(hdev->idle_timeout));
+			wake_lock(&conn->idle_lock);
+		}
+		spin_unlock_bh(&conn->lock);
 	}
 }
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0cd3c3f..345b70f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2291,7 +2291,6 @@
 			if (count > hdev->acl_cnt)
 				return;
 
-			hci_dev_lock(hdev);
 			hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
 
 			hci_send_frame(skb);
@@ -2301,7 +2300,6 @@
 			quote -= count;
 
 			conn->sent += count;
-			hci_dev_unlock(hdev);
 		}
 	}
 }
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index d80c0e3..2c4ab78 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -93,40 +93,15 @@
 	return NULL;
 }
 
-static struct device *hidp_get_device(struct hidp_session *session)
-{
-	bdaddr_t *dst = &session->bdaddr;
-
-	struct device *device = NULL;
-	struct hci_dev *hdev;
-
-	hdev = hci_get_route(dst, BDADDR_ANY);
-	if (!hdev)
-		return NULL;
-
-	session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
-	if (session->conn)
-		device = &session->conn->dev;
-
-	hci_dev_put(hdev);
-
-	return device;
-}
-
 static void __hidp_link_session(struct hidp_session *session)
 {
 	__module_get(THIS_MODULE);
 	list_add(&session->list, &hidp_session_list);
-
-	hci_conn_hold_device(session->conn);
 }
 
 static void __hidp_unlink_session(struct hidp_session *session)
 {
-	struct device *dev;
-
-	dev = hidp_get_device(session);
-	if (dev)
+	if (session->conn)
 		hci_conn_put_device(session->conn);
 
 	list_del(&session->list);
@@ -660,6 +635,28 @@
 	return 0;
 }
 
+static struct hci_conn *hidp_get_connection(struct hidp_session *session)
+{
+	bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
+	bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
+	struct hci_conn *conn;
+	struct hci_dev *hdev;
+
+	hdev = hci_get_route(dst, src);
+	if (!hdev)
+		return NULL;
+
+	hci_dev_lock_bh(hdev);
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+	if (conn)
+		hci_conn_hold_device(conn);
+	hci_dev_unlock_bh(hdev);
+
+	hci_dev_put(hdev);
+
+	return conn;
+}
+
 static int hidp_setup_input(struct hidp_session *session,
 				struct hidp_connadd_req *req)
 {
@@ -707,7 +704,7 @@
 		input->relbit[0] |= BIT_MASK(REL_WHEEL);
 	}
 
-	input->dev.parent = hidp_get_device(session);
+	input->dev.parent = &session->conn->dev;
 
 	input->event = hidp_input_event;
 
@@ -808,7 +805,7 @@
 	strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
 	strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
 
-	hid->dev.parent = hidp_get_device(session);
+	hid->dev.parent = &session->conn->dev;
 	hid->ll_driver = &hidp_hid_driver;
 
 	hid->hid_output_raw_report = hidp_output_raw_report;
@@ -866,6 +863,12 @@
 	session->intr_sock = intr_sock;
 	session->state     = BT_CONNECTED;
 
+	session->conn = hidp_get_connection(session);
+	if (!session->conn) {
+		err = -ENOTCONN;
+		goto failed;
+	}
+
 	setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
 
 	skb_queue_head_init(&session->ctrl_transmit);
@@ -874,6 +877,8 @@
 	session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
 	session->idle_to = req->idle_to;
 
+	__hidp_link_session(session);
+
 	if (req->rd_size > 0) {
 		err = hidp_setup_hid(session, req);
 		if (err && err != -ENODEV)
@@ -886,8 +891,6 @@
 			goto purge;
 	}
 
-	__hidp_link_session(session);
-
 	hidp_set_timer(session);
 
 	err = kernel_thread(hidp_session, session, CLONE_KERNEL);
@@ -909,8 +912,6 @@
 unlink:
 	hidp_del_timer(session);
 
-	__hidp_unlink_session(session);
-
 	if (session->input) {
 		input_unregister_device(session->input);
 		session->input = NULL;
@@ -925,6 +926,8 @@
 	session->rd_data = NULL;
 
 purge:
+	__hidp_unlink_session(session);
+
 	skb_queue_purge(&session->ctrl_transmit);
 	skb_queue_purge(&session->intr_transmit);
 
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 947bd85..b11118f 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2523,7 +2523,7 @@
 		runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
 	return 0;
 }
-		
+
 static int snd_pcm_common_ioctl1(struct file *file,
 				 struct snd_pcm_substream *substream,
 				 unsigned int cmd, void __user *arg)
@@ -2592,6 +2592,7 @@
 	case SNDRV_COMPRESS_SET_PARAMS:
 	case SNDRV_COMPRESS_GET_PARAMS:
 	case SNDRV_COMPRESS_TSTAMP:
+	case SNDRV_COMPRESS_DRAIN:
 		return snd_compressed_ioctl(substream, cmd, arg);
 	}
 	snd_printd("unknown ioctl = 0x%x\n", cmd);
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 67572c3..9432a06 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -2560,6 +2560,40 @@
 	return 0;
 }
 
+static void sitar_codec_pm_runtime_put(struct wcd9xxx *sitar)
+{
+	if (sitar->dev != NULL &&
+			sitar->dev->parent != NULL) {
+		pm_runtime_mark_last_busy(sitar->dev->parent);
+		pm_runtime_put(sitar->dev->parent);
+	}
+}
+
+static void sitar_shutdown(struct snd_pcm_substream *substream,
+	struct snd_soc_dai *dai)
+{
+	struct wcd9xxx *sitar_core = dev_get_drvdata(dai->codec->dev->parent);
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
+	u32 active = 0;
+
+	pr_debug("%s(): substream = %s  stream = %d\n" , __func__,
+		substream->name, substream->stream);
+	if (sitar->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		return;
+
+	if (dai->id <= NUM_CODEC_DAIS) {
+		if (sitar->dai[dai->id-1].ch_mask) {
+			active = 1;
+			pr_debug("%s(): Codec DAI: chmask[%d] = 0x%x\n",
+				__func__, dai->id-1,
+				sitar->dai[dai->id-1].ch_mask);
+		}
+	}
+
+	if (sitar_core != NULL && active == 0)
+		sitar_codec_pm_runtime_put(sitar_core);
+}
+
 int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
@@ -2680,11 +2714,23 @@
 			sitar->dai[dai->id - 1].ch_tot = rx_num;
 		}
 	} else if (dai->id == AIF1_CAP) {
-		for (i = 0; i < tx_num; i++) {
-			sitar->dai[dai->id - 1].ch_num[i]  = tx_slot[i];
-			sitar->dai[dai->id - 1].ch_act = 0;
-			sitar->dai[dai->id - 1].ch_tot = tx_num;
+		sitar->dai[dai->id - 1].ch_tot = tx_num;
+		/* If all channels are already active,
+		 * Do not reset ch_act flag
+		 */
+		if ((sitar->dai[dai->id - 1].ch_tot != 0)
+			&& (sitar->dai[dai->id - 1].ch_act ==
+				sitar->dai[dai->id - 1].ch_tot)) {
+			pr_info("%s: ch_act = %d, ch_tot = %d\n", __func__,
+				sitar->dai[dai->id - 1].ch_act,
+				sitar->dai[dai->id - 1].ch_tot);
+
+			return 0;
 		}
+		sitar->dai[dai->id - 1].ch_act = 0;
+
+		for (i = 0; i < tx_num; i++)
+			sitar->dai[dai->id - 1].ch_num[i]  = tx_slot[i];
 	}
 	return 0;
 }
@@ -2855,6 +2901,7 @@
 
 static struct snd_soc_dai_ops sitar_dai_ops = {
 	.startup = sitar_startup,
+	.shutdown = sitar_shutdown,
 	.hw_params = sitar_hw_params,
 	.set_sysclk = sitar_set_dai_sysclk,
 	.set_fmt = sitar_set_dai_fmt,
@@ -2952,29 +2999,22 @@
 			pr_err("%s: slim close tx/rx timeout\n",
 				   __func__);
 			ret = -EINVAL;
+		} else {
+			ret = 0;
 		}
-		ret = 0;
 		break;
 	}
 	return ret;
 }
 
-static void sitar_codec_pm_runtime_put(struct wcd9xxx *sitar)
-{
-	if (sitar->dev != NULL &&
-			sitar->dev->parent != NULL) {
-		pm_runtime_mark_last_busy(sitar->dev->parent);
-		pm_runtime_put(sitar->dev->parent);
-	}
-}
-
 static int sitar_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct wcd9xxx *sitar;
 	struct snd_soc_codec *codec = w->codec;
 	struct sitar_priv *sitar_p = snd_soc_codec_get_drvdata(codec);
-	u32  j = 0, ret = 0;
+	u32  j = 0;
+	int ret = 0;
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	sitar = codec->control_data;
 
@@ -3018,11 +3058,19 @@
 			wcd9xxx_close_slim_sch_rx(sitar,
 					sitar_p->dai[j].ch_num,
 					sitar_p->dai[j].ch_tot);
+			ret = sitar_codec_enable_chmask(sitar_p, event, j);
+			if (ret < 0) {
+				ret = wcd9xxx_disconnect_port(sitar,
+						sitar_p->dai[j].ch_num,
+						sitar_p->dai[j].ch_tot,
+						1);
+				pr_info("%s: Disconnect RX port ret = %d\n",
+						__func__, ret);
+			}
 			sitar_p->dai[j].rate = 0;
 			memset(sitar_p->dai[j].ch_num, 0, (sizeof(u32)*
 					sitar_p->dai[j].ch_tot));
 			sitar_p->dai[j].ch_tot = 0;
-			ret = sitar_codec_enable_chmask(sitar_p, event, j);
 			if (sitar != NULL)
 				sitar_codec_pm_runtime_put(sitar);
 		}
@@ -3037,7 +3085,8 @@
 	struct snd_soc_codec *codec = w->codec;
 	struct sitar_priv *sitar_p = snd_soc_codec_get_drvdata(codec);
 	/* index to the DAI ID, for now hardcoding */
-	u32  j = 0, ret = 0;
+	u32  j = 0;
+	int ret = 0;
 
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	sitar = codec->control_data;
@@ -3082,11 +3131,19 @@
 			wcd9xxx_close_slim_sch_tx(sitar,
 					sitar_p->dai[j].ch_num,
 					sitar_p->dai[j].ch_tot);
+			ret = sitar_codec_enable_chmask(sitar_p, event, j);
+			if (ret < 0) {
+				ret = wcd9xxx_disconnect_port(sitar,
+						sitar_p->dai[j].ch_num,
+						sitar_p->dai[j].ch_tot,
+						0);
+				pr_info("%s: Disconnect TX port, ret = %d\n",
+						__func__, ret);
+			}
 			sitar_p->dai[j].rate = 0;
 			memset(sitar_p->dai[j].ch_num, 0, (sizeof(u32)*
 					sitar_p->dai[j].ch_tot));
 			sitar_p->dai[j].ch_tot = 0;
-			ret = sitar_codec_enable_chmask(sitar_p, event, j);
 			if (sitar != NULL)
 				sitar_codec_pm_runtime_put(sitar);
 		}
@@ -4744,12 +4801,12 @@
 }
 
 
-static unsigned long slimbus_value;
 
 static irqreturn_t sitar_slimbus_irq(int irq, void *data)
 {
 	struct sitar_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
+	unsigned long slimbus_value;
 	int i, j, k, port_id, ch_mask_temp;
 	u8 val;
 
@@ -4784,7 +4841,8 @@
 			}
 		}
 		wcd9xxx_interface_reg_write(codec->control_data,
-			SITAR_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+			SITAR_SLIM_PGD_PORT_INT_CLR0 + i, slimbus_value);
+		val = 0x0;
 	}
 
 	return IRQ_HANDLED;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 09cb605..ac11f1a 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -64,7 +64,8 @@
 #define NUM_ATTEMPTS_TO_REPORT 5
 
 #define TABLA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | \
-			 SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED)
+			 SND_JACK_OC_HPHR | SND_JACK_LINEOUT | \
+			 SND_JACK_UNSUPPORTED)
 
 #define TABLA_I2S_MASTER_MODE_MASK 0x08
 
@@ -103,7 +104,7 @@
 
 #define TABLA_MBHC_STATUS_REL_DETECTION 0x0C
 
-#define TABLA_MBHC_GPIO_REL_DEBOUNCE_TIME_MS 200
+#define TABLA_MBHC_GPIO_REL_DEBOUNCE_TIME_MS 50
 
 #define TABLA_MBHC_FAKE_INS_DELTA_MV 200
 #define TABLA_MBHC_FAKE_INS_DELTA_SCALED_MV 300
@@ -5308,7 +5309,8 @@
 				    enum snd_jack_types jack_type)
 {
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-
+	pr_debug("%s: enter insertion %d hph_status %x\n",
+		 __func__, insertion, tabla->hph_status);
 	if (!insertion) {
 		/* Report removal */
 		tabla->hph_status &= ~jack_type;
@@ -5343,6 +5345,18 @@
 		tabla->current_plug = PLUG_TYPE_NONE;
 		tabla->mbhc_polling_active = false;
 	} else {
+		if (tabla->mbhc_cfg.detect_extn_cable) {
+			/* Report removal of current jack type */
+			if (tabla->hph_status != jack_type &&
+			    tabla->mbhc_cfg.headset_jack) {
+				pr_debug("%s: Reporting removal (%x)\n",
+					 __func__, tabla->hph_status);
+				tabla_snd_soc_jack_report(tabla,
+						tabla->mbhc_cfg.headset_jack,
+						0, TABLA_JACK_MASK);
+				tabla->hph_status = 0;
+			}
+		}
 		/* Report insertion */
 		tabla->hph_status |= jack_type;
 
@@ -5353,7 +5367,8 @@
 		else if (jack_type == SND_JACK_HEADSET) {
 			tabla->mbhc_polling_active = true;
 			tabla->current_plug = PLUG_TYPE_HEADSET;
-		}
+		} else if (jack_type == SND_JACK_LINEOUT)
+			tabla->current_plug = PLUG_TYPE_HIGH_HPH;
 		if (tabla->mbhc_cfg.headset_jack) {
 			pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
 				 jack_type, tabla->hph_status);
@@ -5364,6 +5379,7 @@
 		}
 		tabla_clr_and_turnon_hph_padac(tabla);
 	}
+	pr_debug("%s: leave hph_status %x\n", __func__, tabla->hph_status);
 }
 
 static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec,
@@ -5377,6 +5393,9 @@
 	const struct tabla_mbhc_plug_detect_cfg *plug_det =
 	    TABLA_MBHC_CAL_PLUG_DET_PTR(tabla->mbhc_cfg.calibration);
 
+	pr_debug("%s: enter insertion(%d) trigger(0x%x)\n",
+		 __func__, insertion, trigger);
+
 	if (!tabla->mbhc_cfg.calibration) {
 		pr_err("Error, no tabla calibration\n");
 		return -EINVAL;
@@ -5391,6 +5410,7 @@
 	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
 
 	if (insertion) {
+		pr_debug("%s: setup for insertion\n", __func__);
 		tabla_codec_switch_micbias(codec, 0);
 
 		/* DAPM can manipulate PA/DAC bits concurrently */
@@ -5486,6 +5506,7 @@
 
 	wcd9xxx_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+	pr_debug("%s: leave\n", __func__);
 	return 0;
 }
 
@@ -6297,8 +6318,10 @@
 
 	if (tabla) {
 		codec = tabla->codec;
-		if (tabla->hphlocp_cnt++ < TABLA_OCP_ATTEMPT) {
+		if ((tabla->hphlocp_cnt < TABLA_OCP_ATTEMPT) &&
+		    (!tabla->hphrocp_cnt)) {
 			pr_info("%s: retry\n", __func__);
+			tabla->hphlocp_cnt++;
 			snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
 					    0x00);
 			snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
@@ -6306,7 +6329,6 @@
 		} else {
 			wcd9xxx_disable_irq(codec->control_data,
 					  TABLA_IRQ_HPH_PA_OCPL_FAULT);
-			tabla->hphlocp_cnt = 0;
 			tabla->hph_status |= SND_JACK_OC_HPHL;
 			if (tabla->mbhc_cfg.headset_jack)
 				tabla_snd_soc_jack_report(tabla,
@@ -6330,8 +6352,10 @@
 
 	if (tabla) {
 		codec = tabla->codec;
-		if (tabla->hphrocp_cnt++ < TABLA_OCP_ATTEMPT) {
+		if ((tabla->hphrocp_cnt < TABLA_OCP_ATTEMPT) &&
+		    (!tabla->hphlocp_cnt)) {
 			pr_info("%s: retry\n", __func__);
+			tabla->hphrocp_cnt++;
 			snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
 					    0x00);
 			snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
@@ -6339,7 +6363,6 @@
 		} else {
 			wcd9xxx_disable_irq(codec->control_data,
 					  TABLA_IRQ_HPH_PA_OCPR_FAULT);
-			tabla->hphrocp_cnt = 0;
 			tabla->hph_status |= SND_JACK_OC_HPHR;
 			if (tabla->mbhc_cfg.headset_jack)
 				tabla_snd_soc_jack_report(tabla,
@@ -6388,6 +6411,9 @@
 {
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
+	pr_debug("%s: enter current_plug(%d) new_plug(%d)\n",
+		 __func__, tabla->current_plug, plug_type);
+
 	if (plug_type == PLUG_TYPE_HEADPHONE &&
 	    tabla->current_plug == PLUG_TYPE_NONE) {
 		/* Nothing was reported previously
@@ -6396,11 +6422,14 @@
 		tabla_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
 		tabla_codec_cleanup_hs_polling(codec);
 	} else if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
-		if (tabla->current_plug == PLUG_TYPE_HEADSET)
-			tabla_codec_report_plug(codec, 0, SND_JACK_HEADSET);
-		else if (tabla->current_plug == PLUG_TYPE_HEADPHONE)
-			tabla_codec_report_plug(codec, 0, SND_JACK_HEADPHONE);
-
+		if (!tabla->mbhc_cfg.detect_extn_cable) {
+			if (tabla->current_plug == PLUG_TYPE_HEADSET)
+				tabla_codec_report_plug(codec, 0,
+							SND_JACK_HEADSET);
+			else if (tabla->current_plug == PLUG_TYPE_HEADPHONE)
+				tabla_codec_report_plug(codec, 0,
+							SND_JACK_HEADPHONE);
+		}
 		tabla_codec_report_plug(codec, 1, SND_JACK_UNSUPPORTED);
 		tabla_codec_cleanup_hs_polling(codec);
 	} else if (plug_type == PLUG_TYPE_HEADSET) {
@@ -6411,19 +6440,37 @@
 		msleep(100);
 		tabla_codec_start_hs_polling(codec);
 	} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
-		if (tabla->current_plug == PLUG_TYPE_NONE)
-			tabla_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
-		tabla_codec_cleanup_hs_polling(codec);
-		pr_debug("setup mic trigger for further detection\n");
-		tabla->lpi_enabled = true;
-		tabla_codec_enable_hs_detect(codec, 1,
-					     MBHC_USE_MB_TRIGGER |
-					     MBHC_USE_HPHL_TRIGGER,
-					     false);
+		if (tabla->mbhc_cfg.detect_extn_cable) {
+			/* High impedance device found. Report as LINEOUT*/
+			tabla_codec_report_plug(codec, 1, SND_JACK_LINEOUT);
+			tabla_codec_cleanup_hs_polling(codec);
+			pr_debug("%s: setup mic trigger for further detection\n",
+				 __func__);
+			tabla->lpi_enabled = true;
+			/*
+			 * Do not enable HPHL trigger. If playback is active,
+			 * it might lead to continuous false HPHL triggers
+			 */
+			tabla_codec_enable_hs_detect(codec, 1,
+						     MBHC_USE_MB_TRIGGER,
+						     false);
+		} else {
+			if (tabla->current_plug == PLUG_TYPE_NONE)
+				tabla_codec_report_plug(codec, 1,
+							SND_JACK_HEADPHONE);
+			tabla_codec_cleanup_hs_polling(codec);
+			pr_debug("setup mic trigger for further detection\n");
+			tabla->lpi_enabled = true;
+			tabla_codec_enable_hs_detect(codec, 1,
+						     MBHC_USE_MB_TRIGGER |
+						     MBHC_USE_HPHL_TRIGGER,
+						     false);
+		}
 	} else {
 		WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
 		     tabla->current_plug, plug_type);
 	}
+	pr_debug("%s: leave\n", __func__);
 }
 
 /* should be called under interrupt context that hold suspend */
@@ -6483,6 +6530,8 @@
 	bool ahighv = false, highv;
 	bool gndmicswapped = false;
 
+	pr_debug("%s: enter\n", __func__);
+
 	/* make sure override is on */
 	WARN_ON(!(snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x04));
 
@@ -6592,6 +6641,7 @@
 	}
 
 	pr_debug("%s: Detected plug type %d\n", __func__, plug_type[0]);
+	pr_debug("%s: leave\n", __func__);
 	return plug_type[0];
 }
 
@@ -6601,7 +6651,7 @@
 	struct snd_soc_codec *codec;
 	int retry = 0, pt_gnd_mic_swap_cnt = 0;
 	bool correction = false;
-	enum tabla_mbhc_plug_type plug_type;
+	enum tabla_mbhc_plug_type plug_type = PLUG_TYPE_INVALID;
 	unsigned long timeout;
 
 	tabla = container_of(work, struct tabla_priv, hs_correct_plug_work);
@@ -6641,16 +6691,23 @@
 		plug_type = tabla_codec_get_plug_type(codec, true);
 		TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
 
+		pr_debug("%s: attempt(%d) current_plug(%d) new_plug(%d)\n",
+			 __func__, retry, tabla->current_plug, plug_type);
 		if (plug_type == PLUG_TYPE_INVALID) {
 			pr_debug("Invalid plug in attempt # %d\n", retry);
-			if (retry == NUM_ATTEMPTS_TO_REPORT &&
+			if (!tabla->mbhc_cfg.detect_extn_cable &&
+			    retry == NUM_ATTEMPTS_TO_REPORT &&
 			    tabla->current_plug == PLUG_TYPE_NONE) {
 				tabla_codec_report_plug(codec, 1,
 							SND_JACK_HEADPHONE);
 			}
 		} else if (plug_type == PLUG_TYPE_HEADPHONE) {
 			pr_debug("Good headphone detected, continue polling mic\n");
-			if (tabla->current_plug == PLUG_TYPE_NONE)
+			if (tabla->mbhc_cfg.detect_extn_cable) {
+				if (tabla->current_plug != plug_type)
+					tabla_codec_report_plug(codec, 1,
+							SND_JACK_HEADPHONE);
+			} else if (tabla->current_plug == PLUG_TYPE_NONE)
 				tabla_codec_report_plug(codec, 1,
 							SND_JACK_HEADPHONE);
 		} else {
@@ -6691,7 +6748,21 @@
 		tabla_turn_onoff_override(codec, false);
 
 	tabla->mbhc_cfg.mclk_cb_fn(codec, 0, false);
-	pr_debug("%s: leave\n", __func__);
+
+	if (tabla->mbhc_cfg.detect_extn_cable) {
+		TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
+		if (tabla->current_plug == PLUG_TYPE_HEADPHONE ||
+		    tabla->current_plug == PLUG_TYPE_GND_MIC_SWAP ||
+		    tabla->current_plug == PLUG_TYPE_INVALID ||
+		    plug_type == PLUG_TYPE_INVALID) {
+			/* Enable removal detection */
+			tabla_codec_cleanup_hs_polling(codec);
+			tabla_codec_enable_hs_detect(codec, 0, 0, false);
+		}
+		TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+	}
+	pr_debug("%s: leave current_plug(%d)\n",
+		 __func__, tabla->current_plug);
 	/* unlock sleep */
 	wcd9xxx_unlock_sleep(tabla->codec->control_data);
 }
@@ -6728,6 +6799,7 @@
 			 __func__, plug_type);
 		tabla_find_plug_and_report(codec, plug_type);
 	}
+	pr_debug("%s: leave\n", __func__);
 }
 
 /* called under codec_resource_lock acquisition */
@@ -6737,7 +6809,7 @@
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 	const struct tabla_mbhc_plug_detect_cfg *plug_det =
 	    TABLA_MBHC_CAL_PLUG_DET_PTR(tabla->mbhc_cfg.calibration);
-
+	pr_debug("%s: enter\n", __func__);
 	/* Turn on the override,
 	 * tabla_codec_setup_hs_polling requires override on */
 	tabla_turn_onoff_override(codec, true);
@@ -6756,6 +6828,7 @@
 				 "plug\n", __func__);
 		else
 			tabla_codec_decide_gpio_plug(codec);
+		pr_debug("%s: leave\n", __func__);
 		return;
 	}
 
@@ -6778,7 +6851,6 @@
 		pr_debug("%s: Headphone Detected\n", __func__);
 		tabla_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
 		tabla_codec_cleanup_hs_polling(codec);
-		tabla_codec_enable_hs_detect(codec, 0, 0, false);
 		tabla_schedule_hs_detect_plug(tabla,
 					&tabla->hs_correct_plug_work_nogpio);
 	} else if (plug_type == PLUG_TYPE_HEADSET) {
@@ -6788,13 +6860,23 @@
 		/* avoid false button press detect */
 		msleep(50);
 		tabla_codec_start_hs_polling(codec);
+	} else if (tabla->mbhc_cfg.detect_extn_cable &&
+		   plug_type == PLUG_TYPE_HIGH_HPH) {
+		pr_debug("%s: High impedance plug type detected\n", __func__);
+		tabla_codec_report_plug(codec, 1, SND_JACK_LINEOUT);
+		/* Enable insertion detection on the other end of cable */
+		tabla_codec_cleanup_hs_polling(codec);
+		tabla_codec_enable_hs_detect(codec, 1,
+					     MBHC_USE_MB_TRIGGER, false);
 	}
+	pr_debug("%s: leave\n", __func__);
 }
 
 /* called only from interrupt which is under codec_resource_lock acquisition */
 static void tabla_hs_insert_irq_gpio(struct tabla_priv *priv, bool is_removal)
 {
 	struct snd_soc_codec *codec = priv->codec;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 
 	if (!is_removal) {
 		pr_debug("%s: MIC trigger insertion interrupt\n", __func__);
@@ -6815,6 +6897,19 @@
 			pr_debug("%s: Invalid insertion, "
 				 "stop plug detection\n", __func__);
 		}
+	} else if (tabla->mbhc_cfg.detect_extn_cable) {
+		pr_debug("%s: Removal\n", __func__);
+		if (!tabla_hs_gpio_level_remove(tabla)) {
+			/*
+			 * gpio says, something is still inserted, could be
+			 * extension cable i.e. headset is removed from
+			 * extension cable
+			 */
+			/* cancel detect plug */
+			tabla_cancel_hs_detect_plug(tabla,
+						&tabla->hs_correct_plug_work);
+			tabla_codec_decide_gpio_plug(codec);
+		}
 	} else {
 		pr_err("%s: GPIO used, invalid MBHC Removal\n", __func__);
 	}
@@ -6880,6 +6975,29 @@
 	}
 }
 
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void tabla_hs_insert_irq_extn(struct tabla_priv *priv,
+				     bool is_mb_trigger)
+{
+	struct snd_soc_codec *codec = priv->codec;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	/* Cancel possibly running hs_detect_work */
+	tabla_cancel_hs_detect_plug(tabla,
+			&tabla->hs_correct_plug_work);
+
+	if (is_mb_trigger) {
+		pr_debug("%s: Waiting for Headphone left trigger\n",
+			__func__);
+		tabla_codec_enable_hs_detect(codec, 1, MBHC_USE_HPHL_TRIGGER,
+					     false);
+	} else  {
+		pr_debug("%s: HPHL trigger received, detecting plug type\n",
+			__func__);
+		tabla_codec_detect_plug_type(codec);
+	}
+}
+
 static irqreturn_t tabla_hs_insert_irq(int irq, void *data)
 {
 	bool is_mb_trigger, is_removal;
@@ -6900,7 +7018,10 @@
 	snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
 	snd_soc_update_bits(codec, priv->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
 
-	if (priv->mbhc_cfg.gpio)
+	if (priv->mbhc_cfg.detect_extn_cable &&
+	    priv->current_plug == PLUG_TYPE_HIGH_HPH)
+		tabla_hs_insert_irq_extn(priv, is_mb_trigger);
+	else if (priv->mbhc_cfg.gpio)
 		tabla_hs_insert_irq_gpio(priv, is_removal);
 	else
 		tabla_hs_insert_irq_nogpio(priv, is_removal, is_mb_trigger);
@@ -7004,10 +7125,10 @@
 static void tabla_hs_remove_irq_gpio(struct tabla_priv *priv)
 {
 	struct snd_soc_codec *codec = priv->codec;
-
+	pr_debug("%s: enter\n", __func__);
 	if (tabla_hs_remove_settle(codec))
 		tabla_codec_start_hs_polling(codec);
-	pr_debug("%s: remove settle done\n", __func__);
+	pr_debug("%s: leave\n", __func__);
 }
 
 /* called only from interrupt which is under codec_resource_lock acquisition */
@@ -7020,6 +7141,7 @@
 	    TABLA_MBHC_CAL_GENERAL_PTR(priv->mbhc_cfg.calibration);
 	int min_us = TABLA_FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
 
+	pr_debug("%s: enter\n", __func__);
 	if (priv->current_plug != PLUG_TYPE_HEADSET) {
 		pr_debug("%s(): Headset is not inserted, ignore removal\n",
 			 __func__);
@@ -7047,25 +7169,41 @@
 	} while (min_us > 0);
 
 	if (removed) {
-		/* Cancel possibly running hs_detect_work */
-		tabla_cancel_hs_detect_plug(priv,
+		if (priv->mbhc_cfg.detect_extn_cable) {
+			if (!tabla_hs_gpio_level_remove(priv)) {
+				/*
+				 * extension cable is still plugged in
+				 * report it as LINEOUT device
+				 */
+				tabla_codec_report_plug(codec, 1,
+							SND_JACK_LINEOUT);
+				tabla_codec_cleanup_hs_polling(codec);
+				tabla_codec_enable_hs_detect(codec, 1,
+							MBHC_USE_MB_TRIGGER,
+							false);
+			}
+		} else {
+			/* Cancel possibly running hs_detect_work */
+			tabla_cancel_hs_detect_plug(priv,
 					&priv->hs_correct_plug_work_nogpio);
-		/*
-		 * If this removal is not false, first check the micbias
-		 * switch status and switch it to LDOH if it is already
-		 * switched to VDDIO.
-		 */
-		tabla_codec_switch_micbias(codec, 0);
+			/*
+			 * If this removal is not false, first check the micbias
+			 * switch status and switch it to LDOH if it is already
+			 * switched to VDDIO.
+			 */
+			tabla_codec_switch_micbias(codec, 0);
 
-		tabla_codec_report_plug(codec, 0, SND_JACK_HEADSET);
-		tabla_codec_cleanup_hs_polling(codec);
-		tabla_codec_enable_hs_detect(codec, 1,
-					     MBHC_USE_MB_TRIGGER |
-					     MBHC_USE_HPHL_TRIGGER,
-					     true);
+			tabla_codec_report_plug(codec, 0, SND_JACK_HEADSET);
+			tabla_codec_cleanup_hs_polling(codec);
+			tabla_codec_enable_hs_detect(codec, 1,
+						     MBHC_USE_MB_TRIGGER |
+						     MBHC_USE_HPHL_TRIGGER,
+						     true);
+		}
 	} else {
 		tabla_codec_start_hs_polling(codec);
 	}
+	pr_debug("%s: leave\n", __func__);
 }
 
 static irqreturn_t tabla_hs_remove_irq(int irq, void *data)
@@ -7080,10 +7218,12 @@
 	if (vddio)
 		__tabla_codec_switch_micbias(priv->codec, 0, false, true);
 
-	if (priv->mbhc_cfg.gpio)
-		tabla_hs_remove_irq_gpio(priv);
-	else
+	if ((priv->mbhc_cfg.detect_extn_cable &&
+	     !tabla_hs_gpio_level_remove(priv)) ||
+	    !priv->mbhc_cfg.gpio) {
 		tabla_hs_remove_irq_nogpio(priv);
+	} else
+		tabla_hs_remove_irq_gpio(priv);
 
 	/* if driver turned off vddio switch and headset is not removed,
 	 * turn on the vddio switch back, if headset is removed then vddio
@@ -7171,6 +7311,9 @@
 			tabla_codec_cleanup_hs_polling(codec);
 			tabla_codec_report_plug(codec, 0, SND_JACK_HEADSET);
 			is_removed = true;
+		} else if (tabla->current_plug == PLUG_TYPE_HIGH_HPH) {
+			tabla_codec_report_plug(codec, 0, SND_JACK_LINEOUT);
+			is_removed = true;
 		}
 
 		if (is_removed) {
@@ -7281,6 +7424,8 @@
 	 */
 	tabla->mbhc_cfg.mclk_cb_fn(codec, 0, false);
 	if (!is_headset) {
+		pr_debug("%s: Inserted headphone is not a headset\n",
+			__func__);
 		tabla_turn_onoff_override(codec, false);
 		tabla_codec_cleanup_hs_polling(codec);
 		tabla_codec_enable_hs_detect(codec, 0, 0, false);
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 1cca360..4c9f8b4 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -176,6 +176,7 @@
 	unsigned int gpio;
 	unsigned int gpio_irq;
 	int gpio_level_insert;
+	bool detect_extn_cable;
 	/* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
 	bool (*swap_gnd_mic) (struct snd_soc_codec *);
 };
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 01820eb..136024c 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -390,35 +390,60 @@
 	TAIKO_A_CDC_TX10_VOL_CTL_GAIN,
 };
 
-static int taiko_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+static int taiko_codec_enable_class_h_clk(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
 
-	pr_debug("%s %d\n", __func__, event);
+	pr_debug("%s %s  %d\n", __func__, w->name, event);
 
-	 /* FIX . need to use CLASS-H controller */
 	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x01,
-			0x01);
-		usleep_range(200, 200);
-		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x10, 0x00);
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLSH_B1_CTL, 0x01, 0x01);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
-		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL,
-				0x01, 0x01);
-		usleep_range(20, 20);
-		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x08, 0x08);
-		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x10, 0x10);
-		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x01,
-			0x00);
-		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x08, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_1, 0x80, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLSH_B1_CTL, 0x01, 0x00);
 		break;
 	}
 	return 0;
 }
 
+static int taiko_codec_enable_class_h(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_debug("%s %s  %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_5, 0x02, 0x02);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_4, 0xFF, 0xFF);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_1, 0x04, 0x04);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x04, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x08, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_1, 0x80, 0x80);
+		usleep_range(1000, 1000);
+		break;
+	}
+	return 0;
+}
+
+static int taiko_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	pr_debug("%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(1000, 1000);
+		break;
+	}
+	return 0;
+}
+
+
 static int taiko_get_anc_slot(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
@@ -2766,7 +2791,7 @@
 	struct snd_soc_codec *codec = w->codec;
 	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
 	u8 mbhc_micb_ctl_val;
-	pr_debug("%s: event = %d\n", __func__, event);
+	pr_debug("%s: %s event = %d\n", __func__, w->name, event);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -2780,6 +2805,19 @@
 		}
 		break;
 
+	case SND_SOC_DAPM_POST_PMU:
+
+		usleep_range(10000, 10000);
+
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_5, 0x02, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x20, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x04, 0x04);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x08, 0x00);
+
+		usleep_range(10, 10);
+
+		break;
+
 	case SND_SOC_DAPM_POST_PMD:
 		/* schedule work is required because at the time HPH PA DAPM
 		 * event callback is called by DAPM framework, CODEC dapm mutex
@@ -3012,6 +3050,8 @@
 	{"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"},
 
 	{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
 	{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
@@ -3028,7 +3068,12 @@
 	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
 
 	{"HPHL DAC", NULL, "CP"},
+	{"CP", NULL, "CLASS_H_HPH_L"},
+	{"CLASS_H_HPH_L", NULL, "CLASS_H_CLK"},
+
 	{"HPHR DAC", NULL, "CP"},
+	{"CP", NULL, "CLASS_H_HPH_R"},
+	{"CLASS_H_HPH_R", NULL, "CLASS_H_CLK"},
 
 	{"ANC", NULL, "ANC1 MUX"},
 	{"ANC", NULL, "ANC2 MUX"},
@@ -3082,7 +3127,7 @@
 	{"RX1 CHAIN", NULL, "ANC"},
 	{"RX2 CHAIN", NULL, "ANC"},
 
-	{"CP", NULL, "RX_BIAS"},
+	{"CLASS_H_CLK", NULL, "RX_BIAS"},
 	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
 	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
 	{"LINEOUT3 DAC", NULL, "RX_BIAS"},
@@ -3094,7 +3139,6 @@
 	{"RX3 MIX1", NULL, "COMP2_CLK"},
 	{"RX5 MIX1", NULL, "COMP2_CLK"},
 
-
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
@@ -3295,38 +3339,16 @@
 	{"ADC6", NULL, "AMIC6"},
 
 	/* AUX PGA Connections */
-	{"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
-	{"HPHL_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
-	{"HPHL_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
-	{"HPHL_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
-	{"HPHR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
-	{"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
-	{"HPHR_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
-	{"HPHR_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
-	{"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
-	{"LINEOUT1_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
-	{"LINEOUT1_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
-	{"LINEOUT1_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
-	{"LINEOUT2_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
-	{"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
-	{"LINEOUT2_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
-	{"LINEOUT2_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
-	{"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
-	{"LINEOUT3_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
-	{"LINEOUT3_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
-	{"LINEOUT3_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
-	{"LINEOUT4_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
-	{"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
-	{"LINEOUT4_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
-	{"LINEOUT4_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
 	{"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
-	{"EAR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
-	{"EAR_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
-	{"EAR_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+	{"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
 	{"AUX_PGA_Left", NULL, "AMIC5"},
 	{"AUX_PGA_Right", NULL, "AMIC6"},
 
-
 	{"IIR1", NULL, "IIR1 INP1 MUX"},
 	{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
 	{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
@@ -4153,6 +4175,28 @@
 	return ret;
 }
 
+static int taiko_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_debug("%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_5, 0x02, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x20, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x04, 0x04);
+		snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x08, 0x00);
+
+		usleep_range(5000, 5000);
+		break;
+	}
+	return 0;
+}
+
 /* Todo: Have seperate dapm widgets for I2S and Slimbus.
  * Might Need to have callbacks registered only for slimbus
  */
@@ -4160,7 +4204,8 @@
 	/*RX stuff */
 	SND_SOC_DAPM_OUTPUT("EAR"),
 
-	SND_SOC_DAPM_PGA("EAR PA", TAIKO_A_RX_EAR_EN, 4, 0, NULL, 0),
+	SND_SOC_DAPM_PGA_E("EAR PA", TAIKO_A_RX_EAR_EN, 4, 0, NULL, 0,
+			taiko_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
 
 	SND_SOC_DAPM_MIXER("DAC1", TAIKO_A_RX_EAR_EN, 6, 0, dac1_switch,
 		ARRAY_SIZE(dac1_switch)),
@@ -4193,13 +4238,13 @@
 	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
 	SND_SOC_DAPM_PGA_E("HPHL", TAIKO_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
 		taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMD),
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_MIXER("HPHL DAC", TAIKO_A_RX_HPH_L_DAC_CTL, 7, 0,
 		hphl_switch, ARRAY_SIZE(hphl_switch)),
 
 	SND_SOC_DAPM_PGA_E("HPHR", TAIKO_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
 		taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMD),
+		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAIKO_A_RX_HPH_R_DAC_CTL, 7, 0,
 		taiko_hphr_dac_event,
@@ -4329,10 +4374,23 @@
 	SND_SOC_DAPM_MUX("RX7 MIX2 INP2", SND_SOC_NOPM, 0, 0,
 		&rx7_mix2_inp2_mux),
 
-	SND_SOC_DAPM_SUPPLY("CP", TAIKO_A_NCP_EN, 0, 0,
-		taiko_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
+	SND_SOC_DAPM_SUPPLY("CLASS_H_CLK", TAIKO_A_CDC_CLK_OTHR_CTL, 0, 0,
+		taiko_codec_enable_class_h_clk, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_PRE_PMD),
 
+	SND_SOC_DAPM_SUPPLY("CLASS_H_EAR", TAIKO_A_CDC_CLSH_B1_CTL, 4, 0,
+		taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_R", TAIKO_A_CDC_CLSH_B1_CTL, 3, 0,
+		taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_L", TAIKO_A_CDC_CLSH_B1_CTL, 2, 0,
+		taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("CP", TAIKO_A_NCP_EN, 0, 0,
+		taiko_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
 	SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
 		taiko_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
@@ -6812,6 +6870,85 @@
 	return IRQ_HANDLED;
 }
 
+static const struct taiko_reg_mask_val taiko_1_0_class_h_ear[] = {
+
+	/* CLASS-H EAR  IDLE_THRESHOLD Table */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_IDLE_EAR_THSD, 0x26),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD, 0x2C),
+
+	/* CLASS-H EAR I_PA_FACT Table. */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L,	0xA9),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U, 0x07),
+
+	/* CLASS-H EAR Voltage Headroom , Voltage Min. */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_V_PA_HD_EAR, 0x0D),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_V_PA_MIN_EAR, 0x3A),
+
+	/* CLASS-H EAR K values --chnages from load. */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_ADDR, 0x08),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x1B),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x2D),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x36),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x37),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
+	/** end of Ear PA load 32 */
+};
+
+
+static const struct taiko_reg_mask_val taiko_1_0_class_h_hph[] = {
+
+	/* CLASS-H HPH  IDLE_THRESHOLD Table */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_IDLE_HPH_THSD, 0x13),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0x19),
+
+	/* CLASS-H HPH I_PA_FACT Table */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L,	0x9A),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U, 0x06),
+
+	/* CLASS-H HPH Voltage Headroom , Voltage Min */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_V_PA_HD_HPH, 0x0D),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_V_PA_MIN_HPH, 0x1D),
+
+	/* CLASS-H HPH K values --chnages from load .*/
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_ADDR, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0xAE),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x01),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x1C),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x25),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x27),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
+};
+
+static int taiko_config_ear_class_h(struct snd_soc_codec *codec, u32 ear_load)
+{
+	u32 i;
+
+	if (ear_load  != 32)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(taiko_1_0_class_h_ear); i++)
+		snd_soc_write(codec, taiko_1_0_class_h_ear[i].reg,
+				taiko_1_0_class_h_ear[i].val);
+	return 0;
+}
+
+static int taiko_config_hph_class_h(struct snd_soc_codec *codec, u32 hph_load)
+{
+	u32 i;
+	if (hph_load  != 16)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(taiko_1_0_class_h_hph); i++)
+		snd_soc_write(codec, taiko_1_0_class_h_hph[i].reg,
+				taiko_1_0_class_h_hph[i].val);
+	return 0;
+}
+
 static int taiko_handle_pdata(struct taiko_priv *taiko)
 {
 	struct snd_soc_codec *codec = taiko->codec;
@@ -6943,28 +7080,48 @@
 			break;
 		}
 	}
+
+	taiko_config_ear_class_h(codec, 32);
+	taiko_config_hph_class_h(codec, 16);
+
 done:
 	return rc;
 }
 
 static const struct taiko_reg_mask_val taiko_1_0_reg_defaults[] = {
 
-	/* Taiko 1.1 MICBIAS changes */
-	TAIKO_REG_VAL(TAIKO_A_MICB_1_INT_RBIAS, 0x24),
-	TAIKO_REG_VAL(TAIKO_A_MICB_2_INT_RBIAS, 0x24),
-	TAIKO_REG_VAL(TAIKO_A_MICB_3_INT_RBIAS, 0x24),
+	/* set MCLk to 9.6 */
+	TAIKO_REG_VAL(TAIKO_A_CHIP_CTL, 0x0A),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLK_POWER_CTL, 0x03),
 
-	/* Taiko 1.1 HPH changes */
-	TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x57),
-	TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_LDO, 0x56),
+	/* EAR PA deafults  */
+	TAIKO_REG_VAL(TAIKO_A_RX_EAR_CMBUFF, 0x05),
+	/* HPH PA */
+	TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x7A),
 
-	/* Taiko 1.1 EAR PA changes */
-	TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0xA6),
-	TAIKO_REG_VAL(TAIKO_A_RX_EAR_GAIN, 0x02),
-	TAIKO_REG_VAL(TAIKO_A_RX_EAR_VCM, 0x03),
+	/** BUCK and NCP defaults for EAR and HS */
+	TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_4, 0x50),
+	TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_VCL_1, 0x08),
+	TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_1, 0x5B),
+	TAIKO_REG_VAL(TAIKO_A_NCP_CLK, 0xFC),
+
+	/* CLASS-H defaults for EAR and HS */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_BUCK_NCP_VARS, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_BUCK_NCP_VARS, 0x04),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B2_CTL, 0x01),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B2_CTL, 0x05),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B2_CTL, 0x35),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B3_CTL, 0x30),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B3_CTL, 0x3B),
+
+	/*
+	 * For CLASS-H, Enable ANC delay buffer,
+	 * set HPHL and EAR PA ref gain to 0 DB.
+	 */
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B1_CTL, 0x26),
 
 
-	/* Taiko 1.1 RX Changes */
+	/* RX deafults */
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B5_CTL, 0x78),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B5_CTL, 0x78),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B5_CTL, 0x78),
@@ -6973,17 +7130,16 @@
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B5_CTL, 0x78),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B5_CTL, 0x78),
 
-	/* Taiko 1.1 RX1 and RX2 Changes */
+	/* RX1 and RX2 defaults */
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B6_CTL, 0xA0),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B6_CTL, 0xA0),
 
-	/* Taiko 1.1 RX3 to RX7 Changes */
+	/* RX3 to RX7 defaults */
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B6_CTL, 0x80),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B6_CTL, 0x80),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B6_CTL, 0x80),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B6_CTL, 0x80),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
-
 };
 
 static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
@@ -7002,21 +7158,16 @@
 	{TAIKO_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
 	{TAIKO_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
 
-	{TAIKO_A_QFUSE_CTL, 0xFF, 0x03},
-
 	/* Initialize gain registers to use register gain */
-	{TAIKO_A_RX_HPH_L_GAIN, 0x10, 0x10},
-	{TAIKO_A_RX_HPH_R_GAIN, 0x10, 0x10},
-	{TAIKO_A_RX_LINE_1_GAIN, 0x10, 0x10},
-	{TAIKO_A_RX_LINE_2_GAIN, 0x10, 0x10},
-	{TAIKO_A_RX_LINE_3_GAIN, 0x10, 0x10},
-	{TAIKO_A_RX_LINE_4_GAIN, 0x10, 0x10},
+	{TAIKO_A_RX_HPH_L_GAIN, 0x20, 0x20},
+	{TAIKO_A_RX_HPH_R_GAIN, 0x20, 0x20},
+	{TAIKO_A_RX_LINE_1_GAIN, 0x20, 0x20},
+	{TAIKO_A_RX_LINE_2_GAIN, 0x20, 0x20},
+	{TAIKO_A_RX_LINE_3_GAIN, 0x20, 0x20},
+	{TAIKO_A_RX_LINE_4_GAIN, 0x20, 0x20},
 
-	/* Initialize mic biases to differential mode */
-	{TAIKO_A_MICB_1_INT_RBIAS, 0x24, 0x24},
-	{TAIKO_A_MICB_2_INT_RBIAS, 0x24, 0x24},
-	{TAIKO_A_MICB_3_INT_RBIAS, 0x24, 0x24},
-
+	/* CLASS H config */
+	{TAIKO_A_CDC_CONN_CLSH_CTL, 0x3C, 0x14},
 
 	/* Use 16 bit sample size for TX1 to TX6 */
 	{TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
@@ -7048,21 +7199,22 @@
 	{TAIKO_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
 	{TAIKO_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
 
-	/* config Decimator for DMIC CLK_MODE_1(4.8Mhz@9.6Mhz mclk) */
-	{TAIKO_A_CDC_TX1_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX2_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX3_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX4_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX5_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX6_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX7_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX8_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX9_DMIC_CTL, 0x7, 0x0},
-	{TAIKO_A_CDC_TX10_DMIC_CTL, 0x7, 0x0},
+	/* config Decimator for DMIC CLK_MODE_1(3.2Mhz@9.6Mhz mclk) */
+	{TAIKO_A_CDC_TX1_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX2_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX3_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX4_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX5_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX6_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX7_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX8_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX9_DMIC_CTL, 0x7, 0x1},
+	{TAIKO_A_CDC_TX10_DMIC_CTL, 0x7, 0x1},
 
-	/* config DMIC clk to CLK_MODE_1 (4.8Mhz@9.6Mhz mclk) */
-	{TAIKO_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x0},
-	{TAIKO_A_CDC_CLK_DMIC_B2_CTL, 0xEE, 0x0},
+	/* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
+	{TAIKO_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
+	{TAIKO_A_CDC_CLK_DMIC_B2_CTL, 0x0E, 0x02},
+
 };
 
 static void taiko_codec_init_reg(struct snd_soc_codec *codec)
@@ -7297,10 +7449,11 @@
 	int i;
 	int ch_cnt;
 
-
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	control = codec->control_data;
 
+	dev_info(codec->dev, "%s()\n", __func__);
+
 	taiko = kzalloc(sizeof(struct taiko_priv), GFP_KERNEL);
 	if (!taiko) {
 		dev_err(codec->dev, "Failed to allocate private data\n");
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index ece0a15..1041818 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -105,6 +105,10 @@
 module_param(apq8064_hs_detect_use_gpio, int, 0444);
 MODULE_PARM_DESC(apq8064_hs_detect_use_gpio, "Use GPIO for headset detection");
 
+static bool apq8064_hs_detect_extn_cable;
+module_param(apq8064_hs_detect_extn_cable, bool, 0444);
+MODULE_PARM_DESC(apq8064_hs_detect_extn_cable, "Enable extension cable feature");
+
 static bool apq8064_hs_detect_use_firmware;
 module_param(apq8064_hs_detect_use_firmware, bool, 0444);
 MODULE_PARM_DESC(apq8064_hs_detect_use_firmware, "Use firmware for headset "
@@ -124,6 +128,7 @@
 	.gpio = 0,
 	.gpio_irq = 0,
 	.gpio_level_insert = 1,
+	.detect_extn_cable = false,
 };
 
 static struct mutex cdc_mclk_mutex;
@@ -1152,8 +1157,9 @@
 	snd_soc_dapm_sync(dapm);
 
 	err = snd_soc_jack_new(codec, "Headset Jack",
-			       (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
-				SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED),
+			       (SND_JACK_HEADSET |  SND_JACK_LINEOUT |
+				SND_JACK_OC_HPHL |  SND_JACK_OC_HPHR |
+				SND_JACK_UNSUPPORTED),
 			       &hs_jack);
 	if (err) {
 		pr_err("failed to create new jack\n");
@@ -1206,6 +1212,8 @@
 			return err;
 		}
 		gpio_direction_input(JACK_DETECT_GPIO);
+		if (apq8064_hs_detect_extn_cable)
+			mbhc_cfg.detect_extn_cable = true;
 	} else
 		pr_debug("%s: Not using MBHC mechanical switch\n", __func__);
 
@@ -2028,7 +2036,8 @@
 	int ret;
 	u32	version = socinfo_get_platform_version();
 	if (!cpu_is_apq8064() || (socinfo_get_id() == 130) ||
-		SOCINFO_VERSION_MINOR(version) == 1) {
+		(machine_is_apq8064_mtp() &&
+		(SOCINFO_VERSION_MINOR(version) == 1))) {
 		pr_info("%s: Not APQ8064 in SLIMBUS mode\n", __func__);
 		return -ENODEV;
 	}
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index b80a0a9..1000a8b 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/mfd/wcd9xxx/core.h>
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
@@ -42,10 +43,8 @@
 #define SAMPLE_RATE_8KHZ 8000
 #define SAMPLE_RATE_16KHZ 16000
 
-#define BOTTOM_SPK_AMP_POS	0x1
-#define BOTTOM_SPK_AMP_NEG	0x2
-#define TOP_SPK_AMP_POS		0x4
-#define TOP_SPK_AMP_NEG		0x8
+#define TOP_AND_BOTTOM_SPK_AMP_POS	0x1
+#define TOP_AND_BOTTOM_SPK_AMP_NEG	0x2
 
 #define GPIO_AUX_PCM_DOUT 23
 #define GPIO_AUX_PCM_DIN 22
@@ -62,6 +61,10 @@
 #define TABLA_MBHC_DEF_BUTTONS 8
 #define TABLA_MBHC_DEF_RLOADS 5
 
+#define PM8018_IRQ_BASE			(NR_MSM_IRQS + NR_GPIO_IRQS)
+#define JACK_DETECT_GPIO 3
+#define JACK_DETECT_INT PM8018_GPIO_IRQ(PM8018_IRQ_BASE, JACK_DETECT_GPIO)
+
 /*
  * Added for I2S
  */
@@ -245,16 +248,13 @@
 /*
  * Added for I2S
  */
-
-static u32 top_spk_pamp_gpio  = PM8018_GPIO_PM_TO_SYS(3);
-static u32 bottom_spk_pamp_gpio = PM8018_GPIO_PM_TO_SYS(5);
+static u32 top_and_bottom_spk_pamp_gpio = PM8018_GPIO_PM_TO_SYS(5);
 
 void *sif_virt_addr;
 void *secpcm_portslc_virt_addr;
 
 static int mdm9615_spk_control;
-static int mdm9615_ext_bottom_spk_pamp;
-static int mdm9615_ext_top_spk_pamp;
+static int mdm9615_ext_top_and_bottom_spk_pamp;
 static int mdm9615_slim_0_rx_ch = 1;
 static int mdm9615_slim_0_tx_ch = 1;
 
@@ -271,6 +271,17 @@
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
 
+static struct platform_device *mdm9615_snd_device_slim;
+static struct platform_device *mdm9615_snd_device_i2s;
+
+static bool hs_detect_use_gpio;
+module_param(hs_detect_use_gpio, bool, 0444);
+MODULE_PARM_DESC(hs_detect_use_gpio, "Use GPIO for headset detection");
+
+static bool hs_detect_use_firmware;
+module_param(hs_detect_use_firmware, bool, 0444);
+MODULE_PARM_DESC(hs_detect_use_firmware, "Use firmware for headset detection");
+
 static int mdm9615_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
 					bool dapm);
 static struct tabla_mbhc_config mbhc_cfg = {
@@ -300,39 +311,26 @@
 		.function       = PM_GPIO_FUNC_NORMAL,
 	};
 
-	if (spk_amp_gpio == bottom_spk_pamp_gpio) {
+	if (spk_amp_gpio == top_and_bottom_spk_pamp_gpio) {
 
-		ret = gpio_request(bottom_spk_pamp_gpio, "BOTTOM_SPK_AMP");
+		ret = gpio_request(top_and_bottom_spk_pamp_gpio,
+				   "TOP_AND_BOTTOM_SPK_AMP");
 		if (ret) {
-			pr_err("%s: Error requesting BOTTOM SPK AMP GPIO %u\n",
-				__func__, bottom_spk_pamp_gpio);
+			pr_err("%s: Error requesting TOP AND BOTTOM SPK AMP GPIO %u\n",
+				__func__, top_and_bottom_spk_pamp_gpio);
 			return;
 		}
-		ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
+		ret = pm8xxx_gpio_config(top_and_bottom_spk_pamp_gpio, &param);
 		if (ret)
-			pr_err("%s: Failed to configure Bottom Spk Ampl"
-				" gpio %u\n", __func__, bottom_spk_pamp_gpio);
+			pr_err("%s: Failed to configure Top & Bottom Spk Ampl\n"
+				"gpio %u\n", __func__,
+				top_and_bottom_spk_pamp_gpio);
 		else {
-			pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
-			gpio_direction_output(bottom_spk_pamp_gpio, 1);
+			pr_debug("%s: enable Top & Bottom spkr amp gpio\n",
+				 __func__);
+			gpio_direction_output(top_and_bottom_spk_pamp_gpio, 1);
 		}
 
-	} else if (spk_amp_gpio == top_spk_pamp_gpio) {
-
-		ret = gpio_request(top_spk_pamp_gpio, "TOP_SPK_AMP");
-		if (ret) {
-			pr_err("%s: Error requesting GPIO %d\n", __func__,
-				top_spk_pamp_gpio);
-			return;
-		}
-		ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
-		if (ret)
-			pr_err("%s: Failed to configure Top Spk Ampl"
-				" gpio %u\n", __func__, top_spk_pamp_gpio);
-		else {
-			pr_debug("%s: enable Top spkr amp gpio\n", __func__);
-			gpio_direction_output(top_spk_pamp_gpio, 1);
-		}
 	} else {
 		pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
 			" gpio = %u\n", __func__, spk_amp_gpio);
@@ -342,49 +340,30 @@
 
 static void mdm9615_ext_spk_power_amp_on(u32 spk)
 {
-	if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
-
-		if ((mdm9615_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
-			(mdm9615_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
-
-			pr_debug("%s() External Bottom Speaker Ampl already "
+	if (spk & (TOP_AND_BOTTOM_SPK_AMP_POS | TOP_AND_BOTTOM_SPK_AMP_NEG)) {
+		if ((mdm9615_ext_top_and_bottom_spk_pamp &
+		     TOP_AND_BOTTOM_SPK_AMP_POS) &&
+		    (mdm9615_ext_top_and_bottom_spk_pamp &
+		     TOP_AND_BOTTOM_SPK_AMP_NEG)) {
+			pr_debug("%s() External Speaker Ampl already "
 				"turned on. spk = 0x%08x\n", __func__, spk);
 			return;
 		}
 
-		mdm9615_ext_bottom_spk_pamp |= spk;
+		mdm9615_ext_top_and_bottom_spk_pamp |= spk;
 
-		if ((mdm9615_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
-			(mdm9615_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
-
-			mdm9615_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
-			pr_debug("%s: slepping 4 ms after turning on external "
-				" Bottom Speaker Ampl\n", __func__);
+		if ((mdm9615_ext_top_and_bottom_spk_pamp &
+		     TOP_AND_BOTTOM_SPK_AMP_POS) &&
+		    (mdm9615_ext_top_and_bottom_spk_pamp &
+		     TOP_AND_BOTTOM_SPK_AMP_NEG)) {
+			mdm9615_enable_ext_spk_amp_gpio(
+					top_and_bottom_spk_pamp_gpio);
+			pr_debug("%s: slepping 4 ms after turning on external\n"
+				"Speaker Ampl\n", __func__);
 			usleep_range(4000, 4000);
 		}
 
-	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
-
-		if ((mdm9615_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
-			(mdm9615_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
-
-			pr_debug("%s() External Top Speaker Ampl already"
-				"turned on. spk = 0x%08x\n", __func__, spk);
-			return;
-		}
-
-		mdm9615_ext_top_spk_pamp |= spk;
-
-		if ((mdm9615_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
-			(mdm9615_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
-
-			mdm9615_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
-			pr_debug("%s: sleeping 4 ms after turning on "
-				" external Top Speaker Ampl\n", __func__);
-			usleep_range(4000, 4000);
-		}
-	} else  {
-
+	} else {
 		pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
 			__func__, spk);
 		return;
@@ -393,33 +372,20 @@
 
 static void mdm9615_ext_spk_power_amp_off(u32 spk)
 {
-	if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
+	if (spk & (TOP_AND_BOTTOM_SPK_AMP_POS | TOP_AND_BOTTOM_SPK_AMP_NEG)) {
 
-		if (!mdm9615_ext_bottom_spk_pamp)
+		if (!mdm9615_ext_top_and_bottom_spk_pamp)
 			return;
 
-		gpio_direction_output(bottom_spk_pamp_gpio, 0);
-		gpio_free(bottom_spk_pamp_gpio);
-		mdm9615_ext_bottom_spk_pamp = 0;
+		gpio_direction_output(top_and_bottom_spk_pamp_gpio, 0);
+		gpio_free(top_and_bottom_spk_pamp_gpio);
+		mdm9615_ext_top_and_bottom_spk_pamp = 0;
 
 		pr_debug("%s: sleeping 4 ms after turning off external Bottom"
 			" Speaker Ampl\n", __func__);
 
 		usleep_range(4000, 4000);
 
-	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
-
-		if (!mdm9615_ext_top_spk_pamp)
-			return;
-
-		gpio_direction_output(top_spk_pamp_gpio, 0);
-		gpio_free(top_spk_pamp_gpio);
-		mdm9615_ext_top_spk_pamp = 0;
-
-		pr_debug("%s: sleeping 4 ms after turning off external Top"
-			" Spkaker Ampl\n", __func__);
-
-		usleep_range(4000, 4000);
 	} else  {
 
 		pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
@@ -434,15 +400,11 @@
 
 	pr_debug("%s: mdm9615_spk_control = %d", __func__, mdm9615_spk_control);
 	if (mdm9615_spk_control == MDM9615_SPK_ON) {
-		snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
-		snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
-		snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
-		snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk Pos");
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk Neg");
 	} else {
-		snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Pos");
-		snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Neg");
-		snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Pos");
-		snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Neg");
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Pos");
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Neg");
 	}
 
 	snd_soc_dapm_sync(dapm);
@@ -474,14 +436,12 @@
 	pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
 
 	if (SND_SOC_DAPM_EVENT_ON(event)) {
-		if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
-			mdm9615_ext_spk_power_amp_on(BOTTOM_SPK_AMP_POS);
-		else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
-			mdm9615_ext_spk_power_amp_on(BOTTOM_SPK_AMP_NEG);
-		else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
-			mdm9615_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
-		else if  (!strncmp(w->name, "Ext Spk Top Neg", 15))
-			mdm9615_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
+		if (!strncmp(w->name, "Ext Spk Pos", 11))
+			mdm9615_ext_spk_power_amp_on(
+					TOP_AND_BOTTOM_SPK_AMP_POS);
+		else if (!strncmp(w->name, "Ext Spk Neg", 11))
+			mdm9615_ext_spk_power_amp_on(
+					TOP_AND_BOTTOM_SPK_AMP_NEG);
 		else {
 			pr_err("%s() Invalid Speaker Widget = %s\n",
 					__func__, w->name);
@@ -489,14 +449,12 @@
 		}
 
 	} else {
-		if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
-			mdm9615_ext_spk_power_amp_off(BOTTOM_SPK_AMP_POS);
-		else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
-			mdm9615_ext_spk_power_amp_off(BOTTOM_SPK_AMP_NEG);
-		else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
-			mdm9615_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
-		else if  (!strncmp(w->name, "Ext Spk Top Neg", 15))
-			mdm9615_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
+		if (!strncmp(w->name, "Ext Spk Pos", 11))
+			mdm9615_ext_spk_power_amp_off(
+					TOP_AND_BOTTOM_SPK_AMP_POS);
+		else if (!strncmp(w->name, "Ext Spk Neg", 11))
+			mdm9615_ext_spk_power_amp_off(
+					TOP_AND_BOTTOM_SPK_AMP_NEG);
 		else {
 			pr_err("%s() Invalid Speaker Widget = %s\n",
 					__func__, w->name);
@@ -557,11 +515,8 @@
 	SND_SOC_DAPM_SUPPLY("MCLK",  SND_SOC_NOPM, 0, 0,
 	mdm9615_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_SPK("Ext Spk Bottom Pos", mdm9615_spkramp_event),
-	SND_SOC_DAPM_SPK("Ext Spk Bottom Neg", mdm9615_spkramp_event),
-
-	SND_SOC_DAPM_SPK("Ext Spk Top Pos", mdm9615_spkramp_event),
-	SND_SOC_DAPM_SPK("Ext Spk Top Neg", mdm9615_spkramp_event),
+	SND_SOC_DAPM_SPK("Ext Spk Pos", mdm9615_spkramp_event),
+	SND_SOC_DAPM_SPK("Ext Spk Neg", mdm9615_spkramp_event),
 
 	SND_SOC_DAPM_MIC("Handset Mic", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
@@ -584,11 +539,11 @@
 	{"LDO_H", NULL, "MCLK"},
 
 	/* Speaker path */
-	{"Ext Spk Bottom Pos", NULL, "LINEOUT1"},
-	{"Ext Spk Bottom Neg", NULL, "LINEOUT3"},
+	{"Ext Spk Pos", NULL, "LINEOUT1"},
+	{"Ext Spk Neg", NULL, "LINEOUT3"},
 
-	{"Ext Spk Top Pos", NULL, "LINEOUT2"},
-	{"Ext Spk Top Neg", NULL, "LINEOUT4"},
+	{"Ext Spk Pos", NULL, "LINEOUT2"},
+	{"Ext Spk Neg", NULL, "LINEOUT4"},
 
 	/* Microphone path */
 	{"AMIC1", NULL, "MIC BIAS1 External"},
@@ -1006,10 +961,8 @@
 
 	snd_soc_dapm_add_routes(dapm, common_audio_map,
 		ARRAY_SIZE(common_audio_map));
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Pos");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Neg");
 
 	snd_soc_dapm_sync(dapm);
 
@@ -1498,10 +1451,28 @@
 		 pintf->intf_status[i2s_intf][MSM_DIR_TX]);
 }
 
+static void  mdm9615_install_codec_i2s_gpio(void)
+{
+	msm_gpiomux_install(msm9615_audio_prim_i2s_codec_configs,
+			ARRAY_SIZE(msm9615_audio_prim_i2s_codec_configs));
+}
+static int msm9615_i2s_prepare(struct snd_pcm_substream *substream)
+{
+	u8 ret = 0;
+
+	if (wcd9xxx_get_intf_type() < 0)
+		ret = -ENODEV;
+	else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+		mdm9615_install_codec_i2s_gpio();
+
+	return ret;
+}
+
 static struct snd_soc_ops msm9615_i2s_be_ops = {
 	.startup = msm9615_i2s_startup,
 	.shutdown = msm9615_i2s_shutdown,
 	.hw_params = msm9615_i2s_hw_params,
+	.prepare = msm9615_i2s_prepare,
 };
 
 static int mdm9615_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -1510,6 +1481,13 @@
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct pm_gpio jack_gpio_cfg = {
+		.direction = PM_GPIO_DIR_IN,
+		.pull = PM_GPIO_PULL_NO,
+		.function = PM_GPIO_FUNC_NORMAL,
+		.vin_sel = 2,
+		.inv_int_pol = 0,
+	};
 
 	pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
 
@@ -1521,10 +1499,8 @@
 	snd_soc_dapm_add_routes(dapm, common_audio_map,
 		ARRAY_SIZE(common_audio_map));
 
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Pos");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Neg");
 
 	snd_soc_dapm_sync(dapm);
 
@@ -1545,6 +1521,22 @@
 	}
 	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
 
+	if (hs_detect_use_gpio) {
+		mbhc_cfg.gpio = PM8018_GPIO_PM_TO_SYS(JACK_DETECT_GPIO);
+		mbhc_cfg.gpio_irq = JACK_DETECT_INT;
+	}
+
+	if (mbhc_cfg.gpio) {
+		err = pm8xxx_gpio_config(mbhc_cfg.gpio, &jack_gpio_cfg);
+		if (err) {
+			pr_err("%s: pm8xxx_gpio_config JACK_DETECT failed %d\n",
+			       __func__, err);
+			return err;
+		}
+	}
+
+	mbhc_cfg.read_fw_bin = hs_detect_use_firmware;
+
 	err = tabla_hs_detect(codec, &mbhc_cfg);
 
 	return err;
@@ -2097,14 +2089,19 @@
 					 ARRAY_SIZE(mdm9615_dai_slimbus_tabla)];
 
 
-static struct snd_soc_card snd_soc_card_mdm9615 = {
-		.name		= "mdm9615-tabla-snd-card",
+static struct snd_soc_card snd_soc_card_mdm9615[] = {
+	[0] = {
+		.name = "mdm9615-tabla-snd-card",
 		.controls = tabla_mdm9615_controls,
 		.num_controls = ARRAY_SIZE(tabla_mdm9615_controls),
+	},
+	[1] = {
+		.name = "mdm9615-tabla-snd-card-i2s",
+		.controls = tabla_mdm9615_controls,
+		.num_controls = ARRAY_SIZE(tabla_mdm9615_controls),
+	},
 };
 
-static struct platform_device *mdm9615_snd_device;
-
 static int mdm9615_configure_headset_mic_gpios(void)
 {
 	int ret;
@@ -2156,11 +2153,6 @@
 	}
 }
 
-void  __init install_codec_i2s_gpio(void)
-{
-	msm_gpiomux_install(msm9615_audio_prim_i2s_codec_configs,
-			ARRAY_SIZE(msm9615_audio_prim_i2s_codec_configs));
-}
 static int __init mdm9615_audio_init(void)
 {
 	int ret;
@@ -2175,53 +2167,69 @@
 		pr_err("Calibration data allocation failed\n");
 		return -ENOMEM;
 	}
+	mdm9615_snd_device_slim = platform_device_alloc("soc-audio", 0);
+	if (!mdm9615_snd_device_slim) {
+		pr_err("Platform device allocation failed\n");
+		kfree(mbhc_cfg.calibration);
+		return -ENOMEM;
+	}
 
-	mdm9615_snd_device = platform_device_alloc("soc-audio", 0);
-	if (!mdm9615_snd_device) {
+	/* Install SLIM specific links */
+	memcpy(mdm9615_slimbus_dai, mdm9615_dai_common,
+			sizeof(mdm9615_dai_common));
+	memcpy(mdm9615_slimbus_dai + ARRAY_SIZE(mdm9615_dai_common),
+		       mdm9615_dai_slimbus_tabla,
+		       sizeof(mdm9615_dai_slimbus_tabla));
+	snd_soc_card_mdm9615[0].dai_link = mdm9615_slimbus_dai;
+	snd_soc_card_mdm9615[0].num_links =
+				ARRAY_SIZE(mdm9615_slimbus_dai);
+
+	mdm9615_snd_device_i2s = platform_device_alloc("soc-audio", 1);
+	if (!mdm9615_snd_device_i2s) {
 		pr_err("Platform device allocation failed\n");
 		kfree(mbhc_cfg.calibration);
 		return -ENOMEM;
 	}
 	pr_err("%s: Interface Type = %d\n", __func__,
 			wcd9xxx_get_intf_type());
-	if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
-		memcpy(mdm9615_slimbus_dai, mdm9615_dai_common,
-			sizeof(mdm9615_dai_common));
-		memcpy(mdm9615_slimbus_dai + ARRAY_SIZE(mdm9615_dai_common),
-		       mdm9615_dai_slimbus_tabla,
-		       sizeof(mdm9615_dai_slimbus_tabla));
-		snd_soc_card_mdm9615.dai_link = mdm9615_slimbus_dai;
-		snd_soc_card_mdm9615.num_links =
-				ARRAY_SIZE(mdm9615_slimbus_dai);
-	} else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C) {
-		install_codec_i2s_gpio();
-		memcpy(mdm9615_i2s_dai, mdm9615_dai_common,
-		       sizeof(mdm9615_dai_common));
-		memcpy(mdm9615_i2s_dai + ARRAY_SIZE(mdm9615_dai_common),
-		       mdm9615_dai_i2s_tabla,
-		       sizeof(mdm9615_dai_i2s_tabla));
-		snd_soc_card_mdm9615.dai_link = mdm9615_i2s_dai;
-		snd_soc_card_mdm9615.num_links =
-				ARRAY_SIZE(mdm9615_i2s_dai);
-	} else{
-		snd_soc_card_mdm9615.dai_link = mdm9615_dai_common;
-		snd_soc_card_mdm9615.num_links =
-				ARRAY_SIZE(mdm9615_dai_common);
-	}
 
-	platform_set_drvdata(mdm9615_snd_device, &snd_soc_card_mdm9615);
-	ret = platform_device_add(mdm9615_snd_device);
+	/* Install I2S specific links */
+	memcpy(mdm9615_i2s_dai, mdm9615_dai_common,
+	       sizeof(mdm9615_dai_common));
+	memcpy(mdm9615_i2s_dai + ARRAY_SIZE(mdm9615_dai_common),
+	       mdm9615_dai_i2s_tabla,
+	       sizeof(mdm9615_dai_i2s_tabla));
+	snd_soc_card_mdm9615[1].dai_link = mdm9615_i2s_dai;
+	snd_soc_card_mdm9615[1].num_links =
+				ARRAY_SIZE(mdm9615_i2s_dai);
+	platform_set_drvdata(mdm9615_snd_device_slim, &snd_soc_card_mdm9615[0]);
+	ret = platform_device_add(mdm9615_snd_device_slim);
 	if (ret) {
-		platform_device_put(mdm9615_snd_device);
+		pr_err("%s Slim platform_device_add fail\n", __func__);
+		platform_device_put(mdm9615_snd_device_slim);
 		kfree(mbhc_cfg.calibration);
 		return ret;
 	}
+	platform_set_drvdata(mdm9615_snd_device_i2s, &snd_soc_card_mdm9615[1]);
+	ret = platform_device_add(mdm9615_snd_device_i2s);
+	if (ret) {
+		pr_err("%s I2S platform_device_add fail\n", __func__);
+		platform_device_put(mdm9615_snd_device_i2s);
+		kfree(mbhc_cfg.calibration);
+		return ret;
+	}
+
 	if (mdm9615_configure_headset_mic_gpios()) {
 		pr_err("%s Fail to configure headset mic gpios\n", __func__);
 		mdm9615_headset_gpios_configured = 0;
 	} else
 		mdm9615_headset_gpios_configured = 1;
 
+	/*
+	 * Irrespective of audio interface type get virtual address
+	 * of LPAIF registers as it may not  be guaranted that I2S
+	 * will probed successfully in Init.
+	 */
 	atomic_set(&msm9615_auxpcm_ref, 0);
 	atomic_set(&msm9615_sec_auxpcm_ref, 0);
 	msm9x15_i2s_ctl.sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
@@ -2243,7 +2251,8 @@
 		return ;
 	}
 	mdm9615_free_headset_mic_gpios();
-	platform_device_unregister(mdm9615_snd_device);
+	platform_device_unregister(mdm9615_snd_device_slim);
+	platform_device_unregister(mdm9615_snd_device_i2s);
 	kfree(mbhc_cfg.calibration);
 	iounmap(msm9x15_i2s_ctl.sif_virt_addr);
 	iounmap(msm9x15_i2s_ctl.spare_virt_addr);
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index be0395b..499e4b6 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -54,7 +54,7 @@
 #define GPIO_SEC_I2S_RX_WS   48
 #define GPIO_SEC_I2S_RX_DOUT 49
 #define GPIO_SEC_I2S_RX_MCLK 50
-#define I2S_MCLK_RATE 1536000
+#define I2S_MCLK_RATE 12288000
 
 #define GPIO_MI2S_WS     27
 #define GPIO_MI2S_SCLK   28
@@ -810,6 +810,19 @@
 	return 0;
 }
 
+static int msm_be_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s()\n", __func__);
+	channels->min =  channels->max = 2;
+
+	return 0;
+}
+
 static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_hw_params *params)
 {
@@ -1340,7 +1353,7 @@
 		.codec_dai_name = "spdif_rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_SEC_I2S_RX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_be_i2s_hw_params_fixup,
 		.ops = &mpq8064_sec_i2s_rx_be_ops,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
 	},
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index bb138d3..a911d9d 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -42,6 +42,7 @@
 #define COMPRE_CAPTURE_PERIOD_SIZE	((COMPRE_CAPTURE_MAX_FRAME_SIZE + \
 					  COMPRE_CAPTURE_HEADER_SIZE) * \
 					  MAX_NUM_FRAMES_PER_BUFFER)
+#define COMPRE_OUTPUT_METADATA_SIZE	(sizeof(struct output_meta_data_st))
 
 struct snd_msm {
 	struct msm_audio *prtd;
@@ -113,8 +114,11 @@
 	struct audio_aio_write_param param;
 	struct audio_aio_read_param read_param;
 	struct audio_buffer *buf = NULL;
+	struct output_meta_data_st output_meta_data;
 	uint32_t *ptrmem = (uint32_t *)payload;
 	int i = 0;
+	int time_stamp_flag = 0;
+	int buffer_length = 0;
 
 	pr_debug("%s opcode =%08x\n", __func__, opcode);
 	switch (opcode) {
@@ -143,14 +147,35 @@
 				((unsigned int)buf[0].phys
 				+ (prtd->out_head * prtd->pcm_count)));
 
+		if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+			time_stamp_flag = SET_TIMESTAMP;
+		else
+			time_stamp_flag = NO_TIMESTAMP;
+		memcpy(&output_meta_data, (char *)(buf->data +
+			prtd->out_head * prtd->pcm_count),
+			COMPRE_OUTPUT_METADATA_SIZE);
+
+		buffer_length = output_meta_data.frame_size;
+		pr_debug("meta_data_length: %d, frame_length: %d\n",
+			 output_meta_data.meta_data_length,
+			 output_meta_data.frame_size);
+		pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
+			 output_meta_data.timestamp_msw,
+			 output_meta_data.timestamp_lsw);
+		if (buffer_length == 0) {
+			pr_debug("Recieved a zero length buffer-break out");
+			break;
+		}
 		param.paddr = (unsigned long)buf[0].phys
-				+ (prtd->out_head * prtd->pcm_count);
-		param.len = prtd->pcm_count;
-		param.msw_ts = 0;
-		param.lsw_ts = 0;
-		param.flags = NO_TIMESTAMP;
+				+ (prtd->out_head * prtd->pcm_count)
+				+ output_meta_data.meta_data_length;
+		param.len = buffer_length;
+		param.msw_ts = output_meta_data.timestamp_msw;
+		param.lsw_ts = output_meta_data.timestamp_lsw;
+		param.flags = time_stamp_flag;
 		param.uid =  (unsigned long)buf[0].phys
-				+ (prtd->out_head * prtd->pcm_count);
+				+ (prtd->out_head * prtd->pcm_count
+				+ output_meta_data.meta_data_length);
 		for (i = 0; i < sizeof(struct audio_aio_write_param)/4;
 					i++, ++ptrmem)
 			pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
@@ -165,8 +190,12 @@
 	}
 	case ASM_DATA_CMDRSP_EOS:
 		pr_debug("ASM_DATA_CMDRSP_EOS\n");
-		prtd->cmd_ack = 1;
-		wake_up(&the_locks.eos_wait);
+		if (atomic_read(&prtd->eos)) {
+			pr_debug("ASM_DATA_CMDRSP_EOS wake up\n");
+			prtd->cmd_ack = 1;
+			wake_up(&the_locks.eos_wait);
+			atomic_set(&prtd->eos, 0);
+		}
 		break;
 	case ASM_DATA_EVENT_READ_DONE: {
 		pr_debug("ASM_DATA_EVENT_READ_DONE\n");
@@ -250,12 +279,28 @@
 				__func__, prtd->out_head,
 				((unsigned int)buf[0].phys
 				+ (prtd->out_head * prtd->pcm_count)));
-			param.paddr = (unsigned long)buf[prtd->out_head].phys;
-			param.len = prtd->pcm_count;
-			param.msw_ts = 0;
-			param.lsw_ts = 0;
-			param.flags = NO_TIMESTAMP;
-			param.uid =  (unsigned long)buf[prtd->out_head].phys;
+			if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
+				time_stamp_flag = SET_TIMESTAMP;
+			else
+				time_stamp_flag = NO_TIMESTAMP;
+			memcpy(&output_meta_data, (char *)(buf->data +
+				prtd->out_head * prtd->pcm_count),
+				COMPRE_OUTPUT_METADATA_SIZE);
+			buffer_length = output_meta_data.frame_size;
+			pr_debug("meta_data_length: %d, frame_length: %d\n",
+				 output_meta_data.meta_data_length,
+				 output_meta_data.frame_size);
+			pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
+				 output_meta_data.timestamp_msw,
+				 output_meta_data.timestamp_lsw);
+			param.paddr = (unsigned long)buf[prtd->out_head].phys
+					+ output_meta_data.meta_data_length;
+			param.len = buffer_length;
+			param.msw_ts = output_meta_data.timestamp_msw;
+			param.lsw_ts = output_meta_data.timestamp_lsw;
+			param.flags = time_stamp_flag;
+			param.uid =  (unsigned long)buf[prtd->out_head].phys
+					+ output_meta_data.meta_data_length;
 			if (q6asm_async_write(prtd->audio_client,
 						&param) < 0)
 				pr_err("%s:q6asm_async_write failed\n",
@@ -270,7 +315,7 @@
 		case ASM_STREAM_CMD_FLUSH:
 			pr_debug("ASM_STREAM_CMD_FLUSH\n");
 			prtd->cmd_ack = 1;
-			wake_up(&the_locks.eos_wait);
+			wake_up(&the_locks.flush_wait);
 			break;
 		default:
 			break;
@@ -337,7 +382,7 @@
 		pr_debug("SND_AUDIOCODEC_WMA\n");
 		memset(&wma_cfg, 0x0, sizeof(struct asm_wma_cfg));
 		wma_cfg.format_tag = compr->info.codec_param.codec.format;
-		wma_cfg.ch_cfg = runtime->channels;
+		wma_cfg.ch_cfg = compr->info.codec_param.codec.ch_in;
 		wma_cfg.sample_rate = compr->info.codec_param.codec.sample_rate;
 		wma_cfg.avg_bytes_per_sec =
 			compr->info.codec_param.codec.bit_rate/8;
@@ -533,7 +578,9 @@
 		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			if (compr->info.codec_param.codec.id ==
-					SND_AUDIOCODEC_AC3_PASS_THROUGH) {
+					SND_AUDIOCODEC_AC3_PASS_THROUGH ||
+					compr->info.codec_param.codec.id ==
+					SND_AUDIOCODEC_DTS_PASS_THROUGH) {
 				msm_pcm_routing_reg_psthr_stream(
 					soc_prtd->dai_link->be_id,
 					prtd->session_id, substream->stream,
@@ -653,6 +700,7 @@
 		compr->codec = FORMAT_MP3;
 	populate_codec_list(compr, runtime);
 	runtime->private_data = compr;
+	atomic_set(&prtd->eos, 0);
 	compressed_audio.prtd =  &compr->prtd;
 	ret = compressed_set_volume(compressed_audio.volume);
 	if (ret < 0)
@@ -699,6 +747,7 @@
 
 	dir = IN;
 	atomic_set(&prtd->pending_buffer, 0);
+	prtd->pcm_irq_pos = 0;
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 	compressed_audio.prtd = NULL;
 	q6asm_audio_client_buf_free_contiguous(dir,
@@ -1014,8 +1063,10 @@
 			compr->codec = FORMAT_AMR_WB_PLUS;
 			break;
 		default:
-			pr_err("msm_compr_ioctl failed..unknown codec\n");
-			return -EFAULT;
+			/*Needed for the HDMI IN compressed use case*/
+			pr_debug("FORMAT_LINEAR_PCM\n");
+			compr->codec = FORMAT_LINEAR_PCM;
+			break;
 		}
 		return 0;
 	case SNDRV_PCM_IOCTL1_RESET:
@@ -1025,18 +1076,41 @@
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
 			  (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
 						atomic_read(&prtd->start))) {
+			if (atomic_read(&prtd->eos)) {
+				prtd->cmd_ack = 1;
+				wake_up(&the_locks.eos_wait);
+				atomic_set(&prtd->eos, 0);
+			}
+
+			/* A unlikely race condition possible with FLUSH
+			   DRAIN if ack is set by flush and reset by drain */
 			prtd->cmd_ack = 0;
 			rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
-			if (rc < 0)
+			if (rc < 0) {
 				pr_err("%s: flush cmd failed rc=%d\n",
-						__func__, rc);
-			rc = wait_event_timeout(the_locks.eos_wait,
-					prtd->cmd_ack, 5 * HZ);
+					__func__, rc);
+				return rc;
+			}
+			rc = wait_event_timeout(the_locks.flush_wait,
+				prtd->cmd_ack, 5 * HZ);
 			if (rc < 0)
 				pr_err("Flush cmd timeout\n");
 			prtd->pcm_irq_pos = 0;
 		}
 		break;
+	case SNDRV_COMPRESS_DRAIN:
+		pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
+		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);
+		if (rc < 0)
+			pr_err("EOS cmd interrupted\n");
+		pr_debug("%s: SNDRV_COMPRESS_DRAIN  out of wait\n", __func__);
+		return 0;
 	default:
 		break;
 	}
@@ -1097,6 +1171,7 @@
 	init_waitqueue_head(&the_locks.eos_wait);
 	init_waitqueue_head(&the_locks.write_wait);
 	init_waitqueue_head(&the_locks.read_wait);
+	init_waitqueue_head(&the_locks.flush_wait);
 
 	return platform_driver_register(&msm_compr_driver);
 }
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 011912e..16a4aaa 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -199,7 +199,7 @@
 					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 6,
+			.channels_max = 8,
 			.rate_min =	8000,
 			.rate_max = 48000,
 		},
@@ -225,7 +225,7 @@
 					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 6,
+			.channels_max = 8,
 			.rate_min =	8000,
 			.rate_max = 48000,
 		},
@@ -240,7 +240,7 @@
 					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 6,
+			.channels_max = 8,
 			.rate_min =	8000,
 			.rate_max = 48000,
 		},
@@ -255,7 +255,7 @@
 					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
-			.channels_max = 6,
+			.channels_max = 8,
 			.rate_min =	8000,
 			.rate_max = 48000,
 		},
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 6945a4f..5b0759c 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -47,11 +47,11 @@
 static struct snd_msm_volume multi_ch_pcm_audio = {NULL, 0x2000};
 
 #define PLAYBACK_NUM_PERIODS		8
-#define PLAYBACK_MAX_PERIOD_SIZE	4032
+#define PLAYBACK_MAX_PERIOD_SIZE	12288
 #define PLAYBACK_MIN_PERIOD_SIZE        256
 #define CAPTURE_NUM_PERIODS		16
 #define CAPTURE_MIN_PERIOD_SIZE		320
-#define CAPTURE_MAX_PERIOD_SIZE		5376
+#define CAPTURE_MAX_PERIOD_SIZE		12288
 
 static struct snd_pcm_hardware msm_pcm_hardware_capture = {
 	.info =                 (SNDRV_PCM_INFO_MMAP |
@@ -195,28 +195,45 @@
 				atomic_set(&prtd->start, 1);
 				break;
 			}
-			pr_debug("%s:writing %d bytes"\
-				" of buffer[%d] to dsp\n",
-				__func__, prtd->pcm_count, prtd->out_head);
-			buf = prtd->audio_client->port[IN].buf;
-			pr_debug("%s:writing buffer[%d] from 0x%08x\n",
-				__func__, prtd->out_head,
-				((unsigned int)buf[0].phys
-				+ (prtd->out_head * prtd->pcm_count)));
-			param.paddr = (unsigned long)buf[prtd->out_head].phys;
-			param.len = prtd->pcm_count;
-			param.msw_ts = 0;
-			param.lsw_ts = 0;
-			param.flags = NO_TIMESTAMP;
-			param.uid =  (unsigned long)buf[prtd->out_head].phys;
-			if (q6asm_async_write(prtd->audio_client,
-						&param) < 0)
-				pr_err("%s:q6asm_async_write failed\n",
-					__func__);
-			else
-				prtd->out_head =
-					(prtd->out_head + 1)
-					& (runtime->periods - 1);
+			if (prtd->mmap_flag) {
+				pr_debug("%s:writing %d bytes"\
+					" of buffer[%d] to dsp\n",
+					__func__, prtd->pcm_count,
+					prtd->out_head);
+				buf = prtd->audio_client->port[IN].buf;
+				pr_debug("%s:writing buffer[%d] from 0x%08x\n",
+					__func__, prtd->out_head,
+					((unsigned int)buf[0].phys
+					+ (prtd->out_head * prtd->pcm_count)));
+				param.paddr = (unsigned long)
+						buf[prtd->out_head].phys;
+				param.len = prtd->pcm_count;
+				param.msw_ts = 0;
+				param.lsw_ts = 0;
+				param.flags = NO_TIMESTAMP;
+				param.uid =  (unsigned long)
+						buf[prtd->out_head].phys;
+				if (q6asm_async_write(prtd->audio_client,
+							&param) < 0)
+					pr_err("%s:q6asm_async_write failed\n",
+						__func__);
+				else
+					prtd->out_head =
+						(prtd->out_head + 1)
+						& (runtime->periods - 1);
+			} else {
+				while (atomic_read(&prtd->out_needed)) {
+					pr_debug("%s:writing %d bytesi" \
+						  " of buffer to dsp\n", \
+						__func__, \
+						prtd->pcm_count);
+					q6asm_write_nolock(prtd->audio_client,
+						prtd->pcm_count,
+						0, 0, NO_TIMESTAMP);
+					atomic_dec(&prtd->out_needed);
+					wake_up(&the_locks.write_wait);
+				};
+			}
 			atomic_set(&prtd->start, 1);
 			break;
 		default:
@@ -237,6 +254,13 @@
 	int ret;
 
 	pr_debug("%s\n", __func__);
+	if (prtd->mmap_flag) {
+		ret = q6asm_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
+		if (ret < 0) {
+			pr_err("%s: Set IO mode failed\n", __func__);
+			return -ENOMEM;
+		}
+	}
 	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
 	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
 	prtd->pcm_irq_pos = 0;
@@ -279,8 +303,8 @@
 
 	pr_debug("Samp_rate = %d\n", prtd->samp_rate);
 	pr_debug("Channel = %d\n", prtd->channel_mode);
-	ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client, prtd->samp_rate,
-					prtd->channel_mode);
+	ret = q6asm_enc_cfg_blk_multi_ch_pcm(prtd->audio_client,
+		 prtd->samp_rate, prtd->channel_mode);
 	if (ret < 0)
 		pr_debug("%s: cmd cfg pcm was block failed", __func__);
 
@@ -375,7 +399,8 @@
 	/* Capture path */
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 		runtime->hw = msm_pcm_hardware_capture;
-		ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
+		ret = q6asm_open_read(prtd->audio_client,
+				FORMAT_MULTI_CHANNEL_LINEAR_PCM);
 		if (ret < 0) {
 			pr_err("%s: pcm in open failed\n", __func__);
 			q6asm_audio_client_free(prtd->audio_client);
@@ -731,12 +756,6 @@
 	else
 		dir = OUT;
 
-	ret = q6asm_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
-	if (ret < 0) {
-		pr_err("%s: Set IO mode failed\n", __func__);
-		return -ENOMEM;
-	}
-
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
 		prtd->audio_client,
 		(params_buffer_bytes(params) / params_periods(params)),
diff --git a/sound/soc/msm/msm-pcm-q6.h b/sound/soc/msm/msm-pcm-q6.h
index 9e743a7..f1af99a 100644
--- a/sound/soc/msm/msm-pcm-q6.h
+++ b/sound/soc/msm/msm-pcm-q6.h
@@ -48,6 +48,7 @@
 	wait_queue_head_t write_wait;
 	wait_queue_head_t eos_wait;
 	wait_queue_head_t enable_wait;
+	wait_queue_head_t flush_wait;
 };
 
 struct msm_audio {
@@ -75,10 +76,19 @@
 	atomic_t out_count;
 	atomic_t in_count;
 	atomic_t out_needed;
+	atomic_t eos;
 	int out_head;
 	int periods;
 	int mmap_flag;
 	atomic_t pending_buffer;
 };
 
+struct output_meta_data_st {
+	uint32_t meta_data_length;
+	uint32_t frame_size;
+	uint32_t timestamp_lsw;
+	uint32_t timestamp_msw;
+	uint32_t reserved[12];
+};
+
 #endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 6456b2a..5b69da4 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -271,8 +271,10 @@
 	}
 
 	mutex_lock(&routing_lock);
-
-	fe_dai_map[fedai_id][session_type] = dspst_id;
+	if (enable)
+		fe_dai_map[fedai_id][session_type] = dspst_id;
+	else
+		fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
 		if (!is_be_dai_extproc(i) &&
 		   (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
@@ -1431,6 +1433,9 @@
 	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("AUX_PCM_TX", MSM_BACKEND_DAI_AUXPCM_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 
@@ -2359,6 +2364,7 @@
 	{"MultiMedia4 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+	{"MultiMedia5 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
 	{"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
 
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index 633973e..c5e2f09 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -464,6 +464,7 @@
 
 	voc_set_tty_mode(voc_get_session_id(VOICE_SESSION_NAME), tty_mode);
 
+	voc_set_tty_mode(voc_get_session_id(SGLTE_SESSION_NAME), tty_mode);
 	return 0;
 }
 static int msm_voice_widevoice_put(struct snd_kcontrol *kcontrol,
@@ -475,7 +476,8 @@
 
 	voc_set_widevoice_enable(voc_get_session_id(VOICE_SESSION_NAME),
 				 wv_enable);
-
+	voc_set_widevoice_enable(voc_get_session_id(SGLTE_SESSION_NAME),
+				 wv_enable);
 	return 0;
 }
 
@@ -497,6 +499,8 @@
 
 	voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
 			MODULE_ID_VOICE_MODULE_ST, st_enable);
+	voc_set_pp_enable(voc_get_session_id(SGLTE_SESSION_NAME),
+			MODULE_ID_VOICE_MODULE_ST, st_enable);
 
 	return 0;
 }
@@ -519,6 +523,8 @@
 
 	voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
 			MODULE_ID_VOICE_MODULE_FENS, fens_enable);
+	voc_set_pp_enable(voc_get_session_id(SGLTE_SESSION_NAME),
+			MODULE_ID_VOICE_MODULE_FENS, fens_enable);
 
 	return 0;
 }
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index e98fe64..6bd6adc 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -88,6 +88,11 @@
 module_param(hs_detect_use_gpio, bool, 0444);
 MODULE_PARM_DESC(hs_detect_use_gpio, "Use GPIO for headset detection");
 
+static bool hs_detect_extn_cable;
+module_param(hs_detect_extn_cable, bool, 0444);
+MODULE_PARM_DESC(hs_detect_extn_cable, "Enable extension cable feature");
+
+
 static bool hs_detect_use_firmware;
 module_param(hs_detect_use_firmware, bool, 0444);
 MODULE_PARM_DESC(hs_detect_use_firmware, "Use firmware for headset detection");
@@ -108,6 +113,7 @@
 	.gpio_irq = 0,
 	.gpio_level_insert = 1,
 	.swap_gnd_mic = NULL,
+	.detect_extn_cable = false,
 };
 
 static u32 us_euro_sel_gpio = PM8921_GPIO_PM_TO_SYS(JACK_US_EURO_SEL_GPIO);
@@ -911,9 +917,10 @@
 	snd_soc_dapm_sync(dapm);
 
 	err = snd_soc_jack_new(codec, "Headset Jack",
-			       (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
-				SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED),
-			       &hs_jack);
+			       (SND_JACK_HEADSET | SND_JACK_LINEOUT |
+				SND_JACK_OC_HPHL | SND_JACK_OC_HPHR |
+				SND_JACK_UNSUPPORTED),
+				&hs_jack);
 	if (err) {
 		pr_err("failed to create new jack\n");
 		return err;
@@ -934,6 +941,8 @@
 	if (hs_detect_use_gpio) {
 		mbhc_cfg.gpio = PM8921_GPIO_PM_TO_SYS(JACK_DETECT_GPIO);
 		mbhc_cfg.gpio_irq = JACK_DETECT_INT;
+		if (hs_detect_extn_cable)
+			mbhc_cfg.detect_extn_cable = true;
 	}
 
 	if (mbhc_cfg.gpio) {
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 45b69ea..c7820dd 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -13,11 +13,11 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/mfd/pm8xxx/pm8921.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>
@@ -28,7 +28,7 @@
 #include <qdsp6v2/msm-pcm-routing-v2.h>
 #include "../codecs/wcd9320.h"
 
-/* 8974 machine driver */
+#define DRV_NAME "msm8974-asoc-taiko"
 
 #define PM8921_GPIO_BASE		NR_GPIO_IRQS
 #define PM8921_GPIO_PM_TO_SYS(pm_gpio)  (pm_gpio - 1 + PM8921_GPIO_BASE)
@@ -57,6 +57,11 @@
 #define TABLA_MBHC_DEF_BUTTONS 8
 #define TABLA_MBHC_DEF_RLOADS 5
 
+struct msm8974_asoc_mach_data {
+	int mclk_gpio;
+	u32 mclk_freq;
+};
+
 /* Shared channel numbers for Slimbus ports that connect APQ to MDM. */
 enum {
 	SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
@@ -76,12 +81,13 @@
 static int msm_slim_0_tx_ch = 1;
 
 static int msm_btsco_rate = BTSCO_RATE_8KHZ;
-static int msm_headset_gpios_configured;
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
 
 static struct mutex cdc_mclk_mutex;
+static struct q_clkdiv *codec_clk;
+static int clk_users;
 
 static void msm_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
 {
@@ -309,16 +315,67 @@
 	return 0;
 }
 
-static int msm_mclk_event(struct snd_soc_dapm_widget *w,
+static int msm8974_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
+					bool dapm)
+{
+	int ret = 0;
+	pr_debug("%s: enable = %d clk_users = %d\n",
+		__func__, enable, clk_users);
+
+	mutex_lock(&cdc_mclk_mutex);
+	if (enable) {
+		if (!codec_clk) {
+			dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
+				__func__);
+			return -EINVAL;
+		}
+
+		clk_users++;
+		if (clk_users != 1)
+			return ret;
+
+		ret = qpnp_clkdiv_enable(codec_clk);
+		if (ret) {
+			dev_err(codec->dev, "%s: Error enabling taiko MCLK\n",
+			       __func__);
+			return -ENODEV;
+		}
+		taiko_mclk_enable(codec, 1, dapm);
+	} else {
+		if (clk_users > 0) {
+			clk_users--;
+			if (clk_users == 0) {
+				taiko_mclk_enable(codec, 0, dapm);
+				qpnp_clkdiv_disable(codec_clk);
+			}
+		} else {
+			pr_err("%s: Error releasing Tabla MCLK\n", __func__);
+			ret = -EINVAL;
+		}
+	}
+	mutex_unlock(&cdc_mclk_mutex);
+	return ret;
+}
+
+static int msm8974_mclk_event(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
+	pr_debug("%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		return msm8974_enable_codec_ext_clk(w->codec, 1, true);
+	case SND_SOC_DAPM_POST_PMD:
+		return msm8974_enable_codec_ext_clk(w->codec, 0, true);
+	}
+
 	return 0;
 }
 
-static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
+static const struct snd_soc_dapm_widget msm8974_dapm_widgets[] = {
 
 	SND_SOC_DAPM_SUPPLY("MCLK",  SND_SOC_NOPM, 0, 0,
-	msm_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	msm8974_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_SPK("Ext Spk Bottom Pos", msm_spkramp_event),
 	SND_SOC_DAPM_SPK("Ext Spk Bottom Neg", msm_spkramp_event),
@@ -328,7 +385,6 @@
 
 	SND_SOC_DAPM_MIC("Handset Mic", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
-	SND_SOC_DAPM_MIC("Digital Mic1", NULL),
 	SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
 	SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
 
@@ -338,92 +394,6 @@
 	SND_SOC_DAPM_MIC("Digital Mic4", NULL),
 	SND_SOC_DAPM_MIC("Digital Mic5", NULL),
 	SND_SOC_DAPM_MIC("Digital Mic6", NULL),
-
-};
-
-static const struct snd_soc_dapm_route common_audio_map[] = {
-
-	{"RX_BIAS", NULL, "MCLK"},
-	{"LDO_H", NULL, "MCLK"},
-
-	/* Speaker path */
-	{"Ext Spk Bottom Pos", NULL, "LINEOUT1"},
-	{"Ext Spk Bottom Neg", NULL, "LINEOUT3"},
-
-	{"Ext Spk Top Pos", NULL, "LINEOUT2"},
-	{"Ext Spk Top Neg", NULL, "LINEOUT4"},
-
-	/* Microphone path */
-	{"AMIC1", NULL, "MIC BIAS1 Internal1"},
-	{"MIC BIAS1 Internal1", NULL, "Handset Mic"},
-
-	{"AMIC2", NULL, "MIC BIAS2 External"},
-	{"MIC BIAS2 External", NULL, "Headset Mic"},
-
-	/**
-	 * AMIC3 and AMIC4 inputs are connected to ANC microphones
-	 * These mics are biased differently on CDP and FLUID
-	 * routing entries below are based on bias arrangement
-	 * on FLUID.
-	 */
-	{"AMIC3", NULL, "MIC BIAS3 Internal1"},
-	{"MIC BIAS3 Internal1", NULL, "ANCRight Headset Mic"},
-
-	{"AMIC4", NULL, "MIC BIAS1 Internal2"},
-	{"MIC BIAS1 Internal2", NULL, "ANCLeft Headset Mic"},
-
-	{"HEADPHONE", NULL, "LDO_H"},
-
-	/**
-	 * The digital Mic routes are setup considering
-	 * fluid as default device.
-	 */
-
-	/**
-	 * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
-	 * Digital Mic GM5 on CDP mainboard.
-	 * Conncted to DMIC2 Input on Tabla codec.
-	 */
-	{"DMIC2", NULL, "MIC BIAS1 External"},
-	{"MIC BIAS1 External", NULL, "Digital Mic1"},
-
-	/**
-	 * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
-	 * Digital Mic GM6 on CDP mainboard.
-	 * Conncted to DMIC1 Input on Tabla codec.
-	 */
-	{"DMIC1", NULL, "MIC BIAS1 External"},
-	{"MIC BIAS1 External", NULL, "Digital Mic2"},
-
-	/**
-	 * Digital Mic3. Back Bottom Digital Mic on Fluid.
-	 * Digital Mic GM1 on CDP mainboard.
-	 * Conncted to DMIC4 Input on Tabla codec.
-	 */
-	{"DMIC4", NULL, "MIC BIAS3 External"},
-	{"MIC BIAS3 External", NULL, "Digital Mic3"},
-
-	/**
-	 * Digital Mic4. Back top Digital Mic on Fluid.
-	 * Digital Mic GM2 on CDP mainboard.
-	 * Conncted to DMIC3 Input on Tabla codec.
-	 */
-	{"DMIC3", NULL, "MIC BIAS3 External"},
-	{"MIC BIAS3 External", NULL, "Digital Mic4"},
-
-	/**
-	 * Digital Mic5. Front top Digital Mic on Fluid.
-	 * Digital Mic GM3 on CDP mainboard.
-	 * Conncted to DMIC5 Input on Tabla codec.
-	 */
-	{"DMIC5", NULL, "MIC BIAS4 External"},
-	{"MIC BIAS4 External", NULL, "Digital Mic5"},
-
-	/* Tabla digital Mic6 - back bottom digital Mic on Liquid and
-	 * bottom mic on CDP. FLUID/MTP do not have dmic6 installed.
-	 */
-	{"DMIC6", NULL, "MIC BIAS4 External"},
-	{"MIC BIAS4 External", NULL, "Digital Mic6"},
 };
 
 static const char *const spk_function[] = {"Off", "On"};
@@ -671,11 +641,8 @@
 	if (err < 0)
 		return err;
 
-	snd_soc_dapm_new_controls(dapm, msm_dapm_widgets,
-				ARRAY_SIZE(msm_dapm_widgets));
-
-	snd_soc_dapm_add_routes(dapm, common_audio_map,
-		ARRAY_SIZE(common_audio_map));
+	snd_soc_dapm_new_controls(dapm, msm8974_dapm_widgets,
+				ARRAY_SIZE(msm8974_dapm_widgets));
 
 	snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
 	snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
@@ -790,7 +757,7 @@
 };
 
 /* Digital audio interface glue - connects codec <---> CPU */
-static struct snd_soc_dai_link msm_dai[] = {
+static struct snd_soc_dai_link msm8974_dai[] = {
 	/* FrontEnd DAI Links */
 	{
 		.name = "MSM8974 Media1",
@@ -954,58 +921,148 @@
 	},
 };
 
-static struct snd_soc_card snd_soc_card_msm = {
+struct snd_soc_card snd_soc_card_msm8974 = {
 	.name		= "msm8974-taiko-snd-card",
-	.dai_link	= msm_dai,
-	.num_links	= ARRAY_SIZE(msm_dai),
+	.dai_link	= msm8974_dai,
+	.num_links	= ARRAY_SIZE(msm8974_dai),
 };
 
-static struct platform_device *msm_snd_device;
-
-static void msm_free_headset_mic_gpios(void)
+static int msm8974_prepare_codec_mclk(struct snd_soc_card *card)
 {
-	if (msm_headset_gpios_configured) {
-		gpio_free(PM8921_GPIO_PM_TO_SYS(23));
-		gpio_free(PM8921_GPIO_PM_TO_SYS(35));
-	}
-}
-
-static int __init msm_audio_init(void)
-{
-	int ret = 0;
-
-	mutex_init(&cdc_mclk_mutex);
-	if (!machine_is_msm8974_sim()) {
-		pr_info("%s: Not msm8974 machine type\n", __func__);
-		return -ENODEV;
-	}
-	msm_snd_device = platform_device_alloc("soc-audio", 0);
-	if (!msm_snd_device) {
-		pr_err("Platform device allocation failed\n");
-		return -ENOMEM;
+	struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int ret;
+	if (pdata->mclk_gpio) {
+		ret = gpio_request(pdata->mclk_gpio, "TAIKO_CODEC_PMIC_MCLK");
+		if (ret) {
+			dev_err(card->dev,
+				"%s: Failed to request taiko mclk gpio %d\n",
+				__func__, pdata->mclk_gpio);
+			return ret;
+		}
 	}
 
-	platform_set_drvdata(msm_snd_device, &snd_soc_card_msm);
-	ret = platform_device_add(msm_snd_device);
+	codec_clk = qpnp_clkdiv_get(card->dev, "taiko-mclk");
+	if (IS_ERR(codec_clk)) {
+		dev_err(card->dev,
+			"%s: Failed to request taiko mclk from pmic %ld\n",
+			__func__, PTR_ERR(codec_clk));
+		return -ENODEV ;
+	}
+
+	ret = qpnp_clkdiv_config(codec_clk, Q_CLKDIV_XO_DIV_2);
 	if (ret) {
-		platform_device_put(msm_snd_device);
-		return ret;
+		dev_err(card->dev, "%s: Failed to set taiko mclk to %u\n",
+			__func__, pdata->mclk_gpio);
+			return ret;
 	}
-	return ret;
-
+	return 0;
 }
-module_init(msm_audio_init);
 
-static void __exit msm_audio_exit(void)
+static __devinit int msm8974_asoc_machine_probe(struct platform_device *pdev)
 {
-	if (!machine_is_msm8974_sim()) {
-		pr_err("%s: Not the right machine type\n", __func__);
-		return ;
+	struct snd_soc_card *card = &snd_soc_card_msm8974;
+	struct msm8974_asoc_mach_data *pdata;
+	int ret;
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev, "No platform supplied from device tree\n");
+		return -EINVAL;
 	}
-	msm_free_headset_mic_gpios();
-	platform_device_unregister(msm_snd_device);
+
+	pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct msm8974_asoc_mach_data), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "Can't allocate msm8974_asoc_mach_data\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+	snd_soc_card_set_drvdata(card, pdata);
+
+	ret = snd_soc_of_parse_card_name(card, "qcom,model");
+	if (ret)
+		goto err;
+
+	ret = snd_soc_of_parse_audio_routing(card,
+			"qcom,audio-routing");
+	if (ret)
+		goto err;
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"qcom,taiko-mclk-clk-freq", &pdata->mclk_freq);
+	if (ret) {
+		dev_err(&pdev->dev, "Looking up %s property in node %s failed",
+			"qcom,taiko-mclk-clk-freq",
+			pdev->dev.of_node->full_name);
+		goto err;
+	}
+
+	if (pdata->mclk_freq != 9600000) {
+		dev_err(&pdev->dev, "unsupported taiko mclk freq %u\n",
+			pdata->mclk_freq);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	pdata->mclk_gpio = of_get_named_gpio(pdev->dev.of_node,
+				"qcom,cdc-mclk-gpios", 0);
+	if (pdata->mclk_gpio < 0) {
+		dev_err(&pdev->dev,
+			"Looking up %s property in node %s failed %d\n",
+			"qcom, cdc-mclk-gpios", pdev->dev.of_node->full_name,
+			pdata->mclk_gpio);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ret = msm8974_prepare_codec_mclk(card);
+	if (ret)
+		goto err;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+			ret);
+		goto err;
+	}
+	mutex_init(&cdc_mclk_mutex);
+	return 0;
+err:
+	devm_kfree(&pdev->dev, pdata);
+	return ret;
 }
-module_exit(msm_audio_exit);
+
+static int __devexit msm8974_asoc_machine_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	gpio_free(pdata->mclk_gpio);
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static const struct of_device_id msm8974_asoc_machine_of_match[]  = {
+	{ .compatible = "qcom,msm8974-audio-taiko", },
+	{},
+};
+
+static struct platform_driver msm8974_asoc_machine_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = msm8974_asoc_machine_of_match,
+	},
+	.probe = msm8974_asoc_machine_probe,
+	.remove = __devexit_p(msm8974_asoc_machine_remove),
+};
+module_platform_driver(msm8974_asoc_machine_driver);
 
 MODULE_DESCRIPTION("ALSA SoC msm");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, msm8974_asoc_machine_of_match);
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 1aac158..3a226b4 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1885,7 +1885,16 @@
 	enc_cfg.enc_blk.cfg.mpcm.sample_rate = rate;
 	enc_cfg.enc_blk.cfg.mpcm.is_signed = 1;
 	enc_cfg.enc_blk.cfg.mpcm.is_interleaved = 1;
-	if (channels == 2) {
+	if (channels == 1) {
+		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
+		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = 0;
+		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = 0;
+		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[3] = 0;
+		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[4] = 0;
+		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[5] = 0;
+		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[6] = 0;
+		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[7] = 0;
+	} else if (channels == 2) {
 		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[0] = PCM_CHANNEL_FL;
 		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[1] = PCM_CHANNEL_FR;
 		enc_cfg.enc_blk.cfg.mpcm.channel_mapping[2] = 0;
@@ -2040,6 +2049,11 @@
 	} else if (num_channels == 2) {
 		channel_mapping[0] = PCM_CHANNEL_FL;
 		channel_mapping[1] = PCM_CHANNEL_FR;
+	} else if (num_channels == 4) {
+		channel_mapping[0] = PCM_CHANNEL_FL;
+		channel_mapping[1] = PCM_CHANNEL_FR;
+		channel_mapping[1] = PCM_CHANNEL_LB;
+		channel_mapping[1] = PCM_CHANNEL_RB;
 	} else if (num_channels == 6) {
 		channel_mapping[0] = PCM_CHANNEL_FC;
 		channel_mapping[1] = PCM_CHANNEL_FL;
@@ -2047,6 +2061,15 @@
 		channel_mapping[3] = PCM_CHANNEL_LB;
 		channel_mapping[4] = PCM_CHANNEL_RB;
 		channel_mapping[5] = PCM_CHANNEL_LFE;
+	} else if (num_channels == 8) {
+		channel_mapping[0] = PCM_CHANNEL_FC;
+		channel_mapping[1] = PCM_CHANNEL_FL;
+		channel_mapping[2] = PCM_CHANNEL_FR;
+		channel_mapping[3] = PCM_CHANNEL_LB;
+		channel_mapping[4] = PCM_CHANNEL_RB;
+		channel_mapping[5] = PCM_CHANNEL_LFE;
+		channel_mapping[6] = PCM_CHANNEL_FLC;
+		channel_mapping[7] = PCM_CHANNEL_FRC;
 	} else {
 		pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
 				num_channels);
@@ -2303,6 +2326,11 @@
 	} else if (channels == 2) {
 		channel_mapping[0] = PCM_CHANNEL_FL;
 		channel_mapping[1] = PCM_CHANNEL_FR;
+	} else if (channels == 4) {
+		channel_mapping[0] = PCM_CHANNEL_FL;
+		channel_mapping[1] = PCM_CHANNEL_FR;
+		channel_mapping[1] = PCM_CHANNEL_LB;
+		channel_mapping[1] = PCM_CHANNEL_RB;
 	} else if (channels == 6) {
 		channel_mapping[0] = PCM_CHANNEL_FC;
 		channel_mapping[1] = PCM_CHANNEL_FL;
@@ -2310,6 +2338,15 @@
 		channel_mapping[3] = PCM_CHANNEL_LB;
 		channel_mapping[4] = PCM_CHANNEL_RB;
 		channel_mapping[5] = PCM_CHANNEL_LFE;
+	} else if (channels == 8) {
+		channel_mapping[0] = PCM_CHANNEL_FC;
+		channel_mapping[1] = PCM_CHANNEL_FL;
+		channel_mapping[2] = PCM_CHANNEL_FR;
+		channel_mapping[3] = PCM_CHANNEL_LB;
+		channel_mapping[4] = PCM_CHANNEL_RB;
+		channel_mapping[5] = PCM_CHANNEL_LFE;
+		channel_mapping[6] = PCM_CHANNEL_FLC;
+		channel_mapping[7] = PCM_CHANNEL_FRC;
 	} else {
 		pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
 				channels);
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 1cb2878..34b1b52 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -13,7 +13,7 @@
 #define __QDSP6VOICE_H__
 
 #include <mach/qdsp6v2/apr.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #define MAX_VOC_PKT_SIZE 642
 #define SESSION_NAME_LEN 21
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 360744a..6f3249a 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -279,7 +279,6 @@
 static int msm_compr_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct compr_audio *compr;
 	struct msm_audio *prtd;
 	int ret = 0;
@@ -319,9 +318,6 @@
 	pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
 
 	prtd->session_id = prtd->audio_client->session;
-	msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
-			prtd->session_id, substream->stream);
-
 	prtd->cmd_ack = 1;
 
 	ret = snd_pcm_hw_constraint_list(runtime, 0,
@@ -460,6 +456,7 @@
 				struct snd_pcm_hw_params *params)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct compr_audio *compr = runtime->private_data;
 	struct msm_audio *prtd = &compr->prtd;
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
@@ -477,6 +474,9 @@
 		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_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
 	if (ret < 0) {
 		pr_err("%s: Set IO mode failed\n", __func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 485569b..3eab972 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -400,70 +400,23 @@
 	int rc = 0;
 
 	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
-		/* PORT START should be set if prepare called in active state */
-		rc = afe_q6_interface_prepare();
+		switch (dai->id) {
+		case VOICE_PLAYBACK_TX:
+		case VOICE_RECORD_TX:
+		case VOICE_RECORD_RX:
+			rc = afe_start_pseudo_port(dai->id);
+		default:
+			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 APR\n");
-	}
-	return rc;
-}
-
-static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
-		struct snd_soc_dai *dai)
-{
-	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
-	int rc = 0;
-
-	/*
-	 * Start/stop port without waiting for Q6 AFE response. Need to have
-	 * native q6 AFE driver propagates AFE response in order to handle
-	 * port start/stop command error properly if error does arise.
-	 */
-	pr_debug("%s:port:%d  cmd:%d dai_data->status_mask = %ld",
-		__func__, dai->id, cmd, *dai_data->status_mask);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
-			switch (dai->id) {
-			case VOICE_PLAYBACK_TX:
-			case VOICE_RECORD_TX:
-			case VOICE_RECORD_RX:
-				afe_pseudo_port_start_nowait(dai->id);
-				break;
-			default:
-				afe_port_start_nowait(dai->id,
-					&dai_data->port_config, dai_data->rate);
-				break;
-			}
+			dev_err(dai->dev, "fail to open AFE port %x\n",
+				dai->id);
+		else
 			set_bit(STATUS_PORT_STARTED,
 				dai_data->status_mask);
-		}
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
-			switch (dai->id) {
-			case VOICE_PLAYBACK_TX:
-			case VOICE_RECORD_TX:
-			case VOICE_RECORD_RX:
-				afe_pseudo_port_stop_nowait(dai->id);
-				break;
-			default:
-				afe_port_stop_nowait(dai->id);
-				break;
-			}
-			clear_bit(STATUS_PORT_STARTED,
-				dai_data->status_mask);
-		}
-		break;
-
-	default:
-		rc = -EINVAL;
 	}
-
 	return rc;
 }
 
@@ -799,7 +752,6 @@
 
 static struct snd_soc_dai_ops msm_dai_q6_ops = {
 	.prepare	= msm_dai_q6_prepare,
-	.trigger	= msm_dai_q6_trigger,
 	.hw_params	= msm_dai_q6_hw_params,
 	.shutdown	= msm_dai_q6_shutdown,
 	.set_fmt	= msm_dai_q6_set_fmt,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 047e0f0..19e0464 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -57,11 +57,11 @@
 	.rate_max =             48000,
 	.channels_min =         1,
 	.channels_max =         2,
-	.buffer_bytes_max =     2 * 1024 * 1024,
+	.buffer_bytes_max =     1024 * 1024,
 	.period_bytes_min =	128 * 1024,
-	.period_bytes_max =     512 * 1024,
+	.period_bytes_max =     256 * 1024,
 	.periods_min =          4,
-	.periods_max =          16,
+	.periods_max =          8,
 	.fifo_size =            0,
 };
 
@@ -87,7 +87,6 @@
 	unsigned long flag = 0;
 	int i = 0;
 
-	pr_debug("%s\n", __func__);
 	spin_lock_irqsave(&the_locks.event_lock, flag);
 	switch (opcode) {
 	case ASM_DATA_EVENT_WRITE_DONE_V2: {
@@ -110,12 +109,16 @@
 			break;
 		} else
 			atomic_set(&prtd->pending_buffer, 0);
-		if (runtime->status->hw_ptr >= runtime->control->appl_ptr)
-			break;
+
+		buf = prtd->audio_client->port[IN].buf;
+		if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
+			memset((void *)buf[0].data +
+				(prtd->out_head * prtd->pcm_count),
+				0, prtd->pcm_count);
+		}
 		pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
 				__func__, prtd->pcm_count);
 
-		buf = prtd->audio_client->port[IN].buf;
 		param.paddr = (unsigned long)buf[0].phys
 				+ (prtd->out_head * prtd->pcm_count);
 		param.len = prtd->pcm_count;
@@ -230,11 +233,13 @@
 		pr_debug("SNDRV_PCM_TRIGGER_START\n");
 		q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
 		atomic_set(&prtd->start, 1);
+		atomic_set(&prtd->stop, 0);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
 		audio_ocmem_process_req(AUDIO, false);
 		atomic_set(&prtd->start, 0);
+		atomic_set(&prtd->stop, 1);
 		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
 			break;
 		break;
@@ -322,6 +327,7 @@
 
 	prtd->dsp_cnt = 0;
 	atomic_set(&prtd->pending_buffer, 1);
+	atomic_set(&prtd->stop, 1);
 	runtime->private_data = prtd;
 	lpa_audio.prtd = prtd;
 	lpa_set_volume(lpa_audio.volume);
@@ -365,7 +371,8 @@
 	To issue EOS to dsp, we need to be run state otherwise
 	EOS is not honored.
 	*/
-	if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id)) {
+	if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id) &&
+		(!atomic_read(&prtd->stop))) {
 		rc = q6asm_run(prtd->audio_client, 0, 0, 0);
 		atomic_set(&prtd->pending_buffer, 0);
 		prtd->cmd_ack = 0;
@@ -385,6 +392,7 @@
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
 
+	atomic_set(&prtd->stop, 1);
 	pr_debug("%s\n", __func__);
 	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
 		SNDRV_PCM_STREAM_PLAYBACK);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index c9f9593..7483bb6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -107,7 +107,6 @@
 	uint32_t idx = 0;
 	uint32_t size = 0;
 
-	pr_err("%s\n", __func__);
 	switch (opcode) {
 	case ASM_DATA_EVENT_WRITE_DONE_V2: {
 		pr_debug("ASM_DATA_EVENT_WRITE_DONE_V2\n");
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index 44395b7..22bf0cc 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -72,6 +72,7 @@
 	int close_ack;
 	int cmd_ack;
 	atomic_t start;
+	atomic_t stop;
 	atomic_t out_count;
 	atomic_t in_count;
 	atomic_t out_needed;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 2e58e1b..0b25545 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -30,6 +30,7 @@
 	atomic_t state;
 	atomic_t status;
 	wait_queue_head_t wait[AFE_MAX_PORTS];
+	struct task_struct *task;
 	void (*tx_cb) (uint32_t opcode,
 		uint32_t token, uint32_t *payload, void *priv);
 	void (*rx_cb) (uint32_t opcode,
@@ -58,6 +59,9 @@
 			atomic_set(&this_afe.state, 0);
 			this_afe.apr = NULL;
 		}
+		/* send info to user */
+		pr_debug("task_name = %s pid = %d\n",
+			this_afe.task->comm, this_afe.task->pid);
 		return 0;
 	}
 	pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x\n",
@@ -248,7 +252,7 @@
 		afe_send_cal_block(RX_CAL, port_id);
 }
 
-int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
+int afe_port_start(u16 port_id, union afe_port_config *afe_config,
 	u32 rate) /* This function is no blocking */
 {
 	struct afe_port_cmd_device_start start;
@@ -274,8 +278,9 @@
 		port_id = VIRTUAL_ID_TO_PORTID(port_id);
 
 	ret = afe_q6_interface_prepare();
-	if (ret != 0)
+	if (IS_ERR_VALUE(ret))
 		return ret;
+
 	if (q6audio_validate_port(port_id) < 0) {
 		pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
 				port_id);
@@ -338,6 +343,8 @@
 
 	config.port = *afe_config;
 
+	atomic_set(&this_afe.state, 1);
+	atomic_set(&this_afe.status, 0);
 	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
 	if (ret < 0) {
 		pr_err("%s: AFE enable for port %d failed\n", __func__,
@@ -345,7 +352,20 @@
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
+	ret = wait_event_timeout(this_afe.wait[index],
+				(atomic_read(&this_afe.state) == 0),
+					msecs_to_jiffies(TIMEOUT_MS));
 
+	if (!ret) {
+		pr_err("%s: wait_event timeout IF CONFIG\n", __func__);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
 	/* send AFE cal */
 	afe_send_cal(port_id);
 
@@ -360,6 +380,7 @@
 	pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
 		 __func__, start.hdr.opcode, start.port_id);
 
+	atomic_set(&this_afe.state, 1);
 	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
 
 	if (IS_ERR_VALUE(ret)) {
@@ -369,6 +390,21 @@
 		goto fail_cmd;
 	}
 
+	ret = wait_event_timeout(this_afe.wait[index],
+				(atomic_read(&this_afe.state) == 0),
+					msecs_to_jiffies(TIMEOUT_MS));
+
+	if (!ret) {
+		pr_err("%s: wait_event timeout PORT START\n", __func__);
+		 ret = -EINVAL;
+		goto fail_cmd;
+	}
+	if (this_afe.task != current)
+		this_afe.task = current;
+
+	pr_debug("task_name = %s pid = %d\n",
+		this_afe.task->comm, this_afe.task->pid);
+
 	return 0;
 
 fail_cmd:
@@ -506,8 +542,7 @@
 	config.pdata.param_size =  sizeof(config.port);
 
 	config.port = *afe_config;
-	pr_debug("%s: param PL size=%d iparam_size[%d][%d %d %d %d]"
-		" param_id[%x]\n",
+	pr_debug("%s: param PL size=%d iparam_size[%d][%d %d %d %d] param_id[%x]\n",
 		__func__, config.param.payload_size, config.pdata.param_size,
 		sizeof(config), sizeof(config.param), sizeof(config.port),
 		sizeof(struct apr_hdr), config.pdata.param_id);
@@ -653,8 +688,8 @@
 
 	/* RX ports numbers are even .TX ports numbers are odd. */
 	if (port_id % 2 == 0) {
-		pr_err("%s: Failed : afe loopback gain only for TX ports."
-			" port_id %d\n", __func__, port_id);
+		pr_err("%s: Failed : afe loopback gain only for TX ports. port_id %d\n",
+				__func__, port_id);
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
@@ -1319,7 +1354,7 @@
 			else
 				base = 10;
 
-			if (strict_strtoul(token, base, &param1[cnt]) != 0)
+			if (kstrtoul(token, base, &param1[cnt]) != 0)
 				return -EINVAL;
 
 			token = strsep(&buf, " ");
@@ -1389,8 +1424,7 @@
 			}
 
 			if (param[1] < 0 || param[1] > 100) {
-				pr_err("%s: Error, volume shoud be 0 to 100"
-					" percentage param = %lu\n",
+				pr_err("%s: Error, volume shoud be 0 to 100 percentage param = %lu\n",
 					__func__, param[1]);
 				rc = -EINVAL;
 				goto afe_error;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 392b9b0..714b2ce 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1060,8 +1060,8 @@
 		pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n",
 				 __func__,
 				 payload[0], payload[1], payload[2]);
-		ac->time_stamp = (uint64_t)(((uint64_t)payload[1] << 32) |
-				payload[2]);
+		ac->time_stamp = (uint64_t)(((uint64_t)payload[2] << 32) |
+				payload[1]);
 		if (atomic_read(&ac->cmd_state)) {
 			atomic_set(&ac->cmd_state, 0);
 			wake_up(&ac->cmd_wait);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index d313349..8bafe04 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -13,7 +13,7 @@
 #define __QDSP6VOICE_H__
 
 #include <mach/qdsp6v2/apr.h>
-#include <linux/ion.h>
+#include <linux/msm_ion.h>
 
 #define MAX_VOC_PKT_SIZE 642
 #define SESSION_NAME_LEN 20
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 65cee5d..f989b17 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2046,6 +2046,8 @@
 			be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
 		}
 
+		fe_path_put(&list);
+
 capture:
 		/* skip if FE doesn't have capture capability */
 		if (!fe->cpu_dai->driver->capture.channels_min)
diff --git a/tools/perf/util/scripting-engines/trace-event-json-export.c b/tools/perf/util/scripting-engines/trace-event-json-export.c
index 3fb6da7..2aec459 100644
--- a/tools/perf/util/scripting-engines/trace-event-json-export.c
+++ b/tools/perf/util/scripting-engines/trace-event-json-export.c
@@ -53,8 +53,8 @@
 
 	value = eval_flag(field_value);
 
-	fprintf(ofp , ",\n[\"%s\",%d,{\"field\":\"%s\",\"value\":%llu,
-			\"name\":\"%s\"}]",
+	fprintf(ofp,
+		",\n[\"%s\",%d,{\"field\":\"%s\",\"value\":%llu,\"name\":\"%s\"}]",
 		handler_name, id, field_name, value, field_str);
 }
 
@@ -77,12 +77,12 @@
 {
 	if (field_type == PRINT_FLAGS) {
 		const char *handler_name = "define_flag_field";
-		fprintf(ofp , ",\n[\"%s\",%d,{\"field\":\"%s\",
-				\"delim\":\"%s\"}]",
-				handler_name, id, field_name, delim);
+		fprintf(ofp,
+			",\n[\"%s\",%d,{\"field\":\"%s\",\"delim\":\"%s\"}]",
+			handler_name, id, field_name, delim);
 	} else {
 		const char *handler_name = "define_symbol_field";
-		fprintf(ofp , ",\n[\"%s\",%d,{\"field\":\"%s\"}]",
+		fprintf(ofp, ",\n[\"%s\",%d,{\"field\":\"%s\"}]",
 				handler_name, id, field_name);
 	}
 }
@@ -140,27 +140,27 @@
 	const char *handler_name = "define_event";
 	struct format_field *field = 0;
 
-	fprintf(ofp , ",\n[\"%s\",%d,{\"system\":\"%s\",
-			\"name\":\"%s\",\"args\":{",
+	fprintf(ofp,
+		",\n[\"%s\",%d,{\"system\":\"%s\",\"name\":\"%s\",\"args\":{",
 			handler_name, event->id, ev_system, ev_name);
 
-	fprintf(ofp , "%s\"%s\":%d", prefix(indx), "common_s", indx);
+	fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_s", indx);
 	indx++;
-	fprintf(ofp , "%s\"%s\":%d", prefix(indx), "common_ns", indx);
+	fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_ns", indx);
 	indx++;
-	fprintf(ofp , "%s\"%s\":%d", prefix(indx), "common_cpu", indx);
+	fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_cpu", indx);
 	indx++;
-	fprintf(ofp , "%s\"%s\":%d", prefix(indx), "common_comm", indx);
+	fprintf(ofp, "%s\"%s\":%d", prefix(indx), "common_comm", indx);
 	indx++;
 	for (field = event->format.common_fields; field; field = field->next) {
-		fprintf(ofp , "%s\"%s\":%d", prefix(indx), field->name, indx);
+		fprintf(ofp, "%s\"%s\":%d", prefix(indx), field->name, indx);
 		indx++;
 	}
 	for (field = event->format.fields; field; field = field->next) {
-		fprintf(ofp , "%s\"%s\":%d", prefix(indx), field->name, indx);
+		fprintf(ofp, "%s\"%s\":%d", prefix(indx), field->name, indx);
 		indx++;
 	}
-	fprintf(ofp , "}}]");
+	fprintf(ofp, "}}]");
 }
 
 static inline struct event *find_cache_event(int type)
@@ -191,14 +191,14 @@
 			offset &= 0xffff;
 		} else
 			offset = field->offset;
-		fprintf(ofp , "%s\"%s\"", prefix(indx), (char *)data + offset);
+		fprintf(ofp, "%s\"%s\"", prefix(indx), (char *)data + offset);
 	} else { /* FIELD_IS_NUMERIC */
 		val = read_size(data + field->offset, field->size);
 		if (field->flags & FIELD_IS_SIGNED)
-			fprintf(ofp , "%s%lld", prefix(indx),
+			fprintf(ofp, "%s%lld", prefix(indx),
 					(long long int) val);
 		else
-			fprintf(ofp , "%s%llu", prefix(indx), val);
+			fprintf(ofp, "%s%llu", prefix(indx), val);
 	}
 }
 
@@ -227,7 +227,7 @@
 	s = nsecs / NSECS_PER_SEC;
 	ns = nsecs - s * NSECS_PER_SEC;
 
-	fprintf(ofp , ",\n[\"event\",%d,[%lu,%lu,%d,\"%s\"",
+	fprintf(ofp, ",\n[\"event\",%d,[%lu,%lu,%d,\"%s\"",
 			type, s, ns, cpu, comm);
 
 	indx += 4;
@@ -258,7 +258,7 @@
 	} else
 		ofp = stdout;
 
-	fprintf(ofp , "[[\"trace_start\"]");
+	fprintf(ofp, "[[\"trace_start\"]");
 
 	return err;
 }
@@ -270,7 +270,7 @@
 {
 	int err = 0;
 
-	fprintf(ofp , ",\n[\"trace_end\"]]");
+	fprintf(ofp, ",\n[\"trace_end\"]]");
 
 	return err;
 }
@@ -288,14 +288,14 @@
 		fprintf(stderr, "couldn't open %s\n", fname);
 		return -EBADF;
 	}
-	fprintf(ofp ,  "[[\"generate_start\"]");
+	fprintf(ofp, "[[\"generate_start\"]");
 
 	while ((event = trace_find_next_event(event))) {
 		define_event(event);
 		define_event_symbols(event, event->print_fmt.args);
 	}
 
-	fprintf(ofp ,  ",\n[\"generate_end\"]]");
+	fprintf(ofp, ",\n[\"generate_end\"]]");
 
 	fclose(ofp);