Merge "qseecom: Fix the kernel_qseecom_client send_cmd fucntionality"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_tspp.txt b/Documentation/devicetree/bindings/arm/msm/msm_tspp.txt
new file mode 100644
index 0000000..2b5e143
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_tspp.txt
@@ -0,0 +1,73 @@
+TSPP Driver
+
+For information on the TSPP driver, please refer to the TSPP driver
+documentation: Documentation/arm/msm/tspp.txt.
+
+The devicetree representation of the TSPP block should be:
+
+Required properties:
+
+- compatible: "qcom,msm_tspp"
+- cell-index: <0> - represents device ID.
+- reg: physical memory base addresses and sizes for the following:
+	TSIF0, TSIF1, TSPP and TSPP_BAM.
+- reg-names: names of the memory regions.
+- interrupts: represents IRQ numbers for the following:
+	TSIF_TSPP_IRQ, TSIF0_IRQ, TSIF1_IRQ, TSIF_BAM_IRQ.
+- interrupt-names: TSPP, TSIF and BAM interrupt names.
+- qcom,tsif-pclk: interface clock name.
+- qcom,tsif-ref-clk: reference clock name.
+	The driver uses clk_get to get the clocks by name. The clocks
+	should be defined in the relevant clock file (e.g. clock-8974.c).
+- gpios: GPIO numbers for TSIF0 (CLK, EN, DATA and SYNC) and TSIF1 (same).
+- qcom,gpio-names: GPIO names - strings describing the GPIO functionality.
+- qcom,gpios-func: GPIO functionality according to the GPIO functionality table.
+	GPIO pins can have more than a single functionality, and the TSPP driver
+	is responsible for configuring the GPIOs to work in TSIF functionality
+	based on this parameter.
+	Note: it is assumed that the functionality value (e.g. 1 in 8974 case)
+	is applicable to all TSIF GPIOs.
+
+Example (for 8974 platform, avaialble at msm8974.dtsi):
+
+	tspp: msm_tspp@f99d8000 {
+		compatible = "qcom,msm_tspp";
+		cell-index = <0>;
+		reg = <0xf99d8000 0x1000>, /* MSM_TSIF0_PHYS */
+		      <0xf99d9000 0x1000>, /* MSM_TSIF1_PHYS */
+		      <0xf99da000 0x1000>, /* MSM_TSPP_PHYS  */
+		      <0xf99c4000 0x14000>; /* MSM_TSPP_BAM_PHYS */
+		reg-names = "MSM_TSIF0_PHYS",
+			"MSM_TSIF1_PHYS",
+			"MSM_TSPP_PHYS",
+			"MSM_TSPP_BAM_PHYS";
+		interrupts = <0 153 0>, /* TSIF_TSPP_IRQ */
+			<0 151 0>, /* TSIF0_IRQ */
+			<0 152 0>, /* TSIF1_IRQ */
+			<0 154 0>; /* TSIF_BAM_IRQ */
+		interrupt-names = "TSIF_TSPP_IRQ",
+			"TSIF0_IRQ",
+			"TSIF1_IRQ",
+			"TSIF_BAM_IRQ";
+		qcom,tsif-pclk = "iface_clk";
+		qcom,tsif-ref-clk = "ref_clk";
+		gpios = <&msmgpio 89 0>, /* TSIF0 CLK  */
+			<&msmgpio 90 0>, /* TSIF0 EN   */
+			<&msmgpio 91 0>, /* TSIF0 DATA */
+			<&msmgpio 92 0>, /* TSIF0 SYNC */
+			<&msmgpio 93 0>, /* TSIF1 CLK  */
+			<&msmgpio 94 0>, /* TSIF1 EN   */
+			<&msmgpio 95 0>, /* TSIF1 DATA */
+			<&msmgpio 96 0>; /* TSIF1 SYNC */
+		qcom,gpio-names = "tsif_clk",
+				"tsif_en",
+				"tsif_data",
+				"tsif_sync",
+				"tsif_clk",
+				"tsif_en",
+				"tsif_data",
+				"tsif_sync";
+		qcom,gpios-func = <1>;
+	};
+
+
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-smd.txt b/Documentation/devicetree/bindings/arm/msm/rpm-smd.txt
index 8ebd3ba..7235a1a 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm-smd.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-smd.txt
@@ -20,6 +20,17 @@
 - rpm-channel-type: The interal SMD edge for this subsystem found in
 			<mach/msm_smd.h>
 
+Optional properties
+- rpm-standlone: Allow the driver to run in standalone mode. This is a
+			suggestion to the RPM driver and if the SMD
+			channel is made available for RPM, the driver
+			would continue to send requests to RPM processor,
+			but if the SMD channel is unavailable, driver will
+			return success even though the data is not sent
+			to the RPM processor. In the absence of this
+			option, the driver will fail if the SMD channel
+			is unavailable.
+
 Example:
 
 	qcom,rpm-smd {
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-server.txt b/Documentation/devicetree/bindings/media/video/msm-cam-server.txt
deleted file mode 100644
index 2b6f513..0000000
--- a/Documentation/devicetree/bindings/media/video/msm-cam-server.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-* Qualcomm MSM Camera Server
-
-Required properties:
-- compatible :
-    - "qcom,cam_server"
-
-Example:
-
-   qcom,cam_server {
-       compatible = "qcom,cam_server";
-   };
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam.txt b/Documentation/devicetree/bindings/media/video/msm-cam.txt
new file mode 100644
index 0000000..b5b6cf6
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video/msm-cam.txt
@@ -0,0 +1,15 @@
+* Qualcomm MSM Camera
+
+Required properties:
+- compatible :
+    - "qcom,msm-cam"
+- reg : offset and length of msm camera device registers.
+- reg-names : should specify relevant names for each reg property defined.
+
+Example:
+
+   qcom,msm-cam@fd8c0000 {
+       compatible = "qcom,msm-cam";
+       reg = <0xfd8C0000 0x10000>;
+       reg-names = "msm-cam";
+   };
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index e256265..cf33f50 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -11,6 +11,25 @@
 - interrupts : should contain the cci interrupt.
 - interrupt-names : should specify relevant names to each interrupts
   property defined.
+- gpios : should contain phandle to gpio controller node and array of
+    #gpio-cells specifying specific gpio (controller specific)
+- 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,hw-thigh : should contain high period of the SCL clock in terms of CCI
+    clock cycle
+- qcom,hw-tlow : should contain high period of the SCL clock in terms of CCI
+    clock cycle
+- qcom,hw-tsu-sto : should contain setup time for STOP condition
+- qcom,hw-tsu-sta : should contain setup time for Repeated START condition
+- qcom,hw-thd-dat : should contain hold time for the data
+- qcom,hw-thd-sta : should contain hold time for START condition
+- qcom,hw-tbuf : should contain free time between a STOP and a START condition
+- qcom,hw-scl-stretch-en : should contain enable or disable clock stretching
+- qcom,hw-trdhld : should contain internal hold time for SDA
+- qcom,hw-tsp : should contain filtering of glitches
 
 [Second level nodes]
 * Qualcomm MSM Sensor
@@ -22,16 +41,14 @@
     - "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
+- qcom,slave-id : should contain i2c slave address, device id address
+    and expected id read value
+- qcom,csiphy-sd-index : should contain csiphy instance that will used to
+    receive sensor data
+    - 0, 1, 2
+- qcom,csid-sd-index : 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"
@@ -52,7 +69,7 @@
     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
+- qcom,sensor-mode : should contain sensor mode supported
     - 0 -> back camera 2D
     - 1 -> front camera 2D
     - 2 -> back camera 3D
@@ -62,7 +79,10 @@
     - 1 -> yuv format
 
 Optional properties:
-- qcom,flash-src-index : should contain phandle to flash source node if flash
+- qcom,is-vpe : should be enabled if VPE module is required for post processing
+    of this sensor
+    - 1 if required, 0 otherwise
+- qcom,led-flash-sd-index : should contain phandle to flash source node if flash
     is supported for this sensor
     - led_flash0, led_flash1
 - qcom,mount-angle : should contain the physical mount angle of the sensor on
@@ -74,12 +94,7 @@
 - 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-reset : should contain index to gpio used by sensors reset_n
 - qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
 - qcom,gpio-req-tbl-flags : should contain direction of gpios present in
     qcom,gpio-req-tbl-num property (in the same order)
@@ -107,7 +122,9 @@
     for actuator
 - qcom,actuator-vcm-enable : should contain value to be set for actuator vcm
     gpio
-
+- qcom,sensor-position : should contain the mount angle of the camera sensor
+    - 0 -> back camera
+    - 1 -> front camera
 Example:
 
    qcom,cci@0xfda0c000 {
@@ -117,13 +134,33 @@
        reg-names = "cci";
        interrupts = <0 50 0>;
        interrupt-names = "cci";
+       gpios = <&msmgpio 19 0>,
+               <&msmgpio 20 0>,
+               <&msmgpio 21 0>,
+               <&msmgpio 22 0>;
+       qcom,gpio-tbl-num = <0 1 2 3>;
+       qcom,gpio-tbl-flags = <1 1 1 1>;
+       qcom,gpio-tbl-label = "CCI_I2C_DATA0",
+                             "CCI_I2C_CLK0",
+                             "CCI_I2C_DATA1",
+                             "CCI_I2C_CLK1";
+       qcom,hw-thigh = <78>;
+       qcom,hw-tlow = <114>;
+       qcom,hw-tsu-sto = <28>;
+       qcom,hw-tsu-sta = <28>;
+       qcom,hw-thd-dat = <10>;
+       qcom,hw-thd-sta = <77>;
+       qcom,hw-tbuf = <118>;
+       qcom,hw-scl-stretch-en = <0>;
+       qcom,hw-trdhld = <6>;
+       qcom,hw-tsp = <1>;
        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,slave-id = <0x6e 0x0 0x3121>;
+               qcom,led-flash-sd-index = <0>;
+               qcom,csiphy-sd-index = <2>;
+               qcom,csid-sd-index = <0>;
                qcom,mount-angle = <90>;
                qcom,sensor-name = "s5k3l1yx";
                cam_vdig-supply = <&pm8941_l3>;
@@ -137,23 +174,18 @@
                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-reset = <1>;
+               qcom,gpio-req-tbl-num = <0 1>;
+               qcom,gpio-req-tbl-flags = <1 0>;
+               qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+                                         "CAM_RESET1";
+               qcom,gpio-set-tbl-num = <1 1>;
                qcom,gpio-set-tbl-flags = <0 2>;
                qcom,gpio-set-tbl-delay = <1000 4000>;
                qcom,csi-lane-assign = <0x4320>;
                qcom,csi-lane-mask = <0x1F>;
                qcom,csi-phy-sel = <0>;
-               qcom,camera-type = <0>;
-               qcom,sensor-type = <0>;
+               qcom,sensor-position = <0>;
+               qcom,sensor-mode = <1>;
        };
    };
diff --git a/Documentation/devicetree/bindings/media/video/msm-vfe.txt b/Documentation/devicetree/bindings/media/video/msm-vfe.txt
index 7a70cac..f02f35e 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vfe.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vfe.txt
@@ -4,6 +4,7 @@
 - cell-index: vfe hardware core index
 - compatible :
     - "qcom,vfe"
+    - "qcom,vfe40"
 - reg : offset and length of the register set for the device
     for the vfe operating in compatible mode.
 - reg-names : should specify relevant names to each reg property defined.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 5aecb48..2d4a6db 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1098,6 +1098,11 @@
 	Functional default: enabled if accept_ra is enabled.
 			    disabled if accept_ra is disabled.
 
+accept_ra_prefix_route - BOOLEAN
+	Set the prefix route for the autoconfigured interface address
+
+	Functional default: enabled
+
 accept_redirects - BOOLEAN
 	Accept Redirects.
 
diff --git a/arch/arm/boot/dts/msm-iommu.dtsi b/arch/arm/boot/dts/msm-iommu.dtsi
index 024c11f..5a9e1ee 100755
--- a/arch/arm/boot/dts/msm-iommu.dtsi
+++ b/arch/arm/boot/dts/msm-iommu.dtsi
@@ -18,6 +18,7 @@
 		ranges;
 		reg = <0xfda64000 0x10000>;
 		reg-names = "iommu_base";
+		interrupts = <0 67 0>;
 		vdd-supply = <&gdsc_jpeg>;
 		qcom,needs-alt-core-clk;
 		label = "jpeg_iommu";
@@ -84,6 +85,7 @@
 		ranges;
 		reg = <0xfd928000 0x10000>;
 		reg-names = "iommu_base";
+		interrupts = <0 73 0>;
 		vdd-supply = <&gdsc_mdss>;
 		qcom,iommu-secure-id = <1>;
 		label = "mdp_iommu";
@@ -151,6 +153,7 @@
 		reg = <0xfdc84000 0x10000
 		       0xfdce0004 0x4>;
 		reg-names = "iommu_base", "clk_base";
+		interrupts = <0 45 0>;
 		vdd-supply = <&gdsc_venus>;
 		qcom,iommu-secure-id = <0>;
 		qcom,needs-alt-core-clk;
@@ -238,6 +241,7 @@
 		ranges;
 		reg = <0xfdb10000 0x10000>;
 		reg-names = "iommu_base";
+		interrupts = <0 38 0>;
 		vdd-supply = <&gdsc_oxili_cx>;
 		qcom,alt-vdd-supply = <&gdsc_oxili_gx>;
 		qcom,needs-alt-core-clk;
@@ -292,6 +296,7 @@
 		ranges;
 		reg = <0xfda44000 0x10000>;
 		reg-names = "iommu_base";
+		interrupts = <0 62 0>;
 		vdd-supply = <&gdsc_vfe>;
 		qcom,needs-alt-core-clk;
 		label = "vfe_iommu";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 098f543..74a95e6 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -77,7 +77,6 @@
 			qcom,bms-calculate-soc-ms = <20000>;
 			qcom,bms-chg-term-ua = <100000>;
 			qcom,bms-batt-type = <0>;
-			qcom,bms-use-external-rsense;
 
 			qcom,bms-iadc@3800 {
 				reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm8910-iommu-domains.dtsi b/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
similarity index 93%
rename from arch/arm/boot/dts/msm8910-iommu-domains.dtsi
rename to arch/arm/boot/dts/msm8610-iommu-domains.dtsi
index dbdbd5f..52a8c47 100644
--- a/arch/arm/boot/dts/msm8910-iommu-domains.dtsi
+++ b/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/arch/arm/boot/dts/msm8910-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8910-ion.dtsi
rename to arch/arm/boot/dts/msm8610-ion.dtsi
index 88bb1ab..0abaca5 100644
--- a/arch/arm/boot/dts/msm8910-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/arch/arm/boot/dts/msm8910-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
similarity index 98%
rename from arch/arm/boot/dts/msm8910-regulator.dtsi
rename to arch/arm/boot/dts/msm8610-regulator.dtsi
index a32d4ab..a81c082 100644
--- a/arch/arm/boot/dts/msm8910-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/arch/arm/boot/dts/msm8910-rumi.dts b/arch/arm/boot/dts/msm8610-rumi.dts
similarity index 75%
rename from arch/arm/boot/dts/msm8910-rumi.dts
rename to arch/arm/boot/dts/msm8610-rumi.dts
index 0d944aa..d889268 100644
--- a/arch/arm/boot/dts/msm8910-rumi.dts
+++ b/arch/arm/boot/dts/msm8610-rumi.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "msm8910.dtsi"
+/include/ "msm8610.dtsi"
 
 / {
-	model = "Qualcomm MSM 8910 Rumi";
-	compatible = "qcom,msm8910-rumi", "qcom,msm8910";
+	model = "Qualcomm MSM 8610 Rumi";
+	compatible = "qcom,msm8610-rumi", "qcom,msm8610";
 	qcom,msm-id = <147 1 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8910-sim.dts b/arch/arm/boot/dts/msm8610-sim.dts
similarity index 74%
rename from arch/arm/boot/dts/msm8910-sim.dts
rename to arch/arm/boot/dts/msm8610-sim.dts
index aae88b1..73ba807 100644
--- a/arch/arm/boot/dts/msm8910-sim.dts
+++ b/arch/arm/boot/dts/msm8610-sim.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,11 +12,11 @@
 
 /dts-v1/;
 
-/include/ "msm8910.dtsi"
+/include/ "msm8610.dtsi"
 
 / {
-	model = "Qualcomm MSM 8910 Simulator";
-	compatible = "qcom,msm8910-sim", "qcom,msm8910";
+	model = "Qualcomm MSM 8610 Simulator";
+	compatible = "qcom,msm8610-sim", "qcom,msm8610";
 	qcom,msm-id = <147 1 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8610.dtsi
similarity index 97%
rename from arch/arm/boot/dts/msm8910.dtsi
rename to arch/arm/boot/dts/msm8610.dtsi
index a08c165..4d00d2b 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,12 +12,12 @@
 
 /include/ "skeleton.dtsi"
 /include/ "msm-iommu-v1.dtsi"
-/include/ "msm8910-ion.dtsi"
+/include/ "msm8610-ion.dtsi"
 /include/ "msm-gdsc.dtsi"
 
 / {
-	model = "Qualcomm MSM 8910";
-	compatible = "qcom,msm8910";
+	model = "Qualcomm MSM 8610";
+	compatible = "qcom,msm8610";
 	interrupt-parent = <&intc>;
 
 	intc: interrupt-controller@f9000000 {
@@ -342,7 +342,7 @@
 	status = "ok";
 };
 
-/include/ "msm8910-iommu-domains.dtsi"
+/include/ "msm8610-iommu-domains.dtsi"
 
-/include/ "msm8910-regulator.dtsi"
+/include/ "msm8610-regulator.dtsi"
 /include/ "msm-pm8110.dtsi"
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index c9b999f..7035bb4 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,8 +17,9 @@
 	qcom,camera@6e {
 		compatible = "qcom,s5k3l1yx";
 		reg = <0x6e 0x0>;
-		qcom,csi-if = <1>;
-		qcom,csid-core = <0>;
+		qcom,slave-id = <0x6e 0x0 0x3121>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
 		qcom,flash-src-index = <&led_flash0>;
 		qcom,mount-angle = <0>;
 		qcom,sensor-name = "s5k3l1yx";
@@ -26,46 +27,42 @@
 		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",
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
 				     "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,cam-vreg-type = <0 1 0 0>;
+		qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 15 0>,
-			<&msmgpio 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-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET1";
+		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 30000>;
 		qcom,csi-lane-assign = <0x4320>;
 		qcom,csi-lane-mask = <0x1F>;
-		qcom,csi-phy-sel = <0>;
-		qcom,camera-type = <0>;
-		qcom,sensor-type = <0>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
 		status = "ok";
 	};
 
 	qcom,camera@6c {
 		compatible = "qcom,ov2720";
 		reg = <0x6c 0x0>;
-		qcom,csi-if = <1>;
-		qcom,csid-core = <0>;
+		qcom,slave-id = <0x6c 0x300A 0x2720>;
+		qcom,led-flash-sd-index = <0>;
+		qcom,csiphy-sd-index = <2>;
+		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <180>;
 		qcom,sensor-name = "ov2720";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
-		cam_vio-supply = <&pm8941_lvs2>;
+		cam_vio-supply = <&pm8941_lvs3>;
 		qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio";
 		qcom,cam-vreg-type = <0 0 1>;
 		qcom,cam-vreg-min-voltage = <1225000 2850000 0>;
@@ -73,25 +70,19 @@
 		qcom,cam-vreg-op-mode = <105000 80000 0>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 17 0>,
-			<&msmgpio 19 0>,
-			<&msmgpio 20 0>,
 			<&msmgpio 18 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-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET1";
+		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 4000>;
 		qcom,csi-lane-assign = <0x4320>;
 		qcom,csi-lane-mask = <0x7>;
-		qcom,csi-phy-sel = <2>;
-		qcom,camera-type = <1>;
-		qcom,sensor-type = <0>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
 		status = "ok";
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor.dtsi
index 68da844..948cdf5 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,8 +16,9 @@
 	qcom,camera@6e {
 		compatible = "qcom,s5k3l1yx";
 		reg = <0x6e 0x0>;
-		qcom,csi-if = <1>;
-		qcom,csid-core = <0>;
+		qcom,slave-id = <0x6e 0x0 0x3121>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
 		qcom,flash-src-index = <&led_flash0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "s5k3l1yx";
@@ -25,41 +26,37 @@
 		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",
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
 				     "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,cam-vreg-type = <0 1 0 0>;
+		qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 15 0>,
-			<&msmgpio 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-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET1";
+		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 30000>;
 		qcom,csi-lane-assign = <0x4320>;
 		qcom,csi-lane-mask = <0x1F>;
-		qcom,csi-phy-sel = <0>;
-		qcom,camera-type = <0>;
-		qcom,sensor-type = <0>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
 		status = "ok";
 	};
 
 	qcom,camera@6c {
 		compatible = "qcom,ov2720";
 		reg = <0x6c 0x0>;
-		qcom,csi-if = <1>;
-		qcom,csid-core = <0>;
+		qcom,slave-id = <0x6c 0x300A 0x2720>;
+		qcom,led-flash-sd-index = <0>;
+		qcom,csiphy-sd-index = <2>;
+		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <180>;
 		qcom,sensor-name = "ov2720";
 		cam_vdig-supply = <&pm8941_l3>;
@@ -72,25 +69,19 @@
 		qcom,cam-vreg-op-mode = <105000 80000 0>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 17 0>,
-			<&msmgpio 19 0>,
-			<&msmgpio 20 0>,
 			<&msmgpio 18 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-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET1";
+		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 4000>;
 		qcom,csi-lane-assign = <0x4320>;
 		qcom,csi-lane-mask = <0x7>;
-		qcom,csi-phy-sel = <2>;
-		qcom,camera-type = <1>;
-		qcom,sensor-type = <0>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
 		status = "ok";
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 48dd4dc..6002f85 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,10 +14,10 @@
 /include/ "skeleton.dtsi"
 
 / {
-	qcom,cam_server {
-		compatible = "qcom,cam_server";
+	qcom,msm-cam@fd8C0000 {
+		compatible = "qcom,msm-cam";
 		reg = <0xfd8C0000 0x10000>;
-		reg-names = "server";
+		reg-names = "msm-cam";
 	};
 
 	qcom,csiphy@fda0ac00 {
@@ -90,7 +90,7 @@
 	qcom,ispif@fda0A000 {
 		cell-index = <0>;
 		compatible = "qcom,ispif";
-		reg = <0xfda0A000 0x300>;
+		reg = <0xfda0A000 0x500>;
 		reg-names = "ispif";
 		interrupts = <0 55 0>;
 		interrupt-names = "ispif";
@@ -182,6 +182,26 @@
 		reg-names = "cci";
 		interrupts = <0 50 0>;
 		interrupt-names = "cci";
+		gpios = <&msmgpio 19 0>,
+			<&msmgpio 20 0>,
+			<&msmgpio 21 0>,
+			<&msmgpio 22 0>;
+		qcom,gpio-tbl-num = <0 1 2 3>;
+		qcom,gpio-tbl-flags = <1 1 1 1>;
+		qcom,gpio-tbl-label = "CCI_I2C_DATA0",
+				      "CCI_I2C_CLK0",
+				      "CCI_I2C_DATA1",
+				      "CCI_I2C_CLK1";
+		qcom,hw-thigh = <78>;
+		qcom,hw-tlow = <114>;
+		qcom,hw-tsu-sto = <28>;
+		qcom,hw-tsu-sta = <28>;
+		qcom,hw-thd-dat = <10>;
+		qcom,hw-thd-sta = <77>;
+		qcom,hw-tbuf = <118>;
+		qcom,hw-scl-stretch-en = <0>;
+		qcom,hw-trdhld = <6>;
+		qcom,hw-tsp = <1>;
 
 		qcom,camera@6e {
 			status = "disable";
@@ -194,8 +214,9 @@
 		qcom,camera@90 {
 			compatible = "qcom,mt9m114";
 			reg = <0x90 0x0>;
-			qcom,csi-if = <1>;
-			qcom,csid-core = <0>;
+			qcom,slave-id = <0x90 0x0 0x2481>;
+			qcom,csiphy-sd-index = <1>;
+			qcom,csid-sd-index = <0>;
 			qcom,mount-angle = <0>;
 			qcom,sensor-name = "mt9m114";
 			cam_vdig-supply = <&pm8941_l3>;
@@ -209,20 +230,18 @@
 			qcom,gpio-no-mux = <0>;
 			gpios = <&msmgpio 16 0>,
 				<&msmgpio 92 0>;
-			qcom,gpio-common-tbl-num = <0>;
-			qcom,gpio-common-tbl-flags = <1>;
-			qcom,gpio-common-tbl-label = "CAMIF_MCLK";
-			qcom,gpio-req-tbl-num = <1>;
-			qcom,gpio-req-tbl-flags = <0>;
-			qcom,gpio-req-tbl-label = "CAM_RESET1";
+			qcom,gpio-reset = <1>;
+			qcom,gpio-req-tbl-num = <0 1>;
+			qcom,gpio-req-tbl-flags = <1 0>;
+			qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+						  "CAM_RESET1";
 			qcom,gpio-set-tbl-num = <1 1>;
 			qcom,gpio-set-tbl-flags = <0 2>;
 			qcom,gpio-set-tbl-delay = <1000 4000>;
 			qcom,csi-lane-assign = <0x4320>;
 			qcom,csi-lane-mask = <0x3>;
-			qcom,csi-phy-sel = <1>;
-			qcom,camera-type = <1>;
-			qcom,sensor-type = <1>;
+			qcom,sensor-position = <1>;
+			qcom,sensor-mode = <1>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index a7a7c88..9b8e506 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -110,9 +110,17 @@
 		pm8841_s4: regulator-s4 {
 			regulator-min-microvolt = <815000>;
 			regulator-max-microvolt = <900000>;
-			qcom,init-voltage = <815000>;
 			status = "okay";
 		};
+		pm8841_s4_corner: regulator-s4-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8841_s4_corner";
+			qcom,set = <3>;
+			qcom,use-voltage-corner;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,init-voltage-corner = <3>; /* SVS SOC */
+		};
 	};
 
 	rpm-regulator-smpa1 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 8838953..c7505cb 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -672,7 +672,7 @@
 	};
 
 	gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
-		parent-supply = <&pm8841_s4>;
+		parent-supply = <&pm8841_s4_corner>;
 	};
 
 	qcom,lpass@fe200000 {
diff --git a/arch/arm/boot/dts/msm9625-cdp.dts b/arch/arm/boot/dts/msm9625-cdp.dts
index 232fba7..f2a798a 100644
--- a/arch/arm/boot/dts/msm9625-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,7 @@
 / {
 	model = "Qualcomm MSM 9625 CDP";
 	compatible = "qcom,msm9625-cdp", "qcom,msm9625";
-	qcom,msm-id = <134 1 0>, <152 1 0>;
+	qcom,msm-id = <134 1 0>, <152 1 0>, <149 1 0>, <150 1 0>;
 
 	i2c@f9925000 {
 		charger@57 {
diff --git a/arch/arm/boot/dts/msm9625-mtp.dts b/arch/arm/boot/dts/msm9625-mtp.dts
index faf86d4..584fc7f 100644
--- a/arch/arm/boot/dts/msm9625-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,7 @@
 / {
 	model = "Qualcomm MSM 9625 MTP";
 	compatible = "qcom,msm9625-mtp", "qcom,msm9625";
-	qcom,msm-id = <134 7 0>, <152 7 0>;
+	qcom,msm-id = <134 7 0>, <152 7 0>, <149 7 0>, <150 7 0>;
 
 	i2c@f9925000 {
 		charger@57 {
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
index 4b1e3f2..dfd6b5e 100644
--- a/arch/arm/configs/msm8910_defconfig
+++ b/arch/arm/configs/msm8910_defconfig
@@ -43,6 +43,9 @@
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG_V2=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 4e9f707..53c97ce 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -371,6 +371,8 @@
 CONFIG_MSM_CSI20_HEADER=y
 CONFIG_S5K3L1YX=y
 CONFIG_IMX091=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
 CONFIG_MSM_WFD=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 5d37dd0..2d97769 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -375,6 +375,8 @@
 CONFIG_MSM_CSI20_HEADER=y
 CONFIG_S5K3L1YX=y
 CONFIG_IMX091=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
 CONFIG_MSM_WFD=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 71b6990..a5a9620 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -304,12 +304,9 @@
 CONFIG_VIDEOBUF2_MSM_MEM=y
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_MSM_CAMERA_V4L2=y
-CONFIG_MT9M114=y
-CONFIG_MSM_CAMERA_LED_TRIGGER_FLASH=y
-CONFIG_OV2720=y
+CONFIG_MSM_CAMERA=n
+CONFIG_MSMB_CAMERA=y
 CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_ACTUATOR=y
 CONFIG_MSM_JPEG=y
 CONFIG_MSM_CCI=y
 CONFIG_MSM_CSI30_HEADER=y
@@ -433,3 +430,5 @@
 CONFIG_CRC_CCITT=y
 CONFIG_SYNC=y
 CONFIG_SW_SYNC=y
+CONFIG_MOBICORE_SUPPORT=m
+CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 6770fe4..ef61e66 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -307,12 +307,9 @@
 CONFIG_VIDEOBUF2_MSM_MEM=y
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_MSM_CAMERA_V4L2=y
-CONFIG_MT9M114=y
-CONFIG_MSM_CAMERA_LED_TRIGGER_FLASH=y
-CONFIG_OV2720=y
+CONFIG_MSM_CAMERA=n
+CONFIG_MSMB_CAMERA=y
 CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_ACTUATOR=y
 CONFIG_MSM_JPEG=y
 CONFIG_MSM_CCI=y
 CONFIG_MSM_CSI30_HEADER=y
@@ -449,3 +446,5 @@
 CONFIG_CRC_CCITT=y
 CONFIG_SYNC=y
 CONFIG_SW_SYNC=y
+CONFIG_MOBICORE_SUPPORT=m
+CONFIG_MOBICORE_API=m
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 3f22221..8f958b7 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -378,8 +378,8 @@
 	select CPU_HAS_L2_PMU
 	select MSM_JTAG_MM if MSM_QDSS
 
-config ARCH_MSM8910
-	bool "MSM8910"
+config ARCH_MSM8610
+	bool "MSM8610"
 	select ARM_GIC
 	select GIC_SECURE
 	select ARCH_MSM_CORTEXMP
@@ -392,6 +392,7 @@
 	select MSM_GPIOMUX
 	select MSM_NATIVE_RESTART
 	select MSM_RESTART_V2
+	select QMI_ENCDEC
 
 config ARCH_MSM8226
 	bool "MSM8226"
@@ -410,6 +411,7 @@
 	select MSM_QDSP6_APRV2
 	select MSM_QDSP6V2_CODECS
 	select MSM_AUDIO_QDSP6V2 if SND_SOC
+	select QMI_ENCDEC
 endmenu
 
 choice
@@ -1001,7 +1003,7 @@
 	default "0x00000000" if ARCH_MSM8974
 	default "0x00000000" if ARCH_MPQ8092
 	default "0x00000000" if ARCH_MSM8226
-	default "0x00000000" if ARCH_MSM8910
+	default "0x00000000" if ARCH_MSM8610
 	default "0x10000000" if ARCH_FSM9XXX
 	default "0x00200000" if ARCH_MSM9625
 	default "0x00200000" if !MSM_STACKED_MEMORY
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index b69f397..23c35de 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -113,7 +113,7 @@
 ifndef CONFIG_ARCH_MSM8226
 ifndef CONFIG_ARCH_MSM9625
 ifndef CONFIG_ARCH_MPQ8092
-ifndef CONFIG_ARCH_MSM8910
+ifndef CONFIG_ARCH_MSM8610
 	obj-y += nand_partitions.o
 endif
 endif
@@ -290,15 +290,15 @@
 obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
 obj-$(CONFIG_ARCH_MSM9625) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8226) += gdsc.o
-obj-$(CONFIG_ARCH_MSM8910) += gdsc.o
+obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
 obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8910) += board-8910.o board-8910-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8910) += clock-local2.o clock-pll.o clock-8910.o clock-rpm.o clock-voter.o
+obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o
+obj-$(CONFIG_ARCH_MSM8610) += clock-local2.o clock-pll.o clock-8610.o clock-rpm.o clock-voter.o
 
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -356,7 +356,7 @@
 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_ARCH_MSM8910) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
 
 obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
 obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_mpdecision.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index e74d61a..377c4af 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -75,7 +75,7 @@
 # MPQ8092
    zreladdr-$(CONFIG_ARCH_MPQ8092)	:= 0x00008000
 
-# MSM8910
-   zreladdr-$(CONFIG_ARCH_MSM8910)	:= 0x00008000
-        dtb-$(CONFIG_ARCH_MSM8910)	+= msm8910-rumi.dtb
-        dtb-$(CONFIG_ARCH_MSM8910)	+= msm8910-sim.dtb
+# MSM8610
+   zreladdr-$(CONFIG_ARCH_MSM8610)	:= 0x00008000
+        dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-rumi.dtb
+        dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-sim.dtb
diff --git a/arch/arm/mach-msm/board-8064-bt.c b/arch/arm/mach-msm/board-8064-bt.c
index a8ae9fa..963b1a3 100644
--- a/arch/arm/mach-msm/board-8064-bt.c
+++ b/arch/arm/mach-msm/board-8064-bt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -121,7 +121,7 @@
 
 	const struct bahama_config_register *p;
 
-	u8 version;
+	int version;
 
 	const struct bahama_config_register v10_bt_on[] = {
 		{ 0xE9, 0x00, 0xFF },
@@ -203,7 +203,7 @@
 	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) {
+	if (version < 0 || version == BAHAMA_VER_UNSUPPORTED) {
 		dev_err(&msm_bt_power_device.dev,
 			"%s : Bahama version read Error, version = %d\n",
 			__func__, version);
@@ -237,10 +237,9 @@
 				__func__, (p+i)->reg,
 				value, (p+i)->mask);
 		value = 0;
-		rc = marimba_read_bit_mask(&config,
+		if (marimba_read_bit_mask(&config,
 				(p+i)->reg, &value,
-				sizeof((p+i)->value), (p+i)->mask);
-		if (rc < 0)
+				sizeof((p+i)->value), (p+i)->mask) < 0)
 			dev_err(&msm_bt_power_device.dev,
 				"%s marimba_read_bit_mask- error",
 				__func__);
@@ -298,15 +297,14 @@
 			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) {
+	if (on) {
+		while (i) {
 			i--;
 			regulator_disable(bt_vregs[i].reg);
 			regulator_put(bt_vregs[i].reg);
@@ -419,8 +417,9 @@
 	int rc = 0;
 	const char *id = "BTPW";
 	int cid = 0;
+	int bt_state = 0;
+	struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
 
-	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",
@@ -429,6 +428,7 @@
 	}
 
 	if (on) {
+		pr_debug("%s: Powering up the BT module.\n", __func__);
 		rc = bluetooth_switch_regulators(on);
 		if (rc < 0) {
 			pr_err("%s: bluetooth_switch_regulators rc = %d",
@@ -437,11 +437,13 @@
 		}
 		/* UART GPIO configuration to be done by by UART module*/
 		/*Setup BT clocks*/
+		pr_debug("%s: Voting for the 19.2MHz clock\n", __func__);
 		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);
+			goto fail_power;
 		}
 		rc = msm_xo_mode_vote(bt_clock, MSM_XO_MODE_ON);
 		if (rc < 0) {
@@ -451,20 +453,23 @@
 		msleep(20);
 
 		/*I2C config for Bahama*/
+		pr_debug("%s: BT Turn On sequence in-progress.\n", __func__);
 		rc = bahama_bt(1);
 		if (rc < 0) {
 			pr_err("%s: bahama_bt rc = %d", __func__, rc);
-			goto fail_i2c;
+			goto fail_xo_vote;
 		}
 		msleep(20);
 
 		/*setup BT PCM lines*/
+		pr_debug("%s: Configuring PCM lines.\n", __func__);
 		rc = config_pcm(BT_PCM_ON);
 		if (rc < 0) {
-			pr_err("%s: config_pcm , rc =%d\n",
+			pr_err("%s: config_pcm , rc = %d\n",
 				__func__, rc);
-				goto fail_power;
+			goto fail_i2c;
 		}
+		pr_debug("%s: BT Turn On complete.\n", __func__);
 		/* TO DO - Enable PIN CTRL */
 		/*
 		rc = msm_xo_mode_vote(bt_clock, MSM_XO_MODE_PIN_CTRL);
@@ -474,9 +479,12 @@
 			goto fail_xo_vote;
 		} */
 	} else {
-		rc = bahama_bt(0);
-		if (rc < 0)
-			pr_err("%s: bahama_bt rc = %d", __func__, rc);
+		pr_debug("%s: Turning BT Off.\n", __func__);
+		bt_state = marimba_get_bt_status(&config);
+		if (!bt_state) {
+			pr_err("%s: BT is already turned OFF.\n", __func__);
+			return 0;
+		}
 
 		rc = config_pcm(BT_PCM_OFF);
 		if (rc < 0) {
@@ -484,19 +492,21 @@
 				__func__, rc);
 		}
 fail_i2c:
-		pr_err("bluetooth_power...FAIL_I2C\n");
-
+		rc = bahama_bt(0);
+		if (rc < 0)
+			pr_err("%s: bahama_bt rc = %d", __func__, rc);
 fail_xo_vote:
-		pr_err("bluetooth_power...FAIL_XO_VOTE\n");
+		pr_debug("%s: Voting off the 19.2MHz clk\n", __func__);
 		msm_xo_put(bt_clock);
 fail_power:
-		pr_err("bluetooth_power...FAIL POWER\n");
+		pr_debug("%s: Switching off voltage regulators.\n", __func__);
 		rc = bluetooth_switch_regulators(0);
 		if (rc < 0) {
 			pr_err("%s: switch_regulators : rc = %d",\
 				__func__, rc);
 			goto exit;
 		}
+		pr_debug("%s: BT Power Off complete.\n", __func__);
 	}
 	return rc;
 exit:
diff --git a/arch/arm/mach-msm/board-8910-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
similarity index 86%
rename from arch/arm/mach-msm/board-8910-gpiomux.c
rename to arch/arm/mach-msm/board-8610-gpiomux.c
index a295a17..49d8236 100644
--- a/arch/arm/mach-msm/board-8910-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,7 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 
-void __init msm8910_init_gpiomux(void)
+void __init msm8610_init_gpiomux(void)
 {
 	int rc;
 
diff --git a/arch/arm/mach-msm/board-8910.c b/arch/arm/mach-msm/board-8610.c
similarity index 66%
rename from arch/arm/mach-msm/board-8910.c
rename to arch/arm/mach-msm/board-8610.c
index f779c1f..91d7863 100644
--- a/arch/arm/mach-msm/board-8910.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -44,7 +44,7 @@
 #include "clock.h"
 #include "platsmp.h"
 
-static struct memtype_reserve msm8910_reserve_table[] __initdata = {
+static struct memtype_reserve msm8610_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
 	},
 	[MEMTYPE_EBI0] = {
@@ -55,12 +55,12 @@
 	},
 };
 
-static int msm8910_paddr_to_memtype(unsigned int paddr)
+static int msm8610_paddr_to_memtype(unsigned int paddr)
 {
 	return MEMTYPE_EBI1;
 }
 
-static struct of_dev_auxdata msm8910_auxdata_lookup[] __initdata = {
+static struct of_dev_auxdata msm8610_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9824000, \
 			"msm_sdcc.1", NULL),
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
@@ -68,54 +68,54 @@
 	{}
 };
 
-static struct reserve_info msm8910_reserve_info __initdata = {
-	.memtype_reserve_table = msm8910_reserve_table,
-	.paddr_to_memtype = msm8910_paddr_to_memtype,
+static struct reserve_info msm8610_reserve_info __initdata = {
+	.memtype_reserve_table = msm8610_reserve_table,
+	.paddr_to_memtype = msm8610_paddr_to_memtype,
 };
 
-static void __init msm8910_early_memory(void)
+static void __init msm8610_early_memory(void)
 {
-	reserve_info = &msm8910_reserve_info;
-	of_scan_flat_dt(dt_scan_for_memory_reserve, msm8910_reserve_table);
+	reserve_info = &msm8610_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msm8610_reserve_table);
 }
 
-static void __init msm8910_reserve(void)
+static void __init msm8610_reserve(void)
 {
 	msm_reserve();
 }
 
-void __init msm8910_init(void)
+void __init msm8610_init(void)
 {
-	struct of_dev_auxdata *adata = msm8910_auxdata_lookup;
+	struct of_dev_auxdata *adata = msm8610_auxdata_lookup;
 	struct device *parent;
 
 	parent = socinfo_init();
 	if (IS_ERR_OR_NULL(parent))
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
-	msm8910_init_gpiomux();
+	msm8610_init_gpiomux();
 
-	if (machine_is_msm8910_rumi())
-		msm_clock_init(&msm8910_rumi_clock_init_data);
+	if (machine_is_msm8610_rumi())
+		msm_clock_init(&msm8610_rumi_clock_init_data);
 	else
-		msm_clock_init(&msm8910_clock_init_data);
+		msm_clock_init(&msm8610_clock_init_data);
 	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
 }
 
-static const char *msm8910_dt_match[] __initconst = {
-	"qcom,msm8910",
+static const char *msm8610_dt_match[] __initconst = {
+	"qcom,msm8610",
 	NULL
 };
 
-DT_MACHINE_START(MSM8910_DT, "Qualcomm MSM 8910 (Flattened Device Tree)")
-	.map_io = msm_map_msm8910_io,
+DT_MACHINE_START(MSM8610_DT, "Qualcomm MSM 8610 (Flattened Device Tree)")
+	.map_io = msm_map_msm8610_io,
 	.init_irq = msm_dt_init_irq_nompm,
-	.init_machine = msm8910_init,
+	.init_machine = msm8610_init,
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_dt_timer,
-	.dt_compat = msm8910_dt_match,
+	.dt_compat = msm8610_dt_match,
 	.restart = msm_restart,
-	.reserve = msm8910_reserve,
-	.init_very_early = msm8910_early_memory,
+	.reserve = msm8610_reserve,
+	.init_very_early = msm8610_early_memory,
 	.smp = &arm_smp_ops,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index f4e7880..f6b62f9 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1438,26 +1438,49 @@
 
 static struct resource tspp_resources[] = {
 	[0] = {
+		.name = "TSIF_TSPP_IRQ",
 		.flags = IORESOURCE_IRQ,
 		.start = TSIF_TSPP_IRQ,
-		.end   = TSIF1_IRQ,
+		.end   = TSIF_TSPP_IRQ,
 	},
 	[1] = {
+		.name = "TSIF0_IRQ",
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF1_IRQ,
+		.end   = TSIF1_IRQ,
+	},
+	[2] = {
+		.name = "TSIF1_IRQ",
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF2_IRQ,
+		.end   = TSIF2_IRQ,
+	},
+	[3] = {
+		.name = "TSIF_BAM_IRQ",
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF_BAM_IRQ,
+		.end   = TSIF_BAM_IRQ,
+	},
+	[4] = {
+		.name = "MSM_TSIF0_PHYS",
 		.flags = IORESOURCE_MEM,
 		.start = MSM_TSIF0_PHYS,
 		.end   = MSM_TSIF0_PHYS + MSM_TSIF_SIZE - 1,
 	},
-	[2] = {
+	[5] = {
+		.name = "MSM_TSIF1_PHYS",
 		.flags = IORESOURCE_MEM,
 		.start = MSM_TSIF1_PHYS,
 		.end   = MSM_TSIF1_PHYS + MSM_TSIF_SIZE - 1,
 	},
-	[3] = {
+	[6] = {
+		.name = "MSM_TSPP_PHYS",
 		.flags = IORESOURCE_MEM,
 		.start = MSM_TSPP_PHYS,
 		.end   = MSM_TSPP_PHYS + MSM_TSPP_SIZE - 1,
 	},
-	[4] = {
+	[7] = {
+		.name = "MSM_TSPP_BAM_PHYS",
 		.flags = IORESOURCE_MEM,
 		.start = MSM_TSPP_BAM_PHYS,
 		.end   = MSM_TSPP_BAM_PHYS + MSM_TSPP_BAM_SIZE - 1,
diff --git a/arch/arm/mach-msm/clock-8910.c b/arch/arm/mach-msm/clock-8610.c
similarity index 98%
rename from arch/arm/mach-msm/clock-8910.c
rename to arch/arm/mach-msm/clock-8610.c
index c5541b4..30229e1 100644
--- a/arch/arm/mach-msm/clock-8910.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2921,7 +2921,7 @@
 	.multiplier = 1,
 };
 
-static struct clk_lookup msm_clocks_8910[] = {
+static struct clk_lookup msm_clocks_8610[] = {
 	CLK_LOOKUP("xo",	gcc_xo_clk_src.c, "msm_otg"),
 	CLK_LOOKUP("xo",	gcc_xo_clk_src.c, "fe200000.qcom,lpass"),
 	CLK_LOOKUP("xo",	gcc_xo_clk_src.c, "pil-q6v5-mss"),
@@ -3157,7 +3157,7 @@
 	CLK_LOOKUP("reg_clk",        q6ss_ahbm_clk.c,  "fe200000.qcom,lpass"),
 };
 
-static struct clk_lookup msm_clocks_8910_rumi[] = {
+static struct clk_lookup msm_clocks_8610_rumi[] = {
 	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
 	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
 	CLK_DUMMY("iface_clk",  HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
@@ -3183,9 +3183,9 @@
 	CLK_DUMMY("core_clk",   NULL, "fd010000.qcom,iommu", OFF),
 };
 
-struct clock_init_data msm8910_rumi_clock_init_data __initdata = {
-	.table = msm_clocks_8910_rumi,
-	.size = ARRAY_SIZE(msm_clocks_8910_rumi),
+struct clock_init_data msm8610_rumi_clock_init_data __initdata = {
+	.table = msm_clocks_8610_rumi,
+	.size = ARRAY_SIZE(msm_clocks_8610_rumi),
 };
 
 static struct pll_config_regs gpll0_regs __initdata = {
@@ -3346,7 +3346,7 @@
 	WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
 }
 
-static void __init msm8910_clock_post_init(void)
+static void __init msm8610_clock_post_init(void)
 {
 	/*
 	 * Hold an active set vote for CXO; this is because CXO is expected
@@ -3377,29 +3377,29 @@
 #define APCS_GCC_CC_PHYS	0xF9011000
 #define APCS_GCC_CC_SIZE	SZ_4K
 
-static void __init msm8910_clock_pre_init(void)
+static void __init msm8610_clock_pre_init(void)
 {
 	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
 	if (!virt_bases[GCC_BASE])
-		panic("clock-8910: Unable to ioremap GCC memory!");
+		panic("clock-8610: Unable to ioremap GCC memory!");
 
 	virt_bases[MMSS_BASE] = ioremap(MMSS_CC_PHYS, MMSS_CC_SIZE);
 	if (!virt_bases[MMSS_BASE])
-		panic("clock-8910: Unable to ioremap MMSS_CC memory!");
+		panic("clock-8610: Unable to ioremap MMSS_CC memory!");
 
 	virt_bases[LPASS_BASE] = ioremap(LPASS_CC_PHYS, LPASS_CC_SIZE);
 	if (!virt_bases[LPASS_BASE])
-		panic("clock-8910: Unable to ioremap LPASS_CC memory!");
+		panic("clock-8610: Unable to ioremap LPASS_CC memory!");
 
 	virt_bases[APCS_BASE] = ioremap(APCS_GCC_CC_PHYS, APCS_GCC_CC_SIZE);
 	if (!virt_bases[APCS_BASE])
-		panic("clock-8910: Unable to ioremap APCS_GCC_CC memory!");
+		panic("clock-8610: Unable to ioremap APCS_GCC_CC memory!");
 
 	clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
 
 	vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
 	if (IS_ERR(vdd_dig_reg))
-		panic("clock-8910: Unable to get the vdd_dig regulator!");
+		panic("clock-8610: Unable to get the vdd_dig regulator!");
 
 	/*
 	 * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
@@ -3429,15 +3429,15 @@
 	clk_prepare_enable(&audio_core_ixfabric_clk.c);
 }
 
-static int __init msm8910_clock_late_init(void)
+static int __init msm8610_clock_late_init(void)
 {
 	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
 }
 
-struct clock_init_data msm8910_clock_init_data __initdata = {
-	.table = msm_clocks_8910,
-	.size = ARRAY_SIZE(msm_clocks_8910),
-	.pre_init = msm8910_clock_pre_init,
-	.post_init = msm8910_clock_post_init,
-	.late_init = msm8910_clock_late_init,
+struct clock_init_data msm8610_clock_init_data __initdata = {
+	.table = msm_clocks_8610,
+	.size = ARRAY_SIZE(msm_clocks_8610),
+	.pre_init = msm8610_clock_pre_init,
+	.post_init = msm8610_clock_post_init,
+	.late_init = msm8610_clock_late_init,
 };
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 389ac62..eb16eae 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -770,6 +770,8 @@
 		.dbg_name = "mmpll1_clk_src",
 		.rate = 846000000,
 		.ops = &clk_ops_pll_vote,
+		/* May be reassigned at runtime; alloc memory at compile time */
+		VDD_DIG_FMAX_MAP1(LOW, 846000000),
 		CLK_INIT(mmpll1_clk_src.c),
 	},
 };
@@ -781,7 +783,7 @@
 	.c = {
 		.parent = &cxo_clk_src.c,
 		.dbg_name = "mmpll3_clk_src",
-		.rate = 1000000000,
+		.rate = 820000000,
 		.ops = &clk_ops_local_pll,
 		CLK_INIT(mmpll3_clk_src.c),
 	},
@@ -2393,6 +2395,19 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_mmss_axi_v2_clk[] = {
+	F_MM( 19200000,    cxo,     1,   0,   0),
+	F_MM( 37500000,  gpll0,    16,   0,   0),
+	F_MM( 50000000,  gpll0,    12,   0,   0),
+	F_MM( 75000000,  gpll0,     8,   0,   0),
+	F_MM(100000000,  gpll0,     6,   0,   0),
+	F_MM(150000000,  gpll0,     4,   0,   0),
+	F_MM(333430000, mmpll1,   3.5,   0,   0),
+	F_MM(400000000, mmpll0,     2,   0,   0),
+	F_MM(466800000, mmpll1,   2.5,   0,   0),
+	F_END
+};
+
 static struct rcg_clk axi_clk_src = {
 	.cmd_rcgr_reg = 0x5040,
 	.set_rate = set_rate_hid,
@@ -2420,6 +2435,18 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_ocmemnoc_v2_clk[] = {
+	F_MM( 19200000,    cxo,   1,   0,   0),
+	F_MM( 37500000,  gpll0,  16,   0,   0),
+	F_MM( 50000000,  gpll0,  12,   0,   0),
+	F_MM( 75000000,  gpll0,   8,   0,   0),
+	F_MM(100000000,  gpll0,   6,   0,   0),
+	F_MM(150000000,  gpll0,   4,   0,   0),
+	F_MM(333430000, mmpll1, 3.5,   0,   0),
+	F_MM(400000000, mmpll0,   2,   0,   0),
+	F_END
+};
+
 struct rcg_clk ocmemnoc_clk_src = {
 	.cmd_rcgr_reg = OCMEMNOC_CMD_RCGR,
 	.set_rate = set_rate_hid,
@@ -3183,6 +3210,16 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_venus0_vcodec0_v2_clk[] = {
+	F_MM( 50000000,  gpll0,  12,   0,   0),
+	F_MM(100000000,  gpll0,   6,   0,   0),
+	F_MM(133330000, mmpll0,   6,   0,   0),
+	F_MM(200000000, mmpll0,   4,   0,   0),
+	F_MM(266670000, mmpll0,   3,   0,   0),
+	F_MM(465000000, mmpll3,   2,   0,   0),
+	F_END
+};
+
 static struct rcg_clk vcodec0_clk_src = {
 	.cmd_rcgr_reg = VCODEC0_CMD_RCGR,
 	.set_rate = set_rate_mnd,
@@ -5057,6 +5094,7 @@
 	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9967000.i2c"),
 	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9966000.spi"),
 	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f995e000.serial"),
+	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f995d000.uart"),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup1_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup1_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup2_i2c_apps_clk.c, ""),
@@ -5069,7 +5107,7 @@
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup5_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup6_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup6_spi_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp2_uart1_apps_clk.c, ""),
+	CLK_LOOKUP("core_clk", gcc_blsp2_uart1_apps_clk.c, "f995d000.uart"),
 	CLK_LOOKUP("core_clk", gcc_blsp2_uart2_apps_clk.c, "f995e000.serial"),
 	CLK_LOOKUP("core_clk", gcc_blsp2_uart3_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_uart4_apps_clk.c, ""),
@@ -5116,8 +5154,8 @@
 	CLK_LOOKUP("iface_clk", gcc_sdcc4_ahb_clk.c, "msm_sdcc.4"),
 	CLK_LOOKUP("core_clk", gcc_sdcc4_apps_clk.c, "msm_sdcc.4"),
 
-	CLK_LOOKUP("iface_clk", gcc_tsif_ahb_clk.c, ""),
-	CLK_LOOKUP("ref_clk", gcc_tsif_ref_clk.c, ""),
+	CLK_LOOKUP("iface_clk", gcc_tsif_ahb_clk.c, "f99d8000.msm_tspp"),
+	CLK_LOOKUP("ref_clk", gcc_tsif_ref_clk.c, "f99d8000.msm_tspp"),
 
 	CLK_LOOKUP("mem_clk", gcc_usb30_master_clk.c,           "usb_bam"),
 	CLK_LOOKUP("mem_iface_clk", gcc_sys_noc_usb3_axi_clk.c, "usb_bam"),
@@ -5182,18 +5220,24 @@
 	CLK_LOOKUP("cci_src_clk", cci_clk_src.c, "fda0c000.qcom,cci"),
 	CLK_LOOKUP("cci_clk", camss_cci_cci_clk.c, "fda0c000.qcom,cci"),
 	/* CSIPHY clocks */
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda0ac00.qcom,csiphy"),
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
 		"fda0ac00.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_src_clk", csi0phytimer_clk_src.c,
 		"fda0ac00.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_clk", camss_phy0_csi0phytimer_clk.c,
 		"fda0ac00.qcom,csiphy"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda0b000.qcom,csiphy"),
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
 		"fda0b000.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_src_clk", csi1phytimer_clk_src.c,
 		"fda0b000.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_clk", camss_phy1_csi1phytimer_clk.c,
 		"fda0b000.qcom,csiphy"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda0b400.qcom,csiphy"),
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
 		"fda0b400.qcom,csiphy"),
 	CLK_LOOKUP("csiphy_timer_src_clk", csi2phytimer_clk_src.c,
@@ -5201,6 +5245,10 @@
 	CLK_LOOKUP("csiphy_timer_clk", camss_phy2_csi2phytimer_clk.c,
 		"fda0b400.qcom,csiphy"),
 	/* CSID clocks */
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda08000.qcom,csid"),
+	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+		"fda08000.qcom,csid"),
 	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08000.qcom,csid"),
 	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c, "fda08000.qcom,csid"),
 	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c, "fda08000.qcom,csid"),
@@ -5208,6 +5256,10 @@
 	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c, "fda08000.qcom,csid"),
 	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda08000.qcom,csid"),
 
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda08400.qcom,csid"),
+	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+		"fda08400.qcom,csid"),
 	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08400.qcom,csid"),
 	CLK_LOOKUP("csi1_ahb_clk", camss_csi1_ahb_clk.c, "fda08400.qcom,csid"),
 	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c, "fda08400.qcom,csid"),
@@ -5221,6 +5273,10 @@
 	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("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda08800.qcom,csid"),
+	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+		"fda08800.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"),
@@ -5234,6 +5290,10 @@
 	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("camss_top_ahb_clk", camss_top_ahb_clk.c,
+		"fda08c00.qcom,csid"),
+	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+		"fda08c00.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"),
@@ -5247,6 +5307,16 @@
 	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c, "fda08c00.qcom,csid"),
 	CLK_LOOKUP("csi3_rdi_clk", camss_csi3rdi_clk.c, "fda08c00.qcom,csid"),
 
+	/* ISPIF clocks */
+	CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
+		"fda0a000.qcom,ispif"),
+	CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe0_clk.c,
+		"fda0a000.qcom,ispif"),
+	CLK_LOOKUP("camss_vfe_vfe_clk1", camss_vfe_vfe1_clk.c,
+		"fda0a000.qcom,ispif"),
+	CLK_LOOKUP("camss_csi_vfe_clk1", camss_csi_vfe1_clk.c,
+		"fda0a000.qcom,ispif"),
+
 	/*VFE clocks*/
 	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
 					"fda10000.qcom,vfe"),
@@ -5499,7 +5569,7 @@
 	.base = &virt_bases[MMSS_BASE],
 };
 
-/* MMPLL1 at 1000 MHz, main output enabled. */
+/* MMPLL1 at 846 MHz, main output enabled. */
 static struct pll_config mmpll1_config __initdata = {
 	.l = 0x2C,
 	.m = 0x1,
@@ -5516,6 +5586,23 @@
 	.main_output_mask = BIT(0),
 };
 
+/* MMPLL1 at 1167 MHz, main output enabled. */
+static struct pll_config mmpll1_v2_config __initdata = {
+	.l = 60,
+	.m = 25,
+	.n = 32,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
 static struct pll_config_regs mmpll3_regs __initdata = {
 	.l_reg = (void __iomem *)MMPLL3_L_REG,
 	.m_reg = (void __iomem *)MMPLL3_M_REG,
@@ -5542,6 +5629,23 @@
 	.main_output_mask = BIT(0),
 };
 
+/* MMPLL3 at 930 MHz, main output enabled. */
+static struct pll_config mmpll3_v2_config __initdata = {
+	.l = 48,
+	.m = 7,
+	.n = 16,
+	.vco_val = 0x0,
+	.vco_mask = BM(21, 20),
+	.pre_div_val = 0x0,
+	.pre_div_mask = BM(14, 12),
+	.post_div_val = 0x0,
+	.post_div_mask = BM(9, 8),
+	.mn_ena_val = BIT(24),
+	.mn_ena_mask = BIT(24),
+	.main_output_val = BIT(0),
+	.main_output_mask = BIT(0),
+};
+
 static struct pll_config_regs lpapll0_regs __initdata = {
 	.l_reg = (void __iomem *)LPAPLL_L_REG,
 	.m_reg = (void __iomem *)LPAPLL_M_REG,
@@ -5588,8 +5692,14 @@
 	int ret;
 
 	configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
-	configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
-	configure_sr_hpm_lp_pll(&mmpll3_config, &mmpll3_regs, 0);
+
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+		configure_sr_hpm_lp_pll(&mmpll1_v2_config, &mmpll1_regs, 1);
+		configure_sr_hpm_lp_pll(&mmpll3_v2_config, &mmpll3_regs, 0);
+	} else {
+		configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
+		configure_sr_hpm_lp_pll(&mmpll3_config, &mmpll3_regs, 0);
+	}
 	configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
 
 	/* Vote for GPLL0 to turn on. Needed by acpuclock. */
@@ -5645,8 +5755,13 @@
 
 static void __init msm8974_clock_post_init(void)
 {
-	clk_set_rate(&axi_clk_src.c, 282000000);
-	clk_set_rate(&ocmemnoc_clk_src.c, 282000000);
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+		clk_set_rate(&axi_clk_src.c, 333430000);
+		clk_set_rate(&ocmemnoc_clk_src.c, 333430000);
+	} else {
+		clk_set_rate(&axi_clk_src.c, 282000000);
+		clk_set_rate(&ocmemnoc_clk_src.c, 282000000);
+	}
 
 	/*
 	 * Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
@@ -5752,6 +5867,25 @@
 	enable_rpm_scaling();
 
 	reg_init();
+
+	/* v2 specific changes */
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+		mmpll3_clk_src.c.rate =  930000000;
+		mmpll1_clk_src.c.rate = 1167000000;
+		mmpll1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 1167000000;
+
+		ocmemnoc_clk_src.freq_tbl = ftbl_ocmemnoc_v2_clk;
+		ocmemnoc_clk_src.c.fmax[VDD_DIG_NOMINAL] = 333430000;
+
+		axi_clk_src.freq_tbl = ftbl_mmss_axi_v2_clk;
+		axi_clk_src.c.fmax[VDD_DIG_NOMINAL] = 333430000;
+		axi_clk_src.c.fmax[VDD_DIG_HIGH] = 466800000;
+
+		vcodec0_clk_src.freq_tbl = ftbl_venus0_vcodec0_v2_clk;
+		vcodec0_clk_src.c.fmax[VDD_DIG_HIGH] = 465000000;
+
+		mdp_clk_src.c.fmax[VDD_DIG_NOMINAL] = 240000000;
+	}
 }
 
 static int __init msm8974_clock_late_init(void)
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 181cf4c..002ee96 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -49,8 +49,8 @@
 extern struct clock_init_data msm8930_pm8917_clock_init_data;
 extern struct clock_init_data msm8974_clock_init_data;
 extern struct clock_init_data msm8974_rumi_clock_init_data;
-extern struct clock_init_data msm8910_clock_init_data;
-extern struct clock_init_data msm8910_rumi_clock_init_data;
+extern struct clock_init_data msm8610_clock_init_data;
+extern struct clock_init_data msm8610_rumi_clock_init_data;
 
 int msm_clock_init(struct clock_init_data *data);
 int find_vdd_level(struct clk *clk, unsigned long rate);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 67485dc..c986064 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -754,26 +754,49 @@
 
 static struct resource tspp_resources[] = {
 	[0] = {
+		.name = "TSIF_TSPP_IRQ",
 		.flags = IORESOURCE_IRQ,
 		.start = TSIF_TSPP_IRQ,
-		.end   = TSIF1_IRQ,
+		.end   = TSIF_TSPP_IRQ,
 	},
 	[1] = {
+		.name = "TSIF0_IRQ",
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF1_IRQ,
+		.end   = TSIF1_IRQ,
+	},
+	[2] = {
+		.name = "TSIF1_IRQ",
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF2_IRQ,
+		.end   = TSIF2_IRQ,
+	},
+	[3] = {
+		.name = "TSIF_BAM_IRQ",
+		.flags = IORESOURCE_IRQ,
+		.start = TSIF_BAM_IRQ,
+		.end   = TSIF_BAM_IRQ,
+	},
+	[4] = {
+		.name = "MSM_TSIF0_PHYS",
 		.flags = IORESOURCE_MEM,
 		.start = MSM_TSIF0_PHYS,
 		.end   = MSM_TSIF0_PHYS + MSM_TSIF_SIZE - 1,
 	},
-	[2] = {
+	[5] = {
+		.name = "MSM_TSIF1_PHYS",
 		.flags = IORESOURCE_MEM,
 		.start = MSM_TSIF1_PHYS,
 		.end   = MSM_TSIF1_PHYS + MSM_TSIF_SIZE - 1,
 	},
-	[3] = {
+	[6] = {
+		.name = "MSM_TSPP_PHYS",
 		.flags = IORESOURCE_MEM,
 		.start = MSM_TSPP_PHYS,
 		.end   = MSM_TSPP_PHYS + MSM_TSPP_SIZE - 1,
 	},
-	[4] = {
+	[7] = {
+		.name = "MSM_TSPP_BAM_PHYS",
 		.flags = IORESOURCE_MEM,
 		.start = MSM_TSPP_BAM_PHYS,
 		.end   = MSM_TSPP_BAM_PHYS + MSM_TSPP_BAM_SIZE - 1,
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 8b5c70f..56c78c6 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/include/mach/board.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -182,9 +182,8 @@
 	uint32_t delay;
 };
 
-struct msm_camera_csi_lane_params {
-	uint16_t csi_lane_assign;
-	uint16_t csi_lane_mask;
+struct msm_camera_gpio_num_info {
+	uint16_t gpio_num[2];
 };
 
 struct msm_camera_gpio_conf {
@@ -201,6 +200,7 @@
 	uint8_t camera_off_table_size;
 	uint32_t *camera_on_table;
 	uint8_t camera_on_table_size;
+	struct msm_camera_gpio_num_info *gpio_num_info;
 };
 
 enum msm_camera_i2c_mux_mode {
@@ -215,13 +215,6 @@
 	enum msm_camera_i2c_mux_mode i2c_mux_mode;
 };
 
-enum msm_camera_vreg_name_t {
-	CAM_VDIG,
-	CAM_VIO,
-	CAM_VANA,
-	CAM_VAF,
-};
-
 struct msm_camera_sensor_platform_info {
 	int mount_angle;
 	int sensor_reset;
@@ -595,9 +588,9 @@
 void msm_map_msm8226_io(void);
 void msm8226_init_irq(void);
 void msm8226_init_gpiomux(void);
-void msm8910_init_gpiomux(void);
-void msm_map_msm8910_io(void);
-void msm8910_init_irq(void);
+void msm8610_init_gpiomux(void);
+void msm_map_msm8610_io(void);
+void msm8610_init_irq(void);
 
 /* Dump debug info (states, rate, etc) of clocks */
 #if defined(CONFIG_ARCH_MSM7X27)
diff --git a/arch/arm/mach-msm/include/mach/camera2.h b/arch/arm/mach-msm/include/mach/camera2.h
new file mode 100644
index 0000000..e624131
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/camera2.h
@@ -0,0 +1,91 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __CAMERA2_H__
+#define __CAMERA2_H__
+
+#include <media/msm_cam_sensor.h>
+#include <mach/board.h>
+
+enum msm_sensor_device_type_t {
+	MSM_SENSOR_I2C_DEVICE,
+	MSM_SENSOR_PLATFORM_DEVICE,
+};
+
+enum msm_bus_perf_setting {
+	S_INIT,
+	S_PREVIEW,
+	S_VIDEO,
+	S_CAPTURE,
+	S_ZSL,
+	S_STEREO_VIDEO,
+	S_STEREO_CAPTURE,
+	S_DEFAULT,
+	S_LIVESHOT,
+	S_DUAL,
+	S_EXIT
+};
+
+struct msm_camera_slave_info {
+	uint16_t sensor_slave_addr;
+	uint16_t sensor_id_reg_addr;
+	uint16_t sensor_id;
+};
+
+struct msm_cam_clk_info {
+	const char *clk_name;
+	long clk_rate;
+	uint32_t delay;
+};
+
+struct msm_cam_clk_setting {
+	struct msm_cam_clk_info *clk_info;
+	uint16_t num_clk_info;
+	uint8_t enable;
+};
+
+struct v4l2_subdev_info {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
+	uint16_t fmt;
+	uint16_t order;
+};
+
+struct msm_camera_sensor_board_info {
+	const char *sensor_name;
+	struct msm_camera_slave_info *slave_info;
+	struct msm_camera_csi_lane_params *csi_lane_params;
+	struct camera_vreg_t *cam_vreg;
+	int num_vreg;
+	struct msm_camera_sensor_strobe_flash_data *strobe_flash_data;
+	struct msm_camera_gpio_conf *gpio_conf;
+	struct msm_actuator_info *actuator_info;
+	struct msm_camera_i2c_conf *i2c_conf;
+	struct msm_sensor_info_t *sensor_info;
+	struct msm_sensor_init_params *sensor_init_params;
+};
+
+enum msm_camera_i2c_cmd_type {
+	MSM_CAMERA_I2C_CMD_WRITE,
+	MSM_CAMERA_I2C_CMD_POLL,
+};
+
+struct msm_camera_i2c_reg_conf {
+	uint16_t reg_addr;
+	uint16_t reg_data;
+	enum msm_camera_i2c_data_type dt;
+	enum msm_camera_i2c_cmd_type cmd_type;
+	int16_t mask;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 9e2c24e..bbf3153 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -119,6 +119,8 @@
 
 void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
 void msm_iommu_remove_drv(struct msm_iommu_drvdata *drv);
+void program_iommu_bfb_settings(void __iomem *base,
+			const struct msm_iommu_bfb_settings *bfb_settings);
 
 /**
  * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 6955c80..65d5d02 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -108,7 +108,7 @@
 #define NR_QPNP_IRQS 32768
 #define NR_BOARD_IRQS NR_QPNP_IRQS
 
-#elif defined(CONFIG_ARCH_MSM8910) || defined(CONFIG_ARCH_MSM8226)
+#elif defined(CONFIG_ARCH_MSM8610) || defined(CONFIG_ARCH_MSM8226)
 #define NR_MSM_IRQS 256
 #define NR_GPIO_IRQS 117
 #define NR_QPNP_IRQS 32768
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8910.h b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
similarity index 61%
rename from arch/arm/mach-msm/include/mach/msm_iomap-8910.h
rename to arch/arm/mach-msm/include/mach/msm_iomap-8610.h
index 64990da..05544af 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8910.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -10,8 +10,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef __ASM_ARCH_MSM_IOMAP_8910_H
-#define __ASM_ARCH_MSM_IOMAP_8910_H
+#ifndef __ASM_ARCH_MSM_IOMAP_8610_H
+#define __ASM_ARCH_MSM_IOMAP_8610_H
 
 /* Physical base address and size of peripherals.
  * Ordered by the virtual base addresses they will be mapped at.
@@ -22,21 +22,21 @@
  *
  */
 
-#define MSM8910_MSM_SHARED_RAM_PHYS	0x0D600000
+#define MSM8610_MSM_SHARED_RAM_PHYS	0x0D600000
 
-#define MSM8910_APCS_GCC_PHYS	0xF9011000
-#define MSM8910_APCS_GCC_SIZE	SZ_4K
+#define MSM8610_APCS_GCC_PHYS	0xF9011000
+#define MSM8610_APCS_GCC_SIZE	SZ_4K
 
-#define MSM8910_TLMM_PHYS	0xFD510000
-#define MSM8910_TLMM_SIZE	SZ_16K
+#define MSM8610_TLMM_PHYS	0xFD510000
+#define MSM8610_TLMM_SIZE	SZ_16K
 
-#define MSM8910_IMEM_PHYS	0xFE805000
-#define MSM8910_IMEM_SIZE	SZ_4K
+#define MSM8610_IMEM_PHYS	0xFE805000
+#define MSM8610_IMEM_SIZE	SZ_4K
 
-#define MSM8910_MPM2_PSHOLD_PHYS	0xFC4AB000
-#define MSM8910_MPM2_PSHOLD_SIZE	SZ_4K
+#define MSM8610_MPM2_PSHOLD_PHYS	0xFC4AB000
+#define MSM8610_MPM2_PSHOLD_SIZE	SZ_4K
 
-#ifdef CONFIG_DEBUG_MSM8910_UART
+#ifdef CONFIG_DEBUG_MSM8610_UART
 #define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
 #define MSM_DEBUG_UART_PHYS	0xF991E000
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index f372b1e..8c49539 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -54,7 +54,7 @@
 	defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
 	defined(CONFIG_ARCH_MSM8625) || defined(CONFIG_ARCH_MSM7X30) || \
 	defined(CONFIG_ARCH_MSM9625) || defined(CONFIG_ARCH_MPQ8092) || \
-	defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8910)
+	defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8610)
 
 /* Unified iomap */
 
@@ -122,7 +122,7 @@
 #include "msm_iomap-9625.h"
 #include "msm_iomap-8092.h"
 #include "msm_iomap-8226.h"
-#include "msm_iomap-8910.h"
+#include "msm_iomap-8610.h"
 
 #else
 /* Legacy single-target iomap */
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
index b830134..31dd582 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,13 +14,8 @@
 #define _AUDIO_ACDB_H
 
 #include <linux/msm_audio_acdb.h>
-#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM9625) \
-	|| defined(CONFIG_ARCH_MSM8226)
-
-#include <sound/q6adm-v2.h>
-#else
 #include <sound/q6adm.h>
-#endif
+
 enum {
 	RX_CAL,
 	TX_CAL,
@@ -62,14 +57,11 @@
 void get_all_vocproc_cal(struct acdb_cal_block *cal_block);
 void get_all_vocstrm_cal(struct acdb_cal_block *cal_block);
 void get_all_vocvol_cal(struct acdb_cal_block *cal_block);
-void get_voice_col_data(uint32_t vocproc_type,
-	struct acdb_cal_block *cal_block);
 void get_anc_cal(struct acdb_cal_block *cal_block);
 void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block);
 void get_vocproc_cal(struct acdb_cal_data *cal_data);
 void get_vocstrm_cal(struct acdb_cal_data *cal_data);
 void get_vocvol_cal(struct acdb_cal_data *cal_data);
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 345f09c..b0fe4ba 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -56,14 +56,14 @@
 	of_machine_is_compatible("qcom,msm8226-sim")
 #define machine_is_msm8226_rumi()		\
 	of_machine_is_compatible("qcom,msm8226-rumi")
-#define early_machine_is_msm8910()	\
-	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8910")
-#define machine_is_msm8910()		\
-	of_machine_is_compatible("qcom,msm8910")
-#define machine_is_msm8910_sim()		\
-	of_machine_is_compatible("qcom,msm8910-sim")
-#define machine_is_msm8910_rumi()		\
-	of_machine_is_compatible("qcom,msm8910-rumi")
+#define early_machine_is_msm8610()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8610")
+#define machine_is_msm8610()		\
+	of_machine_is_compatible("qcom,msm8610")
+#define machine_is_msm8610_sim()		\
+	of_machine_is_compatible("qcom,msm8610-sim")
+#define machine_is_msm8610_rumi()		\
+	of_machine_is_compatible("qcom,msm8610-rumi")
 #else
 #define early_machine_is_msm8974()	0
 #define machine_is_msm8974()		0
@@ -77,10 +77,10 @@
 #define machine_is_msm8226()		0
 #define machine_is_msm8226_sim()	0
 #define machine_is_msm8226_rumi()	0
-#define early_machine_is_msm8910()	0
-#define machine_is_msm8910()		0
-#define machine_is_msm8910_sim()	0
-#define machine_is_msm8910_rumi()	0
+#define early_machine_is_msm8610()	0
+#define machine_is_msm8610()		0
+#define machine_is_msm8610_sim()	0
+#define machine_is_msm8610_rumi()	0
 
 #endif
 
@@ -116,7 +116,7 @@
 	MSM_CPU_9625,
 	MSM_CPU_8092,
 	MSM_CPU_8226,
-	MSM_CPU_8910,
+	MSM_CPU_8610,
 	MSM_CPU_8625Q,
 };
 
@@ -442,13 +442,13 @@
 #endif
 }
 
-static inline int cpu_is_msm8910(void)
+static inline int cpu_is_msm8610(void)
 {
-#ifdef CONFIG_ARCH_MSM8910
+#ifdef CONFIG_ARCH_MSM8610
 	enum msm_cpu cpu = socinfo_get_msm_cpu();
 
 	BUG_ON(cpu == MSM_CPU_UNKNOWN);
-	return cpu == MSM_CPU_8910;
+	return cpu == MSM_CPU_8610;
 #else
 	return 0;
 #endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index cd70ae9..013b4b2 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -3,7 +3,7 @@
  * MSM7K, QSD io support
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -538,12 +538,12 @@
 }
 #endif /* CONFIG_ARCH_MSM8226 */
 
-#ifdef CONFIG_ARCH_MSM8910
-static struct map_desc msm8910_io_desc[] __initdata = {
-	MSM_CHIP_DEVICE(APCS_GCC, MSM8910),
-	MSM_CHIP_DEVICE(TLMM, MSM8910),
-	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8910),
-	MSM_CHIP_DEVICE(IMEM, MSM8910),
+#ifdef CONFIG_ARCH_MSM8610
+static struct map_desc msm8610_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(APCS_GCC, MSM8610),
+	MSM_CHIP_DEVICE(TLMM, MSM8610),
+	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8610),
+	MSM_CHIP_DEVICE(IMEM, MSM8610),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
 		.length =   MSM_SHARED_RAM_SIZE,
@@ -551,9 +551,9 @@
 	},
 };
 
-void __init msm_map_msm8910_io(void)
+void __init msm_map_msm8610_io(void)
 {
-	msm_shared_ram_phys = MSM8910_MSM_SHARED_RAM_PHYS;
-	msm_map_io(msm8910_io_desc, ARRAY_SIZE(msm8910_io_desc));
+	msm_shared_ram_phys = MSM8610_MSM_SHARED_RAM_PHYS;
+	msm_map_io(msm8610_io_desc, ARRAY_SIZE(msm8610_io_desc));
 }
-#endif /* CONFIG_ARCH_MSM8910 */
+#endif /* CONFIG_ARCH_MSM8610 */
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index f7b2b1e..dd61db3 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s: " fmt, __func__
+#define pr_fmt(fmt) "PDN %s: " fmt, __func__
 
 #include <linux/err.h>
 #include <linux/kernel.h>
@@ -247,6 +247,7 @@
 				LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
 
 	kvreg->mode = HS_MODE;
+	pr_debug("%s using BHS\n", kvreg->name);
 	return 0;
 }
 
@@ -282,6 +283,7 @@
 		BHS_EN_MASK | LDO_BYP_MASK, 0);
 
 	kvreg->mode = LDO_MODE;
+	pr_debug("%s using LDO\n", kvreg->name);
 	return 0;
 }
 
@@ -294,9 +296,15 @@
 	return 0;
 }
 
-static int set_pmic_gang_voltage(int uV)
+static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
 {
 	int setpoint;
+	int rc;
+
+	if (pvreg->pmic_vmax_uV == uV)
+		return 0;
+
+	pr_debug("%d\n", uV);
 
 	if (uV < PMIC_VOLTAGE_MIN) {
 		pr_err("requested %d < %d, restricting it to %d\n",
@@ -311,10 +319,17 @@
 
 	setpoint = DIV_ROUND_UP(uV, LV_RANGE_STEP);
 
-	return msm_spm_apcs_set_vdd(setpoint);
+	rc = msm_spm_apcs_set_vdd(setpoint);
+	if (rc < 0)
+		pr_err("could not set %duV setpt = 0x%x rc = %d\n",
+				uV, setpoint, rc);
+	else
+		pvreg->pmic_vmax_uV = uV;
+
+	return rc;
 }
 
-static int configure_ldo_or_hs(struct krait_power_vreg *from, int vmax)
+static int configure_ldo_or_hs_all(struct krait_power_vreg *from, int vmax)
 {
 	struct pmic_gang_vreg *pvreg = from->pvreg;
 	struct krait_power_vreg *kvreg;
@@ -345,7 +360,7 @@
 }
 
 #define SLEW_RATE 2994
-static int pmic_gang_set_voltage_increase(struct krait_power_vreg *from,
+static int krait_voltage_increase(struct krait_power_vreg *from,
 							int vmax)
 {
 	struct pmic_gang_vreg *pvreg = from->pvreg;
@@ -353,20 +368,21 @@
 	int settling_us;
 
 	/*
-	 * since pmic gang voltage is increasing set the gang voltage
+	 * since krait voltage is increasing set the gang voltage
 	 * prior to changing ldo/hs states of the requesting krait
 	 */
-	rc = set_pmic_gang_voltage(vmax);
+	rc = set_pmic_gang_voltage(pvreg, vmax);
 	if (rc < 0) {
 		dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
 				pvreg->name, vmax, rc);
+		return rc;
 	}
 
 	/* delay until the voltage is settled when it is raised */
 	settling_us = DIV_ROUND_UP(vmax - pvreg->pmic_vmax_uV, SLEW_RATE);
 	udelay(settling_us);
 
-	rc = configure_ldo_or_hs(from, vmax);
+	rc = configure_ldo_or_hs_all(from, vmax);
 	if (rc < 0) {
 		dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
 				pvreg->name, vmax, rc);
@@ -375,25 +391,25 @@
 	return rc;
 }
 
-static int pmic_gang_set_voltage_decrease(struct krait_power_vreg *from,
+static int krait_voltage_decrease(struct krait_power_vreg *from,
 							int vmax)
 {
 	struct pmic_gang_vreg *pvreg = from->pvreg;
 	int rc = 0;
 
 	/*
-	 * since pmic gang voltage is decreasing ldos might get out of their
+	 * since krait voltage is decreasing ldos might get out of their
 	 * operating range. Hence configure such kraits to be in hs mode prior
 	 * to setting the pmic gang voltage
 	 */
-	rc = configure_ldo_or_hs(from, vmax);
+	rc = configure_ldo_or_hs_all(from, vmax);
 	if (rc < 0) {
 		dev_err(&from->rdev->dev, "%s failed ldo/hs conf %d rc = %d\n",
 				pvreg->name, vmax, rc);
 		return rc;
 	}
 
-	rc = set_pmic_gang_voltage(vmax);
+	rc = set_pmic_gang_voltage(pvreg, vmax);
 	if (rc < 0) {
 		dev_err(&from->rdev->dev, "%s failed set voltage %d rc = %d\n",
 				pvreg->name, vmax, rc);
@@ -402,19 +418,6 @@
 	return rc;
 }
 
-static int pmic_gang_set_voltage(struct krait_power_vreg *from,
-				 int vmax)
-{
-	struct pmic_gang_vreg *pvreg = from->pvreg;
-
-	if (pvreg->pmic_vmax_uV == vmax)
-		return 0;
-	else if (vmax < pvreg->pmic_vmax_uV)
-		return pmic_gang_set_voltage_decrease(from, vmax);
-
-	return pmic_gang_set_voltage_increase(from, vmax);
-}
-
 #define PHASE_SETTLING_TIME_US		10
 static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
 				int load_uA)
@@ -478,12 +481,11 @@
 	return kvreg->uV;
 }
 
-static int get_vmax(struct krait_power_vreg *from, int min_uV)
+static int get_vmax(struct pmic_gang_vreg *pvreg)
 {
 	int vmax = 0;
 	int v;
 	struct krait_power_vreg *kvreg;
-	struct pmic_gang_vreg *pvreg = from->pvreg;
 
 	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
 		if (!kvreg->online)
@@ -491,9 +493,6 @@
 
 		v = kvreg->uV;
 
-		if (kvreg == from)
-			v = min_uV;
-
 		if (vmax < v)
 			vmax = v;
 	}
@@ -518,28 +517,35 @@
 
 #define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
 static int _set_voltage(struct regulator_dev *rdev,
-			int min_uV, int max_uV, unsigned *selector)
+			int orig_krait_uV, int requested_uV)
 {
 	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
 	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
 	int rc;
 	int vmax;
 
-	vmax = get_vmax(kvreg, min_uV);
+	pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
+	/*
+	 * Assign the voltage before updating the gang voltage as we iterate
+	 * over all the core voltages and choose HS or LDO for each of them
+	 */
+	kvreg->uV = requested_uV;
+
+	vmax = get_vmax(pvreg);
 
 	/* round up the pmic voltage as per its resolution */
 	vmax = ROUND_UP_VOLTAGE(vmax, LV_RANGE_STEP);
 
-	rc = pmic_gang_set_voltage(kvreg, vmax);
+	if (requested_uV > orig_krait_uV)
+		rc = krait_voltage_increase(kvreg, vmax);
+	else
+		rc = krait_voltage_decrease(kvreg, vmax);
+
 	if (rc < 0) {
-		dev_err(&rdev->dev, "%s failed set voltage (%d, %d) rc = %d\n",
-				kvreg->name, min_uV, max_uV, rc);
-		goto out;
+		dev_err(&rdev->dev, "%s failed to set %duV from %duV rc = %d\n",
+				kvreg->name, requested_uV, orig_krait_uV, rc);
 	}
 
-	pvreg->pmic_vmax_uV = vmax;
-
-out:
 	return rc;
 }
 
@@ -562,14 +568,13 @@
 	}
 
 	mutex_lock(&pvreg->krait_power_vregs_lock);
-	kvreg->uV = min_uV;
-
 	if (!kvreg->online) {
+		kvreg->uV = min_uV;
 		mutex_unlock(&pvreg->krait_power_vregs_lock);
 		return 0;
 	}
 
-	rc = _set_voltage(rdev, min_uV, max_uV, selector);
+	rc = _set_voltage(rdev, kvreg->uV, min_uV);
 	mutex_unlock(&pvreg->krait_power_vregs_lock);
 
 	return rc;
@@ -673,12 +678,14 @@
 
 	mutex_lock(&pvreg->krait_power_vregs_lock);
 	kvreg->online = true;
-	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV,
-							kvreg->load_uA);
+	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
 	if (rc < 0)
 		goto en_err;
-	rc = _set_voltage(rdev, kvreg->uV,
-					rdev->constraints->max_uV, NULL);
+	/*
+	 * since the core is being enabled, behave as if it is increasing
+	 * the core voltage
+	 */
+	rc = _set_voltage(rdev, 0, kvreg->uV);
 en_err:
 	mutex_unlock(&pvreg->krait_power_vregs_lock);
 	return rc;
@@ -698,8 +705,7 @@
 	if (rc < 0)
 		goto dis_err;
 
-	rc = _set_voltage(rdev, kvreg->uV,
-					rdev->constraints->max_uV, NULL);
+	rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
 dis_err:
 	mutex_unlock(&pvreg->krait_power_vregs_lock);
 	return rc;
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 80f6014..b034525 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 2002 ARM Ltd.
  *  All Rights Reserved
- *  Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -263,7 +263,7 @@
 	pr_debug("Starting secondary CPU %d\n", cpu);
 
 	if (per_cpu(cold_boot_done, cpu) == false) {
-		if (machine_is_msm8226_sim() || machine_is_msm8910_sim())
+		if (machine_is_msm8226_sim() || machine_is_msm8610_sim())
 			release_secondary_sim(0xf9088000, cpu);
 
 		per_cpu(cold_boot_done, cpu) = true;
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 323532c..34d336e 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -13,17 +13,17 @@
 endif
 obj-$(CONFIG_MSM_QDSP6_APR) += apr.o apr_v1.o apr_tal.o q6core.o dsp_debug.o
 obj-$(CONFIG_MSM_QDSP6_APRV2) += apr.o apr_v2.o apr_tal.o q6core.o dsp_debug.o
-obj-y += audio_acdb.o
 ifdef CONFIG_ARCH_MSM9615
+obj-y += audio_acdb.o
 obj-y += rtac.o
 endif
 obj-$(CONFIG_MSM_QDSP6_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
 obj-$(CONFIG_MSM_QDSP6_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
-obj-$(CONFIG_MSM_QDSP6_CODECS) += rtac.o q6audio_v1.o q6audio_v1_aio.o
+obj-$(CONFIG_MSM_QDSP6_CODECS) += audio_acdb.o rtac.o q6audio_v1.o q6audio_v1_aio.o
 obj-$(CONFIG_MSM_QDSP6_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
-obj-$(CONFIG_MSM_QDSP6V2_CODECS) += rtac_v2.o q6audio_v2.o q6audio_v2_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o
 obj-$(CONFIG_MSM_QDSP6V2_CODECS)  += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
 obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
index 44ab611..2a8d5c8 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, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -135,10 +135,9 @@
 		} else {
 			uint16_t sce_left = 1, sce_right = 2;
 			aac_config = audio->codec_cfg;
-			if ((aac_config->dual_mono_mode <
-				AUDIO_AAC_DUAL_MONO_PL_PR) ||
-				(aac_config->dual_mono_mode >
-				AUDIO_AAC_DUAL_MONO_PL_SR)) {
+			/* PL_PR is 0 only need to check PL_SR */
+			if (aac_config->dual_mono_mode >
+			    AUDIO_AAC_DUAL_MONO_PL_SR) {
 				pr_err("%s:AUDIO_SET_AAC_CONFIG: Invalid"
 					"dual_mono mode =%d\n", __func__,
 					aac_config->dual_mono_mode);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index cad845f..ea22c12 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -64,15 +64,6 @@
 	atomic_t			vocstrm_total_cal_size;
 	atomic_t			vocvol_total_cal_size;
 
-	/* Voice Column data */
-	struct acdb_atomic_cal_block	vocproc_col_cal[MAX_VOCPROC_TYPES];
-	uint32_t			*col_data[MAX_VOCPROC_TYPES];
-
-	/* VocProc dev cfg cal*/
-	struct acdb_atomic_cal_block	vocproc_dev_cal[MAX_NETWORKS];
-	atomic_t			vocproc_dev_cal_size;
-	atomic_t			vocproc_dev_total_cal_size;
-
 	/* AFE cal */
 	struct acdb_atomic_cal_block	afe_cal[MAX_AUDPROC_TYPES];
 
@@ -203,45 +194,6 @@
 		atomic_read(&acdb_data.vocvol_total_cal_size);
 }
 
-void get_voice_col_data(uint32_t vocproc_type,
-			struct acdb_cal_block *cal_block)
-{
-	if (cal_block == NULL) {
-		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
-		goto done;
-	}
-
-	cal_block->cal_kvaddr = atomic_read(&acdb_data.
-				vocproc_col_cal[vocproc_type].cal_kvaddr);
-	cal_block->cal_paddr = atomic_read(&acdb_data.
-				vocproc_col_cal[vocproc_type].cal_paddr);
-	cal_block->cal_size = atomic_read(&acdb_data.
-				vocproc_col_cal[vocproc_type].cal_size);
-done:
-	return;
-}
-
-void store_voice_col_data(uint32_t vocproc_type, uint32_t cal_size,
-			  uint32_t *cal_data)
-{
-	if (cal_size > MAX_COL_SIZE) {
-		pr_err("%s: col size is to big %d\n", __func__,
-				cal_size);
-		goto done;
-	}
-	if (copy_from_user(acdb_data.col_data[vocproc_type],
-			(void *)((uint8_t *)cal_data + sizeof(cal_size)),
-			cal_size)) {
-		pr_err("%s: fail to copy col size %d\n",
-			__func__, cal_size);
-		goto done;
-	}
-	atomic_set(&acdb_data.vocproc_col_cal[vocproc_type].cal_size,
-		cal_size);
-done:
-	return;
-}
-
 void get_anc_cal(struct acdb_cal_block *cal_block)
 {
 	pr_debug("%s\n", __func__);
@@ -482,7 +434,7 @@
 	return;
 }
 
-void store_vocproc_dev_cfg_cal(int32_t len, struct cal_block *cal_blocks)
+void store_vocproc_cal(int32_t len, struct cal_block *cal_blocks)
 {
 	int i;
 	pr_debug("%s\n", __func__);
@@ -493,57 +445,6 @@
 		goto done;
 	}
 
-	atomic_set(&acdb_data.vocproc_dev_total_cal_size, 0);
-	for (i = 0; i < len; i++) {
-		if (cal_blocks[i].cal_offset >
-					atomic64_read(&acdb_data.mem_len)) {
-			pr_err("%s: offset %d is > mem_len %ld\n",
-				__func__, cal_blocks[i].cal_offset,
-				(long)atomic64_read(&acdb_data.mem_len));
-			atomic_set(&acdb_data.vocproc_dev_cal[i].cal_size, 0);
-		} else {
-			atomic_add(cal_blocks[i].cal_size,
-				&acdb_data.vocproc_dev_total_cal_size);
-			atomic_set(&acdb_data.vocproc_dev_cal[i].cal_size,
-				cal_blocks[i].cal_size);
-			atomic_set(&acdb_data.vocproc_dev_cal[i].cal_paddr,
-				cal_blocks[i].cal_offset +
-				atomic64_read(&acdb_data.paddr));
-			atomic_set(&acdb_data.vocproc_dev_cal[i].cal_kvaddr,
-				cal_blocks[i].cal_offset +
-				atomic64_read(&acdb_data.kvaddr));
-		}
-	}
-	atomic_set(&acdb_data.vocproc_dev_cal_size, len);
-done:
-	return;
-}
-
-void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block)
-{
-	pr_debug("%s\n", __func__);
-
-	cal_block->cal_kvaddr =
-		atomic_read(&acdb_data.vocproc_dev_cal[0].cal_kvaddr);
-	cal_block->cal_paddr =
-		atomic_read(&acdb_data.vocproc_dev_cal[0].cal_paddr);
-	cal_block->cal_size =
-		atomic_read(&acdb_data.vocproc_dev_total_cal_size);
-}
-
-
-
-void store_vocproc_cal(int32_t len, struct cal_block *cal_blocks)
-{
-	int i;
-	pr_debug("%s\n", __func__);
-
-	if (len > MAX_NETWORKS) {
-		pr_err("%s: Calibration sent for %d networks, only %d are "
-			"supported!\n", __func__, len, MAX_NETWORKS);
-		goto done;
-	}
-
 	atomic_set(&acdb_data.vocproc_total_cal_size, 0);
 	for (i = 0; i < len; i++) {
 		if (cal_blocks[i].cal_offset >
@@ -591,8 +492,8 @@
 	pr_debug("%s\n", __func__);
 
 	if (len > MAX_NETWORKS) {
-		pr_err("%s: Calibration sent for %d networks, only %d are "
-			"supported!\n", __func__, len, MAX_NETWORKS);
+		pr_err("%s: Calibration sent for %d networks, only %d are supported!\n",
+			__func__, len, MAX_NETWORKS);
 		goto done;
 	}
 
@@ -643,8 +544,8 @@
 	pr_debug("%s\n", __func__);
 
 	if (len > MAX_NETWORKS) {
-		pr_err("%s: Calibration sent for %d networks, only %d are "
-			"supported!\n", __func__, len, MAX_NETWORKS);
+		pr_err("%s: Calibration sent for %d networks, only %d are supported!\n",
+			__func__, len, MAX_NETWORKS);
 		goto done;
 	}
 
@@ -719,8 +620,7 @@
 	pr_debug("%s\n", __func__);
 
 	if (atomic64_read(&acdb_data.mem_len)) {
-		pr_debug("%s: ACDB opened but memory allocated, "
-			"using existing allocation!\n",
+		pr_debug("%s: ACDB opened but memory allocated, using existing allocation!\n",
 			__func__);
 	}
 
@@ -730,19 +630,12 @@
 
 static int deregister_memory(void)
 {
-	int i;
-
 	if (atomic64_read(&acdb_data.mem_len)) {
 		mutex_lock(&acdb_data.acdb_mutex);
 		atomic64_set(&acdb_data.mem_len, 0);
 		atomic_set(&acdb_data.vocstrm_total_cal_size, 0);
 		atomic_set(&acdb_data.vocproc_total_cal_size, 0);
 		atomic_set(&acdb_data.vocvol_total_cal_size, 0);
-
-		for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
-			kfree(acdb_data.col_data[i]);
-			acdb_data.col_data[i] = NULL;
-		}
 		ion_unmap_kernel(acdb_data.ion_client, acdb_data.ion_handle);
 		ion_free(acdb_data.ion_client, acdb_data.ion_handle);
 		ion_client_destroy(acdb_data.ion_client);
@@ -754,18 +647,12 @@
 static int register_memory(void)
 {
 	int			result;
-	int			i;
 	unsigned long		paddr;
 	void                    *kvptr;
 	unsigned long		kvaddr;
 	unsigned long		mem_len;
 
 	mutex_lock(&acdb_data.acdb_mutex);
-	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
-		acdb_data.col_data[i] = kmalloc(MAX_COL_SIZE, GFP_KERNEL);
-		atomic_set(&acdb_data.vocproc_col_cal[i].cal_kvaddr,
-			(uint32_t)acdb_data.col_data[i]);
-	}
 
 	acdb_data.ion_client =
 		msm_ion_client_create(UINT_MAX, "audio_acdb_client");
@@ -803,8 +690,7 @@
 	atomic64_set(&acdb_data.mem_len, mem_len);
 	mutex_unlock(&acdb_data.acdb_mutex);
 
-	pr_debug("%s done! paddr = 0x%lx, "
-		"kvaddr = 0x%lx, len = x%lx\n",
+	pr_debug("%s done! paddr = 0x%lx, kvaddr = 0x%lx, len = x%lx\n",
 		 __func__,
 		(long)atomic64_read(&acdb_data.paddr),
 		(long)atomic64_read(&acdb_data.kvaddr),
@@ -820,6 +706,7 @@
 	mutex_unlock(&acdb_data.acdb_mutex);
 	return result;
 }
+
 static long acdb_ioctl(struct file *f,
 		unsigned int cmd, unsigned long arg)
 {
@@ -906,18 +793,6 @@
 		goto done;
 	}
 
-	switch (cmd) {
-	case AUDIO_SET_VOCPROC_COL_CAL:
-		store_voice_col_data(VOCPROC_CAL, size, (uint32_t *)arg);
-		goto done;
-	case AUDIO_SET_VOCSTRM_COL_CAL:
-		store_voice_col_data(VOCSTRM_CAL, size, (uint32_t *)arg);
-		goto done;
-	case AUDIO_SET_VOCVOL_COL_CAL:
-		store_voice_col_data(VOCVOL_CAL, size, (uint32_t *)arg);
-		goto done;
-	}
-
 	if (copy_from_user(data, (void *)(arg + sizeof(size)), size)) {
 
 		pr_err("%s: fail to copy table size %d\n", __func__, size);
@@ -934,50 +809,50 @@
 	switch (cmd) {
 	case AUDIO_SET_AUDPROC_TX_CAL:
 		if (size > sizeof(struct cal_block))
-			pr_err("%s: More Audproc Cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More Audproc Cal then expected, size received: %d\n",
+				__func__, size);
 		store_audproc_cal(TX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_CAL:
 		if (size > sizeof(struct cal_block))
-			pr_err("%s: More Audproc Cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More Audproc Cal then expected, size received: %d\n",
+				__func__, size);
 		store_audproc_cal(RX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
 		if (size > sizeof(struct cal_block))
-			pr_err("%s: More Audproc Cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More Audproc Cal then expected, size received: %d\n",
+				__func__, size);
 		store_audstrm_cal(TX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
 		if (size > sizeof(struct cal_block))
-			pr_err("%s: More Audproc Cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More Audproc Cal then expected, size received: %d\n",
+				__func__, size);
 		store_audstrm_cal(RX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_TX_VOL_CAL:
 		if (size > sizeof(struct cal_block))
-			pr_err("%s: More Audproc Cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More Audproc Cal then expected, size received: %d\n",
+				__func__, size);
 		store_audvol_cal(TX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_VOL_CAL:
 		if (size > sizeof(struct cal_block))
-			pr_err("%s: More Audproc Cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More Audproc Cal then expected, size received: %d\n",
+				__func__, size);
 		store_audvol_cal(RX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AFE_TX_CAL:
 		if (size > sizeof(struct cal_block))
-			pr_err("%s: More AFE Cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More AFE Cal then expected, size received: %d\n",
+				__func__, size);
 		store_afe_cal(TX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AFE_RX_CAL:
 		if (size > sizeof(struct cal_block))
-			pr_err("%s: More AFE Cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More AFE Cal then expected, size received: %d\n",
+				__func__, size);
 		store_afe_cal(RX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_VOCPROC_CAL:
@@ -992,14 +867,10 @@
 		store_vocvol_cal(size / sizeof(struct cal_block),
 						(struct cal_block *)data);
 		break;
-	case AUDIO_SET_VOCPROC_DEV_CFG_CAL:
-		store_vocproc_dev_cfg_cal(size / sizeof(struct cal_block),
-						(struct cal_block *)data);
-		break;
 	case AUDIO_SET_SIDETONE_CAL:
 		if (size > sizeof(struct sidetone_cal))
-			pr_err("%s: More sidetone cal then expected, "
-				"size received: %d\n", __func__, size);
+			pr_err("%s: More sidetone cal then expected, size received: %d\n",
+			       __func__, size);
 		store_sidetone_cal((struct sidetone_cal *)data);
 		break;
 	case AUDIO_SET_ANC_CAL:
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index b53edd9..658c07b 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, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -147,10 +147,8 @@
 		} else {
 			uint16_t sce_left = 1, sce_right = 2;
 			aac_config = audio->codec_cfg;
-			if ((aac_config->dual_mono_mode <
-				AUDIO_AAC_DUAL_MONO_PL_PR) ||
-				(aac_config->dual_mono_mode >
-				AUDIO_AAC_DUAL_MONO_PL_SR)) {
+			if (aac_config->dual_mono_mode >
+			    AUDIO_AAC_DUAL_MONO_PL_SR) {
 				pr_err("%s:AUDIO_SET_AAC_CONFIG: Invalid dual_mono mode =%d\n",
 					 __func__, aac_config->dual_mono_mode);
 			} else {
diff --git a/arch/arm/mach-msm/qdsp6v2/dsp_debug.c b/arch/arm/mach-msm/qdsp6v2/dsp_debug.c
index 3635fbd..26c8f75 100644
--- a/arch/arm/mach-msm/qdsp6v2/dsp_debug.c
+++ b/arch/arm/mach-msm/qdsp6v2/dsp_debug.c
@@ -38,12 +38,14 @@
 
 void q6audio_dsp_not_responding(void)
 {
+	int i;
+
 	if (cb_ptr)
 		cb_ptr(DSP_STATE_CRASHED);
 	if (atomic_add_return(1, &dsp_crash_count) != 1) {
 		pr_err("q6audio_dsp_not_responding() \
 			- parking additional crasher...\n");
-		for (;;)
+		for (i = 0; i < 600; i++)
 			msleep(1000);
 	}
 	if (dsp_wait_count) {
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index 9dd66e1..f23ba67 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -253,8 +253,6 @@
 	int len;
 	static int t_len;
 
-	if (count < 0)
-		return 0;
 	len = count > 63 ? 63 : count;
 	if (copy_from_user(l_buf + 20 , buf, len)) {
 		pr_info("Unable to copy data from user space\n");
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index ccd0861..4295fd4 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -960,6 +960,9 @@
  */
 int msm_rpm_enter_sleep(void)
 {
+	if (standalone)
+		return 0;
+
 	return smd_mask_receive_interrupt(msm_rpm_data.ch_info, true);
 }
 EXPORT_SYMBOL(msm_rpm_enter_sleep);
@@ -970,20 +973,13 @@
  */
 void msm_rpm_exit_sleep(void)
 {
+	if (standalone)
+		return;
+
 	smd_mask_receive_interrupt(msm_rpm_data.ch_info, false);
 }
 EXPORT_SYMBOL(msm_rpm_exit_sleep);
 
-static bool msm_rpm_set_standalone(void)
-{
-	if (machine_is_msm9625() || machine_is_msm8974_rumi()) {
-		pr_warn("%s(): Running in standalone mode, requests "
-				"will not be sent to RPM\n", __func__);
-		standalone = true;
-	}
-	return standalone;
-}
-
 static int __devinit msm_rpm_dev_probe(struct platform_device *pdev)
 {
 	char *key = NULL;
@@ -1001,6 +997,9 @@
 	if (ret)
 		goto fail;
 
+	key = "rpm-standalone";
+	standalone = of_property_read_bool(pdev->dev.of_node, key);
+
 	init_completion(&msm_rpm_data.smd_open);
 	spin_lock_init(&msm_rpm_data.smd_lock_write);
 	spin_lock_init(&msm_rpm_data.smd_lock_read);
@@ -1012,9 +1011,14 @@
 		pr_info("Cannot open RPM channel %s %d\n", msm_rpm_data.ch_name,
 				msm_rpm_data.ch_type);
 
-		msm_rpm_set_standalone();
 		BUG_ON(!standalone);
 		complete(&msm_rpm_data.smd_open);
+	} else {
+		/*
+		 * Override DT's suggestion to try standalone; since we have an
+		 * SMD channel.
+		 */
+		standalone = false;
 	}
 
 	wait_for_completion(&msm_rpm_data.smd_open);
@@ -1029,6 +1033,10 @@
 	}
 
 	of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+
+	if (standalone)
+		pr_info("%s(): RPM running in standalone mode\n", __func__);
+
 	return 0;
 fail:
 	pr_err("%s(): Failed to read node: %s, key=%s\n", __func__,
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 1ab1f71..51c995f 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -282,6 +282,8 @@
 	/* 9625 IDs */
 	[134] = MSM_CPU_9625,
 	[152] = MSM_CPU_9625,
+	[149] = MSM_CPU_9625,
+	[150] = MSM_CPU_9625,
 
 	/* 8960AB IDs */
 	[138] = MSM_CPU_8960AB,
@@ -301,8 +303,8 @@
 	/* 8092 IDs */
 	[146] = MSM_CPU_8092,
 
-	/* 8910 IDs */
-	[147] = MSM_CPU_8910,
+	/* 8610 IDs */
+	[147] = MSM_CPU_8610,
 
 	/* 8064AB IDs */
 	[153] = MSM_CPU_8064AB,
@@ -897,9 +899,9 @@
 		dummy_socinfo.id = 146;
 		strlcpy(dummy_socinfo.build_id, "mpq8092 - ",
 		sizeof(dummy_socinfo.build_id));
-	} else if (early_machine_is_msm8910()) {
+	} else if (early_machine_is_msm8610()) {
 		dummy_socinfo.id = 147;
-		strlcpy(dummy_socinfo.build_id, "msm8910 - ",
+		strlcpy(dummy_socinfo.build_id, "msm8610 - ",
 			sizeof(dummy_socinfo.build_id));
 	}
 	strlcat(dummy_socinfo.build_id, "Dummy socinfo",
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 79f20a4..0d5ad6a 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -81,7 +81,6 @@
 #define SMD_DATA_TYPE 0
 #define SMD_CNTL_TYPE 1
 #define SMD_DCI_TYPE 2
-#define MAX_PROC	10
 
 /* Maximum number of pkt reg supported at initialization*/
 extern unsigned int diag_max_reg;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 564e085..d2454f4 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -80,9 +80,6 @@
     means that the diag packet has a delayed response. */
 static uint16_t delayed_rsp_id = 1;
 
-/* Array of valid token ids */
-static int token_list[MAX_PROC] = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9};
-
 #define DIAGPKT_MAX_DELAYED_RSP 0xFFFF
 
 /* returns the next delayed rsp id - rollsover the id if wrapping is
@@ -384,10 +381,13 @@
 {
 	uint16_t remote_dev = 0;
 
+	/* Check for MDM processor */
 	if (driver->hsic_inited)
-		remote_dev |= (1 << 0);
+		remote_dev |= 1 << 0;
+
+	/* Check for QSC processor */
 	if (driver->diag_smux_enabled)
-		remote_dev |= (1 << 1);
+		remote_dev |= 1 << 1;
 
 	return remote_dev;
 }
@@ -395,15 +395,22 @@
 inline uint16_t diag_get_remote_device_mask(void) { return 0; }
 #endif
 
-static int diag_get_token(int token)
+static int diag_get_remote(int remote_info)
 {
-	int i;
+	int val = (remote_info < 0) ? -remote_info : remote_info;
+	int remote_val;
 
-	for (i = 0; i < MAX_PROC; i++)
-		if (token_list[i] == token)
-			return 1 << i;
+	switch (val) {
+	case MDM:
+	case QSC:
+		remote_val = -remote_info;
+		break;
+	default:
+		remote_val = 0;
+		break;
+	}
 
-	return 0;
+	return remote_val;
 }
 
 long diagchar_ioctl(struct file *filp,
@@ -811,6 +818,7 @@
 	struct diag_dci_client_tbl *entry;
 	int index = -1, i = 0, ret = 0;
 	int num_data = 0, data_type;
+	int remote_token;
 
 	for (i = 0; i < driver->num_clients; i++)
 		if (driver->client_map[i].pid == current->tgid)
@@ -831,7 +839,7 @@
 		unsigned long spin_lock_flags;
 		struct diag_write_device hsic_buf_tbl[NUM_HSIC_BUF_TBL_ENTRIES];
 #endif
-
+		remote_token = 0;
 		pr_debug("diag: process woken up\n");
 		/*Copy the type of data being passed*/
 		data_type = driver->data_ready[index] & USER_SPACE_DATA_TYPE;
@@ -907,9 +915,12 @@
 #ifdef CONFIG_DIAG_SDIO_PIPE
 		/* copy 9K data over SDIO */
 		if (driver->in_busy_sdio == 1) {
+			remote_token = diag_get_remote(MDM);
 			num_data++;
-			/*Copy the negative  token of data being passed*/
-			COPY_USER_SPACE_OR_EXIT(buf+ret, token_list[MDM], 4);
+
+			/*Copy the negative token of data being passed*/
+			COPY_USER_SPACE_OR_EXIT(buf+ret,
+						remote_token, 4);
 			/*Copy the length of data being passed*/
 			COPY_USER_SPACE_OR_EXIT(buf+ret,
 				 (driver->write_ptr_mdm->length), 4);
@@ -933,6 +944,7 @@
 		spin_unlock_irqrestore(&driver->hsic_spinlock,
 					spin_lock_flags);
 
+		remote_token = diag_get_remote(MDM);
 		for (i = 0; i < driver->poolsize_hsic_write; i++) {
 			if (hsic_buf_tbl[i].length > 0) {
 				pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n",
@@ -941,8 +953,8 @@
 				num_data++;
 
 				/* Copy the negative token */
-				if (copy_to_user(buf+ret, &token_list[MDM],
-									4)) {
+				if (copy_to_user(buf+ret,
+						&remote_token, 4)) {
 					num_data--;
 					goto drop_hsic;
 				}
@@ -977,10 +989,12 @@
 			}
 		}
 		if (driver->in_busy_smux == 1) {
+			remote_token = diag_get_remote(QSC);
 			num_data++;
 
 			/* Copy the negative  token of data being passed */
-			COPY_USER_SPACE_OR_EXIT(buf+ret, token_list[QSC], 4);
+			COPY_USER_SPACE_OR_EXIT(buf+ret,
+						remote_token, 4);
 			/* Copy the length of data being passed */
 			COPY_USER_SPACE_OR_EXIT(buf+ret,
 					(driver->write_ptr_mdm->length), 4);
@@ -1142,7 +1156,7 @@
 		err = copy_from_user(driver->user_space_data, buf + 4,
 							 payload_size);
 		/* Check for proc_type */
-		remote_proc = diag_get_token(*(int *)driver->user_space_data);
+		remote_proc = diag_get_remote(*(int *)driver->user_space_data);
 
 		if (remote_proc) {
 			token_offset = 4;
@@ -1167,7 +1181,7 @@
 #endif
 #ifdef CONFIG_DIAG_SDIO_PIPE
 		/* send masks to 9k too */
-		if (driver->sdio_ch && (remote_proc & MDM)) {
+		if (driver->sdio_ch && (remote_proc == MDM)) {
 			wait_event_interruptible(driver->wait_q,
 				 (sdio_write_avail(driver->sdio_ch) >=
 					 payload_size));
@@ -1181,7 +1195,7 @@
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 		/* send masks to 9k too */
 		if (driver->hsic_ch && (payload_size > 0) &&
-						(remote_proc & MDM)) {
+						(remote_proc == MDM)) {
 			/* wait sending mask updates if HSIC ch not ready */
 			if (driver->in_busy_hsic_write)
 				wait_event_interruptible(driver->wait_q,
@@ -1204,7 +1218,7 @@
 					driver->in_busy_hsic_write = 0;
 			}
 		}
-		if (driver->diag_smux_enabled && (remote_proc & QSC)
+		if (driver->diag_smux_enabled && (remote_proc == QSC)
 						&& driver->lcid) {
 			if (payload_size > 0) {
 				err = msm_smux_write(driver->lcid, NULL,
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index d605a61..4eac9cb 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto Engine driver.
  *
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, 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
@@ -895,7 +895,10 @@
 			len = ALIGN(len, pce_dev->ce_sps.ce_burst_size);
 		while (len > 0) {
 			if (len > SPS_MAX_PKT_SIZE) {
-				data_cnt = SPS_MAX_PKT_SIZE;
+				if ((len % SPS_MAX_PKT_SIZE) > 0)
+					data_cnt = (len % SPS_MAX_PKT_SIZE);
+				else
+					data_cnt = SPS_MAX_PKT_SIZE;
 				iovec->size = data_cnt;
 				iovec->addr = addr;
 				iovec->flags = 0;
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index 8533636..7a7aacc 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -36,7 +36,7 @@
 
 /* QCE max number of descriptor in a descriptor list */
 #define QCE_MAX_NUM_DESC    128
-#define SPS_MAX_PKT_SIZE  (32 * 1024  - 64)
+#define SPS_MAX_PKT_SIZE  (16 * 1024)
 
 /* State of consumer/producer Pipe */
 enum qce_pipe_st_enum {
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 818bd63..abf125f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,7 @@
  *
  */
 #include <linux/types.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/spinlock.h>
 #include <linux/genalloc.h>
@@ -40,6 +41,8 @@
 	{ 0x20, 0, 0 },				/* FSR */
 	{ 0x800, 0, 0 },			/* TLBIALL */
 	{ 0x820, 0, 0 },			/* RESUME */
+	{ 0x03C, 0, 0 },			/* TLBLKCR */
+	{ 0x818, 0, 0 },			/* V2PUR */
 };
 
 static struct kgsl_iommu_register_list kgsl_iommuv2_reg[KGSL_IOMMU_REG_MAX] = {
@@ -782,16 +785,26 @@
  */
 static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu)
 {
-	struct kgsl_iommu *iommu = mmu->device->mmu.priv;
+	struct kgsl_iommu *iommu = mmu->priv;
 	int status = 0;
 	uint32_t lock_phy_addr = 0;
 	uint32_t page_offset = 0;
 
-	if (KGSL_DEVICE_3D0 != mmu->device->id ||
-		!msm_soc_version_supports_iommu_v1() ||
+	if (!msm_soc_version_supports_iommu_v1() ||
 		!kgsl_mmu_is_perprocess())
 		return status;
 
+	/*
+	 * For 2D devices cpu side sync lock is required. For 3D device,
+	 * since we only have a single 3D core and we always ensure that
+	 * 3D core is idle while writing to IOMMU register using CPU this
+	 * lock is not required
+	 */
+	if (KGSL_DEVICE_2D0 == mmu->device->id ||
+		KGSL_DEVICE_2D1 == mmu->device->id) {
+		return status;
+	}
+
 	/* Return if already initialized */
 	if (iommu->sync_lock_initialized)
 		return status;
@@ -1260,6 +1273,111 @@
 	return status;
 }
 
+/*
+ * kgsl_iommu_lock_rb_in_tlb - Allocates tlb entries and locks the
+ * virtual to physical address translation of ringbuffer for 3D
+ * device into tlb.
+ * @mmu - Pointer to mmu structure
+ *
+ * Return - void
+ */
+static void kgsl_iommu_lock_rb_in_tlb(struct kgsl_mmu *mmu)
+{
+	struct kgsl_device *device = mmu->device;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_ringbuffer *rb;
+	struct kgsl_iommu *iommu = mmu->priv;
+	unsigned int num_tlb_entries;
+	unsigned int tlblkcr = 0;
+	unsigned int v2pxx = 0;
+	unsigned int vaddr = 0;
+	int i, j, k, l;
+
+	if (!iommu->sync_lock_initialized)
+		return;
+
+	rb = &adreno_dev->ringbuffer;
+	num_tlb_entries = rb->buffer_desc.size / PAGE_SIZE;
+
+	for (i = 0; i < iommu->unit_count; i++) {
+		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
+		for (j = 0; j < iommu_unit->dev_count; j++) {
+			tlblkcr = 0;
+			if (cpu_is_msm8960())
+				tlblkcr |= ((num_tlb_entries &
+					KGSL_IOMMU_TLBLKCR_FLOOR_MASK) <<
+					KGSL_IOMMU_TLBLKCR_FLOOR_SHIFT);
+			else
+				tlblkcr |= (((num_tlb_entries *
+					iommu_unit->dev_count) &
+					KGSL_IOMMU_TLBLKCR_FLOOR_MASK) <<
+					KGSL_IOMMU_TLBLKCR_FLOOR_SHIFT);
+			/* Do not invalidate locked entries on tlbiall flush */
+			tlblkcr	|= ((1 & KGSL_IOMMU_TLBLKCR_TLBIALLCFG_MASK)
+				<< KGSL_IOMMU_TLBLKCR_TLBIALLCFG_SHIFT);
+			tlblkcr	|= ((1 & KGSL_IOMMU_TLBLKCR_TLBIASIDCFG_MASK)
+				<< KGSL_IOMMU_TLBLKCR_TLBIASIDCFG_SHIFT);
+			tlblkcr	|= ((1 & KGSL_IOMMU_TLBLKCR_TLBIVAACFG_MASK)
+				<< KGSL_IOMMU_TLBLKCR_TLBIVAACFG_SHIFT);
+			/* Enable tlb locking */
+			tlblkcr |= ((1 & KGSL_IOMMU_TLBLKCR_LKE_MASK)
+				<< KGSL_IOMMU_TLBLKCR_LKE_SHIFT);
+			KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit,
+					iommu_unit->dev[j].ctx_id,
+					TLBLKCR, tlblkcr);
+		}
+		for (j = 0; j < iommu_unit->dev_count; j++) {
+			/* skip locking entries for private bank on 8960 */
+			if (cpu_is_msm8960() &&  KGSL_IOMMU_CONTEXT_PRIV == j)
+				continue;
+			/* Lock the ringbuffer virtual address into tlb */
+			vaddr = rb->buffer_desc.gpuaddr;
+			for (k = 0; k < num_tlb_entries; k++) {
+				v2pxx = 0;
+				v2pxx |= (((k + j * num_tlb_entries) &
+					KGSL_IOMMU_V2PXX_INDEX_MASK)
+					<< KGSL_IOMMU_V2PXX_INDEX_SHIFT);
+				v2pxx |= vaddr & (KGSL_IOMMU_V2PXX_VA_MASK <<
+						KGSL_IOMMU_V2PXX_VA_SHIFT);
+
+				KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit,
+						iommu_unit->dev[j].ctx_id,
+						V2PUR, v2pxx);
+				vaddr += PAGE_SIZE;
+				for (l = 0; l < iommu_unit->dev_count; l++) {
+					tlblkcr = KGSL_IOMMU_GET_CTX_REG(iommu,
+						iommu_unit,
+						iommu_unit->dev[l].ctx_id,
+						TLBLKCR);
+					mb();
+					tlblkcr &=
+					~(KGSL_IOMMU_TLBLKCR_VICTIM_MASK
+					<< KGSL_IOMMU_TLBLKCR_VICTIM_SHIFT);
+					tlblkcr |= (((k + 1 +
+					(j * num_tlb_entries)) &
+					KGSL_IOMMU_TLBLKCR_VICTIM_MASK) <<
+					KGSL_IOMMU_TLBLKCR_VICTIM_SHIFT);
+					KGSL_IOMMU_SET_CTX_REG(iommu,
+						iommu_unit,
+						iommu_unit->dev[l].ctx_id,
+						TLBLKCR, tlblkcr);
+				}
+			}
+		}
+		for (j = 0; j < iommu_unit->dev_count; j++) {
+			tlblkcr = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
+						iommu_unit->dev[j].ctx_id,
+						TLBLKCR);
+			mb();
+			/* Disable tlb locking */
+			tlblkcr &= ~(KGSL_IOMMU_TLBLKCR_LKE_MASK
+				<< KGSL_IOMMU_TLBLKCR_LKE_SHIFT);
+			KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit,
+				iommu_unit->dev[j].ctx_id, TLBLKCR, tlblkcr);
+		}
+	}
+}
+
 static int kgsl_iommu_start(struct kgsl_mmu *mmu)
 {
 	int status;
@@ -1280,7 +1398,7 @@
 
 	/* We use the GPU MMU to control access to IOMMU registers on 8960 with
 	 * a225, hence we still keep the MMU active on 8960 */
-	if (cpu_is_msm8960()) {
+	if (cpu_is_msm8960() && KGSL_DEVICE_3D0 == mmu->device->id) {
 		struct kgsl_mh *mh = &(mmu->device->mh);
 		BUG_ON(iommu->iommu_units[0].reg_map.gpuaddr != 0 &&
 			mh->mpu_base > iommu->iommu_units[0].reg_map.gpuaddr);
@@ -1312,6 +1430,7 @@
 	 * changing pagetables we can use this lsb value of the pagetable w/o
 	 * having to read it again
 	 */
+	msm_iommu_lock();
 	for (i = 0; i < iommu->unit_count; i++) {
 		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
 		for (j = 0; j < iommu_unit->dev_count; j++) {
@@ -1322,6 +1441,9 @@
 						TTBR0));
 		}
 	}
+	kgsl_iommu_lock_rb_in_tlb(mmu);
+	msm_iommu_unlock();
+
 
 	kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
 	mmu->flags |= KGSL_FLAGS_STARTED;
@@ -1408,7 +1530,6 @@
 	 *
 	 *  call this with the global lock held
 	 */
-
 	if (mmu->flags & KGSL_FLAGS_STARTED) {
 		/* detach iommu attachment */
 		kgsl_detach_pagetable_iommu_domain(mmu);
@@ -1423,10 +1544,12 @@
 				for (j = 0; j < iommu_unit->dev_count; j++) {
 					if (iommu_unit->dev[j].fault) {
 						kgsl_iommu_enable_clk(mmu, j);
+						msm_iommu_lock();
 						KGSL_IOMMU_SET_CTX_REG(iommu,
 						iommu_unit,
 						iommu_unit->dev[j].ctx_id,
 						RESUME, 1);
+						msm_iommu_unlock();
 						iommu_unit->dev[j].fault = 0;
 					}
 				}
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index f539b07..25f0d45 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,26 @@
 #define KGSL_IOMMU_CTX_OFFSET_V2	0x8000
 #define KGSL_IOMMU_CTX_SHIFT		12
 
+/* TLBLKCR feilds */
+#define KGSL_IOMMU_TLBLKCR_LKE_MASK		0x00000001
+#define KGSL_IOMMU_TLBLKCR_LKE_SHIFT		0
+#define KGSL_IOMMU_TLBLKCR_TLBIALLCFG_MASK	0x00000001
+#define KGSL_IOMMU_TLBLKCR_TLBIALLCFG_SHIFT	1
+#define KGSL_IOMMU_TLBLKCR_TLBIASIDCFG_MASK	0x00000001
+#define KGSL_IOMMU_TLBLKCR_TLBIASIDCFG_SHIFT	2
+#define KGSL_IOMMU_TLBLKCR_TLBIVAACFG_MASK	0x00000001
+#define KGSL_IOMMU_TLBLKCR_TLBIVAACFG_SHIFT	3
+#define KGSL_IOMMU_TLBLKCR_FLOOR_MASK		0x000000FF
+#define KGSL_IOMMU_TLBLKCR_FLOOR_SHIFT		8
+#define KGSL_IOMMU_TLBLKCR_VICTIM_MASK		0x000000FF
+#define KGSL_IOMMU_TLBLKCR_VICTIM_SHIFT		16
+
+/* V2PXX feilds */
+#define KGSL_IOMMU_V2PXX_INDEX_MASK		0x000000FF
+#define KGSL_IOMMU_V2PXX_INDEX_SHIFT		0
+#define KGSL_IOMMU_V2PXX_VA_MASK		0x000FFFFF
+#define KGSL_IOMMU_V2PXX_VA_SHIFT		12
+
 enum kgsl_iommu_reg_map {
 	KGSL_IOMMU_GLOBAL_BASE = 0,
 	KGSL_IOMMU_CTX_TTBR0,
@@ -26,6 +46,8 @@
 	KGSL_IOMMU_CTX_FSR,
 	KGSL_IOMMU_CTX_TLBIALL,
 	KGSL_IOMMU_CTX_RESUME,
+	KGSL_IOMMU_CTX_TLBLKCR,
+	KGSL_IOMMU_CTX_V2PUR,
 	KGSL_IOMMU_REG_MAX
 };
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 8311a2d..10f8ae1 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1003,7 +1003,7 @@
 	}
 
 	/* Set the CPU latency to 501usec to allow low latency PC modes */
-	pwr->pm_qos_latency = 501;
+	pwr->pm_qos_latency = 3;
 
 	pm_runtime_enable(device->parentdev);
 	register_early_suspend(&device->display_off);
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index c28c61d..11f351c 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -537,6 +537,7 @@
 
 	return rc;
 }
+EXPORT_SYMBOL(qpnp_iadc_get_rsense);
 
 int32_t qpnp_check_pmic_temp(void)
 {
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c
index 79bd15c..687269e 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v2.c
@@ -251,10 +251,8 @@
 /*
  * May only be called for non-secure iommus
  */
-static void __program_iommu(void __iomem *base,
-			    struct msm_iommu_bfb_settings *bfb_settings)
+static void __program_iommu(void __iomem *base)
 {
-	int i;
 	__reset_iommu(base);
 
 	SET_CR0_SMCFCFG(base, 1);
@@ -266,12 +264,19 @@
 	SET_CR0_GFRE(base, 1);
 	SET_CR0_CLIENTPD(base, 0);
 
+	mb(); /* Make sure writes complete before returning */
+}
+
+void program_iommu_bfb_settings(void __iomem *base,
+			const struct msm_iommu_bfb_settings *bfb_settings)
+{
+	unsigned int i;
 	if (bfb_settings)
 		for (i = 0; i < bfb_settings->length; i++)
 			SET_GLOBAL_REG(base, bfb_settings->regs[i],
 					     bfb_settings->data[i]);
 
-	mb();	/* Make sure writes complete before returning */
+	mb(); /* Make sure writes complete before returning */
 }
 
 static void __reset_context(void __iomem *base, int ctx)
@@ -567,8 +572,7 @@
 
 	if (!msm_iommu_ctx_attached(dev->parent)) {
 		if (!is_secure) {
-			__program_iommu(iommu_drvdata->base,
-				iommu_drvdata->bfb_settings);
+			__program_iommu(iommu_drvdata->base);
 		} else {
 			ret = msm_iommu_sec_program_iommu(
 				iommu_drvdata->sec_id);
@@ -578,6 +582,8 @@
 				goto fail;
 			}
 		}
+		program_iommu_bfb_settings(iommu_drvdata->base,
+					   iommu_drvdata->bfb_settings);
 	}
 
 	__program_context(iommu_drvdata, ctx_drvdata, __pa(priv->pt.fl_table),
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index a6483b9..490fac8 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -362,6 +362,11 @@
 	}
 
 	ret = msm_iommu_sec_program_iommu(iommu_drvdata->sec_id);
+
+	/* bfb settings are always programmed by HLOS */
+	program_iommu_bfb_settings(iommu_drvdata->base,
+				   iommu_drvdata->bfb_settings);
+
 	__disable_clocks(iommu_drvdata);
 	if (ret) {
 		regulator_disable(iommu_drvdata->gdsc);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index e7d514e..dc0f7a1 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -1,5 +1,5 @@
 
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -703,7 +703,8 @@
 	if (led->wled_cfg->cs_out_en) {
 		rc = qpnp_led_masked_write(led, WLED_CURR_SINK_REG(led->base),
 			WLED_CURR_SINK_MASK,
-			(led->wled_cfg->num_strings << WLED_CURR_SINK_SHFT));
+			(((1 << led->wled_cfg->num_strings) - 1)
+			<< WLED_CURR_SINK_SHFT));
 		if (rc) {
 			dev_err(&led->spmi_dev->dev,
 				"WLED curr sink reg write failed(%d)\n", rc);
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 0d2d91c..830ba81 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1195,8 +1195,28 @@
 	help
 	  Enable printk() debug for msm camera
 
-
+if MSM_CAMERA
 source "drivers/media/video/msm/Kconfig"
+endif # MSM_CAMERA
+
+menuconfig MSMB_CAMERA
+	bool "Qualcomm MSM camera and video capture 2.0 support"
+	depends on ARCH_MSM && VIDEO_V4L2 && I2C
+	---help---
+	  Say Y here to enable selecting the video adapters for
+	  Qualcomm msm camera and video capture 2.0, enabling this
+	  adds support for the camera driver stack including sensor, isp
+	  and postprocessing drivers.
+
+config MSMB_CAMERA_DEBUG
+	bool "Qualcomm MSM camera 2.0 debugging with printk"
+	depends on MSMB_CAMERA
+	---help---
+	  Enable printk() debug for msm camera 2.0
+
+if MSMB_CAMERA
+source "drivers/media/video/msmb/Kconfig"
+endif # MSMB_CAMERA
 
 endif # V4L_PLATFORM_DRIVERS
 endif # VIDEO_CAPTURE_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index fd736c3..e732773 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -213,6 +213,7 @@
 obj-y	+= davinci/
 
 obj-$(CONFIG_MSM_CAMERA) += msm/
+obj-$(CONFIG_MSMB_CAMERA) += msmb/
 obj-$(CONFIG_ARCH_OMAP)	+= omap/
 obj-$(CONFIG_MSM_VIDC_V4L2) += msm_vidc/
 obj-$(CONFIG_MSM_WFD) += msm_wfd/
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 56d3e0c..67ac906 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -22,7 +22,8 @@
   obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
 endif
 obj-$(CONFIG_MSM_CAMERA) += vfe/
-obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/ mercury/ jpeg_10/
+obj-$(CONFIG_MSM_CAMERA) += msm_axi_qos.o gemini/ mercury/
+obj-$(CONFIG_MSM_JPEG) += jpeg_10/
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   obj-$(CONFIG_ARCH_MSM8X60) += msm_vpe.o
   obj-$(CONFIG_ARCH_MSM7X30) += msm_vpe.o msm_axi_qos.o
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 955f4ca..78015e4 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -717,7 +717,8 @@
 	if (vb) {
 		vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
 		if (!(fill_buf_done->flags1 &
-			HAL_BUFFERFLAG_TIMESTAMPINVALID)) {
+			HAL_BUFFERFLAG_TIMESTAMPINVALID) &&
+			fill_buf_done->filled_len1) {
 			int64_t time_usec = fill_buf_done->timestamp_hi;
 			time_usec = (time_usec << 32) |
 				fill_buf_done->timestamp_lo;
@@ -2100,7 +2101,7 @@
 	op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
 
 	if (ip_flush && !op_flush) {
-		dprintk(VIDC_WARN, "Input only flush not supported\n");
+		dprintk(VIDC_INFO, "Input only flush not supported\n");
 		return 0;
 	}
 	if (inst->state == MSM_VIDC_CORE_INVALID ||
diff --git a/drivers/media/video/msmb/Kconfig b/drivers/media/video/msmb/Kconfig
new file mode 100644
index 0000000..c128b0d
--- /dev/null
+++ b/drivers/media/video/msmb/Kconfig
@@ -0,0 +1,93 @@
+config MSM_CAMERA_SENSOR
+	    bool "Qualcomm MSM camera sensor support"
+	    depends on MSMB_CAMERA
+        ---help---
+          This flag enables support for Camera Sensor.
+          The sensor driver is capable of providing real time
+          data for camera support. The driver support V4L2
+          subdev APIs.
+
+config MSM_CPP
+        bool "Qualcomm MSM Camera Post Processing Engine support"
+        depends on MSMB_CAMERA
+        ---help---
+          Enable support for Camera Post-processing Engine
+          The Post processing engine is capable of scaling
+          and cropping image. The driver support V4L2 subdev
+          APIs.
+
+config MSM_CCI
+        bool "Qualcomm MSM Camera Control Interface support"
+        depends on MSMB_CAMERA
+        ---help---
+          Enable support for Camera Control Interface driver only
+          for those platforms that have hardware support. This driver
+          is responsible for handling I2C read and write on the I2C
+          bus. It is also responsible for synchronization with
+          GPIO and data frames.
+
+config MSM_CSI20_HEADER
+        bool "Qualcomm MSM CSI 2.0 Header"
+        depends on MSMB_CAMERA
+        ---help---
+          Enable support for CSI drivers to include 2.0
+          header. This header has register macros and its
+          values and bit mask for register configuration bits
+          This config macro is required targets based on 8960,
+          8930 and 8064 platforms.
+
+config MSM_CSI30_HEADER
+        bool "Qualcomm MSM CSI 3.0 Header"
+        depends on MSMB_CAMERA
+        ---help---
+          Enable support for CSI drivers to include 3.0
+          header. This header has register macros and its
+          values and bit mask for register configuration bits
+          This config macro is required for targets based on
+          8064 platforms.
+
+config MSM_CSIPHY
+        bool "Qualcomm MSM Camera Serial Interface Physical receiver support"
+        depends on MSMB_CAMERA
+        ---help---
+          Enable support for Camera Serial Interface
+          Physical receiver. It deserializes packets and
+          supports detection of packet start and stop
+          signalling.
+
+config MSM_CSID
+        bool "Qualcomm MSM Camera Serial Interface decoder support"
+        depends on MSMB_CAMERA
+        ---help---
+          Enable support for Camera Serial Interface decoder.
+          It supports lane merging and decoding of packets
+          based on cid which is mapped to a virtual channel
+          and datatype.
+
+config MSM_ISPIF
+        bool "Qualcomm MSM Image Signal Processing interface support"
+        depends on MSMB_CAMERA
+        ---help---
+          Enable support for Image Signal Processing interface module.
+          This module acts as a crossbar between CSID and VFE. Output
+          of any CID of CSID can be routed to of of pixel or raw
+          data interface in VFE.
+
+config S5K3L1YX
+	bool "Sensor S5K3L1YX (BAYER 12M)"
+	depends on MSMB_CAMERA
+	---help---
+		Samsung 12 MP Bayer Sensor with auto focus, uses
+		4 mipi lanes, preview config = 1984 * 1508 at 30 fps,
+		snapshot config = 4000 * 3000 at 20 fps,
+		hfr video at 60, 90 and 120 fps.
+
+config MSM_V4L2_VIDEO_OVERLAY_DEVICE
+	tristate "Qualcomm MSM V4l2 video overlay device"
+	---help---
+	  Enables support for the MSM V4L2 video
+	  overlay driver. This allows video rendering
+	  apps to render overlaid video using Video4Linux2
+	  APIs, by using /dev/videoX device
+
+
diff --git a/drivers/media/video/msmb/Makefile b/drivers/media/video/msmb/Makefile
new file mode 100644
index 0000000..3986128
--- /dev/null
+++ b/drivers/media/video/msmb/Makefile
@@ -0,0 +1,14 @@
+ccflags-y += -Idrivers/media/video/msmb
+ccflags-y += -Idrivers/media/video/msmb/sensor
+ccflags-y += -Idrivers/media/video/msmb/codecs
+ccflags-y += -Idrivers/media/video/msmb/isps
+ccflags-y += -Idrivers/media/video/msmb/pps
+ccflags-y += -Idrivers/media/video/msmb/msm_vb2
+ccflags-y += -Idrivers/media/video/msmb/camera
+
+obj-$(CONFIG_MSMB_CAMERA) += msm.o
+obj-$(CONFIG_MSMB_CAMERA) += camera/
+obj-$(CONFIG_MSMB_CAMERA) += msm_vb2/
+obj-$(CONFIG_MSMB_CAMERA) += sensor/
+obj-$(CONFIG_MSMB_CAMERA) += isp/
+obj-$(CONFIG_MSMB_CAMERA) += ispif/
diff --git a/drivers/media/video/msmb/camera/Makefile b/drivers/media/video/msmb/camera/Makefile
new file mode 100644
index 0000000..89ff167
--- /dev/null
+++ b/drivers/media/video/msmb/camera/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/video/msmb
+ccflags-y += -Idrivers/media/video/msmb/msm_vb2
+obj-$(CONFIG_MSMB_CAMERA) += camera.o
diff --git a/drivers/media/video/msmb/camera/camera.c b/drivers/media/video/msmb/camera/camera.c
new file mode 100644
index 0000000..c726958
--- /dev/null
+++ b/drivers/media/video/msmb/camera/camera.c
@@ -0,0 +1,706 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/spinlock.h>
+#include <linux/proc_fs.h>
+#include <linux/atomic.h>
+#include <linux/wait.h>
+#include <linux/videodev2.h>
+#include <linux/msm_ion.h>
+#include <linux/iommu.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-fh.h>
+
+#include "camera.h"
+#include "msm.h"
+#include "msm_vb2.h"
+
+#define fh_to_private(__fh) \
+	container_of(__fh, struct camera_v4l2_private, fh)
+
+struct camera_v4l2_private {
+	struct v4l2_fh fh;
+	unsigned int stream_id;
+	struct vb2_queue vb2_q;
+};
+
+static void camera_pack_event(struct file *filep, int evt_id,
+	int command, struct v4l2_event *event)
+{
+	struct msm_v4l2_event_data *event_data =
+		(struct msm_v4l2_event_data *)&event->u.data[0];
+	struct msm_video_device *pvdev = video_drvdata(filep);
+	struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
+
+	/* always MSM_CAMERA_V4L2_EVENT_TYPE */
+	event->type = MSM_CAMERA_V4L2_EVENT_TYPE;
+	event->id = evt_id;
+	event_data->command = command;
+	event_data->session_id = pvdev->vdev->num;
+	event_data->stream_id = sp->stream_id;
+}
+
+static int camera_check_event_status(struct v4l2_event *event)
+{
+	struct msm_v4l2_event_data *event_data =
+		(struct msm_v4l2_event_data *)&event->u.data[0];
+
+	if (event_data->status > MSM_CAMERA_ERR_EVT_BASE)
+		return -EFAULT;
+
+	return 0;
+}
+
+static int camera_v4l2_querycap(struct file *filep, void *fh,
+	struct v4l2_capability *cap)
+{
+	int rc;
+	struct v4l2_event event;
+
+	/* can use cap->driver to make differentiation */
+	camera_pack_event(filep, MSM_CAMERA_GET_PARM,
+		MSM_CAMERA_PRIV_QUERY_CAP, &event);
+
+	rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+	if (rc < 0)
+		return rc;
+
+	rc = camera_check_event_status(&event);
+
+	return rc;
+}
+
+static int camera_v4l2_s_crop(struct file *filep, void *fh,
+	struct v4l2_crop *crop)
+{
+	int rc = 0;
+	struct v4l2_event event;
+
+	if (crop->type == V4L2_BUF_TYPE_PRIVATE) {
+
+		camera_pack_event(filep, MSM_CAMERA_SET_PARM,
+			MSM_CAMERA_PRIV_S_CROP, &event);
+
+		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+		if (rc < 0)
+			return rc;
+
+		rc = camera_check_event_status(&event);
+	}
+
+	return rc;
+}
+
+static int camera_v4l2_g_crop(struct file *filep, void *fh,
+	struct v4l2_crop *crop)
+{
+	int rc = 0;
+	struct v4l2_event event;
+
+	if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		camera_pack_event(filep, MSM_CAMERA_GET_PARM,
+			MSM_CAMERA_PRIV_G_CROP, &event);
+
+		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+		if (rc < 0)
+			return rc;
+
+		rc = camera_check_event_status(&event);
+	}
+
+	return rc;
+}
+
+static int camera_v4l2_queryctrl(struct file *filep, void *fh,
+	struct v4l2_queryctrl *ctrl)
+{
+	int rc = 0;
+	struct v4l2_event event;
+
+	if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
+
+		camera_pack_event(filep, MSM_CAMERA_GET_PARM,
+			ctrl->id, &event);
+
+		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+		if (rc < 0)
+			return rc;
+
+		rc = camera_check_event_status(&event);
+	}
+
+	return rc;
+}
+
+static int camera_v4l2_g_ctrl(struct file *filep, void *fh,
+	struct v4l2_control *ctrl)
+{
+	int rc = 0;
+	struct v4l2_event event;
+
+	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
+		camera_pack_event(filep, MSM_CAMERA_GET_PARM, ctrl->id, &event);
+
+		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+		if (rc < 0)
+			return rc;
+
+		rc = camera_check_event_status(&event);
+	}
+
+	return rc;
+}
+
+static int camera_v4l2_s_ctrl(struct file *filep, void *fh,
+	struct v4l2_control *ctrl)
+{
+	int rc = 0;
+	struct v4l2_event event;
+	if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
+		camera_pack_event(filep, MSM_CAMERA_SET_PARM, ctrl->id, &event);
+
+		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+		if (rc < 0)
+			return rc;
+
+		rc = camera_check_event_status(&event);
+	}
+
+	return rc;
+}
+
+static int camera_v4l2_reqbufs(struct file *filep, void *fh,
+	struct v4l2_requestbuffers *req)
+{
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+
+	return vb2_reqbufs(&sp->vb2_q, req);
+}
+
+static int camera_v4l2_querybuf(struct file *filep, void *fh,
+	struct v4l2_buffer *pb)
+{
+	return 0;
+}
+
+static int camera_v4l2_qbuf(struct file *filep, void *fh,
+	struct v4l2_buffer *pb)
+{
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+
+	return vb2_qbuf(&sp->vb2_q, pb);
+}
+
+static int camera_v4l2_dqbuf(struct file *filep, void *fh,
+	struct v4l2_buffer *pb)
+{
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+
+	return vb2_dqbuf(&sp->vb2_q, pb, filep->f_flags & O_NONBLOCK);
+}
+
+static int camera_v4l2_streamon(struct file *filep, void *fh,
+	enum v4l2_buf_type buf_type)
+{
+	struct v4l2_event event;
+	int rc;
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+
+	rc = vb2_streamon(&sp->vb2_q, buf_type);
+	camera_pack_event(filep, MSM_CAMERA_SET_PARM,
+		MSM_CAMERA_PRIV_STREAM_ON, &event);
+
+	rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+	if (rc < 0)
+		return rc;
+
+	rc = camera_check_event_status(&event);
+	return rc;
+}
+
+static int camera_v4l2_streamoff(struct file *filep, void *fh,
+		enum v4l2_buf_type buf_type)
+{
+	struct v4l2_event event;
+	int rc;
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+
+	camera_pack_event(filep, MSM_CAMERA_SET_PARM,
+		MSM_CAMERA_PRIV_STREAM_OFF, &event);
+
+	rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+	if (rc < 0)
+		return rc;
+
+	rc = camera_check_event_status(&event);
+	vb2_streamoff(&sp->vb2_q, buf_type);
+	return rc;
+}
+
+static int camera_v4l2_g_fmt_cap_private(struct file *filep, void *fh,
+	struct v4l2_format *pfmt)
+{
+	int rc = -EINVAL;
+
+	if (pfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		struct v4l2_event event;
+
+		camera_pack_event(filep, MSM_CAMERA_GET_PARM,
+			MSM_CAMERA_PRIV_G_FMT, &event);
+
+		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+		if (rc < 0)
+			return rc;
+
+		rc = camera_check_event_status(&event);
+	}
+
+	return rc;
+}
+
+static int camera_v4l2_s_fmt_cap_private(struct file *filep, void *fh,
+	struct v4l2_format *pfmt)
+{
+	int rc = 0;
+	int i = 0;
+	struct v4l2_event event;
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+	struct msm_v4l2_format_data *user_fmt;
+
+	if (pfmt->type == V4L2_BUF_TYPE_PRIVATE) {
+
+		if (WARN_ON(!sp->vb2_q.drv_priv))
+			return -ENOMEM;
+
+		memcpy(sp->vb2_q.drv_priv, pfmt->fmt.raw_data,
+			sizeof(struct msm_v4l2_format_data));
+		user_fmt = (struct msm_v4l2_format_data *)sp->vb2_q.drv_priv;
+
+		pr_debug("%s: num planes :%c\n", __func__,
+					user_fmt->num_planes);
+		for (i = 0; i < user_fmt->num_planes; i++)
+			pr_debug("%s: plane size[%d]\n", __func__,
+					user_fmt->plane_sizes[i]);
+
+		camera_pack_event(filep, MSM_CAMERA_SET_PARM,
+			MSM_CAMERA_PRIV_S_FMT, &event);
+
+		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+		if (rc < 0)
+			goto set_fmt_fail;
+
+		rc = camera_check_event_status(&event);
+		if (rc < 0)
+			goto set_fmt_fail;
+	}
+
+	return rc;
+
+set_fmt_fail:
+	kfree(sp->vb2_q.drv_priv);
+	return rc;
+}
+
+static int camera_v4l2_try_fmt_cap_private(struct file *filep, void *fh,
+	struct v4l2_format *pfmt)
+{
+	return 0;
+}
+
+int camera_v4l2_g_fmt_vid_cap_mplane(struct file *file, void *fh,
+	struct v4l2_format *f)
+{
+	return 0;
+}
+
+static int camera_v4l2_g_parm(struct file *filep, void *fh,
+	struct v4l2_streamparm *a)
+{
+	/* TODO */
+	return 0;
+}
+
+static int camera_v4l2_s_parm(struct file *filep, void *fh,
+	struct v4l2_streamparm *parm)
+{
+	int rc = 0;
+	struct v4l2_event event;
+	struct msm_v4l2_event_data *event_data =
+		(struct msm_v4l2_event_data *)&event.u.data[0];
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+
+	camera_pack_event(filep, MSM_CAMERA_SET_PARM,
+		MSM_CAMERA_PRIV_NEW_STREAM, &event);
+
+	rc = msm_create_stream(event_data->session_id,
+		event_data->stream_id, &sp->vb2_q);
+	if (rc < 0)
+		return rc;
+
+	rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+	if (rc < 0)
+		goto error;
+
+	rc = camera_check_event_status(&event);
+	if (rc < 0)
+		goto error;
+
+	/* use stream_id as stream index */
+	parm->parm.capture.extendedmode = sp->stream_id;
+
+	return rc;
+
+error:
+	msm_delete_stream(event_data->session_id,
+		event_data->stream_id);
+	return rc;
+}
+
+static int camera_v4l2_subscribe_event(struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub)
+{
+	int rc = 0;
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+
+	rc = v4l2_event_subscribe(&sp->fh, sub, 5);
+
+	return rc;
+}
+
+static int camera_v4l2_unsubscribe_event(struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub)
+{
+	int rc = 0;
+	struct camera_v4l2_private *sp = fh_to_private(fh);
+
+	rc = v4l2_event_unsubscribe(&sp->fh, sub);
+
+	return rc;
+}
+
+static const struct v4l2_ioctl_ops camera_v4l2_ioctl_ops = {
+	.vidioc_querycap = camera_v4l2_querycap,
+	.vidioc_s_crop = camera_v4l2_s_crop,
+	.vidioc_g_crop = camera_v4l2_g_crop,
+	.vidioc_queryctrl = camera_v4l2_queryctrl,
+	.vidioc_g_ctrl = camera_v4l2_g_ctrl,
+	.vidioc_s_ctrl = camera_v4l2_s_ctrl,
+	.vidioc_reqbufs = camera_v4l2_reqbufs,
+	.vidioc_querybuf = camera_v4l2_querybuf,
+	.vidioc_qbuf = camera_v4l2_qbuf,
+	.vidioc_dqbuf = camera_v4l2_dqbuf,
+	.vidioc_streamon =  camera_v4l2_streamon,
+	.vidioc_streamoff = camera_v4l2_streamoff,
+	.vidioc_g_fmt_type_private = camera_v4l2_g_fmt_cap_private,
+	.vidioc_s_fmt_type_private = camera_v4l2_s_fmt_cap_private,
+	.vidioc_try_fmt_type_private = camera_v4l2_try_fmt_cap_private,
+	.vidioc_g_fmt_vid_cap_mplane = camera_v4l2_g_fmt_vid_cap_mplane,
+
+	/* Stream type-dependent parameter ioctls */
+	.vidioc_g_parm = camera_v4l2_g_parm,
+	.vidioc_s_parm = camera_v4l2_s_parm,
+
+	/* event subscribe/unsubscribe */
+	.vidioc_subscribe_event = camera_v4l2_subscribe_event,
+	.vidioc_unsubscribe_event = camera_v4l2_unsubscribe_event,
+};
+
+static int camera_v4l2_fh_open(struct file *filep)
+{
+	struct msm_video_device *pvdev = video_drvdata(filep);
+	struct camera_v4l2_private *sp;
+
+	sp = kzalloc(sizeof(*sp), GFP_KERNEL);
+	if (!sp)
+		return -ENOMEM;
+
+	filep->private_data = &sp->fh;
+
+	/* stream_id = open id */
+	sp->stream_id = atomic_read(&pvdev->opened);
+
+	v4l2_fh_init(&sp->fh, pvdev->vdev);
+	v4l2_fh_add(&sp->fh);
+
+	return 0;
+}
+
+static int camera_v4l2_fh_release(struct file *filep)
+{
+	struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
+
+	if (sp) {
+		v4l2_fh_del(&sp->fh);
+		v4l2_fh_exit(&sp->fh);
+	}
+
+	kfree(sp);
+	return 0;
+}
+
+static int camera_v4l2_vb2_q_init(struct file *filep)
+{
+	struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
+	struct vb2_queue *q = &sp->vb2_q;
+
+	memset(q, 0, sizeof(struct vb2_queue));
+
+	/* free up this buffer when stream is done */
+	q->drv_priv =
+		kzalloc(sizeof(struct msm_v4l2_format_data), GFP_KERNEL);
+	if (!q->drv_priv)
+		return -ENOMEM;
+
+	q->mem_ops = msm_vb2_get_q_mem_ops();
+	q->ops = msm_vb2_get_q_ops();
+
+	/* default queue type */
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	q->io_modes = VB2_USERPTR;
+	q->io_flags = 0;
+	q->buf_struct_size = sizeof(struct msm_vb2_buffer);
+	vb2_queue_init(q);
+
+	return 0;
+}
+
+static void camera_v4l2_vb2_q_release(struct file *filep)
+{
+	struct camera_v4l2_private *sp = filep->private_data;
+
+	kfree(sp->vb2_q.drv_priv);
+	vb2_queue_release(&sp->vb2_q);
+}
+
+static int camera_v4l2_open(struct file *filep)
+{
+	int rc = 0;
+	struct v4l2_event event;
+	struct msm_video_device *pvdev = video_drvdata(filep);
+	BUG_ON(!pvdev);
+
+	rc = camera_v4l2_fh_open(filep);
+	if (rc < 0)
+		goto fh_open_fail;
+
+	/* every stream has a vb2 queue */
+	rc = camera_v4l2_vb2_q_init(filep);
+	if (rc < 0)
+		goto vb2_q_fail;
+
+	if (!atomic_read(&pvdev->opened)) {
+
+		/* create a new session when first opened */
+		rc = msm_create_session(pvdev->vdev->num, pvdev->vdev);
+		if (rc < 0)
+			goto session_fail;
+
+		rc = msm_create_command_ack_q(pvdev->vdev->num, 0);
+		if (rc < 0)
+			goto command_ack_q_fail;
+
+		camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, &event);
+		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+		if (rc < 0)
+			goto post_fail;
+
+		rc = camera_check_event_status(&event);
+		if (rc < 0)
+			goto post_fail;
+	} else {
+		rc = msm_create_command_ack_q(pvdev->vdev->num,
+			atomic_read(&pvdev->opened));
+		if (rc < 0)
+			goto session_fail;
+	}
+
+	atomic_add(1, &pvdev->opened);
+	return rc;
+
+post_fail:
+	msm_delete_command_ack_q(pvdev->vdev->num, 0);
+command_ack_q_fail:
+	msm_destroy_session(pvdev->vdev->num);
+session_fail:
+	camera_v4l2_vb2_q_release(filep);
+vb2_q_fail:
+	camera_v4l2_fh_release(filep);
+fh_open_fail:
+	return rc;
+}
+
+static unsigned int camera_v4l2_poll(struct file *filep,
+	struct poll_table_struct *wait)
+{
+	int rc = 0;
+	struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
+
+	rc = vb2_poll(&sp->vb2_q, filep, wait);
+
+	poll_wait(filep, &sp->fh.wait, wait);
+	if (v4l2_event_pending(&sp->fh))
+		rc |= POLLPRI;
+
+	return rc;
+}
+
+static int camera_v4l2_close(struct file *filep)
+{
+	int rc = 0;
+	struct v4l2_event event;
+	struct msm_video_device *pvdev = video_drvdata(filep);
+	struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
+
+	BUG_ON(!pvdev);
+
+	atomic_sub_return(1, &pvdev->opened);
+
+	if (atomic_read(&pvdev->opened) == 0) {
+
+		camera_pack_event(filep, MSM_CAMERA_DEL_SESSION, 0, &event);
+
+		/* Donot wait, imaging server may have crashed */
+		msm_post_event(&event, -1);
+
+		/* This should take care of both normal close
+		 * and application crashes */
+		msm_destroy_session(pvdev->vdev->num);
+
+	} else {
+		camera_pack_event(filep, MSM_CAMERA_SET_PARM,
+			MSM_CAMERA_PRIV_DEL_STREAM, &event);
+
+		/* Donot wait, imaging server may have crashed */
+		msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+
+		msm_delete_command_ack_q(pvdev->vdev->num,
+			sp->stream_id);
+
+		msm_delete_stream(pvdev->vdev->num, sp->stream_id);
+	}
+
+	camera_v4l2_vb2_q_release(filep);
+	camera_v4l2_fh_release(filep);
+
+	return rc;
+}
+
+static struct v4l2_file_operations camera_v4l2_fops = {
+	.owner   = THIS_MODULE,
+	.open	= camera_v4l2_open,
+	.poll	= camera_v4l2_poll,
+	.release = camera_v4l2_close,
+	.ioctl   = video_ioctl2,
+};
+
+int camera_init_v4l2(struct device *dev, unsigned int *session)
+{
+	struct msm_video_device *pvdev;
+	struct v4l2_device *v4l2_dev;
+	int rc = 0;
+
+	pvdev = kzalloc(sizeof(struct msm_video_device),
+		GFP_KERNEL);
+	if (WARN_ON(!pvdev)) {
+		rc = -ENOMEM;
+		goto init_end;
+	}
+
+	pvdev->vdev = video_device_alloc();
+	if (WARN_ON(!pvdev->vdev)) {
+		rc = -ENOMEM;
+		goto video_fail;
+	}
+
+	v4l2_dev = kzalloc(sizeof(struct v4l2_device), GFP_KERNEL);
+	if (WARN_ON(!v4l2_dev)) {
+		rc = -ENOMEM;
+		goto v4l2_fail;
+	}
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	v4l2_dev->mdev = kzalloc(sizeof(struct media_device),
+							 GFP_KERNEL);
+	if (!v4l2_dev->mdev) {
+		rc = -ENOMEM;
+		goto mdev_fail;
+	}
+	strlcpy(v4l2_dev->mdev->model, MSM_CAMERA_NAME,
+			sizeof(v4l2_dev->mdev->model));
+
+	v4l2_dev->mdev->dev = dev;
+
+	rc = media_device_register(v4l2_dev->mdev);
+	if (WARN_ON(rc < 0))
+		goto media_fail;
+
+	rc = media_entity_init(&pvdev->vdev->entity, 0, NULL, 0);
+	if (WARN_ON(rc < 0))
+		goto entity_fail;
+	pvdev->vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+	pvdev->vdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
+#endif
+
+	v4l2_dev->notify = NULL;
+	pvdev->vdev->v4l2_dev = v4l2_dev;
+
+	rc = v4l2_device_register(dev, pvdev->vdev->v4l2_dev);
+	if (WARN_ON(rc < 0))
+		goto register_fail;
+
+	strlcpy(pvdev->vdev->name, "msm-sensor", sizeof(pvdev->vdev->name));
+	pvdev->vdev->release  = video_device_release;
+	pvdev->vdev->fops     = &camera_v4l2_fops;
+	pvdev->vdev->ioctl_ops = &camera_v4l2_ioctl_ops;
+	pvdev->vdev->minor     = -1;
+	pvdev->vdev->vfl_type  = VFL_TYPE_GRABBER;
+	rc = video_register_device(pvdev->vdev,
+		VFL_TYPE_GRABBER, -1);
+	if (WARN_ON(rc < 0))
+		goto video_register_fail;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	/* FIXME: How to get rid of this messy? */
+	pvdev->vdev->entity.name = video_device_node_name(pvdev->vdev);
+#endif
+
+	*session = pvdev->vdev->num;
+	atomic_set(&pvdev->opened, 0);
+	video_set_drvdata(pvdev->vdev, pvdev);
+	goto init_end;
+
+video_register_fail:
+	v4l2_device_unregister(pvdev->vdev->v4l2_dev);
+register_fail:
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	media_entity_cleanup(&pvdev->vdev->entity);
+entity_fail:
+	media_device_unregister(v4l2_dev->mdev);
+media_fail:
+	kfree(v4l2_dev->mdev);
+mdev_fail:
+#endif
+	kfree(v4l2_dev);
+v4l2_fail:
+	video_device_release(pvdev->vdev);
+video_fail:
+	kfree(pvdev);
+init_end:
+	return rc;
+}
diff --git a/arch/arm/boot/dts/msm8910-sim.dts b/drivers/media/video/msmb/camera/camera.h
similarity index 63%
copy from arch/arm/boot/dts/msm8910-sim.dts
copy to drivers/media/video/msmb/camera/camera.h
index aae88b1..ac860a4 100644
--- a/arch/arm/boot/dts/msm8910-sim.dts
+++ b/drivers/media/video/msmb/camera/camera.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,16 +10,14 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
+#ifndef _CAMERA_H
+#define _CAMERA_H
 
-/include/ "msm8910.dtsi"
-
-/ {
-	model = "Qualcomm MSM 8910 Simulator";
-	compatible = "qcom,msm8910-sim", "qcom,msm8910";
-	qcom,msm-id = <147 1 0>;
-
-	serial@f991f000 {
-		status = "ok";
-	};
+enum stream_state {
+	START_STREAM = 0,
+	STOP_STREAM,
 };
+
+int camera_init_v4l2(struct device *dev, unsigned int *session);
+
+#endif /*_CAMERA_H */
diff --git a/drivers/media/video/msmb/isp/Makefile b/drivers/media/video/msmb/isp/Makefile
new file mode 100644
index 0000000..e517798
--- /dev/null
+++ b/drivers/media/video/msmb/isp/Makefile
@@ -0,0 +1,4 @@
+ccflags-y += -Idrivers/media/video/msmb
+ccflags-y += -Idrivers/media/video/msmb/sensor/io
+obj-$(CONFIG_MSMB_CAMERA) += msm_isp.o msm_buf_mgr.o msm_isp_util.o msm_isp_axi_util.o msm_isp_stats_util.o
+obj-$(CONFIG_MSMB_CAMERA) += msm_isp40.o
diff --git a/drivers/media/video/msmb/isp/msm_buf_mgr.c b/drivers/media/video/msmb/isp/msm_buf_mgr.c
new file mode 100644
index 0000000..aab97d7
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_buf_mgr.c
@@ -0,0 +1,604 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+#include <linux/proc_fs.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/android_pmem.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf2-core.h>
+#include <media/msm_camera.h>
+#include <media/msm_isp.h>
+
+#include <mach/iommu.h>
+
+#include "msm.h"
+#include "msm_buf_mgr.h"
+
+/*#define CONFIG_MSM_ISP_DBG*/
+#undef CDBG
+#ifdef CONFIG_MSM_ISP_DBG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+static struct msm_isp_bufq *msm_isp_get_bufq(
+	struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t bufq_handle)
+{
+	struct msm_isp_bufq *bufq = NULL;
+	uint32_t bufq_index = bufq_handle & 0xFF;
+	if (bufq_index > buf_mgr->num_buf_q)
+		return bufq;
+
+	bufq = &buf_mgr->bufq[bufq_index];
+	if (bufq->bufq_handle == bufq_handle)
+		return bufq;
+
+	return NULL;
+}
+
+static struct msm_isp_buffer *msm_isp_get_buf_ptr(
+	struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t bufq_handle, uint32_t buf_index)
+{
+	struct msm_isp_bufq *bufq = NULL;
+	struct msm_isp_buffer *buf_info = NULL;
+
+	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
+	if (!bufq) {
+		pr_err("%s: Invalid bufq\n", __func__);
+		return buf_info;
+	}
+
+	if (bufq->num_bufs <= buf_index) {
+		pr_err("%s: Invalid buf index\n", __func__);
+		return buf_info;
+	}
+	buf_info = &bufq->bufs[buf_index];
+	return buf_info;
+}
+
+static uint32_t msm_isp_get_buf_handle(
+	struct msm_isp_buf_mgr *buf_mgr)
+{
+	int i;
+	if ((buf_mgr->buf_handle_cnt << 8) == 0)
+		buf_mgr->buf_handle_cnt++;
+
+	for (i = 0; i < buf_mgr->num_buf_q; i++) {
+		if (buf_mgr->bufq[i].bufq_handle == 0) {
+			memset(&buf_mgr->bufq[i],
+				0, sizeof(struct msm_isp_bufq));
+			buf_mgr->bufq[i].bufq_handle =
+				(++buf_mgr->buf_handle_cnt) << 8 | i;
+			return buf_mgr->bufq[i].bufq_handle;
+		}
+	}
+	return 0;
+}
+
+static int msm_isp_free_buf_handle(struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t bufq_handle)
+{
+	struct msm_isp_bufq *bufq =
+		msm_isp_get_bufq(buf_mgr, bufq_handle);
+	if (!bufq)
+		return -EINVAL;
+	memset(bufq, 0, sizeof(struct msm_isp_bufq));
+	return 0;
+}
+
+static int msm_isp_prepare_v4l2_buf(struct msm_isp_buf_mgr *buf_mgr,
+	struct msm_isp_buffer *buf_info,
+	struct v4l2_buffer *v4l2_buf)
+{
+	int i, rc = -1;
+	struct msm_isp_buffer_mapped_info *mapped_info;
+	for (i = 0; i < v4l2_buf->length; i++) {
+		mapped_info = &buf_info->mapped_info[i];
+		mapped_info->handle =
+		ion_import_dma_buf(buf_mgr->client,
+			v4l2_buf->m.planes[i].m.userptr);
+		if (IS_ERR_OR_NULL(mapped_info->handle)) {
+			pr_err("%s: buf has null/error ION handle %p\n",
+				__func__, mapped_info->handle);
+			goto ion_map_error;
+		}
+		if (ion_map_iommu(buf_mgr->client, mapped_info->handle,
+				buf_mgr->iommu_domain_num, 0, SZ_4K,
+				0, &(mapped_info->paddr),
+				&(mapped_info->len), 0, 0) < 0) {
+			rc = -EINVAL;
+			pr_err("%s: cannot map address", __func__);
+			ion_free(buf_mgr->client, mapped_info->handle);
+			goto ion_map_error;
+		}
+		mapped_info->paddr += v4l2_buf->m.planes[i].data_offset;
+		CDBG("%s: plane: %d addr:%lu\n",
+			__func__, i, mapped_info->paddr);
+	}
+	buf_info->num_planes = v4l2_buf->length;
+	return 0;
+ion_map_error:
+	for (--i; i >= 0; i--) {
+		mapped_info = &buf_info->mapped_info[i];
+		ion_unmap_iommu(buf_mgr->client, mapped_info->handle,
+		buf_mgr->iommu_domain_num, 0);
+		ion_free(buf_mgr->client, mapped_info->handle);
+	}
+	return rc;
+}
+
+static void msm_isp_unprepare_v4l2_buf(
+	struct msm_isp_buf_mgr *buf_mgr,
+	struct msm_isp_buffer *buf_info)
+{
+	int i;
+	struct msm_isp_buffer_mapped_info *mapped_info;
+	for (i = 0; i < buf_info->num_planes; i++) {
+		mapped_info = &buf_info->mapped_info[i];
+		ion_unmap_iommu(buf_mgr->client, mapped_info->handle,
+			buf_mgr->iommu_domain_num, 0);
+		ion_free(buf_mgr->client, mapped_info->handle);
+	}
+	return;
+}
+
+static int msm_isp_buf_prepare(struct msm_isp_buf_mgr *buf_mgr,
+	struct msm_isp_qbuf_info *info, struct vb2_buffer *vb2_buf)
+{
+	int rc = -1;
+	struct msm_isp_buffer *buf_info = NULL;
+	struct v4l2_buffer *buf = NULL;
+	struct v4l2_plane *plane = NULL;
+
+	buf_info = msm_isp_get_buf_ptr(buf_mgr,
+		info->handle, info->buf_idx);
+	if (!buf_info) {
+		pr_err("Invalid buffer prepare\n");
+		return rc;
+	}
+
+	if (buf_info->state == MSM_ISP_BUFFER_STATE_UNUSED ||
+			buf_info->state != MSM_ISP_BUFFER_STATE_INITIALIZED) {
+		pr_err("%s: Invalid buffer state: %d\n",
+			__func__, buf_info->state);
+		return rc;
+	}
+
+	if (vb2_buf) {
+		buf = &vb2_buf->v4l2_buf;
+		buf_info->vb2_buf = vb2_buf;
+	} else {
+		buf = &info->buffer;
+		plane =
+			kzalloc(sizeof(struct v4l2_plane) * buf->length,
+				GFP_KERNEL);
+		if (!plane) {
+			pr_err("%s: Cannot alloc plane: %d\n",
+			__func__, buf_info->state);
+			return rc;
+		}
+		if (copy_from_user(plane,
+				(void __user *)(buf->m.planes),
+			sizeof(struct v4l2_plane) * buf->length)) {
+			kfree(plane);
+			return rc;
+		}
+		buf->m.planes = plane;
+	}
+
+	rc = msm_isp_prepare_v4l2_buf(buf_mgr, buf_info, buf);
+	if (rc < 0) {
+		pr_err("%s: Prepare buffer error\n", __func__);
+		kfree(plane);
+		return rc;
+	}
+	buf_info->state = MSM_ISP_BUFFER_STATE_PREPARED;
+	kfree(plane);
+	return rc;
+}
+
+static int msm_isp_buf_unprepare(struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t buf_handle)
+{
+	int rc = -1, i;
+	struct msm_isp_bufq *bufq = NULL;
+	struct msm_isp_buffer *buf_info = NULL;
+	bufq = msm_isp_get_bufq(buf_mgr, buf_handle);
+	if (!bufq) {
+		pr_err("%s: Invalid bufq\n", __func__);
+		return rc;
+	}
+
+	for (i = 0; i < bufq->num_bufs; i++) {
+		buf_info = msm_isp_get_buf_ptr(buf_mgr, buf_handle, i);
+		if (buf_info->state == MSM_ISP_BUFFER_STATE_UNUSED ||
+				buf_info->state ==
+					MSM_ISP_BUFFER_STATE_INITIALIZED)
+			continue;
+		msm_isp_unprepare_v4l2_buf(buf_mgr, buf_info);
+	}
+	return 0;
+}
+
+static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t bufq_handle, struct msm_isp_buffer **buf_info)
+{
+	int rc = -1;
+	struct msm_isp_buffer *temp_buf_info;
+	struct msm_isp_bufq *bufq = NULL;
+	struct vb2_buffer *vb2_buf = NULL;
+	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
+	if (!bufq) {
+		pr_err("%s: Invalid bufq\n", __func__);
+		return rc;
+	}
+
+	*buf_info = NULL;
+	if (BUF_SRC(bufq->stream_id)) {
+		list_for_each_entry(temp_buf_info, &bufq->head, list) {
+			if (temp_buf_info->state ==
+					MSM_ISP_BUFFER_STATE_QUEUED) {
+				/* found one buf */
+				list_del_init(&temp_buf_info->list);
+				*buf_info = temp_buf_info;
+				break;
+			}
+		}
+	} else {
+		vb2_buf = buf_mgr->vb2_ops->get_buf(
+			bufq->session_id, bufq->stream_id);
+		if (vb2_buf) {
+			if (vb2_buf->v4l2_buf.index < bufq->num_bufs) {
+				*buf_info =
+					&bufq->bufs[vb2_buf->v4l2_buf.index];
+				(*buf_info)->vb2_buf = vb2_buf;
+			} else {
+				pr_err("%s: Incorrect buf index %d\n",
+					__func__, vb2_buf->v4l2_buf.index);
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (!(*buf_info)) {
+		pr_err("%s: No free buffer\n", __func__);
+		return rc;
+	}
+
+	(*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
+	return 0;
+}
+
+static int msm_isp_put_buf(struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t bufq_handle, uint32_t buf_index)
+{
+	int rc = -1;
+	struct msm_isp_bufq *bufq = NULL;
+	struct msm_isp_buffer *buf_info = NULL;
+
+	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
+	if (!bufq) {
+		pr_err("%s: Invalid bufq\n", __func__);
+		return rc;
+	}
+
+	buf_info = msm_isp_get_buf_ptr(buf_mgr, bufq_handle, buf_index);
+	if (!buf_info) {
+		pr_err("%s: buf not found\n", __func__);
+		return rc;
+	}
+
+	switch (buf_info->state) {
+	case MSM_ISP_BUFFER_STATE_PREPARED:
+	case MSM_ISP_BUFFER_STATE_DEQUEUED:
+	case MSM_ISP_BUFFER_STATE_DISPATCHED:
+		if (BUF_SRC(bufq->stream_id))
+			list_add_tail(&buf_info->list, &bufq->head);
+		else
+			buf_mgr->vb2_ops->put_buf(buf_info->vb2_buf);
+		buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
+		rc = 0;
+		break;
+	default:
+		pr_err("%s: incorrect state = %d",
+			__func__, buf_info->state);
+		break;
+	}
+
+	return rc;
+}
+
+static int msm_isp_buf_done(struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t bufq_handle, uint32_t buf_index,
+	struct timeval *tv, uint32_t frame_id)
+{
+	int rc = -1;
+	struct msm_isp_bufq *bufq = NULL;
+	struct msm_isp_buffer *buf_info = NULL;
+
+	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
+	if (!bufq) {
+		pr_err("Invalid bufq\n");
+		return rc;
+	}
+
+	buf_info = msm_isp_get_buf_ptr(buf_mgr, bufq_handle, buf_index);
+	if (!buf_info) {
+		pr_err("%s: buf not found\n", __func__);
+		return rc;
+	}
+
+	if (buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED) {
+		buf_info->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+		if (!(BUF_SRC(bufq->stream_id))) {
+			buf_info->vb2_buf->v4l2_buf.timestamp = *tv;
+			buf_info->vb2_buf->v4l2_buf.sequence  = frame_id;
+			buf_mgr->vb2_ops->buf_done(buf_info->vb2_buf);
+		}
+	}
+
+	return 0;
+}
+
+static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
+	struct msm_isp_qbuf_info *info)
+{
+	int rc;
+	struct msm_isp_bufq *bufq = NULL;
+	rc = msm_isp_buf_prepare(buf_mgr, info, NULL);
+	if (rc < 0) {
+		pr_err("%s: Buf prepare failed\n", __func__);
+		return rc;
+	}
+
+	bufq = msm_isp_get_bufq(buf_mgr, info->handle);
+	if (BUF_SRC(bufq->stream_id)) {
+		rc = msm_isp_put_buf(buf_mgr, info->handle, info->buf_idx);
+		if (rc < 0) {
+			pr_err("%s: Buf put failed\n", __func__);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
+static int msm_isp_get_bufq_handle(struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t session_id, uint32_t stream_id)
+{
+	int i;
+	for (i = 0; i < buf_mgr->num_buf_q; i++) {
+		if (buf_mgr->bufq[i].session_id == session_id &&
+			buf_mgr->bufq[i].stream_id == stream_id) {
+			return buf_mgr->bufq[i].bufq_handle;
+		}
+	}
+	return 0;
+}
+
+static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
+	struct msm_isp_buf_request *buf_request)
+{
+	int rc = -1, i;
+	struct msm_isp_bufq *bufq = NULL;
+	CDBG("%s: E\n", __func__);
+
+	if (!buf_request->num_buf) {
+		pr_err("Invalid buffer request\n");
+		return rc;
+	}
+
+	buf_request->handle = msm_isp_get_buf_handle(buf_mgr);
+	if (!buf_request->handle) {
+		pr_err("Invalid buffer handle\n");
+		return rc;
+	}
+
+	bufq = msm_isp_get_bufq(buf_mgr, buf_request->handle);
+	if (!bufq) {
+		pr_err("Invalid buffer queue\n");
+		return rc;
+	}
+
+	bufq->bufs = kzalloc(sizeof(struct msm_isp_buffer) *
+		buf_request->num_buf, GFP_KERNEL);
+	if (!bufq->bufs) {
+		pr_err("No free memory for buf info\n");
+		msm_isp_free_buf_handle(buf_mgr, buf_request->handle);
+		return rc;
+	}
+
+	bufq->bufq_handle = buf_request->handle;
+	bufq->session_id = buf_request->session_id;
+	bufq->stream_id = buf_request->stream_id;
+	bufq->num_bufs = buf_request->num_buf;
+	INIT_LIST_HEAD(&bufq->head);
+	for (i = 0; i < buf_request->num_buf; i++) {
+		bufq->bufs[i].state = MSM_ISP_BUFFER_STATE_INITIALIZED;
+		bufq->bufs[i].bufq_handle = bufq->bufq_handle;
+		bufq->bufs[i].buf_idx = i;
+	}
+
+	return 0;
+}
+
+static int msm_isp_release_bufq(struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t bufq_handle)
+{
+	struct msm_isp_bufq *bufq = NULL;
+	int rc = -1;
+	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
+	if (!bufq) {
+		pr_err("Invalid bufq release\n");
+		return rc;
+	}
+
+	msm_isp_buf_unprepare(buf_mgr, bufq_handle);
+
+	kfree(bufq->bufs);
+	msm_isp_free_buf_handle(buf_mgr, bufq_handle);
+	return 0;
+}
+
+static void msm_isp_release_all_bufq(
+	struct msm_isp_buf_mgr *buf_mgr)
+{
+	struct msm_isp_bufq *bufq = NULL;
+	int i;
+	for (i = 0; i < buf_mgr->num_buf_q; i++) {
+		bufq = &buf_mgr->bufq[i];
+		if (!bufq->bufq_handle)
+			continue;
+		msm_isp_buf_unprepare(buf_mgr, bufq->bufq_handle);
+		kfree(bufq->bufs);
+		msm_isp_free_buf_handle(buf_mgr, bufq->bufq_handle);
+	}
+}
+
+static int msm_isp_attach_ctx(struct msm_isp_buf_mgr *buf_mgr,
+	struct device *iommu_ctx)
+{
+	int rc;
+	rc = iommu_attach_device(buf_mgr->iommu_domain, iommu_ctx);
+	if (rc) {
+		pr_err("%s: Iommu attach error\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void msm_isp_detach_ctx(struct msm_isp_buf_mgr *buf_mgr,
+	struct device *iommu_ctx)
+{
+	iommu_detach_device(buf_mgr->iommu_domain, iommu_ctx);
+}
+
+static int msm_isp_init_isp_buf_mgr(
+	struct msm_isp_buf_mgr *buf_mgr,
+	const char *ctx_name, uint16_t num_buf_q)
+{
+	int rc = -1;
+	if (!num_buf_q) {
+		pr_err("Invalid buffer queue number\n");
+		return rc;
+	}
+
+	CDBG("%s: E\n", __func__);
+	buf_mgr->num_buf_q = num_buf_q;
+	buf_mgr->bufq =
+		kzalloc(sizeof(struct msm_isp_bufq) * num_buf_q,
+		GFP_KERNEL);
+	if (!buf_mgr->bufq) {
+		pr_err("Bufq malloc error\n");
+		goto bufq_error;
+	}
+	buf_mgr->client = msm_ion_client_create(-1, ctx_name);
+	buf_mgr->buf_handle_cnt = 0;
+
+	return 0;
+bufq_error:
+	return rc;
+}
+
+static int msm_isp_deinit_isp_buf_mgr(
+	struct msm_isp_buf_mgr *buf_mgr)
+{
+	msm_isp_release_all_bufq(buf_mgr);
+	ion_client_destroy(buf_mgr->client);
+	kfree(buf_mgr->bufq);
+	buf_mgr->num_buf_q = 0;
+	return 0;
+}
+
+int msm_isp_proc_buf_cmd(struct msm_isp_buf_mgr *buf_mgr,
+	unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case VIDIOC_MSM_ISP_REQUEST_BUF: {
+		struct msm_isp_buf_request *buf_req = arg;
+		buf_mgr->ops->request_buf(buf_mgr, buf_req);
+		break;
+	}
+	case VIDIOC_MSM_ISP_ENQUEUE_BUF: {
+		struct msm_isp_qbuf_info *qbuf_info = arg;
+		buf_mgr->ops->enqueue_buf(buf_mgr, qbuf_info);
+		break;
+	}
+	case VIDIOC_MSM_ISP_RELEASE_BUF: {
+		struct msm_isp_buf_request *buf_req = arg;
+		buf_mgr->ops->release_buf(buf_mgr, buf_req->handle);
+		break;
+	}
+	}
+	return 0;
+}
+
+static struct msm_isp_buf_ops isp_buf_ops = {
+	.request_buf = msm_isp_request_bufq,
+	.enqueue_buf = msm_isp_buf_enqueue,
+	.release_buf = msm_isp_release_bufq,
+	.get_bufq_handle = msm_isp_get_bufq_handle,
+	.get_buf = msm_isp_get_buf,
+	.put_buf = msm_isp_put_buf,
+	.buf_done = msm_isp_buf_done,
+	.attach_ctx = msm_isp_attach_ctx,
+	.detach_ctx = msm_isp_detach_ctx,
+	.buf_mgr_init = msm_isp_init_isp_buf_mgr,
+	.buf_mgr_deinit = msm_isp_deinit_isp_buf_mgr,
+};
+
+int msm_isp_create_isp_buf_mgr(
+	struct msm_isp_buf_mgr *buf_mgr,
+	struct msm_sd_req_vb2_q *vb2_ops,
+	struct msm_iova_layout *iova_layout)
+{
+	int rc = 0;
+	if (buf_mgr->init_done)
+		return rc;
+
+	buf_mgr->iommu_domain_num = msm_register_domain(iova_layout);
+	if (buf_mgr->iommu_domain_num < 0) {
+		pr_err("%s: Invalid iommu domain number\n", __func__);
+		rc = -1;
+		goto iommu_domain_error;
+	}
+
+	buf_mgr->iommu_domain = msm_get_iommu_domain(
+		buf_mgr->iommu_domain_num);
+	if (!buf_mgr->iommu_domain) {
+		pr_err("%s: Invalid iommu domain\n", __func__);
+		rc = -1;
+		goto iommu_domain_error;
+	}
+
+	buf_mgr->ops = &isp_buf_ops;
+	buf_mgr->vb2_ops = vb2_ops;
+	buf_mgr->init_done = 1;
+	buf_mgr->ref_count = 0;
+	return 0;
+iommu_domain_error:
+	return rc;
+}
diff --git a/drivers/media/video/msmb/isp/msm_buf_mgr.h b/drivers/media/video/msmb/isp/msm_buf_mgr.h
new file mode 100644
index 0000000..a44b5ec
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_buf_mgr.h
@@ -0,0 +1,123 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_ISP_BUF_H_
+#define _MSM_ISP_BUF_H_
+
+#include <media/msmb_isp.h>
+#include <mach/iommu_domains.h>
+#include "msm_sd.h"
+
+#define BUF_SRC_SHIFT 16
+/*Buffer source can be from userspace / HAL*/
+#define BUF_SRC(id) (id >> BUF_SRC_SHIFT)
+
+struct msm_isp_buf_mgr;
+
+enum msm_isp_buffer_state {
+	MSM_ISP_BUFFER_STATE_UNUSED,         /* not used */
+	MSM_ISP_BUFFER_STATE_INITIALIZED,    /* REQBUF done */
+	MSM_ISP_BUFFER_STATE_PREPARED,       /* BUF mapped */
+	MSM_ISP_BUFFER_STATE_QUEUED,         /* buf queued */
+	MSM_ISP_BUFFER_STATE_DEQUEUED,       /* in use in VFE */
+	MSM_ISP_BUFFER_STATE_DISPATCHED,     /* sent to userspace */
+};
+
+struct msm_isp_buffer_mapped_info {
+	unsigned long len;
+	unsigned long paddr;
+	struct ion_handle *handle;
+};
+
+struct msm_isp_buffer {
+	/*Common Data structure*/
+	int num_planes;
+	struct msm_isp_buffer_mapped_info mapped_info[VIDEO_MAX_PLANES];
+	int buf_idx;
+	uint32_t bufq_handle;
+
+	/*Native buffer*/
+	struct list_head list;
+	enum msm_isp_buffer_state state;
+
+	/*Vb2 buffer data*/
+	struct vb2_buffer *vb2_buf;
+
+};
+
+struct msm_isp_bufq {
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t num_bufs;
+	uint32_t bufq_handle;
+	struct msm_isp_buffer *bufs;
+
+	/*Native buffer queue*/
+	struct list_head head;
+};
+
+struct msm_isp_buf_ops {
+	int (*request_buf) (struct msm_isp_buf_mgr *buf_mgr,
+		struct msm_isp_buf_request *buf_request);
+
+	int (*enqueue_buf) (struct msm_isp_buf_mgr *buf_mgr,
+		struct msm_isp_qbuf_info *info);
+
+	int (*release_buf) (struct msm_isp_buf_mgr *buf_mgr,
+		uint32_t bufq_handle);
+
+	int (*get_bufq_handle) (struct msm_isp_buf_mgr *buf_mgr,
+		uint32_t session_id, uint32_t stream_id);
+
+	int (*get_buf) (struct msm_isp_buf_mgr *buf_mgr,
+		uint32_t bufq_handle, struct msm_isp_buffer **buf_info);
+
+	int (*put_buf) (struct msm_isp_buf_mgr *buf_mgr,
+		uint32_t bufq_handle, uint32_t buf_index);
+
+	int (*buf_done) (struct msm_isp_buf_mgr *buf_mgr,
+		uint32_t bufq_handle, uint32_t buf_index,
+		struct timeval *tv, uint32_t frame_id);
+	int (*attach_ctx) (struct msm_isp_buf_mgr *buf_mgr,
+		struct device *iommu_ctx);
+	void (*detach_ctx) (struct msm_isp_buf_mgr *buf_mgr,
+		struct device *iommu_ctx);
+	int (*buf_mgr_init) (struct msm_isp_buf_mgr *buf_mgr,
+		const char *ctx_name, uint16_t num_buf_q);
+	int (*buf_mgr_deinit) (struct msm_isp_buf_mgr *buf_mgr);
+};
+
+struct msm_isp_buf_mgr {
+	int init_done;
+	uint32_t ref_count;
+	spinlock_t lock;
+	uint16_t num_buf_q;
+	struct msm_isp_bufq *bufq;
+
+	struct ion_client *client;
+	struct msm_isp_buf_ops *ops;
+	uint32_t buf_handle_cnt;
+
+	struct msm_sd_req_vb2_q *vb2_ops;
+
+	/*IOMMU specific*/
+	int iommu_domain_num;
+	struct iommu_domain *iommu_domain;
+};
+
+int msm_isp_create_isp_buf_mgr(struct msm_isp_buf_mgr *buf_mgr,
+	struct msm_sd_req_vb2_q *vb2_ops, struct msm_iova_layout *iova_layout);
+
+int msm_isp_proc_buf_cmd(struct msm_isp_buf_mgr *buf_mgr,
+	unsigned int cmd, void *arg);
+
+#endif /* _MSM_ISP_BUF_H_ */
diff --git a/drivers/media/video/msmb/isp/msm_isp.c b/drivers/media/video/msmb/isp/msm_isp.c
new file mode 100644
index 0000000..960144e
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp.c
@@ -0,0 +1,166 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-device.h>
+#include <mach/board.h>
+#include <mach/vreg.h>
+#include <mach/iommu.h>
+
+#include "msm_isp.h"
+#include "msm_isp_util.h"
+#include "msm_isp_axi_util.h"
+#include "msm_isp_stats_util.h"
+#include "msm_sd.h"
+#include "msm_isp40.h"
+
+static struct msm_sd_req_vb2_q vfe_vb2_ops;
+
+static const struct of_device_id msm_vfe_dt_match[] = {
+	{
+		.compatible = "qcom,vfe40",
+		.data = &vfe40_hw_info,
+	},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_vfe_dt_match);
+
+static const struct platform_device_id msm_vfe_dev_id[] = {
+	{"msm_vfe32"},
+	{}
+};
+
+static struct msm_isp_buf_mgr vfe_buf_mgr;
+
+static int __devinit vfe_probe(struct platform_device *pdev)
+{
+	struct vfe_device *vfe_dev;
+	/*struct msm_cam_subdev_info sd_info;*/
+	const struct of_device_id *match_dev;
+	int rc = 0;
+
+	struct msm_iova_partition vfe_partition = {
+		.start = SZ_128K,
+		.size = SZ_2G - SZ_128K,
+	};
+	struct msm_iova_layout vfe_layout = {
+		.partitions = &vfe_partition,
+		.npartitions = 1,
+		.client_name = "vfe",
+		.domain_flags = 0,
+	};
+
+	vfe_dev = kzalloc(sizeof(struct vfe_device), GFP_KERNEL);
+	if (!vfe_dev) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	if (pdev->dev.of_node) {
+		of_property_read_u32((&pdev->dev)->of_node,
+			"cell-index", &pdev->id);
+		match_dev = of_match_device(msm_vfe_dt_match, &pdev->dev);
+		vfe_dev->hw_info =
+			(struct msm_vfe_hardware_info *) match_dev->data;
+	} else {
+		vfe_dev->hw_info = platform_get_drvdata(pdev);
+	}
+
+	if (!vfe_dev->hw_info) {
+		pr_err("%s: No vfe hardware info\n", __func__);
+		return -EINVAL;
+	}
+	ISP_DBG("%s: device id = %d\n", __func__, pdev->id);
+
+	vfe_dev->pdev = pdev;
+	rc = vfe_dev->hw_info->vfe_ops.core_ops.get_platform_data(vfe_dev);
+	if (rc < 0) {
+		pr_err("%s: failed to get platform resources\n", __func__);
+		kfree(vfe_dev);
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&vfe_dev->tasklet_q);
+	tasklet_init(&vfe_dev->vfe_tasklet,
+		msm_isp_do_tasklet, (unsigned long)vfe_dev);
+
+	v4l2_subdev_init(&vfe_dev->subdev.sd, vfe_dev->hw_info->subdev_ops);
+	vfe_dev->subdev.sd.internal_ops =
+		vfe_dev->hw_info->subdev_internal_ops;
+	snprintf(vfe_dev->subdev.sd.name,
+		ARRAY_SIZE(vfe_dev->subdev.sd.name),
+		"vfe");
+	vfe_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	vfe_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
+	v4l2_set_subdevdata(&vfe_dev->subdev.sd, vfe_dev);
+	platform_set_drvdata(pdev, &vfe_dev->subdev.sd);
+	mutex_init(&vfe_dev->mutex);
+	spin_lock_init(&vfe_dev->tasklet_lock);
+	spin_lock_init(&vfe_dev->shared_data_lock);
+	media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0);
+	vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
+	vfe_dev->subdev.sd.entity.name = pdev->name;
+	rc = msm_sd_register(&vfe_dev->subdev);
+	if (rc != 0) {
+		pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
+		kfree(vfe_dev);
+		goto end;
+	}
+
+	vfe_dev->buf_mgr = &vfe_buf_mgr;
+	v4l2_subdev_notify(&vfe_dev->subdev.sd,
+		MSM_SD_NOTIFY_REQ_CB, &vfe_vb2_ops);
+	rc = msm_isp_create_isp_buf_mgr(vfe_dev->buf_mgr,
+		&vfe_vb2_ops, &vfe_layout);
+	if (rc < 0) {
+		pr_err("%s: Unable to create buffer manager\n", __func__);
+		kfree(vfe_dev);
+		return -EINVAL;
+	}
+	vfe_dev->vfe_open_cnt = 0;
+end:
+	return rc;
+}
+
+static struct platform_driver vfe_driver = {
+	.probe = vfe_probe,
+	.driver = {
+		.name = "msm_vfe",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_vfe_dt_match,
+	},
+	.id_table = msm_vfe_dev_id,
+};
+
+static int __init msm_vfe_init_module(void)
+{
+	return platform_driver_register(&vfe_driver);
+}
+
+static void __exit msm_vfe_exit_module(void)
+{
+	platform_driver_unregister(&vfe_driver);
+}
+
+module_init(msm_vfe_init_module);
+module_exit(msm_vfe_exit_module);
+MODULE_DESCRIPTION("MSM VFE driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msmb/isp/msm_isp.h b/drivers/media/video/msmb/isp/msm_isp.h
new file mode 100644
index 0000000..c320a1a
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp.h
@@ -0,0 +1,347 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_VFE_H__
+#define __MSM_VFE_H__
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <media/v4l2-subdev.h>
+#include <media/msmb_isp.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+
+#include "msm_buf_mgr.h"
+
+#define MAX_NUM_WM 7
+#define MAX_NUM_RDI 3
+#define MAX_NUM_RDI_MASTER 3
+#define MAX_NUM_COMPOSITE_MASK 4
+#define MAX_NUM_STATS_COMP_MASK 2
+#define MAX_INIT_FRAME_DROP 31
+#define ISP_SUB(a) ((a > 0) ? a-1 : 0)
+
+struct vfe_device;
+struct msm_vfe_axi_stream;
+struct msm_vfe_stats_stream;
+
+struct vfe_subscribe_info {
+	struct v4l2_fh *vfh;
+	uint32_t active;
+};
+
+enum msm_isp_camif_update_state {
+	NO_UPDATE,
+	ENABLE_CAMIF,
+	DISABLE_CAMIF,
+	DISABLE_CAMIF_IMMEDIATELY
+};
+
+struct msm_vfe_irq_ops {
+	void (*read_irq_status) (struct vfe_device *vfe_dev,
+		uint32_t *irq_status0, uint32_t *irq_status1);
+	void (*process_reg_update) (struct vfe_device *vfe_dev,
+		uint32_t irq_status0, uint32_t irq_status1);
+	void (*process_reset_irq) (struct vfe_device *vfe_dev,
+		uint32_t irq_status0, uint32_t irq_status1);
+	void (*process_halt_irq) (struct vfe_device *vfe_dev,
+		uint32_t irq_status0, uint32_t irq_status1);
+	void (*process_camif_irq) (struct vfe_device *vfe_dev,
+		uint32_t irq_status0, uint32_t irq_status1);
+	void (*process_axi_irq) (struct vfe_device *vfe_dev,
+		uint32_t irq_status0, uint32_t irq_status1,
+		struct timeval *tv);
+	void (*process_error_irq) (struct vfe_device *vfe_dev,
+		uint32_t irq_status0, uint32_t irq_status1);
+	void (*process_stats_irq) (struct vfe_device *vfe_dev,
+		uint32_t irq_status0, uint32_t irq_status1,
+		struct timeval *tv);
+};
+
+struct msm_vfe_axi_ops {
+	void (*reload_wm) (struct vfe_device *vfe_dev,
+		uint32_t reload_mask);
+	void (*enable_wm) (struct vfe_device *vfe_dev,
+		uint8_t wm_idx, uint8_t enable);
+
+	void (*cfg_framedrop) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream *stream_info);
+	void (*clear_framedrop) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream *stream_info);
+	void (*cfg_comp_mask) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream *stream_info);
+	void (*clear_comp_mask) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream *stream_info);
+	void (*cfg_wm_irq_mask) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream *stream_info);
+	void (*clear_wm_irq_mask) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream *stream_info);
+
+	void (*cfg_wm_reg) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+		uint8_t plane_idx);
+	void (*clear_wm_reg) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx);
+
+	void (*cfg_wm_xbar_reg) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+		uint8_t plane_idx);
+	void (*clear_wm_xbar_reg) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx);
+
+	void (*cfg_rdi_reg) (struct vfe_device *vfe_dev,
+		struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+		uint8_t plane_idx);
+
+	void (*cfg_ub) (struct vfe_device *vfe_dev);
+
+	void (*update_ping_pong_addr) (struct vfe_device *vfe_dev,
+		uint8_t wm_idx, uint32_t pingpong_status, unsigned long paddr);
+
+	uint32_t (*get_wm_mask) (uint32_t irq_status0, uint32_t irq_status1);
+	uint32_t (*get_comp_mask) (uint32_t irq_status0, uint32_t irq_status1);
+	uint32_t (*get_pingpong_status) (struct vfe_device *vfe_dev);
+	long (*halt) (struct vfe_device *vfe_dev);
+};
+
+struct msm_vfe_core_ops {
+	void (*epoch_irq) (struct vfe_device *vfe_dev,
+		uint32_t epoch_line0, uint32_t epoch_line1);
+	void (*reg_update) (struct vfe_device *vfe_dev, uint32_t update_mask);
+	long (*reset_hw) (struct vfe_device *vfe_dev);
+	int (*init_hw) (struct vfe_device *vfe_dev);
+	void (*init_hw_reg) (struct vfe_device *vfe_dev);
+	void (*release_hw) (struct vfe_device *vfe_dev);
+	void (*cfg_camif) (struct vfe_device *vfe_dev,
+		struct msm_vfe_pix_cfg *pix_cfg);
+	void (*update_camif_state) (struct vfe_device *vfe_dev,
+		enum msm_isp_camif_update_state update_state);
+	int (*get_platform_data) (struct vfe_device *vfe_dev);
+};
+struct msm_vfe_stats_ops {
+	void (*cfg_comp_mask) (struct vfe_device *vfe_dev,
+		struct msm_vfe_stats_stream *stream_info);
+	void (*clear_comp_mask) (struct vfe_device *vfe_dev,
+		struct msm_vfe_stats_stream *stream_info);
+	void (*cfg_wm_irq_mask) (struct vfe_device *vfe_dev,
+		struct msm_vfe_stats_stream *stream_info);
+	void (*clear_wm_irq_mask) (struct vfe_device *vfe_dev,
+		struct msm_vfe_stats_stream *stream_info);
+
+	void (*cfg_wm_reg) (struct vfe_device *vfe_dev,
+		struct msm_vfe_stats_stream_request_cmd *stream_cfg_cmd);
+	void (*clear_wm_reg) (struct vfe_device *vfe_dev,
+		struct msm_vfe_stats_stream *stream_info);
+
+	void (*cfg_ub) (struct vfe_device *vfe_dev);
+
+	void (*stats_enable) (struct vfe_device *vfe_dev,
+		uint32_t stats_mask, uint8_t enable);
+
+	void (*update_ping_pong_addr) (struct vfe_device *vfe_dev,
+		enum msm_isp_stats_type stats_type, uint32_t pingpong_status,
+		unsigned long paddr);
+
+	uint32_t (*get_frame_id) (struct vfe_device *vfe_dev);
+	uint32_t (*get_wm_mask) (uint32_t irq_status0, uint32_t irq_status1);
+	uint32_t (*get_comp_mask) (uint32_t irq_status0, uint32_t irq_status1);
+};
+
+struct msm_vfe_ops {
+	struct msm_vfe_irq_ops irq_ops;
+	struct msm_vfe_axi_ops axi_ops;
+	struct msm_vfe_core_ops core_ops;
+	struct msm_vfe_stats_ops stats_ops;
+};
+
+struct msm_vfe_hardware_info {
+	struct msm_vfe_ops vfe_ops;
+	struct msm_vfe_axi_hardware_info *axi_hw_info;
+	struct v4l2_subdev_internal_ops *subdev_internal_ops;
+	struct v4l2_subdev_ops *subdev_ops;
+};
+
+struct msm_vfe_axi_hardware_info {
+	uint8_t num_wm;
+	uint8_t num_rdi;
+	uint8_t num_rdi_master;
+	uint8_t num_comp_mask;
+	uint32_t min_wm_ub;
+};
+
+enum msm_vfe_axi_state {
+	AVALIABLE,
+	INACTIVE,
+	ACTIVE,
+	PAUSE,
+	START_PENDING,
+	STOP_PENDING,
+	STOPPING,
+	PAUSE_PENDING,
+};
+
+#define VFE_NO_DROP            0xFFFFFFFF
+#define VFE_DROP_EVERY_2FRAME  0x55555555
+#define VFE_DROP_EVERY_4FRAME  0x11111111
+#define VFE_DROP_EVERY_8FRAME  0x01010101
+#define VFE_DROP_EVERY_16FRAME 0x00010001
+#define VFE_DROP_EVERY_32FRAME 0x00000001
+
+enum msm_vfe_axi_stream_type {
+	CONTINUOUS_STREAM,
+	BURST_STREAM,
+};
+
+struct msm_vfe_axi_stream {
+	uint32_t frame_id;
+	enum msm_vfe_axi_state state;
+	enum msm_vfe_axi_stream_src stream_src;
+	uint8_t num_planes;
+	uint8_t wm[MAX_PLANES_PER_STREAM];
+	uint8_t rdi[MAX_PLANES_PER_STREAM];
+	uint8_t rdi_master[MAX_PLANES_PER_STREAM];
+	uint8_t comp_mask_index;
+	struct msm_isp_buffer *buf[2];
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t bufq_handle;
+	uint32_t stream_handle;
+	uint8_t buf_divert;
+	enum msm_vfe_axi_stream_type stream_type;
+
+	uint32_t framedrop_pattern;
+	uint32_t init_frame_drop;
+	uint32_t burst_frame_count;/*number of sof before burst stop*/
+	uint8_t auto_trigger_stop;
+	uint8_t framedrop_update;
+};
+
+struct msm_vfe_axi_composite_info {
+	uint32_t stream_handle;
+	uint32_t stream_composite_mask;
+};
+struct msm_vfe_src_info {
+	unsigned long frame_id;
+	uint8_t active;
+	uint8_t pix_stream_count;
+	uint8_t raw_stream_count;
+	enum msm_vfe_inputmux input_mux;
+};
+
+
+struct msm_vfe_stats_stream {
+	uint32_t frame_id;
+	uint8_t enable;
+	enum msm_isp_stats_type stats_type;
+	uint8_t comp_mask_index;
+	struct msm_isp_buffer *buf[2];
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t bufq_handle;
+	uint32_t stream_handle;
+	uint32_t framedrop_pattern;
+};
+
+struct msm_vfe_stats_composite_info {
+	uint32_t stream_handle;
+	uint32_t stream_composite_mask;
+};
+
+enum msm_wm_ub_cfg_type {
+	MSM_WM_UB_CFG_DEFAULT,
+	MSM_WM_UB_EQUAL_SLICING,
+	MSM_WM_UB_CFG_MAX_NUM
+};
+struct msm_vfe_axi_shared_data {
+	struct msm_vfe_axi_hardware_info *hw_info;
+	struct msm_vfe_axi_stream stream_info[MAX_NUM_STREAM];
+	uint32_t free_wm[MAX_NUM_WM];
+	uint32_t wm_image_size[MAX_NUM_WM];
+	enum msm_wm_ub_cfg_type wm_ub_cfg_policy;
+	uint8_t num_used_wm;
+	uint8_t free_rdi[MAX_NUM_RDI];
+	uint8_t free_rdi_master[MAX_NUM_RDI][MAX_NUM_RDI_MASTER];
+	uint8_t num_used_rdi;
+	uint8_t num_active_stream;
+	struct msm_vfe_axi_composite_info
+		composite_info[MAX_NUM_COMPOSITE_MASK];
+	uint8_t num_used_composite_mask;
+	uint32_t stream_update;
+	struct msm_vfe_src_info src_info[VFE_SRC_MAX];
+	uint16_t stream_handle_cnt;
+	unsigned long event_mask;
+};
+
+struct msm_vfe_stats_shared_data {
+	struct msm_vfe_stats_stream stream_info[MSM_ISP_STATS_MAX];
+	struct msm_vfe_stats_composite_info
+		comp_info[MAX_NUM_STATS_COMP_MASK];
+	uint8_t num_active_stream;
+	uint8_t num_used_composite_mask;
+	uint16_t stream_handle_cnt;
+};
+struct msm_vfe_tasklet_queue_cmd {
+	struct list_head list;
+	uint32_t vfeInterruptStatus0;
+	uint32_t vfeInterruptStatus1;
+	struct timeval tv;
+	uint8_t cmd_used;
+};
+
+#define MSM_VFE_TASKLETQ_SIZE 200
+
+struct vfe_device {
+	struct platform_device *pdev;
+	struct msm_sd_subdev subdev;
+	struct resource *vfe_irq;
+	struct resource *vfe_mem;
+	struct resource *vfe_vbif_mem;
+	struct resource *vfe_io;
+	struct resource *vfe_vbif_io;
+	void __iomem *vfe_base;
+	void __iomem *vfe_vbif_base;
+
+	struct device *iommu_ctx;
+
+	struct regulator *fs_vfe;
+	struct clk *vfe_clk[7];
+
+	uint32_t bus_perf_client;
+
+	struct completion reset_complete;
+	struct completion halt_complete;
+	struct completion stream_config_complete;
+	struct mutex mutex;
+
+	atomic_t irq_cnt;
+	uint8_t taskletq_idx;
+	spinlock_t  tasklet_lock;
+	spinlock_t  shared_data_lock;
+	struct list_head tasklet_q;
+	struct tasklet_struct vfe_tasklet;
+	struct msm_vfe_tasklet_queue_cmd
+		tasklet_queue_cmd[MSM_VFE_TASKLETQ_SIZE];
+
+	struct msm_vfe_hardware_info *hw_info;
+
+	struct msm_vfe_axi_shared_data axi_data;
+	struct msm_vfe_stats_shared_data stats_data;
+	struct msm_isp_buf_mgr *buf_mgr;
+	int dump_reg;
+	uint32_t vfe_open_cnt;
+};
+
+#endif
diff --git a/drivers/media/video/msmb/isp/msm_isp32.c b/drivers/media/video/msmb/isp/msm_isp32.c
new file mode 100644
index 0000000..d7b62d1
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp32.c
@@ -0,0 +1,822 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+
+#include "msm_isp32.h"
+#include "msm_isp_util.h"
+#include "msm_isp_axi_util.h"
+#include "msm_isp.h"
+#include "msm.h"
+
+#define VFE32_BURST_LEN 4
+#define VFE32_EQUAL_SLICE_UB 117
+#define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx)
+#define VFE32_RDI_BASE(idx) (0x734 + 0x4 * idx)
+#define VFE32_RDI_MN_BASE(m) (0x734 + 0x4 * m/3)
+#define VFE32_RDI_MN_SEL_SHIFT(m) (4*(m%3) + 4)
+#define VFE32_RDI_MN_FB_SHIFT(m) ((m%3) + 16)
+#define VFE32_XBAR_BASE(idx) (0x40 + 0x4 * (idx / 4))
+#define VFE32_XBAR_SHIFT(idx) ((idx % 4) * 8)
+#define VFE32_PING_PONG_BASE(wm, ping_pong) \
+	(VFE32_WM_BASE(wm) + 0x4 * (1 + (~(ping_pong >> wm) & 0x1)))
+
+/*Temporary use fixed bus vectors in VFE */
+static struct msm_bus_vectors msm_vfe32_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors msm_vfe32_preview_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 1027648000,
+		.ib  = 1105920000,
+	},
+};
+
+static struct msm_bus_paths msm_vfe32_bus_client_config[] = {
+	{
+		ARRAY_SIZE(msm_vfe32_init_vectors),
+		msm_vfe32_init_vectors,
+	},
+	{
+		ARRAY_SIZE(msm_vfe32_preview_vectors),
+		msm_vfe32_preview_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata msm_vfe32_bus_client_pdata = {
+		msm_vfe32_bus_client_config,
+		ARRAY_SIZE(msm_vfe32_bus_client_config),
+		.name = "msm_camera_vfe",
+};
+
+static struct msm_cam_clk_info msm_vfe32_clk_info[] = {
+	{"vfe_clk", 228570000},
+	{"vfe_pclk", -1},
+	{"csi_vfe_clk", -1},
+};
+
+static int msm_vfe32_init_hardware(struct vfe_device *vfe_dev)
+{
+	int rc = -1;
+
+	vfe_dev->bus_perf_client =
+		msm_bus_scale_register_client(&msm_vfe32_bus_client_pdata);
+	if (!vfe_dev->bus_perf_client) {
+		pr_err("%s: Registration Failed!\n", __func__);
+		vfe_dev->bus_perf_client = 0;
+		goto bus_scale_register_failed;
+	}
+	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 1);
+
+	if (vfe_dev->fs_vfe) {
+		rc = regulator_enable(vfe_dev->fs_vfe);
+		if (rc) {
+			pr_err("%s: Regulator enable failed\n", __func__);
+			goto fs_failed;
+		}
+	}
+
+	rc = msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe32_clk_info,
+		 vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe32_clk_info), 1);
+	if (rc < 0)
+		goto clk_enable_failed;
+
+	vfe_dev->vfe_base = ioremap(vfe_dev->vfe_mem->start,
+		resource_size(vfe_dev->vfe_mem));
+	if (!vfe_dev->vfe_base) {
+		rc = -ENOMEM;
+		pr_err("%s: vfe ioremap failed\n", __func__);
+		goto vfe_remap_failed;
+	}
+
+	rc = request_irq(vfe_dev->vfe_irq->start, msm_isp_process_irq,
+					 IRQF_TRIGGER_RISING, "vfe", vfe_dev);
+	if (rc < 0) {
+		pr_err("%s: irq request failed\n", __func__);
+		goto irq_req_failed;
+	}
+
+	return rc;
+irq_req_failed:
+	iounmap(vfe_dev->vfe_base);
+vfe_remap_failed:
+	msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe32_clk_info,
+		 vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe32_clk_info), 0);
+clk_enable_failed:
+	regulator_disable(vfe_dev->fs_vfe);
+fs_failed:
+	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
+	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+bus_scale_register_failed:
+	return rc;
+}
+
+static void msm_vfe32_release_hardware(struct vfe_device *vfe_dev)
+{
+	free_irq(vfe_dev->vfe_irq->start, vfe_dev);
+	tasklet_kill(&vfe_dev->vfe_tasklet);
+	iounmap(vfe_dev->vfe_base);
+	msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe32_clk_info,
+		 vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe32_clk_info), 0);
+	regulator_disable(vfe_dev->fs_vfe);
+	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
+	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+}
+
+static void msm_vfe32_init_hardware_reg(struct vfe_device *vfe_dev)
+{
+	/* CGC_OVERRIDE */
+	msm_camera_io_w(0x07FFFFFF, vfe_dev->vfe_base + 0xC);
+	/* BUS_CFG */
+	msm_camera_io_w(0x00000001, vfe_dev->vfe_base + 0x3C);
+	msm_camera_io_w(0x00000025, vfe_dev->vfe_base + 0x1C);
+	msm_camera_io_w_mb(0x1DFFFFFF, vfe_dev->vfe_base + 0x20);
+	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24);
+	msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28);
+}
+
+static void msm_vfe32_process_reset_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	if (irq_status1 & (1 << 23))
+		complete(&vfe_dev->reset_complete);
+}
+
+static void msm_vfe32_process_halt_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	if (irq_status1 & (1 << 24))
+		complete(&vfe_dev->halt_complete);
+}
+
+static void msm_vfe32_process_camif_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	if (!(irq_status0 & 0x1F))
+		return;
+
+	if (irq_status0 & (1 << 0)) {
+		ISP_DBG("%s: PIX0 frame id: %lu\n", __func__,
+			   vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
+		msm_isp_update_framedrop_count(vfe_dev);
+		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id++;
+	}
+}
+
+static void msm_vfe32_process_violation_irq(struct vfe_device *vfe_dev)
+{
+	uint32_t violation_status;
+	violation_status = msm_camera_io_r(vfe_dev->vfe_base + 0x48);
+	if (!violation_status)
+		return;
+
+	if (violation_status & (1 << 0))
+		pr_err("%s: black violation\n", __func__);
+	if (violation_status & (1 << 1))
+		pr_err("%s: rolloff violation\n", __func__);
+	if (violation_status & (1 << 2))
+		pr_err("%s: demux violation\n", __func__);
+	if (violation_status & (1 << 3))
+		pr_err("%s: demosaic violation\n", __func__);
+	if (violation_status & (1 << 4))
+		pr_err("%s: crop violation\n", __func__);
+	if (violation_status & (1 << 5))
+		pr_err("%s: scale violation\n", __func__);
+	if (violation_status & (1 << 6))
+		pr_err("%s: wb violation\n", __func__);
+	if (violation_status & (1 << 7))
+		pr_err("%s: clf violation\n", __func__);
+	if (violation_status & (1 << 8))
+		pr_err("%s: matrix violation\n", __func__);
+	if (violation_status & (1 << 9))
+		pr_err("%s: rgb lut violation\n", __func__);
+	if (violation_status & (1 << 10))
+		pr_err("%s: la violation\n", __func__);
+	if (violation_status & (1 << 11))
+		pr_err("%s: chroma enhance violation\n", __func__);
+	if (violation_status & (1 << 12))
+		pr_err("%s: chroma supress mce violation\n", __func__);
+	if (violation_status & (1 << 13))
+		pr_err("%s: skin enhance violation\n", __func__);
+	if (violation_status & (1 << 14))
+		pr_err("%s: asf violation\n", __func__);
+	if (violation_status & (1 << 15))
+		pr_err("%s: scale y violation\n", __func__);
+	if (violation_status & (1 << 16))
+		pr_err("%s: scale cbcr violation\n", __func__);
+	if (violation_status & (1 << 17))
+		pr_err("%s: chroma subsample violation\n", __func__);
+	if (violation_status & (1 << 18))
+		pr_err("%s: framedrop enc y violation\n", __func__);
+	if (violation_status & (1 << 19))
+		pr_err("%s: framedrop enc cbcr violation\n", __func__);
+	if (violation_status & (1 << 20))
+		pr_err("%s: framedrop view y violation\n", __func__);
+	if (violation_status & (1 << 21))
+		pr_err("%s: framedrop view cbcr violation\n", __func__);
+	if (violation_status & (1 << 22))
+		pr_err("%s: realign buf y violation\n", __func__);
+	if (violation_status & (1 << 23))
+		pr_err("%s: realign buf cb violation\n", __func__);
+	if (violation_status & (1 << 24))
+		pr_err("%s: realign buf cr violation\n", __func__);
+}
+
+static void msm_vfe32_process_error_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	uint32_t camif_status;
+	if (!(irq_status1 & 0x7FFFFF))
+		return;
+
+	if (irq_status1 & (1 << 0)) {
+		camif_status = msm_camera_io_r(vfe_dev->vfe_base + 0x204);
+		pr_err("%s: camif error status: 0x%x\n",
+			__func__, camif_status);
+	}
+	if (irq_status1 & (1 << 1))
+		pr_err("%s: stats bhist overwrite\n", __func__);
+	if (irq_status1 & (1 << 2))
+		pr_err("%s: stats cs overwrite\n", __func__);
+	if (irq_status1 & (1 << 3))
+		pr_err("%s: stats ihist overwrite\n", __func__);
+	if (irq_status1 & (1 << 4))
+		pr_err("%s: realign buf y overflow\n", __func__);
+	if (irq_status1 & (1 << 5))
+		pr_err("%s: realign buf cb overflow\n", __func__);
+	if (irq_status1 & (1 << 6))
+		pr_err("%s: realign buf cr overflow\n", __func__);
+	if (irq_status1 & (1 << 7)) {
+		pr_err("%s: violation\n", __func__);
+		msm_vfe32_process_violation_irq(vfe_dev);
+	}
+	if (irq_status1 & (1 << 8))
+		pr_err("%s: image master 0 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 9))
+		pr_err("%s: image master 1 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 10))
+		pr_err("%s: image master 2 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 11))
+		pr_err("%s: image master 3 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 12))
+		pr_err("%s: image master 4 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 13))
+		pr_err("%s: image master 5 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 14))
+		pr_err("%s: image master 6 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 15))
+		pr_err("%s: status ae/bg bus overflow\n", __func__);
+	if (irq_status1 & (1 << 16))
+		pr_err("%s: status af/bf bus overflow\n", __func__);
+	if (irq_status1 & (1 << 17))
+		pr_err("%s: status awb bus overflow\n", __func__);
+	if (irq_status1 & (1 << 18))
+		pr_err("%s: status rs bus overflow\n", __func__);
+	if (irq_status1 & (1 << 19))
+		pr_err("%s: status cs bus overflow\n", __func__);
+	if (irq_status1 & (1 << 20))
+		pr_err("%s: status ihist bus overflow\n", __func__);
+	if (irq_status1 & (1 << 21))
+		pr_err("%s: status skin bhist bus overflow\n", __func__);
+	if (irq_status1 & (1 << 22))
+		pr_err("%s: axi error\n", __func__);
+}
+
+static void msm_vfe32_read_irq_status(struct vfe_device *vfe_dev,
+	uint32_t *irq_status0, uint32_t *irq_status1)
+{
+	*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
+	*irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x30);
+	msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x24);
+	msm_camera_io_w(*irq_status1, vfe_dev->vfe_base + 0x28);
+	msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x18);
+}
+
+static void msm_vfe32_process_reg_update(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	if (!(irq_status0 & 0x20) && !(irq_status1 & 0x1C000000))
+		return;
+
+	if (vfe_dev->axi_data.stream_update)
+		msm_isp_axi_stream_update(vfe_dev);
+
+	msm_isp_update_framedrop_reg(vfe_dev);
+
+	return;
+}
+
+static void msm_vfe32_reg_update(
+	struct vfe_device *vfe_dev, uint32_t update_mask)
+{
+	msm_camera_io_w_mb(update_mask, vfe_dev->vfe_base + 0x260);
+}
+
+static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev)
+{
+	init_completion(&vfe_dev->reset_complete);
+	msm_camera_io_w_mb(0x3FF, vfe_dev->vfe_base + 0x4);
+	return wait_for_completion_interruptible_timeout(
+	   &vfe_dev->reset_complete, msecs_to_jiffies(50));
+}
+
+static void msm_vfe32_axi_reload_wm(
+	struct vfe_device *vfe_dev, uint32_t reload_mask)
+{
+	msm_camera_io_w_mb(reload_mask, vfe_dev->vfe_base + 0x38);
+}
+
+static void msm_vfe32_axi_enable_wm(struct vfe_device *vfe_dev,
+	uint8_t wm_idx, uint8_t enable)
+{
+	if (enable)
+		msm_camera_io_w_mb(0x1,
+			vfe_dev->vfe_base + VFE32_WM_BASE(wm_idx));
+	else
+		msm_camera_io_w_mb(0x0,
+			vfe_dev->vfe_base + VFE32_WM_BASE(wm_idx));
+}
+
+static void msm_vfe32_axi_cfg_comp_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	uint32_t comp_mask, comp_mask_index =
+		stream_info->comp_mask_index;
+	uint32_t irq_mask;
+
+	comp_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x34);
+	comp_mask &= ~(0x7F << (comp_mask_index * 8));
+	comp_mask |= (axi_data->composite_info[comp_mask_index].
+		stream_composite_mask << (comp_mask_index * 8));
+	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x34);
+
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
+	irq_mask |= 1 << (comp_mask_index + 21);
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
+}
+
+static void msm_vfe32_axi_clear_comp_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t comp_mask, comp_mask_index = stream_info->comp_mask_index;
+	uint32_t irq_mask;
+
+	comp_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x34);
+	comp_mask &= ~(0x7F << (comp_mask_index * 8));
+	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x34);
+
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
+	irq_mask &= ~(1 << (comp_mask_index + 21));
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
+}
+
+static void msm_vfe32_axi_cfg_wm_irq_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t irq_mask;
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
+	irq_mask |= 1 << (stream_info->wm[0] + 6);
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
+}
+
+static void msm_vfe32_axi_clear_wm_irq_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t irq_mask;
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
+	irq_mask &= ~(1 << (stream_info->wm[0] + 6));
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
+}
+
+static void msm_vfe32_cfg_framedrop(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t framedrop_pattern = 0;
+
+	if (stream_info->init_frame_drop == 0)
+		framedrop_pattern = stream_info->framedrop_pattern;
+
+	if (stream_info->stream_type == BURST_STREAM &&
+		stream_info->burst_frame_count == 0)
+		framedrop_pattern = 0;
+
+	if (stream_info->stream_src == PIX_ENCODER) {
+		msm_camera_io_w(0x1F, vfe_dev->vfe_base + 0x504);
+		msm_camera_io_w(0x1F, vfe_dev->vfe_base + 0x508);
+		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x50C);
+		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x510);
+	} else if (stream_info->stream_src == PIX_VIEWFINDER) {
+		msm_camera_io_w(0x1F, vfe_dev->vfe_base + 0x514);
+		msm_camera_io_w(0x1F, vfe_dev->vfe_base + 0x518);
+		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x51C);
+		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x520);
+	}
+	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x260);
+}
+
+static void msm_vfe32_clear_framedrop(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	if (stream_info->stream_src == PIX_ENCODER) {
+		msm_camera_io_w(0, vfe_dev->vfe_base + 0x50C);
+		msm_camera_io_w(0, vfe_dev->vfe_base + 0x510);
+	} else if (stream_info->stream_src == PIX_VIEWFINDER) {
+		msm_camera_io_w(0, vfe_dev->vfe_base + 0x51C);
+		msm_camera_io_w(0, vfe_dev->vfe_base + 0x520);
+	}
+}
+
+static void msm_vfe32_cfg_camif(struct vfe_device *vfe_dev,
+	struct msm_vfe_pix_cfg *pix_cfg)
+{
+	uint16_t first_pixel, last_pixel, first_line, last_line;
+	struct msm_vfe_camif_cfg *camif_cfg = &pix_cfg->camif_cfg;
+	uint32_t val;
+
+	first_pixel = camif_cfg->left_crop;
+	last_pixel = camif_cfg->pixels_per_line -
+					 camif_cfg->left_crop -
+					 camif_cfg->right_crop;
+	first_line = camif_cfg->left_crop;
+	last_line = camif_cfg->lines_per_frame -
+					 camif_cfg->top_crop -
+					 camif_cfg->bottom_crop;
+
+	msm_camera_io_w(pix_cfg->input_mux << 16 | pix_cfg->pixel_pattern,
+					vfe_dev->vfe_base + 0x14);
+
+	msm_camera_io_w(camif_cfg->lines_per_frame << 16 |
+					camif_cfg->pixels_per_line,
+					vfe_dev->vfe_base + 0x1EC);
+
+	msm_camera_io_w(ISP_SUB(first_pixel) << 16 | ISP_SUB(last_pixel),
+					vfe_dev->vfe_base + 0x1F0);
+
+	msm_camera_io_w(ISP_SUB(first_line) << 16 | ISP_SUB(last_line),
+					vfe_dev->vfe_base + 0x1F4);
+
+	val = msm_camera_io_r(vfe_dev->vfe_base + 0x6FC);
+	val &= 0xFFFFFFFC;
+	val |= camif_cfg->camif_input;
+	msm_camera_io_w(val, vfe_dev->vfe_base + 0x6FC);
+}
+
+static void msm_vfe32_update_camif_state(
+	struct vfe_device *vfe_dev,
+	enum msm_isp_camif_update_state update_state)
+{
+	uint32_t val;
+	bool bus_en, vfe_en;
+	if (update_state == NO_UPDATE)
+		return;
+
+	val = msm_camera_io_r(vfe_dev->vfe_base + 0x1E4);
+	if (update_state == ENABLE_CAMIF) {
+		bus_en =
+		((vfe_dev->axi_data.src_info[
+			VFE_PIX_0].raw_stream_count > 0) ? 1 : 0);
+		vfe_en =
+		((vfe_dev->axi_data.src_info[
+			VFE_PIX_0].pix_stream_count > 0) ? 1 : 0);
+		val &= 0xFFFFFF3F;
+		val = val | bus_en << 7 | vfe_en << 6;
+		msm_camera_io_w(val, vfe_dev->vfe_base + 0x1E4);
+		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1E0);
+		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 1;
+	} else if (update_state == DISABLE_CAMIF) {
+		msm_camera_io_w_mb(0x0, vfe_dev->vfe_base + 0x1E0);
+		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
+	}
+}
+
+static void msm_vfe32_axi_cfg_wm_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	uint8_t plane_idx)
+{
+	uint32_t val;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	uint32_t wm_base = VFE32_WM_BASE(stream_info->wm[plane_idx]);
+
+	/*WR_IMAGE_SIZE*/
+	val =
+		((msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
+		stream_cfg_cmd->plane_cfg[
+			plane_idx].output_width)+1)/2 - 1) << 16 |
+		(stream_cfg_cmd->plane_cfg[plane_idx].output_height - 1);
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x10);
+
+	/*WR_BUFFER_CFG*/
+	val =
+		msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
+		  stream_cfg_cmd->plane_cfg[plane_idx].output_width) << 16 |
+		(stream_cfg_cmd->plane_cfg[
+			plane_idx].output_scan_lines - 1) << 4 |
+		VFE32_BURST_LEN >> 2;
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
+	return;
+}
+
+static void msm_vfe32_axi_clear_wm_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx)
+{
+	uint32_t val = 0;
+	uint32_t wm_base = VFE32_WM_BASE(stream_info->wm[plane_idx]);
+	/*WR_IMAGE_SIZE*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x10);
+	/*WR_BUFFER_CFG*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
+	return;
+}
+
+static void msm_vfe32_axi_cfg_rdi_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	uint8_t plane_idx)
+{
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info =
+	 &axi_data->stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	struct msm_vfe_axi_plane_cfg *plane_cfg =
+		&stream_cfg_cmd->plane_cfg[plane_idx];
+	uint8_t rdi = stream_info->rdi[plane_idx];
+	uint8_t rdi_master = stream_info->rdi_master[plane_idx];
+	uint32_t rdi_reg_cfg;
+
+	rdi_reg_cfg = msm_camera_io_r(vfe_dev->vfe_base + VFE32_RDI_BASE(rdi));
+	rdi_reg_cfg = (rdi_reg_cfg & 0xFFFFFFF) | rdi_master << 28;
+	msm_camera_io_w(rdi_reg_cfg, vfe_dev->vfe_base + VFE32_RDI_BASE(rdi));
+
+	rdi_reg_cfg = msm_camera_io_r(
+		vfe_dev->vfe_base + VFE32_RDI_MN_BASE(rdi_master));
+	rdi_reg_cfg &= ~((0xF << VFE32_RDI_MN_SEL_SHIFT(rdi_master)) |
+		(0x1 << VFE32_RDI_MN_FB_SHIFT(rdi_master)));
+	rdi_reg_cfg |= (plane_cfg->rdi_cid <<
+		VFE32_RDI_MN_SEL_SHIFT(rdi_master) |
+		(stream_cfg_cmd->frame_base <<
+			VFE32_RDI_MN_FB_SHIFT(rdi_master)));
+	msm_camera_io_w(rdi_reg_cfg,
+					vfe_dev->vfe_base +
+					VFE32_RDI_MN_BASE(rdi_master));
+}
+
+static void msm_vfe32_axi_cfg_wm_xbar_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	uint8_t plane_idx)
+{
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info =
+	 &axi_data->stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	struct msm_vfe_axi_plane_cfg *plane_cfg =
+		&stream_cfg_cmd->plane_cfg[plane_idx];
+	uint8_t wm = stream_info->wm[plane_idx];
+	uint32_t xbar_cfg = 0;
+	uint32_t xbar_reg_cfg = 0;
+
+	switch (stream_cfg_cmd->stream_src) {
+	case PIX_ENCODER:
+	case PIX_VIEWFINDER: {
+		if (plane_cfg->output_plane_format
+			!= CRCB_PLANE) {
+			/*SINGLE_STREAM_SEL*/
+			xbar_cfg |= plane_cfg->output_plane_format << 5;
+		} else {
+			switch (stream_cfg_cmd->output_format) {
+			case V4L2_PIX_FMT_NV12:
+			case V4L2_PIX_FMT_NV16:
+				xbar_cfg |= 0x3 << 3; /*PAIR_STREAM_SWAP_CTRL*/
+				break;
+			}
+			xbar_cfg |= 0x1 << 1; /*PAIR_STREAM_EN*/
+		}
+		if (stream_cfg_cmd->stream_src == PIX_VIEWFINDER)
+			xbar_cfg |= 0x1; /*VIEW_STREAM_EN*/
+		break;
+	}
+	case CAMIF_RAW:
+		xbar_cfg = 0x60;
+		break;
+	case IDEAL_RAW:
+		xbar_cfg = 0x80;
+		break;
+	case RDI:
+		if (stream_info->rdi[plane_idx] == 0)
+			xbar_cfg = 0xA0;
+		else if (stream_info->rdi[plane_idx] == 1)
+			xbar_cfg = 0xC0;
+		else if (stream_info->rdi[plane_idx] == 2)
+			xbar_cfg = 0xE0;
+		break;
+	default:
+		pr_err("%s: Invalid stream src\n", __func__);
+	}
+	xbar_reg_cfg = msm_camera_io_r(vfe_dev->vfe_base + VFE32_XBAR_BASE(wm));
+	xbar_reg_cfg &= ~(0xFF << VFE32_XBAR_SHIFT(wm));
+	xbar_reg_cfg |= (xbar_cfg << VFE32_XBAR_SHIFT(wm));
+	msm_camera_io_w(xbar_reg_cfg, vfe_dev->vfe_base + VFE32_XBAR_BASE(wm));
+	return;
+}
+
+static void msm_vfe32_axi_clear_wm_xbar_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx)
+{
+	uint8_t wm = stream_info->wm[plane_idx];
+	uint32_t xbar_reg_cfg = 0;
+
+	xbar_reg_cfg = msm_camera_io_r(vfe_dev->vfe_base + VFE32_XBAR_BASE(wm));
+	xbar_reg_cfg &= ~(0xFF << VFE32_XBAR_SHIFT(wm));
+	msm_camera_io_w(xbar_reg_cfg, vfe_dev->vfe_base + VFE32_XBAR_BASE(wm));
+}
+
+static void msm_vfe32_cfg_axi_ub(struct vfe_device *vfe_dev)
+{
+	int i;
+	uint32_t ub_offset = 0;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	for (i = 0; i < axi_data->hw_info->num_wm; i++) {
+		msm_camera_io_w(ub_offset << 16 | (VFE32_EQUAL_SLICE_UB - 1),
+			vfe_dev->vfe_base + VFE32_WM_BASE(i) + 0xC);
+		ub_offset += VFE32_EQUAL_SLICE_UB;
+	}
+}
+
+static void msm_vfe32_update_ping_pong_addr(struct vfe_device *vfe_dev,
+		uint8_t wm_idx, uint32_t pingpong_status, unsigned long paddr)
+{
+	msm_camera_io_w(paddr, vfe_dev->vfe_base +
+		VFE32_PING_PONG_BASE(wm_idx, pingpong_status));
+}
+
+static long msm_vfe32_axi_halt(struct vfe_device *vfe_dev)
+{
+	uint32_t halt_mask;
+	halt_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x20);
+	halt_mask |= (1 << 24);
+	msm_camera_io_w_mb(halt_mask, vfe_dev->vfe_base + 0x20);
+	init_completion(&vfe_dev->halt_complete);
+	/*TD: Need to fix crashes with this*/
+	/*msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8);*/
+	return wait_for_completion_interruptible_timeout(
+		&vfe_dev->halt_complete, msecs_to_jiffies(500));
+}
+
+static uint32_t msm_vfe32_get_wm_mask(
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	return (irq_status0 >> 6) & 0x7F;
+}
+
+static uint32_t msm_vfe32_get_comp_mask(
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	return (irq_status0 >> 21) & 0x7;
+}
+
+static uint32_t msm_vfe32_get_pingpong_status(struct vfe_device *vfe_dev)
+{
+	return msm_camera_io_r(vfe_dev->vfe_base + 0x180);
+}
+
+static int msm_vfe32_get_platform_data(struct vfe_device *vfe_dev)
+{
+	int rc = 0;
+	vfe_dev->vfe_mem = platform_get_resource_byname(vfe_dev->pdev,
+					IORESOURCE_MEM, "vfe");
+	if (!vfe_dev->vfe_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+	vfe_dev->vfe_irq = platform_get_resource_byname(vfe_dev->pdev,
+					IORESOURCE_IRQ, "vfe");
+	if (!vfe_dev->vfe_irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+	vfe_dev->fs_vfe = regulator_get(&vfe_dev->pdev->dev, "vdd");
+	if (IS_ERR(vfe_dev->fs_vfe)) {
+		pr_err("%s: Regulator get failed %ld\n", __func__,
+			PTR_ERR(vfe_dev->fs_vfe));
+		vfe_dev->fs_vfe = NULL;
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+	vfe_dev->iommu_ctx[0] = msm_iommu_get_ctx("vfe_imgwr");
+	if (!vfe_dev->iommu_ctx[0]) {
+		pr_err("%s: no iommux ctx resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+	vfe_dev->iommu_ctx[1] = msm_iommu_get_ctx("vfe_misc");
+	if (!vfe_dev->iommu_ctx[1]) {
+		pr_err("%s: no iommux ctx resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+	vfe_dev->num_ctx = 2;
+
+vfe_no_resource:
+	return rc;
+}
+
+struct msm_vfe_axi_hardware_info msm_vfe32_axi_hw_info = {
+	.num_wm = 7,
+	.num_comp_mask = 3,
+	.num_rdi = 3,
+	.num_rdi_master = 3,
+};
+
+static struct v4l2_subdev_core_ops msm_vfe32_subdev_core_ops = {
+	.ioctl = msm_isp_ioctl,
+	.subscribe_event = msm_isp_subscribe_event,
+	.unsubscribe_event = msm_isp_unsubscribe_event,
+};
+
+static struct v4l2_subdev_ops msm_vfe32_subdev_ops = {
+	.core = &msm_vfe32_subdev_core_ops,
+};
+
+static struct v4l2_subdev_internal_ops msm_vfe32_internal_ops = {
+	.open = msm_isp_open_node,
+	.close = msm_isp_close_node,
+};
+
+struct msm_vfe_hardware_info vfe32_hw_info = {
+	.vfe_ops = {
+		.irq_ops = {
+			.read_irq_status = msm_vfe32_read_irq_status,
+			.process_camif_irq = msm_vfe32_process_camif_irq,
+			.process_reset_irq = msm_vfe32_process_reset_irq,
+			.process_halt_irq = msm_vfe32_process_halt_irq,
+			.process_reset_irq = msm_vfe32_process_reset_irq,
+			.process_error_irq = msm_vfe32_process_error_irq,
+			.process_reg_update = msm_vfe32_process_reg_update,
+			.process_axi_irq = msm_isp_process_axi_irq,
+		},
+		.axi_ops = {
+			.reload_wm = msm_vfe32_axi_reload_wm,
+			.enable_wm = msm_vfe32_axi_enable_wm,
+			.cfg_comp_mask = msm_vfe32_axi_cfg_comp_mask,
+			.clear_comp_mask = msm_vfe32_axi_clear_comp_mask,
+			.cfg_wm_irq_mask = msm_vfe32_axi_cfg_wm_irq_mask,
+			.clear_wm_irq_mask = msm_vfe32_axi_clear_wm_irq_mask,
+			.cfg_framedrop = msm_vfe32_cfg_framedrop,
+			.clear_framedrop = msm_vfe32_clear_framedrop,
+			.cfg_wm_reg = msm_vfe32_axi_cfg_wm_reg,
+			.clear_wm_reg = msm_vfe32_axi_clear_wm_reg,
+			.cfg_wm_xbar_reg = msm_vfe32_axi_cfg_wm_xbar_reg,
+			.clear_wm_xbar_reg = msm_vfe32_axi_clear_wm_xbar_reg,
+			.cfg_rdi_reg = msm_vfe32_axi_cfg_rdi_reg,
+			.cfg_ub = msm_vfe32_cfg_axi_ub,
+			.update_ping_pong_addr =
+				msm_vfe32_update_ping_pong_addr,
+			.get_comp_mask = msm_vfe32_get_comp_mask,
+			.get_wm_mask = msm_vfe32_get_wm_mask,
+			.get_pingpong_status = msm_vfe32_get_pingpong_status,
+			.halt = msm_vfe32_axi_halt,
+		},
+		.core_ops = {
+			.reg_update = msm_vfe32_reg_update,
+			.cfg_camif = msm_vfe32_cfg_camif,
+			.update_camif_state = msm_vfe32_update_camif_state,
+			.reset_hw = msm_vfe32_reset_hardware,
+			.init_hw = msm_vfe32_init_hardware,
+			.init_hw_reg = msm_vfe32_init_hardware_reg,
+			.release_hw = msm_vfe32_release_hardware,
+			.get_platform_data = msm_vfe32_get_platform_data,
+		},
+	},
+	.axi_hw_info = &msm_vfe32_axi_hw_info,
+	.subdev_ops = &msm_vfe32_subdev_ops,
+	.subdev_internal_ops = &msm_vfe32_internal_ops,
+};
+EXPORT_SYMBOL(vfe32_hw_info);
diff --git a/arch/arm/boot/dts/msm8910-sim.dts b/drivers/media/video/msmb/isp/msm_isp32.h
similarity index 63%
copy from arch/arm/boot/dts/msm8910-sim.dts
copy to drivers/media/video/msmb/isp/msm_isp32.h
index aae88b1..0535048 100644
--- a/arch/arm/boot/dts/msm8910-sim.dts
+++ b/drivers/media/video/msmb/isp/msm_isp32.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,16 +10,8 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
+#ifndef __MSM_ISP32_H__
+#define __MSM_ISP32_H__
 
-/include/ "msm8910.dtsi"
-
-/ {
-	model = "Qualcomm MSM 8910 Simulator";
-	compatible = "qcom,msm8910-sim", "qcom,msm8910";
-	qcom,msm-id = <147 1 0>;
-
-	serial@f991f000 {
-		status = "ok";
-	};
-};
+extern struct msm_vfe_hardware_info vfe32_hw_info;
+#endif /* __MSM_ISP32_H__ */
diff --git a/drivers/media/video/msmb/isp/msm_isp40.c b/drivers/media/video/msmb/isp/msm_isp40.c
new file mode 100644
index 0000000..47abcef
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp40.c
@@ -0,0 +1,1127 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <mach/iommu.h>
+
+#include "msm_isp40.h"
+#include "msm_isp_util.h"
+#include "msm_isp_axi_util.h"
+#include "msm_isp_stats_util.h"
+#include "msm_isp.h"
+#include "msm.h"
+#include "msm_camera_io_util.h"
+
+/*#define CONFIG_MSM_ISP_DBG*/
+#undef CDBG
+#ifdef CONFIG_MSM_ISP_DBG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+#define VFE40_BURST_LEN 4
+#define VFE40_EQUAL_SLICE_UB 117
+#define VFE40_WM_BASE(idx) (0x6C + 0x24 * idx)
+#define VFE40_RDI_BASE(idx) (0x2E8 + 0x4 * idx)
+#define VFE40_RDI_MN_BASE(m) (0x2E8 + 0x4 * m/3)
+#define VFE40_RDI_MN_SEL_SHIFT(m) (4*(m%3) + 4)
+#define VFE40_RDI_MN_FB_SHIFT(m) ((m%3) + 16)
+#define VFE40_XBAR_BASE(idx) (0x58 + 0x4 * (idx / 2))
+#define VFE40_XBAR_SHIFT(idx) ((idx%2) ? 16 : 0)
+#define VFE40_PING_PONG_BASE(wm, ping_pong) \
+	(VFE40_WM_BASE(wm) + 0x4 * (1 + (~(ping_pong >> wm) & 0x1)))
+
+#define VFE40_VBIF_CLKON        0x4
+#define VFE40_VBIF_IN_RD_LIM_CONF0    0xB0
+#define VFE40_VBIF_IN_RD_LIM_CONF1    0xB4
+#define VFE40_VBIF_IN_RD_LIM_CONF2    0xB8
+#define VFE40_VBIF_IN_WR_LIM_CONF0    0xC0
+#define VFE40_VBIF_IN_WR_LIM_CONF1    0xC4
+#define VFE40_VBIF_IN_WR_LIM_CONF2    0xC8
+#define VFE40_VBIF_OUT_RD_LIM_CONF0   0xD0
+#define VFE40_VBIF_OUT_WR_LIM_CONF0   0xD4
+#define VFE40_VBIF_DDR_OUT_MAX_BURST  0xD8
+#define VFE40_VBIF_ARB_CTL        0xF0
+#define VFE40_VBIF_DDR_ARB_CONF0    0xF4
+#define VFE40_VBIF_DDR_ARB_CONF1    0xF8
+#define VFE40_VBIF_ROUND_ROBIN_QOS_ARB  0x124
+#define VFE40_VBIF_OUT_AXI_AOOO_EN    0x178
+#define VFE40_VBIF_OUT_AXI_AOOO     0x17C
+
+/*Temporary use fixed bus vectors in VFE */
+static struct msm_bus_vectors msm_vfe40_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors msm_vfe40_preview_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 1027648000,
+		.ib  = 1105920000,
+	},
+};
+
+static struct msm_bus_paths msm_vfe40_bus_client_config[] = {
+	{
+		ARRAY_SIZE(msm_vfe40_init_vectors),
+		msm_vfe40_init_vectors,
+	},
+	{
+		ARRAY_SIZE(msm_vfe40_preview_vectors),
+		msm_vfe40_preview_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata msm_vfe40_bus_client_pdata = {
+	msm_vfe40_bus_client_config,
+	ARRAY_SIZE(msm_vfe40_bus_client_config),
+	.name = "msm_camera_vfe",
+};
+
+static struct msm_cam_clk_info msm_vfe40_clk_info[] = {
+	{"camss_top_ahb_clk", -1},
+	{"vfe_clk_src", 266670000},
+	{"camss_vfe_vfe_clk", -1},
+	{"camss_csi_vfe_clk", -1},
+	{"iface_clk", -1},
+	{"bus_clk", -1},
+	{"alt_bus_clk", -1},
+};
+
+static void msm_vfe40_init_vbif_parms(
+	void __iomem *vfe_vbif_base)
+{
+	msm_camera_io_w_mb(0x1,
+		vfe_vbif_base + VFE40_VBIF_CLKON);
+	msm_camera_io_w_mb(0x1,
+		vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
+	msm_camera_io_w_mb(0xFFFF,
+		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
+	msm_camera_io_w_mb(0xFFFFFFFF,
+		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
+
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
+	msm_camera_io_w_mb(0x10101010,
+		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
+	msm_camera_io_w_mb(0x00001010,
+		vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
+	msm_camera_io_w_mb(0x00001010,
+		vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
+	msm_camera_io_w_mb(0x00000707,
+		vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
+	msm_camera_io_w_mb(0x00000030,
+		vfe_vbif_base + VFE40_VBIF_ARB_CTL);
+	msm_camera_io_w_mb(0x04210842,
+		vfe_vbif_base + VFE40_VBIF_DDR_ARB_CONF0);
+	msm_camera_io_w_mb(0x04210842,
+	vfe_vbif_base + VFE40_VBIF_DDR_ARB_CONF1);
+}
+
+static int msm_vfe40_init_hardware(struct vfe_device *vfe_dev)
+{
+	int rc = -1;
+
+	vfe_dev->bus_perf_client =
+		msm_bus_scale_register_client(&msm_vfe40_bus_client_pdata);
+	if (!vfe_dev->bus_perf_client) {
+		pr_err("%s: Registration Failed!\n", __func__);
+		vfe_dev->bus_perf_client = 0;
+		goto bus_scale_register_failed;
+	}
+	msm_bus_scale_client_update_request(
+		vfe_dev->bus_perf_client, 1);
+
+	if (vfe_dev->fs_vfe) {
+		rc = regulator_enable(vfe_dev->fs_vfe);
+		if (rc) {
+			pr_err("%s: Regulator enable failed\n", __func__);
+			goto fs_failed;
+		}
+	}
+
+	rc = msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe40_clk_info,
+		vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe40_clk_info), 1);
+	if (rc < 0)
+		goto clk_enable_failed;
+
+	vfe_dev->vfe_base = ioremap(vfe_dev->vfe_mem->start,
+		resource_size(vfe_dev->vfe_mem));
+	if (!vfe_dev->vfe_base) {
+		rc = -ENOMEM;
+		pr_err("%s: vfe ioremap failed\n", __func__);
+		goto vfe_remap_failed;
+	}
+
+	vfe_dev->vfe_vbif_base = ioremap(vfe_dev->vfe_vbif_mem->start,
+		resource_size(vfe_dev->vfe_vbif_mem));
+	if (!vfe_dev->vfe_vbif_base) {
+		rc = -ENOMEM;
+		pr_err("%s: vfe ioremap failed\n", __func__);
+		goto vbif_remap_failed;
+	}
+
+	rc = request_irq(vfe_dev->vfe_irq->start, msm_isp_process_irq,
+		IRQF_TRIGGER_RISING, "vfe", vfe_dev);
+	if (rc < 0) {
+		pr_err("%s: irq request failed\n", __func__);
+		goto irq_req_failed;
+	}
+
+	msm_vfe40_init_vbif_parms(vfe_dev->vfe_vbif_base);
+	return rc;
+irq_req_failed:
+	iounmap(vfe_dev->vfe_vbif_base);
+vbif_remap_failed:
+	iounmap(vfe_dev->vfe_base);
+vfe_remap_failed:
+	msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe40_clk_info,
+		vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe40_clk_info), 0);
+clk_enable_failed:
+	regulator_disable(vfe_dev->fs_vfe);
+fs_failed:
+	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
+	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+bus_scale_register_failed:
+	return rc;
+}
+
+static void msm_vfe40_release_hardware(struct vfe_device *vfe_dev)
+{
+	free_irq(vfe_dev->vfe_irq->start, vfe_dev);
+	tasklet_kill(&vfe_dev->vfe_tasklet);
+	iounmap(vfe_dev->vfe_vbif_base);
+	iounmap(vfe_dev->vfe_base);
+	msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe40_clk_info,
+		vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe40_clk_info), 0);
+	regulator_disable(vfe_dev->fs_vfe);
+	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
+	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+}
+
+static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
+{
+	/* CGC_OVERRIDE */
+	msm_camera_io_w(0x3FFFFFFF, vfe_dev->vfe_base + 0x14);
+	/* BUS_CFG */
+	msm_camera_io_w(0x00000001, vfe_dev->vfe_base + 0x50);
+	msm_camera_io_w(0x800000F3, vfe_dev->vfe_base + 0x28);
+	msm_camera_io_w_mb(0xFEFFFFFF, vfe_dev->vfe_base + 0x2C);
+	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x30);
+	msm_camera_io_w_mb(0xFEFFFFFF, vfe_dev->vfe_base + 0x34);
+}
+
+static void msm_vfe40_process_reset_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	if (irq_status0 & (1 << 31))
+		complete(&vfe_dev->reset_complete);
+}
+
+static void msm_vfe40_process_halt_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	if (irq_status1 & (1 << 8))
+		complete(&vfe_dev->halt_complete);
+}
+
+static void msm_vfe40_process_camif_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	if (!(irq_status0 & 0xF))
+		return;
+
+	if (vfe_dev->hw_info->vfe_ops.core_ops.epoch_irq) {
+		if (irq_status0 & (1 << 2)) {
+			ISP_DBG("%s: EPOCH0 IRQ, PIX0_frameid = 0x%lu\n",
+				__func__,
+				vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
+			msm_isp_new_frame_notify(vfe_dev, VFE_PIX_0);
+		}
+	} else {
+		if (irq_status0 & (1 << 0)) {
+			ISP_DBG("%s: SOF: PIX0 frame id: %lu\n", __func__,
+			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
+			msm_isp_new_frame_notify(vfe_dev, VFE_PIX_0);
+		}
+	}
+}
+
+static void msm_vfe40_process_violation_irq(
+	struct vfe_device *vfe_dev)
+{
+	uint32_t violation_status;
+	violation_status = msm_camera_io_r(vfe_dev->vfe_base + 0x48);
+	if (!violation_status)
+		return;
+
+	if (violation_status & (1 << 0))
+		pr_err("%s: camif violation\n", __func__);
+	if (violation_status & (1 << 1))
+		pr_err("%s: black violation\n", __func__);
+	if (violation_status & (1 << 2))
+		pr_err("%s: rolloff violation\n", __func__);
+	if (violation_status & (1 << 3))
+		pr_err("%s: demux violation\n", __func__);
+	if (violation_status & (1 << 4))
+		pr_err("%s: demosaic violation\n", __func__);
+	if (violation_status & (1 << 5))
+		pr_err("%s: wb violation\n", __func__);
+	if (violation_status & (1 << 6))
+		pr_err("%s: clf violation\n", __func__);
+	if (violation_status & (1 << 7))
+		pr_err("%s: color correct violation\n", __func__);
+	if (violation_status & (1 << 8))
+		pr_err("%s: rgb lut violation\n", __func__);
+	if (violation_status & (1 << 9))
+		pr_err("%s: la violation\n", __func__);
+	if (violation_status & (1 << 10))
+		pr_err("%s: chroma enhance violation\n", __func__);
+	if (violation_status & (1 << 11))
+		pr_err("%s: chroma supress mce violation\n", __func__);
+	if (violation_status & (1 << 12))
+		pr_err("%s: skin enhance violation\n", __func__);
+	if (violation_status & (1 << 13))
+		pr_err("%s: color tranform enc violation\n", __func__);
+	if (violation_status & (1 << 14))
+		pr_err("%s: color tranform view violation\n", __func__);
+	if (violation_status & (1 << 15))
+		pr_err("%s: scale enc y violation\n", __func__);
+	if (violation_status & (1 << 16))
+		pr_err("%s: scale enc cbcr violation\n", __func__);
+	if (violation_status & (1 << 17))
+		pr_err("%s: scale view y violation\n", __func__);
+	if (violation_status & (1 << 18))
+		pr_err("%s: scale view cbcr violation\n", __func__);
+	if (violation_status & (1 << 19))
+		pr_err("%s: asf enc violation\n", __func__);
+	if (violation_status & (1 << 20))
+		pr_err("%s: asf view violation\n", __func__);
+	if (violation_status & (1 << 21))
+		pr_err("%s: crop enc y violation\n", __func__);
+	if (violation_status & (1 << 22))
+		pr_err("%s: crop enc cbcr violation\n", __func__);
+	if (violation_status & (1 << 23))
+		pr_err("%s: crop view y violation\n", __func__);
+	if (violation_status & (1 << 24))
+		pr_err("%s: crop view cbcr violation\n", __func__);
+	if (violation_status & (1 << 25))
+		pr_err("%s: realign buf y violation\n", __func__);
+	if (violation_status & (1 << 26))
+		pr_err("%s: realign buf cb violation\n", __func__);
+	if (violation_status & (1 << 27))
+		pr_err("%s: realign buf cr violation\n", __func__);
+}
+
+static void msm_vfe40_process_error_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	uint32_t camif_status;
+	if (!(irq_status1 & 0x00FFFEFF))
+		return;
+
+	if (irq_status1 & (1 << 0)) {
+		camif_status = msm_camera_io_r(vfe_dev->vfe_base + 0x31C);
+		pr_err("%s: camif error status: 0x%x\n",
+			__func__, camif_status);
+	}
+	if (irq_status1 & (1 << 1))
+		pr_err("%s: stats bhist overwrite\n", __func__);
+	if (irq_status1 & (1 << 2))
+		pr_err("%s: stats cs overwrite\n", __func__);
+	if (irq_status1 & (1 << 3))
+		pr_err("%s: stats ihist overwrite\n", __func__);
+	if (irq_status1 & (1 << 4))
+		pr_err("%s: realign buf y overflow\n", __func__);
+	if (irq_status1 & (1 << 5))
+		pr_err("%s: realign buf cb overflow\n", __func__);
+	if (irq_status1 & (1 << 6))
+		pr_err("%s: realign buf cr overflow\n", __func__);
+	if (irq_status1 & (1 << 7)) {
+		pr_err("%s: violation\n", __func__);
+		msm_vfe40_process_violation_irq(vfe_dev);
+	}
+	if (irq_status1 & (1 << 9))
+		pr_err("%s: image master 0 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 10))
+		pr_err("%s: image master 1 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 11))
+		pr_err("%s: image master 2 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 12))
+		pr_err("%s: image master 3 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 13))
+		pr_err("%s: image master 4 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 14))
+		pr_err("%s: image master 5 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 15))
+		pr_err("%s: image master 6 bus overflow\n", __func__);
+	if (irq_status1 & (1 << 16))
+		pr_err("%s: status be bus overflow\n", __func__);
+	if (irq_status1 & (1 << 17))
+		pr_err("%s: status bg bus overflow\n", __func__);
+	if (irq_status1 & (1 << 18))
+		pr_err("%s: status bf bus overflow\n", __func__);
+	if (irq_status1 & (1 << 19))
+		pr_err("%s: status awb bus overflow\n", __func__);
+	if (irq_status1 & (1 << 20))
+		pr_err("%s: status rs bus overflow\n", __func__);
+	if (irq_status1 & (1 << 21))
+		pr_err("%s: status cs bus overflow\n", __func__);
+	if (irq_status1 & (1 << 22))
+		pr_err("%s: status ihist bus overflow\n", __func__);
+	if (irq_status1 & (1 << 23))
+		pr_err("%s: status skin bhist bus overflow\n", __func__);
+}
+
+static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev,
+	uint32_t *irq_status0, uint32_t *irq_status1)
+{
+	*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x38);
+	*irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x3C);
+	msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x30);
+	msm_camera_io_w(*irq_status1, vfe_dev->vfe_base + 0x34);
+	msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x24);
+}
+
+static void msm_vfe40_process_reg_update(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	uint32_t update_mask = 0xF;
+
+	if (!(irq_status0 & 0xF0))
+		return;
+
+	if (vfe_dev->axi_data.stream_update)
+		msm_isp_axi_stream_update(vfe_dev);
+	msm_isp_update_framedrop_reg(vfe_dev);
+
+	vfe_dev->hw_info->vfe_ops.core_ops.
+		reg_update(vfe_dev, update_mask);
+	return;
+}
+
+static void msm_vfe40_epoch_irq_enb(struct vfe_device *vfe_dev,
+	uint32_t epoch_line0, uint32_t epoch_line1)
+{
+	uint32_t irq_mask = 0;
+	uint32_t epoch_val = 0;
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
+	if (epoch_line0 > 0) {
+		irq_mask |= 0x4;
+		epoch_val |= (epoch_line0 - 1) << 16;
+	} else {
+		irq_mask &= ~0x4;
+		epoch_val &= 0xFFFF;
+	}
+	if (epoch_line1 > 0) {
+		irq_mask |= 0x8;
+		epoch_val |= epoch_line1 - 1;
+	} else {
+		irq_mask &= ~0x8;
+		epoch_val &= 0xFFFF0000;
+	}
+	msm_camera_io_w_mb(epoch_val, vfe_dev->vfe_base + 0x318);
+	msm_camera_io_w_mb(irq_mask, vfe_dev->vfe_base + 0x28);
+}
+
+static void msm_vfe40_reg_update(
+	struct vfe_device *vfe_dev, uint32_t update_mask)
+{
+	msm_camera_io_w_mb(update_mask, vfe_dev->vfe_base + 0x378);
+}
+
+static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev)
+{
+	init_completion(&vfe_dev->reset_complete);
+	msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC);
+	return wait_for_completion_interruptible_timeout(
+		&vfe_dev->reset_complete, msecs_to_jiffies(50));
+}
+
+static void msm_vfe40_axi_reload_wm(
+	struct vfe_device *vfe_dev, uint32_t reload_mask)
+{
+	msm_camera_io_w_mb(reload_mask, vfe_dev->vfe_base + 0x4C);
+}
+
+static void msm_vfe40_axi_enable_wm(struct vfe_device *vfe_dev,
+	uint8_t wm_idx, uint8_t enable)
+{
+	if (enable)
+		msm_camera_io_w_mb(0x1,
+			vfe_dev->vfe_base + VFE40_WM_BASE(wm_idx));
+	else
+		msm_camera_io_w_mb(0x0,
+			vfe_dev->vfe_base + VFE40_WM_BASE(wm_idx));
+}
+
+static void msm_vfe40_axi_cfg_comp_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	uint32_t comp_mask, comp_mask_index =
+		stream_info->comp_mask_index;
+	uint32_t irq_mask;
+
+	comp_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x40);
+	comp_mask &= ~(0x7F << (comp_mask_index * 8));
+	comp_mask |= (axi_data->composite_info[comp_mask_index].
+	stream_composite_mask << (comp_mask_index * 8));
+	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x40);
+
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
+	irq_mask |= 1 << (comp_mask_index + 25);
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
+}
+
+static void msm_vfe40_axi_clear_comp_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t comp_mask, comp_mask_index = stream_info->comp_mask_index;
+	uint32_t irq_mask;
+
+	comp_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x40);
+	comp_mask &= ~(0x7F << (comp_mask_index * 8));
+	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x40);
+
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
+	irq_mask &= ~(1 << (comp_mask_index + 25));
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
+}
+
+static void msm_vfe40_axi_cfg_wm_irq_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t irq_mask;
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
+	irq_mask |= 1 << (stream_info->wm[0] + 8);
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
+}
+
+static void msm_vfe40_axi_clear_wm_irq_mask(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t irq_mask;
+	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
+	irq_mask &= ~(1 << (stream_info->wm[0] + 8));
+	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
+}
+
+static void msm_vfe40_cfg_framedrop(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t i;
+	uint32_t framedrop_pattern = 0;
+
+	if (stream_info->init_frame_drop == 0)
+		framedrop_pattern = stream_info->framedrop_pattern;
+
+	if (stream_info->stream_type == BURST_STREAM &&
+			stream_info->burst_frame_count == 0)
+		framedrop_pattern = 0;
+
+	for (i = 0; i < stream_info->num_planes; i++)
+		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base +
+			VFE40_WM_BASE(stream_info->wm[i]) + 0x1C);
+
+	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x378);
+}
+
+static void msm_vfe40_clear_framedrop(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	uint32_t i;
+	for (i = 0; i < stream_info->num_planes; i++)
+		msm_camera_io_w(0, vfe_dev->vfe_base +
+			VFE40_WM_BASE(stream_info->wm[i]) + 0x1C);
+}
+
+static void msm_vfe40_cfg_camif(struct vfe_device *vfe_dev,
+	struct msm_vfe_pix_cfg *pix_cfg)
+{
+	uint16_t first_pixel, last_pixel, first_line, last_line;
+	struct msm_vfe_camif_cfg *camif_cfg = &pix_cfg->camif_cfg;
+	uint32_t val;
+
+	first_pixel = camif_cfg->first_pixel;
+	last_pixel = camif_cfg->last_pixel;
+	first_line = camif_cfg->first_line;
+	last_line = camif_cfg->last_line;
+
+	msm_camera_io_w(pix_cfg->input_mux << 16 | pix_cfg->pixel_pattern,
+		vfe_dev->vfe_base + 0x1C);
+
+	msm_camera_io_w(camif_cfg->lines_per_frame << 16 |
+		camif_cfg->pixels_per_line, vfe_dev->vfe_base + 0x300);
+
+	msm_camera_io_w(first_pixel << 16 | last_pixel,
+	vfe_dev->vfe_base + 0x304);
+
+	msm_camera_io_w(first_line << 16 | last_line,
+	vfe_dev->vfe_base + 0x308);
+
+	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x314);
+
+	val = msm_camera_io_r(vfe_dev->vfe_base + 0x2E8);
+	val |= camif_cfg->camif_input;
+	msm_camera_io_w(val, vfe_dev->vfe_base + 0x2E8);
+
+	vfe_dev->hw_info->vfe_ops.core_ops.epoch_irq(vfe_dev,
+		camif_cfg->epoch_line0, camif_cfg->epoch_line1);
+
+	switch (pix_cfg->input_mux) {
+	case CAMIF:
+		val = 0x01;
+		msm_camera_io_w(val, vfe_dev->vfe_base + 0x2F4);
+		break;
+	case TESTGEN:
+		val = 0x01;
+		msm_camera_io_w(val, vfe_dev->vfe_base + 0x93C);
+		break;
+	case EXTERNAL_READ:
+	default:
+		pr_err("%s: not supported input_mux %d\n",
+			__func__, pix_cfg->input_mux);
+		break;
+	}
+}
+
+static void msm_vfe40_update_camif_state(struct vfe_device *vfe_dev,
+	enum msm_isp_camif_update_state update_state)
+{
+	uint32_t val;
+	bool bus_en, vfe_en;
+	if (update_state == NO_UPDATE)
+		return;
+
+	val = msm_camera_io_r(vfe_dev->vfe_base + 0x2F8);
+	if (update_state == ENABLE_CAMIF) {
+		bus_en =
+			((vfe_dev->axi_data.
+			src_info[VFE_PIX_0].raw_stream_count > 0) ? 1 : 0);
+		vfe_en =
+			((vfe_dev->axi_data.
+			src_info[VFE_PIX_0].pix_stream_count > 0) ? 1 : 0);
+		val &= 0xFFFFFF3F;
+		val = val | bus_en << 7 | vfe_en << 6;
+		msm_camera_io_w(val, vfe_dev->vfe_base + 0x2F8);
+		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2F4);
+		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 1;
+	} else if (update_state == DISABLE_CAMIF) {
+		msm_camera_io_w_mb(0x0, vfe_dev->vfe_base + 0x2F4);
+		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
+	} else if (update_state == DISABLE_CAMIF_IMMEDIATELY) {
+		msm_camera_io_w_mb(0x2, vfe_dev->vfe_base + 0x2F4);
+		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
+	}
+}
+
+static void msm_vfe40_axi_cfg_wm_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	uint8_t plane_idx)
+{
+	uint32_t val;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	uint32_t wm_base = VFE40_WM_BASE(stream_info->wm[plane_idx]);
+
+	/*WR_ADDR_CFG*/
+	msm_camera_io_w(0x7C, vfe_dev->vfe_base + wm_base + 0xC);
+
+	/*WR_IMAGE_SIZE*/
+	val =
+		((msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
+		stream_cfg_cmd->plane_cfg[plane_idx].
+			output_width)+1)/2 - 1) << 16 |
+			(stream_cfg_cmd->plane_cfg[plane_idx].
+			output_height - 1);
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
+
+	/*WR_BUFFER_CFG*/
+	val =
+		msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
+		stream_cfg_cmd->plane_cfg[
+			plane_idx].output_width) << 16 |
+		(stream_cfg_cmd->plane_cfg[
+			plane_idx].output_scan_lines - 1) << 4 |
+		VFE40_BURST_LEN >> 2;
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x18);
+
+	/*WR_IRQ_SUBSAMPLE_PATTERN*/
+	msm_camera_io_w(0xFFFFFFFF,
+		vfe_dev->vfe_base + wm_base + 0x20);
+	/* TD: Add IRQ subsample pattern */
+	return;
+}
+
+static void msm_vfe40_axi_clear_wm_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx)
+{
+	uint32_t val = 0;
+	uint32_t wm_base = VFE40_WM_BASE(stream_info->wm[plane_idx]);
+	/*WR_ADDR_CFG*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0xC);
+	/*WR_IMAGE_SIZE*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
+	/*WR_BUFFER_CFG*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x18);
+	/*WR_IRQ_SUBSAMPLE_PATTERN*/
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x20);
+	return;
+}
+
+static void msm_vfe40_axi_cfg_rdi_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	uint8_t plane_idx)
+{
+	struct msm_vfe_axi_shared_data *axi_data =
+		&vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	struct msm_vfe_axi_plane_cfg *plane_cfg =
+		&stream_cfg_cmd->plane_cfg[plane_idx];
+	uint8_t rdi = stream_info->rdi[plane_idx];
+	uint8_t rdi_master = stream_info->rdi_master[plane_idx];
+	uint32_t rdi_reg_cfg;
+
+	rdi_reg_cfg = msm_camera_io_r(
+		vfe_dev->vfe_base + VFE40_RDI_BASE(rdi));
+	rdi_reg_cfg = (rdi_reg_cfg & 0xFFFFFFF) | rdi_master << 28;
+	msm_camera_io_w(
+		rdi_reg_cfg, vfe_dev->vfe_base + VFE40_RDI_BASE(rdi));
+
+	rdi_reg_cfg = msm_camera_io_r(
+		vfe_dev->vfe_base + VFE40_RDI_MN_BASE(rdi_master));
+	rdi_reg_cfg &= ~((0xF << VFE40_RDI_MN_SEL_SHIFT(rdi_master)) |
+		(0x1 << VFE40_RDI_MN_FB_SHIFT(rdi_master)));
+	rdi_reg_cfg |=
+		(plane_cfg->rdi_cid << VFE40_RDI_MN_SEL_SHIFT(rdi_master) |
+		(stream_cfg_cmd->frame_base <<
+		VFE40_RDI_MN_FB_SHIFT(rdi_master)));
+	msm_camera_io_w(rdi_reg_cfg,
+		vfe_dev->vfe_base + VFE40_RDI_MN_BASE(rdi_master));
+}
+
+static void msm_vfe40_axi_cfg_wm_xbar_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	uint8_t plane_idx)
+{
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	struct msm_vfe_axi_plane_cfg *plane_cfg =
+		&stream_cfg_cmd->plane_cfg[plane_idx];
+	uint8_t wm = stream_info->wm[plane_idx];
+	uint32_t xbar_cfg = 0;
+	uint32_t xbar_reg_cfg = 0;
+
+	switch (stream_cfg_cmd->stream_src) {
+	case PIX_ENCODER:
+	case PIX_VIEWFINDER: {
+		if (plane_cfg->output_plane_format
+				!= CRCB_PLANE) {
+			/*SINGLE_STREAM_SEL*/
+			xbar_cfg |= plane_cfg->output_plane_format << 8;
+		} else {
+			switch (stream_cfg_cmd->output_format) {
+			case V4L2_PIX_FMT_NV12:
+			case V4L2_PIX_FMT_NV16:
+				xbar_cfg |= 0x3 << 4; /*PAIR_STREAM_SWAP_CTRL*/
+				break;
+			}
+			xbar_cfg |= 0x1 << 1; /*PAIR_STREAM_EN*/
+		}
+		if (stream_cfg_cmd->stream_src == PIX_VIEWFINDER)
+			xbar_cfg |= 0x1; /*VIEW_STREAM_EN*/
+		break;
+	}
+	case CAMIF_RAW:
+		xbar_cfg = 0x300;
+		break;
+	case IDEAL_RAW:
+		xbar_cfg = 0x400;
+		break;
+	case RDI:
+		if (stream_info->rdi[plane_idx] == 0)
+			xbar_cfg = 0x500;
+		else if (stream_info->rdi[plane_idx] == 1)
+			xbar_cfg = 0x600;
+		else if (stream_info->rdi[plane_idx] == 2)
+			xbar_cfg = 0x700;
+		break;
+	default:
+		pr_err("%s: Invalid stream src\n", __func__);
+		break;
+	}
+	xbar_reg_cfg =
+		msm_camera_io_r(vfe_dev->vfe_base + VFE40_XBAR_BASE(wm));
+	xbar_reg_cfg &= ~(0xFFFF << VFE40_XBAR_SHIFT(wm));
+	xbar_reg_cfg |= (xbar_cfg << VFE40_XBAR_SHIFT(wm));
+	msm_camera_io_w(xbar_reg_cfg,
+		vfe_dev->vfe_base + VFE40_XBAR_BASE(wm));
+	return;
+}
+
+static void msm_vfe40_axi_clear_wm_xbar_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx)
+{
+	uint8_t wm = stream_info->wm[plane_idx];
+	uint32_t xbar_reg_cfg = 0;
+
+	xbar_reg_cfg =
+		msm_camera_io_r(vfe_dev->vfe_base + VFE40_XBAR_BASE(wm));
+	xbar_reg_cfg &= ~(0xFFFF << VFE40_XBAR_SHIFT(wm));
+	msm_camera_io_w(xbar_reg_cfg,
+		vfe_dev->vfe_base + VFE40_XBAR_BASE(wm));
+}
+
+#define MSM_ISP40_TOTAL_WM_UB 819
+
+static void msm_vfe40_cfg_axi_ub_equal_default(
+	struct vfe_device *vfe_dev)
+{
+	int i;
+	uint32_t ub_offset = 0;
+	struct msm_vfe_axi_shared_data *axi_data =
+		&vfe_dev->axi_data;
+	uint32_t total_image_size = 0;
+	uint8_t num_used_wms = 0;
+	uint32_t prop_size = 0;
+	uint32_t wm_ub_size;
+	uint32_t delta;
+
+	for (i = 0; i < axi_data->hw_info->num_wm; i++) {
+		if (axi_data->free_wm[i] > 0) {
+			num_used_wms++;
+			total_image_size += axi_data->wm_image_size[i];
+		}
+	}
+	prop_size = MSM_ISP40_TOTAL_WM_UB -
+		axi_data->hw_info->min_wm_ub * num_used_wms;
+	for (i = 0; i < axi_data->hw_info->num_wm; i++) {
+		if (axi_data->free_wm[i]) {
+			delta =
+				(axi_data->wm_image_size[i] *
+					prop_size)/total_image_size;
+			wm_ub_size = axi_data->hw_info->min_wm_ub + delta;
+			msm_camera_io_w(ub_offset << 16 | (wm_ub_size - 1),
+				vfe_dev->vfe_base + VFE40_WM_BASE(i) + 0x10);
+			ub_offset += wm_ub_size;
+		} else
+			msm_camera_io_w(0,
+				vfe_dev->vfe_base + VFE40_WM_BASE(i) + 0x10);
+	}
+}
+
+static void msm_vfe40_cfg_axi_ub_equal_slicing(
+	struct vfe_device *vfe_dev)
+{
+	int i;
+	uint32_t ub_offset = 0;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	for (i = 0; i < axi_data->hw_info->num_wm; i++) {
+		msm_camera_io_w(ub_offset << 16 | (VFE40_EQUAL_SLICE_UB - 1),
+			vfe_dev->vfe_base + VFE40_WM_BASE(i) + 0x10);
+		ub_offset += VFE40_EQUAL_SLICE_UB;
+	}
+}
+
+static void msm_vfe40_cfg_axi_ub(struct vfe_device *vfe_dev)
+{
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+
+	if (axi_data->wm_ub_cfg_policy == MSM_WM_UB_EQUAL_SLICING)
+		msm_vfe40_cfg_axi_ub_equal_slicing(vfe_dev);
+	else
+		msm_vfe40_cfg_axi_ub_equal_default(vfe_dev);
+}
+
+static void msm_vfe40_update_ping_pong_addr(
+	struct vfe_device *vfe_dev,
+	uint8_t wm_idx, uint32_t pingpong_status, unsigned long paddr)
+{
+	msm_camera_io_w(paddr, vfe_dev->vfe_base +
+		VFE40_PING_PONG_BASE(wm_idx, pingpong_status));
+}
+
+static long msm_vfe40_axi_halt(struct vfe_device *vfe_dev)
+{
+	uint32_t halt_mask;
+	halt_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
+	halt_mask |= (1 << 8);
+	msm_camera_io_w_mb(halt_mask, vfe_dev->vfe_base + 0x2C);
+	init_completion(&vfe_dev->halt_complete);
+	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0);
+	return wait_for_completion_interruptible_timeout(
+		&vfe_dev->halt_complete, msecs_to_jiffies(500));
+}
+
+static uint32_t msm_vfe40_get_wm_mask(
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	return (irq_status0 >> 8) & 0x7F;
+}
+
+static uint32_t msm_vfe40_get_comp_mask(
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	return (irq_status0 >> 25) & 0xF;
+}
+
+static uint32_t msm_vfe40_get_pingpong_status(
+	struct vfe_device *vfe_dev)
+{
+	return msm_camera_io_r(vfe_dev->vfe_base + 0x268);
+}
+
+static void msm_vfe40_stats_cfg_comp_mask(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+
+}
+
+static void msm_vfe40_stats_clear_comp_mask(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+
+}
+
+static void msm_vfe40_stats_cfg_wm_irq_mask(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+
+}
+
+static void msm_vfe40_stats_clear_wm_irq_mask(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+
+}
+
+static void msm_vfe40_stats_cfg_wm_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream_request_cmd *stream_cfg_cmd)
+{
+
+}
+
+static void msm_vfe40_stats_clear_wm_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+
+}
+
+static void msm_vfe40_stats_cfg_ub(struct vfe_device *vfe_dev)
+{
+}
+
+static void msm_vfe40_stats_enable(struct vfe_device *vfe_dev,
+	uint32_t stats_mask, uint8_t enable)
+{
+
+}
+
+static void msm_vfe40_stats_update_ping_pong_addr(
+	struct vfe_device *vfe_dev,
+	enum msm_isp_stats_type stats_type,
+	uint32_t pingpong_status,
+	unsigned long paddr)
+{
+}
+
+static uint32_t msm_vfe40_stats_get_wm_mask(
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	return (irq_status0 >> 16) & 0xFF;
+}
+
+static uint32_t msm_vfe40_stats_get_comp_mask(
+	uint32_t irq_status0, uint32_t irq_status1)
+{
+	return (irq_status0 >> 29) & 0x2;
+}
+
+static uint32_t msm_vfe40_stats_get_frame_id(
+	struct vfe_device *vfe_dev)
+{
+	return vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
+}
+static int msm_vfe40_get_platform_data(struct vfe_device *vfe_dev)
+{
+	int rc = 0;
+	vfe_dev->vfe_mem = platform_get_resource_byname(vfe_dev->pdev,
+		IORESOURCE_MEM, "vfe");
+	if (!vfe_dev->vfe_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+	vfe_dev->vfe_vbif_mem = platform_get_resource_byname(
+		vfe_dev->pdev,
+		IORESOURCE_MEM, "vfe_vbif");
+	if (!vfe_dev->vfe_vbif_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+	vfe_dev->vfe_irq = platform_get_resource_byname(vfe_dev->pdev,
+		IORESOURCE_IRQ, "vfe");
+	if (!vfe_dev->vfe_irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+	vfe_dev->fs_vfe = regulator_get(&vfe_dev->pdev->dev, "vdd");
+	if (IS_ERR(vfe_dev->fs_vfe)) {
+		pr_err("%s: Regulator get failed %ld\n", __func__,
+		PTR_ERR(vfe_dev->fs_vfe));
+		vfe_dev->fs_vfe = NULL;
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+	if (vfe_dev->pdev->id == 0)
+		vfe_dev->iommu_ctx = msm_iommu_get_ctx("vfe0");
+	else if (vfe_dev->pdev->id == 1)
+		vfe_dev->iommu_ctx = msm_iommu_get_ctx("vfe1");
+	if (!vfe_dev->iommu_ctx) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe_no_resource;
+	}
+
+vfe_no_resource:
+	return rc;
+}
+
+struct msm_vfe_axi_hardware_info msm_vfe40_axi_hw_info = {
+	.num_wm = 7,
+	.num_comp_mask = 4,
+	.num_rdi = 3,
+	.num_rdi_master = 3,
+	.min_wm_ub = 64,
+};
+
+static struct v4l2_subdev_core_ops msm_vfe40_subdev_core_ops = {
+	.ioctl = msm_isp_ioctl,
+	.subscribe_event = msm_isp_subscribe_event,
+	.unsubscribe_event = msm_isp_unsubscribe_event,
+};
+
+static struct v4l2_subdev_ops msm_vfe40_subdev_ops = {
+	.core = &msm_vfe40_subdev_core_ops,
+};
+
+static struct v4l2_subdev_internal_ops msm_vfe40_internal_ops = {
+	.open = msm_isp_open_node,
+	.close = msm_isp_close_node,
+};
+
+struct msm_vfe_hardware_info vfe40_hw_info = {
+	.vfe_ops = {
+		.irq_ops = {
+			.read_irq_status = msm_vfe40_read_irq_status,
+			.process_camif_irq = msm_vfe40_process_camif_irq,
+			.process_reset_irq = msm_vfe40_process_reset_irq,
+			.process_halt_irq = msm_vfe40_process_halt_irq,
+			.process_reset_irq = msm_vfe40_process_reset_irq,
+			.process_error_irq = msm_vfe40_process_error_irq,
+			.process_reg_update = msm_vfe40_process_reg_update,
+			.process_axi_irq = msm_isp_process_axi_irq,
+			.process_stats_irq = msm_isp_process_stats_irq,
+		},
+		.axi_ops = {
+			.reload_wm = msm_vfe40_axi_reload_wm,
+			.enable_wm = msm_vfe40_axi_enable_wm,
+			.cfg_comp_mask = msm_vfe40_axi_cfg_comp_mask,
+			.clear_comp_mask = msm_vfe40_axi_clear_comp_mask,
+			.cfg_wm_irq_mask = msm_vfe40_axi_cfg_wm_irq_mask,
+			.clear_wm_irq_mask = msm_vfe40_axi_clear_wm_irq_mask,
+			.cfg_framedrop = msm_vfe40_cfg_framedrop,
+			.clear_framedrop = msm_vfe40_clear_framedrop,
+			.cfg_wm_reg = msm_vfe40_axi_cfg_wm_reg,
+			.clear_wm_reg = msm_vfe40_axi_clear_wm_reg,
+			.cfg_wm_xbar_reg = msm_vfe40_axi_cfg_wm_xbar_reg,
+			.clear_wm_xbar_reg = msm_vfe40_axi_clear_wm_xbar_reg,
+			.cfg_rdi_reg = msm_vfe40_axi_cfg_rdi_reg,
+			.cfg_ub = msm_vfe40_cfg_axi_ub,
+			.update_ping_pong_addr =
+				msm_vfe40_update_ping_pong_addr,
+			.get_comp_mask = msm_vfe40_get_comp_mask,
+			.get_wm_mask = msm_vfe40_get_wm_mask,
+			.get_pingpong_status = msm_vfe40_get_pingpong_status,
+			.halt = msm_vfe40_axi_halt,
+		},
+		.core_ops = {
+			.epoch_irq = msm_vfe40_epoch_irq_enb,
+			.reg_update = msm_vfe40_reg_update,
+			.cfg_camif = msm_vfe40_cfg_camif,
+			.update_camif_state = msm_vfe40_update_camif_state,
+			.reset_hw = msm_vfe40_reset_hardware,
+			.init_hw = msm_vfe40_init_hardware,
+			.init_hw_reg = msm_vfe40_init_hardware_reg,
+			.release_hw = msm_vfe40_release_hardware,
+			.get_platform_data = msm_vfe40_get_platform_data,
+		},
+		.stats_ops = {
+			.cfg_comp_mask = msm_vfe40_stats_cfg_comp_mask,
+			.clear_comp_mask = msm_vfe40_stats_clear_comp_mask,
+			.cfg_wm_irq_mask = msm_vfe40_stats_cfg_wm_irq_mask,
+			.clear_wm_irq_mask = msm_vfe40_stats_clear_wm_irq_mask,
+			.cfg_wm_reg = msm_vfe40_stats_cfg_wm_reg,
+			.clear_wm_reg = msm_vfe40_stats_clear_wm_reg,
+			.cfg_ub = msm_vfe40_stats_cfg_ub,
+			.stats_enable = msm_vfe40_stats_enable,
+			.update_ping_pong_addr =
+				msm_vfe40_stats_update_ping_pong_addr,
+			.get_comp_mask = msm_vfe40_stats_get_comp_mask,
+			.get_wm_mask = msm_vfe40_stats_get_wm_mask,
+			.get_frame_id = msm_vfe40_stats_get_frame_id,
+		},
+	},
+	.axi_hw_info = &msm_vfe40_axi_hw_info,
+	.subdev_ops = &msm_vfe40_subdev_ops,
+	.subdev_internal_ops = &msm_vfe40_internal_ops,
+};
+EXPORT_SYMBOL(vfe40_hw_info);
diff --git a/arch/arm/boot/dts/msm8910-sim.dts b/drivers/media/video/msmb/isp/msm_isp40.h
similarity index 63%
copy from arch/arm/boot/dts/msm8910-sim.dts
copy to drivers/media/video/msmb/isp/msm_isp40.h
index aae88b1..e9b1518 100644
--- a/arch/arm/boot/dts/msm8910-sim.dts
+++ b/drivers/media/video/msmb/isp/msm_isp40.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,16 +10,8 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
+#ifndef __MSM_ISP40_H__
+#define __MSM_ISP40_H__
 
-/include/ "msm8910.dtsi"
-
-/ {
-	model = "Qualcomm MSM 8910 Simulator";
-	compatible = "qcom,msm8910-sim", "qcom,msm8910";
-	qcom,msm-id = <147 1 0>;
-
-	serial@f991f000 {
-		status = "ok";
-	};
-};
+extern struct msm_vfe_hardware_info vfe40_hw_info;
+#endif /* __MSM_ISP40_H__ */
diff --git a/drivers/media/video/msmb/isp/msm_isp_axi_util.c b/drivers/media/video/msmb/isp/msm_isp_axi_util.c
new file mode 100644
index 0000000..fe55b40
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp_axi_util.c
@@ -0,0 +1,968 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+#include "msm_isp_util.h"
+#include "msm_isp_axi_util.h"
+
+int msm_isp_axi_create_stream(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+{
+	int i, rc = -1;
+	for (i = 0; i < MAX_NUM_STREAM; i++) {
+		if (axi_data->stream_info[i].state == AVALIABLE)
+			break;
+	}
+
+	if (i == MAX_NUM_STREAM) {
+		pr_err("%s: No free stream\n", __func__);
+		return rc;
+	}
+
+	axi_data->stream_info[i].session_id = stream_cfg_cmd->session_id;
+	axi_data->stream_info[i].stream_id = stream_cfg_cmd->stream_id;
+	axi_data->stream_info[i].buf_divert = stream_cfg_cmd->buf_divert;
+	axi_data->stream_info[i].state = INACTIVE;
+
+	if ((axi_data->stream_handle_cnt << 8) == 0)
+		axi_data->stream_handle_cnt++;
+
+	stream_cfg_cmd->axi_stream_handle =
+		(++axi_data->stream_handle_cnt) << 8 | i;
+
+	return 0;
+}
+
+void msm_isp_axi_destroy_stream(
+	struct msm_vfe_axi_shared_data *axi_data, int stream_idx)
+{
+	if (axi_data->stream_info[stream_idx].state != AVALIABLE)
+		axi_data->stream_info[stream_idx].state = AVALIABLE;
+	else
+		pr_err("%s: stream does not exist\n", __func__);
+}
+
+int msm_isp_validate_axi_request(struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+{
+	int rc = -1;
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+
+	switch (stream_cfg_cmd->output_format) {
+	case V4L2_PIX_FMT_SBGGR8:
+	case V4L2_PIX_FMT_SGBRG8:
+	case V4L2_PIX_FMT_SGRBG8:
+	case V4L2_PIX_FMT_SRGGB8:
+	case V4L2_PIX_FMT_SBGGR10:
+	case V4L2_PIX_FMT_SGBRG10:
+	case V4L2_PIX_FMT_SGRBG10:
+	case V4L2_PIX_FMT_SRGGB10:
+	case V4L2_PIX_FMT_SBGGR12:
+	case V4L2_PIX_FMT_SGBRG12:
+	case V4L2_PIX_FMT_SGRBG12:
+	case V4L2_PIX_FMT_SRGGB12:
+		stream_info->num_planes = 1;
+		break;
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		stream_info->num_planes = 2;
+		break;
+	/*TD: Add more image format*/
+	default:
+		pr_err("%s: Invalid output format\n", __func__);
+		return rc;
+	}
+
+	if (axi_data->hw_info->num_wm - axi_data->num_used_wm <
+		stream_info->num_planes) {
+		pr_err("%s: No free write masters\n", __func__);
+		return rc;
+	}
+
+	if ((stream_info->num_planes > 1) &&
+			(axi_data->hw_info->num_comp_mask -
+			axi_data->num_used_composite_mask < 1)) {
+		pr_err("%s: No free composite mask\n", __func__);
+		return rc;
+	}
+
+	if (stream_cfg_cmd->stream_src == RDI) {
+		if (axi_data->hw_info->num_rdi -
+			axi_data->num_used_rdi < stream_info->num_planes) {
+			pr_err("%s: No free RDI\n", __func__);
+			return rc;
+		}
+	}
+
+	if (stream_cfg_cmd->init_frame_drop >= MAX_INIT_FRAME_DROP) {
+		pr_err("%s: Invalid skip pattern\n", __func__);
+		return rc;
+	}
+
+	if (stream_cfg_cmd->frame_skip_pattern >= MAX_SKIP) {
+		pr_err("%s: Invalid skip pattern\n", __func__);
+		return rc;
+	}
+
+	return 0;
+}
+
+static uint32_t msm_isp_axi_get_plane_size(
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd, int plane_idx)
+{
+	uint32_t size = 0;
+	struct msm_vfe_axi_plane_cfg *plane_cfg = stream_cfg_cmd->plane_cfg;
+	switch (stream_cfg_cmd->output_format) {
+	case V4L2_PIX_FMT_SBGGR8:
+	case V4L2_PIX_FMT_SGBRG8:
+	case V4L2_PIX_FMT_SGRBG8:
+	case V4L2_PIX_FMT_SRGGB8:
+		size = plane_cfg[plane_idx].output_height *
+		plane_cfg[plane_idx].output_width;
+		break;
+	case V4L2_PIX_FMT_SBGGR10:
+	case V4L2_PIX_FMT_SGBRG10:
+	case V4L2_PIX_FMT_SGRBG10:
+	case V4L2_PIX_FMT_SRGGB10:
+		/* TODO: fix me */
+		size = plane_cfg[plane_idx].output_height *
+		plane_cfg[plane_idx].output_width;
+		break;
+	case V4L2_PIX_FMT_SBGGR12:
+	case V4L2_PIX_FMT_SGBRG12:
+	case V4L2_PIX_FMT_SGRBG12:
+	case V4L2_PIX_FMT_SRGGB12:
+		/* TODO: fix me */
+		size = plane_cfg[plane_idx].output_height *
+		plane_cfg[plane_idx].output_width;
+		break;
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		if (plane_cfg[plane_idx].output_plane_format == Y_PLANE)
+			size = plane_cfg[plane_idx].output_height *
+				plane_cfg[plane_idx].output_width;
+		else
+			size = plane_cfg[plane_idx].output_height *
+				plane_cfg[plane_idx].output_width / 2;
+		break;
+	/*TD: Add more image format*/
+	default:
+		pr_err("%s: Invalid output format\n", __func__);
+		break;
+	}
+	return size;
+}
+
+void msm_isp_axi_reserve_wm(struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+{
+	int i, j;
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+
+	for (i = 0; i < stream_info->num_planes; i++) {
+		for (j = 0; j < axi_data->hw_info->num_wm; j++) {
+			if (!axi_data->free_wm[j]) {
+				axi_data->free_wm[j] =
+					stream_cfg_cmd->axi_stream_handle;
+				axi_data->wm_image_size[j] =
+					msm_isp_axi_get_plane_size(
+						stream_cfg_cmd, i);
+				axi_data->num_used_wm++;
+				break;
+			}
+		}
+		stream_info->wm[i] = j;
+	}
+}
+
+void msm_isp_axi_free_wm(struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	int i;
+	for (i = 0; i < stream_info->num_planes; i++) {
+		axi_data->free_wm[stream_info->wm[i]] = 0;
+		axi_data->num_used_wm--;
+	}
+}
+
+void msm_isp_axi_reserve_rdi(struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+{
+	int i, j;
+	struct msm_vfe_axi_stream *stream_info =
+	&axi_data->stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+
+	for (i = 0; i < stream_info->num_planes; i++) {
+		uint8_t csid = stream_cfg_cmd->plane_cfg[i].csid_src;
+
+		for (j = 0; j < axi_data->hw_info->num_rdi; j++) {
+			if (!axi_data->free_rdi[j]) {
+				axi_data->free_rdi[j] = 1;
+				axi_data->num_used_rdi++;
+				break;
+			}
+		}
+		stream_info->rdi[i] = j;
+
+		for (j = 0; j < axi_data->hw_info->num_rdi; j++) {
+			if (!axi_data->free_rdi_master[csid][j]) {
+				axi_data->free_rdi_master[csid][j] = 1;
+				axi_data->num_used_rdi++;
+				break;
+			}
+		}
+		stream_info->rdi_master[i] =
+			csid * axi_data->hw_info->num_rdi_master + j;
+	}
+	return;
+}
+
+void msm_isp_axi_reserve_comp_mask(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+{
+	int i;
+	uint8_t comp_mask = 0;
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	for (i = 0; i < stream_info->num_planes; i++)
+		comp_mask |= 1 << stream_info->wm[i];
+
+	for (i = 0; i < axi_data->hw_info->num_comp_mask; i++) {
+		if (!axi_data->composite_info[i].stream_handle) {
+			axi_data->composite_info[i].stream_handle =
+			stream_cfg_cmd->axi_stream_handle;
+			axi_data->composite_info[i].
+				stream_composite_mask = comp_mask;
+			axi_data->num_used_composite_mask++;
+			break;
+		}
+	}
+	stream_info->comp_mask_index = i;
+	return;
+}
+
+void msm_isp_axi_free_comp_mask(struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	axi_data->composite_info[stream_info->comp_mask_index].
+		stream_composite_mask = 0;
+	axi_data->composite_info[stream_info->comp_mask_index].
+		stream_handle = 0;
+	axi_data->num_used_composite_mask--;
+}
+
+int msm_isp_axi_check_stream_state(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd)
+{
+	int rc = 0, i, j;
+	uint8_t src_state;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info;
+	enum msm_vfe_axi_state valid_state =
+		(stream_cfg_cmd->cmd == START_STREAM) ? INACTIVE : ACTIVE;
+
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		stream_info = &axi_data->stream_info[
+			(stream_cfg_cmd->stream_handle[i] & 0xFF)];
+		if (stream_info->state != valid_state) {
+			pr_err("%s: Invalid stream state\n", __func__);
+			rc = -EINVAL;
+			break;
+		}
+		/*
+		 * For RDI stream, if multiple RDIs are used
+		 * check if all the RDI srcs are in the same state, on/off
+		 */
+		if (stream_info->stream_src == RDI) {
+			src_state = axi_data->src_info[
+				stream_info->rdi[0]+1].active;
+			for (j = 0; j < stream_info->num_planes; j++) {
+				if (src_state !=
+						axi_data->src_info[
+						stream_info->rdi[j]+1].active) {
+					pr_err("%s: RDI stream has inconsistent state\n",
+						__func__);
+					rc = -EINVAL;
+					break;
+				}
+			}
+		}
+
+		if (stream_cfg_cmd->cmd == START_STREAM) {
+			stream_info->bufq_handle =
+				vfe_dev->buf_mgr->ops->get_bufq_handle(
+			vfe_dev->buf_mgr, stream_info->session_id,
+			stream_info->stream_id);
+			if (stream_info->bufq_handle == 0) {
+				pr_err("%s: Stream has no valid buffer queue\n",
+					__func__);
+				rc = -EINVAL;
+				break;
+			}
+		}
+	}
+	return rc;
+}
+
+void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev)
+{
+	int i;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info;
+	for (i = 0; i < MAX_NUM_STREAM; i++) {
+		stream_info = &axi_data->stream_info[i];
+		if (stream_info->framedrop_update) {
+			if (stream_info->init_frame_drop == 0) {
+				stream_info->framedrop_update = 0;
+				vfe_dev->hw_info->vfe_ops.axi_ops.
+				cfg_framedrop(vfe_dev, stream_info);
+			}
+		}
+		if (stream_info->stream_type == BURST_STREAM) {
+			if (stream_info->burst_frame_count == 0 &&
+					stream_info->state == ACTIVE) {
+				vfe_dev->hw_info->vfe_ops.axi_ops.
+				cfg_framedrop(vfe_dev, stream_info);
+				if (stream_info->stream_src == RDI) {
+					uint32_t wm_reload_mask = 0,
+					reg_update_mask = 0;
+					stream_info->state = STOP_PENDING;
+					msm_isp_axi_stream_enable_cfg(
+						vfe_dev, stream_info,
+						&wm_reload_mask,
+						&reg_update_mask);
+				}
+			}
+		}
+	}
+}
+
+void msm_isp_update_framedrop_count(
+	struct vfe_device *vfe_dev)
+{
+	int i;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info;
+	for (i = 0; i < MAX_NUM_STREAM; i++) {
+		stream_info = &axi_data->stream_info[i];
+		if (stream_info->framedrop_update) {
+			stream_info->init_frame_drop--;
+			if (stream_info->init_frame_drop == 1) {
+				vfe_dev->hw_info->vfe_ops.core_ops.
+					reg_update(vfe_dev, 0xF);
+			}
+		}
+		if (stream_info->stream_type == BURST_STREAM) {
+			stream_info->burst_frame_count--;
+			if (stream_info->burst_frame_count == 1) {
+				vfe_dev->hw_info->vfe_ops.core_ops.
+					reg_update(vfe_dev, 0xF);
+			} else if (stream_info->burst_frame_count == 0) {
+				if (stream_info->stream_src != RDI) {
+					vfe_dev->hw_info->vfe_ops.core_ops.
+						update_camif_state(vfe_dev,
+						DISABLE_CAMIF);
+					pr_err("%s: pending burst_cnt = %d, disable camif\n",
+						__func__,
+						stream_info->burst_frame_count);
+				}
+			}
+		}
+	}
+}
+
+void msm_isp_new_frame_notify(struct vfe_device *vfe_dev,
+	enum msm_vfe_input_src frame_src) {
+	switch (frame_src) {
+	case VFE_PIX_0:
+		ISP_DBG("%s: PIX0 frame id: %lu\n", __func__,
+			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
+		msm_isp_update_framedrop_count(vfe_dev);
+		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id++;
+		if (vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id == 0)
+			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id = 1;
+		break;
+	case VFE_RAW_0:
+	case VFE_RAW_1:
+	case VFE_RAW_2:
+		break;
+	default:
+		pr_err("%s: invalid frame src %d received\n",
+			__func__, frame_src);
+		break;
+	}
+}
+void msm_isp_calculate_framedrop(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+{
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+		(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	uint32_t framedrop_period = 1;
+
+	switch (stream_cfg_cmd->frame_skip_pattern) {
+	case NO_SKIP:
+		stream_info->framedrop_pattern = VFE_NO_DROP;
+		framedrop_period = 1;
+		break;
+	case EVERY_2FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_2FRAME;
+		framedrop_period = 2;
+		break;
+	case EVERY_4FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_4FRAME;
+		framedrop_period = 4;
+		break;
+	case EVERY_8FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_8FRAME;
+		framedrop_period = 8;
+		break;
+	case EVERY_16FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_16FRAME;
+		framedrop_period = 16;
+		break;
+	case EVERY_32FRAME:
+		stream_info->framedrop_pattern = VFE_DROP_EVERY_32FRAME;
+		framedrop_period = 32;
+		break;
+	default:
+		stream_info->framedrop_pattern = VFE_NO_DROP;
+		framedrop_period = 1;
+		break;
+	}
+
+	if (stream_cfg_cmd->init_frame_drop < framedrop_period) {
+		stream_info->framedrop_pattern <<=
+			stream_cfg_cmd->init_frame_drop;
+		stream_info->init_frame_drop = 0;
+		stream_info->framedrop_update = 0;
+	} else {
+		stream_info->init_frame_drop = stream_cfg_cmd->init_frame_drop;
+		stream_info->framedrop_update = 1;
+	}
+
+	if (stream_cfg_cmd->burst_count > 0) {
+		stream_info->stream_type = BURST_STREAM;
+		stream_info->burst_frame_count =
+		stream_cfg_cmd->init_frame_drop +
+			(stream_cfg_cmd->burst_count - 1) *
+			framedrop_period + 1;
+	} else {
+		stream_info->stream_type = CONTINUOUS_STREAM;
+		stream_info->burst_frame_count = 0;
+	}
+}
+
+int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0, i;
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd = arg;
+	struct msm_vfe_axi_stream *stream_info;
+
+	rc = msm_isp_axi_create_stream(
+		&vfe_dev->axi_data, stream_cfg_cmd);
+	if (rc) {
+		pr_err("%s: create stream failed\n", __func__);
+		return rc;
+	}
+
+	rc = msm_isp_validate_axi_request(
+		&vfe_dev->axi_data, stream_cfg_cmd);
+	if (rc) {
+		pr_err("%s: Request validation failed\n", __func__);
+		msm_isp_axi_destroy_stream(&vfe_dev->axi_data,
+			(stream_cfg_cmd->axi_stream_handle & 0xFF));
+		return rc;
+	}
+
+	msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_cfg_cmd);
+	if (stream_cfg_cmd->stream_src == RDI)
+		msm_isp_axi_reserve_rdi(&vfe_dev->axi_data, stream_cfg_cmd);
+
+	stream_info =
+		&vfe_dev->axi_data.
+			stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+
+	msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);
+	vfe_dev->hw_info->vfe_ops.axi_ops.cfg_framedrop(vfe_dev, stream_info);
+
+	if (stream_info->num_planes > 1) {
+		msm_isp_axi_reserve_comp_mask(
+			&vfe_dev->axi_data, stream_cfg_cmd);
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+		cfg_comp_mask(vfe_dev, stream_info);
+	} else {
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+			cfg_wm_irq_mask(vfe_dev, stream_info);
+	}
+
+	for (i = 0; i < stream_info->num_planes; i++) {
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+			cfg_wm_reg(vfe_dev, stream_cfg_cmd, i);
+
+	vfe_dev->hw_info->vfe_ops.axi_ops.
+		cfg_wm_xbar_reg(vfe_dev, stream_cfg_cmd, i);
+
+	if (stream_cfg_cmd->stream_src == RDI)
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+			cfg_rdi_reg(vfe_dev, stream_cfg_cmd, i);
+	}
+	return rc;
+}
+
+int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0, i;
+	struct msm_vfe_axi_stream_release_cmd *stream_release_cmd = arg;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_vfe_axi_stream *stream_info =
+		&axi_data->stream_info[
+		(stream_release_cmd->stream_handle & 0xFF)];
+	struct msm_vfe_axi_stream_cfg_cmd stream_cfg;
+
+	if (stream_info->state == AVALIABLE) {
+		pr_err("%s: Stream already released\n", __func__);
+		return -EINVAL;
+	} else if (stream_info->state != INACTIVE) {
+		stream_cfg.cmd = STOP_STREAM;
+		stream_cfg.num_streams = 1;
+		stream_cfg.stream_handle[0] = stream_release_cmd->stream_handle;
+		msm_isp_cfg_axi_stream(vfe_dev, (void *) &stream_cfg);
+	}
+
+	for (i = 0; i < stream_info->num_planes; i++) {
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+			clear_wm_reg(vfe_dev, stream_info, i);
+
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+		clear_wm_xbar_reg(vfe_dev, stream_info, i);
+	}
+
+	if (stream_info->num_planes > 1) {
+		msm_isp_axi_free_comp_mask(&vfe_dev->axi_data, stream_info);
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+		clear_comp_mask(vfe_dev, stream_info);
+	} else {
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+		clear_wm_irq_mask(vfe_dev, stream_info);
+	}
+
+	vfe_dev->hw_info->vfe_ops.axi_ops.clear_framedrop(vfe_dev, stream_info);
+	msm_isp_axi_free_wm(axi_data, stream_info);
+
+	msm_isp_axi_destroy_stream(&vfe_dev->axi_data,
+		(stream_release_cmd->stream_handle & 0xFF));
+
+	return rc;
+}
+
+void msm_isp_axi_stream_enable_cfg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info,
+	uint32_t *wm_reload_mask, uint32_t *reg_update_mask)
+{
+	int i;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	if (stream_info->state == INACTIVE)
+		return;
+	for (i = 0; i < stream_info->num_planes; i++) {
+		/*TD: Frame base command*/
+		if (stream_info->state == START_PENDING)
+			vfe_dev->hw_info->vfe_ops.axi_ops.
+				enable_wm(vfe_dev, stream_info->wm[i], 1);
+		else
+			vfe_dev->hw_info->vfe_ops.axi_ops.
+				enable_wm(vfe_dev, stream_info->wm[i], 0);
+
+	*wm_reload_mask |= (1 << stream_info->wm[i]);
+	if (stream_info->stream_src == RDI)
+		*reg_update_mask |= (1 << stream_info->rdi[i]);
+	}
+	if (stream_info->state == START_PENDING) {
+		axi_data->num_active_stream++;
+		stream_info->state = ACTIVE;
+	} else {
+		axi_data->num_active_stream--;
+		stream_info->state = INACTIVE;
+	}
+}
+
+void msm_isp_axi_stream_update(struct vfe_device *vfe_dev)
+{
+	int i;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	uint32_t wm_reload_mask = 0x0, reg_update_mask = 0x1;
+	int send_update_complete = 0;
+	for (i = 0; i < MAX_NUM_STREAM; i++) {
+		if (axi_data->stream_info[i].state == START_PENDING ||
+				axi_data->stream_info[i].state ==
+					STOP_PENDING) {
+			msm_isp_axi_stream_enable_cfg(
+				vfe_dev, &axi_data->stream_info[i],
+				&wm_reload_mask, &reg_update_mask);
+			if (axi_data->stream_info[i].state == STOP_PENDING)
+				axi_data->stream_info[i].state = STOPPING;
+		} else if (axi_data->stream_info[i].state == STOPPING) {
+			send_update_complete = 1;
+			axi_data->stream_info[i].state = INACTIVE;
+		}
+	}
+	/*Reload AXI*/
+	vfe_dev->hw_info->vfe_ops.axi_ops.
+		reload_wm(vfe_dev, wm_reload_mask);
+	/*Reg update per src*/
+	vfe_dev->hw_info->vfe_ops.core_ops.
+		reg_update(vfe_dev, reg_update_mask);
+	if (send_update_complete) {
+		ISP_DBG("%s: send update complete\n", __func__);
+		vfe_dev->axi_data.stream_update = 0;
+		complete(&vfe_dev->stream_config_complete);
+	}
+}
+
+#define VFE_PING_FLAG 0xFFFFFFFF
+#define VFE_PONG_FLAG 0x0
+
+int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
+	struct timeval *tv)
+{
+	int i, rc = -1;
+	struct msm_isp_buffer *buf;
+	struct msm_isp_event_data buf_event;
+	uint32_t pingpong_bit = 0;
+	uint32_t bufq_handle = stream_info->bufq_handle;
+
+	pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1);
+	rc = vfe_dev->buf_mgr->ops->get_buf(
+		vfe_dev->buf_mgr, bufq_handle, &buf);
+	if (rc < 0) {
+		if (stream_info->stream_type == BURST_STREAM &&
+				stream_info->burst_frame_count <= 1) {
+			rc = 0;
+			if (pingpong_bit)
+				buf = stream_info->buf[0];
+			else
+				buf = stream_info->buf[1];
+		} else {
+			pr_err("%s: No free buffer, stream_type = %d, burst_cnt = %d\n",
+				__func__, stream_info->stream_type,
+				stream_info->burst_frame_count);
+			return rc;
+		}
+	}
+
+	if (buf->num_planes != stream_info->num_planes) {
+		pr_err("%s: Invalid buffer\n", __func__);
+		rc = -EINVAL;
+		goto buf_error;
+	}
+	for (i = 0; i < stream_info->num_planes; i++) {
+		if (pingpong_bit !=
+			(~(pingpong_status >> stream_info->wm[i]) & 0x1)) {
+			pr_warn("%s: Write master ping pong mismatch. Status: 0x%x\n",
+				__func__, pingpong_status);
+		}
+	}
+	for (i = 0; i < stream_info->num_planes; i++)
+		vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
+		vfe_dev, stream_info->wm[i],
+		pingpong_status, buf->mapped_info[i].paddr);
+
+	if (stream_info->buf[pingpong_bit]) {
+		if (stream_info->buf_divert) {
+			buf_event.frame_id = stream_info->frame_id;
+			buf_event.timestamp = *tv;
+			buf_event.u.buf_done.session_id =
+				stream_info->session_id;
+			buf_event.u.buf_done.stream_id =
+				stream_info->stream_id;
+			buf_event.u.buf_done.handle =
+				stream_info->bufq_handle;
+			buf_event.u.buf_done.buf_idx =
+			stream_info->buf[pingpong_bit]->buf_idx;
+			msm_isp_send_event(
+				vfe_dev, ISP_EVENT_BUF_DIVERT, &buf_event);
+		} else {
+			vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
+				stream_info->buf[pingpong_bit]->bufq_handle,
+				stream_info->buf[pingpong_bit]->buf_idx,
+				tv, stream_info->frame_id);
+		}
+	}
+
+	stream_info->buf[pingpong_bit] = buf;
+	return 0;
+buf_error:
+	vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
+		buf->bufq_handle, buf->buf_idx);
+	return rc;
+}
+
+enum msm_isp_camif_update_state
+	msm_isp_update_camif_output_count(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd)
+{
+	int i;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	uint8_t cur_pix_count = axi_data->src_info[VFE_PIX_0].
+		pix_stream_count;
+	uint8_t cur_raw_count = axi_data->src_info[VFE_PIX_0].
+		raw_stream_count;
+	uint8_t pix_stream_cnt = 0;
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		stream_info =
+			&axi_data->stream_info[
+			(stream_cfg_cmd->stream_handle[i] & 0xFF)];
+		if (stream_info->stream_src  != RDI)
+			pix_stream_cnt++;
+		if (stream_info->stream_src == PIX_ENCODER ||
+				stream_info->stream_src == PIX_VIEWFINDER) {
+			if (stream_cfg_cmd->cmd == START_STREAM)
+				vfe_dev->axi_data.src_info[VFE_PIX_0].
+					pix_stream_count++;
+			else
+				vfe_dev->axi_data.src_info[VFE_PIX_0].
+					pix_stream_count--;
+		} else if (stream_info->stream_src == CAMIF_RAW ||
+				stream_info->stream_src == IDEAL_RAW) {
+			if (stream_cfg_cmd->cmd == START_STREAM)
+				vfe_dev->axi_data.src_info[VFE_PIX_0].
+					raw_stream_count++;
+			else
+				vfe_dev->axi_data.src_info[VFE_PIX_0].
+					raw_stream_count--;
+		}
+	}
+	if (pix_stream_cnt) {
+		if ((cur_pix_count + cur_raw_count == 0) &&
+				(axi_data->src_info[VFE_PIX_0].
+				pix_stream_count +
+				axi_data->src_info[VFE_PIX_0].
+					raw_stream_count != 0)) {
+			return ENABLE_CAMIF;
+		}
+
+		if ((cur_pix_count + cur_raw_count != 0) &&
+				(axi_data->src_info[VFE_PIX_0].
+				pix_stream_count +
+				axi_data->src_info[VFE_PIX_0].
+					raw_stream_count == 0)) {
+			return DISABLE_CAMIF;
+		}
+	}
+
+	return NO_UPDATE;
+}
+
+void msm_camera_io_dump_2(void __iomem *addr, int size)
+{
+	char line_str[128], *p_str;
+	int i;
+	u32 *p = (u32 *) addr;
+	u32 data;
+	ISP_DBG("%s: %p %d\n", __func__, addr, size);
+	line_str[0] = '\0';
+	p_str = line_str;
+	for (i = 0; i < size/4; i++) {
+		if (i % 4 == 0) {
+			snprintf(p_str, 12, "%08x: ", (u32) p);
+			p_str += 10;
+		}
+		data = readl_relaxed(p++);
+		snprintf(p_str, 12, "%08x ", data);
+		p_str += 9;
+		if ((i + 1) % 4 == 0) {
+			ISP_DBG("%s\n", line_str);
+			line_str[0] = '\0';
+			p_str = line_str;
+		}
+	}
+	if (line_str[0] != '\0')
+		ISP_DBG("%s\n", line_str);
+}
+
+int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0, i;
+	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
+	uint32_t wm_reload_mask = 0x0, reg_update_mask = 0x1;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	uint8_t src_state;
+	enum msm_isp_camif_update_state camif_update;
+	uint8_t wait_for_complete = 0;
+	rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
+	if (rc < 0) {
+		pr_err("%s: Invalid stream state\n", __func__);
+		return rc;
+	}
+
+	if (axi_data->num_active_stream == 0) {
+		/*Configure UB*/
+		vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
+	}
+
+	camif_update =
+		msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
+
+	if (camif_update == DISABLE_CAMIF)
+		vfe_dev->hw_info->vfe_ops.core_ops.
+			update_camif_state(vfe_dev, DISABLE_CAMIF_IMMEDIATELY);
+
+	/*
+	* Stream start either immediately or at reg update
+	* Depends on whether the stream src is active
+	* If source is on, start and stop have to be done during reg update
+	* If source is off, start can happen immediately or during reg update
+	* stop has to be done immediately.
+	*/
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		stream_info =
+			&axi_data->stream_info[
+				(stream_cfg_cmd->stream_handle[i] & 0xFF)];
+
+
+		if (stream_info->stream_src == RDI)
+			src_state =
+				axi_data->src_info[
+					stream_info->rdi[0]+1].active;
+		else
+			src_state = axi_data->src_info[0].active;
+
+		stream_info->state = (stream_cfg_cmd->cmd == START_STREAM) ?
+			START_PENDING : STOP_PENDING;
+
+		if (stream_cfg_cmd->cmd == START_STREAM) {
+			/*Set address for both PING & PONG register */
+			rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+				stream_info, VFE_PING_FLAG, NULL);
+			rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+				stream_info, VFE_PONG_FLAG, NULL);
+		}
+		if (src_state && camif_update != DISABLE_CAMIF) {
+			/*On the fly stream start/stop */
+			wait_for_complete = 1;
+			reg_update_mask = 0xF; /*TD: Maybe set this per src*/
+		} else {
+			if (vfe_dev->dump_reg)
+				msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);
+			/*Configure AXI start bits to start immediately*/
+			msm_isp_axi_stream_enable_cfg(
+				vfe_dev, stream_info,
+				&wm_reload_mask, &reg_update_mask);
+		}
+	}
+	if (!wait_for_complete) {
+		/*Reload AXI*/
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+			reload_wm(vfe_dev, wm_reload_mask);
+		/*Reg update per src*/
+		vfe_dev->hw_info->vfe_ops.core_ops.
+			reg_update(vfe_dev, reg_update_mask);
+
+		if (camif_update == ENABLE_CAMIF)
+			vfe_dev->hw_info->vfe_ops.core_ops.
+				update_camif_state(vfe_dev, camif_update);
+	} else {
+		unsigned long flags;
+		spin_lock_irqsave(&vfe_dev->shared_data_lock, flags);
+		init_completion(&vfe_dev->stream_config_complete);
+		axi_data->stream_update = 1;
+		spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
+		/*Reload AXI*/
+		vfe_dev->hw_info->vfe_ops.axi_ops.
+			reload_wm(vfe_dev, wm_reload_mask);
+		/*Reg update per src*/
+		vfe_dev->hw_info->vfe_ops.core_ops.
+			reg_update(vfe_dev, reg_update_mask);
+		rc = wait_for_completion_interruptible_timeout(
+			&vfe_dev->stream_config_complete,
+			msecs_to_jiffies(500));
+		if (rc == 0) {
+			pr_err("%s: wait timeout\n", __func__);
+			rc = -1;
+		}
+	}
+	return rc;
+}
+
+void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1,
+	struct timeval *tv)
+{
+	int i;
+	uint32_t comp_mask = 0, wm_mask = 0;
+	uint32_t pingpong_status, stream_idx;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_composite_info *comp_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+
+	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
+	comp_mask = vfe_dev->hw_info->vfe_ops.axi_ops.
+		get_comp_mask(irq_status0, irq_status1);
+	wm_mask = vfe_dev->hw_info->vfe_ops.axi_ops.
+		get_wm_mask(irq_status0, irq_status1);
+	if (!(comp_mask || wm_mask))
+		return;
+
+	pingpong_status =
+		vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status(vfe_dev);
+
+	for (i = 0; i < axi_data->hw_info->num_comp_mask; i++) {
+		comp_info = &axi_data->composite_info[i];
+		if (comp_mask & (1 << i)) {
+			if (!comp_info->stream_handle) {
+				pr_err("%s: Invalid handle for composite irq\n",
+					__func__);
+			} else {
+				stream_idx = comp_info->stream_handle & 0xFF;
+				stream_info =
+					&axi_data->stream_info[stream_idx];
+				ISP_DBG("%s: stream%d frame id: 0x%x\n",
+					__func__,
+					stream_idx, stream_info->frame_id);
+				stream_info->frame_id++;
+				msm_isp_cfg_ping_pong_address(vfe_dev,
+					stream_info, pingpong_status, tv);
+			}
+		}
+		wm_mask &= ~(comp_info->stream_composite_mask);
+	}
+
+	for (i = 0; i < axi_data->hw_info->num_wm; i++) {
+		if (wm_mask & (1 << i)) {
+			if (!axi_data->free_wm[i]) {
+				pr_err("%s: Invalid handle for wm irq\n",
+					__func__);
+				continue;
+			}
+			stream_idx = axi_data->free_wm[i] & 0xFF;
+			stream_info = &axi_data->stream_info[stream_idx];
+			stream_info->frame_id++;
+			msm_isp_cfg_ping_pong_address(vfe_dev,
+			stream_info, pingpong_status, tv);
+		}
+	}
+	return;
+}
diff --git a/drivers/media/video/msmb/isp/msm_isp_axi_util.h b/drivers/media/video/msmb/isp/msm_isp_axi_util.h
new file mode 100644
index 0000000..4847c06
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp_axi_util.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MSM_ISP_AXI_UTIL_H__
+#define __MSM_ISP_AXI_UTIL_H__
+
+#include "msm_isp.h"
+
+int msm_isp_axi_create_stream(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+
+void msm_isp_axi_destroy_stream(
+	struct msm_vfe_axi_shared_data *axi_data, int stream_idx);
+
+int msm_isp_validate_axi_request(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+
+void msm_isp_axi_reserve_wm(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+
+void msm_isp_axi_reserve_rdi(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+
+void msm_isp_axi_reserve_comp_mask(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+
+int msm_isp_axi_check_stream_state(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd);
+
+int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg);
+
+void msm_isp_axi_stream_enable_cfg(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info,
+	uint32_t *wm_reload_mask, uint32_t *reg_update_mask);
+
+void msm_isp_axi_stream_update(struct vfe_device *vfe_dev);
+
+int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
+	struct timeval *tv);
+
+void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev);
+void msm_isp_update_framedrop_count(struct vfe_device *vfe_dev);
+void msm_isp_new_frame_notify(struct vfe_device *vfe_dev,
+	enum msm_vfe_input_src frame_src);
+void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1,
+	struct timeval *tv);
+#endif /* __MSM_ISP_AXI_UTIL_H__ */
diff --git a/drivers/media/video/msmb/isp/msm_isp_stats_util.c b/drivers/media/video/msmb/isp/msm_isp_stats_util.c
new file mode 100644
index 0000000..15f4c23
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp_stats_util.c
@@ -0,0 +1,69 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+#include "msm_isp_util.h"
+#include "msm_isp_stats_util.h"
+
+void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1,
+	struct timeval *tv)
+{
+	uint32_t frame_id;
+	uint32_t stats_comp_mask = 0, stats_mask = 0;
+	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
+	stats_comp_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
+	get_comp_mask(irq_status0, irq_status1);
+	stats_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
+		get_wm_mask(irq_status0, irq_status1);
+	if (!(stats_comp_mask || stats_mask))
+		return;
+	frame_id = vfe_dev->hw_info->vfe_ops.stats_ops.get_frame_id(vfe_dev);
+	/* TD: process comp/non comp stats */
+}
+
+int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0;
+	/*To Do*/
+	return rc;
+}
+
+int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0;
+	struct msm_vfe_stats_stream_release_cmd *stream_release_cmd = arg;
+	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
+	struct msm_vfe_stats_stream *stream_info =
+		&stats_data->stream_info[
+			(stream_release_cmd->stream_handle & 0xFF)];
+
+	if (stream_info == NULL)
+		rc = -1;
+	return rc;
+}
+
+int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0;
+	uint32_t stats_mask = 0;
+	uint8_t enable = 0;
+	uint32_t pingpong_status = 0;
+	struct msm_isp_buffer *buf = NULL;
+	enum msm_isp_stats_type stats_type = MSM_ISP_STATS_BE;
+	vfe_dev->hw_info->vfe_ops.stats_ops.
+	stats_enable(vfe_dev, stats_mask, enable);
+	vfe_dev->hw_info->vfe_ops.stats_ops.
+	update_ping_pong_addr(vfe_dev, stats_type,
+		pingpong_status, buf->mapped_info[0].paddr);
+	return rc;
+}
diff --git a/drivers/media/video/msmb/isp/msm_isp_stats_util.h b/drivers/media/video/msmb/isp/msm_isp_stats_util.h
new file mode 100644
index 0000000..4feb653
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp_stats_util.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MSM_ISP_STATS_UTIL_H__
+#define __MSM_ISP_STATS_UTIL_H__
+
+#include "msm_isp.h"
+
+void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
+	uint32_t irq_status0, uint32_t irq_status1,
+	struct timeval *tv);
+int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg);
+#endif /* __MSM_ISP_STATS_UTIL_H__ */
diff --git a/drivers/media/video/msmb/isp/msm_isp_util.c b/drivers/media/video/msmb/isp/msm_isp_util.c
new file mode 100644
index 0000000..ee3e50e
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp_util.c
@@ -0,0 +1,462 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+#include "msm.h"
+#include "msm_isp_util.h"
+#include "msm_isp_axi_util.h"
+#include "msm_isp_stats_util.h"
+#include "msm_camera_io_util.h"
+
+#define MAX_ISP_V4l2_EVENTS 100
+
+void msm_isp_gettimeofday(struct timeval *tv)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_usec = ts.tv_nsec/1000;
+}
+
+int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub)
+{
+	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
+	int rc = 0;
+	rc = v4l2_event_subscribe(fh, sub, MAX_ISP_V4l2_EVENTS);
+	if (rc == 0) {
+		if (sub->type == V4L2_EVENT_ALL) {
+			int i;
+
+			vfe_dev->axi_data.event_mask = 0;
+			for (i = 0; i < ISP_EVENT_MAX; i++)
+				vfe_dev->axi_data.event_mask |= (1 << i);
+		} else {
+			int event_idx = sub->type - ISP_EVENT_BASE;
+
+			vfe_dev->axi_data.event_mask |= (1 << event_idx);
+		}
+	}
+	return rc;
+}
+
+int msm_isp_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub)
+{
+	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
+	int rc = 0;
+
+	rc = v4l2_event_unsubscribe(fh, sub);
+	if (sub->type == V4L2_EVENT_ALL) {
+		vfe_dev->axi_data.event_mask = 0;
+	} else {
+		int event_idx = sub->type - ISP_EVENT_BASE;
+
+		vfe_dev->axi_data.event_mask &= ~(1 << event_idx);
+	}
+	return rc;
+}
+
+int msm_isp_cfg_pix(struct vfe_device *vfe_dev,
+	struct msm_vfe_pix_cfg *pix_cfg)
+{
+	int rc = 0;
+	/*TD Validate config info
+	 * should check if all streams are off */
+
+	vfe_dev->axi_data.src_info[VFE_PIX_0].input_mux = pix_cfg->input_mux;
+
+	vfe_dev->hw_info->vfe_ops.core_ops.cfg_camif(vfe_dev, pix_cfg);
+	return rc;
+}
+
+int msm_isp_cfg_input(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0;
+	struct msm_vfe_input_cfg *input_cfg = arg;
+
+	switch (input_cfg->input_src) {
+	case VFE_PIX_0:
+		msm_isp_cfg_pix(vfe_dev, &input_cfg->d.pix_cfg);
+		break;
+	case VFE_RAW_0:
+	case VFE_RAW_1:
+	case VFE_RAW_2:
+	case VFE_SRC_MAX:
+		break;
+	}
+	return rc;
+}
+
+long msm_isp_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
+
+	mutex_lock(&vfe_dev->mutex);
+	ISP_DBG("%s cmd: %d\n", __func__, cmd);
+
+	switch (cmd) {
+	case VIDIOC_MSM_VFE_REG_CFG: {
+		msm_isp_proc_cmd(vfe_dev, arg);
+		break;
+	}
+	case VIDIOC_MSM_ISP_REQUEST_BUF:
+	case VIDIOC_MSM_ISP_ENQUEUE_BUF:
+	case VIDIOC_MSM_ISP_RELEASE_BUF: {
+		msm_isp_proc_buf_cmd(vfe_dev->buf_mgr, cmd, arg);
+		break;
+	}
+	case VIDIOC_MSM_ISP_REQUEST_STREAM:
+		msm_isp_request_axi_stream(vfe_dev, arg);
+		break;
+	case VIDIOC_MSM_ISP_RELEASE_STREAM:
+		msm_isp_release_axi_stream(vfe_dev, arg);
+		break;
+	case VIDIOC_MSM_ISP_CFG_STREAM:
+		msm_isp_cfg_axi_stream(vfe_dev, arg);
+		break;
+	case VIDIOC_MSM_ISP_INPUT_CFG:
+		msm_isp_cfg_input(vfe_dev, arg);
+		break;
+	case VIDIOC_MSM_ISP_SET_SRC_STATE:
+		msm_isp_set_src_state(vfe_dev, arg);
+		break;
+	case VIDIOC_MSM_ISP_REQUEST_STATS_STREAM:
+		msm_isp_request_stats_stream(vfe_dev, arg);
+		break;
+	case VIDIOC_MSM_ISP_RELEASE_STATS_STREAM:
+		msm_isp_release_stats_stream(vfe_dev, arg);
+		break;
+	case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
+		msm_isp_cfg_stats_stream(vfe_dev, arg);
+		break;
+	}
+
+	mutex_unlock(&vfe_dev->mutex);
+	return 0;
+}
+
+static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
+	struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd, uint32_t *cfg_data)
+{
+	switch (reg_cfg_cmd->cmd_type) {
+	case VFE_WRITE: {
+		if (resource_size(vfe_dev->vfe_mem) <
+				(reg_cfg_cmd->reg_offset + reg_cfg_cmd->len)) {
+			pr_err("%s: Invalid length\n", __func__);
+			return -EINVAL;
+		}
+		msm_camera_io_memcpy(vfe_dev->vfe_base +
+			reg_cfg_cmd->reg_offset,
+		cfg_data + reg_cfg_cmd->cmd_data/4, reg_cfg_cmd->len);
+		break;
+	}
+	case VFE_WRITE_MB: {
+		uint32_t *data_ptr = cfg_data + reg_cfg_cmd->cmd_data/4;
+		msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base +
+			reg_cfg_cmd->reg_offset);
+		break;
+	}
+	case VFE_WRITE_MASK: {
+		uint32_t temp;
+		temp = msm_camera_io_r(vfe_dev->vfe_base +
+			reg_cfg_cmd->reg_offset);
+		temp |= reg_cfg_cmd->cmd_data;
+		msm_camera_io_w(temp, vfe_dev->vfe_base +
+			reg_cfg_cmd->reg_offset);
+		break;
+	}
+	case VFE_CLEAR_MASK: {
+		uint32_t temp;
+		temp = msm_camera_io_r(vfe_dev->vfe_base +
+			reg_cfg_cmd->reg_offset);
+		temp &= ~reg_cfg_cmd->cmd_data;
+		msm_camera_io_w(temp, vfe_dev->vfe_base +
+			reg_cfg_cmd->reg_offset);
+		break;
+	}
+	case VFE_WRITE_AUTO_INCREMENT: {
+		int i;
+		uint32_t *data_ptr = cfg_data + reg_cfg_cmd->cmd_data/4;
+		for (i = 0; i < reg_cfg_cmd->len/4; i++)
+			msm_camera_io_w(*data_ptr++,
+				vfe_dev->vfe_base + reg_cfg_cmd->reg_offset);
+		break;
+	}
+	case VFE_READ: {
+		int i;
+		uint32_t *data_ptr = cfg_data + reg_cfg_cmd->cmd_data/4;
+		for (i = 0; i < reg_cfg_cmd->len/4; i++)
+			*data_ptr++ = msm_camera_io_r(
+				vfe_dev->vfe_base + reg_cfg_cmd->reg_offset++);
+		break;
+	}
+	}
+	return 0;
+}
+
+int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0, i;
+	struct msm_vfe_cfg_cmd2 *proc_cmd = arg;
+	struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd;
+	uint32_t *cfg_data;
+
+	reg_cfg_cmd = kzalloc(sizeof(struct msm_vfe_reg_cfg_cmd)*
+		proc_cmd->num_cfg, GFP_KERNEL);
+	if (!reg_cfg_cmd) {
+		pr_err("%s: reg_cfg alloc failed\n", __func__);
+		rc = -ENOMEM;
+		goto reg_cfg_failed;
+	}
+
+	cfg_data = kzalloc(proc_cmd->cmd_len, GFP_KERNEL);
+	if (!cfg_data) {
+		pr_err("%s: cfg_data alloc failed\n", __func__);
+		rc = -ENOMEM;
+		goto cfg_data_failed;
+	}
+
+	if (copy_from_user(reg_cfg_cmd,
+		(void __user *)(proc_cmd->cfg_cmd),
+		sizeof(struct msm_vfe_reg_cfg_cmd) * proc_cmd->num_cfg)) {
+		rc = -EFAULT;
+		goto copy_cmd_failed;
+	}
+
+	if (copy_from_user(cfg_data,
+			(void __user *)(proc_cmd->cfg_data),
+			proc_cmd->cmd_len)) {
+		rc = -EFAULT;
+		goto copy_cmd_failed;
+	}
+
+	for (i = 0; i < proc_cmd->num_cfg; i++)
+		msm_isp_send_hw_cmd(vfe_dev, &reg_cfg_cmd[i], cfg_data);
+
+	if (copy_to_user(proc_cmd->cfg_data,
+			cfg_data, proc_cmd->cmd_len)) {
+		rc = -EFAULT;
+		goto copy_cmd_failed;
+	}
+
+copy_cmd_failed:
+	kfree(cfg_data);
+cfg_data_failed:
+	kfree(reg_cfg_cmd);
+reg_cfg_failed:
+	return rc;
+}
+
+int msm_isp_send_event(struct vfe_device *vfe_dev,
+	uint32_t event_type,
+	struct msm_isp_event_data *event_data)
+{
+	struct v4l2_event isp_event;
+	memset(&isp_event, 0, sizeof(struct v4l2_event));
+	isp_event.id = 0;
+	isp_event.type = event_type;
+	memcpy(&isp_event.u.data[0], event_data,
+		sizeof(struct msm_isp_event_data));
+	v4l2_event_queue(vfe_dev->subdev.sd.devnode, &isp_event);
+	return 0;
+}
+
+#define CAL_WORD(width, M, N) ((width * M + N - 1) / N)
+
+int msm_isp_cal_word_per_line(uint32_t output_format,
+	uint32_t pixel_per_line)
+{
+	int val = -1;
+	switch (output_format) {
+	case V4L2_PIX_FMT_SBGGR8:
+	case V4L2_PIX_FMT_SGBRG8:
+	case V4L2_PIX_FMT_SGRBG8:
+	case V4L2_PIX_FMT_SRGGB8:
+		val = CAL_WORD(pixel_per_line, 1, 8);
+		break;
+	case V4L2_PIX_FMT_SBGGR10:
+	case V4L2_PIX_FMT_SGBRG10:
+	case V4L2_PIX_FMT_SGRBG10:
+	case V4L2_PIX_FMT_SRGGB10:
+		val = CAL_WORD(pixel_per_line, 1, 6);
+		break;
+	case V4L2_PIX_FMT_SBGGR12:
+	case V4L2_PIX_FMT_SGBRG12:
+	case V4L2_PIX_FMT_SGRBG12:
+	case V4L2_PIX_FMT_SRGGB12:
+		val = CAL_WORD(pixel_per_line, 1, 5);
+		break;
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		val = CAL_WORD(pixel_per_line, 1, 8);
+		break;
+		/*TD: Add more image format*/
+	default:
+		pr_err("%s: Invalid output format\n", __func__);
+		break;
+	}
+	return val;
+}
+
+irqreturn_t msm_isp_process_irq(int irq_num, void *data)
+{
+	unsigned long flags;
+	struct msm_vfe_tasklet_queue_cmd *queue_cmd;
+	struct vfe_device *vfe_dev = (struct vfe_device *) data;
+	uint32_t irq_status0, irq_status1;
+
+	vfe_dev->hw_info->vfe_ops.irq_ops.
+		read_irq_status(vfe_dev, &irq_status0, &irq_status1);
+	if ((irq_status0 == 0) && (irq_status1 == 0)) {
+		ISP_DBG("%s: irq_status0 & 1 are both 0!\n", __func__);
+		return IRQ_HANDLED;
+	}
+
+	spin_lock_irqsave(&vfe_dev->tasklet_lock, flags);
+	queue_cmd = &vfe_dev->tasklet_queue_cmd[vfe_dev->taskletq_idx];
+	if (queue_cmd->cmd_used) {
+		pr_err("%s: Tasklet queue overflow\n", __func__);
+		list_del(&queue_cmd->list);
+	} else {
+		atomic_add(1, &vfe_dev->irq_cnt);
+	}
+	queue_cmd->vfeInterruptStatus0 = irq_status0;
+	queue_cmd->vfeInterruptStatus1 = irq_status1;
+	msm_isp_gettimeofday(&queue_cmd->tv);
+	queue_cmd->cmd_used = 1;
+	vfe_dev->taskletq_idx =
+		(vfe_dev->taskletq_idx + 1) % MSM_VFE_TASKLETQ_SIZE;
+	list_add_tail(&queue_cmd->list, &vfe_dev->tasklet_q);
+	spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+	tasklet_schedule(&vfe_dev->vfe_tasklet);
+	return IRQ_HANDLED;
+}
+
+void msm_isp_do_tasklet(unsigned long data)
+{
+	unsigned long flags;
+	struct vfe_device *vfe_dev = (struct vfe_device *) data;
+	struct msm_vfe_irq_ops *irq_ops = &vfe_dev->hw_info->vfe_ops.irq_ops;
+	struct msm_vfe_tasklet_queue_cmd *queue_cmd;
+	struct timeval tv;
+	uint32_t irq_status0, irq_status1;
+	while (atomic_read(&vfe_dev->irq_cnt)) {
+		spin_lock_irqsave(&vfe_dev->tasklet_lock, flags);
+		queue_cmd = list_first_entry(&vfe_dev->tasklet_q,
+		struct msm_vfe_tasklet_queue_cmd, list);
+		if (!queue_cmd) {
+			atomic_set(&vfe_dev->irq_cnt, 0);
+			spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+			return;
+		}
+		atomic_sub(1, &vfe_dev->irq_cnt);
+		list_del(&queue_cmd->list);
+		queue_cmd->cmd_used = 0;
+		irq_status0 = queue_cmd->vfeInterruptStatus0;
+		irq_status1 = queue_cmd->vfeInterruptStatus1;
+		tv = queue_cmd->tv;
+		spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
+		ISP_DBG("%s: status0: 0x%x status1: 0x%x\n",
+			__func__, irq_status0, irq_status1);
+		irq_ops->process_reset_irq(vfe_dev,
+			irq_status0, irq_status1);
+		irq_ops->process_halt_irq(vfe_dev,
+			irq_status0, irq_status1);
+		irq_ops->process_camif_irq(vfe_dev,
+			irq_status0, irq_status1);
+		irq_ops->process_error_irq(vfe_dev,
+			irq_status0, irq_status1);
+		irq_ops->process_axi_irq(vfe_dev,
+			irq_status0, irq_status1, &tv);
+		irq_ops->process_stats_irq(vfe_dev,
+			irq_status0, irq_status1, &tv);
+		irq_ops->process_reg_update(vfe_dev, irq_status0, irq_status1);
+	}
+}
+
+void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg)
+{
+	struct msm_vfe_axi_src_state *src_state = arg;
+	vfe_dev->axi_data.src_info[src_state->input_src].active =
+	src_state->src_active;
+}
+
+int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
+	long rc;
+	ISP_DBG("%s\n", __func__);
+
+	mutex_lock(&vfe_dev->mutex);
+	if (vfe_dev->vfe_open_cnt == 1) {
+		pr_err("VFE already open\n");
+		mutex_unlock(&vfe_dev->mutex);
+		return -ENODEV;
+	}
+
+	if (vfe_dev->hw_info->vfe_ops.core_ops.init_hw(vfe_dev) < 0) {
+		pr_err("%s: init hardware failed\n", __func__);
+		mutex_unlock(&vfe_dev->mutex);
+		return -EBUSY;
+	}
+
+	rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
+	if (rc <= 0) {
+		pr_err("%s: reset timeout\n", __func__);
+		mutex_unlock(&vfe_dev->mutex);
+		return -EINVAL;
+	}
+	vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
+
+	vfe_dev->buf_mgr->ops->attach_ctx(vfe_dev->buf_mgr, vfe_dev->iommu_ctx);
+	vfe_dev->buf_mgr->ops->buf_mgr_init(vfe_dev->buf_mgr, "msm_isp", 14);
+
+	memset(&vfe_dev->axi_data, 0, sizeof(struct msm_vfe_axi_shared_data));
+	vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
+
+	ISP_DBG("%s: HW Version: 0x%x\n",
+		__func__, msm_camera_io_r(vfe_dev->vfe_base));
+
+	vfe_dev->vfe_open_cnt++;
+	vfe_dev->taskletq_idx = 0;
+	mutex_unlock(&vfe_dev->mutex);
+	return 0;
+}
+
+int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	long rc;
+	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
+	ISP_DBG("%s\n", __func__);
+	mutex_lock(&vfe_dev->mutex);
+	if (vfe_dev->vfe_open_cnt == 0) {
+		pr_err("%s: Invalid close\n", __func__);
+		mutex_unlock(&vfe_dev->mutex);
+		return -ENODEV;
+	}
+
+	rc = vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
+	if (rc <= 0)
+		pr_err("%s: halt timeout\n", __func__);
+
+	vfe_dev->buf_mgr->ops->buf_mgr_deinit(vfe_dev->buf_mgr);
+	vfe_dev->buf_mgr->ops->detach_ctx(vfe_dev->buf_mgr, vfe_dev->iommu_ctx);
+	vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
+
+	vfe_dev->vfe_open_cnt--;
+	mutex_unlock(&vfe_dev->mutex);
+	return 0;
+}
diff --git a/drivers/media/video/msmb/isp/msm_isp_util.h b/drivers/media/video/msmb/isp/msm_isp_util.h
new file mode 100644
index 0000000..729c8b5
--- /dev/null
+++ b/drivers/media/video/msmb/isp/msm_isp_util.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MSM_ISP_UTIL_H__
+#define __MSM_ISP_UTIL_H__
+
+#include "msm_isp.h"
+
+/* #define CONFIG_MSM_ISP_DBG 1 */
+
+#ifdef CONFIG_MSM_ISP_DBG
+#define ISP_DBG(fmt, args...) printk(fmt, ##args)
+#else
+#define ISP_DBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+void msm_isp_gettimeofday(struct timeval *tv);
+
+int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub);
+
+int msm_isp_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub);
+
+int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_send_event(struct vfe_device *vfe_dev,
+	uint32_t type, struct msm_isp_event_data *event_data);
+int msm_isp_cal_word_per_line(uint32_t output_format,
+	uint32_t pixel_per_line);
+irqreturn_t msm_isp_process_irq(int irq_num, void *data);
+void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
+void msm_isp_do_tasklet(unsigned long data);
+
+int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
+int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
+long msm_isp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
+#endif /* __MSM_ISP_UTIL_H__ */
diff --git a/drivers/media/video/msmb/ispif/Makefile b/drivers/media/video/msmb/ispif/Makefile
new file mode 100644
index 0000000..908cc28
--- /dev/null
+++ b/drivers/media/video/msmb/ispif/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/video/msmb
+ccflags-y += -Idrivers/media/video/msmb/sensor/io
+obj-$(CONFIG_MSM_CSID) += msm_ispif.o
diff --git a/drivers/media/video/msmb/ispif/msm_ispif.c b/drivers/media/video/msmb/ispif/msm_ispif.c
new file mode 100644
index 0000000..ffb9263
--- /dev/null
+++ b/drivers/media/video/msmb/ispif/msm_ispif.c
@@ -0,0 +1,954 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/videodev2.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include "msm_ispif.h"
+#include "msm.h"
+#include "msm_ispif_hwreg.h"
+#include "msm_sd.h"
+#include "msm_camera_io_util.h"
+
+#define V4L2_IDENT_ISPIF                      50001
+#define MSM_ISPIF_DRV_NAME                    "msm_ispif"
+#define DUMP_BUFF_SIZE_128                    128
+
+#define ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY  0x01
+#define ISPIF_INTF_CMD_DISABLE_FRAME_BOUNDARY 0x00
+#define ISPIF_INTF_CMD_DISABLE_IMMEDIATELY    0x02
+
+#define CONFIG_MSMB_CAMERA_DEBUG
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+static void msm_ispif_io_dump(void __iomem *addr, int size)
+{
+	char line_str[DUMP_BUFF_SIZE_128], *p_str;
+	int i;
+	u32 *p = (u32 *) addr;
+	u32 data;
+
+
+	CDBG("%s: %p %d\n", __func__, addr, size);
+	line_str[0] = '\0';
+	p_str = line_str;
+	for (i = 0; i < size/4; i++) {
+		if (i % 4 == 0) {
+			snprintf(p_str, 12, "%08x: ", (u32) p);
+			p_str += 10;
+		}
+		data = readl_relaxed(p++);
+		snprintf(p_str, 12, "%08x ", data);
+		p_str += 9;
+		if ((i + 1) % 4 == 0) {
+			CDBG("%s\n", line_str);
+			line_str[0] = '\0';
+			p_str = line_str;
+		}
+	}
+	if (line_str[0] != '\0')
+		CDBG("%s\n", line_str);
+}
+
+static void msm_ispif_io_dump_reg(struct ispif_device *ispif)
+{
+	int size;
+
+	if (!ispif->enb_dump_reg)
+		return;
+	size = 0x250;
+	msm_ispif_io_dump(ispif->base+0x100, size);
+}
+
+static int msm_ispif_intf_reset(struct ispif_device *ispif,
+	struct msm_ispif_param_data *params)
+{
+
+	int i, rc = 0;
+	enum msm_ispif_intftype intf_type;
+	uint32_t data = (0x1 << STROBED_RST_EN);
+
+	for (i = 0; i < params->num; i++) {
+		intf_type = params->entries[i].intftype;
+		ispif->sof_count[params->vfe_intf].sof_cnt[intf_type] = 0;
+		switch (intf_type) {
+		case PIX0:
+			data |= (0x1 << PIX_0_VFE_RST_STB) |
+				(0x1 << PIX_0_CSID_RST_STB);
+			break;
+		case RDI0:
+			data |= (0x1 << RDI_0_VFE_RST_STB) |
+				(0x1 << RDI_0_CSID_RST_STB);
+			break;
+		case PIX1:
+			data |= (0x1 << PIX_1_VFE_RST_STB) |
+				(0x1 << PIX_1_CSID_RST_STB);
+			break;
+		case RDI1:
+			data |= (0x1 << RDI_1_VFE_RST_STB) |
+				(0x1 << RDI_1_CSID_RST_STB);
+			break;
+		case RDI2:
+			data |= (0x1 << RDI_2_VFE_RST_STB) |
+				(0x1 << RDI_2_CSID_RST_STB);
+			break;
+		default:
+			rc = -EINVAL;
+			break;
+		}
+	}
+	if (data > 0x1) {
+		unsigned long jiffes = msecs_to_jiffies(500);
+		long lrc = 0;
+		if (params->vfe_intf == VFE0)
+			msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
+		else
+			msm_camera_io_w(data, ispif->base +
+				ISPIF_RST_CMD_1_ADDR);
+		lrc = wait_for_completion_interruptible_timeout(
+			&ispif->reset_complete, jiffes);
+		if (lrc < 0 || !lrc) {
+			pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
+			rc = -EIO;
+		}
+	}
+	return rc;
+}
+
+static int msm_ispif_reset(struct ispif_device *ispif)
+{
+	int rc = 0;
+	unsigned long jiffes = msecs_to_jiffies(500);
+	long lrc = 0;
+
+	memset(ispif->sof_count,  0,  sizeof(ispif->sof_count));
+	msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR);
+	if (ispif->csid_version == CSID_VERSION_V3)
+		msm_camera_io_w_mb(ISPIF_RST_CMD_1_MASK, ispif->base +
+			ISPIF_RST_CMD_1_ADDR);
+	CDBG("%s: Sending reset\n", __func__);
+	lrc = wait_for_completion_interruptible_timeout(
+		&ispif->reset_complete, jiffes);
+	if (lrc < 0 || !lrc) {
+		pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
+		rc = -EIO;
+	}
+	CDBG("%s: reset returned\n", __func__);
+	return rc;
+}
+
+static int msm_ispif_subdev_g_chip_ident(struct v4l2_subdev *sd,
+	struct v4l2_dbg_chip_ident *chip)
+{
+	BUG_ON(!chip);
+	chip->ident = V4L2_IDENT_ISPIF;
+	chip->revision = 0;
+	return 0;
+}
+
+static void msm_ispif_sel_csid_core(struct ispif_device *ispif,
+	uint8_t intftype, uint8_t csid, uint8_t vfe_intf)
+{
+	int rc = 0;
+	uint32_t data = 0;
+
+	if (ispif->csid_version <= CSID_VERSION_V2) {
+		if (ispif->ispif_clk[intftype] == NULL) {
+			CDBG("%s: ispif NULL clk\n", __func__);
+			return;
+		}
+		rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
+		if (rc < 0)
+			pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
+		return;
+	}
+	data = msm_camera_io_r(ispif->base + ISPIF_INPUT_SEL_ADDR +
+		(0x200 * vfe_intf));
+	switch (intftype) {
+	case PIX0:
+		data &= ~(0x3);        /* clear old setting */
+		data |= csid;          /* add new setting */
+		break;
+	case RDI0:
+		data &= ~(0x3 << 4);   /* clear old setting */
+		data |= (csid << 4);   /* add new setting */
+		break;
+	case PIX1:
+		data &= ~(0x3 << 8);   /* clear old setting */
+		data |= (csid << 8);   /* add new setting */
+		break;
+	case RDI1:
+		data &= ~(0x3 << 12);  /* clear old setting */
+		data |= (csid << 12);  /* add new setting */
+		break;
+	case RDI2:
+		data &= ~(0x3 << 20);  /* clear old setting */
+		data |= (csid << 20);  /* add new setting */
+		break;
+	}
+	if (data) {
+		msm_camera_io_w_mb(data, ispif->base + ISPIF_INPUT_SEL_ADDR +
+			(0x200 * vfe_intf));
+	}
+}
+
+static void msm_ispif_enable_intf_cids(struct ispif_device *ispif,
+	uint8_t intftype, uint16_t cid_mask,
+	uint8_t vfe_intf, uint8_t enable)
+{
+	uint32_t data = 0;
+
+	switch (intftype) {
+	case PIX0:
+		data = msm_camera_io_r(ispif->base +
+		ISPIF_PIX_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		if (enable)
+			data |= cid_mask;  /* add new config */
+		else
+			data &= ~cid_mask;  /* remove CID bit */
+		msm_camera_io_w_mb(data, ispif->base +
+		ISPIF_PIX_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		break;
+	case RDI0:
+		data = msm_camera_io_r(ispif->base +
+		ISPIF_RDI_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		if (enable)
+			data |= cid_mask;  /* add new config */
+		else
+			data &= ~cid_mask;  /* remove CID bit */
+		msm_camera_io_w_mb(data, ispif->base +
+			ISPIF_RDI_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		break;
+	case PIX1:
+		data = msm_camera_io_r(ispif->base +
+		ISPIF_PIX_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		if (enable)
+			data |= cid_mask;  /* add new config */
+		else
+			data &= ~cid_mask;  /* remove CID bit */
+		msm_camera_io_w_mb(data, ispif->base +
+			ISPIF_PIX_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		break;
+	case RDI1:
+		data = msm_camera_io_r(ispif->base +
+			ISPIF_RDI_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		if (enable)
+			data |= cid_mask;  /* add new config */
+		else
+			data &= ~cid_mask;  /* remove CID bit */
+		msm_camera_io_w_mb(data, ispif->base +
+			ISPIF_RDI_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		break;
+	case RDI2:
+		data = msm_camera_io_r(ispif->base +
+			ISPIF_RDI_2_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		if (enable)
+			data |= cid_mask;  /* add new config */
+		else
+			data &= ~cid_mask;  /* remove CID bit */
+		msm_camera_io_w_mb(data, ispif->base +
+			ISPIF_RDI_2_INTF_CID_MASK_ADDR + (0x200 * vfe_intf));
+		break;
+	}
+}
+
+static int32_t msm_ispif_validate_intf_status(struct ispif_device *ispif,
+	uint8_t intftype, uint8_t vfe_intf)
+{
+	int32_t rc = 0;
+	uint32_t data = 0;
+	switch (intftype) {
+	case PIX0:
+		data = msm_camera_io_r(ispif->base +
+		ISPIF_PIX_0_STATUS_ADDR + (0x200 * vfe_intf));
+		break;
+	case RDI0:
+		data = msm_camera_io_r(ispif->base +
+		ISPIF_RDI_0_STATUS_ADDR + (0x200 * vfe_intf));
+		break;
+	case PIX1:
+		data = msm_camera_io_r(ispif->base +
+		ISPIF_PIX_1_STATUS_ADDR + (0x200 * vfe_intf));
+		break;
+	case RDI1:
+		data = msm_camera_io_r(ispif->base +
+		ISPIF_RDI_1_STATUS_ADDR + (0x200 * vfe_intf));
+		break;
+	case RDI2:
+		data = msm_camera_io_r(ispif->base +
+		ISPIF_RDI_2_STATUS_ADDR + (0x200 * vfe_intf));
+		break;
+	}
+	if ((data & 0xf) != 0xf)
+		rc = -EBUSY;
+	return rc;
+}
+
+static uint16_t msm_ispif_get_cids_mask_from_cfg(
+	struct msm_ispif_params_entry *entry)
+{
+	int i;
+	uint16_t cids_mask = 0;
+
+	for (i = 0; i < entry->num_cids; i++)
+		cids_mask |= (1 << entry->cids[i]);
+	return cids_mask;
+}
+
+static int msm_ispif_config(struct ispif_device *ispif,
+	struct msm_ispif_param_data *params)
+{
+	int rc = 0, i = 0;
+	enum msm_ispif_intftype intftype;
+	enum msm_ispif_vfe_intf vfe_intf = params->vfe_intf;
+	uint16_t cid_mask;
+
+	msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_ADDR);
+	msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_1_ADDR);
+	msm_camera_io_w_mb(0x00000000, ispif->base + ISPIF_IRQ_MASK_2_ADDR);
+	for (i = 0; i < params->num; i++) {
+		intftype = params->entries[i].intftype;
+		vfe_intf = params->vfe_intf;
+		CDBG("%s intftype %x, vfe_intf %d, csid %d\n", __func__,
+		intftype, vfe_intf, params->entries[i].csid);
+		if ((intftype >= INTF_MAX) ||
+				(ispif->csid_version <= CSID_VERSION_V2 &&
+				vfe_intf > VFE0) ||
+				(ispif->csid_version == CSID_VERSION_V3 &&
+				vfe_intf >= VFE_MAX)) {
+			pr_err("%s: VFEID %d and CSID version %d mismatch\n",
+				__func__, vfe_intf, ispif->csid_version);
+			return -EINVAL;
+		}
+		rc = msm_ispif_validate_intf_status(ispif, intftype, vfe_intf);
+		if (rc < 0) {
+			pr_err("%s:validate_intf_status failed, rc = %d\n",
+				__func__, rc);
+			return rc;
+		}
+		msm_ispif_sel_csid_core(ispif, intftype,
+			params->entries[i].csid, vfe_intf);
+		cid_mask = msm_ispif_get_cids_mask_from_cfg(
+				&params->entries[i]);
+		msm_ispif_enable_intf_cids(ispif, intftype,
+			cid_mask, vfe_intf, 1);
+	}
+
+	msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
+		ISPIF_IRQ_MASK_ADDR);
+
+	msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
+		ISPIF_IRQ_CLEAR_ADDR);
+
+	msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+		ISPIF_IRQ_MASK_1_ADDR);
+
+	msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+		ISPIF_IRQ_CLEAR_1_ADDR);
+
+	msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+		ISPIF_IRQ_MASK_2_ADDR);
+
+	msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+		ISPIF_IRQ_CLEAR_2_ADDR);
+
+	msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
+		ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+	return rc;
+}
+
+static void msm_ispif_intf_cmd(struct ispif_device *ispif,
+	uint32_t cmd_bits,
+	struct msm_ispif_param_data *params)
+{
+	uint8_t vc = 0;
+	int i, k;
+	enum msm_ispif_intftype intf_type;
+	enum msm_ispif_cid cid;
+	enum msm_ispif_vfe_intf vfe_intf = params->vfe_intf;
+
+	for (i = 0; i < params->num; i++) {
+		intf_type = params->entries[i].intftype;
+		for (k = 0; k < params->entries[i].num_cids; k++) {
+			cid = params->entries[i].cids[k];
+			vc = cid % 4;
+			if (intf_type == RDI2) {
+				/* zero out two bits */
+				ispif->applied_intf_cmd[vfe_intf].intf_cmd1 &=
+					~(0x3 << (vc * 2 + 8));
+				ispif->applied_intf_cmd[vfe_intf].intf_cmd1 |=
+				(cmd_bits << (vc * 2 + 8)); /* set cmd bits */
+			} else {
+				/* zero 2 bits */
+				ispif->applied_intf_cmd[vfe_intf].intf_cmd &=
+					~(0x3 << (vc * 2 + vfe_intf * 8));
+				/* set cmd bits */
+				ispif->applied_intf_cmd[vfe_intf].intf_cmd |=
+				(cmd_bits << (vc * 2 + vfe_intf * 8));
+			}
+		}
+	}
+	/* cmd for PIX0, PIX1, RDI0, RDI1 */
+	if (ispif->applied_intf_cmd[vfe_intf].intf_cmd != 0xFFFFFFFF) {
+		msm_camera_io_w_mb(ispif->applied_intf_cmd[vfe_intf].intf_cmd,
+			ispif->base + ISPIF_INTF_CMD_ADDR +
+			(0x200 * vfe_intf));
+	}
+	/* cmd for RDI2 */
+	if (ispif->applied_intf_cmd[vfe_intf].intf_cmd1 != 0xFFFFFFFF)
+		msm_camera_io_w_mb(ispif->applied_intf_cmd[vfe_intf].intf_cmd1,
+			ispif->base + ISPIF_INTF_CMD_1_ADDR +
+			(0x200 * vfe_intf));
+}
+
+static int msm_ispif_stop_immediately(struct ispif_device *ispif,
+	struct msm_ispif_param_data *params)
+{
+	int i, rc = 0;
+	uint16_t cid_mask = 0;
+
+	msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_DISABLE_IMMEDIATELY, params);
+
+	/* after stop the interface we need to unmask the CID enable bits */
+	for (i = 0; i < params->num; i++) {
+		cid_mask = msm_ispif_get_cids_mask_from_cfg(
+			&params->entries[i]);
+		msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
+		cid_mask, params->vfe_intf, 0);
+	}
+	return rc;
+}
+
+static int msm_ispif_start_frame_boundary(struct ispif_device *ispif,
+	struct msm_ispif_param_data *params)
+{
+	int rc = 0;
+
+	rc = msm_ispif_intf_reset(ispif, params);
+	msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY, params);
+	return rc;
+}
+
+static int msm_ispif_stop_frame_boundary(struct ispif_device *ispif,
+	struct msm_ispif_param_data *params)
+{
+	int i, rc = 0;
+	uint16_t cid_mask = 0;
+
+	msm_ispif_intf_cmd(ispif,
+		ISPIF_INTF_CMD_DISABLE_FRAME_BOUNDARY, params);
+	for (i = 0; i < params->num; i++) {
+		cid_mask =
+			msm_ispif_get_cids_mask_from_cfg(
+				&params->entries[i]);
+		switch (params->entries[i].intftype) {
+		case PIX0:
+			while ((msm_camera_io_r(ispif->base +
+				ISPIF_PIX_0_STATUS_ADDR +
+				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
+				CDBG("Wait for pix0 Idle\n");
+			}
+			break;
+		case RDI0:
+			while ((msm_camera_io_r(ispif->base +
+				ISPIF_RDI_0_STATUS_ADDR +
+				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
+				CDBG("Wait for rdi0 Idle\n");
+			}
+			break;
+		case PIX1:
+			while ((msm_camera_io_r(ispif->base +
+				ISPIF_PIX_1_STATUS_ADDR +
+				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
+				CDBG("Wait for pix1 Idle\n");
+			}
+			break;
+		case RDI1:
+			while ((msm_camera_io_r(ispif->base +
+				ISPIF_RDI_1_STATUS_ADDR +
+				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
+				CDBG("Wait for rdi1 Idle\n");
+			}
+			break;
+		case RDI2:
+			while ((msm_camera_io_r(ispif->base +
+				ISPIF_RDI_2_STATUS_ADDR +
+				(0x200 * params->vfe_intf)) & 0xf) != 0xf) {
+				CDBG("Wait for rdi2 Idle\n");
+			}
+			break;
+		default:
+			break;
+		}
+		/* disable CIDs in CID_MASK register */
+		msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
+		cid_mask, params->vfe_intf, 0);
+	}
+	return rc;
+}
+
+static void ispif_process_irq(struct ispif_device *ispif,
+	struct ispif_irq_status *out, enum msm_ispif_vfe_intf vfe_id)
+{
+	if (out[vfe_id].ispifIrqStatus0 &
+			ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
+		ispif->sof_count[vfe_id].sof_cnt[PIX0]++;
+	}
+	if (out[vfe_id].ispifIrqStatus0 &
+			ISPIF_IRQ_STATUS_RDI0_SOF_MASK) {
+		ispif->sof_count[vfe_id].sof_cnt[RDI0]++;
+	}
+	if (out[vfe_id].ispifIrqStatus1 &
+			ISPIF_IRQ_STATUS_RDI1_SOF_MASK) {
+		ispif->sof_count[vfe_id].sof_cnt[RDI1]++;
+	}
+	if (out[vfe_id].ispifIrqStatus2 &
+			ISPIF_IRQ_STATUS_RDI2_SOF_MASK) {
+		ispif->sof_count[vfe_id].sof_cnt[RDI2]++;
+	}
+	return;
+}
+
+static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
+	void *data)
+{
+	struct ispif_device *ispif = (struct ispif_device *)data;
+
+	out[VFE0].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
+		ISPIF_IRQ_STATUS_ADDR);
+	out[VFE0].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
+		ISPIF_IRQ_STATUS_1_ADDR);
+	out[VFE0].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
+		ISPIF_IRQ_STATUS_2_ADDR);
+	msm_camera_io_w(out[VFE0].ispifIrqStatus0,
+		ispif->base + ISPIF_IRQ_CLEAR_ADDR);
+	msm_camera_io_w(out[VFE0].ispifIrqStatus1,
+		ispif->base + ISPIF_IRQ_CLEAR_1_ADDR);
+	msm_camera_io_w_mb(out[VFE0].ispifIrqStatus2,
+		ispif->base + ISPIF_IRQ_CLEAR_2_ADDR);
+
+	if (out[VFE0].ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
+		if (out[VFE0].ispifIrqStatus0 & (0x1 <<
+				RESET_DONE_IRQ))
+			complete(&ispif->reset_complete);
+		if (out[VFE0].ispifIrqStatus0 & (0x1 <<
+				PIX_INTF_0_OVERFLOW_IRQ))
+			pr_err("%s: VFE0 pix0 overflow.\n", __func__);
+		if (out[VFE0].ispifIrqStatus0 & (0x1 <<
+				RAW_INTF_0_OVERFLOW_IRQ))
+			pr_err("%s: VFE0 rdi0 overflow.\n", __func__);
+		if (out[VFE0].ispifIrqStatus1 & (0x1 <<
+				RAW_INTF_1_OVERFLOW_IRQ))
+			pr_err("%s: VFE0 rdi1 overflow.\n", __func__);
+		if (out[VFE0].ispifIrqStatus2 & (0x1 <<
+				RAW_INTF_2_OVERFLOW_IRQ))
+			pr_err("%s: VFE0 rdi2 overflow.\n", __func__);
+		if ((out[VFE0].ispifIrqStatus0 &
+			ISPIF_IRQ_STATUS_SOF_MASK) ||
+				(out[VFE0].ispifIrqStatus1 &
+					ISPIF_IRQ_STATUS_SOF_MASK) ||
+				(out[VFE0].ispifIrqStatus2 &
+					ISPIF_IRQ_STATUS_RDI2_SOF_MASK))
+			ispif_process_irq(ispif, out, VFE0);
+	}
+	if (ispif->csid_version == CSID_VERSION_V3) {
+		out[VFE1].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
+			ISPIF_IRQ_STATUS_ADDR + 0x200);
+		msm_camera_io_w(out[VFE1].ispifIrqStatus0,
+			ispif->base + ISPIF_IRQ_CLEAR_ADDR + 0x200);
+		out[VFE1].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
+			ISPIF_IRQ_STATUS_1_ADDR + 0x200);
+		msm_camera_io_w(out[VFE1].ispifIrqStatus1,
+			ispif->base + ISPIF_IRQ_CLEAR_1_ADDR + 0x200);
+		out[VFE1].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
+			ISPIF_IRQ_STATUS_2_ADDR + 0x200);
+		msm_camera_io_w_mb(out[VFE1].ispifIrqStatus2,
+			ispif->base + ISPIF_IRQ_CLEAR_2_ADDR + 0x200);
+		if (out[VFE1].ispifIrqStatus0 & (0x1 <<
+				PIX_INTF_0_OVERFLOW_IRQ))
+			pr_err("%s: VFE1 pix0 overflow.\n", __func__);
+		if (out[VFE1].ispifIrqStatus0 & (0x1 <<
+				RAW_INTF_0_OVERFLOW_IRQ))
+			pr_err("%s: VFE1 rdi0 overflow.\n", __func__);
+		if (out[VFE1].ispifIrqStatus1 & (0x1 <<
+				RAW_INTF_1_OVERFLOW_IRQ))
+			pr_err("%s: VFE1 rdi1 overflow.\n", __func__);
+		if (out[VFE1].ispifIrqStatus2 & (0x1 <<
+				RAW_INTF_2_OVERFLOW_IRQ))
+			pr_err("%s: VFE1 rdi2 overflow.\n", __func__);
+		if ((out[VFE1].ispifIrqStatus0 & ISPIF_IRQ_STATUS_SOF_MASK) ||
+				(out[VFE1].ispifIrqStatus1 &
+					ISPIF_IRQ_STATUS_SOF_MASK) ||
+				(out[VFE1].ispifIrqStatus2 &
+					ISPIF_IRQ_STATUS_RDI2_SOF_MASK))
+			ispif_process_irq(ispif, out, VFE1);
+	}
+	msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
+		ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+}
+
+static irqreturn_t msm_io_ispif_irq(int irq_num, void *data)
+{
+	struct ispif_irq_status irq[VFE_MAX];
+
+	msm_ispif_read_irq_status(irq, data);
+	return IRQ_HANDLED;
+}
+
+static struct msm_cam_clk_info ispif_8960_clk_info[] = {
+	{"csi_pix_clk", 0},
+	{"csi_rdi_clk", 0},
+	{"csi_pix1_clk", 0},
+	{"csi_rdi1_clk", 0},
+	{"csi_rdi2_clk", 0},
+};
+static struct msm_cam_clk_info ispif_8974_clk_info[] = {
+	{"camss_vfe_vfe_clk", -1},
+	{"camss_csi_vfe_clk", -1},
+	{"camss_vfe_vfe_clk1", -1},
+	{"camss_csi_vfe_clk1", -1},
+};
+
+static int msm_ispif_init(struct ispif_device *ispif,
+	uint32_t csid_version)
+{
+	int rc = 0;
+
+	if (ispif->ispif_state == ISPIF_POWER_UP) {
+		CDBG("%s: ispif already initted state = %d\n", __func__,
+		ispif->ispif_state);
+		rc = -EAGAIN;
+		return rc;
+	}
+
+	/* can we set to zero? */
+	ispif->applied_intf_cmd[VFE0].intf_cmd  = 0xFFFFFFFF;
+	ispif->applied_intf_cmd[VFE0].intf_cmd1 = 0xFFFFFFFF;
+	ispif->applied_intf_cmd[VFE1].intf_cmd  = 0xFFFFFFFF;
+	ispif->applied_intf_cmd[VFE1].intf_cmd1 = 0xFFFFFFFF;
+	memset(ispif->sof_count, 0, sizeof(ispif->sof_count));
+
+	ispif->csid_version = csid_version;
+	if (ispif->csid_version < CSID_VERSION_V2) {
+		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+			ispif->ispif_clk, 2, 1);
+		if (rc < 0) {
+			pr_err("%s: cannot enable clock, error = %d\n",
+				__func__, rc);
+			goto end;
+		}
+	} else if (ispif->csid_version == CSID_VERSION_V2) {
+		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 1);
+		if (rc < 0) {
+			pr_err("%s: cannot enable clock, error = %d\n",
+				__func__, rc);
+			goto end;
+		}
+	} else {
+		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), 1);
+		if (rc < 0) {
+			pr_err("%s: cannot enable clock, error = %d\n",
+				__func__, rc);
+			goto end;
+		}
+	}
+	ispif->base = ioremap(ispif->mem->start,
+		resource_size(ispif->mem));
+	if (!ispif->base) {
+		rc = -ENOMEM;
+		pr_err("%s: nomem\n", __func__);
+		goto error_clk;
+	}
+	rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
+		IRQF_TRIGGER_RISING, "ispif", ispif);
+	init_completion(&ispif->reset_complete);
+	if (rc < 0) {
+		pr_err("%s: request_irq error = %d\n", __func__, rc);
+		goto error_irq;
+	}
+	rc = msm_ispif_reset(ispif);
+	if (rc == 0) {
+		ispif->ispif_state = ISPIF_POWER_UP;
+		CDBG("%s: power up done\n", __func__);
+		goto end;
+	}
+	free_irq(ispif->irq->start, ispif);
+error_irq:
+	iounmap(ispif->base);
+error_clk:
+	if (ispif->csid_version < CSID_VERSION_V2) {
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+		ispif->ispif_clk, 2, 0);
+	} else if (ispif->csid_version == CSID_VERSION_V2) {
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+		ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
+	}
+end:
+	return rc;
+}
+
+static void msm_ispif_release(struct ispif_device *ispif)
+{
+	if (ispif->ispif_state != ISPIF_POWER_UP) {
+		pr_err("%s: ispif invalid state %d\n", __func__,
+		ispif->ispif_state);
+		return;
+	}
+	/* make sure no streaming going on */
+	msm_ispif_reset(ispif);
+	free_irq(ispif->irq->start, ispif);
+	iounmap(ispif->base);
+	if (ispif->csid_version < CSID_VERSION_V2) {
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+		ispif->ispif_clk, 2, 0);
+	} else if (ispif->csid_version == CSID_VERSION_V2) {
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
+	}
+	ispif->ispif_state = ISPIF_POWER_DOWN;
+}
+
+static int msm_ispif_clk_enable(struct ispif_device *ispif,
+	uint32_t csid_version, int enable)
+{
+	int rc = 0;
+
+	if (csid_version != CSID_VERSION_V3)
+		goto end;
+	rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
+		ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), enable);
+	if (rc < 0)
+		pr_err("%s: cannot enable clock, error = %d\n", __func__, rc);
+end:
+	return rc;
+}
+
+static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
+{
+	long rc = 0;
+	struct ispif_cfg_data *pcdata = (struct ispif_cfg_data *)arg;
+	struct ispif_device *ispif =
+		(struct ispif_device *)v4l2_get_subdevdata(sd);
+	mutex_lock(&ispif->mutex);
+	switch (pcdata->cfg_type) {
+	case ISPIF_CLK_ENABLE:
+		rc = msm_ispif_clk_enable(ispif, pcdata->csid_version, 1);
+		break;
+	case ISPIF_CLK_DISABLE:
+		rc = msm_ispif_clk_enable(ispif, pcdata->csid_version, 0);
+		break;
+	case ISPIF_ENABLE_REG_DUMP:
+		ispif->enb_dump_reg = pcdata->reg_dump; /* save dump config */
+		break;
+	case ISPIF_INIT:
+		/* need to move back to CDBG */
+		rc = msm_ispif_init(ispif, pcdata->csid_version);
+		msm_ispif_io_dump_reg(ispif);
+		break;
+	case ISPIF_CFG:
+		rc = msm_ispif_config(ispif, &pcdata->params);
+		msm_ispif_io_dump_reg(ispif);
+		break;
+	case ISPIF_START_FRAME_BOUNDARY:
+		rc = msm_ispif_start_frame_boundary(ispif, &pcdata->params);
+		msm_ispif_io_dump_reg(ispif);
+		break;
+	case ISPIF_STOP_FRAME_BOUNDARY:
+		rc = msm_ispif_stop_frame_boundary(ispif, &pcdata->params);
+		msm_ispif_io_dump_reg(ispif);
+		break;
+	case ISPIF_STOP_IMMEDIATELY:
+		rc = msm_ispif_stop_immediately(ispif, &pcdata->params);
+		msm_ispif_io_dump_reg(ispif);
+		break;
+	case ISPIF_RELEASE:
+		msm_ispif_release(ispif);
+		break;
+	default:
+		break;
+	}
+	mutex_unlock(&ispif->mutex);
+	return rc;
+}
+
+static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case VIDIOC_MSM_ISPIF_CFG:
+		return msm_ispif_cmd(sd, arg);
+	default:
+		pr_err("%s: invalid cmd received\n", __func__);
+		return -ENOIOCTLCMD;
+	}
+}
+
+static int ispif_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct ispif_device *ispif = v4l2_get_subdevdata(sd);
+	int rc = 0;
+
+	mutex_lock(&ispif->mutex);
+	if (ispif->open_cnt > 0) {
+		CDBG("%s: dev already open\n", __func__);
+		goto end;
+	}
+	/* mem remap is done in init when the clock is on */
+	ispif->open_cnt++;
+end:
+	mutex_unlock(&ispif->mutex);
+	return rc;
+}
+
+static int ispif_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct ispif_device *ispif = v4l2_get_subdevdata(sd);
+	int rc = 0;
+
+	CDBG("%s\n", __func__);
+	mutex_lock(&ispif->mutex);
+	if (ispif->open_cnt == 0) {
+		pr_err("Invalid close\n");
+		rc = -ENODEV;
+		goto end;
+	}
+	ispif->open_cnt--;
+	if (ispif->open_cnt == 0)
+		msm_ispif_release(ispif);
+end:
+	mutex_unlock(&ispif->mutex);
+	return rc;
+}
+
+static struct v4l2_subdev_core_ops msm_ispif_subdev_core_ops = {
+	.g_chip_ident = &msm_ispif_subdev_g_chip_ident,
+	.ioctl = &msm_ispif_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_ispif_subdev_ops = {
+	.core = &msm_ispif_subdev_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops msm_ispif_internal_ops = {
+	.open = ispif_open_node,
+	.close = ispif_close_node,
+};
+static int __devinit ispif_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	struct ispif_device *ispif;
+
+	CDBG("%s\n", __func__);
+	ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
+	if (!ispif) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&ispif->msm_sd.sd, &msm_ispif_subdev_ops);
+	ispif->msm_sd.sd.internal_ops = &msm_ispif_internal_ops;
+	ispif->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	snprintf(ispif->msm_sd.sd.name,
+		ARRAY_SIZE(ispif->msm_sd.sd.name), "msm_ispif");
+	v4l2_set_subdevdata(&ispif->msm_sd.sd, ispif);
+	platform_set_drvdata(pdev, &ispif->msm_sd.sd);
+	mutex_init(&ispif->mutex);
+	ispif->pdev = pdev;
+	media_entity_init(&ispif->msm_sd.sd.entity, 0, NULL, 0);
+	ispif->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	ispif->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ISPIF;
+	ispif->msm_sd.sd.entity.name = pdev->name;
+	rc = msm_sd_register(&ispif->msm_sd);
+	if (rc != 0) {
+		pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
+		goto error;
+	}
+	if (pdev->dev.of_node)
+		of_property_read_u32((&pdev->dev)->of_node,
+		"cell-index", &pdev->id);
+
+	ispif->mem = platform_get_resource_byname(pdev,
+		IORESOURCE_MEM, "ispif");
+	if (!ispif->mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto error;
+	}
+	ispif->irq = platform_get_resource_byname(pdev,
+		IORESOURCE_IRQ, "ispif");
+	if (!ispif->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto error;
+	}
+	ispif->io = request_mem_region(ispif->mem->start,
+		resource_size(ispif->mem), pdev->name);
+	if (!ispif->io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto error;
+	}
+	ispif->pdev = pdev;
+	ispif->ispif_state = ISPIF_POWER_DOWN;
+	ispif->open_cnt = 0;
+	return 0;
+
+error:
+	mutex_destroy(&ispif->mutex);
+	kfree(ispif);
+	return rc;
+}
+
+static const struct of_device_id msm_ispif_dt_match[] = {
+	{.compatible = "qcom,ispif"},
+};
+
+MODULE_DEVICE_TABLE(of, msm_ispif_dt_match);
+
+static struct platform_driver ispif_driver = {
+	.probe = ispif_probe,
+	.driver = {
+		.name = MSM_ISPIF_DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = msm_ispif_dt_match,
+	},
+};
+
+static int __init msm_ispif_init_module(void)
+{
+	return platform_driver_register(&ispif_driver);
+}
+
+static void __exit msm_ispif_exit_module(void)
+{
+	platform_driver_unregister(&ispif_driver);
+}
+
+module_init(msm_ispif_init_module);
+module_exit(msm_ispif_exit_module);
+MODULE_DESCRIPTION("MSM ISP Interface driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msmb/ispif/msm_ispif.h b/drivers/media/video/msmb/ispif/msm_ispif.h
new file mode 100644
index 0000000..c4418c1
--- /dev/null
+++ b/drivers/media/video/msmb/ispif/msm_ispif.h
@@ -0,0 +1,59 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_ISPIF_H
+#define MSM_ISPIF_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+#include <media/msmb_ispif.h>
+#include "msm_sd.h"
+
+struct ispif_irq_status {
+	uint32_t ispifIrqStatus0;
+	uint32_t ispifIrqStatus1;
+	uint32_t ispifIrqStatus2;
+};
+
+enum msm_ispif_state_t {
+	ISPIF_POWER_UP,
+	ISPIF_POWER_DOWN,
+};
+struct ispif_sof_count {
+	uint32_t sof_cnt[INTF_MAX];
+};
+
+struct ispif_intf_cmd {
+	uint32_t intf_cmd;
+	uint32_t intf_cmd1;
+};
+
+struct ispif_device {
+	struct platform_device *pdev;
+	struct msm_sd_subdev msm_sd;
+	struct resource *mem;
+	struct resource *irq;
+	struct resource *io;
+	void __iomem *base;
+	struct mutex mutex;
+	uint8_t start_ack_pending;
+	struct completion reset_complete;
+	uint32_t csid_version;
+	int enb_dump_reg;
+	uint32_t open_cnt;
+	struct ispif_sof_count sof_count[VFE_MAX];
+	struct ispif_intf_cmd applied_intf_cmd[VFE_MAX];
+	enum msm_ispif_state_t ispif_state;
+	struct clk *ispif_clk[INTF_MAX];
+};
+#endif
diff --git a/drivers/media/video/msmb/ispif/msm_ispif_hwreg.h b/drivers/media/video/msmb/ispif/msm_ispif_hwreg.h
new file mode 100644
index 0000000..16575ae
--- /dev/null
+++ b/drivers/media/video/msmb/ispif/msm_ispif_hwreg.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_ISPIF_HWREG_H
+#define MSM_ISPIF_HWREG_H
+
+
+/* ISPIF registers */
+
+#define ISPIF_RST_CMD_ADDR                        0x08
+#define ISPIF_RST_CMD_1_ADDR                      0x0C
+#define ISPIF_INTF_CMD_ADDR                      0x248
+#define ISPIF_INTF_CMD_1_ADDR                    0x24C
+#define ISPIF_CTRL_ADDR                           0x08
+#define ISPIF_INPUT_SEL_ADDR                     0x244
+#define ISPIF_PIX_0_INTF_CID_MASK_ADDR           0x254
+#define ISPIF_RDI_0_INTF_CID_MASK_ADDR           0x264
+#define ISPIF_PIX_1_INTF_CID_MASK_ADDR           0x258
+#define ISPIF_RDI_1_INTF_CID_MASK_ADDR           0x268
+#define ISPIF_RDI_2_INTF_CID_MASK_ADDR           0x26C
+#define ISPIF_PIX_0_STATUS_ADDR                  0x2C0
+#define ISPIF_RDI_0_STATUS_ADDR                  0x2D0
+#define ISPIF_PIX_1_STATUS_ADDR                  0x2C4
+#define ISPIF_RDI_1_STATUS_ADDR                  0x2D4
+#define ISPIF_RDI_2_STATUS_ADDR                  0x2D8
+#define ISPIF_IRQ_MASK_ADDR                      0x208
+#define ISPIF_IRQ_CLEAR_ADDR                     0x230
+#define ISPIF_IRQ_STATUS_ADDR                    0x21C
+#define ISPIF_IRQ_MASK_1_ADDR                    0x20C
+#define ISPIF_IRQ_CLEAR_1_ADDR                   0x234
+#define ISPIF_IRQ_STATUS_1_ADDR                  0x220
+#define ISPIF_IRQ_MASK_2_ADDR                    0x210
+#define ISPIF_IRQ_CLEAR_2_ADDR                   0x238
+#define ISPIF_IRQ_STATUS_2_ADDR                  0x224
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR           0x1C
+
+/* new */
+#define ISPIF_VFE_m_CTRL_0_ADDR                  0x200
+#define ISPIF_VFE_m_IRQ_MASK_0                   0x208
+#define ISPIF_VFE_m_IRQ_MASK_1                   0x20C
+#define ISPIF_VFE_m_IRQ_MASK_2                   0x210
+#define ISPIF_VFE_m_IRQ_STATUS_0                 0x21C
+#define ISPIF_VFE_m_IRQ_STATUS_1                 0x220
+#define ISPIF_VFE_m_IRQ_STATUS_2                 0x224
+#define ISPIF_VFE_m_IRQ_CLEAR_0                  0x230
+#define ISPIF_VFE_m_IRQ_CLEAR_1                  0x234
+#define ISPIF_VFE_m_IRQ_CLEAR_2                  0x238
+
+/*ISPIF RESET BITS*/
+
+#define VFE_CLK_DOMAIN_RST                       31
+#define RDI_CLK_DOMAIN_RST                       26
+#define RDI_1_CLK_DOMAIN_RST                     27
+#define RDI_2_CLK_DOMAIN_RST                     28
+#define PIX_CLK_DOMAIN_RST                       29
+#define PIX_1_CLK_DOMAIN_RST                     30
+#define AHB_CLK_DOMAIN_RST                       25
+#define RDI_2_VFE_RST_STB                        12
+#define RDI_2_CSID_RST_STB                       11
+#define RDI_1_VFE_RST_STB                        10
+#define RDI_1_CSID_RST_STB                       9
+#define RDI_0_VFE_RST_STB                        8
+#define RDI_0_CSID_RST_STB                       7
+#define PIX_1_VFE_RST_STB                        6
+#define PIX_1_CSID_RST_STB                       5
+#define PIX_0_VFE_RST_STB                        4
+#define PIX_0_CSID_RST_STB                       3
+#define SW_REG_RST_STB                           2
+#define MISC_LOGIC_RST_STB                       1
+#define STROBED_RST_EN                           0
+
+#define ISPIF_RST_CMD_MASK                       0xFE0F1FFF
+#define ISPIF_RST_CMD_1_MASK                     0xFC0F1FF9
+
+#define PIX_INTF_0_OVERFLOW_IRQ                  12
+#define RAW_INTF_0_OVERFLOW_IRQ                  25
+#define RAW_INTF_1_OVERFLOW_IRQ                  25
+#define RAW_INTF_2_OVERFLOW_IRQ                  12
+#define RESET_DONE_IRQ                           27
+
+#define ISPIF_IRQ_STATUS_MASK                    0x0A493249
+#define ISPIF_IRQ_STATUS_1_MASK                  0x02493249
+#define ISPIF_IRQ_STATUS_2_MASK                  0x00001249
+
+#define ISPIF_IRQ_STATUS_PIX_SOF_MASK            0x249
+#define ISPIF_IRQ_STATUS_RDI0_SOF_MASK           0x492000
+#define ISPIF_IRQ_STATUS_RDI1_SOF_MASK           0x492000
+#define ISPIF_IRQ_STATUS_RDI2_SOF_MASK           0x249
+
+#define ISPIF_IRQ_STATUS_SOF_MASK                0x492249
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD               0x1
+
+#endif
diff --git a/drivers/media/video/msmb/msm.c b/drivers/media/video/msmb/msm.c
new file mode 100644
index 0000000..c908333
--- /dev/null
+++ b/drivers/media/video/msmb/msm.c
@@ -0,0 +1,1060 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/spinlock.h>
+#include <linux/proc_fs.h>
+#include <linux/atomic.h>
+#include <linux/wait.h>
+#include <linux/videodev2.h>
+#include <linux/msm_ion.h>
+#include <linux/iommu.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-fh.h>
+#include "msm.h"
+#include "msm_vb2.h"
+#include "msm_sd.h"
+
+struct msm_queue_head {
+	struct list_head list;
+	spinlock_t lock;
+	int len;
+	int max;
+};
+
+/** msm_event:
+ *
+ *  event sent by imaging server
+ **/
+struct msm_event {
+	struct video_device *vdev;
+	atomic_t on_heap;
+};
+
+struct msm_command {
+	struct list_head list;
+	struct v4l2_event event;
+	atomic_t on_heap;
+};
+
+/** struct msm_command_ack
+ *
+ *  Object of command_ack_q, which is
+ *  created per open operation
+ *
+ *  contains struct msm_command
+ **/
+struct msm_command_ack {
+	struct list_head list;
+	struct msm_queue_head command_q;
+	wait_queue_head_t wait;
+	int stream_id;
+};
+
+struct msm_stream {
+	struct list_head list;
+
+	/* stream index per session, same
+	 * as stream_id but set through s_parm */
+	unsigned int stream_id;
+
+	/* vb2 buffer handling */
+	struct vb2_queue *vb2_q;
+};
+
+struct msm_v4l2_subdev {
+	/* FIXME: for session close and error handling such
+	 * as daemon shutdown */
+	int    close_sequence;
+};
+
+struct msm_session {
+	struct list_head list;
+
+	/* session index */
+	unsigned int session_id;
+
+	/* event queue sent by imaging server */
+	struct msm_event event_q;
+
+	/* ACK by imaging server. Object type of
+	 * struct msm_command_ack per open,
+	 * assumption is application can send
+	 * command on every opened video node */
+	struct msm_queue_head command_ack_q;
+
+	/* real streams(either data or metadate) owned by one
+	 * session struct msm_stream */
+	struct msm_queue_head stream_q;
+};
+
+static struct v4l2_device *msm_v4l2_dev;
+
+static struct msm_queue_head *msm_session_q;
+
+/* config node envent queue */
+static struct v4l2_fh  *msm_eventq;
+spinlock_t msm_eventq_lock;
+
+static struct pid *msm_pid;
+spinlock_t msm_pid_lock;
+
+#define msm_dequeue(queue, type, member) ({				\
+	unsigned long flags;					\
+	struct msm_queue_head *__q = (queue);			\
+	type *node = 0;				\
+	spin_lock_irqsave(&__q->lock, flags);			\
+	if (!list_empty(&__q->list)) {				\
+		__q->len--;					\
+		node = list_first_entry(&__q->list,		\
+				type, member);	\
+		if ((node) && (&node->member) && (&node->member.next))	\
+			list_del_init(&node->member);			\
+	}							\
+	spin_unlock_irqrestore(&__q->lock, flags);	\
+	node;							\
+})
+
+#define msm_delete_sd_entry(queue, type, member, q_node) ({		\
+	unsigned long flags;					\
+	struct msm_queue_head *__q = (queue);			\
+	type *node = 0;				\
+	spin_lock_irqsave(&__q->lock, flags);			\
+	if (!list_empty(&__q->list)) {				\
+		list_for_each_entry(node, &__q->list, member)	\
+		if (node->sd == q_node) {				\
+			__q->len--;				\
+			list_del_init(&node->member);		\
+			kfree(node);				\
+			break;					\
+		}						\
+	}							\
+	spin_unlock_irqrestore(&__q->lock, flags);		\
+})
+
+#define msm_delete_entry(queue, type, member, q_node) ({		\
+	unsigned long flags;					\
+	struct msm_queue_head *__q = (queue);			\
+	type *node = 0;				\
+	spin_lock_irqsave(&__q->lock, flags);			\
+	if (!list_empty(&__q->list)) {				\
+		list_for_each_entry(node, &__q->list, member)	\
+		if (node == q_node) {				\
+			__q->len--;				\
+			list_del_init(&node->member);		\
+			kfree(node);				\
+			break;					\
+		}						\
+	}							\
+	spin_unlock_irqrestore(&__q->lock, flags);		\
+})
+
+#define msm_queue_drain(queue, type, member) do {			\
+	unsigned long flags;					\
+	struct msm_queue_head *__q = (queue);			\
+	type *node;				\
+	spin_lock_irqsave(&__q->lock, flags);			\
+	while (!list_empty(&__q->list)) {			\
+		__q->len--;					\
+		node = list_first_entry(&__q->list,		\
+			type, member);		\
+		if (node) {					\
+			if (&node->member) \
+				list_del_init(&node->member);		\
+			kfree(node);	\
+		}	\
+	}	\
+	spin_unlock_irqrestore(&__q->lock, flags);		\
+} while (0);
+
+typedef int (*msm_queue_func)(void *d1, void *d2);
+#define msm_queue_traverse_action(queue, type, member, func, data) do {\
+	unsigned long flags;					\
+	struct msm_queue_head *__q = (queue);			\
+	type *node = 0; \
+	msm_queue_func __f = (func); \
+	spin_lock_irqsave(&__q->lock, flags);			\
+	if (!list_empty(&__q->list)) { \
+		list_for_each_entry(node, &__q->list, member) \
+		if (node && __f)  { \
+			__f(node, data); \
+	  } \
+	} \
+	spin_unlock_irqrestore(&__q->lock, flags);			\
+} while (0)
+
+typedef int (*msm_queue_find_func)(void *d1, void *d2);
+#define msm_queue_find(queue, type, member, func, data) ({\
+	unsigned long flags;					\
+	struct msm_queue_head *__q = (queue);			\
+	type *node = 0; \
+	typeof(node) __ret = NULL; \
+	msm_queue_find_func __f = (func); \
+	spin_lock_irqsave(&__q->lock, flags);			\
+	if (!list_empty(&__q->list)) { \
+		list_for_each_entry(node, &__q->list, member) \
+		if ((__f) && __f(node, data)) { \
+			__ret = node; \
+		  break; \
+		} \
+	} \
+	spin_unlock_irqrestore(&__q->lock, flags); \
+	__ret; \
+})
+
+static void msm_init_queue(struct msm_queue_head *qhead)
+{
+	BUG_ON(!qhead);
+
+	INIT_LIST_HEAD(&qhead->list);
+	spin_lock_init(&qhead->lock);
+	qhead->len = 0;
+	qhead->max = 0;
+}
+
+static void msm_enqueue(struct msm_queue_head *qhead,
+		struct list_head *entry)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&qhead->lock, flags);
+	qhead->len++;
+	if (qhead->len > qhead->max)
+		qhead->max = qhead->len;
+	list_add_tail(entry, &qhead->list);
+	spin_unlock_irqrestore(&qhead->lock, flags);
+}
+
+/* index = session id */
+static inline int __msm_queue_find_session(void *d1, void *d2)
+{
+	struct msm_session *session = d1;
+	return (session->session_id == *(unsigned int *)d2) ? 1 : 0;
+}
+
+static inline int __msm_queue_find_stream(void *d1, void *d2)
+{
+	struct msm_stream *stream = d1;
+	return (stream->stream_id == *(unsigned int *)d2) ? 1 : 0;
+}
+
+static inline int __msm_queue_find_command_ack_q(void *d1, void *d2)
+{
+	struct msm_command_ack *ack = d1;
+	return (ack->stream_id == *(unsigned int *)d2) ? 1 : 0;
+}
+
+int msm_create_stream(unsigned int session_id,
+	unsigned int stream_id, struct vb2_queue *q)
+{
+	struct msm_session *session;
+	struct msm_stream  *stream;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (!session)
+		return -EINVAL;
+
+	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+	if (!stream)
+		return -ENOMEM;
+
+	stream->stream_id = stream_id;
+	stream->vb2_q = q;
+
+	msm_enqueue(&session->stream_q, &stream->list);
+	session->stream_q.len++;
+
+	return 0;
+}
+
+void msm_delete_stream(unsigned int session_id, unsigned int stream_id)
+{
+	struct msm_session *session = NULL;
+	struct msm_stream  *stream = NULL;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (!session)
+		return;
+
+	stream = msm_queue_find(&session->stream_q, struct msm_stream,
+		list, __msm_queue_find_stream, &stream_id);
+	if (!stream)
+		return;
+
+	list_del_init(&stream->list);
+	session->stream_q.len--;
+	kfree(stream);
+}
+
+static void msm_sd_unregister_subdev(struct video_device *vdev)
+{
+	struct v4l2_subdev *sd = video_get_drvdata(vdev);
+	sd->devnode = NULL;
+	kfree(vdev);
+}
+
+static inline int __msm_sd_register_subdev(struct v4l2_subdev *sd)
+{
+	int rc = 0;
+	struct video_device *vdev;
+
+	if (!msm_v4l2_dev || !sd || !sd->name[0])
+		return -EINVAL;
+
+	rc = v4l2_device_register_subdev(msm_v4l2_dev, sd);
+	if (rc < 0)
+		return rc;
+
+	/* Register a device node for every subdev marked with the
+	 * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
+	 */
+	if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
+		return rc;
+
+	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+	if (!vdev) {
+		rc = -ENOMEM;
+		goto clean_up;
+	}
+
+	video_set_drvdata(vdev, sd);
+	strlcpy(vdev->name, sd->name, sizeof(vdev->name));
+	vdev->v4l2_dev = msm_v4l2_dev;
+	vdev->fops = &v4l2_subdev_fops;
+	vdev->release = msm_sd_unregister_subdev;
+	rc = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+		  sd->owner);
+	if (rc < 0) {
+		kfree(vdev);
+		goto clean_up;
+	}
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	sd->entity.info.v4l.major = VIDEO_MAJOR;
+	sd->entity.info.v4l.minor = vdev->minor;
+	sd->entity.name = video_device_node_name(vdev);
+#endif
+	sd->devnode = vdev;
+	return 0;
+
+clean_up:
+	if (sd->devnode)
+		video_unregister_device(sd->devnode);
+	return rc;
+}
+
+int msm_sd_register(struct msm_sd_subdev *msm_subdev)
+{
+	if (WARN_ON(!msm_subdev))
+		return -EINVAL;
+
+	if (WARN_ON(!msm_v4l2_dev) && WARN_ON(!msm_v4l2_dev->dev))
+		return -EIO;
+
+	return __msm_sd_register_subdev(&msm_subdev->sd);
+}
+
+int msm_sd_unregister(struct msm_sd_subdev *msm_subdev)
+{
+	if (WARN_ON(!msm_subdev))
+		return -EINVAL;
+
+	v4l2_device_unregister_subdev(&msm_subdev->sd);
+	return 0;
+}
+
+int msm_create_session(unsigned int session_id, struct video_device *vdev)
+{
+	struct msm_session *session = NULL;
+
+	if (!msm_session_q)
+		return -ENODEV;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (session)
+		return -EINVAL;
+
+	session = kzalloc(sizeof(*session), GFP_KERNEL);
+	if (!session)
+		return -ENOMEM;
+
+	session->session_id = session_id;
+	session->event_q.vdev = vdev;
+	msm_init_queue(&session->command_ack_q);
+	msm_init_queue(&session->stream_q);
+	msm_enqueue(msm_session_q, &session->list);
+	return 0;
+}
+
+int msm_create_command_ack_q(unsigned int session_id, unsigned int stream_id)
+{
+	struct msm_session *session;
+	struct msm_command_ack *cmd_ack;
+
+	if (!msm_session_q)
+		return -ENODEV;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (!session)
+		return -EINVAL;
+
+	cmd_ack = kzalloc(sizeof(*cmd_ack), GFP_KERNEL);
+	if (!cmd_ack)
+		return -ENOMEM;
+
+	msm_init_queue(&cmd_ack->command_q);
+	INIT_LIST_HEAD(&cmd_ack->list);
+	init_waitqueue_head(&cmd_ack->wait);
+	cmd_ack->stream_id = stream_id;
+
+	msm_enqueue(&session->command_ack_q, &cmd_ack->list);
+	session->command_ack_q.len++;
+
+	return 0;
+}
+
+void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id)
+{
+	struct msm_session *session;
+	struct msm_command_ack *cmd_ack;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (!session)
+		return;
+
+	cmd_ack = msm_queue_find(&session->command_ack_q,
+		struct msm_command_ack,	list, __msm_queue_find_command_ack_q,
+		&stream_id);
+	if (!cmd_ack)
+		return;
+
+	msm_queue_drain(&cmd_ack->command_q, struct msm_command, list);
+}
+
+static inline int __msm_v4l2_subdev_shutdown(struct v4l2_subdev *sd)
+{
+	return 0;
+}
+
+static void msm_sd_try_shutdown(void)
+{
+	unsigned long flags;
+	struct v4l2_subdev *sd;
+
+	/* release all subdev's resource */
+	spin_lock_irqsave(&msm_v4l2_dev->lock, flags);
+	if (!list_empty(&msm_v4l2_dev->subdevs)) {
+		list_for_each_entry(sd, &msm_v4l2_dev->subdevs, list)
+			__msm_v4l2_subdev_shutdown(sd);
+	}
+	spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
+}
+
+static inline int __msm_sd_close_session_streams(struct v4l2_subdev *sd,
+	struct msm_sd_close_ioctl *sd_close)
+{
+	v4l2_subdev_call(sd, core, ioctl,
+		MSM_SD_CLOSE_SESSION_AND_STREAM, &sd_close);
+
+	return 0;
+}
+
+static inline int __msm_destroy_session_streams(void *d1, void *d2)
+{
+	struct msm_stream *stream = d1;
+	struct msm_sd_close_ioctl *sd_close = d2;
+	struct v4l2_subdev *sd;
+	unsigned long flags;
+
+	sd_close->stream = stream->stream_id;
+
+	spin_lock_irqsave(&msm_v4l2_dev->lock, flags);
+	if (!list_empty(&msm_v4l2_dev->subdevs))
+		list_for_each_entry(sd, &msm_v4l2_dev->subdevs, list)
+			__msm_sd_close_session_streams(sd, sd_close);
+	spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
+
+	return 0;
+}
+
+static void msm_destroy_session_streams(struct msm_session *session)
+{
+	struct msm_sd_close_ioctl sd_close;
+
+	/* to ensure error handling purpose, it needs to detach all subdevs
+	 * which are being connected to streams */
+	if (!session)
+		return;
+
+	sd_close.session = session->session_id;
+
+	msm_queue_traverse_action(&session->stream_q, struct msm_stream, list,
+		__msm_destroy_session_streams, &sd_close);
+
+	msm_queue_drain(&session->stream_q, struct msm_stream, list);
+}
+
+static inline int __msm_remove_session_cmd_ack_q(void *d1, void *d2)
+{
+	struct msm_command_ack *cmd_ack = d1;
+
+	msm_queue_drain(&cmd_ack->command_q, struct msm_command, list);
+
+	return 0;
+}
+
+static void msm_remove_session_cmd_ack_q(struct msm_session *session)
+{
+	if (!session)
+		return;
+
+	/* to ensure error handling purpose, it needs to detach all subdevs
+	 * which are being connected to streams */
+	msm_queue_traverse_action(&session->command_ack_q,
+		struct msm_command_ack,	list,
+		__msm_remove_session_cmd_ack_q, NULL);
+
+	msm_queue_drain(&session->command_ack_q, struct msm_command_ack, list);
+}
+
+int msm_destroy_session(unsigned int session_id)
+{
+	struct msm_session *session;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (!session)
+		return -EINVAL;
+
+	msm_destroy_session_streams(session);
+	msm_remove_session_cmd_ack_q(session);
+
+	msm_delete_entry(msm_session_q, struct msm_session,
+		list, session);
+
+	return 0;
+}
+
+static long msm_private_ioctl(struct file *file, void *fh,
+	bool valid_prio, int cmd, void *arg)
+{
+	int rc = 0;
+	struct msm_v4l2_event_data *event_data;
+	struct msm_session *session;
+	unsigned int session_id;
+	unsigned int stream_id;
+
+	event_data = (struct msm_v4l2_event_data *)
+		((struct v4l2_event *)arg)->u.data;
+
+	session_id = event_data->session_id;
+	stream_id = event_data->stream_id;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+
+	if (!session)
+		return -EINVAL;
+
+	switch (cmd) {
+	case MSM_CAM_V4L2_IOCTL_NOTIFY: {
+		if (WARN_ON(!session->event_q.vdev)) {
+			rc = -EFAULT;
+			break;
+		}
+
+		v4l2_event_queue(session->event_q.vdev,
+			(struct v4l2_event *)arg);
+	}
+		break;
+
+	case MSM_CAM_V4L2_IOCTL_CMD_ACK: {
+		struct msm_command_ack *cmd_ack;
+		struct msm_command *ret_cmd;
+
+		ret_cmd = kzalloc(sizeof(*ret_cmd), GFP_KERNEL);
+		if (!ret_cmd) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		cmd_ack = msm_queue_find(&session->command_ack_q,
+			struct msm_command_ack, list,
+			__msm_queue_find_command_ack_q,
+			&stream_id);
+		if (WARN_ON(!cmd_ack)) {
+			kfree(ret_cmd);
+			rc = -EFAULT;
+			break;
+		}
+
+		ret_cmd->event = *(struct v4l2_event *)arg;
+		msm_enqueue(&cmd_ack->command_q, &ret_cmd->list);
+		wake_up(&cmd_ack->wait);
+	}
+		break;
+
+	default:
+		rc = -ENOTTY;
+		break;
+	}
+
+	return rc;
+}
+
+static int msm_unsubscribe_event(struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub)
+{
+	return v4l2_event_unsubscribe(fh, sub);
+}
+
+static int msm_subscribe_event(struct v4l2_fh *fh,
+	struct v4l2_event_subscription *sub)
+{
+	return v4l2_event_subscribe(fh, sub, 5);
+}
+
+static const struct v4l2_ioctl_ops g_msm_ioctl_ops = {
+	.vidioc_subscribe_event = msm_subscribe_event,
+	.vidioc_unsubscribe_event = msm_unsubscribe_event,
+	.vidioc_default = msm_private_ioctl,
+};
+
+static unsigned int msm_poll(struct file *f,
+	struct poll_table_struct *pll_table)
+{
+	int rc = 0;
+	struct v4l2_fh *eventq = f->private_data;
+
+	BUG_ON(!eventq);
+
+	poll_wait(f, &eventq->wait, pll_table);
+
+	if (v4l2_event_pending(eventq))
+		rc = POLLIN | POLLRDNORM;
+
+	return rc;
+}
+
+/* something seriously wrong if msm_close is triggered
+ *   !!! user space imaging server is shutdown !!!
+ */
+int msm_post_event(struct v4l2_event *event, int timeout)
+{
+	int rc = 0;
+	struct video_device *vdev;
+	struct msm_session *session;
+	struct msm_v4l2_event_data *event_data =
+		(struct msm_v4l2_event_data *)&event->u.data[0];
+	struct msm_command_ack *cmd_ack;
+	struct msm_command *cmd;
+	int session_id, stream_id;
+	unsigned long flags = 0;
+
+	session_id = event_data->session_id;
+	stream_id = event_data->stream_id;
+
+	spin_lock_irqsave(&msm_eventq_lock, flags);
+	if (!msm_eventq) {
+		spin_unlock_irqrestore(&msm_eventq_lock, flags);
+		return -ENODEV;
+	}
+	spin_unlock_irqrestore(&msm_eventq_lock, flags);
+
+	vdev = msm_eventq->vdev;
+
+	/* send to imaging server and wait for ACK */
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (WARN_ON(!session))
+		return -EIO;
+
+	cmd_ack = msm_queue_find(&session->command_ack_q,
+		struct msm_command_ack, list,
+		__msm_queue_find_command_ack_q, &stream_id);
+	if (WARN_ON(!cmd_ack))
+		return -EIO;
+
+	v4l2_event_queue(vdev, event);
+
+	if (timeout < 0)
+		return rc;
+
+	/* should wait on session based condition */
+	rc = wait_event_interruptible_timeout(cmd_ack->wait,
+		!list_empty_careful(&cmd_ack->command_q.list),
+		msecs_to_jiffies(timeout));
+	if (list_empty_careful(&cmd_ack->command_q.list)) {
+		if (!rc)
+			rc = -ETIMEDOUT;
+		if (rc < 0)
+			return rc;
+	}
+
+	cmd = msm_dequeue(&cmd_ack->command_q,
+		struct msm_command, list);
+	if (!cmd)
+		return -EINVAL;
+
+	event_data = (struct msm_v4l2_event_data *)cmd->event.u.data;
+
+	/* compare cmd_ret and event */
+	if (WARN_ON(event->type != cmd->event.type) ||
+			WARN_ON(event->id != cmd->event.id))
+		rc = -EINVAL;
+
+	*event = cmd->event;
+
+	kfree(cmd);
+	return rc;
+}
+
+static int __msm_close_destry_session_notify_apps(void *d1, void *d2)
+{
+	struct v4l2_event event;
+	struct msm_v4l2_event_data *event_data =
+		(struct msm_v4l2_event_data *)&event.u.data[0];
+	struct msm_session *session = d1;
+
+	event.type = MSM_CAMERA_V4L2_EVENT_TYPE;
+	event.id   = MSM_CAMERA_MSM_NOTIFY;
+	event_data->command = MSM_CAMERA_PRIV_SHUTDOWN;
+
+	v4l2_event_queue(session->event_q.vdev, &event);
+
+	msm_destroy_session_streams(session);
+	msm_remove_session_cmd_ack_q(session);
+
+	return 0;
+}
+
+static int msm_close(struct file *filep)
+{
+	int rc = 0;
+	unsigned long flags;
+	struct msm_video_device *pvdev = video_drvdata(filep);
+
+	/* 1st thing 1st, send v4l2_event to HAL immediately,
+	 * to ensure error handling purpose, it needs to detach all subdevs
+	 * which are being connected to streams */
+	msm_queue_traverse_action(msm_session_q, struct msm_session, list,
+		__msm_close_destry_session_notify_apps, NULL);
+
+	msm_queue_drain(msm_session_q, struct msm_session, list);
+
+	spin_lock_irqsave(&msm_eventq_lock, flags);
+	msm_eventq = NULL;
+	spin_unlock_irqrestore(&msm_eventq_lock, flags);
+	v4l2_fh_release(filep);
+
+	msm_sd_try_shutdown();
+
+	spin_lock_irqsave(&msm_pid_lock, flags);
+	put_pid(msm_pid);
+	msm_pid = NULL;
+	spin_unlock_irqrestore(&msm_pid_lock, flags);
+
+	atomic_set(&pvdev->opened, 0);
+
+	return rc;
+}
+
+static inline void msm_list_switch(struct list_head *l1,
+	struct list_head *l2)
+{
+	l1->next = l2->next;
+	l2->prev = l1->prev;
+	l1->prev->next = l2;
+	l2->next->prev = l1;
+	l1->prev = l2;
+	l2->next = l1;
+}
+
+static int msm_open(struct file *filep)
+{
+	int rc;
+	unsigned long flags;
+	struct msm_video_device *pvdev = video_drvdata(filep);
+
+	BUG_ON(!pvdev);
+
+	/* !!! only ONE open is allowed !!! */
+	if (atomic_read(&pvdev->opened))
+		return -EBUSY;
+
+	atomic_set(&pvdev->opened, 1);
+
+	spin_lock_irqsave(&msm_pid_lock, flags);
+	msm_pid = get_pid(task_pid(current));
+	spin_unlock_irqrestore(&msm_pid_lock, flags);
+
+	/* create event queue */
+	rc = v4l2_fh_open(filep);
+	if (rc  < 0)
+		return rc;
+
+	spin_lock_irqsave(&msm_eventq_lock, flags);
+	msm_eventq = filep->private_data;
+	spin_unlock_irqrestore(&msm_eventq_lock, flags);
+
+	return rc;
+}
+
+static struct v4l2_file_operations msm_fops = {
+	.owner  = THIS_MODULE,
+	.open   = msm_open,
+	.poll   = msm_poll,
+	.release = msm_close,
+	.ioctl   = video_ioctl2,
+};
+
+struct msm_stream *msm_get_stream(unsigned int session_id,
+	unsigned int stream_id)
+{
+	struct msm_session *session;
+	struct msm_stream *stream;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (!session)
+		return ERR_PTR(-EINVAL);
+
+	stream = msm_queue_find(&session->stream_q, struct msm_stream,
+		list, __msm_queue_find_stream, &stream_id);
+
+	if (!stream)
+		return ERR_PTR(-EINVAL);
+
+	return stream;
+}
+
+struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
+	unsigned int stream_id)
+{
+	struct msm_session *session;
+	struct msm_stream *stream;
+
+	session = msm_queue_find(msm_session_q, struct msm_session,
+		list, __msm_queue_find_session, &session_id);
+	if (!session)
+		return NULL;
+
+	stream = msm_queue_find(&session->stream_q, struct msm_stream,
+		list, __msm_queue_find_stream, &stream_id);
+	if (!stream)
+		return NULL;
+
+	return stream->vb2_q;
+}
+
+static struct v4l2_subdev *msm_sd_find(const char *name)
+{
+	unsigned long flags;
+	struct v4l2_subdev *subdev = NULL;
+
+	spin_lock_irqsave(&msm_v4l2_dev->lock, flags);
+	if (!list_empty(&msm_v4l2_dev->subdevs)) {
+		list_for_each_entry(subdev, &msm_v4l2_dev->subdevs, list)
+			if (!strcmp(name, subdev->name))
+				break;
+	}
+	spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
+
+	return subdev;
+}
+
+static void msm_sd_notify(struct v4l2_subdev *sd,
+	unsigned int notification, void *arg)
+{
+	int rc = 0;
+	struct v4l2_subdev *subdev = NULL;
+
+	BUG_ON(!sd);
+	BUG_ON(!arg);
+
+	/* Check if subdev exists before processing*/
+	if (!msm_sd_find(sd->name))
+		return;
+
+	switch (notification) {
+	case MSM_SD_NOTIFY_GET_SD: {
+		struct msm_sd_req_sd *get_sd = arg;
+
+		get_sd->subdev = msm_sd_find(get_sd->name);
+		/* TODO: might need to add ref count on ret_sd */
+	}
+		break;
+
+	case MSM_SD_NOTIFY_PUT_SD: {
+		struct msm_sd_req_sd *put_sd = arg;
+		subdev = msm_sd_find(put_sd->name);
+	}
+		break;
+
+	case MSM_SD_NOTIFY_REQ_CB: {
+		struct msm_sd_req_vb2_q *req_sd = arg;
+		rc = msm_vb2_request_cb(req_sd);
+		if (rc < 0)
+			return;
+	}
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int __devinit msm_probe(struct platform_device *pdev)
+{
+	struct msm_video_device *pvdev;
+	int rc = 0;
+
+	msm_v4l2_dev = kzalloc(sizeof(*msm_v4l2_dev),
+		GFP_KERNEL);
+	if (WARN_ON(!msm_v4l2_dev)) {
+		rc = -ENOMEM;
+		goto probe_end;
+	}
+
+	pvdev = kzalloc(sizeof(struct msm_video_device),
+		GFP_KERNEL);
+	if (WARN_ON(!pvdev)) {
+		rc = -ENOMEM;
+		goto pvdev_fail;
+	}
+
+	pvdev->vdev = video_device_alloc();
+	if (WARN_ON(!pvdev->vdev)) {
+		rc = -ENOMEM;
+		goto video_fail;
+	}
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	msm_v4l2_dev->mdev = kzalloc(sizeof(struct media_device),
+		GFP_KERNEL);
+	if (!msm_v4l2_dev->mdev) {
+		rc = -ENOMEM;
+		goto mdev_fail;
+	}
+	strlcpy(msm_v4l2_dev->mdev->model, MSM_CONFIGURATION_NAME,
+			sizeof(msm_v4l2_dev->mdev->model));
+	msm_v4l2_dev->mdev->dev = &(pdev->dev);
+
+	rc = media_device_register(msm_v4l2_dev->mdev);
+	if (WARN_ON(rc < 0))
+		goto media_fail;
+
+	if (WARN_ON((rc == media_entity_init(&pvdev->vdev->entity,
+			0, NULL, 0)) < 0))
+		goto entity_fail;
+
+	pvdev->vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+	pvdev->vdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
+#endif
+
+	msm_v4l2_dev->notify = msm_sd_notify;
+
+	pvdev->vdev->v4l2_dev = msm_v4l2_dev;
+
+	rc = v4l2_device_register(&(pdev->dev), pvdev->vdev->v4l2_dev);
+	if (WARN_ON(rc < 0))
+		goto register_fail;
+
+	strlcpy(pvdev->vdev->name, "msm-config", sizeof(pvdev->vdev->name));
+	pvdev->vdev->release  = video_device_release;
+	pvdev->vdev->fops     = &msm_fops;
+	pvdev->vdev->ioctl_ops = &g_msm_ioctl_ops;
+	pvdev->vdev->minor     = -1;
+	pvdev->vdev->vfl_type  = VFL_TYPE_GRABBER;
+	rc = video_register_device(pvdev->vdev,
+		VFL_TYPE_GRABBER, -1);
+	if (WARN_ON(rc < 0))
+		goto v4l2_fail;
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	/* FIXME: How to get rid of this messy? */
+	pvdev->vdev->entity.name = video_device_node_name(pvdev->vdev);
+#endif
+
+	atomic_set(&pvdev->opened, 0);
+	video_set_drvdata(pvdev->vdev, pvdev);
+
+	msm_session_q = kzalloc(sizeof(*msm_session_q), GFP_KERNEL);
+	if (WARN_ON(!msm_session_q))
+		goto v4l2_fail;
+
+	msm_init_queue(msm_session_q);
+	spin_lock_init(&msm_eventq_lock);
+	spin_lock_init(&msm_pid_lock);
+
+	goto probe_end;
+
+v4l2_fail:
+	v4l2_device_unregister(pvdev->vdev->v4l2_dev);
+register_fail:
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	media_entity_cleanup(&pvdev->vdev->entity);
+entity_fail:
+	media_device_unregister(msm_v4l2_dev->mdev);
+media_fail:
+	kfree(msm_v4l2_dev->mdev);
+mdev_fail:
+#endif
+	video_device_release(pvdev->vdev);
+video_fail:
+	kfree(pvdev);
+pvdev_fail:
+	kfree(msm_v4l2_dev);
+probe_end:
+	return rc;
+}
+
+static const struct of_device_id msm_dt_match[] = {
+	{.compatible = "qcom,msm-cam"},
+}
+
+MODULE_DEVICE_TABLE(of, msm_dt_match);
+
+static struct platform_driver msm_driver = {
+	.probe = msm_probe,
+	.driver = {
+		.name = "msm",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_dt_match,
+	},
+};
+
+static int __init msm_init(void)
+{
+	return platform_driver_register(&msm_driver);
+}
+
+static void __exit msm_exit(void)
+{
+	platform_driver_unregister(&msm_driver);
+}
+
+
+module_init(msm_init);
+module_exit(msm_exit);
+MODULE_DESCRIPTION("MSM V4L2 Camera");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msmb/msm.h b/drivers/media/video/msmb/msm.h
new file mode 100644
index 0000000..eb15cab
--- /dev/null
+++ b/drivers/media/video/msmb/msm.h
@@ -0,0 +1,55 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_H
+#define _MSM_H
+
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/pm_qos.h>
+#include <linux/wakelock.h>
+#include <linux/msm_ion.h>
+#include <linux/iommu.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mediabus.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-msm-mem.h>
+#include <media/msmb_camera.h>
+
+#define MSM_POST_EVT_TIMEOUT 5000
+#define MSM_POST_EVT_NOTIMEOUT 0xFFFFFFFF
+
+struct msm_video_device {
+	struct video_device *vdev;
+	atomic_t opened;
+};
+
+int msm_post_event(struct v4l2_event *event, int timeout);
+int  msm_create_session(unsigned int session, struct video_device *vdev);
+int msm_destroy_session(unsigned int session_id);
+
+int msm_create_stream(unsigned int session_id,
+	unsigned int stream_id, struct vb2_queue *q);
+void msm_delete_stream(unsigned int session_id, unsigned int stream_id);
+int  msm_create_command_ack_q(unsigned int session_id, unsigned int stream_id);
+void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id);
+struct msm_stream *msm_get_stream(unsigned int session_id,
+	unsigned int stream_id);
+struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
+	unsigned int stream_id);
+
+#endif /*_MSM_H */
diff --git a/drivers/media/video/msmb/msm_sd.h b/drivers/media/video/msmb/msm_sd.h
new file mode 100644
index 0000000..aaf3548
--- /dev/null
+++ b/drivers/media/video/msmb/msm_sd.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_SD_H
+#define _MSM_SD_H
+
+#include <media/v4l2-subdev.h>
+#include <media/msmb_camera.h>
+
+/* NOTE: this header file should ONLY be included by subdev drivers */
+
+struct msm_sd_close_ioctl {
+	unsigned int session;
+	unsigned int stream;
+};
+
+#define MSM_SD_CLOSE_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 26, struct msm_sd_close_ioctl)
+
+#define MSM_SD_CLOSE_SESSION \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 27, struct msm_sd_close_ioctl)
+
+#define MSM_SD_CLOSE_SESSION_AND_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 28, struct msm_sd_close_ioctl)
+
+#define MSM_SD_SHUTDOWN \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 29, struct msm_sd_close_ioctl)
+
+/*
+ * This is used to install Sequence in msm_sd_register.
+ * During msm_close, proper close sequence will be triggered.
+ * For example:
+ *
+ * close_sequence = 0x00100001 (ISP)
+ * close_sequence = 0x00100002 (ISP)
+ * close_sequence = 0x00100003 (ISP)
+ * close_sequence = 0x00200001 (sensor)
+ * close_sequence = 0x00200002 (sensor)
+ * close_sequence = 0x00200003 (sensor)
+ */
+#define MSM_SD_CLOSE_1ST_CATEGORY  0x00010000
+#define MSM_SD_CLOSE_2ND_CATEGORY  0x00020000
+#define MSM_SD_CLOSE_3RD_CATEGORY  0x00030000
+
+struct msm_sd_subdev {
+	struct v4l2_subdev sd;
+	int close_seq;
+};
+
+struct msm_sd_req_sd {
+	char *name;
+	struct v4l2_subdev *subdev;
+};
+
+struct msm_sd_req_vb2_q {
+	struct vb2_buffer *(*get_buf)(int session_id, unsigned int stream_id);
+	struct vb2_queue *(*get_vb2_queue)(int session_id,
+		unsigned int stream_id);
+	int (*put_buf)(struct vb2_buffer *vb2_buf);
+	int (*buf_done)(struct vb2_buffer *vb2_buf);
+};
+
+#define MSM_SD_NOTIFY_GET_SD 0x00000001
+#define MSM_SD_NOTIFY_PUT_SD 0x00000002
+#define MSM_SD_NOTIFY_REQ_CB 0x00000003
+
+int msm_sd_register(struct msm_sd_subdev *msm_subdev);
+int msm_sd_unregister(struct msm_sd_subdev *sd);
+struct v4l2_subdev *msm_sd_get_subdev(struct v4l2_subdev *sd,
+	const char *get_name);
+void msm_sd_put_subdev(struct v4l2_subdev *sd, struct v4l2_subdev *put);
+
+#endif /*_MSM_SD_H */
diff --git a/drivers/media/video/msmb/msm_vb2/Makefile b/drivers/media/video/msmb/msm_vb2/Makefile
new file mode 100644
index 0000000..9f61289
--- /dev/null
+++ b/drivers/media/video/msmb/msm_vb2/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/video/msmb
+ccflags-y += -Idrivers/media/video/msmb/msm_vb2
+obj-$(CONFIG_MSMB_CAMERA) += msm_vb2.o
diff --git a/drivers/media/video/msmb/msm_vb2/msm_vb2.c b/drivers/media/video/msmb/msm_vb2/msm_vb2.c
new file mode 100644
index 0000000..8a572a6
--- /dev/null
+++ b/drivers/media/video/msmb/msm_vb2/msm_vb2.c
@@ -0,0 +1,197 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_vb2.h"
+
+static spinlock_t vb2_buf_lock;
+
+static int msm_vb2_queue_setup(struct vb2_queue *q,
+	const struct v4l2_format *fmt,
+	unsigned int *num_buffers, unsigned int *num_planes,
+	unsigned int sizes[], void *alloc_ctxs[])
+{
+	int i;
+	struct msm_v4l2_format_data *data = q->drv_priv;
+
+	if (data->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		if (WARN_ON(data->num_planes > VIDEO_MAX_PLANES))
+			return -EINVAL;
+
+		*num_planes = data->num_planes;
+
+		for (i = 0; i < data->num_planes; i++)
+			sizes[i] = data->plane_sizes[i];
+	} else {
+		pr_err("%s: Unsupported buf type :%d\n", __func__,
+			   data->type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int msm_vb2_buf_init(struct vb2_buffer *vb)
+{
+	struct msm_vb2_buffer *msm_vb2_buf;
+
+	msm_vb2_buf = container_of(vb, struct msm_vb2_buffer, vb2_buf);
+	msm_vb2_buf->in_freeq = 0;
+	spin_lock_init(&vb2_buf_lock);
+
+	return 0;
+}
+
+static void msm_vb2_buf_queue(struct vb2_buffer *vb)
+{
+}
+
+static struct vb2_ops msm_vb2_get_q_op = {
+	.queue_setup		= msm_vb2_queue_setup,
+	.buf_init		= msm_vb2_buf_init,
+	.buf_queue              = msm_vb2_buf_queue,
+};
+
+
+struct vb2_ops *msm_vb2_get_q_ops(void)
+{
+	return &msm_vb2_get_q_op;
+}
+
+static void *msm_vb2_dma_contig_get_userptr(void *alloc_ctx,
+	unsigned long vaddr, unsigned long size, int write)
+{
+	struct msm_vb2_private_data *priv;
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return ERR_PTR(-ENOMEM);
+	priv->vaddr = (void *)vaddr;
+	priv->size = size;
+	priv->alloc_ctx = alloc_ctx;
+	return priv;
+}
+
+static void msm_vb2_dma_contig_put_userptr(void *buf_priv)
+{
+	kfree(buf_priv);
+}
+
+static struct vb2_mem_ops msm_vb2_get_q_mem_op = {
+	.get_userptr		= msm_vb2_dma_contig_get_userptr,
+	.put_userptr		= msm_vb2_dma_contig_put_userptr,
+};
+
+struct vb2_mem_ops *msm_vb2_get_q_mem_ops(void)
+{
+	return &msm_vb2_get_q_mem_op;
+}
+
+static struct vb2_queue *msm_vb2_get_queue(int session_id,
+	unsigned int stream_id)
+{
+	return msm_get_stream_vb2q(session_id, stream_id);
+}
+
+static struct vb2_buffer *msm_vb2_get_buf(int session_id,
+	unsigned int stream_id)
+{
+	struct vb2_queue *q;
+	struct vb2_buffer *vb2_buf = NULL;
+	struct msm_vb2_buffer *msm_vb2;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vb2_buf_lock, flags);
+
+	q = msm_get_stream_vb2q(session_id, stream_id);
+
+	/*FIXME: need a check if stream on issue*/
+	if (!q) {
+		pr_err("%s: stream q not available\n", __func__);
+		goto end;
+	}
+
+	list_for_each_entry(vb2_buf, &(q->queued_list),
+		queued_entry) {
+		if (vb2_buf->state != VB2_BUF_STATE_ACTIVE)
+			continue;
+
+		msm_vb2 = container_of(vb2_buf, struct msm_vb2_buffer, vb2_buf);
+		if (msm_vb2->in_freeq)
+			continue;
+
+		msm_vb2->in_freeq = 1;
+		goto end;
+	}
+	vb2_buf = NULL;
+end:
+	spin_unlock_irqrestore(&vb2_buf_lock, flags);
+	return vb2_buf;
+}
+
+static int msm_vb2_put_buf(struct vb2_buffer *vb)
+{
+	struct msm_vb2_buffer *msm_vb2;
+	int rc = 0;
+
+	if (vb) {
+		msm_vb2 =
+			container_of(vb, struct msm_vb2_buffer, vb2_buf);
+		if (msm_vb2->in_freeq) {
+			msm_vb2->in_freeq = 0;
+			rc = 0;
+		} else
+			rc = -EINVAL;
+	} else {
+		pr_err("%s: VB buffer is null\n", __func__);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static int msm_vb2_buf_done(struct vb2_buffer *vb)
+{
+	unsigned long flags;
+	struct msm_vb2_buffer *msm_vb2;
+	int rc = 0;
+
+	spin_lock_irqsave(&vb2_buf_lock, flags);
+	if (vb) {
+		msm_vb2 =
+			container_of(vb, struct msm_vb2_buffer, vb2_buf);
+		/* put buf before buf done */
+		if (msm_vb2->in_freeq) {
+			vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+			rc = 0;
+		} else
+			rc = -EINVAL;
+	} else {
+		pr_err("%s: VB buffer is null\n", __func__);
+		rc = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&vb2_buf_lock, flags);
+	return rc;
+}
+
+int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req)
+{
+	if (!req) {
+		pr_err("%s: suddev is null\n", __func__);
+		return -EINVAL;
+	}
+
+	req->get_buf = msm_vb2_get_buf;
+	req->get_vb2_queue = msm_vb2_get_queue;
+	req->put_buf = msm_vb2_put_buf;
+	req->buf_done = msm_vb2_buf_done;
+
+	return 0;
+}
+
diff --git a/drivers/media/video/msmb/msm_vb2/msm_vb2.h b/drivers/media/video/msmb/msm_vb2/msm_vb2.h
new file mode 100644
index 0000000..148d577
--- /dev/null
+++ b/drivers/media/video/msmb/msm_vb2/msm_vb2.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_VB_H
+#define _MSM_VB_H
+
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/pm_qos.h>
+#include <linux/wakelock.h>
+#include <linux/msm_ion.h>
+#include <linux/iommu.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mediabus.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-msm-mem.h>
+#include <media/msmb_camera.h>
+#include <media/videobuf2-core.h>
+#include "msm.h"
+#include "msm_sd.h"
+
+struct msm_vb2_buffer {
+	/*
+	 * vb2 buffer has to be first in the structure
+	 * because both v4l2 frameworks and driver directly
+	 * cast msm_vb2_buffer to a vb2_buf.
+	 */
+	struct vb2_buffer vb2_buf;
+	struct list_head list;
+	int in_freeq;
+};
+
+struct msm_vb2_private_data {
+	void *vaddr;
+	unsigned long size;
+	/* Offset of the plane inside the buffer */
+	void *alloc_ctx;
+};
+
+struct vb2_ops *msm_vb2_get_q_ops(void);
+struct vb2_mem_ops *msm_vb2_get_q_mem_ops(void);
+int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req_sd);
+
+#endif /*_MSM_VB_H */
diff --git a/drivers/media/video/msmb/sensor/Makefile b/drivers/media/video/msmb/sensor/Makefile
new file mode 100644
index 0000000..5fa3f6e
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/Makefile
@@ -0,0 +1,8 @@
+ccflags-y += -Idrivers/media/video/msmb
+ccflags-y += -Idrivers/media/video/msmb/msm_vb2
+ccflags-y += -Idrivers/media/video/msmb/camera
+ccflags-y += -Idrivers/media/video/msmb/sensor/io
+ccflags-y += -Idrivers/media/video/msmb/sensor/cci
+obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/
+obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
+obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
diff --git a/drivers/media/video/msmb/sensor/cci/Makefile b/drivers/media/video/msmb/sensor/cci/Makefile
new file mode 100644
index 0000000..8eef3fc
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/cci/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/video/msmb/
+ccflags-y += -Idrivers/media/video/msmb/sensor/io
+obj-$(CONFIG_MSM_CCI) += msm_cci.o
diff --git a/drivers/media/video/msmb/sensor/cci/msm_cam_cci_hwreg.h b/drivers/media/video/msmb/sensor/cci/msm_cam_cci_hwreg.h
new file mode 100644
index 0000000..19cff3b
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/cci/msm_cam_cci_hwreg.h
@@ -0,0 +1,61 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+   *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_CAM_CCI_HWREG__
+#define __MSM_CAM_CCI_HWREG__
+
+#define CCI_HW_VERSION_ADDR                                         0x00000000
+#define CCI_RESET_CMD_ADDR                                          0x00000004
+#define CCI_RESET_CMD_RMSK                                          0xcf73f3f7
+#define CCI_M0_RESET_RMSK                                                0x3F1
+#define CCI_M1_RESET_RMSK                                              0x3F001
+#define CCI_QUEUE_START_ADDR                                        0x00000008
+#define CCI_SET_CID_SYNC_TIMER_0_ADDR                               0x00000010
+#define CCI_I2C_M0_SCL_CTL_ADDR                                     0x00000100
+#define CCI_I2C_M0_SDA_CTL_0_ADDR                                   0x00000104
+#define CCI_I2C_M0_SDA_CTL_1_ADDR                                   0x00000108
+#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
+#define CCI_HALT_REQ_ADDR                                           0x00000034
+#define CCI_I2C_M1_SCL_CTL_ADDR                                     0x00000200
+#define CCI_I2C_M1_SDA_CTL_0_ADDR                                   0x00000204
+#define CCI_I2C_M1_SDA_CTL_1_ADDR                                   0x00000208
+#define CCI_I2C_M1_SDA_CTL_2_ADDR                                   0x0000020c
+#define CCI_I2C_M1_MISC_CTL_ADDR                                    0x00000210
+#define CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR                             0x00000304
+#define CCI_I2C_M0_Q0_CUR_CMD_ADDR                                  0x00000308
+#define CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR                            0x00000300
+#define CCI_I2C_M0_Q0_LOAD_DATA_ADDR                                0x00000310
+#define CCI_IRQ_MASK_0_ADDR                                         0x00000c04
+#define CCI_IRQ_MASK_0_RMSK                                         0x7fff7ff7
+#define CCI_IRQ_CLEAR_0_ADDR                                        0x00000c08
+#define CCI_IRQ_STATUS_0_ADDR                                       0x00000c0c
+#define CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR_BMSK                    0x40000000
+#define CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR_BMSK                    0x20000000
+#define CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERR_BMSK                    0x10000000
+#define CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERR_BMSK                     0x8000000
+#define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK_BMSK                   0x4000000
+#define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK                   0x2000000
+#define CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK                           0x1000000
+#define CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT_BMSK                        0x100000
+#define CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK                         0x10000
+#define CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK                            0x1000
+#define CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT_BMSK                           0x100
+#define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK                            0x10
+#define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK                               0x1
+#define CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR                               0x00000c00
+#endif /* __MSM_CAM_CCI_HWREG__ */
diff --git a/drivers/media/video/msmb/sensor/cci/msm_cci.c b/drivers/media/video/msmb/sensor/cci/msm_cci.c
new file mode 100644
index 0000000..b1c9a40
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/cci/msm_cci.c
@@ -0,0 +1,969 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <media/msm_isp.h>
+#include "msm_sd.h"
+#include "msm_cci.h"
+#include "msm_cam_cci_hwreg.h"
+#include "msm_camera_io_util.h"
+
+#define V4L2_IDENT_CCI 50005
+#define CCI_I2C_QUEUE_0_SIZE 64
+#define CCI_I2C_QUEUE_1_SIZE 16
+
+#define CCI_TIMEOUT msecs_to_jiffies(100)
+
+/* TODO move this somewhere else */
+#define MSM_CCI_DRV_NAME "msm_cci"
+
+#define CONFIG_MSMB_CAMERA_DEBUG
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+static struct v4l2_subdev *g_cci_subdev;
+
+static void msm_cci_set_clk_param(struct cci_device *cci_dev)
+{
+	struct msm_cci_clk_params_t *clk_params = &cci_dev->cci_clk_params;
+
+	msm_camera_io_w(clk_params->hw_thigh << 16 | clk_params->hw_tlow,
+		cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR);
+	msm_camera_io_w(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta,
+		cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR);
+	msm_camera_io_w(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta,
+		cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR);
+	msm_camera_io_w(clk_params->hw_tbuf,
+		cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR);
+	msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
+		clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
+		cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR);
+	msm_camera_io_w(clk_params->hw_thigh << 16 | clk_params->hw_tlow,
+		cci_dev->base + CCI_I2C_M1_SCL_CTL_ADDR);
+	msm_camera_io_w(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta,
+		cci_dev->base + CCI_I2C_M1_SDA_CTL_0_ADDR);
+	msm_camera_io_w(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta,
+		cci_dev->base + CCI_I2C_M1_SDA_CTL_1_ADDR);
+	msm_camera_io_w(clk_params->hw_tbuf,
+		cci_dev->base + CCI_I2C_M1_SDA_CTL_2_ADDR);
+	msm_camera_io_w(clk_params->hw_scl_stretch_en << 8 |
+		clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
+		cci_dev->base + CCI_I2C_M1_MISC_CTL_ADDR);
+	return;
+}
+
+static int32_t msm_cci_i2c_config_sync_timer(struct v4l2_subdev *sd,
+	struct msm_camera_cci_ctrl *c_ctrl)
+{
+	struct cci_device *cci_dev;
+	cci_dev = v4l2_get_subdevdata(sd);
+	msm_camera_io_w(c_ctrl->cci_info->cid, cci_dev->base +
+		CCI_SET_CID_SYNC_TIMER_0_ADDR + (c_ctrl->cci_info->cid * 0x4));
+	return 0;
+}
+
+static int32_t msm_cci_i2c_set_freq(struct v4l2_subdev *sd,
+	struct msm_camera_cci_ctrl *c_ctrl)
+{
+	struct cci_device *cci_dev;
+	uint32_t val;
+	cci_dev = v4l2_get_subdevdata(sd);
+	val = c_ctrl->cci_info->freq;
+	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR +
+		c_ctrl->cci_info->cci_i2c_master*0x100);
+	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR +
+		c_ctrl->cci_info->cci_i2c_master*0x100);
+	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR +
+		c_ctrl->cci_info->cci_i2c_master*0x100);
+	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR +
+		c_ctrl->cci_info->cci_i2c_master*0x100);
+	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR +
+		c_ctrl->cci_info->cci_i2c_master*0x100);
+	return 0;
+}
+
+static int32_t msm_cci_validate_queue(struct cci_device *cci_dev,
+	uint32_t len,
+	enum cci_i2c_master_t master,
+	enum cci_i2c_queue_t queue)
+{
+	int32_t rc = 0;
+	uint32_t read_val = 0;
+	uint32_t reg_offset = master * 0x200 + queue * 0x100;
+	read_val = msm_camera_io_r(cci_dev->base +
+		CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
+	CDBG("%s line %d CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d len %d max %d\n",
+		__func__, __LINE__, read_val, len,
+		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size);
+	if ((read_val + len + 1) > cci_dev->
+		cci_i2c_queue_info[master][queue].max_queue_size) {
+		uint32_t reg_val = 0;
+		uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8);
+		CDBG("%s:%d CCI_I2C_REPORT_CMD\n", __func__, __LINE__);
+		msm_camera_io_w(report_val,
+			cci_dev->base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
+			reg_offset);
+		read_val++;
+		CDBG("%s:%d CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d\n",
+			__func__, __LINE__, read_val);
+		msm_camera_io_w(read_val, cci_dev->base +
+			CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
+		reg_val = 1 << ((master * 2) + queue);
+		CDBG("%s:%d CCI_QUEUE_START_ADDR\n", __func__, __LINE__);
+		msm_camera_io_w(reg_val, cci_dev->base + CCI_QUEUE_START_ADDR);
+		CDBG("%s line %d wait_for_completion_interruptible\n",
+			__func__, __LINE__);
+		rc = wait_for_completion_interruptible_timeout(&cci_dev->
+			cci_master_info[master].reset_complete, CCI_TIMEOUT);
+		if (rc <= 0) {
+			pr_err("%s: wait_for_completion_interruptible_timeout %d\n",
+				 __func__, __LINE__);
+			if (rc == 0)
+				rc = -ETIMEDOUT;
+			return rc;
+		}
+		rc = cci_dev->cci_master_info[master].status;
+		if (rc < 0)
+			pr_err("%s failed rc %d\n", __func__, rc);
+	}
+	return rc;
+}
+
+static int32_t msm_cci_data_queue(struct cci_device *cci_dev,
+	struct msm_camera_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue)
+{
+	uint16_t i = 0, j = 0, k = 0, h = 0, len = 0;
+	int32_t rc = 0;
+	uint32_t cmd = 0;
+	uint8_t data[10];
+	uint16_t reg_addr = 0;
+	struct msm_camera_cci_i2c_write_cfg *i2c_msg =
+		&c_ctrl->cfg.cci_i2c_write_cfg;
+	uint16_t cmd_size = i2c_msg->size;
+	struct msm_camera_i2c_reg_conf *i2c_cmd = i2c_msg->reg_conf_tbl;
+	enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
+	CDBG("%s addr type %d data type %d\n", __func__,
+		i2c_msg->addr_type, i2c_msg->data_type);
+	/* assume total size within the max queue */
+	while (cmd_size) {
+		CDBG("%s cmd_size %d addr 0x%x data 0x%x", __func__,
+			cmd_size, i2c_cmd->reg_addr, i2c_cmd->reg_data);
+		data[i++] = CCI_I2C_WRITE_CMD;
+		if (i2c_cmd->reg_addr)
+			reg_addr = i2c_cmd->reg_addr;
+		/* either byte or word addr */
+		if (i2c_msg->addr_type == MSM_CAMERA_I2C_BYTE_ADDR)
+			data[i++] = reg_addr;
+		else {
+			data[i++] = (reg_addr & 0xFF00) >> 8;
+			data[i++] = reg_addr & 0x00FF;
+		}
+		/* max of 10 data bytes */
+		do {
+			if (i2c_msg->data_type == MSM_CAMERA_I2C_BYTE_DATA) {
+				data[i++] = i2c_cmd->reg_data;
+				reg_addr++;
+			} else {
+				if ((i + 1) <= 10) {
+					data[i++] = (i2c_cmd->reg_data &
+						0xFF00) >> 8; /* MSB */
+					data[i++] = i2c_cmd->reg_data &
+						0x00FF; /* LSB */
+					reg_addr += 2;
+				} else
+					break;
+			}
+			i2c_cmd++;
+		} while (--cmd_size && !i2c_cmd->reg_addr && (i <= 10));
+		data[0] |= ((i-1) << 4);
+		len = ((i-1)/4) + 1;
+		rc = msm_cci_validate_queue(cci_dev, len, master, queue);
+		if (rc < 0) {
+			pr_err("%s: failed %d", __func__, __LINE__);
+			return rc;
+		}
+		for (h = 0, k = 0; h < len; h++) {
+			cmd = 0;
+			for (j = 0; (j < 4 && k < i); j++)
+				cmd |= (data[k++] << (j * 8));
+			CDBG("%s CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x\n",
+				__func__, cmd);
+			msm_camera_io_w(cmd, cci_dev->base +
+				CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
+				master * 0x200 + queue * 0x100);
+		}
+		i = 0;
+	}
+	return rc;
+}
+
+static int32_t msm_cci_write_i2c_queue(struct cci_device *cci_dev,
+	uint32_t val,
+	enum cci_i2c_master_t master,
+	enum cci_i2c_queue_t queue)
+{
+	int32_t rc = 0;
+	uint32_t reg_offset = master * 0x200 + queue * 0x100;
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	rc = msm_cci_validate_queue(cci_dev, 1, master, queue);
+	if (rc < 0) {
+		pr_err("%s: failed %d", __func__, __LINE__);
+		return rc;
+	}
+	CDBG("%s CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val %x:%x\n",
+		__func__, CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
+		reg_offset, val);
+	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
+		reg_offset);
+	return rc;
+}
+
+static int32_t msm_cci_i2c_read(struct v4l2_subdev *sd,
+	struct msm_camera_cci_ctrl *c_ctrl)
+{
+	uint32_t rc = 0;
+	uint32_t val = 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;
+	enum cci_i2c_queue_t queue = QUEUE_1;
+	struct cci_device *cci_dev = NULL;
+	struct msm_camera_cci_i2c_read_cfg *read_cfg = NULL;
+	CDBG("%s line %d\n", __func__, __LINE__);
+	cci_dev = v4l2_get_subdevdata(sd);
+	master = c_ctrl->cci_info->cci_i2c_master;
+	read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
+	mutex_lock(&cci_dev->cci_master_info[master].mutex);
+	CDBG("%s master %d, queue %d\n", __func__, master, queue);
+	CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
+		c_ctrl->cci_info->id_map);
+	val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
+		c_ctrl->cci_info->retries << 16 |
+		c_ctrl->cci_info->id_map << 18;
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	val = CCI_I2C_LOCK_CMD;
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	if (read_cfg->addr_type == MSM_CAMERA_I2C_BYTE_ADDR)
+		val = CCI_I2C_WRITE_CMD | (read_cfg->addr_type << 4) |
+			((read_cfg->addr & 0xFF) << 8);
+	if (read_cfg->addr_type == MSM_CAMERA_I2C_WORD_ADDR)
+		val = CCI_I2C_WRITE_CMD | (read_cfg->addr_type << 4) |
+			(((read_cfg->addr & 0xFF00) >> 8) << 8) |
+			((read_cfg->addr & 0xFF) << 16);
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	val = CCI_I2C_UNLOCK_CMD;
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	val = msm_camera_io_r(cci_dev->base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR +
+		master * 0x200 + queue * 0x100);
+	CDBG("%s cur word cnt %x\n", __func__, val);
+	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR +
+		master * 0x200 + queue * 0x100);
+
+	val = 1 << ((master * 2) + queue);
+	msm_camera_io_w(val, cci_dev->base + CCI_QUEUE_START_ADDR);
+	CDBG("%s:%d E wait_for_completion_interruptible_timeout\n", __func__,
+		__LINE__);
+	rc = wait_for_completion_interruptible_timeout(&cci_dev->
+		cci_master_info[master].reset_complete, CCI_TIMEOUT);
+	if (rc <= 0) {
+		pr_err("%s: wait_for_completion_interruptible_timeout %d\n",
+			 __func__, __LINE__);
+		if (rc == 0)
+			rc = -ETIMEDOUT;
+		return rc;
+	} else {
+		rc = 0;
+	}
+	CDBG("%s:%d E wait_for_completion_interruptible_timeout\n", __func__,
+		__LINE__);
+
+	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);
+		rc = -EINVAL;
+		goto ERROR;
+	}
+	index = 0;
+	CDBG("%s index %d num_type %d\n", __func__, index,
+		read_cfg->num_byte);
+	first_byte = 0;
+	do {
+		val = msm_camera_io_r(cci_dev->base +
+			CCI_I2C_M0_READ_DATA_ADDR + master * 0x100);
+		CDBG("%s read val %x\n", __func__, val);
+		for (i = 0; (i < 4) && (index < read_cfg->num_byte); i++) {
+			CDBG("%s i %d index %d\n", __func__, i, index);
+			if (!first_byte) {
+				CDBG("%s sid %x\n", __func__, val & 0xFF);
+				first_byte++;
+			} else {
+				read_cfg->data[index] =
+					(val  >> (i * 8)) & 0xFF;
+				CDBG("%s data[%d] %x\n", __func__, index,
+					read_cfg->data[index]);
+				index++;
+			}
+		}
+	} while (--read_words > 0);
+ERROR:
+	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+	return rc;
+}
+
+static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd,
+	struct msm_camera_cci_ctrl *c_ctrl)
+{
+	int32_t rc = 0;
+	struct cci_device *cci_dev;
+	uint32_t val;
+	enum cci_i2c_master_t master;
+	enum cci_i2c_queue_t queue = QUEUE_0;
+	cci_dev = v4l2_get_subdevdata(sd);
+	master = c_ctrl->cci_info->cci_i2c_master;
+	CDBG("%s master %d, queue %d\n", __func__, master, queue);
+	CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
+		c_ctrl->cci_info->id_map);
+	mutex_lock(&cci_dev->cci_master_info[master].mutex);
+	val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
+		c_ctrl->cci_info->retries << 16 |
+		c_ctrl->cci_info->id_map << 18;
+	CDBG("%s:%d CCI_I2C_SET_PARAM_CMD\n", __func__, __LINE__);
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	val = CCI_I2C_LOCK_CMD;
+	CDBG("%s:%d CCI_I2C_LOCK_CMD\n", __func__, __LINE__);
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	msm_cci_data_queue(cci_dev, c_ctrl, queue);
+	val = CCI_I2C_UNLOCK_CMD;
+	CDBG("%s:%d CCI_I2C_UNLOCK_CMD\n", __func__, __LINE__);
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	val = CCI_I2C_REPORT_CMD | (1 << 8);
+	CDBG("%s:%d CCI_I2C_REPORT_CMD\n", __func__, __LINE__);
+	rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
+	if (rc < 0) {
+		CDBG("%s failed line %d\n", __func__, __LINE__);
+		goto ERROR;
+	}
+
+	val = msm_camera_io_r(cci_dev->base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR +
+		master * 0x200 + queue * 0x100);
+	CDBG("%s:%d cur word count %d\n", __func__, __LINE__, val);
+	CDBG("%s:%d CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR\n", __func__, __LINE__);
+	msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR +
+		master * 0x200 + queue * 0x100);
+
+	val = 1 << ((master * 2) + queue);
+	CDBG("%s:%d CCI_QUEUE_START_ADDR\n", __func__, __LINE__);
+	msm_camera_io_w(val, cci_dev->base + CCI_QUEUE_START_ADDR +
+		master*0x200 + queue * 0x100);
+
+	CDBG("%s:%d E wait_for_completion_interruptible\n",
+		__func__, __LINE__);
+	rc = wait_for_completion_interruptible_timeout(&cci_dev->
+		cci_master_info[master].reset_complete, CCI_TIMEOUT);
+	if (rc <= 0) {
+		pr_err("%s: wait_for_completion_interruptible_timeout %d\n",
+			 __func__, __LINE__);
+		if (rc == 0)
+			rc = -ETIMEDOUT;
+		return rc;
+	} else {
+		rc = 0;
+	}
+	CDBG("%s:%d X wait_for_completion_interruptible\n", __func__,
+		__LINE__);
+
+ERROR:
+	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+	return rc;
+}
+
+static int msm_cci_subdev_g_chip_ident(struct v4l2_subdev *sd,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	BUG_ON(!chip);
+	chip->ident = V4L2_IDENT_CCI;
+	chip->revision = 0;
+	return 0;
+}
+
+static struct msm_cam_clk_info cci_clk_info[] = {
+	{"camss_top_ahb_clk", -1},
+	{"cci_src_clk", 19200000},
+	{"cci_ahb_clk", -1},
+	{"cci_clk", -1},
+};
+
+static int32_t msm_cci_init(struct v4l2_subdev *sd)
+{
+	int rc = 0;
+	struct cci_device *cci_dev;
+	cci_dev = v4l2_get_subdevdata(sd);
+	CDBG("%s line %d\n", __func__, __LINE__);
+
+	if (!cci_dev) {
+		pr_err("%s cci device NULL\n", __func__);
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	if (cci_dev->ref_count++) {
+		CDBG("%s ref_count %d\n", __func__, cci_dev->ref_count);
+		return 0;
+	}
+
+	rc = msm_camera_request_gpio_table(cci_dev->cci_gpio_tbl,
+		cci_dev->cci_gpio_tbl_size, 1);
+	if (rc < 0) {
+		cci_dev->ref_count--;
+		CDBG("%s: request gpio failed\n", __func__);
+		goto clk_enable_failed;
+	}
+
+	rc = msm_cam_clk_enable(&cci_dev->pdev->dev, cci_clk_info,
+		cci_dev->cci_clk, ARRAY_SIZE(cci_clk_info), 1);
+	if (rc < 0) {
+		cci_dev->ref_count--;
+		CDBG("%s: clk enable failed\n", __func__);
+		goto clk_enable_failed;
+	}
+
+	enable_irq(cci_dev->irq->start);
+	cci_dev->hw_version = msm_camera_io_r(cci_dev->base +
+		CCI_HW_VERSION_ADDR);
+	cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
+	msm_camera_io_w(CCI_RESET_CMD_RMSK, cci_dev->base + CCI_RESET_CMD_ADDR);
+	msm_camera_io_w(0x1, cci_dev->base + CCI_RESET_CMD_ADDR);
+	rc = wait_for_completion_interruptible_timeout(
+		&cci_dev->cci_master_info[MASTER_0].reset_complete,
+		CCI_TIMEOUT);
+	if (rc <= 0) {
+		pr_err("%s: wait_for_completion_interruptible_timeout %d\n",
+			 __func__, __LINE__);
+		if (rc == 0)
+			rc = -ETIMEDOUT;
+		return rc;
+	}
+	msm_cci_set_clk_param(cci_dev);
+	msm_camera_io_w(CCI_IRQ_MASK_0_RMSK,
+		cci_dev->base + CCI_IRQ_MASK_0_ADDR);
+	msm_camera_io_w(CCI_IRQ_MASK_0_RMSK,
+		cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
+	msm_camera_io_w(0x1, cci_dev->base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+	cci_dev->cci_state = CCI_STATE_ENABLED;
+	return 0;
+
+clk_enable_failed:
+	return rc;
+}
+
+static int32_t msm_cci_release(struct v4l2_subdev *sd)
+{
+	struct cci_device *cci_dev;
+	cci_dev = v4l2_get_subdevdata(sd);
+
+	if (!cci_dev->ref_count || cci_dev->cci_state != CCI_STATE_ENABLED) {
+		pr_err("%s invalid ref count %d / cci state %d\n",
+			__func__, cci_dev->ref_count, cci_dev->cci_state);
+		return -EINVAL;
+	}
+
+	if (--cci_dev->ref_count) {
+		CDBG("%s ref_count %d\n", __func__, cci_dev->ref_count);
+		return 0;
+	}
+
+	disable_irq(cci_dev->irq->start);
+
+	msm_cam_clk_enable(&cci_dev->pdev->dev, cci_clk_info,
+		cci_dev->cci_clk, ARRAY_SIZE(cci_clk_info), 0);
+
+	msm_camera_request_gpio_table(cci_dev->cci_gpio_tbl,
+		cci_dev->cci_gpio_tbl_size, 0);
+
+	cci_dev->cci_state = CCI_STATE_DISABLED;
+	return 0;
+}
+
+static int32_t msm_cci_config(struct v4l2_subdev *sd,
+	struct msm_camera_cci_ctrl *cci_ctrl)
+{
+	int32_t rc = 0;
+	CDBG("%s line %d cmd %d\n", __func__, __LINE__,
+		cci_ctrl->cmd);
+	switch (cci_ctrl->cmd) {
+	case MSM_CCI_INIT:
+		rc = msm_cci_init(sd);
+		break;
+	case MSM_CCI_RELEASE:
+		rc = msm_cci_release(sd);
+		break;
+	case MSM_CCI_SET_SID:
+		break;
+	case MSM_CCI_SET_FREQ:
+		rc = msm_cci_i2c_set_freq(sd, cci_ctrl);
+		break;
+	case MSM_CCI_SET_SYNC_CID:
+		rc = msm_cci_i2c_config_sync_timer(sd, cci_ctrl);
+		break;
+	case MSM_CCI_I2C_READ:
+		rc = msm_cci_i2c_read(sd, cci_ctrl);
+		break;
+	case MSM_CCI_I2C_WRITE:
+		rc = msm_cci_i2c_write(sd, cci_ctrl);
+		break;
+	case MSM_CCI_GPIO_WRITE:
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+	}
+	CDBG("%s line %d rc %d\n", __func__, __LINE__, rc);
+	cci_ctrl->status = rc;
+	return rc;
+}
+
+static irqreturn_t msm_cci_irq(int irq_num, void *data)
+{
+	uint32_t irq;
+	struct cci_device *cci_dev = data;
+	irq = msm_camera_io_r(cci_dev->base + CCI_IRQ_STATUS_0_ADDR);
+	msm_camera_io_w(irq, cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
+	msm_camera_io_w(0x1, cci_dev->base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+	msm_camera_io_w(0x0, cci_dev->base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+	CDBG("%s CCI_I2C_M0_STATUS_ADDR = 0x%x\n", __func__, irq);
+	if (irq & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) {
+		if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) {
+			cci_dev->cci_master_info[MASTER_0].reset_pending =
+				FALSE;
+			complete(&cci_dev->cci_master_info[MASTER_0].
+				reset_complete);
+		}
+		if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) {
+			cci_dev->cci_master_info[MASTER_1].reset_pending =
+				FALSE;
+			complete(&cci_dev->cci_master_info[MASTER_1].
+				reset_complete);
+		}
+	} else if ((irq & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) ||
+		(irq & CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK) ||
+		(irq & CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT_BMSK)) {
+		cci_dev->cci_master_info[MASTER_0].status = 0;
+		complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
+	} else if ((irq & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) ||
+		(irq & CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK) ||
+		(irq & CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT_BMSK)) {
+		cci_dev->cci_master_info[MASTER_1].status = 0;
+		complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
+	} else if ((irq & CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERR_BMSK) ||
+		(irq & CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERR_BMSK)) {
+		cci_dev->cci_master_info[MASTER_0].status = -EINVAL;
+		msm_camera_io_w(CCI_M0_HALT_REQ_RMSK,
+			cci_dev->base + CCI_HALT_REQ_ADDR);
+	} else if ((irq & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR_BMSK) ||
+		(irq & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR_BMSK)) {
+		cci_dev->cci_master_info[MASTER_1].status = -EINVAL;
+		msm_camera_io_w(CCI_M1_HALT_REQ_RMSK,
+			cci_dev->base + CCI_HALT_REQ_ADDR);
+	} else if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK) {
+		cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
+		msm_camera_io_w(CCI_M0_RESET_RMSK,
+			cci_dev->base + CCI_RESET_CMD_ADDR);
+	} else if (irq & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK_BMSK) {
+		cci_dev->cci_master_info[MASTER_1].reset_pending = TRUE;
+		msm_camera_io_w(CCI_M1_RESET_RMSK,
+			cci_dev->base + CCI_RESET_CMD_ADDR);
+	} else {
+		pr_err("%s unhandled irq 0x%x\n", __func__, irq);
+		cci_dev->cci_master_info[MASTER_0].status = 0;
+		complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
+		cci_dev->cci_master_info[MASTER_1].status = 0;
+		complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
+	}
+	return IRQ_HANDLED;
+}
+
+static int msm_cci_irq_routine(struct v4l2_subdev *sd, u32 status,
+	bool *handled)
+{
+	struct cci_device *cci_dev = v4l2_get_subdevdata(sd);
+	irqreturn_t ret;
+	CDBG("%s line %d\n", __func__, __LINE__);
+	ret = msm_cci_irq(cci_dev->irq->start, cci_dev);
+	CDBG("%s: msm_cci_irq return %d\n", __func__, ret);
+	*handled = TRUE;
+	return 0;
+}
+
+static long msm_cci_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	int32_t rc = 0;
+	CDBG("%s line %d\n", __func__, __LINE__);
+	switch (cmd) {
+	case VIDIOC_MSM_CCI_CFG:
+		rc = msm_cci_config(sd, arg);
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+	}
+	CDBG("%s line %d rc %d\n", __func__, __LINE__, rc);
+	return rc;
+}
+
+static struct v4l2_subdev_core_ops msm_cci_subdev_core_ops = {
+	.g_chip_ident = &msm_cci_subdev_g_chip_ident,
+	.ioctl = &msm_cci_subdev_ioctl,
+	.interrupt_service_routine = msm_cci_irq_routine,
+};
+
+static const struct v4l2_subdev_ops msm_cci_subdev_ops = {
+	.core = &msm_cci_subdev_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops msm_cci_internal_ops;
+
+static void msm_cci_init_cci_params(struct cci_device *new_cci_dev)
+{
+	uint8_t i = 0, j = 0;
+	for (i = 0; i < NUM_MASTERS; i++) {
+		new_cci_dev->cci_master_info[i].status = 0;
+		mutex_init(&new_cci_dev->cci_master_info[i].mutex);
+		init_completion(&new_cci_dev->
+			cci_master_info[i].reset_complete);
+		for (j = 0; j < NUM_QUEUES; j++) {
+			if (j == QUEUE_0)
+				new_cci_dev->cci_i2c_queue_info[i][j].
+					max_queue_size = CCI_I2C_QUEUE_0_SIZE;
+			else
+				new_cci_dev->cci_i2c_queue_info[i][j].
+					max_queue_size = CCI_I2C_QUEUE_1_SIZE;
+			}
+	}
+	return;
+}
+
+static int32_t msm_cci_init_gpio_params(struct cci_device *cci_dev)
+{
+	int32_t rc = 0, i = 0;
+	uint32_t *val_array = NULL;
+	uint8_t tbl_size = 0;
+	struct device_node *of_node = cci_dev->pdev->dev.of_node;
+	struct gpio *gpio_tbl = NULL;
+
+	cci_dev->cci_gpio_tbl_size = tbl_size = of_gpio_count(of_node);
+	CDBG("%s gpio count %d\n", __func__, tbl_size);
+	if (!tbl_size) {
+		pr_err("%s:%d gpio count 0\n", __func__, __LINE__);
+		return 0;
+	}
+
+	gpio_tbl = cci_dev->cci_gpio_tbl =
+		kzalloc(sizeof(struct gpio) * tbl_size, GFP_KERNEL);
+	if (!gpio_tbl) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return 0;
+	}
+
+	for (i = 0; i < tbl_size; i++) {
+		gpio_tbl[i].gpio = of_get_gpio(of_node, i);
+		CDBG("%s gpio_tbl[%d].gpio = %d\n", __func__, i,
+			gpio_tbl[i].gpio);
+	}
+
+	val_array = kzalloc(sizeof(uint32_t) * tbl_size, GFP_KERNEL);
+	if (!val_array) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-tbl-flags",
+		val_array, tbl_size);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < tbl_size; i++) {
+		gpio_tbl[i].flags = val_array[i];
+		CDBG("%s gpio_tbl[%d].flags = %ld\n", __func__, i,
+			gpio_tbl[i].flags);
+	}
+
+	for (i = 0; i < tbl_size; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,gpio-tbl-label", i, &gpio_tbl[i].label);
+		CDBG("%s gpio_tbl[%d].label = %s\n", __func__, i,
+			gpio_tbl[i].label);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR2;
+		}
+	}
+
+	kfree(val_array);
+	return rc;
+
+ERROR2:
+	kfree(val_array);
+ERROR1:
+	kfree(cci_dev->cci_gpio_tbl);
+	cci_dev->cci_gpio_tbl = NULL;
+	cci_dev->cci_gpio_tbl_size = 0;
+	return rc;
+}
+
+static void msm_cci_init_clk_params(struct cci_device *cci_dev)
+{
+	int32_t rc = 0;
+	uint32_t val = 0;
+	struct device_node *of_node = cci_dev->pdev->dev.of_node;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-thigh", &val);
+	CDBG("%s qcom,hw-thigh %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_thigh = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-tlow", &val);
+	CDBG("%s qcom,hw-tlow %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_tlow = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-tsu-sto", &val);
+	CDBG("%s qcom,hw-tsu-sto %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_tsu_sto = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-tsu-sta", &val);
+	CDBG("%s qcom,hw-tsu-sta %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_tsu_sta = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-thd-dat", &val);
+	CDBG("%s qcom,hw-thd-dat %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_thd_dat = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-thd-sta", &val);
+	CDBG("%s qcom,hwthd-sta %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_thd_sta = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-tbuf", &val);
+	CDBG("%s qcom,hw-tbuf %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_tbuf = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-scl-stretch-en", &val);
+	CDBG("%s qcom,hw-scl-stretch-en %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_scl_stretch_en = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-trdhld", &val);
+	CDBG("%s qcom,hw-trdhld %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_trdhld = val;
+
+	rc = of_property_read_u32(of_node, "qcom,hw-tsp", &val);
+	CDBG("%s qcom,hw-tsp %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		cci_dev->cci_clk_params.hw_tsp = val;
+
+	return;
+}
+
+struct v4l2_subdev *msm_cci_get_subdev(void)
+{
+	return g_cci_subdev;
+}
+
+static int __devinit msm_cci_probe(struct platform_device *pdev)
+{
+	struct cci_device *new_cci_dev;
+	int rc = 0;
+	pr_err("%s: pdev %p device id = %d\n", __func__, pdev, pdev->id);
+	new_cci_dev = kzalloc(sizeof(struct cci_device), GFP_KERNEL);
+	if (!new_cci_dev) {
+		CDBG("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+	v4l2_subdev_init(&new_cci_dev->msm_sd.sd, &msm_cci_subdev_ops);
+	new_cci_dev->msm_sd.sd.internal_ops = &msm_cci_internal_ops;
+	snprintf(new_cci_dev->msm_sd.sd.name,
+			ARRAY_SIZE(new_cci_dev->msm_sd.sd.name), "msm_cci");
+	v4l2_set_subdevdata(&new_cci_dev->msm_sd.sd, new_cci_dev);
+	platform_set_drvdata(pdev, &new_cci_dev->msm_sd.sd);
+	CDBG("%s sd %p\n", __func__, &new_cci_dev->msm_sd.sd);
+	if (pdev->dev.of_node)
+		of_property_read_u32((&pdev->dev)->of_node,
+			"cell-index", &pdev->id);
+
+	new_cci_dev->mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "cci");
+	if (!new_cci_dev->mem) {
+		CDBG("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto cci_no_resource;
+	}
+	new_cci_dev->irq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "cci");
+	CDBG("%s line %d cci irq start %d end %d\n", __func__,
+		__LINE__,
+		new_cci_dev->irq->start,
+		new_cci_dev->irq->end);
+	if (!new_cci_dev->irq) {
+		CDBG("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto cci_no_resource;
+	}
+	new_cci_dev->io = request_mem_region(new_cci_dev->mem->start,
+		resource_size(new_cci_dev->mem), pdev->name);
+	if (!new_cci_dev->io) {
+		CDBG("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto cci_no_resource;
+	}
+
+	new_cci_dev->base = ioremap(new_cci_dev->mem->start,
+		resource_size(new_cci_dev->mem));
+	if (!new_cci_dev->base) {
+		rc = -ENOMEM;
+		goto cci_release_mem;
+	}
+	rc = request_irq(new_cci_dev->irq->start, msm_cci_irq,
+		IRQF_TRIGGER_RISING, "cci", new_cci_dev);
+	if (rc < 0) {
+		CDBG("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto cci_release_mem;
+	}
+	disable_irq(new_cci_dev->irq->start);
+	msm_sd_register(&new_cci_dev->msm_sd);
+	new_cci_dev->pdev = pdev;
+	msm_cci_init_cci_params(new_cci_dev);
+	msm_cci_init_clk_params(new_cci_dev);
+	msm_cci_init_gpio_params(new_cci_dev);
+	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (rc)
+		pr_err("%s: failed to add child nodes, rc=%d\n", __func__, rc);
+	new_cci_dev->cci_state = CCI_STATE_DISABLED;
+	g_cci_subdev = &new_cci_dev->msm_sd.sd;
+	CDBG("%s cci subdev %p\n", __func__, &new_cci_dev->msm_sd.sd);
+	CDBG("%s line %d\n", __func__, __LINE__);
+	return 0;
+
+cci_release_mem:
+	release_mem_region(new_cci_dev->mem->start,
+		resource_size(new_cci_dev->mem));
+cci_no_resource:
+	kfree(new_cci_dev);
+	return 0;
+}
+
+static int __exit msm_cci_exit(struct platform_device *pdev)
+{
+	struct v4l2_subdev *subdev = platform_get_drvdata(pdev);
+	struct cci_device *cci_dev =
+		v4l2_get_subdevdata(subdev);
+	release_mem_region(cci_dev->mem->start, resource_size(cci_dev->mem));
+	kfree(cci_dev);
+	return 0;
+}
+
+static const struct of_device_id msm_cci_dt_match[] = {
+	{.compatible = "qcom,cci"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_cci_dt_match);
+
+static struct platform_driver cci_driver = {
+	.probe = msm_cci_probe,
+	.remove = msm_cci_exit,
+	.driver = {
+		.name = MSM_CCI_DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = msm_cci_dt_match,
+	},
+};
+
+static int __init msm_cci_init_module(void)
+{
+	return platform_driver_register(&cci_driver);
+}
+
+static void __exit msm_cci_exit_module(void)
+{
+	platform_driver_unregister(&cci_driver);
+}
+
+module_init(msm_cci_init_module);
+module_exit(msm_cci_exit_module);
+MODULE_DESCRIPTION("MSM CCI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msmb/sensor/cci/msm_cci.h b/drivers/media/video/msmb/sensor/cci/msm_cci.h
new file mode 100644
index 0000000..527a8db
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/cci/msm_cci.h
@@ -0,0 +1,189 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CCI_H
+#define MSM_CCI_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_cam_sensor.h>
+#include "msm_sd.h"
+
+#define NUM_MASTERS 2
+#define NUM_QUEUES 2
+
+#define TRUE  1
+#define FALSE 0
+
+enum cci_i2c_master_t {
+	MASTER_0,
+	MASTER_1,
+};
+
+enum cci_i2c_queue_t {
+	QUEUE_0,
+	QUEUE_1,
+};
+
+struct msm_camera_cci_client {
+	struct v4l2_subdev *cci_subdev;
+	uint32_t freq;
+	enum cci_i2c_master_t cci_i2c_master;
+	uint16_t sid;
+	uint16_t cid;
+	uint32_t timeout;
+	uint16_t retries;
+	uint16_t id_map;
+};
+
+enum msm_cci_cmd_type {
+	MSM_CCI_INIT,
+	MSM_CCI_RELEASE,
+	MSM_CCI_SET_SID,
+	MSM_CCI_SET_FREQ,
+	MSM_CCI_SET_SYNC_CID,
+	MSM_CCI_I2C_READ,
+	MSM_CCI_I2C_WRITE,
+	MSM_CCI_GPIO_WRITE,
+};
+
+struct msm_camera_cci_wait_sync_cfg {
+	uint16_t line;
+	uint16_t delay;
+};
+
+struct msm_camera_cci_gpio_cfg {
+	uint16_t gpio_queue;
+	uint16_t i2c_queue;
+};
+
+struct msm_camera_cci_i2c_write_cfg {
+	struct msm_camera_i2c_reg_conf *reg_conf_tbl;
+	enum msm_camera_i2c_reg_addr_type addr_type;
+	enum msm_camera_i2c_data_type data_type;
+	uint16_t size;
+};
+
+struct msm_camera_cci_i2c_read_cfg {
+	uint16_t addr;
+	enum msm_camera_i2c_reg_addr_type addr_type;
+	uint8_t *data;
+	uint16_t num_byte;
+};
+
+struct msm_camera_cci_i2c_queue_info {
+	uint32_t max_queue_size;
+	uint32_t report_id;
+	uint32_t irq_en;
+	uint32_t capture_rep_data;
+};
+
+struct msm_camera_cci_ctrl {
+	int32_t status;
+	struct msm_camera_cci_client *cci_info;
+	enum msm_cci_cmd_type cmd;
+	union {
+		struct msm_camera_cci_i2c_write_cfg cci_i2c_write_cfg;
+		struct msm_camera_cci_i2c_read_cfg cci_i2c_read_cfg;
+		struct msm_camera_cci_wait_sync_cfg cci_wait_sync_cfg;
+		struct msm_camera_cci_gpio_cfg gpio_cfg;
+	} cfg;
+};
+
+struct msm_camera_cci_master_info {
+	uint32_t status;
+	uint8_t reset_pending;
+	struct mutex mutex;
+	struct completion reset_complete;
+};
+
+struct msm_cci_clk_params_t {
+	uint16_t hw_thigh;
+	uint16_t hw_tlow;
+	uint16_t hw_tsu_sto;
+	uint16_t hw_tsu_sta;
+	uint16_t hw_thd_dat;
+	uint16_t hw_thd_sta;
+	uint16_t hw_tbuf;
+	uint8_t hw_scl_stretch_en;
+	uint8_t hw_trdhld;
+	uint8_t hw_tsp;
+};
+
+enum msm_cci_state_t {
+	CCI_STATE_ENABLED,
+	CCI_STATE_DISABLED,
+};
+
+struct cci_device {
+	struct platform_device *pdev;
+	struct msm_sd_subdev msm_sd;
+	struct v4l2_subdev subdev;
+	struct resource *mem;
+	struct resource *irq;
+	struct resource *io;
+	void __iomem *base;
+
+	uint32_t hw_version;
+	uint8_t ref_count;
+	enum msm_cci_state_t cci_state;
+
+	struct clk *cci_clk[5];
+	struct msm_camera_cci_i2c_queue_info
+		cci_i2c_queue_info[NUM_MASTERS][NUM_QUEUES];
+	struct msm_camera_cci_master_info cci_master_info[NUM_MASTERS];
+	struct msm_cci_clk_params_t cci_clk_params;
+	struct gpio *cci_gpio_tbl;
+	uint8_t cci_gpio_tbl_size;
+};
+
+enum msm_cci_i2c_cmd_type {
+	CCI_I2C_SET_PARAM_CMD = 1,
+	CCI_I2C_WAIT_CMD,
+	CCI_I2C_WAIT_SYNC_CMD,
+	CCI_I2C_WAIT_GPIO_EVENT_CMD,
+	CCI_I2C_TRIG_I2C_EVENT_CMD,
+	CCI_I2C_LOCK_CMD,
+	CCI_I2C_UNLOCK_CMD,
+	CCI_I2C_REPORT_CMD,
+	CCI_I2C_WRITE_CMD,
+	CCI_I2C_READ_CMD,
+	CCI_I2C_WRITE_DISABLE_P_CMD,
+	CCI_I2C_READ_DISABLE_P_CMD,
+	CCI_I2C_WRITE_CMD2,
+	CCI_I2C_WRITE_CMD3,
+	CCI_I2C_REPEAT_CMD,
+	CCI_I2C_INVALID_CMD,
+};
+
+enum msm_cci_gpio_cmd_type {
+	CCI_GPIO_SET_PARAM_CMD = 1,
+	CCI_GPIO_WAIT_CMD,
+	CCI_GPIO_WAIT_SYNC_CMD,
+	CCI_GPIO_WAIT_GPIO_IN_EVENT_CMD,
+	CCI_GPIO_WAIT_I2C_Q_TRIG_EVENT_CMD,
+	CCI_GPIO_OUT_CMD,
+	CCI_GPIO_TRIG_EVENT_CMD,
+	CCI_GPIO_REPORT_CMD,
+	CCI_GPIO_REPEAT_CMD,
+	CCI_GPIO_CONTINUE_CMD,
+	CCI_GPIO_INVALID_CMD,
+};
+
+struct v4l2_subdev *msm_cci_get_subdev(void);
+
+#define VIDIOC_MSM_CCI_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct msm_camera_cci_ctrl *)
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/csid/Makefile b/drivers/media/video/msmb/sensor/csid/Makefile
new file mode 100644
index 0000000..44d7726
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csid/Makefile
@@ -0,0 +1,8 @@
+ccflags-y += -Idrivers/media/video/msmb
+ccflags-y += -Idrivers/media/video/msmb/sensor/io
+ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
+  ccflags-y += -Idrivers/media/video/msmb/sensor/csid/include/csi2.0
+else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
+  ccflags-y += -Idrivers/media/video/msmb/sensor/csid/include/csi3.0
+endif
+obj-$(CONFIG_MSM_CSID) += msm_csid.o
diff --git a/drivers/media/video/msmb/sensor/csid/include/csi2.0/msm_csid_hwreg.h b/drivers/media/video/msmb/sensor/csid/include/csi2.0/msm_csid_hwreg.h
new file mode 100644
index 0000000..87a114e
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csid/include/csi2.0/msm_csid_hwreg.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_HWREG_H
+#define MSM_CSID_HWREG_H
+
+/* MIPI	CSID registers */
+#define CSID_HW_VERSION_ADDR                        0x0
+#define CSID_CORE_CTRL_0_ADDR                       0x4
+#define CSID_CORE_CTRL_1_ADDR                       0x4
+#define CSID_RST_CMD_ADDR                           0x8
+#define CSID_CID_LUT_VC_0_ADDR                      0xc
+#define CSID_CID_LUT_VC_1_ADDR                      0x10
+#define CSID_CID_LUT_VC_2_ADDR                      0x14
+#define CSID_CID_LUT_VC_3_ADDR                      0x18
+#define CSID_CID_n_CFG_ADDR                         0x1C
+#define CSID_IRQ_CLEAR_CMD_ADDR                     0x5c
+#define CSID_IRQ_MASK_ADDR                          0x60
+#define CSID_IRQ_STATUS_ADDR                        0x64
+#define CSID_CAPTURED_UNMAPPED_LONG_PKT_HDR_ADDR    0x68
+#define CSID_CAPTURED_MMAPPED_LONG_PKT_HDR_ADDR     0x6c
+#define CSID_CAPTURED_SHORT_PKT_ADDR                0x70
+#define CSID_CAPTURED_LONG_PKT_HDR_ADDR             0x74
+#define CSID_CAPTURED_LONG_PKT_FTR_ADDR             0x78
+#define CSID_PIF_MISR_DL0_ADDR                      0x7C
+#define CSID_PIF_MISR_DL1_ADDR                      0x80
+#define CSID_PIF_MISR_DL2_ADDR                      0x84
+#define CSID_PIF_MISR_DL3_ADDR                      0x88
+#define CSID_STATS_TOTAL_PKTS_RCVD_ADDR             0x8C
+#define CSID_STATS_ECC_ADDR                         0x90
+#define CSID_STATS_CRC_ADDR                         0x94
+#define CSID_TG_CTRL_ADDR                           0x9C
+#define CSID_TG_VC_CFG_ADDR                         0xA0
+#define CSID_TG_DT_n_CFG_0_ADDR                     0xA8
+#define CSID_TG_DT_n_CFG_1_ADDR                     0xAC
+#define CSID_TG_DT_n_CFG_2_ADDR                     0xB0
+#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                          17
+#define CSID_VERSION                                0x02000011
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/csid/include/csi3.0/msm_csid_hwreg.h b/drivers/media/video/msmb/sensor/csid/include/csi3.0/msm_csid_hwreg.h
new file mode 100644
index 0000000..8cea521
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csid/include/csi3.0/msm_csid_hwreg.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_HWREG_H
+#define MSM_CSID_HWREG_H
+
+/* MIPI	CSID registers */
+#define CSID_HW_VERSION_ADDR                        0x0
+#define CSID_CORE_CTRL_0_ADDR                       0x4
+#define CSID_CORE_CTRL_1_ADDR                       0x8
+#define CSID_RST_CMD_ADDR                           0xC
+#define CSID_CID_LUT_VC_0_ADDR                      0x10
+#define CSID_CID_LUT_VC_1_ADDR                      0x14
+#define CSID_CID_LUT_VC_2_ADDR                      0x18
+#define CSID_CID_LUT_VC_3_ADDR                      0x1C
+#define CSID_CID_n_CFG_ADDR                         0x20
+#define CSID_IRQ_CLEAR_CMD_ADDR                     0x60
+#define CSID_IRQ_MASK_ADDR                          0x64
+#define CSID_IRQ_STATUS_ADDR                        0x68
+#define CSID_CAPTURED_UNMAPPED_LONG_PKT_HDR_ADDR    0x6C
+#define CSID_CAPTURED_MMAPPED_LONG_PKT_HDR_ADDR     0x70
+#define CSID_CAPTURED_SHORT_PKT_ADDR                0x74
+#define CSID_CAPTURED_LONG_PKT_HDR_ADDR             0x78
+#define CSID_CAPTURED_LONG_PKT_FTR_ADDR             0x7C
+#define CSID_PIF_MISR_DL0_ADDR                      0x80
+#define CSID_PIF_MISR_DL1_ADDR                      0x84
+#define CSID_PIF_MISR_DL2_ADDR                      0x88
+#define CSID_PIF_MISR_DL3_ADDR                      0x8C
+#define CSID_STATS_TOTAL_PKTS_RCVD_ADDR             0x90
+#define CSID_STATS_ECC_ADDR                         0x94
+#define CSID_STATS_CRC_ADDR                         0x98
+#define CSID_TG_CTRL_ADDR                           0xA0
+#define CSID_TG_VC_CFG_ADDR                         0xA4
+#define CSID_TG_DT_n_CFG_0_ADDR                     0xAC
+#define CSID_TG_DT_n_CFG_1_ADDR                     0xB0
+#define CSID_TG_DT_n_CFG_2_ADDR                     0xB4
+#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                          17
+#define CSID_VERSION                                0x30000000
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/csid/msm_csid.c b/drivers/media/video/msmb/sensor/csid/msm_csid.c
new file mode 100644
index 0000000..5889f20
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csid/msm_csid.c
@@ -0,0 +1,693 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/irqreturn.h>
+#include "msm_csid.h"
+#include "msm_csid_hwreg.h"
+#include "msm_sd.h"
+#include "msm_camera_io_util.h"
+
+#define V4L2_IDENT_CSID                            50002
+#define CSID_VERSION_V2                      0x02000011
+#define CSID_VERSION_V3                      0x30000000
+#define MSM_CSID_DRV_NAME                    "msm_csid"
+
+#define DBG_CSID 1
+
+#define TRUE   1
+#define FALSE  0
+
+#define CONFIG_MSMB_CAMERA_DEBUG
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+static uint32_t irq_count;
+
+static int msm_csid_cid_lut(
+	struct msm_camera_csid_lut_params *csid_lut_params,
+	void __iomem *csidbase)
+{
+	int rc = 0, i = 0;
+	uint32_t val = 0;
+
+	if (!csid_lut_params) {
+		pr_err("%s:%d csid_lut_params NULL\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	for (i = 0; i < csid_lut_params->num_cid && i < 16; i++) {
+		CDBG("%s lut params num_cid = %d, cid = %d, dt = %x, df = %d\n",
+			__func__,
+			csid_lut_params->num_cid,
+			csid_lut_params->vc_cfg[i]->cid,
+			csid_lut_params->vc_cfg[i]->dt,
+			csid_lut_params->vc_cfg[i]->decode_format);
+		if (csid_lut_params->vc_cfg[i]->dt < 0x12 ||
+			csid_lut_params->vc_cfg[i]->dt > 0x37) {
+			pr_err("%s: unsupported data type 0x%x\n",
+				 __func__, csid_lut_params->vc_cfg[i]->dt);
+			return rc;
+		}
+		val = msm_camera_io_r(csidbase + CSID_CID_LUT_VC_0_ADDR +
+			(csid_lut_params->vc_cfg[i]->cid >> 2) * 4)
+			& ~(0xFF << ((csid_lut_params->vc_cfg[i]->cid % 4) *
+			8));
+		val |= (csid_lut_params->vc_cfg[i]->dt <<
+			((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));
+	}
+	return rc;
+}
+
+#if DBG_CSID
+static void msm_csid_set_debug_reg(void __iomem *csidbase,
+	struct msm_camera_csid_params *csid_params)
+{
+	uint32_t val = 0;
+	val = ((1 << csid_params->lane_cnt) - 1) << 20;
+	msm_camera_io_w(0x7f010801 | val, csidbase + CSID_IRQ_MASK_ADDR);
+	msm_camera_io_w(0x7f010801 | val, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+}
+#else
+static void msm_csid_set_debug_reg(void __iomem *csidbase,
+	struct msm_camera_csid_params *csid_params) {}
+#endif
+
+static void msm_csid_reset(struct csid_device *csid_dev)
+{
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	msm_camera_io_w(CSID_RST_STB_ALL, csid_dev->base + CSID_RST_CMD_ADDR);
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	wait_for_completion_interruptible(&csid_dev->reset_complete);
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	return;
+}
+
+static int msm_csid_config(struct csid_device *csid_dev,
+	struct msm_camera_csid_params *csid_params)
+{
+	int rc = 0;
+	uint32_t val = 0;
+	void __iomem *csidbase;
+	csidbase = csid_dev->base;
+	if (!csidbase || !csid_params) {
+		pr_err("%s:%d csidbase %p, csid params %p\n", __func__,
+			__LINE__, csidbase, csid_params);
+		return -EINVAL;
+	}
+
+	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->phy_sel);
+
+	msm_csid_reset(csid_dev);
+
+	val = csid_params->lane_cnt - 1;
+	val |= csid_params->lane_assign << CSID_DL_INPUT_SEL_SHIFT;
+	if (csid_dev->hw_version < 0x30000000) {
+		val |= (0xF << 10);
+		msm_camera_io_w(val, csidbase + CSID_CORE_CTRL_0_ADDR);
+	} else {
+		msm_camera_io_w(val, csidbase + CSID_CORE_CTRL_0_ADDR);
+		val = csid_params->phy_sel << CSID_PHY_SEL_SHIFT;
+		val |= 0xF;
+		msm_camera_io_w(val, csidbase + CSID_CORE_CTRL_1_ADDR);
+	}
+
+	rc = msm_csid_cid_lut(&csid_params->lut_params, csidbase);
+	if (rc < 0)
+		return rc;
+
+	msm_csid_set_debug_reg(csidbase, csid_params);
+	return rc;
+}
+
+static irqreturn_t msm_csid_irq(int irq_num, void *data)
+{
+	uint32_t irq;
+	struct csid_device *csid_dev = data;
+	uint32_t val = 0;
+	void __iomem *csidbase;
+	csidbase = csid_dev->base;
+
+	if (!csid_dev) {
+		pr_err("%s:%d csid_dev NULL\n", __func__, __LINE__);
+		return IRQ_HANDLED;
+	}
+	irq = msm_camera_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
+	CDBG("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
+		 __func__, csid_dev->pdev->id, irq);
+	if (irq & (0x1 << CSID_RST_DONE_IRQ_BITSHIFT))
+			complete(&csid_dev->reset_complete);
+	if (irq & 0x1) {
+		pr_debug("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
+			__func__, csid_dev->pdev->id, irq);
+		irq_count++;
+		if (irq_count >= 5) {
+			msm_camera_io_w(0x7f010800 | val,
+				csidbase + CSID_IRQ_MASK_ADDR);
+			msm_camera_io_w(0x7f010800 | val,
+				csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+		}
+	}
+	msm_camera_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
+	return IRQ_HANDLED;
+}
+
+static int msm_csid_irq_routine(struct v4l2_subdev *sd, u32 status,
+	bool *handled)
+{
+	struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
+	irqreturn_t ret;
+	CDBG("%s E\n", __func__);
+	ret = msm_csid_irq(csid_dev->irq->start, csid_dev);
+	*handled = TRUE;
+	return 0;
+}
+
+static int msm_csid_subdev_g_chip_ident(struct v4l2_subdev *sd,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	BUG_ON(!chip);
+	chip->ident = V4L2_IDENT_CSID;
+	chip->revision = 0;
+	return 0;
+}
+
+static struct msm_cam_clk_info csid_8960_clk_info[] = {
+	{"csi_src_clk", 177780000},
+	{"csi_clk", -1},
+	{"csi_phy_clk", -1},
+	{"csi_pclk", -1},
+};
+
+static struct msm_cam_clk_info csid0_8974_clk_info[] = {
+	{"camss_top_ahb_clk", -1},
+	{"ispif_ahb_clk", -1},
+	{"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[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+};
+
+static struct camera_vreg_t csid_8974_vreg_info[] = {
+	{"mipi_csi_vdd", REG_LDO, 1800000, 1800000, 12000},
+};
+
+static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
+{
+	int rc = 0;
+	uint8_t core_id = 0;
+
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	if (!csid_version) {
+		pr_err("%s:%d csid_version NULL\n", __func__, __LINE__);
+		rc = -EINVAL;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	if (csid_dev->csid_state == CSID_POWER_UP) {
+		pr_err("%s: csid invalid state %d\n", __func__,
+			csid_dev->csid_state);
+		rc = -EINVAL;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	csid_dev->base = ioremap(csid_dev->mem->start,
+		resource_size(csid_dev->mem));
+	if (!csid_dev->base) {
+		pr_err("%s csid_dev->base NULL\n", __func__);
+		rc = -ENOMEM;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	if (CSID_VERSION <= CSID_VERSION_V2) {
+		CDBG("%s:%d called\n", __func__, __LINE__);
+		rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 1);
+		if (rc < 0) {
+			pr_err("%s: regulator on failed\n", __func__);
+			goto vreg_config_failed;
+		}
+		CDBG("%s:%d called\n", __func__, __LINE__);
+
+		rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 1);
+		if (rc < 0) {
+			pr_err("%s: regulator enable failed\n", __func__);
+			goto vreg_enable_failed;
+		}
+		CDBG("%s:%d called\n", __func__, __LINE__);
+
+		rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+			csid_8960_clk_info, csid_dev->csid_clk,
+			ARRAY_SIZE(csid_8960_clk_info), 1);
+		if (rc < 0) {
+			pr_err("%s: clock enable failed\n", __func__);
+			goto clk_enable_failed;
+		}
+		CDBG("%s:%d called\n", __func__, __LINE__);
+	} else if (CSID_VERSION == CSID_VERSION_V3) {
+		CDBG("%s:%d called\n", __func__, __LINE__);
+		rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 1);
+		if (rc < 0) {
+			pr_err("%s: regulator on failed\n", __func__);
+			goto vreg_config_failed;
+		}
+		CDBG("%s:%d called\n", __func__, __LINE__);
+
+		rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 1);
+		if (rc < 0) {
+			pr_err("%s: regulator enable failed\n", __func__);
+			goto vreg_enable_failed;
+		}
+		CDBG("%s:%d called\n", __func__, __LINE__);
+
+		rc = 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, 1);
+		if (rc < 0) {
+			pr_err("%s: clock enable failed\n", __func__);
+			goto csid0_clk_enable_failed;
+		}
+		CDBG("%s:%d called\n", __func__, __LINE__);
+		core_id = csid_dev->pdev->id;
+		if (core_id) {
+			CDBG("%s:%d called\n", __func__, __LINE__);
+			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;
+			}
+		}
+	}
+		CDBG("%s:%d called\n", __func__, __LINE__);
+
+	csid_dev->hw_version =
+		msm_camera_io_r(csid_dev->base + CSID_HW_VERSION_ADDR);
+	CDBG("%s:%d called csid_dev->hw_version %x\n", __func__, __LINE__,
+		csid_dev->hw_version);
+	*csid_version = csid_dev->hw_version;
+
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	init_completion(&csid_dev->reset_complete);
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	enable_irq(csid_dev->irq->start);
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	msm_csid_reset(csid_dev);
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	csid_dev->csid_state = CSID_POWER_UP;
+	irq_count = 0;
+	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),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	} else if (CSID_VERSION == CSID_VERSION_V3) {
+		msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	}
+vreg_enable_failed:
+	if (CSID_VERSION <= CSID_VERSION_V2) {
+		msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	} else if (CSID_VERSION == CSID_VERSION_V3) {
+		msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	}
+vreg_config_failed:
+	iounmap(csid_dev->base);
+	csid_dev->base = NULL;
+	return rc;
+}
+
+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__,
+			csid_dev->csid_state);
+		return -EINVAL;
+	}
+
+	irq = msm_camera_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
+	msm_camera_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
+	msm_camera_io_w(0, csid_dev->base + CSID_IRQ_MASK_ADDR);
+
+	disable_irq(csid_dev->irq->start);
+
+	if (csid_dev->hw_version <= CSID_VERSION_V2) {
+		msm_cam_clk_enable(&csid_dev->pdev->dev, csid_8960_clk_info,
+			csid_dev->csid_clk, ARRAY_SIZE(csid_8960_clk_info), 0);
+
+		msm_camera_enable_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+
+		msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	} else if (csid_dev->hw_version == CSID_VERSION_V3) {
+		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),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+
+		msm_camera_config_vreg(&csid_dev->pdev->dev,
+			csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+			NULL, 0, &csid_dev->csi_vdd, 0);
+	}
+
+	iounmap(csid_dev->base);
+	csid_dev->base = NULL;
+	csid_dev->csid_state = CSID_POWER_DOWN;
+	return 0;
+}
+
+static long msm_csid_cmd(struct csid_device *csid_dev, void *arg)
+{
+	int rc = 0;
+	struct csid_cfg_data *cdata = (struct csid_cfg_data *)arg;
+
+	if (!csid_dev || !cdata) {
+		pr_err("%s:%d csid_dev %p, cdata %p\n", __func__, __LINE__,
+			csid_dev, cdata);
+		return -EINVAL;
+	}
+	CDBG("%s cfgtype = %d\n", __func__, cdata->cfgtype);
+	switch (cdata->cfgtype) {
+	case CSID_INIT:
+		rc = msm_csid_init(csid_dev, &cdata->cfg.csid_version);
+		CDBG("%s csid version %x\n", __func__,
+			cdata->cfg.csid_version);
+		break;
+	case CSID_CFG: {
+		struct msm_camera_csid_params csid_params;
+		struct msm_camera_csid_vc_cfg *vc_cfg = NULL;
+		int32_t i = 0;
+		if (copy_from_user(&csid_params,
+			(void *)cdata->cfg.csid_params,
+			sizeof(struct msm_camera_csid_params))) {
+			pr_err("%s: %d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		for (i = 0; i < csid_params.lut_params.num_cid; i++) {
+			vc_cfg = kzalloc(csid_params.lut_params.num_cid *
+				sizeof(struct msm_camera_csid_vc_cfg),
+				GFP_KERNEL);
+			if (!vc_cfg) {
+				pr_err("%s: %d failed\n", __func__, __LINE__);
+				for (i--; i >= 0; i--)
+					kfree(csid_params.lut_params.vc_cfg[i]);
+				rc = -ENOMEM;
+				break;
+			}
+			if (copy_from_user(vc_cfg,
+				(void *)csid_params.lut_params.vc_cfg[i],
+				(csid_params.lut_params.num_cid *
+				sizeof(struct msm_camera_csid_vc_cfg)))) {
+				pr_err("%s: %d failed\n", __func__, __LINE__);
+				kfree(vc_cfg);
+				for (i--; i >= 0; i--)
+					kfree(csid_params.lut_params.vc_cfg[i]);
+				rc = -EFAULT;
+				break;
+			}
+			csid_params.lut_params.vc_cfg[i] = vc_cfg;
+		}
+		rc = msm_csid_config(csid_dev, &csid_params);
+		for (i--; i >= 0; i--)
+			kfree(csid_params.lut_params.vc_cfg[i]);
+		break;
+	}
+	case CSID_RELEASE:
+		rc = msm_csid_release(csid_dev);
+		break;
+	default:
+		pr_err("%s: %d failed\n", __func__, __LINE__);
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	return rc;
+}
+
+static int32_t msm_csid_get_subdev_id(struct csid_device *csid_dev, void *arg)
+{
+	uint32_t *subdev_id = (uint32_t *)arg;
+	if (!subdev_id) {
+		pr_err("%s:%d failed\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	*subdev_id = csid_dev->pdev->id;
+	pr_debug("%s:%d subdev_id %d\n", __func__, __LINE__, *subdev_id);
+	return 0;
+}
+
+static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	int rc = -ENOIOCTLCMD;
+	struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
+	mutex_lock(&csid_dev->mutex);
+	CDBG("%s:%d id %d\n", __func__, __LINE__, csid_dev->pdev->id);
+	switch (cmd) {
+	case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+		rc = msm_csid_get_subdev_id(csid_dev, arg);
+		break;
+	case VIDIOC_MSM_CSID_IO_CFG:
+		rc = msm_csid_cmd(csid_dev, arg);
+		break;
+	case VIDIOC_MSM_CSID_RELEASE:
+		rc = msm_csid_release(csid_dev);
+		break;
+	default:
+		pr_err("%s: command not found\n", __func__);
+	}
+	CDBG("%s:%d\n", __func__, __LINE__);
+	mutex_unlock(&csid_dev->mutex);
+	return rc;
+}
+
+static const struct v4l2_subdev_internal_ops msm_csid_internal_ops;
+
+static struct v4l2_subdev_core_ops msm_csid_subdev_core_ops = {
+	.g_chip_ident = &msm_csid_subdev_g_chip_ident,
+	.ioctl = &msm_csid_subdev_ioctl,
+	.interrupt_service_routine = msm_csid_irq_routine,
+};
+
+static const struct v4l2_subdev_ops msm_csid_subdev_ops = {
+	.core = &msm_csid_subdev_core_ops,
+};
+
+static int __devinit csid_probe(struct platform_device *pdev)
+{
+	struct csid_device *new_csid_dev;
+
+	int rc = 0;
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
+	if (!new_csid_dev) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&new_csid_dev->msm_sd.sd, &msm_csid_subdev_ops);
+	v4l2_set_subdevdata(&new_csid_dev->msm_sd.sd, new_csid_dev);
+	platform_set_drvdata(pdev, &new_csid_dev->msm_sd.sd);
+	mutex_init(&new_csid_dev->mutex);
+
+	if (pdev->dev.of_node)
+		of_property_read_u32((&pdev->dev)->of_node,
+			"cell-index", &pdev->id);
+
+	CDBG("%s device id %d\n", __func__, pdev->id);
+	new_csid_dev->mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "csid");
+	if (!new_csid_dev->mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto csid_no_resource;
+	}
+	new_csid_dev->irq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "csid");
+	if (!new_csid_dev->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto csid_no_resource;
+	}
+	new_csid_dev->io = request_mem_region(new_csid_dev->mem->start,
+		resource_size(new_csid_dev->mem), pdev->name);
+	if (!new_csid_dev->io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto csid_no_resource;
+	}
+
+	new_csid_dev->pdev = pdev;
+	new_csid_dev->msm_sd.sd.internal_ops = &msm_csid_internal_ops;
+	new_csid_dev->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(new_csid_dev->msm_sd.sd.name,
+			ARRAY_SIZE(new_csid_dev->msm_sd.sd.name), "msm_csid");
+	media_entity_init(&new_csid_dev->msm_sd.sd.entity, 0, NULL, 0);
+	new_csid_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	new_csid_dev->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_CSID;
+	msm_sd_register(&new_csid_dev->msm_sd);
+
+	rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
+		IRQF_TRIGGER_RISING, "csid", new_csid_dev);
+	if (rc < 0) {
+		release_mem_region(new_csid_dev->mem->start,
+			resource_size(new_csid_dev->mem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto csid_no_resource;
+	}
+	disable_irq(new_csid_dev->irq->start);
+	if (rc < 0) {
+		release_mem_region(new_csid_dev->mem->start,
+			resource_size(new_csid_dev->mem));
+		pr_err("%s Error registering irq ", __func__);
+		goto csid_no_resource;
+	}
+
+	new_csid_dev->csid_state = CSID_POWER_DOWN;
+	return 0;
+
+csid_no_resource:
+	mutex_destroy(&new_csid_dev->mutex);
+	kfree(new_csid_dev);
+	return 0;
+}
+
+static const struct of_device_id msm_csid_dt_match[] = {
+	{.compatible = "qcom,csid"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_csid_dt_match);
+
+static struct platform_driver csid_driver = {
+	.probe = csid_probe,
+	.driver = {
+		.name = MSM_CSID_DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = msm_csid_dt_match,
+	},
+};
+
+static int __init msm_csid_init_module(void)
+{
+	return platform_driver_register(&csid_driver);
+}
+
+static void __exit msm_csid_exit_module(void)
+{
+	platform_driver_unregister(&csid_driver);
+}
+
+module_init(msm_csid_init_module);
+module_exit(msm_csid_exit_module);
+MODULE_DESCRIPTION("MSM CSID driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msmb/sensor/csid/msm_csid.h b/drivers/media/video/msmb/sensor/csid/msm_csid.h
new file mode 100644
index 0000000..7ae1392
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csid/msm_csid.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_H
+#define MSM_CSID_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_cam_sensor.h>
+#include "msm_sd.h"
+
+enum msm_csid_state_t {
+	CSID_POWER_UP,
+	CSID_POWER_DOWN,
+};
+
+struct csid_device {
+	struct platform_device *pdev;
+	struct msm_sd_subdev msm_sd;
+	struct resource *mem;
+	struct resource *irq;
+	struct resource *io;
+	struct regulator *csi_vdd;
+	void __iomem *base;
+	struct mutex mutex;
+	struct completion reset_complete;
+	uint32_t hw_version;
+	enum msm_csid_state_t csid_state;
+
+	struct clk *csid0_clk[11];
+	struct clk *csid_clk[11];
+};
+
+#define VIDIOC_MSM_CSID_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+#endif
diff --git a/drivers/media/video/msmb/sensor/csiphy/Makefile b/drivers/media/video/msmb/sensor/csiphy/Makefile
new file mode 100644
index 0000000..11e352c
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csiphy/Makefile
@@ -0,0 +1,8 @@
+ccflags-y += -Idrivers/media/video/msmb
+ccflags-y += -Idrivers/media/video/msmb/sensor/io
+ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
+  ccflags-y += -Idrivers/media/video/msmb/sensor/csiphy/include/csi2.0
+else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
+  ccflags-y += -Idrivers/media/video/msmb/sensor/csiphy/include/csi3.0
+endif
+obj-$(CONFIG_MSM_CSIPHY) += msm_csiphy.o
diff --git a/drivers/media/video/msmb/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h b/drivers/media/video/msmb/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
new file mode 100644
index 0000000..e5093f8
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSIPHY_HWREG_H
+#define MSM_CSIPHY_HWREG_H
+
+/*MIPI CSI PHY registers*/
+#define MIPI_CSIPHY_HW_VERSION_ADDR              0x180
+#define MIPI_CSIPHY_LNn_CFG1_ADDR                0x0
+#define MIPI_CSIPHY_LNn_CFG2_ADDR                0x4
+#define MIPI_CSIPHY_LNn_CFG3_ADDR                0x8
+#define MIPI_CSIPHY_LNn_CFG4_ADDR                0xC
+#define MIPI_CSIPHY_LNn_CFG5_ADDR                0x10
+#define MIPI_CSIPHY_LNCK_CFG1_ADDR               0x100
+#define MIPI_CSIPHY_LNCK_CFG2_ADDR               0x104
+#define MIPI_CSIPHY_LNCK_CFG3_ADDR               0x108
+#define MIPI_CSIPHY_LNCK_CFG4_ADDR               0x10C
+#define MIPI_CSIPHY_LNCK_CFG5_ADDR               0x110
+#define MIPI_CSIPHY_LNCK_MISC1_ADDR              0x128
+#define MIPI_CSIPHY_GLBL_RESET_ADDR              0x140
+#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR            0x144
+#define MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR            0x164
+#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR       0x180
+#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR         0x1A0
+#define MIPI_CSIPHY_INTERRUPT_MASK_VAL           0x6F
+#define MIPI_CSIPHY_INTERRUPT_MASK_ADDR          0x1A4
+#define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR        0x1C0
+#define MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR         0x1C4
+#define MIPI_CSIPHY_MODE_CONFIG_SHIFT            0x4
+#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR        0x1E0
+#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR           0x1E8
+#define CSIPHY_VERSION                           0x0
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/csiphy/include/csi3.0/msm_csiphy_hwreg.h b/drivers/media/video/msmb/sensor/csiphy/include/csi3.0/msm_csiphy_hwreg.h
new file mode 100644
index 0000000..b90fbc5
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csiphy/include/csi3.0/msm_csiphy_hwreg.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSIPHY_HWREG_H
+#define MSM_CSIPHY_HWREG_H
+
+/*MIPI CSI PHY registers*/
+#define MIPI_CSIPHY_LNn_CFG1_ADDR                0x0
+#define MIPI_CSIPHY_LNn_CFG2_ADDR                0x4
+#define MIPI_CSIPHY_LNn_CFG3_ADDR                0x8
+#define MIPI_CSIPHY_LNn_CFG4_ADDR                0xC
+#define MIPI_CSIPHY_LNn_CFG5_ADDR                0x10
+#define MIPI_CSIPHY_LNCK_CFG1_ADDR               0x100
+#define MIPI_CSIPHY_LNCK_CFG2_ADDR               0x104
+#define MIPI_CSIPHY_LNCK_CFG3_ADDR               0x108
+#define MIPI_CSIPHY_LNCK_CFG4_ADDR               0x10C
+#define MIPI_CSIPHY_LNCK_CFG5_ADDR               0x110
+#define MIPI_CSIPHY_LNCK_MISC1_ADDR              0x128
+#define MIPI_CSIPHY_GLBL_RESET_ADDR              0x140
+#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR            0x144
+#define MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR            0x164
+#define MIPI_CSIPHY_HW_VERSION_ADDR              0x188
+#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR       0x18C
+#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR         0x1AC
+#define MIPI_CSIPHY_INTERRUPT_MASK_VAL           0x3F
+#define MIPI_CSIPHY_INTERRUPT_MASK_ADDR          0x1AC
+#define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR        0x1CC
+#define MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR         0x1CC
+#define MIPI_CSIPHY_MODE_CONFIG_SHIFT            0x4
+#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR        0x1EC
+#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR           0x1F4
+#define CSIPHY_VERSION                           0x10
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.c b/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.c
new file mode 100644
index 0000000..cc29ed4
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.c
@@ -0,0 +1,640 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/irqreturn.h>
+#include <mach/vreg.h>
+#include "msm_csiphy.h"
+#include "msm_sd.h"
+#include "msm_csiphy_hwreg.h"
+#include "msm_camera_io_util.h"
+#define DBG_CSIPHY 0
+
+#define V4L2_IDENT_CSIPHY                        50003
+#define CSIPHY_VERSION_V3                        0x10
+#define MSM_CSIPHY_DRV_NAME                      "msm_csiphy"
+
+#define CONFIG_MSMB_CAMERA_DEBUG
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+static int msm_csiphy_lane_config(struct csiphy_device *csiphy_dev,
+	struct msm_camera_csiphy_params *csiphy_params)
+{
+	int rc = 0;
+	int j = 0;
+	uint32_t val = 0;
+	uint8_t lane_cnt = 0;
+	uint16_t lane_mask = 0;
+	void __iomem *csiphybase;
+	csiphybase = csiphy_dev->base;
+	if (!csiphybase) {
+		pr_err("%s: csiphybase NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	csiphy_dev->lane_mask[csiphy_dev->pdev->id] |= csiphy_params->lane_mask;
+	lane_mask = csiphy_dev->lane_mask[csiphy_dev->pdev->id];
+	lane_cnt = csiphy_params->lane_cnt;
+	if (csiphy_params->lane_cnt < 1 || csiphy_params->lane_cnt > 4) {
+		pr_err("%s: unsupported lane cnt %d\n",
+			__func__, csiphy_params->lane_cnt);
+		return rc;
+	}
+
+	CDBG("%s csiphy_params, mask = %x, cnt = %d, settle cnt = %x\n",
+		__func__,
+		csiphy_params->lane_mask,
+		csiphy_params->lane_cnt,
+		csiphy_params->settle_cnt);
+	msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
+	msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
+
+	if (csiphy_dev->hw_version != CSIPHY_VERSION_V3) {
+		val = 0x3;
+		msm_camera_io_w((lane_mask << 2) | val,
+				csiphybase + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
+		msm_camera_io_w(0x10, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+		msm_camera_io_w(csiphy_params->settle_cnt,
+			 csiphybase + MIPI_CSIPHY_LNCK_CFG3_ADDR);
+		msm_camera_io_w(0x24,
+			csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR);
+		msm_camera_io_w(0x24,
+			csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
+	} else {
+		val = 0x1;
+		msm_camera_io_w((lane_mask << 1) | val,
+				csiphybase + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
+		msm_camera_io_w(csiphy_params->combo_mode <<
+			MIPI_CSIPHY_MODE_CONFIG_SHIFT,
+			csiphybase + MIPI_CSIPHY_GLBL_RESET_ADDR);
+	}
+
+	lane_mask &= 0x1f;
+	while (lane_mask & 0x1f) {
+		if (!(lane_mask & 0x1)) {
+			j++;
+			lane_mask >>= 1;
+			continue;
+		}
+		msm_camera_io_w(0x10,
+			csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*j);
+		msm_camera_io_w(csiphy_params->settle_cnt,
+			csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*j);
+		msm_camera_io_w(MIPI_CSIPHY_INTERRUPT_MASK_VAL, csiphybase +
+			MIPI_CSIPHY_INTERRUPT_MASK_ADDR + 0x4*j);
+		msm_camera_io_w(MIPI_CSIPHY_INTERRUPT_MASK_VAL, csiphybase +
+			MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR + 0x4*j);
+		j++;
+		lane_mask >>= 1;
+	}
+	msleep(20);
+	return rc;
+}
+
+static irqreturn_t msm_csiphy_irq(int irq_num, void *data)
+{
+	uint32_t irq;
+	int i;
+	struct csiphy_device *csiphy_dev = data;
+
+	for (i = 0; i < 8; i++) {
+		irq = msm_camera_io_r(
+			csiphy_dev->base +
+			MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR + 0x4*i);
+		msm_camera_io_w(irq,
+			csiphy_dev->base +
+			MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
+		pr_err("%s MIPI_CSIPHY%d_INTERRUPT_STATUS%d = 0x%x\n",
+			 __func__, csiphy_dev->pdev->id, i, irq);
+		msm_camera_io_w(0x1, csiphy_dev->base +
+			MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR);
+		msm_camera_io_w(0x0, csiphy_dev->base +
+			MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR);
+		msm_camera_io_w(0x0,
+			csiphy_dev->base +
+			MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
+	}
+	return IRQ_HANDLED;
+}
+
+static void msm_csiphy_reset(struct csiphy_device *csiphy_dev)
+{
+	msm_camera_io_w(0x1, csiphy_dev->base + MIPI_CSIPHY_GLBL_RESET_ADDR);
+	usleep_range(5000, 8000);
+	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_GLBL_RESET_ADDR);
+}
+
+static int msm_csiphy_subdev_g_chip_ident(struct v4l2_subdev *sd,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	BUG_ON(!chip);
+	chip->ident = V4L2_IDENT_CSIPHY;
+	chip->revision = 0;
+	return 0;
+}
+
+static struct msm_cam_clk_info csiphy_8960_clk_info[] = {
+	{"csiphy_timer_src_clk", 177780000},
+	{"csiphy_timer_clk", -1},
+};
+
+static struct msm_cam_clk_info csiphy_8974_clk_info[] = {
+	{"camss_top_ahb_clk", -1},
+	{"ispif_ahb_clk", -1},
+	{"csiphy_timer_src_clk", 200000000},
+	{"csiphy_timer_clk", -1},
+};
+
+#if DBG_CSIPHY
+static int msm_csiphy_init(struct csiphy_device *csiphy_dev)
+{
+	int rc = 0;
+	if (csiphy_dev == NULL) {
+		pr_err("%s: csiphy_dev NULL\n", __func__);
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	if (csiphy_dev->csiphy_state == CSIPHY_POWER_UP) {
+		pr_err("%s: csiphy invalid state %d\n", __func__,
+			csiphy_dev->csiphy_state);
+		rc = -EINVAL;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	if (csiphy_dev->ref_count++) {
+		CDBG("%s csiphy refcount = %d\n", __func__,
+			csiphy_dev->ref_count);
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	csiphy_dev->base = ioremap(csiphy_dev->mem->start,
+		resource_size(csiphy_dev->mem));
+	if (!csiphy_dev->base) {
+		pr_err("%s: csiphy_dev->base NULL\n", __func__);
+		csiphy_dev->ref_count--;
+		rc = -ENOMEM;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	if (CSIPHY_VERSION != CSIPHY_VERSION_V3) {
+		CDBG("%s:%d called\n", __func__, __LINE__);
+		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8960_clk_info), 1);
+	} else {
+		CDBG("%s:%d called\n", __func__, __LINE__);
+		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8974_clk_info), 1);
+	}
+
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	if (rc < 0) {
+		pr_err("%s: csiphy clk enable failed\n", __func__);
+		csiphy_dev->ref_count--;
+		iounmap(csiphy_dev->base);
+		csiphy_dev->base = NULL;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	enable_irq(csiphy_dev->irq->start);
+
+	msm_csiphy_reset(csiphy_dev);
+
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	csiphy_dev->hw_version =
+		msm_camera_io_r(csiphy_dev->base + MIPI_CSIPHY_HW_VERSION_ADDR);
+
+	CDBG("%s:%d called csiphy_dev->hw_version %x\n", __func__, __LINE__,
+		csiphy_dev->hw_version);
+	csiphy_dev->csiphy_state = CSIPHY_POWER_UP;
+	return 0;
+}
+#else
+static int msm_csiphy_init(struct csiphy_device *csiphy_dev)
+{
+	int rc = 0;
+	if (csiphy_dev == NULL) {
+		pr_err("%s: csiphy_dev NULL\n", __func__);
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	if (csiphy_dev->csiphy_state == CSIPHY_POWER_UP) {
+		pr_err("%s: csiphy invalid state %d\n", __func__,
+			csiphy_dev->csiphy_state);
+		rc = -EINVAL;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	if (csiphy_dev->ref_count++) {
+		CDBG("%s csiphy refcount = %d\n", __func__,
+			csiphy_dev->ref_count);
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	csiphy_dev->base = ioremap(csiphy_dev->mem->start,
+		resource_size(csiphy_dev->mem));
+	if (!csiphy_dev->base) {
+		pr_err("%s: csiphy_dev->base NULL\n", __func__);
+		csiphy_dev->ref_count--;
+		rc = -ENOMEM;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	if (CSIPHY_VERSION != CSIPHY_VERSION_V3) {
+		CDBG("%s:%d called\n", __func__, __LINE__);
+		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8960_clk_info), 1);
+	} else {
+		CDBG("%s:%d called\n", __func__, __LINE__);
+		rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8974_clk_info), 1);
+	}
+
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	if (rc < 0) {
+		pr_err("%s: csiphy clk enable failed\n", __func__);
+		csiphy_dev->ref_count--;
+		iounmap(csiphy_dev->base);
+		csiphy_dev->base = NULL;
+		return rc;
+	}
+	CDBG("%s:%d called\n", __func__, __LINE__);
+
+	msm_csiphy_reset(csiphy_dev);
+
+	CDBG("%s:%d called\n", __func__, __LINE__);
+	csiphy_dev->hw_version =
+		msm_camera_io_r(csiphy_dev->base + MIPI_CSIPHY_HW_VERSION_ADDR);
+
+	CDBG("%s:%d called csiphy_dev->hw_version %x\n", __func__, __LINE__,
+		csiphy_dev->hw_version);
+	csiphy_dev->csiphy_state = CSIPHY_POWER_UP;
+	return 0;
+}
+#endif
+
+#if DBG_CSIPHY
+static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg)
+{
+	int i = 0;
+	struct msm_camera_csi_lane_params *csi_lane_params;
+	uint16_t csi_lane_mask;
+	csi_lane_params = (struct msm_camera_csi_lane_params *)arg;
+	csi_lane_mask = csi_lane_params->csi_lane_mask;
+
+	if (!csiphy_dev || !csiphy_dev->ref_count) {
+		pr_err("%s csiphy dev NULL / ref_count ZERO\n", __func__);
+		return 0;
+	}
+
+	if (csiphy_dev->csiphy_state != CSIPHY_POWER_UP) {
+		pr_err("%s: csiphy invalid state %d\n", __func__,
+			csiphy_dev->csiphy_state);
+		return -EINVAL;
+	}
+
+	CDBG("%s csiphy_params, lane assign %x mask = %x\n",
+		__func__,
+		csi_lane_params->csi_lane_assign,
+		csi_lane_params->csi_lane_mask);
+
+	if (csiphy_dev->hw_version != CSIPHY_VERSION_V3) {
+		csiphy_dev->lane_mask[csiphy_dev->pdev->id] = 0;
+		for (i = 0; i < 4; i++)
+			msm_camera_io_w(0x0, csiphy_dev->base +
+				MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+	} else {
+		csiphy_dev->lane_mask[csiphy_dev->pdev->id] &=
+			~(csi_lane_params->csi_lane_mask);
+		i = 0;
+		while (csi_lane_mask & 0x1F) {
+			if (csi_lane_mask & 0x1) {
+				msm_camera_io_w(0x0, csiphy_dev->base +
+					MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+			}
+			csi_lane_mask >>= 1;
+			i++;
+		}
+	}
+
+	if (--csiphy_dev->ref_count) {
+		CDBG("%s csiphy refcount = %d\n", __func__,
+			csiphy_dev->ref_count);
+		return 0;
+	}
+
+	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
+
+	disable_irq(csiphy_dev->irq->start);
+
+	if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8960_clk_info), 0);
+	else
+		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8974_clk_info), 0);
+
+	iounmap(csiphy_dev->base);
+	csiphy_dev->base = NULL;
+	csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
+	return 0;
+}
+#else
+static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg)
+{
+	int i = 0;
+	struct msm_camera_csi_lane_params *csi_lane_params;
+	uint16_t csi_lane_mask;
+	csi_lane_params = (struct msm_camera_csi_lane_params *)arg;
+	csi_lane_mask = csi_lane_params->csi_lane_mask;
+
+	if (!csiphy_dev || !csiphy_dev->ref_count) {
+		pr_err("%s csiphy dev NULL / ref_count ZERO\n", __func__);
+		return 0;
+	}
+
+	if (csiphy_dev->csiphy_state != CSIPHY_POWER_UP) {
+		pr_err("%s: csiphy invalid state %d\n", __func__,
+			csiphy_dev->csiphy_state);
+		return -EINVAL;
+	}
+
+	CDBG("%s csiphy_params, lane assign %x mask = %x\n",
+		__func__,
+		csi_lane_params->csi_lane_assign,
+		csi_lane_params->csi_lane_mask);
+
+	if (csiphy_dev->hw_version != CSIPHY_VERSION_V3) {
+		csiphy_dev->lane_mask[csiphy_dev->pdev->id] = 0;
+		for (i = 0; i < 4; i++)
+			msm_camera_io_w(0x0, csiphy_dev->base +
+				MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+	} else {
+		csiphy_dev->lane_mask[csiphy_dev->pdev->id] &=
+			~(csi_lane_params->csi_lane_mask);
+		i = 0;
+		while (csi_lane_mask & 0x1F) {
+			if (csi_lane_mask & 0x1) {
+				msm_camera_io_w(0x0, csiphy_dev->base +
+					MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+			}
+			csi_lane_mask >>= 1;
+			i++;
+		}
+	}
+
+	if (--csiphy_dev->ref_count) {
+		CDBG("%s csiphy refcount = %d\n", __func__,
+			csiphy_dev->ref_count);
+		return 0;
+	}
+
+	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+	msm_camera_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
+
+	if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8960_clk_info), 0);
+	else
+		msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+			csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+			ARRAY_SIZE(csiphy_8974_clk_info), 0);
+
+	iounmap(csiphy_dev->base);
+	csiphy_dev->base = NULL;
+	csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
+	return 0;
+}
+#endif
+
+static long msm_csiphy_cmd(struct csiphy_device *csiphy_dev, void *arg)
+{
+	int rc = 0;
+	struct csiphy_cfg_data *cdata = (struct csiphy_cfg_data *)arg;
+	struct msm_camera_csiphy_params csiphy_params;
+	struct msm_camera_csi_lane_params csi_lane_params;
+	if (!csiphy_dev || !cdata) {
+		pr_err("%s: csiphy_dev NULL\n", __func__);
+		return -EINVAL;
+	}
+	switch (cdata->cfgtype) {
+	case CSIPHY_INIT:
+		rc = msm_csiphy_init(csiphy_dev);
+		break;
+	case CSIPHY_CFG:
+		if (copy_from_user(&csiphy_params,
+			(void *)cdata->cfg.csiphy_params,
+			sizeof(struct msm_camera_csiphy_params))) {
+			pr_err("%s: %d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = msm_csiphy_lane_config(csiphy_dev, &csiphy_params);
+		break;
+	case CSIPHY_RELEASE:
+		if (copy_from_user(&csi_lane_params,
+			(void *)cdata->cfg.csi_lane_params,
+			sizeof(struct msm_camera_csi_lane_params))) {
+			pr_err("%s: %d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		rc = msm_csiphy_release(csiphy_dev, &csi_lane_params);
+		break;
+	default:
+		pr_err("%s: %d failed\n", __func__, __LINE__);
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	return rc;
+}
+
+static int32_t msm_csiphy_get_subdev_id(struct csiphy_device *csiphy_dev,
+	void *arg)
+{
+	uint32_t *subdev_id = (uint32_t *)arg;
+	if (!subdev_id) {
+		pr_err("%s:%d failed\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	*subdev_id = csiphy_dev->pdev->id;
+	pr_debug("%s:%d subdev_id %d\n", __func__, __LINE__, *subdev_id);
+	return 0;
+}
+
+static long msm_csiphy_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	int rc = -ENOIOCTLCMD;
+	struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd);
+	CDBG("%s:%d id %d\n", __func__, __LINE__, csiphy_dev->pdev->id);
+	mutex_lock(&csiphy_dev->mutex);
+	switch (cmd) {
+	case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+		rc = msm_csiphy_get_subdev_id(csiphy_dev, arg);
+		break;
+	case VIDIOC_MSM_CSIPHY_IO_CFG:
+		rc = msm_csiphy_cmd(csiphy_dev, arg);
+		break;
+	case VIDIOC_MSM_CSIPHY_RELEASE:
+		rc = msm_csiphy_release(csiphy_dev, arg);
+		break;
+	default:
+		pr_err("%s: command not found\n", __func__);
+	}
+	mutex_unlock(&csiphy_dev->mutex);
+	CDBG("%s:%d\n", __func__, __LINE__);
+	return rc;
+}
+
+static const struct v4l2_subdev_internal_ops msm_csiphy_internal_ops;
+
+static struct v4l2_subdev_core_ops msm_csiphy_subdev_core_ops = {
+	.g_chip_ident = &msm_csiphy_subdev_g_chip_ident,
+	.ioctl = &msm_csiphy_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csiphy_subdev_ops = {
+	.core = &msm_csiphy_subdev_core_ops,
+};
+
+static int __devinit csiphy_probe(struct platform_device *pdev)
+{
+	struct csiphy_device *new_csiphy_dev;
+	int rc = 0;
+
+	new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL);
+	if (!new_csiphy_dev) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&new_csiphy_dev->msm_sd.sd, &msm_csiphy_subdev_ops);
+	v4l2_set_subdevdata(&new_csiphy_dev->msm_sd.sd, new_csiphy_dev);
+	platform_set_drvdata(pdev, &new_csiphy_dev->msm_sd.sd);
+
+	mutex_init(&new_csiphy_dev->mutex);
+
+	if (pdev->dev.of_node)
+		of_property_read_u32((&pdev->dev)->of_node,
+			"cell-index", &pdev->id);
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+
+	new_csiphy_dev->mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "csiphy");
+	if (!new_csiphy_dev->mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto csiphy_no_resource;
+	}
+	new_csiphy_dev->irq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "csiphy");
+	if (!new_csiphy_dev->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto csiphy_no_resource;
+	}
+	new_csiphy_dev->io = request_mem_region(new_csiphy_dev->mem->start,
+		resource_size(new_csiphy_dev->mem), pdev->name);
+	if (!new_csiphy_dev->io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto csiphy_no_resource;
+	}
+
+	rc = request_irq(new_csiphy_dev->irq->start, msm_csiphy_irq,
+		IRQF_TRIGGER_RISING, "csiphy", new_csiphy_dev);
+	if (rc < 0) {
+		release_mem_region(new_csiphy_dev->mem->start,
+			resource_size(new_csiphy_dev->mem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto csiphy_no_resource;
+	}
+	disable_irq(new_csiphy_dev->irq->start);
+
+	new_csiphy_dev->pdev = pdev;
+	new_csiphy_dev->msm_sd.sd.internal_ops = &msm_csiphy_internal_ops;
+	new_csiphy_dev->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(new_csiphy_dev->msm_sd.sd.name,
+		ARRAY_SIZE(new_csiphy_dev->msm_sd.sd.name), "msm_csiphy");
+	media_entity_init(&new_csiphy_dev->msm_sd.sd.entity, 0, NULL, 0);
+	new_csiphy_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	new_csiphy_dev->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_CSIPHY;
+
+	msm_sd_register(&new_csiphy_dev->msm_sd);
+	new_csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
+	return 0;
+
+csiphy_no_resource:
+	mutex_destroy(&new_csiphy_dev->mutex);
+	kfree(new_csiphy_dev);
+	return 0;
+}
+
+static const struct of_device_id msm_csiphy_dt_match[] = {
+	{.compatible = "qcom,csiphy"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_csiphy_dt_match);
+
+static struct platform_driver csiphy_driver = {
+	.probe = csiphy_probe,
+	.driver = {
+		.name = MSM_CSIPHY_DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = msm_csiphy_dt_match,
+	},
+};
+
+static int __init msm_csiphy_init_module(void)
+{
+	return platform_driver_register(&csiphy_driver);
+}
+
+static void __exit msm_csiphy_exit_module(void)
+{
+	platform_driver_unregister(&csiphy_driver);
+}
+
+module_init(msm_csiphy_init_module);
+module_exit(msm_csiphy_exit_module);
+MODULE_DESCRIPTION("MSM CSIPHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.h b/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.h
new file mode 100644
index 0000000..e19be34
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/csiphy/msm_csiphy.h
@@ -0,0 +1,49 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSIPHY_H
+#define MSM_CSIPHY_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_cam_sensor.h>
+#include "msm_sd.h"
+
+#define MAX_CSIPHY 3
+
+enum msm_csiphy_state_t {
+	CSIPHY_POWER_UP,
+	CSIPHY_POWER_DOWN,
+};
+
+struct csiphy_device {
+	struct platform_device *pdev;
+	struct msm_sd_subdev msm_sd;
+	struct v4l2_subdev subdev;
+	struct resource *mem;
+	struct resource *irq;
+	struct resource *io;
+	void __iomem *base;
+	struct mutex mutex;
+	uint32_t hw_version;
+	enum msm_csiphy_state_t csiphy_state;
+
+	struct clk *csiphy_clk[4];
+	uint8_t ref_count;
+	uint16_t lane_mask[MAX_CSIPHY];
+};
+
+#define VIDIOC_MSM_CSIPHY_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, void *)
+#endif
diff --git a/drivers/media/video/msmb/sensor/io/Makefile b/drivers/media/video/msmb/sensor/io/Makefile
new file mode 100644
index 0000000..ec1faa5
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/io/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/video/msmb/
+ccflags-y += -Idrivers/media/video/msmb/sensor/cci
+obj-$(CONFIG_MSMB_CAMERA)   += msm_camera_io_util.o msm_camera_cci_i2c.o msm_camera_qup_i2c.o msm_camera_i2c_mux.o
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_cci_i2c.c b/drivers/media/video/msmb/sensor/io/msm_camera_cci_i2c.c
new file mode 100644
index 0000000..b07bb36
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/io/msm_camera_cci_i2c.c
@@ -0,0 +1,284 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/camera2.h>
+#include "msm_camera_i2c.h"
+#include "msm_cci.h"
+
+#define CONFIG_MSMB_CAMERA_DEBUG
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#define S_I2C_DBG(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#define S_I2C_DBG(fmt, args...) do { } while (0)
+#endif
+
+
+int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t *data,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[client->addr_type+data_type];
+	struct msm_camera_cci_ctrl cci_ctrl;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	cci_ctrl.cmd = MSM_CCI_I2C_READ;
+	cci_ctrl.cci_info = client->cci_client;
+	cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr;
+	cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = client->addr_type;
+	cci_ctrl.cfg.cci_i2c_read_cfg.data = buf;
+	cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = data_type;
+	rc = v4l2_subdev_call(client->cci_client->cci_subdev,
+			core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
+	if (rc < 0) {
+		pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
+		return rc;
+	}
+	rc = cci_ctrl.status;
+	if (data_type == MSM_CAMERA_I2C_BYTE_DATA)
+		*data = buf[0];
+	else
+		*data = buf[0] << 8 | buf[1];
+
+	S_I2C_DBG("%s addr = 0x%x data: 0x%x\n", __func__, addr, *data);
+	return rc;
+}
+
+int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint8_t *data, uint16_t num_byte)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[client->addr_type+num_byte];
+	int i;
+	struct msm_camera_cci_ctrl cci_ctrl;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| num_byte == 0)
+		return rc;
+
+	cci_ctrl.cmd = MSM_CCI_I2C_READ;
+	cci_ctrl.cci_info = client->cci_client;
+	cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr;
+	cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = client->addr_type;
+	cci_ctrl.cfg.cci_i2c_read_cfg.data = buf;
+	cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = num_byte;
+	rc = v4l2_subdev_call(client->cci_client->cci_subdev,
+			core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
+	CDBG("%s line %d rc = %d\n", __func__, __LINE__, rc);
+	rc = cci_ctrl.status;
+
+	S_I2C_DBG("%s addr = 0x%x", __func__, addr);
+	for (i = 0; i < num_byte; i++) {
+		data[i] = buf[i];
+		S_I2C_DBG("Byte %d: 0x%x\n", i, buf[i]);
+		S_I2C_DBG("Data: 0x%x\n", data[i]);
+	}
+	return rc;
+}
+
+int32_t msm_camera_cci_i2c_write(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t data,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc = -EFAULT;
+	struct msm_camera_cci_ctrl cci_ctrl;
+	struct msm_camera_i2c_reg_conf reg_conf_tbl;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	CDBG("%s:%d reg addr = 0x%x data type: %d\n",
+		__func__, __LINE__, addr, data_type);
+	reg_conf_tbl.reg_addr = addr;
+	reg_conf_tbl.reg_data = data;
+	cci_ctrl.cmd = MSM_CCI_I2C_WRITE;
+	cci_ctrl.cci_info = client->cci_client;
+	cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = &reg_conf_tbl;
+	cci_ctrl.cfg.cci_i2c_write_cfg.data_type = data_type;
+	cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
+	cci_ctrl.cfg.cci_i2c_write_cfg.size = 1;
+	rc = v4l2_subdev_call(client->cci_client->cci_subdev,
+			core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
+	if (rc < 0) {
+		pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
+		return rc;
+	}
+	rc = cci_ctrl.status;
+	return rc;
+}
+
+int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint8_t *data, uint16_t num_byte)
+{
+	int32_t rc = -EFAULT;
+	uint8_t i = 0;
+	struct msm_camera_cci_ctrl cci_ctrl;
+	struct msm_camera_i2c_reg_conf reg_conf_tbl[num_byte];
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| num_byte == 0)
+		return rc;
+
+	S_I2C_DBG("%s reg addr = 0x%x num bytes: %d\n",
+			  __func__, addr, num_byte);
+	reg_conf_tbl[0].reg_addr = addr;
+	for (i = 0; i < num_byte; i++)
+		reg_conf_tbl[i].reg_data = data[i];
+	cci_ctrl.cmd = MSM_CCI_I2C_WRITE;
+	cci_ctrl.cci_info = client->cci_client;
+	cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = reg_conf_tbl;
+	cci_ctrl.cfg.cci_i2c_write_cfg.size = num_byte;
+	rc = v4l2_subdev_call(client->cci_client->cci_subdev,
+			core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
+	CDBG("%s line %d rc = %d\n", __func__, __LINE__, rc);
+	rc = cci_ctrl.status;
+	return rc;
+}
+
+int32_t msm_camera_cci_i2c_write_table(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_setting *write_setting)
+{
+	int i;
+	int32_t rc = -EFAULT;
+	struct msm_camera_i2c_reg_array *reg_setting;
+	uint16_t client_addr_type;
+
+	if (!client || !write_setting)
+		return rc;
+
+	if ((write_setting->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& write_setting->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (write_setting->data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& write_setting->data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	reg_setting = write_setting->reg_setting;
+	client_addr_type = client->addr_type;
+	client->addr_type = write_setting->addr_type;
+
+	for (i = 0; i < write_setting->size; i++) {
+		rc = msm_camera_cci_i2c_write(client, reg_setting->reg_addr,
+			reg_setting->reg_data, write_setting->data_type);
+		if (rc < 0)
+			return rc;
+		reg_setting++;
+	}
+	if (write_setting->delay > 20)
+		msleep(write_setting->delay);
+	else if (write_setting->delay)
+		usleep_range(write_setting->delay * 1000, (write_setting->delay
+			* 1000) + 1000);
+
+	client->addr_type = client_addr_type;
+	return rc;
+}
+
+int32_t msm_camera_cci_i2c_write_seq_table(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_seq_reg_setting *write_setting)
+{
+	int i;
+	int32_t rc = -EFAULT;
+	struct msm_camera_i2c_seq_reg_array *reg_setting;
+	uint16_t client_addr_type;
+
+	if (!client || !write_setting)
+		return rc;
+
+	if ((write_setting->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& write_setting->addr_type != MSM_CAMERA_I2C_WORD_ADDR)) {
+		pr_err("%s Invalide addr type %d\n", __func__,
+			write_setting->addr_type);
+		return rc;
+	}
+
+	reg_setting = write_setting->reg_setting;
+	client_addr_type = client->addr_type;
+	client->addr_type = write_setting->addr_type;
+
+	for (i = 0; i < write_setting->size; i++) {
+		rc = msm_camera_cci_i2c_write_seq(client, reg_setting->reg_addr,
+			reg_setting->reg_data, reg_setting->reg_data_size);
+		if (rc < 0)
+			return rc;
+		reg_setting++;
+	}
+	if (write_setting->delay > 20)
+		msleep(write_setting->delay);
+	else if (write_setting->delay)
+		usleep_range(write_setting->delay * 1000, (write_setting->delay
+			* 1000) + 1000);
+
+	client->addr_type = client_addr_type;
+	return rc;
+}
+
+int32_t msm_camera_cci_i2c_write_table_w_microdelay(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int i;
+	int32_t rc = -EFAULT;
+
+	if (!client || !reg_tbl)
+		return rc;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	for (i = 0; i < size; i++) {
+		rc = msm_camera_cci_i2c_write(client, reg_tbl->reg_addr,
+			reg_tbl->reg_data, data_type);
+		if (rc < 0)
+			return rc;
+		if (reg_tbl->delay)
+			usleep_range(reg_tbl->delay, reg_tbl->delay + 1000);
+		reg_tbl++;
+	}
+	return rc;
+}
+
+int32_t msm_sensor_cci_i2c_util(struct msm_camera_i2c_client *client,
+	uint16_t cci_cmd)
+{
+	int32_t rc = 0;
+	struct msm_camera_cci_ctrl cci_ctrl;
+
+	CDBG("%s line %d\n", __func__, __LINE__);
+	cci_ctrl.cmd = cci_cmd;
+	cci_ctrl.cci_info = client->cci_client;
+	rc = v4l2_subdev_call(client->cci_client->cci_subdev,
+			core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
+	if (rc < 0) {
+		pr_err("%s line %d rc = %d\n", __func__, __LINE__, rc);
+		return rc;
+	}
+	return cci_ctrl.status;
+}
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_i2c.h b/drivers/media/video/msmb/sensor/io/msm_camera_i2c.h
new file mode 100644
index 0000000..aa38e62
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/io/msm_camera_i2c.h
@@ -0,0 +1,108 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CAMERA_CCI_I2C_H
+#define MSM_CAMERA_CCI_I2C_H
+
+#include <linux/delay.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_cam_sensor.h>
+
+struct msm_camera_i2c_client {
+	struct msm_camera_i2c_fn_t *i2c_func_tbl;
+	struct i2c_client *client;
+	struct msm_camera_cci_client *cci_client;
+	enum msm_camera_i2c_reg_addr_type addr_type;
+};
+
+struct msm_camera_i2c_reg_tbl {
+	uint16_t reg_addr;
+	uint16_t reg_data;
+	uint16_t delay;
+};
+
+struct msm_camera_i2c_fn_t {
+	int (*i2c_read) (struct msm_camera_i2c_client *, uint16_t, uint16_t *,
+		enum msm_camera_i2c_data_type);
+	int32_t (*i2c_read_seq)(struct msm_camera_i2c_client *, uint16_t,
+		uint8_t *, uint16_t);
+	int (*i2c_write) (struct msm_camera_i2c_client *, uint16_t, uint16_t,
+		enum msm_camera_i2c_data_type);
+	int (*i2c_write_seq) (struct msm_camera_i2c_client *, uint16_t ,
+		uint8_t *, uint16_t);
+	int32_t (*i2c_write_table)(struct msm_camera_i2c_client *,
+		struct msm_camera_i2c_reg_setting *);
+	int32_t (*i2c_write_seq_table)(struct msm_camera_i2c_client *,
+		struct msm_camera_i2c_seq_reg_setting *);
+	int32_t (*i2c_write_table_w_microdelay)
+		(struct msm_camera_i2c_client *,
+		struct msm_camera_i2c_reg_tbl *, uint16_t,
+		enum msm_camera_i2c_data_type);
+	int32_t (*i2c_util)(struct msm_camera_i2c_client *, uint16_t);
+};
+
+int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t *data,
+	enum msm_camera_i2c_data_type data_type);
+
+int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint8_t *data, uint16_t num_byte);
+
+int32_t msm_camera_cci_i2c_write(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t data,
+	enum msm_camera_i2c_data_type data_type);
+
+int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint8_t *data, uint16_t num_byte);
+
+int32_t msm_camera_cci_i2c_write_table(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_setting *write_setting);
+
+int32_t msm_camera_cci_i2c_write_seq_table(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_seq_reg_setting *write_setting);
+
+int32_t msm_camera_cci_i2c_write_table_w_microdelay(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
+	enum msm_camera_i2c_data_type data_type);
+
+int32_t msm_sensor_cci_i2c_util(struct msm_camera_i2c_client *client,
+	uint16_t cci_cmd);
+
+int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t *data,
+	enum msm_camera_i2c_data_type data_type);
+
+int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint8_t *data, uint16_t num_byte);
+
+int32_t msm_camera_qup_i2c_write(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t data,
+	enum msm_camera_i2c_data_type data_type);
+
+int32_t msm_camera_qup_i2c_write_seq(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint8_t *data, uint16_t num_byte);
+
+int32_t msm_camera_qup_i2c_write_table(struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_setting *write_setting);
+
+int32_t msm_camera_qup_i2c_write_seq_table(struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_seq_reg_setting *write_setting);
+
+int32_t msm_camera_qup_i2c_write_table_w_microdelay(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
+	enum msm_camera_i2c_data_type data_type);
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.c b/drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.c
new file mode 100644
index 0000000..49759e6
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.c
@@ -0,0 +1,188 @@
+/* Copyright (c) 2011-2013, The Linux Foundatation. All rights reserved.
+ *
+ * This 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/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include "msm_camera_i2c_mux.h"
+
+/* TODO move this somewhere else */
+#define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
+static int msm_i2c_mux_config(struct i2c_mux_device *mux_device, uint8_t *mode)
+{
+	uint32_t val;
+	val = msm_camera_io_r(mux_device->ctl_base);
+	if (*mode == MODE_DUAL) {
+		msm_camera_io_w(val | 0x3, mux_device->ctl_base);
+	} else if (*mode == MODE_L) {
+		msm_camera_io_w(((val | 0x2) & ~(0x1)), mux_device->ctl_base);
+		val = msm_camera_io_r(mux_device->ctl_base);
+		CDBG("the camio mode config left value is %d\n", val);
+	} else {
+		msm_camera_io_w(((val | 0x1) & ~(0x2)), mux_device->ctl_base);
+		val = msm_camera_io_r(mux_device->ctl_base);
+		CDBG("the camio mode config right value is %d\n", val);
+	}
+	return 0;
+}
+
+static int msm_i2c_mux_init(struct i2c_mux_device *mux_device)
+{
+	int rc = 0, val = 0;
+	if (mux_device->use_count == 0) {
+		mux_device->ctl_base = ioremap(mux_device->ctl_mem->start,
+			resource_size(mux_device->ctl_mem));
+		if (!mux_device->ctl_base) {
+			rc = -ENOMEM;
+			return rc;
+		}
+		mux_device->rw_base = ioremap(mux_device->rw_mem->start,
+			resource_size(mux_device->rw_mem));
+		if (!mux_device->rw_base) {
+			rc = -ENOMEM;
+			iounmap(mux_device->ctl_base);
+			return rc;
+		}
+		val = msm_camera_io_r(mux_device->rw_base);
+		msm_camera_io_w((val | 0x200), mux_device->rw_base);
+	}
+	mux_device->use_count++;
+	return 0;
+};
+
+static int msm_i2c_mux_release(struct i2c_mux_device *mux_device)
+{
+	int val = 0;
+	mux_device->use_count--;
+	if (mux_device->use_count == 0) {
+		val = msm_camera_io_r(mux_device->rw_base);
+		msm_camera_io_w((val & ~0x200), mux_device->rw_base);
+		iounmap(mux_device->rw_base);
+		iounmap(mux_device->ctl_base);
+	}
+	return 0;
+}
+
+static long msm_i2c_mux_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct i2c_mux_device *mux_device;
+	int rc = 0;
+	mux_device = v4l2_get_subdevdata(sd);
+	if (mux_device == NULL) {
+		rc = -ENOMEM;
+		return rc;
+	}
+	mutex_lock(&mux_device->mutex);
+	switch (cmd) {
+	case VIDIOC_MSM_I2C_MUX_CFG:
+		rc = msm_i2c_mux_config(mux_device, (uint8_t *) arg);
+		break;
+	case VIDIOC_MSM_I2C_MUX_INIT:
+		rc = msm_i2c_mux_init(mux_device);
+		break;
+	case VIDIOC_MSM_I2C_MUX_RELEASE:
+		rc = msm_i2c_mux_release(mux_device);
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+	}
+	mutex_unlock(&mux_device->mutex);
+	return rc;
+}
+
+static struct v4l2_subdev_core_ops msm_i2c_mux_subdev_core_ops = {
+	.ioctl = &msm_i2c_mux_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_i2c_mux_subdev_ops = {
+	.core = &msm_i2c_mux_subdev_core_ops,
+};
+
+static int __devinit i2c_mux_probe(struct platform_device *pdev)
+{
+	struct i2c_mux_device *mux_device;
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	mux_device = kzalloc(sizeof(struct i2c_mux_device), GFP_KERNEL);
+	if (!mux_device) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&mux_device->subdev, &msm_i2c_mux_subdev_ops);
+	v4l2_set_subdevdata(&mux_device->subdev, mux_device);
+	platform_set_drvdata(pdev, &mux_device->subdev);
+	mutex_init(&mux_device->mutex);
+
+	mux_device->ctl_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "i2c_mux_ctl");
+	if (!mux_device->ctl_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->ctl_io = request_mem_region(mux_device->ctl_mem->start,
+		resource_size(mux_device->ctl_mem), pdev->name);
+	if (!mux_device->ctl_io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->rw_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "i2c_mux_rw");
+	if (!mux_device->rw_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->rw_io = request_mem_region(mux_device->rw_mem->start,
+		resource_size(mux_device->rw_mem), pdev->name);
+	if (!mux_device->rw_io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->pdev = pdev;
+	return 0;
+
+i2c_mux_no_resource:
+	mutex_destroy(&mux_device->mutex);
+	kfree(mux_device);
+	return 0;
+}
+
+static struct platform_driver i2c_mux_driver = {
+	.probe = i2c_mux_probe,
+	.driver = {
+		.name = MSM_I2C_MUX_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_camera_i2c_mux_init_module(void)
+{
+	return platform_driver_register(&i2c_mux_driver);
+}
+
+static void __exit msm_camera_i2c_mux_exit_module(void)
+{
+	platform_driver_unregister(&i2c_mux_driver);
+}
+
+module_init(msm_camera_i2c_mux_init_module);
+module_exit(msm_camera_i2c_mux_exit_module);
+MODULE_DESCRIPTION("MSM Camera I2C mux driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.h b/drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.h
new file mode 100644
index 0000000..30f908b
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/io/msm_camera_i2c_mux.h
@@ -0,0 +1,46 @@
+/* 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 MSM_I2C_MUX_H
+#define MSM_I2C_MUX_H
+
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct i2c_mux_device {
+	struct platform_device *pdev;
+	struct v4l2_subdev subdev;
+	struct resource *ctl_mem;
+	struct resource *ctl_io;
+	void __iomem *ctl_base;
+	struct resource *rw_mem;
+	struct resource *rw_io;
+	void __iomem *rw_base;
+	struct mutex mutex;
+	unsigned use_count;
+};
+
+struct i2c_mux_cfg_params {
+	struct v4l2_subdev *subdev;
+	void *parms;
+};
+
+#define VIDIOC_MSM_I2C_MUX_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct i2c_mux_cfg_params)
+
+#define VIDIOC_MSM_I2C_MUX_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 14, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_I2C_MUX_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct v4l2_subdev*)
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_io_util.c b/drivers/media/video/msmb/sensor/io/msm_camera_io_util.c
new file mode 100644
index 0000000..0f41a68
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/io/msm_camera_io_util.c
@@ -0,0 +1,523 @@
+/* Copyright (c) 2011-2013, The Linux Foundataion. All rights reserved.
+ *
+ * This 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/clk.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <mach/camera2.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_bus.h>
+#include "msm_camera_io_util.h"
+
+#define BUFF_SIZE_128 128
+
+#define CONFIG_MSMB_CAMERA_DEBUG
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+void msm_camera_io_w(u32 data, void __iomem *addr)
+{
+	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+	writel_relaxed((data), (addr));
+}
+
+void msm_camera_io_w_mb(u32 data, void __iomem *addr)
+{
+	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+	wmb();
+	writel_relaxed((data), (addr));
+	wmb();
+}
+
+u32 msm_camera_io_r(void __iomem *addr)
+{
+	uint32_t data = readl_relaxed(addr);
+	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+	return data;
+}
+
+u32 msm_camera_io_r_mb(void __iomem *addr)
+{
+	uint32_t data;
+	rmb();
+	data = readl_relaxed(addr);
+	rmb();
+	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+	return data;
+}
+
+void msm_camera_io_memcpy_toio(void __iomem *dest_addr,
+	void __iomem *src_addr, u32 len)
+{
+	int i;
+	u32 *d = (u32 *) dest_addr;
+	u32 *s = (u32 *) src_addr;
+
+	for (i = 0; i < len; i++)
+		writel_relaxed(*s++, d++);
+}
+
+void msm_camera_io_dump(void __iomem *addr, int size)
+{
+	char line_str[BUFF_SIZE_128], *p_str;
+	int i;
+	u32 *p = (u32 *) addr;
+	u32 data;
+	CDBG("%s: %p %d\n", __func__, addr, size);
+	line_str[0] = '\0';
+	p_str = line_str;
+	for (i = 0; i < size/4; i++) {
+		if (i % 4 == 0) {
+			snprintf(p_str, 12, "%08x: ", (u32) p);
+			p_str += 10;
+		}
+		data = readl_relaxed(p++);
+		snprintf(p_str, 12, "%08x ", data);
+		p_str += 9;
+		if ((i + 1) % 4 == 0) {
+			CDBG("%s\n", line_str);
+			line_str[0] = '\0';
+			p_str = line_str;
+		}
+	}
+	if (line_str[0] != '\0')
+		CDBG("%s\n", line_str);
+}
+
+void msm_camera_io_memcpy(void __iomem *dest_addr,
+	void __iomem *src_addr, u32 len)
+{
+	CDBG("%s: %p %p %d\n", __func__, dest_addr, src_addr, len);
+	msm_camera_io_memcpy_toio(dest_addr, src_addr, len / 4);
+	msm_camera_io_dump(dest_addr, len);
+}
+
+int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct clk **clk_ptr, int num_clk, int enable)
+{
+	int i;
+	int rc = 0;
+	if (enable) {
+		for (i = 0; i < num_clk; i++) {
+			CDBG("%s enable %s\n", __func__,
+				clk_info[i].clk_name);
+			clk_ptr[i] = clk_get(dev, clk_info[i].clk_name);
+			if (IS_ERR(clk_ptr[i])) {
+				pr_err("%s get failed\n", clk_info[i].clk_name);
+				rc = PTR_ERR(clk_ptr[i]);
+				goto cam_clk_get_err;
+			}
+			if (clk_info[i].clk_rate >= 0) {
+				rc = clk_set_rate(clk_ptr[i],
+							clk_info[i].clk_rate);
+				if (rc < 0) {
+					pr_err("%s set failed\n",
+						   clk_info[i].clk_name);
+					goto cam_clk_set_err;
+				}
+			}
+			rc = clk_prepare(clk_ptr[i]);
+			if (rc < 0) {
+				pr_err("%s prepare failed\n",
+					   clk_info[i].clk_name);
+				goto cam_clk_prepare_err;
+			}
+
+			rc = clk_enable(clk_ptr[i]);
+			if (rc < 0) {
+				pr_err("%s enable failed\n",
+					   clk_info[i].clk_name);
+				goto cam_clk_enable_err;
+			}
+			if (clk_info[i].delay > 20) {
+				msleep(clk_info[i].delay);
+			} else if (clk_info[i].delay) {
+				usleep_range(clk_info[i].delay * 1000,
+					(clk_info[i].delay * 1000) + 1000);
+			}
+		}
+	} else {
+		for (i = num_clk - 1; i >= 0; i--) {
+			if (clk_ptr[i] != NULL) {
+				CDBG("%s disable %s\n", __func__,
+					clk_info[i].clk_name);
+				clk_disable(clk_ptr[i]);
+				clk_unprepare(clk_ptr[i]);
+				clk_put(clk_ptr[i]);
+			}
+		}
+	}
+	return rc;
+
+
+cam_clk_enable_err:
+	clk_unprepare(clk_ptr[i]);
+cam_clk_prepare_err:
+cam_clk_set_err:
+	clk_put(clk_ptr[i]);
+cam_clk_get_err:
+	for (i--; i >= 0; i--) {
+		if (clk_ptr[i] != NULL) {
+			clk_disable(clk_ptr[i]);
+			clk_unprepare(clk_ptr[i]);
+			clk_put(clk_ptr[i]);
+		}
+	}
+	return rc;
+}
+
+int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int config)
+{
+	int i = 0, j = 0;
+	int rc = 0;
+	struct camera_vreg_t *curr_vreg;
+
+	if (num_vreg_seq > num_vreg) {
+		pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	if (!num_vreg_seq)
+		num_vreg_seq = num_vreg;
+
+	if (config) {
+		for (i = 0; i < num_vreg_seq; i++) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			curr_vreg = &cam_vreg[j];
+			reg_ptr[j] = regulator_get(dev,
+				curr_vreg->reg_name);
+			if (IS_ERR(reg_ptr[j])) {
+				pr_err("%s: %s get failed\n",
+					 __func__,
+					 curr_vreg->reg_name);
+				reg_ptr[j] = NULL;
+				goto vreg_get_fail;
+			}
+			if (curr_vreg->type == REG_LDO) {
+				rc = regulator_set_voltage(
+					reg_ptr[j],
+					curr_vreg->min_voltage,
+					curr_vreg->max_voltage);
+				if (rc < 0) {
+					pr_err("%s: %s set voltage failed\n",
+						__func__,
+						curr_vreg->reg_name);
+					goto vreg_set_voltage_fail;
+				}
+				if (curr_vreg->op_mode >= 0) {
+					rc = regulator_set_optimum_mode(
+						reg_ptr[j],
+						curr_vreg->op_mode);
+					if (rc < 0) {
+						pr_err(
+						"%s:%s set optimum mode fail\n",
+						__func__,
+						curr_vreg->reg_name);
+						goto vreg_set_opt_mode_fail;
+					}
+				}
+			}
+		}
+	} else {
+		for (i = num_vreg_seq-1; i >= 0; i--) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			curr_vreg = &cam_vreg[j];
+			if (reg_ptr[j]) {
+				if (curr_vreg->type == REG_LDO) {
+					if (curr_vreg->op_mode >= 0) {
+						regulator_set_optimum_mode(
+							reg_ptr[j], 0);
+					}
+					regulator_set_voltage(
+						reg_ptr[j], 0, curr_vreg->
+						max_voltage);
+				}
+				regulator_put(reg_ptr[j]);
+				reg_ptr[j] = NULL;
+			}
+		}
+	}
+	return 0;
+
+vreg_unconfig:
+if (curr_vreg->type == REG_LDO)
+	regulator_set_optimum_mode(reg_ptr[j], 0);
+
+vreg_set_opt_mode_fail:
+if (curr_vreg->type == REG_LDO)
+	regulator_set_voltage(reg_ptr[j], 0,
+		curr_vreg->max_voltage);
+
+vreg_set_voltage_fail:
+	regulator_put(reg_ptr[j]);
+	reg_ptr[j] = NULL;
+
+vreg_get_fail:
+	for (i--; i >= 0; i--) {
+		if (vreg_seq) {
+			j = vreg_seq[i];
+			if (j >= num_vreg)
+				continue;
+		} else
+			j = i;
+		curr_vreg = &cam_vreg[j];
+		goto vreg_unconfig;
+	}
+	return -ENODEV;
+}
+
+int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int enable)
+{
+	int i = 0, j = 0, rc = 0;
+
+	if (num_vreg_seq > num_vreg) {
+		pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	if (!num_vreg_seq)
+		num_vreg_seq = num_vreg;
+
+	if (enable) {
+		for (i = 0; i < num_vreg_seq; i++) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			if (IS_ERR(reg_ptr[j])) {
+				pr_err("%s: %s null regulator\n",
+					__func__, cam_vreg[j].reg_name);
+				goto disable_vreg;
+			}
+			rc = regulator_enable(reg_ptr[j]);
+			if (rc < 0) {
+				pr_err("%s: %s enable failed\n",
+					__func__, cam_vreg[j].reg_name);
+				goto disable_vreg;
+			}
+			if (cam_vreg[j].delay > 20)
+				msleep(cam_vreg[j].delay);
+			else if (cam_vreg[j].delay)
+				usleep_range(cam_vreg[j].delay * 1000,
+					(cam_vreg[j].delay * 1000) + 1000);
+		}
+	} else {
+		for (i = num_vreg_seq-1; i >= 0; i--) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			regulator_disable(reg_ptr[j]);
+			if (cam_vreg[j].delay > 20)
+				msleep(cam_vreg[j].delay);
+			else if (cam_vreg[j].delay)
+				usleep_range(cam_vreg[j].delay * 1000,
+					(cam_vreg[j].delay * 1000) + 1000);
+		}
+	}
+	return rc;
+disable_vreg:
+	for (i--; i >= 0; i--) {
+		if (vreg_seq) {
+			j = vreg_seq[i];
+			if (j >= num_vreg)
+				continue;
+		} else
+			j = i;
+		regulator_disable(reg_ptr[j]);
+		if (cam_vreg[j].delay > 20)
+			msleep(cam_vreg[j].delay);
+		else if (cam_vreg[j].delay)
+			usleep_range(cam_vreg[j].delay * 1000,
+				(cam_vreg[j].delay * 1000) + 1000);
+	}
+	return rc;
+}
+
+void msm_camera_bus_scale_cfg(uint32_t bus_perf_client,
+		enum msm_bus_perf_setting perf_setting)
+{
+	int rc = 0;
+	if (!bus_perf_client) {
+		pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+		return;
+	}
+
+	switch (perf_setting) {
+	case S_EXIT:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 1);
+		msm_bus_scale_unregister_client(bus_perf_client);
+		break;
+	case S_PREVIEW:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 1);
+		break;
+	case S_VIDEO:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 2);
+		break;
+	case S_CAPTURE:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 3);
+		break;
+	case S_ZSL:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 4);
+		break;
+	case S_LIVESHOT:
+		rc = msm_bus_scale_client_update_request(bus_perf_client, 5);
+		break;
+	case S_DEFAULT:
+		break;
+	default:
+		pr_warning("%s: INVALID CASE\n", __func__);
+	}
+}
+
+int msm_camera_set_gpio_table(struct msm_gpio_set_tbl *gpio_tbl,
+	uint8_t gpio_tbl_size, int gpio_en)
+{
+	int rc = 0, i;
+
+	if (gpio_en) {
+		for (i = 0; i < gpio_tbl_size; i++) {
+			gpio_set_value_cansleep(gpio_tbl[i].gpio,
+				gpio_tbl[i].flags);
+			usleep_range(gpio_tbl[i].delay,
+				gpio_tbl[i].delay + 1000);
+		}
+	} else {
+		for (i = gpio_tbl_size - 1; i >= 0; i--) {
+			if (gpio_tbl[i].flags)
+				gpio_set_value_cansleep(gpio_tbl[i].gpio,
+					GPIOF_OUT_INIT_LOW);
+		}
+	}
+	return rc;
+}
+
+int msm_camera_config_single_vreg(struct device *dev,
+	struct camera_vreg_t *cam_vreg, struct regulator **reg_ptr, int config)
+{
+	int rc = 0;
+	if (config) {
+		CDBG("%s enable %s\n", __func__, cam_vreg->reg_name);
+		*reg_ptr = regulator_get(dev, cam_vreg->reg_name);
+		if (IS_ERR(*reg_ptr)) {
+			pr_err("%s: %s get failed\n", __func__,
+				cam_vreg->reg_name);
+			*reg_ptr = NULL;
+			goto vreg_get_fail;
+		}
+		if (cam_vreg->type == REG_LDO) {
+			rc = regulator_set_voltage(
+				*reg_ptr, cam_vreg->min_voltage,
+				cam_vreg->max_voltage);
+			if (rc < 0) {
+				pr_err("%s: %s set voltage failed\n",
+					__func__, cam_vreg->reg_name);
+				goto vreg_set_voltage_fail;
+			}
+			if (cam_vreg->op_mode >= 0) {
+				rc = regulator_set_optimum_mode(*reg_ptr,
+					cam_vreg->op_mode);
+				if (rc < 0) {
+					pr_err(
+					"%s: %s set optimum mode failed\n",
+					__func__, cam_vreg->reg_name);
+					goto vreg_set_opt_mode_fail;
+				}
+			}
+		}
+		rc = regulator_enable(*reg_ptr);
+		if (rc < 0) {
+			pr_err("%s: %s enable failed\n",
+				__func__, cam_vreg->reg_name);
+			goto vreg_unconfig;
+		}
+	} else {
+		if (*reg_ptr) {
+			CDBG("%s disable %s\n", __func__, cam_vreg->reg_name);
+			regulator_disable(*reg_ptr);
+			if (cam_vreg->type == REG_LDO) {
+				if (cam_vreg->op_mode >= 0)
+					regulator_set_optimum_mode(*reg_ptr, 0);
+				regulator_set_voltage(
+					*reg_ptr, 0, cam_vreg->max_voltage);
+			}
+			regulator_put(*reg_ptr);
+			*reg_ptr = NULL;
+		}
+	}
+	return 0;
+
+vreg_unconfig:
+if (cam_vreg->type == REG_LDO)
+	regulator_set_optimum_mode(*reg_ptr, 0);
+
+vreg_set_opt_mode_fail:
+if (cam_vreg->type == REG_LDO)
+	regulator_set_voltage(*reg_ptr, 0, cam_vreg->max_voltage);
+
+vreg_set_voltage_fail:
+	regulator_put(*reg_ptr);
+	*reg_ptr = NULL;
+
+vreg_get_fail:
+	return -ENODEV;
+}
+
+int msm_camera_request_gpio_table(struct gpio *gpio_tbl, uint8_t size,
+	int gpio_en)
+{
+	int rc = 0, i = 0;
+
+	if (!gpio_tbl || !size) {
+		pr_err("%s:%d invalid gpio_tbl %p / size %d\n", __func__,
+			__LINE__, gpio_tbl, size);
+		return -EINVAL;
+	}
+	for (i = 0; i < size; i++) {
+		CDBG("%s:%d i %d, gpio %d dir %ld\n", __func__, __LINE__, i,
+			gpio_tbl[i].gpio, gpio_tbl[i].flags);
+	}
+	if (gpio_en) {
+		rc = gpio_request_array(gpio_tbl, size);
+		if (rc < 0) {
+			pr_err("%s:%d camera gpio request failed\n", __func__,
+				__LINE__);
+			return rc;
+		}
+	} else {
+		gpio_free_array(gpio_tbl, size);
+	}
+	return rc;
+}
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_io_util.h b/drivers/media/video/msmb/sensor/io/msm_camera_io_util.h
new file mode 100644
index 0000000..499a045
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/io/msm_camera_io_util.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2011-2013, The Linux Foundataion. All rights reserved.
+ *
+ * This 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_CAMERA_IO_UTIL_H
+#define __MSM_CAMERA_IO_UTIL_H
+
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <mach/camera2.h>
+#include <media/msm_cam_sensor.h>
+
+void msm_camera_io_w(u32 data, void __iomem *addr);
+void msm_camera_io_w_mb(u32 data, void __iomem *addr);
+u32 msm_camera_io_r(void __iomem *addr);
+u32 msm_camera_io_r_mb(void __iomem *addr);
+void msm_camera_io_dump(void __iomem *addr, int size);
+void msm_camera_io_memcpy(void __iomem *dest_addr,
+		void __iomem *src_addr, u32 len);
+
+int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct clk **clk_ptr, int num_clk, int enable);
+
+int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int config);
+int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int enable);
+
+void msm_camera_bus_scale_cfg(uint32_t bus_perf_client,
+		enum msm_bus_perf_setting perf_setting);
+
+int msm_camera_set_gpio_table(struct msm_gpio_set_tbl *gpio_tbl,
+	uint8_t gpio_tbl_size, int gpio_en);
+
+void msm_camera_config_single_gpio(uint16_t gpio, unsigned long flags,
+	int gpio_en);
+
+int msm_camera_config_single_vreg(struct device *dev,
+	struct camera_vreg_t *cam_vreg, struct regulator **reg_ptr, int config);
+
+int msm_camera_request_gpio_table(struct gpio *gpio_tbl, uint8_t size,
+	int gpio_en);
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/io/msm_camera_qup_i2c.c b/drivers/media/video/msmb/sensor/io/msm_camera_qup_i2c.c
new file mode 100644
index 0000000..d2cfbff
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/io/msm_camera_qup_i2c.c
@@ -0,0 +1,333 @@
+/* Copyright (c) 2011, 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/camera2.h>
+#include "msm_camera_i2c.h"
+
+#define CONFIG_MSMB_CAMERA_DEBUG
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#define S_I2C_DBG(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#define S_I2C_DBG(fmt, args...) do { } while (0)
+#endif
+
+static int32_t msm_camera_qup_i2c_rxdata(
+	struct msm_camera_i2c_client *dev_client, unsigned char *rxdata,
+	int data_length)
+{
+	int32_t rc = 0;
+	uint16_t saddr = dev_client->client->addr >> 1;
+	struct i2c_msg msgs[] = {
+		{
+			.addr  = saddr,
+			.flags = 0,
+			.len   = dev_client->addr_type,
+			.buf   = rxdata,
+		},
+		{
+			.addr  = saddr,
+			.flags = I2C_M_RD,
+			.len   = data_length,
+			.buf   = rxdata,
+		},
+	};
+	rc = i2c_transfer(dev_client->client->adapter, msgs, 2);
+	if (rc < 0)
+		S_I2C_DBG("msm_camera_qup_i2c_rxdata failed 0x%x\n", saddr);
+	return rc;
+}
+
+static int32_t msm_camera_qup_i2c_txdata(
+	struct msm_camera_i2c_client *dev_client, unsigned char *txdata,
+	int length)
+{
+	int32_t rc = 0;
+	uint16_t saddr = dev_client->client->addr >> 1;
+	struct i2c_msg msg[] = {
+		{
+			.addr = saddr,
+			.flags = 0,
+			.len = length,
+			.buf = txdata,
+		 },
+	};
+	rc = i2c_transfer(dev_client->client->adapter, msg, 1);
+	if (rc < 0)
+		S_I2C_DBG("msm_camera_qup_i2c_txdata faild 0x%x\n", saddr);
+	return 0;
+}
+
+int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t *data,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[client->addr_type+data_type];
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	if (client->addr_type == MSM_CAMERA_I2C_BYTE_ADDR) {
+		buf[0] = addr;
+	} else if (client->addr_type == MSM_CAMERA_I2C_WORD_ADDR) {
+		buf[0] = addr >> BITS_PER_BYTE;
+		buf[1] = addr;
+	}
+	rc = msm_camera_qup_i2c_rxdata(client, buf, data_type);
+	if (rc < 0) {
+		S_I2C_DBG("%s fail\n", __func__);
+		return rc;
+	}
+
+	if (data_type == MSM_CAMERA_I2C_BYTE_DATA)
+		*data = buf[0];
+	else
+		*data = buf[0] << 8 | buf[1];
+
+	S_I2C_DBG("%s addr = 0x%x data: 0x%x\n", __func__, addr, *data);
+	return rc;
+}
+
+int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint8_t *data, uint16_t num_byte)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[client->addr_type+num_byte];
+	int i;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| num_byte == 0)
+		return rc;
+
+	if (client->addr_type == MSM_CAMERA_I2C_BYTE_ADDR) {
+		buf[0] = addr;
+	} else if (client->addr_type == MSM_CAMERA_I2C_WORD_ADDR) {
+		buf[0] = addr >> BITS_PER_BYTE;
+		buf[1] = addr;
+	}
+	rc = msm_camera_qup_i2c_rxdata(client, buf, num_byte);
+	if (rc < 0) {
+		S_I2C_DBG("%s fail\n", __func__);
+		return rc;
+	}
+
+	S_I2C_DBG("%s addr = 0x%x", __func__, addr);
+	for (i = 0; i < num_byte; i++) {
+		data[i] = buf[i];
+		S_I2C_DBG("Byte %d: 0x%x\n", i, buf[i]);
+		S_I2C_DBG("Data: 0x%x\n", data[i]);
+	}
+	return rc;
+}
+
+int32_t msm_camera_qup_i2c_write(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint16_t data,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[client->addr_type+data_type];
+	uint8_t len = 0;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	S_I2C_DBG("%s reg addr = 0x%x data type: %d\n",
+			  __func__, addr, data_type);
+	if (client->addr_type == MSM_CAMERA_I2C_BYTE_ADDR) {
+		buf[0] = addr;
+		S_I2C_DBG("%s byte %d: 0x%x\n", __func__,
+			len, buf[len]);
+		len = 1;
+	} else if (client->addr_type == MSM_CAMERA_I2C_WORD_ADDR) {
+		buf[0] = addr >> BITS_PER_BYTE;
+		buf[1] = addr;
+		S_I2C_DBG("%s byte %d: 0x%x\n", __func__,
+			len, buf[len]);
+		S_I2C_DBG("%s byte %d: 0x%x\n", __func__,
+			len+1, buf[len+1]);
+		len = 2;
+	}
+	S_I2C_DBG("Data: 0x%x\n", data);
+	if (data_type == MSM_CAMERA_I2C_BYTE_DATA) {
+		buf[len] = data;
+		S_I2C_DBG("Byte %d: 0x%x\n", len, buf[len]);
+		len += 1;
+	} else if (data_type == MSM_CAMERA_I2C_WORD_DATA) {
+		buf[len] = data >> BITS_PER_BYTE;
+		buf[len+1] = data;
+		S_I2C_DBG("Byte %d: 0x%x\n", len, buf[len]);
+		S_I2C_DBG("Byte %d: 0x%x\n", len+1, buf[len+1]);
+		len += 2;
+	}
+	rc = msm_camera_qup_i2c_txdata(client, buf, len);
+	if (rc < 0)
+		S_I2C_DBG("%s fail\n", __func__);
+	return rc;
+}
+
+int32_t msm_camera_qup_i2c_write_seq(struct msm_camera_i2c_client *client,
+	uint16_t addr, uint8_t *data, uint16_t num_byte)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[client->addr_type+num_byte];
+	uint8_t len = 0, i = 0;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| num_byte == 0)
+		return rc;
+
+	S_I2C_DBG("%s reg addr = 0x%x num bytes: %d\n",
+			  __func__, addr, num_byte);
+	if (client->addr_type == MSM_CAMERA_I2C_BYTE_ADDR) {
+		buf[0] = addr;
+		S_I2C_DBG("%s byte %d: 0x%x\n", __func__,
+			len, buf[len]);
+		len = 1;
+	} else if (client->addr_type == MSM_CAMERA_I2C_WORD_ADDR) {
+		buf[0] = addr >> BITS_PER_BYTE;
+		buf[1] = addr;
+		S_I2C_DBG("%s byte %d: 0x%x\n", __func__,
+			len, buf[len]);
+		S_I2C_DBG("%s byte %d: 0x%x\n", __func__,
+			len+1, buf[len+1]);
+		len = 2;
+	}
+	for (i = 0; i < num_byte; i++) {
+		buf[i+len] = data[i];
+		S_I2C_DBG("Byte %d: 0x%x\n", i+len, buf[i+len]);
+		S_I2C_DBG("Data: 0x%x\n", data[i]);
+	}
+	rc = msm_camera_qup_i2c_txdata(client, buf, len+num_byte);
+	if (rc < 0)
+		S_I2C_DBG("%s fail\n", __func__);
+	return rc;
+}
+
+int32_t msm_camera_qup_i2c_write_table(struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_setting *write_setting)
+{
+	int i;
+	int32_t rc = -EFAULT;
+	struct msm_camera_i2c_reg_array *reg_setting;
+	uint16_t client_addr_type;
+
+	if (!client || !write_setting)
+		return rc;
+
+	if ((write_setting->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& write_setting->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (write_setting->data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& write_setting->data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	reg_setting = write_setting->reg_setting;
+	client_addr_type = client->addr_type;
+	client->addr_type = write_setting->addr_type;
+
+	for (i = 0; i < write_setting->size; i++) {
+		CDBG("%s addr %x data %x\n", __func__,
+			reg_setting->reg_addr, reg_setting->reg_data);
+
+		rc = msm_camera_qup_i2c_write(client, reg_setting->reg_addr,
+			reg_setting->reg_data, write_setting->data_type);
+		if (rc < 0)
+			break;
+		reg_setting++;
+	}
+	if (write_setting->delay > 20)
+		msleep(write_setting->delay);
+	else if (write_setting->delay)
+		usleep_range(write_setting->delay * 1000, (write_setting->delay
+			* 1000) + 1000);
+
+	client->addr_type = client_addr_type;
+	return rc;
+}
+
+int32_t msm_camera_qup_i2c_write_seq_table(struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_seq_reg_setting *write_setting)
+{
+	int i;
+	int32_t rc = -EFAULT;
+	struct msm_camera_i2c_seq_reg_array *reg_setting;
+	uint16_t client_addr_type;
+
+	if (!client || !write_setting)
+		return rc;
+
+	if ((write_setting->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& write_setting->addr_type != MSM_CAMERA_I2C_WORD_ADDR)) {
+		pr_err("%s Invalide addr type %d\n", __func__,
+			write_setting->addr_type);
+		return rc;
+	}
+
+	reg_setting = write_setting->reg_setting;
+	client_addr_type = client->addr_type;
+	client->addr_type = write_setting->addr_type;
+
+	for (i = 0; i < write_setting->size; i++) {
+		rc = msm_camera_qup_i2c_write_seq(client, reg_setting->reg_addr,
+			reg_setting->reg_data, reg_setting->reg_data_size);
+		if (rc < 0)
+			break;
+		reg_setting++;
+	}
+	if (write_setting->delay > 20)
+		msleep(write_setting->delay);
+	else if (write_setting->delay)
+		usleep_range(write_setting->delay * 1000, (write_setting->delay
+			* 1000) + 1000);
+
+	client->addr_type = client_addr_type;
+	return rc;
+}
+
+int32_t msm_camera_qup_i2c_write_table_w_microdelay(
+	struct msm_camera_i2c_client *client,
+	struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int i;
+	int32_t rc = -EFAULT;
+
+	if (!client || !reg_tbl)
+		return rc;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+		|| (data_type != MSM_CAMERA_I2C_BYTE_DATA
+		&& data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	for (i = 0; i < size; i++) {
+		rc = msm_camera_qup_i2c_write(client, reg_tbl->reg_addr,
+			reg_tbl->reg_data, data_type);
+		if (rc < 0)
+			break;
+		if (reg_tbl->delay)
+			usleep_range(reg_tbl->delay, reg_tbl->delay + 1000);
+		reg_tbl++;
+	}
+	return rc;
+}
diff --git a/drivers/media/video/msmb/sensor/msm_sensor.c b/drivers/media/video/msmb/sensor/msm_sensor.c
new file mode 100644
index 0000000..1f54951
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/msm_sensor.c
@@ -0,0 +1,1537 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <mach/gpiomux.h>
+#include "msm_sensor.h"
+#include "msm_sd.h"
+#include "camera.h"
+#include "msm_cci.h"
+#include "msm_camera_io_util.h"
+#include "msm_camera_i2c_mux.h"
+
+#undef CDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+static int32_t msm_sensor_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_INIT, NULL);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_CFG, (void *)&i2c_conf->i2c_mux_mode);
+	return 0;
+}
+
+static int32_t msm_sensor_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+				VIDIOC_MSM_I2C_MUX_RELEASE, NULL);
+	return 0;
+}
+
+static int32_t msm_sensor_get_sub_module_index(struct device_node *of_node,
+	struct  msm_camera_sensor_board_info *sensordata)
+{
+	int32_t rc = 0, i = 0;
+	uint32_t val = 0, count = 0;
+	uint32_t *val_array = NULL;
+
+	sensordata->sensor_info = kzalloc(sizeof(struct msm_sensor_info_t),
+		GFP_KERNEL);
+	if (!sensordata->sensor_info) {
+		pr_err("%s:%d failed\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	for (i = 0; i < SUB_MODULE_MAX; i++)
+		sensordata->sensor_info->subdev_id[i] = -1;
+
+	if (of_property_read_bool(of_node, "qcom,actuator-sd-index") ==
+		true) {
+		rc = of_property_read_u32(of_node, "qcom,actuator-sd-index",
+			&val);
+		CDBG("%s qcom,actuator-sd-index %d, rc %d\n", __func__, val,
+			rc);
+		if (rc < 0) {
+			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
+			return rc;
+		}
+		sensordata->sensor_info->subdev_id[SUB_MODULE_ACTUATOR] = val;
+	}
+
+	if (of_property_read_bool(of_node, "qcom,eeprom-sd-index") ==
+		true) {
+		rc = of_property_read_u32(of_node, "qcom,eeprom-sd-index",
+			&val);
+		CDBG("%s qcom,eeprom-sd-index %d, rc %d\n", __func__, val, rc);
+		if (rc < 0) {
+			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
+			return rc;
+		}
+		sensordata->sensor_info->subdev_id[SUB_MODULE_EEPROM] = val;
+	}
+
+	if (of_property_read_bool(of_node, "qcom,led-flash-sd-index") ==
+		true) {
+		rc = of_property_read_u32(of_node, "qcom,led-flash-sd-index",
+			&val);
+		CDBG("%s qcom,led-flash-sd-index %d, rc %d\n", __func__, val,
+			rc);
+		if (rc < 0) {
+			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
+			return rc;
+		}
+		sensordata->sensor_info->subdev_id[SUB_MODULE_LED_FLASH] = val;
+	}
+
+	if (of_property_read_bool(of_node, "qcom,strobe-flash-sd-index") ==
+		true) {
+		rc = of_property_read_u32(of_node, "qcom,strobe-flash-sd-index",
+			&val);
+		CDBG("%s qcom,strobe-flash-sd-index %d, rc %d\n", __func__,
+			val, rc);
+		if (rc < 0) {
+			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
+			return rc;
+		}
+		sensordata->sensor_info->subdev_id[SUB_MODULE_STROBE_FLASH] =
+			val;
+	}
+
+	if (of_get_property(of_node, "qcom,csiphy-sd-index", &count)) {
+		count /= sizeof(uint32_t);
+		if (count > 2) {
+			pr_err("%s qcom,csiphy-sd-index count %d > 2\n",
+				__func__, count);
+			return -EINVAL;
+		}
+		val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+		if (!val_array) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			return -ENOMEM;
+		}
+
+		rc = of_property_read_u32_array(of_node, "qcom,csiphy-sd-index",
+			val_array, count);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			kfree(val_array);
+			return rc;
+		}
+		for (i = 0; i < count; i++) {
+			sensordata->sensor_info->subdev_id
+				[SUB_MODULE_CSIPHY + i] = val_array[i];
+			CDBG("%s csiphy_core[%d] = %d\n",
+				__func__, i, val_array[i]);
+		}
+		kfree(val_array);
+	} else {
+		pr_err("%s:%d qcom,csiphy-sd-index not present\n", __func__,
+			__LINE__);
+		return -EINVAL;
+	}
+
+	if (of_get_property(of_node, "qcom,csid-sd-index", &count)) {
+		count /= sizeof(uint32_t);
+		if (count > 2) {
+			pr_err("%s qcom,csid-sd-index count %d > 2\n",
+				__func__, count);
+			return -EINVAL;
+		}
+		val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+		if (!val_array) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			return -ENOMEM;
+		}
+
+		rc = of_property_read_u32_array(of_node, "qcom,csid-sd-index",
+			val_array, count);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			kfree(val_array);
+			return rc;
+		}
+		for (i = 0; i < count; i++) {
+			sensordata->sensor_info->subdev_id
+				[SUB_MODULE_CSID + i] = val_array[i];
+			CDBG("%s csid_core[%d] = %d\n",
+				__func__, i, val_array[i]);
+		}
+		kfree(val_array);
+	} else {
+		pr_err("%s:%d qcom,csid-sd-index not present\n", __func__,
+			__LINE__);
+		return -EINVAL;
+	}
+	return rc;
+}
+
+static int32_t msm_sensor_get_dt_csi_data(struct device_node *of_node,
+	struct  msm_camera_sensor_board_info *sensordata)
+{
+	int32_t rc = 0;
+	uint32_t val = 0;
+
+	sensordata->csi_lane_params = kzalloc(
+		sizeof(struct msm_camera_csi_lane_params), GFP_KERNEL);
+	if (!sensordata->csi_lane_params) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,csi-lane-assign", &val);
+	CDBG("%s qcom,csi-lane-assign %x, rc %d\n", __func__, val, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	sensordata->csi_lane_params->csi_lane_assign = val;
+
+	rc = of_property_read_u32(of_node, "qcom,csi-lane-mask", &val);
+	CDBG("%s qcom,csi-lane-mask %x, rc %d\n", __func__, val, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	sensordata->csi_lane_params->csi_lane_mask = val;
+
+	return rc;
+ERROR2:
+	kfree(sensordata->csi_lane_params);
+ERROR1:
+	return rc;
+}
+
+static int32_t msm_sensor_get_dt_vreg_data(struct device_node *of_node,
+	struct msm_camera_sensor_board_info *sensordata)
+{
+	int32_t rc = 0, i = 0;
+	uint32_t count = 0;
+	uint32_t *vreg_array = NULL;
+
+	count = of_property_count_strings(of_node, "qcom,cam-vreg-name");
+	CDBG("%s qcom,cam-vreg-name count %d\n", __func__, count);
+
+	if (!count)
+		return 0;
+
+	sensordata->cam_vreg = kzalloc(sizeof(struct camera_vreg_t) * count,
+		GFP_KERNEL);
+	if (!sensordata->cam_vreg) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	sensordata->num_vreg = count;
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,cam-vreg-name", i,
+			&sensordata->cam_vreg[i].reg_name);
+		CDBG("%s reg_name[%d] = %s\n", __func__, i,
+			sensordata->cam_vreg[i].reg_name);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR1;
+		}
+	}
+
+	vreg_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+	if (!vreg_array) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-type",
+		vreg_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		sensordata->cam_vreg[i].type = vreg_array[i];
+		CDBG("%s cam_vreg[%d].type = %d\n", __func__, i,
+			sensordata->cam_vreg[i].type);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-min-voltage",
+		vreg_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		sensordata->cam_vreg[i].min_voltage = vreg_array[i];
+		CDBG("%s cam_vreg[%d].min_voltage = %d\n", __func__,
+			i, sensordata->cam_vreg[i].min_voltage);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-max-voltage",
+		vreg_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		sensordata->cam_vreg[i].max_voltage = vreg_array[i];
+		CDBG("%s cam_vreg[%d].max_voltage = %d\n", __func__,
+			i, sensordata->cam_vreg[i].max_voltage);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-op-mode",
+		vreg_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		sensordata->cam_vreg[i].op_mode = vreg_array[i];
+		CDBG("%s cam_vreg[%d].op_mode = %d\n", __func__, i,
+			sensordata->cam_vreg[i].op_mode);
+	}
+
+	kfree(vreg_array);
+	return rc;
+ERROR2:
+	kfree(vreg_array);
+ERROR1:
+	kfree(sensordata->cam_vreg);
+	sensordata->num_vreg = 0;
+	return rc;
+}
+
+static int32_t msm_sensor_get_dt_gpio_req_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
+{
+	int32_t rc = 0, i = 0;
+	uint32_t count = 0;
+	uint32_t *val_array = NULL;
+
+	if (!of_get_property(of_node, "qcom,gpio-req-tbl-num", &count))
+		return 0;
+
+	count /= sizeof(uint32_t);
+	if (!count) {
+		pr_err("%s qcom,gpio-req-tbl-num 0\n", __func__);
+		return 0;
+	}
+
+	val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+	if (!val_array) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	gconf->cam_gpio_req_tbl = kzalloc(sizeof(struct gpio) * count,
+		GFP_KERNEL);
+	if (!gconf->cam_gpio_req_tbl) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+	gconf->cam_gpio_req_tbl_size = count;
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-num",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		if (val_array[i] >= gpio_array_size) {
+			pr_err("%s gpio req tbl index %d invalid\n",
+				__func__, val_array[i]);
+			return -EINVAL;
+		}
+		gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]];
+		CDBG("%s cam_gpio_req_tbl[%d].gpio = %d\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].gpio);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-flags",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		gconf->cam_gpio_req_tbl[i].flags = val_array[i];
+		CDBG("%s cam_gpio_req_tbl[%d].flags = %ld\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].flags);
+	}
+
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,gpio-req-tbl-label", i,
+			&gconf->cam_gpio_req_tbl[i].label);
+		CDBG("%s cam_gpio_req_tbl[%d].label = %s\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].label);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR2;
+		}
+	}
+
+	kfree(val_array);
+	return rc;
+
+ERROR2:
+	kfree(gconf->cam_gpio_req_tbl);
+ERROR1:
+	kfree(val_array);
+	gconf->cam_gpio_req_tbl_size = 0;
+	return rc;
+}
+
+static int32_t msm_sensor_get_dt_gpio_set_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
+{
+	int32_t rc = 0, i = 0;
+	uint32_t count = 0;
+	uint32_t *val_array = NULL;
+
+	if (!of_get_property(of_node, "qcom,gpio-set-tbl-num", &count))
+		return 0;
+
+	count /= sizeof(uint32_t);
+	if (!count) {
+		pr_err("%s qcom,gpio-set-tbl-num 0\n", __func__);
+		return 0;
+	}
+
+	val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+	if (!val_array) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	gconf->cam_gpio_set_tbl = kzalloc(sizeof(struct msm_gpio_set_tbl) *
+		count, GFP_KERNEL);
+	if (!gconf->cam_gpio_set_tbl) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+	gconf->cam_gpio_set_tbl_size = count;
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-num",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		if (val_array[i] >= gpio_array_size) {
+			pr_err("%s gpio set tbl index %d invalid\n",
+				__func__, val_array[i]);
+			return -EINVAL;
+		}
+		gconf->cam_gpio_set_tbl[i].gpio = gpio_array[val_array[i]];
+		CDBG("%s cam_gpio_set_tbl[%d].gpio = %d\n", __func__, i,
+			gconf->cam_gpio_set_tbl[i].gpio);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-flags",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		gconf->cam_gpio_set_tbl[i].flags = val_array[i];
+		CDBG("%s cam_gpio_set_tbl[%d].flags = %ld\n", __func__, i,
+			gconf->cam_gpio_set_tbl[i].flags);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-delay",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		gconf->cam_gpio_set_tbl[i].delay = val_array[i];
+		CDBG("%s cam_gpio_set_tbl[%d].delay = %d\n", __func__, i,
+			gconf->cam_gpio_set_tbl[i].delay);
+	}
+
+	kfree(val_array);
+	return rc;
+
+ERROR2:
+	kfree(gconf->cam_gpio_set_tbl);
+ERROR1:
+	kfree(val_array);
+	gconf->cam_gpio_set_tbl_size = 0;
+	return rc;
+}
+
+static int32_t msm_sensor_init_gpio_pin_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
+{
+	int32_t rc = 0;
+	int32_t val = 0;
+
+	gconf->gpio_num_info = kzalloc(sizeof(struct msm_camera_gpio_num_info),
+		GFP_KERNEL);
+	if (!gconf->gpio_num_info) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	if (of_property_read_bool(of_node, "qcom,gpio-reset") == true) {
+		rc = of_property_read_u32(of_node, "qcom,gpio-reset", &val);
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-reset failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto ERROR;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-reset invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_RESET] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-reset %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_RESET]);
+	}
+
+	if (of_property_read_bool(of_node, "qcom,gpio-standby") == true) {
+		rc = of_property_read_u32(of_node, "qcom,gpio-standby", &val);
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-standby failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto ERROR;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-standby invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-reset %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY]);
+	}
+	return rc;
+
+ERROR:
+	kfree(gconf->gpio_num_info);
+	gconf->gpio_num_info = NULL;
+	return rc;
+}
+
+static int32_t msm_sensor_get_dt_actuator_data(struct device_node *of_node,
+	struct  msm_camera_sensor_board_info *sensordata)
+{
+	int32_t rc = 0;
+	uint32_t val = 0;
+
+	rc = of_property_read_u32(of_node, "qcom,actuator-cam-name", &val);
+	CDBG("%s qcom,actuator-cam-name %d, rc %d\n", __func__, val, rc);
+	if (rc < 0)
+		return 0;
+
+	sensordata->actuator_info = kzalloc(sizeof(struct msm_actuator_info),
+		GFP_KERNEL);
+	if (!sensordata->actuator_info) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR;
+	}
+
+	sensordata->actuator_info->cam_name = val;
+
+	rc = of_property_read_u32(of_node, "qcom,actuator-vcm-pwd", &val);
+	CDBG("%s qcom,actuator-vcm-pwd %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		sensordata->actuator_info->vcm_pwd = val;
+
+	rc = of_property_read_u32(of_node, "qcom,actuator-vcm-enable", &val);
+	CDBG("%s qcom,actuator-vcm-enable %d, rc %d\n", __func__, val, rc);
+	if (!rc)
+		sensordata->actuator_info->vcm_enable = val;
+
+	return 0;
+ERROR:
+	return rc;
+}
+
+static int32_t msm_sensor_get_dt_data(struct platform_device *pdev,
+	struct msm_sensor_ctrl_t *s_ctrl)
+{
+	int32_t rc = 0, i = 0;
+	struct device_node *of_node = pdev->dev.of_node;
+	struct msm_camera_gpio_conf *gconf = NULL;
+	struct msm_camera_sensor_board_info *sensordata = NULL;
+	uint16_t *gpio_array = NULL;
+	uint16_t gpio_array_size = 0;
+	uint32_t id_info[3];
+
+	s_ctrl->sensordata = kzalloc(sizeof(
+		struct msm_camera_sensor_board_info),
+		GFP_KERNEL);
+	if (!s_ctrl->sensordata) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	sensordata = s_ctrl->sensordata;
+
+	sensordata->sensor_init_params = kzalloc(sizeof(
+		struct msm_sensor_init_params), GFP_KERNEL);
+	if (!sensordata->sensor_init_params) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	rc = of_property_read_string(of_node, "qcom,sensor-name",
+		&sensordata->sensor_name);
+	CDBG("%s qcom,sensor-name %s, rc %d\n", __func__,
+		sensordata->sensor_name, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR1;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,sensor-mode",
+		&sensordata->sensor_init_params->modes_supported);
+	CDBG("%s qcom,sensor-mode %d, rc %d\n", __func__,
+		sensordata->sensor_init_params->modes_supported, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR1;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,sensor-position",
+		&sensordata->sensor_init_params->position);
+	CDBG("%s qcom,sensor-position %d, rc %d\n", __func__,
+		sensordata->sensor_init_params->position, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR1;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,mount-angle",
+		&sensordata->sensor_init_params->sensor_mount_angle);
+	CDBG("%s qcom,mount-angle %d, rc %d\n", __func__,
+		sensordata->sensor_init_params->sensor_mount_angle, rc);
+	if (rc < 0) {
+		/* Set default mount angle */
+		sensordata->sensor_init_params->sensor_mount_angle = 0;
+		rc = 0;
+	}
+
+	rc = msm_sensor_get_sub_module_index(of_node, sensordata);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR1;
+	}
+
+	rc = msm_sensor_get_dt_csi_data(of_node, sensordata);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR1;
+	}
+
+	rc = msm_sensor_get_dt_vreg_data(of_node, sensordata);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+
+	sensordata->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
+		GFP_KERNEL);
+	if (!sensordata->gpio_conf) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR3;
+	}
+	gconf = sensordata->gpio_conf;
+
+	gpio_array_size = of_gpio_count(of_node);
+	CDBG("%s gpio count %d\n", __func__, gpio_array_size);
+
+	if (gpio_array_size) {
+		gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
+			GFP_KERNEL);
+		if (!gpio_array) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR4;
+		}
+		for (i = 0; i < gpio_array_size; i++) {
+			gpio_array[i] = of_get_gpio(of_node, i);
+			CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+				gpio_array[i]);
+		}
+
+		rc = msm_sensor_get_dt_gpio_req_tbl(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR4;
+		}
+
+		rc = msm_sensor_get_dt_gpio_set_tbl(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR5;
+		}
+
+		rc = msm_sensor_init_gpio_pin_tbl(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR6;
+		}
+	}
+	rc = msm_sensor_get_dt_actuator_data(of_node, sensordata);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR7;
+	}
+
+	sensordata->slave_info = kzalloc(sizeof(struct msm_camera_slave_info),
+		GFP_KERNEL);
+	if (!sensordata->slave_info) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR8;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,slave-id",
+		id_info, 3);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR9;
+	}
+
+	sensordata->slave_info->sensor_slave_addr = id_info[0];
+	sensordata->slave_info->sensor_id_reg_addr = id_info[1];
+	sensordata->slave_info->sensor_id = id_info[2];
+
+	kfree(gpio_array);
+	return rc;
+
+ERROR9:
+	kfree(s_ctrl->sensordata->slave_info);
+ERROR8:
+	kfree(s_ctrl->sensordata->actuator_info);
+ERROR7:
+	kfree(s_ctrl->sensordata->gpio_conf->gpio_num_info);
+ERROR6:
+	kfree(s_ctrl->sensordata->gpio_conf->cam_gpio_set_tbl);
+ERROR5:
+	kfree(s_ctrl->sensordata->gpio_conf->cam_gpio_req_tbl);
+ERROR4:
+	kfree(s_ctrl->sensordata->gpio_conf);
+ERROR3:
+	kfree(s_ctrl->sensordata->cam_vreg);
+ERROR2:
+	kfree(s_ctrl->sensordata->csi_lane_params);
+ERROR1:
+	kfree(s_ctrl->sensordata);
+	kfree(gpio_array);
+	return rc;
+}
+
+int32_t msm_sensor_free_sensor_data(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	if (!s_ctrl->pdev)
+		return 0;
+	kfree(s_ctrl->sensordata->slave_info);
+	kfree(s_ctrl->sensordata->actuator_info);
+	kfree(s_ctrl->sensordata->gpio_conf->gpio_num_info);
+	kfree(s_ctrl->sensordata->gpio_conf->cam_gpio_set_tbl);
+	kfree(s_ctrl->sensordata->gpio_conf->cam_gpio_req_tbl);
+	kfree(s_ctrl->sensordata->gpio_conf);
+	kfree(s_ctrl->sensordata->cam_vreg);
+	kfree(s_ctrl->sensordata->csi_lane_params);
+	kfree(s_ctrl->sensordata->sensor_info);
+	kfree(s_ctrl->sensordata->sensor_init_params);
+	kfree(s_ctrl->sensordata);
+	return 0;
+}
+
+static struct msm_cam_clk_info cam_8960_clk_info[] = {
+	[SENSOR_CAM_MCLK] = {"cam_clk", 24000000},
+};
+
+static struct msm_cam_clk_info cam_8974_clk_info[] = {
+	[SENSOR_CAM_MCLK] = {"cam_src_clk", 19200000},
+	[SENSOR_CAM_CLK] = {"cam_clk", 0},
+};
+
+int32_t msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	int32_t rc = 0, index = 0, clk_index = 0;
+	struct msm_sensor_power_setting_array *power_setting_array = NULL;
+	struct msm_sensor_power_setting *power_setting = NULL;
+	struct msm_camera_sensor_board_info *data = s_ctrl->sensordata;
+
+	CDBG("%s:%d\n", __func__, __LINE__);
+	power_setting_array = &s_ctrl->power_setting_array;
+
+	if (data->gpio_conf->cam_gpiomux_conf_tbl != NULL) {
+		pr_err("%s:%d mux install\n", __func__, __LINE__);
+		msm_gpiomux_install(
+			(struct msm_gpiomux_config *)
+			data->gpio_conf->cam_gpiomux_conf_tbl,
+			data->gpio_conf->cam_gpiomux_conf_tbl_size);
+	}
+
+	rc = msm_camera_request_gpio_table(
+		data->gpio_conf->cam_gpio_req_tbl,
+		data->gpio_conf->cam_gpio_req_tbl_size, 1);
+	if (rc < 0) {
+		pr_err("%s: request gpio failed\n", __func__);
+		return rc;
+	}
+	for (index = 0; index < power_setting_array->size; index++) {
+		CDBG("%s index %d\n", __func__, index);
+		power_setting = &power_setting_array->power_setting[index];
+		CDBG("%s type %d\n", __func__, power_setting->seq_type);
+		switch (power_setting->seq_type) {
+		case SENSOR_CLK:
+			if (power_setting->seq_val >= s_ctrl->clk_info_size) {
+				pr_err("%s clk index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					s_ctrl->clk_info_size);
+				goto power_up_failed;
+			}
+			if (power_setting->config_val)
+				s_ctrl->clk_info[power_setting->seq_val].
+					clk_rate = power_setting->config_val;
+
+			rc = msm_cam_clk_enable(s_ctrl->dev,
+				&s_ctrl->clk_info[0],
+				(struct clk **)&power_setting->data[0],
+				s_ctrl->clk_info_size,
+				1);
+			if (rc < 0) {
+				pr_err("%s: clk enable failed\n",
+					__func__);
+				goto power_up_failed;
+			}
+			break;
+		case SENSOR_GPIO:
+			if (power_setting->seq_val >= SENSOR_GPIO_MAX ||
+				!data->gpio_conf->gpio_num_info) {
+				pr_err("%s gpio index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					SENSOR_GPIO_MAX);
+				goto power_up_failed;
+			}
+			pr_debug("%s:%d gpio set val %d\n", __func__, __LINE__,
+				data->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val]);
+			gpio_set_value_cansleep(
+				data->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val],
+				power_setting->config_val);
+			break;
+		case SENSOR_VREG:
+			if (power_setting->seq_val >= CAM_VREG_MAX) {
+				pr_err("%s vreg index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					SENSOR_GPIO_MAX);
+				goto power_up_failed;
+			}
+			msm_camera_config_single_vreg(s_ctrl->dev,
+				&data->cam_vreg[power_setting->seq_val],
+				(struct regulator **)&power_setting->data[0],
+				1);
+			break;
+		case SENSOR_I2C_MUX:
+			if (data->i2c_conf && data->i2c_conf->use_i2c_mux)
+				msm_sensor_enable_i2c_mux(data->i2c_conf);
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				power_setting->seq_type);
+			break;
+		}
+		if (power_setting->delay > 20) {
+			msleep(power_setting->delay);
+		} else if (power_setting->delay) {
+			usleep_range(power_setting->delay * 1000,
+				(power_setting->delay * 1000) + 1000);
+		}
+	}
+
+	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_util(
+			s_ctrl->sensor_i2c_client, MSM_CCI_INIT);
+		if (rc < 0) {
+			pr_err("%s cci_init failed\n", __func__);
+			goto power_up_failed;
+		}
+	}
+
+	if (s_ctrl->func_tbl->sensor_match_id)
+		rc = s_ctrl->func_tbl->sensor_match_id(s_ctrl);
+	else
+		rc = msm_sensor_match_id(s_ctrl);
+	if (rc < 0) {
+		pr_err("%s:%d match id failed rc %d\n", __func__, __LINE__, rc);
+		goto power_up_failed;
+	}
+
+	CDBG("%s exit\n", __func__);
+	return 0;
+power_up_failed:
+	pr_err("%s:%d failed\n", __func__, __LINE__);
+	for (index--; index >= 0; index--) {
+		CDBG("%s index %d\n", __func__, index);
+		power_setting = &power_setting_array->power_setting[index];
+		CDBG("%s type %d\n", __func__, power_setting->seq_type);
+		switch (power_setting->seq_type) {
+		case SENSOR_CLK:
+			for (clk_index--; clk_index >= 0; clk_index--)
+				msm_cam_clk_enable(s_ctrl->dev,
+					&s_ctrl->clk_info[clk_index],
+					(struct clk **)&power_setting->data[0],
+					1, 0);
+			break;
+		case SENSOR_GPIO:
+			gpio_set_value_cansleep(
+				data->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+			break;
+		case SENSOR_VREG:
+			msm_camera_config_single_vreg(s_ctrl->dev,
+				&data->cam_vreg[power_setting->seq_val],
+				(struct regulator **)&power_setting->data[0],
+				0);
+			break;
+		case SENSOR_I2C_MUX:
+			if (data->i2c_conf && data->i2c_conf->use_i2c_mux)
+				msm_sensor_disable_i2c_mux(data->i2c_conf);
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				power_setting->seq_type);
+			break;
+		}
+		if (power_setting->delay > 20) {
+			msleep(power_setting->delay);
+		} else if (power_setting->delay) {
+			usleep_range(power_setting->delay * 1000,
+				(power_setting->delay * 1000) + 1000);
+		}
+	}
+	msm_camera_request_gpio_table(
+		data->gpio_conf->cam_gpio_req_tbl,
+		data->gpio_conf->cam_gpio_req_tbl_size, 0);
+	return rc;
+}
+
+int32_t msm_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	int32_t index = 0;
+	struct msm_sensor_power_setting_array *power_setting_array = NULL;
+	struct msm_sensor_power_setting *power_setting = NULL;
+	struct msm_camera_sensor_board_info *data = s_ctrl->sensordata;
+
+	CDBG("%s:%d\n", __func__, __LINE__);
+	power_setting_array = &s_ctrl->power_setting_array;
+
+	if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
+		s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_util(
+			s_ctrl->sensor_i2c_client, MSM_CCI_RELEASE);
+	}
+
+	for (index = (power_setting_array->size - 1); index >= 0; index--) {
+		CDBG("%s index %d\n", __func__, index);
+		power_setting = &power_setting_array->power_setting[index];
+		CDBG("%s type %d\n", __func__, power_setting->seq_type);
+		switch (power_setting->seq_type) {
+		case SENSOR_CLK:
+			msm_cam_clk_enable(s_ctrl->dev,
+				&s_ctrl->clk_info[0],
+				(struct clk **)&power_setting->data[0],
+				s_ctrl->clk_info_size,
+				0);
+			break;
+		case SENSOR_GPIO:
+			if (power_setting->seq_val >= SENSOR_GPIO_MAX ||
+				!data->gpio_conf->gpio_num_info) {
+				pr_err("%s gpio index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					SENSOR_GPIO_MAX);
+				continue;
+			}
+			gpio_set_value_cansleep(
+				data->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+			break;
+		case SENSOR_VREG:
+			if (power_setting->seq_val >= CAM_VREG_MAX) {
+				pr_err("%s vreg index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					SENSOR_GPIO_MAX);
+				continue;
+			}
+			msm_camera_config_single_vreg(s_ctrl->dev,
+				&data->cam_vreg[power_setting->seq_val],
+				(struct regulator **)&power_setting->data[0],
+				0);
+			break;
+		case SENSOR_I2C_MUX:
+			if (data->i2c_conf && data->i2c_conf->use_i2c_mux)
+				msm_sensor_disable_i2c_mux(data->i2c_conf);
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				power_setting->seq_type);
+			break;
+		}
+		if (power_setting->delay > 20) {
+			msleep(power_setting->delay);
+		} else if (power_setting->delay) {
+			usleep_range(power_setting->delay * 1000,
+				(power_setting->delay * 1000) + 1000);
+		}
+	}
+	msm_camera_request_gpio_table(
+		data->gpio_conf->cam_gpio_req_tbl,
+		data->gpio_conf->cam_gpio_req_tbl_size, 0);
+	CDBG("%s exit\n", __func__);
+	return 0;
+}
+
+int32_t msm_sensor_match_id(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	int32_t rc = 0;
+	uint16_t chipid = 0;
+	rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_read(
+			s_ctrl->sensor_i2c_client,
+			s_ctrl->sensordata->slave_info->sensor_id_reg_addr,
+			&chipid, MSM_CAMERA_I2C_WORD_DATA);
+	if (rc < 0) {
+		pr_err("%s: %s: read id failed\n", __func__,
+			s_ctrl->sensordata->sensor_name);
+		return rc;
+	}
+
+	CDBG("%s: read id: %x expected id %x:\n", __func__, chipid,
+		s_ctrl->sensordata->slave_info->sensor_id);
+	if (chipid != s_ctrl->sensordata->slave_info->sensor_id) {
+		pr_err("msm_sensor_match_id chip id doesnot match\n");
+		return -ENODEV;
+	}
+	return rc;
+}
+
+static struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd)
+{
+	return container_of(container_of(sd, struct msm_sd_subdev, sd),
+		struct msm_sensor_ctrl_t, msm_sd);
+}
+
+static void msm_sensor_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table(
+		s_ctrl->sensor_i2c_client, &s_ctrl->stop_setting);
+	kfree(s_ctrl->stop_setting.reg_setting);
+	return;
+}
+
+static long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+	void __user *argp = (void __user *)arg;
+	if (!s_ctrl) {
+		pr_err("%s s_ctrl NULL\n", __func__);
+		return -EBADF;
+	}
+	switch (cmd) {
+	case VIDIOC_MSM_SENSOR_CFG:
+		return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+	case VIDIOC_MSM_SENSOR_RELEASE:
+		msm_sensor_stop_stream(s_ctrl);
+		return 0;
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+int32_t msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl,
+	void __user *argp)
+{
+	struct sensorb_cfg_data *cdata = (struct sensorb_cfg_data *)argp;
+	long rc = 0;
+	int32_t i = 0;
+	mutex_lock(s_ctrl->msm_sensor_mutex);
+	CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__,
+		s_ctrl->sensordata->sensor_name, cdata->cfgtype);
+	switch (cdata->cfgtype) {
+	case CFG_GET_SENSOR_INFO:
+		memcpy(cdata->cfg.sensor_info.sensor_name,
+			s_ctrl->sensordata->sensor_name,
+			sizeof(cdata->cfg.sensor_info.sensor_name));
+		cdata->cfg.sensor_info.session_id =
+			s_ctrl->sensordata->sensor_info->session_id;
+		for (i = 0; i < SUB_MODULE_MAX; i++)
+			cdata->cfg.sensor_info.subdev_id[i] =
+				s_ctrl->sensordata->sensor_info->subdev_id[i];
+		CDBG("%s:%d sensor name %s\n", __func__, __LINE__,
+			cdata->cfg.sensor_info.sensor_name);
+		CDBG("%s:%d session id %d\n", __func__, __LINE__,
+			cdata->cfg.sensor_info.session_id);
+		for (i = 0; i < SUB_MODULE_MAX; i++)
+			CDBG("%s:%d subdev_id[%d] %d\n", __func__, __LINE__, i,
+				cdata->cfg.sensor_info.subdev_id[i]);
+
+		break;
+	case CFG_GET_SENSOR_INIT_PARAMS:
+		cdata->cfg.sensor_init_params =
+			*s_ctrl->sensordata->sensor_init_params;
+		CDBG("%s:%d init params mode %d pos %d mount %d\n", __func__,
+			__LINE__,
+			cdata->cfg.sensor_init_params.modes_supported,
+			cdata->cfg.sensor_init_params.position,
+			cdata->cfg.sensor_init_params.sensor_mount_angle);
+		break;
+	case CFG_SET_SLAVE_INFO: {
+		struct msm_camera_sensor_slave_info sensor_slave_info;
+		struct msm_sensor_power_setting_array *power_setting_array;
+		int slave_index = 0;
+		if (copy_from_user(&sensor_slave_info,
+			(void *)cdata->cfg.setting,
+			sizeof(struct msm_camera_sensor_slave_info))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		/* Update sensor slave address */
+		if (sensor_slave_info.slave_addr) {
+			s_ctrl->sensor_i2c_client->cci_client->sid =
+				sensor_slave_info.slave_addr >> 1;
+		}
+
+		/* Update sensor address type */
+		s_ctrl->sensor_i2c_client->addr_type =
+			sensor_slave_info.addr_type;
+
+		/* Update power up / down sequence */
+		s_ctrl->power_setting_array =
+			sensor_slave_info.power_setting_array;
+		power_setting_array = &s_ctrl->power_setting_array;
+		power_setting_array->power_setting = kzalloc(
+			power_setting_array->size *
+			sizeof(struct msm_sensor_power_setting), GFP_KERNEL);
+		if (!power_setting_array->power_setting) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(power_setting_array->power_setting,
+			(void *)
+			sensor_slave_info.power_setting_array.power_setting,
+			power_setting_array->size *
+			sizeof(struct msm_sensor_power_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+		s_ctrl->free_power_setting = true;
+		CDBG("%s sensor id %x\n", __func__,
+			sensor_slave_info.slave_addr);
+		CDBG("%s sensor addr type %d\n", __func__,
+			sensor_slave_info.addr_type);
+		CDBG("%s sensor reg %x\n", __func__,
+			sensor_slave_info.sensor_id_info.sensor_id_reg_addr);
+		CDBG("%s sensor id %x\n", __func__,
+			sensor_slave_info.sensor_id_info.sensor_id);
+		for (slave_index = 0; slave_index <
+			power_setting_array->size; slave_index++) {
+			CDBG("%s i %d power setting %d %d %ld %d\n", __func__,
+				slave_index,
+				power_setting_array->power_setting[slave_index].
+				seq_type,
+				power_setting_array->power_setting[slave_index].
+				seq_val,
+				power_setting_array->power_setting[slave_index].
+				config_val,
+				power_setting_array->power_setting[slave_index].
+				delay);
+		}
+		break;
+	}
+	case CFG_WRITE_I2C_ARRAY: {
+		struct msm_camera_i2c_reg_setting conf_array;
+		struct msm_camera_i2c_reg_array *reg_setting = NULL;
+
+		if (copy_from_user(&conf_array,
+			(void *)cdata->cfg.setting,
+			sizeof(struct msm_camera_i2c_reg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		reg_setting = kzalloc(conf_array.size *
+			(sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL);
+		if (!reg_setting) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(reg_setting, (void *)conf_array.reg_setting,
+			conf_array.size *
+			sizeof(struct msm_camera_i2c_reg_array))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(reg_setting);
+			rc = -EFAULT;
+			break;
+		}
+
+		conf_array.reg_setting = reg_setting;
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table(
+			s_ctrl->sensor_i2c_client, &conf_array);
+		kfree(reg_setting);
+		break;
+	}
+	case CFG_WRITE_I2C_SEQ_ARRAY: {
+		struct msm_camera_i2c_seq_reg_setting conf_array;
+		struct msm_camera_i2c_seq_reg_array *reg_setting = NULL;
+
+		if (copy_from_user(&conf_array,
+			(void *)cdata->cfg.setting,
+			sizeof(struct msm_camera_i2c_seq_reg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		reg_setting = kzalloc(conf_array.size *
+			(sizeof(struct msm_camera_i2c_seq_reg_array)),
+			GFP_KERNEL);
+		if (!reg_setting) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(reg_setting, (void *)conf_array.reg_setting,
+			conf_array.size *
+			sizeof(struct msm_camera_i2c_seq_reg_array))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(reg_setting);
+			rc = -EFAULT;
+			break;
+		}
+
+		conf_array.reg_setting = reg_setting;
+		rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->
+			i2c_write_seq_table(s_ctrl->sensor_i2c_client,
+			&conf_array);
+		kfree(reg_setting);
+		break;
+	}
+
+	case CFG_POWER_UP:
+		if (s_ctrl->func_tbl->sensor_power_up)
+			rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+		else
+			rc = -EFAULT;
+		break;
+
+	case CFG_POWER_DOWN:
+		if (s_ctrl->func_tbl->sensor_power_down)
+			rc = s_ctrl->func_tbl->sensor_power_down(
+				s_ctrl);
+		else
+			rc = -EFAULT;
+		break;
+
+	case CFG_SET_STOP_STREAM_SETTING: {
+		struct msm_camera_i2c_reg_setting *stop_setting =
+			&s_ctrl->stop_setting;
+		struct msm_camera_i2c_reg_array *reg_setting = NULL;
+		if (copy_from_user(stop_setting,
+			(void *)cdata->cfg.setting,
+			sizeof(struct msm_camera_i2c_reg_setting))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -EFAULT;
+			break;
+		}
+
+		reg_setting = stop_setting->reg_setting;
+		stop_setting->reg_setting = kzalloc(stop_setting->size *
+			(sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL);
+		if (!stop_setting->reg_setting) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			rc = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(stop_setting->reg_setting,
+			(void *)reg_setting,
+			stop_setting->size *
+			sizeof(struct msm_camera_i2c_reg_array))) {
+			pr_err("%s:%d failed\n", __func__, __LINE__);
+			kfree(stop_setting->reg_setting);
+			stop_setting->reg_setting = NULL;
+			stop_setting->size = 0;
+			rc = -EFAULT;
+			break;
+		}
+		break;
+	}
+	default:
+		rc = -EFAULT;
+		break;
+	}
+
+	mutex_unlock(s_ctrl->msm_sensor_mutex);
+
+	return rc;
+}
+
+static int32_t msm_sensor_power(struct v4l2_subdev *sd, int on)
+{
+	int rc = 0;
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+	mutex_lock(s_ctrl->msm_sensor_mutex);
+	if (!on)
+		rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+	if (s_ctrl->free_power_setting == true) {
+		kfree(s_ctrl->power_setting_array.power_setting);
+		s_ctrl->free_power_setting = false;
+	}
+	mutex_unlock(s_ctrl->msm_sensor_mutex);
+	return rc;
+}
+
+static int32_t msm_sensor_v4l2_enum_fmt(struct v4l2_subdev *sd,
+	unsigned int index, enum v4l2_mbus_pixelcode *code)
+{
+	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+
+	if ((unsigned int)index >= s_ctrl->sensor_v4l2_subdev_info_size)
+		return -EINVAL;
+
+	*code = s_ctrl->sensor_v4l2_subdev_info[index].code;
+	return 0;
+}
+
+static struct v4l2_subdev_core_ops msm_sensor_subdev_core_ops = {
+	.ioctl = msm_sensor_subdev_ioctl,
+	.s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops msm_sensor_subdev_video_ops = {
+	.enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops msm_sensor_subdev_ops = {
+	.core = &msm_sensor_subdev_core_ops,
+	.video  = &msm_sensor_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t msm_sensor_func_tbl = {
+	.sensor_config = msm_sensor_config,
+	.sensor_power_up = msm_sensor_power_up,
+	.sensor_power_down = msm_sensor_power_down,
+	.sensor_match_id = msm_sensor_match_id,
+};
+
+static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = {
+	.i2c_read = msm_camera_cci_i2c_read,
+	.i2c_read_seq = msm_camera_cci_i2c_read_seq,
+	.i2c_write = msm_camera_cci_i2c_write,
+	.i2c_write_table = msm_camera_cci_i2c_write_table,
+	.i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table,
+	.i2c_write_table_w_microdelay =
+		msm_camera_cci_i2c_write_table_w_microdelay,
+	.i2c_util = msm_sensor_cci_i2c_util,
+};
+
+static struct msm_camera_i2c_fn_t msm_sensor_qup_func_tbl = {
+	.i2c_read = msm_camera_qup_i2c_read,
+	.i2c_read_seq = msm_camera_qup_i2c_read_seq,
+	.i2c_write = msm_camera_qup_i2c_write,
+	.i2c_write_table = msm_camera_qup_i2c_write_table,
+	.i2c_write_seq_table = msm_camera_qup_i2c_write_seq_table,
+	.i2c_write_table_w_microdelay =
+		msm_camera_qup_i2c_write_table_w_microdelay,
+};
+
+int32_t msm_sensor_platform_probe(struct platform_device *pdev, void *data)
+{
+	int32_t rc = 0;
+	struct msm_sensor_ctrl_t *s_ctrl =
+		(struct msm_sensor_ctrl_t *)data;
+	struct msm_camera_cci_client *cci_client = NULL;
+	uint32_t session_id;
+	s_ctrl->pdev = pdev;
+	s_ctrl->dev = &pdev->dev;
+	CDBG("%s called data %p\n", __func__, data);
+	CDBG("%s pdev name %s\n", __func__, pdev->id_entry->name);
+	if (pdev->dev.of_node) {
+		rc = msm_sensor_get_dt_data(pdev, s_ctrl);
+		if (rc < 0) {
+			pr_err("%s failed line %d\n", __func__, __LINE__);
+			return rc;
+		}
+	}
+	s_ctrl->sensor_device_type = MSM_SENSOR_PLATFORM_DEVICE;
+	s_ctrl->sensor_i2c_client->cci_client = kzalloc(sizeof(
+		struct msm_camera_cci_client), GFP_KERNEL);
+	if (!s_ctrl->sensor_i2c_client->cci_client) {
+		pr_err("%s failed line %d\n", __func__, __LINE__);
+		return rc;
+	}
+	/* TODO: get CCI subdev */
+	cci_client = s_ctrl->sensor_i2c_client->cci_client;
+	cci_client->cci_subdev = msm_cci_get_subdev();
+	cci_client->cci_i2c_master = MASTER_0;
+	cci_client->sid =
+		s_ctrl->sensordata->slave_info->sensor_slave_addr >> 1;
+	cci_client->retries = 3;
+	cci_client->id_map = 0;
+	if (!s_ctrl->func_tbl)
+		s_ctrl->func_tbl = &msm_sensor_func_tbl;
+	if (!s_ctrl->sensor_i2c_client->i2c_func_tbl)
+		s_ctrl->sensor_i2c_client->i2c_func_tbl =
+			&msm_sensor_cci_func_tbl;
+	if (!s_ctrl->sensor_v4l2_subdev_ops)
+		s_ctrl->sensor_v4l2_subdev_ops = &msm_sensor_subdev_ops;
+	s_ctrl->clk_info = cam_8974_clk_info;
+	s_ctrl->clk_info_size = ARRAY_SIZE(cam_8974_clk_info);
+	rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+	if (rc < 0) {
+		pr_err("%s %s power up failed\n", __func__,
+			s_ctrl->sensordata->sensor_name);
+		kfree(cci_client);
+		return rc;
+	}
+
+	CDBG("%s %s probe succeeded\n", __func__,
+		s_ctrl->sensordata->sensor_name);
+	v4l2_subdev_init(&s_ctrl->msm_sd.sd,
+		s_ctrl->sensor_v4l2_subdev_ops);
+	snprintf(s_ctrl->msm_sd.sd.name,
+		sizeof(s_ctrl->msm_sd.sd.name), "%s",
+		s_ctrl->sensordata->sensor_name);
+	v4l2_set_subdevdata(&s_ctrl->msm_sd.sd, pdev);
+	s_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&s_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+	s_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	s_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_SENSOR;
+	s_ctrl->msm_sd.sd.entity.name =
+		s_ctrl->msm_sd.sd.name;
+
+	rc = camera_init_v4l2(&s_ctrl->pdev->dev, &session_id);
+	CDBG("%s rc %d session_id %d\n", __func__, rc, session_id);
+	s_ctrl->sensordata->sensor_info->session_id = session_id;
+	msm_sd_register(&s_ctrl->msm_sd);
+	CDBG("%s:%d\n", __func__, __LINE__);
+
+	s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+	CDBG("%s:%d\n", __func__, __LINE__);
+	return rc;
+}
+
+int32_t msm_sensor_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int rc = 0;
+	struct msm_sensor_ctrl_t *s_ctrl;
+	uint32_t session_id;
+	CDBG("%s %s_i2c_probe called\n", __func__, client->name);
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("%s %s i2c_check_functionality failed\n",
+			__func__, client->name);
+		rc = -EFAULT;
+		return rc;
+	}
+
+	s_ctrl = (struct msm_sensor_ctrl_t *)(id->driver_data);
+	if (!s_ctrl) {
+		pr_err("%s:%d sensor ctrl structure NULL\n", __func__,
+			__LINE__);
+		return -EINVAL;
+	}
+
+	s_ctrl->sensor_device_type = MSM_SENSOR_I2C_DEVICE;
+	s_ctrl->sensordata = client->dev.platform_data;
+	if (s_ctrl->sensordata == NULL) {
+		pr_err("%s %s NULL sensor data\n", __func__, client->name);
+		return -EFAULT;
+	}
+
+	if (s_ctrl->sensor_i2c_client != NULL) {
+		s_ctrl->sensor_i2c_client->client = client;
+		s_ctrl->dev = &client->dev;
+		if (s_ctrl->sensordata->slave_info->sensor_slave_addr)
+			s_ctrl->sensor_i2c_client->client->addr =
+				s_ctrl->sensordata->slave_info->
+				sensor_slave_addr;
+	} else {
+		pr_err("%s %s sensor_i2c_client NULL\n",
+			__func__, client->name);
+		rc = -EFAULT;
+		return rc;
+	}
+
+	if (!s_ctrl->func_tbl)
+		s_ctrl->func_tbl = &msm_sensor_func_tbl;
+	if (!s_ctrl->sensor_i2c_client->i2c_func_tbl)
+		s_ctrl->sensor_i2c_client->i2c_func_tbl =
+			&msm_sensor_qup_func_tbl;
+	if (!s_ctrl->sensor_v4l2_subdev_ops)
+		s_ctrl->sensor_v4l2_subdev_ops = &msm_sensor_subdev_ops;
+
+	s_ctrl->clk_info = cam_8960_clk_info;
+	s_ctrl->clk_info_size = ARRAY_SIZE(cam_8960_clk_info);
+
+	rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+	if (rc < 0) {
+		pr_err("%s %s power up failed\n", __func__, client->name);
+		return rc;
+	}
+
+	CDBG("%s %s probe succeeded\n", __func__, client->name);
+	snprintf(s_ctrl->msm_sd.sd.name,
+		sizeof(s_ctrl->msm_sd.sd.name), "%s", id->name);
+	v4l2_i2c_subdev_init(&s_ctrl->msm_sd.sd, client,
+		s_ctrl->sensor_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&s_ctrl->msm_sd.sd, client);
+	s_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&s_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+	s_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	s_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_SENSOR;
+	s_ctrl->msm_sd.sd.entity.name =
+		s_ctrl->msm_sd.sd.name;
+
+	rc = camera_init_v4l2(&s_ctrl->sensor_i2c_client->client->dev,
+		&session_id);
+	CDBG("%s rc %d session_id %d\n", __func__, rc, session_id);
+	s_ctrl->sensordata->sensor_info->session_id = session_id;
+	msm_sd_register(&s_ctrl->msm_sd);
+	CDBG("%s:%d\n", __func__, __LINE__);
+
+	s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+	return rc;
+}
diff --git a/drivers/media/video/msmb/sensor/msm_sensor.h b/drivers/media/video/msmb/sensor/msm_sensor.h
new file mode 100644
index 0000000..20a2b14
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/msm_sensor.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_SENSOR_H
+#define MSM_SENSOR_H
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <mach/camera2.h>
+#include <media/msm_cam_sensor.h>
+#include <media/v4l2-subdev.h>
+#include "msm_camera_i2c.h"
+#include "msm_sd.h"
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+	static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+struct msm_sensor_ctrl_t;
+
+struct msm_sensor_fn_t {
+	int (*sensor_config) (struct msm_sensor_ctrl_t *, void __user *);
+	int (*sensor_power_down)
+		(struct msm_sensor_ctrl_t *);
+	int (*sensor_power_up) (struct msm_sensor_ctrl_t *);
+	int32_t (*sensor_match_id)(struct msm_sensor_ctrl_t *s_ctrl);
+};
+
+struct msm_sensor_ctrl_t {
+	struct platform_device *pdev;
+	enum msm_sensor_device_type_t sensor_device_type;
+	struct msm_camera_sensor_board_info *sensordata;
+	struct msm_sensor_power_setting_array power_setting_array;
+	struct mutex *msm_sensor_mutex;
+
+	struct msm_camera_i2c_client *sensor_i2c_client;
+	struct device *dev;
+
+	struct msm_sd_subdev msm_sd;
+	struct v4l2_subdev_info *sensor_v4l2_subdev_info;
+	uint8_t sensor_v4l2_subdev_info_size;
+	struct v4l2_subdev_ops *sensor_v4l2_subdev_ops;
+	struct msm_sensor_fn_t *func_tbl;
+	struct msm_camera_i2c_reg_setting stop_setting;
+	bool free_power_setting;
+	struct msm_cam_clk_info *clk_info;
+	uint16_t clk_info_size;
+};
+
+int32_t msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl,
+			void __user *argp);
+
+int32_t msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl);
+
+int32_t msm_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl);
+
+int32_t msm_sensor_match_id(struct msm_sensor_ctrl_t *s_ctrl);
+
+int32_t msm_sensor_platform_probe(struct platform_device *pdev,
+	void *data);
+
+int32_t msm_sensor_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id);
+
+int32_t msm_sensor_free_sensor_data(struct msm_sensor_ctrl_t *s_ctrl);
+
+#endif
diff --git a/drivers/media/video/msmb/sensor/s5k3l1yx.c b/drivers/media/video/msmb/sensor/s5k3l1yx.c
new file mode 100644
index 0000000..9c36b5b
--- /dev/null
+++ b/drivers/media/video/msmb/sensor/s5k3l1yx.c
@@ -0,0 +1,155 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "msm_sensor.h"
+#define S5K3L1YX_SENSOR_NAME "s5k3l1yx"
+DEFINE_MSM_MUTEX(s5k3l1yx_mut);
+
+static struct msm_sensor_ctrl_t s5k3l1yx_s_ctrl;
+
+static struct msm_sensor_power_setting s5k3l1yx_power_setting[] = {
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VDIG,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VANA,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VIO,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VAF,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 1,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_RESET,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 30,
+	},
+	{
+		.seq_type = SENSOR_CLK,
+		.seq_val = SENSOR_CAM_MCLK,
+		.config_val = 0,
+		.delay = 1,
+	},
+	{
+		.seq_type = SENSOR_I2C_MUX,
+		.seq_val = 0,
+		.config_val = 0,
+		.delay = 0,
+	},
+};
+
+static struct v4l2_subdev_info s5k3l1yx_subdev_info[] = {
+	{
+		.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.fmt    = 1,
+		.order    = 0,
+	},
+};
+
+static const struct i2c_device_id s5k3l1yx_i2c_id[] = {
+	{S5K3L1YX_SENSOR_NAME, (kernel_ulong_t)&s5k3l1yx_s_ctrl},
+	{ }
+};
+
+static struct i2c_driver s5k3l1yx_i2c_driver = {
+	.id_table = s5k3l1yx_i2c_id,
+	.probe  = msm_sensor_i2c_probe,
+	.driver = {
+		.name = S5K3L1YX_SENSOR_NAME,
+	},
+};
+
+static struct msm_camera_i2c_client s5k3l1yx_sensor_i2c_client = {
+	.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id s5k3l1yx_dt_match[] = {
+	{.compatible = "qcom,s5k3l1yx", .data = &s5k3l1yx_s_ctrl},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, s5k3l1yx_dt_match);
+
+static struct platform_driver s5k3l1yx_platform_driver = {
+	.driver = {
+		.name = "qcom,s5k3l1yx",
+		.owner = THIS_MODULE,
+		.of_match_table = s5k3l1yx_dt_match,
+	},
+};
+
+static int32_t s5k3l1yx_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	const struct of_device_id *match;
+	match = of_match_device(s5k3l1yx_dt_match, &pdev->dev);
+	rc = msm_sensor_platform_probe(pdev, match->data);
+	return rc;
+}
+
+static int __init s5k3l1yx_init_module(void)
+{
+	int32_t rc = 0;
+	pr_info("%s:%d\n", __func__, __LINE__);
+	rc = platform_driver_probe(&s5k3l1yx_platform_driver,
+		s5k3l1yx_platform_probe);
+	if (!rc)
+		return rc;
+	pr_err("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&s5k3l1yx_i2c_driver);
+}
+
+static void __exit s5k3l1yx_exit_module(void)
+{
+	pr_info("%s:%d\n", __func__, __LINE__);
+	if (s5k3l1yx_s_ctrl.pdev) {
+		msm_sensor_free_sensor_data(&s5k3l1yx_s_ctrl);
+		platform_driver_unregister(&s5k3l1yx_platform_driver);
+	} else
+		i2c_del_driver(&s5k3l1yx_i2c_driver);
+	return;
+}
+
+static struct msm_sensor_ctrl_t s5k3l1yx_s_ctrl = {
+	.sensor_i2c_client = &s5k3l1yx_sensor_i2c_client,
+	.power_setting_array.power_setting = s5k3l1yx_power_setting,
+	.power_setting_array.size = ARRAY_SIZE(s5k3l1yx_power_setting),
+	.msm_sensor_mutex = &s5k3l1yx_mut,
+	.sensor_v4l2_subdev_info = s5k3l1yx_subdev_info,
+	.sensor_v4l2_subdev_info_size = ARRAY_SIZE(s5k3l1yx_subdev_info),
+};
+
+module_init(s5k3l1yx_init_module);
+module_exit(s5k3l1yx_exit_module);
+MODULE_DESCRIPTION("s5k3l1yx");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 91c5f54..b11e30e 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -58,7 +58,7 @@
 #define QSEE_CE_CLK_100MHZ		100000000
 #define QSEE_CE_CLK_50MHZ		50000000
 
-#define QSEECOM_MAX_SG_ENTRY	10
+#define QSEECOM_MAX_SG_ENTRY	512
 
 enum qseecom_command_scm_resp_type {
 	QSEOS_APP_ID = 0xEE01,
@@ -1772,16 +1772,25 @@
 
 int qseecom_set_bandwidth(struct qseecom_handle *handle, bool high)
 {
+	int ret = 0;
 	if ((handle == NULL) || (handle->dev == NULL)) {
 		pr_err("No valid kernel client\n");
 		return -EINVAL;
 	}
-	if (high)
-		return qsee_vote_for_clock(handle->dev, CLK_DFAB);
-	else {
+	if (high) {
+		ret = qsee_vote_for_clock(handle->dev, CLK_DFAB);
+		if (ret)
+			pr_err("Failed to vote for DFAB clock%d\n", ret);
+		ret = qsee_vote_for_clock(handle->dev, CLK_SFPB);
+		if (ret) {
+			pr_err("Failed to vote for SFPB clock%d\n", ret);
+			qsee_disable_clock_vote(handle->dev, CLK_DFAB);
+		}
+	} else {
 		qsee_disable_clock_vote(handle->dev, CLK_DFAB);
-		return 0;
+		qsee_disable_clock_vote(handle->dev, CLK_SFPB);
 	}
+	return ret;
 }
 EXPORT_SYMBOL(qseecom_set_bandwidth);
 
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 563a013..4e504da5 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -41,6 +41,8 @@
 #include <mach/dma.h>
 #include <mach/msm_tspp.h>
 #include <linux/debugfs.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 /*
  * General defines
@@ -647,45 +649,19 @@
 }
 
 /*** GPIO functions ***/
-static void tspp_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 tspp_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("tspp: gpio_request(%d) <%s> failed: %d\n",
-			       GPIO_PIN(g->gpio_cfg), g->label ?: "?", rc);
-			goto err;
-		}
-	}
-	return 0;
-err:
-	tspp_gpios_free(table, i);
-	return rc;
-}
-
 static int tspp_gpios_disable(const struct msm_gpio *table, int size)
 {
 	int rc = 0;
 	int i;
 	const struct msm_gpio *g;
+
 	for (i = size-1; i >= 0; i--) {
 		int tmp;
 		g = table + i;
-		tmp = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_DISABLE);
+
+		tmp = gpio_tlmm_config(GPIO_CFG(GPIO_PIN(g->gpio_cfg),
+			0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+			GPIO_CFG_DISABLE);
 		if (tmp) {
 			pr_err("tspp_gpios_disable(0x%08x, GPIO_CFG_DISABLE) <%s> failed: %d\n",
 			       g->gpio_cfg, g->label ?: "?", rc);
@@ -704,8 +680,9 @@
 static int tspp_gpios_enable(const struct msm_gpio *table, int size)
 {
 	int rc;
-	int i;
+	int i, j;
 	const struct msm_gpio *g;
+
 	for (i = 0; i < size; i++) {
 		g = table + i;
 		rc = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_ENABLE);
@@ -721,39 +698,26 @@
 	}
 	return 0;
 err:
-	tspp_gpios_disable(table, i);
-	return rc;
-}
+	for (j = 0; j < i; j++)
+		tspp_gpios_disable(table, j);
 
-static int tspp_gpios_request_enable(const struct msm_gpio *table, int size)
-{
-	int rc = tspp_gpios_request(table, size);
-	if (rc)
-		return rc;
-	rc = tspp_gpios_enable(table, size);
-	if (rc)
-		tspp_gpios_free(table, size);
 	return rc;
 }
 
-static void tspp_gpios_disable_free(const struct msm_gpio *table, int size)
-{
-	tspp_gpios_disable(table, size);
-	tspp_gpios_free(table, size);
-}
-
 static int tspp_start_gpios(struct tspp_device *device)
 {
 	struct msm_tspp_platform_data *pdata =
 		device->pdev->dev.platform_data;
-	return tspp_gpios_request_enable(pdata->gpios, pdata->num_gpios);
+
+	return tspp_gpios_enable(pdata->gpios, pdata->num_gpios);
 }
 
 static void tspp_stop_gpios(struct tspp_device *device)
 {
 	struct msm_tspp_platform_data *pdata =
 		device->pdev->dev.platform_data;
-	tspp_gpios_disable_free(pdata->gpios, pdata->num_gpios);
+
+	tspp_gpios_disable(pdata->gpios, pdata->num_gpios);
 }
 
 /*** Clock functions ***/
@@ -1427,9 +1391,10 @@
 	event = &channel->event;
 
 	/* start the clocks if needed */
-	tspp_clock_start(pdev);
-	if (tspp_channels_in_use(pdev) == 0)
+	if (tspp_channels_in_use(pdev) == 0) {
+		tspp_clock_start(pdev);
 		wake_lock(&pdev->wake_lock);
+	}
 
 	/* mark it as used */
 	channel->used = 1;
@@ -1604,9 +1569,10 @@
 	channel->locked = NULL;
 	channel->used = 0;
 
-	if (tspp_channels_in_use(pdev) == 0)
+	if (tspp_channels_in_use(pdev) == 0) {
 		wake_unlock(&pdev->wake_lock);
-	tspp_clock_stop(pdev);
+		tspp_clock_stop(pdev);
+	}
 
 	return 0;
 }
@@ -2554,6 +2520,137 @@
 	}
 }
 
+/* copy device-tree data to platfrom data struct */
+static __devinit struct msm_tspp_platform_data *
+msm_tspp_dt_to_pdata(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct msm_tspp_platform_data *data;
+	struct msm_gpio *gpios;
+	int i, rc;
+	int gpio;
+	u32 gpio_func;
+
+	/* Note: memory allocated by devm_kzalloc is freed automatically */
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		pr_err("tspp: Unable to allocate platform data\n");
+		return NULL;
+	}
+	rc = of_property_read_string(node, "qcom,tsif-pclk", &data->tsif_pclk);
+	if (rc) {
+		pr_err("tspp: Could not find tsif-pclk property, err = %d\n",
+			rc);
+		return NULL;
+	}
+	rc = of_property_read_string(node, "qcom,tsif-ref-clk",
+			&data->tsif_ref_clk);
+	if (rc) {
+		pr_err("tspp: Could not find tsif-ref-clk property, err = %d\n",
+			rc);
+		return NULL;
+	}
+
+	data->num_gpios = of_gpio_count(node);
+	if (data->num_gpios == 0) {
+		pr_err("tspp: Could not find GPIO definitions\n");
+		return NULL;
+	}
+	gpios = devm_kzalloc(&pdev->dev,
+			(data->num_gpios * sizeof(struct msm_gpio)),
+			GFP_KERNEL);
+	if (!gpios) {
+		pr_err("tspp: Unable to allocate memory for GPIOs table\n");
+		return NULL;
+	}
+	/* Assuming GPIO FUNC property is the same for all GPIOs */
+	if (of_property_read_u32(node, "qcom,gpios-func", &gpio_func)) {
+		pr_err("tspp: Could not find gpios-func property\n");
+		return NULL;
+	}
+	for (i = 0; i < data->num_gpios; i++) {
+		gpio = of_get_gpio(node, i);
+		gpios[i].gpio_cfg = GPIO_CFG(gpio, gpio_func,
+						GPIO_CFG_INPUT,
+						GPIO_CFG_PULL_DOWN,
+						GPIO_CFG_2MA);
+		rc = of_property_read_string_index(node, "qcom,gpio-names",
+						i, &gpios[i].label);
+		if (rc)
+			pr_warn("tspp: Could not find gpio-names property\n");
+	}
+
+	data->gpios = gpios;
+
+	return data;
+}
+
+static int msm_tspp_map_irqs(struct platform_device *pdev,
+				struct tspp_device *device)
+{
+	int rc;
+	int i;
+
+	/* get IRQ numbers from platform information */
+
+	/* map TSPP IRQ */
+	rc = platform_get_irq_byname(pdev, "TSIF_TSPP_IRQ");
+	if (rc > 0) {
+		device->tspp_irq = rc;
+		rc = request_irq(device->tspp_irq, tspp_isr, IRQF_SHARED,
+				 dev_name(&pdev->dev), device);
+		if (rc) {
+			dev_err(&pdev->dev,
+				"failed to request TSPP IRQ %d : %d",
+				device->tspp_irq, rc);
+			device->tspp_irq = 0;
+			return -EINVAL;
+		}
+	} else {
+		dev_err(&pdev->dev, "failed to get TSPP IRQ");
+		return -EINVAL;
+	}
+
+	/* map TSIF IRQs */
+	rc = platform_get_irq_byname(pdev, "TSIF0_IRQ");
+	if (rc > 0) {
+		device->tsif[0].tsif_irq = rc;
+	} else {
+		dev_err(&pdev->dev, "failed to get TSIF0 IRQ");
+		return -EINVAL;
+	}
+
+	rc = platform_get_irq_byname(pdev, "TSIF1_IRQ");
+	if (rc > 0) {
+		device->tsif[1].tsif_irq = rc;
+	} else {
+		dev_err(&pdev->dev, "failed to get TSIF1 IRQ");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
+		rc = request_irq(device->tsif[i].tsif_irq,
+				tsif_isr, IRQF_SHARED,
+				dev_name(&pdev->dev), &device->tsif[i]);
+		if (rc) {
+			dev_warn(&pdev->dev, "failed to request TSIF%d IRQ: %d",
+				i, rc);
+			device->tsif[i].tsif_irq = 0;
+		}
+	}
+
+	/* map BAM IRQ */
+	rc = platform_get_irq_byname(pdev, "TSIF_BAM_IRQ");
+	if (rc > 0) {
+		device->bam_irq = rc;
+	} else {
+		dev_err(&pdev->dev, "failed to get TSPP BAM IRQ");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int __devinit msm_tspp_probe(struct platform_device *pdev)
 {
 	int rc = -ENODEV;
@@ -2567,8 +2664,20 @@
 	struct resource *mem_bam;
 	struct tspp_channel *channel;
 
-	/* must have platform data */
-	data = pdev->dev.platform_data;
+	if (pdev->dev.of_node) {
+		/* get information from device tree */
+		data = msm_tspp_dt_to_pdata(pdev);
+		/* get device ID */
+		rc = of_property_read_u32(pdev->dev.of_node,
+					"cell-index", &pdev->id);
+		if (rc)
+			pdev->id = -1;
+
+		pdev->dev.platform_data = data;
+	} else {
+		/* must have platform data */
+		data = pdev->dev.platform_data;
+	}
 	if (!data) {
 		pr_err("tspp: Platform data not available");
 		rc = -EINVAL;
@@ -2617,7 +2726,8 @@
 	}
 
 	/* map I/O memory */
-	mem_tsif0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mem_tsif0 = platform_get_resource_byname(pdev,
+				IORESOURCE_MEM, "MSM_TSIF0_PHYS");
 	if (!mem_tsif0) {
 		pr_err("tspp: Missing tsif0 MEM resource");
 		rc = -ENXIO;
@@ -2630,7 +2740,8 @@
 		goto err_map_tsif0;
 	}
 
-	mem_tsif1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	mem_tsif1 = platform_get_resource_byname(pdev,
+				IORESOURCE_MEM, "MSM_TSIF1_PHYS");
 	if (!mem_tsif1) {
 		dev_err(&pdev->dev, "Missing tsif1 MEM resource");
 		rc = -ENXIO;
@@ -2643,7 +2754,8 @@
 		goto err_map_tsif1;
 	}
 
-	mem_tspp = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	mem_tspp = platform_get_resource_byname(pdev,
+				IORESOURCE_MEM, "MSM_TSPP_PHYS");
 	if (!mem_tspp) {
 		dev_err(&pdev->dev, "Missing MEM resource");
 		rc = -ENXIO;
@@ -2655,7 +2767,8 @@
 		goto err_map_dev;
 	}
 
-	mem_bam = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+	mem_bam = platform_get_resource_byname(pdev,
+				IORESOURCE_MEM, "MSM_TSPP_BAM_PHYS");
 	if (!mem_bam) {
 		pr_err("tspp: Missing bam MEM resource");
 		rc = -ENXIO;
@@ -2670,39 +2783,8 @@
 		goto err_map_bam;
 	}
 
-	/* map TSPP IRQ */
-	rc = platform_get_irq(pdev, 0);
-	if (rc > 0) {
-		device->tspp_irq = rc;
-		rc = request_irq(device->tspp_irq, tspp_isr, IRQF_SHARED,
-				 dev_name(&pdev->dev), device);
-		if (rc) {
-			dev_err(&pdev->dev, "failed to request IRQ %d : %d",
-				device->tspp_irq, rc);
-			goto err_irq;
-		}
-	} else {
-		dev_err(&pdev->dev, "failed to get tspp IRQ");
+	if (msm_tspp_map_irqs(pdev, device))
 		goto err_irq;
-	}
-
-	/* map TSIF IRQs */
-	device->tsif[0].tsif_irq = TSIF1_IRQ;
-	device->tsif[1].tsif_irq = TSIF2_IRQ;
-
-	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
-		rc = request_irq(device->tsif[i].tsif_irq,
-				tsif_isr, IRQF_SHARED,
-				dev_name(&pdev->dev), &device->tsif[i]);
-		if (rc) {
-			dev_warn(&pdev->dev, "failed to request TSIF%d IRQ: %d",
-				i, rc);
-			device->tsif[i].tsif_irq = 0;
-		}
-	}
-
-	/* BAM IRQ */
-	device->bam_irq = TSIF_BAM_IRQ;
 
 	/* GPIOs */
 	rc = tspp_start_gpios(device);
@@ -2737,17 +2819,17 @@
 	device->bam_props.irq = device->bam_irq;
 	device->bam_props.manage = SPS_BAM_MGR_LOCAL;
 
+	if (tspp_clock_start(device) != 0) {
+		dev_err(&pdev->dev, "Can't start clocks");
+		goto err_clock;
+	}
+
 	if (sps_register_bam_device(&device->bam_props,
 		&device->bam_handle) != 0) {
 		pr_err("tspp: failed to register bam");
 		goto err_bam;
 	}
 
-	if (tspp_clock_start(device) != 0) {
-		dev_err(&pdev->dev, "Can't start clocks");
-		goto err_clock;
-	}
-
 	spin_lock_init(&device->spinlock);
 	tasklet_init(&device->tlet, tspp_sps_complete_tlet,
 			(unsigned long)device);
@@ -2756,7 +2838,11 @@
 	tspp_global_reset(device);
 
 	version = readl_relaxed(device->base + TSPP_VERSION);
-	if (version != 1)
+	/*
+	 * TSPP version can be bits [7:0] or alternatively,
+	 * TSPP major version is bits [31:28].
+	 */
+	if ((version != 0x1) && (((version >> 28) & 0xF) != 0x1))
 		pr_warn("tspp: unrecognized hw version=%i", version);
 
 	/* initialize the channels */
@@ -2776,21 +2862,30 @@
 	return 0;
 
 err_channel:
-	/* uninitialize channels */
+	/* un-initialize channels */
 	for (j = 0; j < i; j++) {
 		channel = &(device->channels[i]);
 		device_destroy(tspp_class, channel->cdev.dev);
 		cdev_del(&channel->cdev);
 	}
-err_clock:
+
 	sps_deregister_bam_device(device->bam_handle);
+err_clock:
 err_bam:
 	tspp_debugfs_exit(device);
 	for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
 		tsif_debugfs_exit(&device->tsif[i]);
+
+	tspp_stop_gpios(device);
 err_gpio:
 err_irq:
-	tspp_stop_gpios(device);
+	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
+		if (device->tsif[i].tsif_irq)
+			free_irq(device->tsif[i].tsif_irq,  &device->tsif[i]);
+	}
+	if (device->tspp_irq)
+		free_irq(device->tspp_irq, device);
+
 	iounmap(device->bam_props.virt_addr);
 err_map_bam:
 err_res_bam:
@@ -2830,7 +2925,10 @@
 		cdev_del(&channel->cdev);
 	}
 
+	/* de-registering BAM device requires clocks */
+	tspp_clock_start(device);
 	sps_deregister_bam_device(device->bam_handle);
+	tspp_clock_stop(device);
 
 	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
 		tsif_debugfs_exit(&device->tsif[i]);
@@ -2879,12 +2977,18 @@
 	.runtime_resume = tspp_runtime_resume,
 };
 
+static struct of_device_id msm_match_table[] = {
+	{.compatible = "qcom,msm_tspp"},
+	{}
+};
+
 static struct platform_driver msm_tspp_driver = {
 	.probe          = msm_tspp_probe,
 	.remove         = __exit_p(msm_tspp_remove),
 	.driver         = {
 		.name   = "msm_tspp",
 		.pm     = &tspp_dev_pm_ops,
+		.of_match_table = msm_match_table,
 	},
 };
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 1b2b33a..2fedc97 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1965,7 +1965,7 @@
 			msmsdcc_do_cmdirq(host, status);
 		}
 
-		if (host->curr.data) {
+		if (data) {
 			/* Check for data errors */
 			if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|
 				      MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 5485e27..f9aff40 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1404,6 +1404,8 @@
 				  enum power_supply_property psp,
 				  union power_supply_propval *val)
 {
+	int type;
+
 	/* Check if called before init */
 	if (!the_chip)
 		return -EINVAL;
@@ -1423,10 +1425,11 @@
 			return 0;
 		}
 
-		/* USB with max current greater than 500 mA connected */
-		if (usb_target_ma > USB_WALL_THRESHOLD_MA)
+		type = the_chip->usb_psy.type;
+		if (type == POWER_SUPPLY_TYPE_USB_DCP ||
+			type == POWER_SUPPLY_TYPE_USB_ACA ||
+			type == POWER_SUPPLY_TYPE_USB_CDP)
 			val->intval = is_usb_chg_plugged_in(the_chip);
-			return 0;
 
 		break;
 	default:
@@ -1521,11 +1524,9 @@
 	case POWER_SUPPLY_PROP_ONLINE:
 		val->intval = 0;
 
-		/* USB charging */
-		if (usb_target_ma < USB_WALL_THRESHOLD_MA)
+		if (the_chip->usb_psy.type == POWER_SUPPLY_TYPE_USB)
 			val->intval = is_usb_chg_plugged_in(the_chip);
-		else
-		    return 0;
+
 		break;
 
 	case POWER_SUPPLY_PROP_SCOPE:
@@ -2186,7 +2187,7 @@
 		return -EINVAL;
 	}
 
-	if (type < POWER_SUPPLY_TYPE_USB)
+	if (type < POWER_SUPPLY_TYPE_USB && type > POWER_SUPPLY_TYPE_BATTERY)
 		return -EINVAL;
 
 	the_chip->usb_psy.type = type;
@@ -4757,6 +4758,9 @@
 	platform_set_drvdata(pdev, chip);
 	the_chip = chip;
 
+	/* set initial state of the USB charger type to UNKNOWN */
+	power_supply_set_supply_type(&chip->usb_psy, POWER_SUPPLY_TYPE_UNKNOWN);
+
 	wake_lock_init(&chip->eoc_wake_lock, WAKE_LOCK_SUSPEND, "pm8921_eoc");
 	INIT_DELAYED_WORK(&chip->eoc_work, eoc_worker);
 	INIT_DELAYED_WORK(&chip->vin_collapse_check_work,
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 1bc027c..8002e9e 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -93,6 +93,7 @@
 	int		iavg_ua;
 	int		uuc_uah;
 	int		ocv_charge_uah;
+	int		delta_time_s;
 };
 
 struct raw_soc_params {
@@ -139,8 +140,6 @@
 
 	bool				use_external_rsense;
 
-	unsigned int			start_percent;
-	unsigned int			end_percent;
 	bool				ignore_shutdown_soc;
 	int				shutdown_soc_invalid;
 	int				shutdown_soc;
@@ -569,7 +568,7 @@
 	} else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
 		convert_and_store_ocv(chip, raw);
 		/* forget the old cc value upon ocv */
-		chip->last_cc_uah = 0;
+		chip->last_cc_uah = INT_MIN;
 	} else {
 		raw->last_good_ocv_uv = chip->last_ocv_uv;
 	}
@@ -713,46 +712,18 @@
 }
 
 static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
-				int *iavg_ua)
+				int *iavg_ua, int delta_time_s)
 {
-	int delta_cc_uah, delta_time_s, rc;
-	struct rtc_time tm;
-	struct rtc_device *rtc;
-	unsigned long now_tm_sec = 0;
+	int delta_cc_uah = 0;
 
-	rc = 0;
 	/* if anything fails report the previous iavg_ua */
 	*iavg_ua = chip->prev_iavg_ua;
 
-	rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
-	if (rtc == NULL) {
-		pr_err("%s: unable to open rtc device (%s)\n",
-			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
-		goto out;
-	}
-
-	rc = rtc_read_time(rtc, &tm);
-	if (rc) {
-		pr_err("Error reading rtc device (%s) : %d\n",
-			CONFIG_RTC_HCTOSYS_DEVICE, rc);
-		goto out;
-	}
-
-	rc = rtc_valid_tm(&tm);
-	if (rc) {
-		pr_err("Invalid RTC time (%s): %d\n",
-			CONFIG_RTC_HCTOSYS_DEVICE, rc);
-		goto out;
-	}
-	rtc_tm_to_time(&tm, &now_tm_sec);
-
-	if (chip->tm_sec == 0) {
+	if (chip->last_cc_uah == INT_MIN) {
 		get_battery_current(chip, iavg_ua);
 		goto out;
 	}
 
-	delta_time_s = (now_tm_sec - chip->tm_sec);
-
 	/* use the previous iavg if called within 15 seconds */
 	if (delta_time_s < 15) {
 		*iavg_ua = chip->prev_iavg_ua;
@@ -763,19 +734,13 @@
 
 	*iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
 
-	pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d delta_cc = %d iavg_ua = %d\n",
-				chip->tm_sec, now_tm_sec,
-				delta_time_s, delta_cc_uah, (int)*iavg_ua);
-
 out:
+	pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
 	/* remember the iavg */
 	chip->prev_iavg_ua = *iavg_ua;
 
 	/* remember cc_uah */
 	chip->last_cc_uah = cc_uah;
-
-	/* remember this time */
-	chip->tm_sec = now_tm_sec;
 }
 
 static int calculate_termination_uuc(struct qpnp_bms_chip *chip,
@@ -827,6 +792,7 @@
 	return uuc_uah;
 }
 
+#define TIME_PER_PERCENT_UUC			60
 static int adjust_uuc(struct qpnp_bms_chip *chip,
 			struct soc_params *params,
 			int new_pc_unusable,
@@ -835,18 +801,23 @@
 {
 	int new_unusable_mv, new_iavg_ma;
 	int batt_temp_degc = batt_temp / 10;
+	int max_percent_change;
+
+	max_percent_change = max(params->delta_time_s
+				/ TIME_PER_PERCENT_UUC, 1);
 
 	if (chip->prev_pc_unusable == -EINVAL
-		|| abs(chip->prev_pc_unusable - new_pc_unusable) <= 1) {
+		|| abs(chip->prev_pc_unusable - new_pc_unusable)
+			<= max_percent_change) {
 		chip->prev_pc_unusable = new_pc_unusable;
 		return new_uuc_uah;
 	}
 
 	/* the uuc is trying to change more than 1% restrict it */
 	if (new_pc_unusable > chip->prev_pc_unusable)
-		chip->prev_pc_unusable++;
+		chip->prev_pc_unusable += max_percent_change;
 	else
-		chip->prev_pc_unusable--;
+		chip->prev_pc_unusable -= max_percent_change;
 
 	new_uuc_uah = (params->fcc_uah * chip->prev_pc_unusable) / 100;
 
@@ -976,6 +947,58 @@
 	params->ocv_charge_uah = (int)ocv_charge_uah;
 }
 
+static int get_current_time(unsigned long *now_tm_sec)
+{
+	struct rtc_time tm;
+	struct rtc_device *rtc;
+	int rc;
+
+	rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+	if (rtc == NULL) {
+		pr_err("%s: unable to open rtc device (%s)\n",
+			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
+		rc = -EINVAL;
+		goto close_time;
+	}
+
+	rc = rtc_read_time(rtc, &tm);
+	if (rc) {
+		pr_err("Error reading rtc device (%s) : %d\n",
+			CONFIG_RTC_HCTOSYS_DEVICE, rc);
+		goto close_time;
+	}
+
+	rc = rtc_valid_tm(&tm);
+	if (rc) {
+		pr_err("Invalid RTC time (%s): %d\n",
+			CONFIG_RTC_HCTOSYS_DEVICE, rc);
+		goto close_time;
+	}
+	rtc_tm_to_time(&tm, now_tm_sec);
+
+close_time:
+	rtc_class_close(rtc);
+	return rc;
+}
+
+static int calculate_delta_time(struct qpnp_bms_chip *chip, int *delta_time_s)
+{
+	unsigned long now_tm_sec = 0;
+
+	/* default to delta time = 0 if anything fails */
+	*delta_time_s = 0;
+
+	get_current_time(&now_tm_sec);
+
+	*delta_time_s = (now_tm_sec - chip->tm_sec);
+	pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
+		chip->tm_sec, now_tm_sec, *delta_time_s);
+
+	/* remember this time */
+	chip->tm_sec = now_tm_sec;
+	return 0;
+}
+
 static void calculate_soc_params(struct qpnp_bms_chip *chip,
 						struct raw_soc_params *raw,
 						struct soc_params *params,
@@ -983,6 +1006,7 @@
 {
 	int soc_rbatt;
 
+	calculate_delta_time(chip, &params->delta_time_s);
 	params->fcc_uah = calculate_fcc(chip, batt_temp);
 	pr_debug("FCC = %uuAh batt_temp = %d\n", params->fcc_uah, batt_temp);
 
@@ -1006,7 +1030,8 @@
 		soc_rbatt = 0;
 	params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
 
-	calculate_iavg(chip, params->cc_uah, &params->iavg_ua);
+	calculate_iavg(chip, params->cc_uah, &params->iavg_ua,
+						params->delta_time_s);
 
 	params->uuc_uah = calculate_unusable_charge_uah(chip, params,
 							batt_temp);
@@ -1085,6 +1110,24 @@
 	return 0;
 }
 
+static bool is_battery_charging(struct qpnp_bms_chip *chip)
+{
+	union power_supply_propval ret = {0,};
+
+	if (chip->batt_psy == NULL)
+		chip->batt_psy = power_supply_get_by_name("battery");
+	if (chip->batt_psy) {
+		/* if battery has been registered, use the status property */
+		chip->batt_psy->get_property(chip->batt_psy,
+					POWER_SUPPLY_PROP_STATUS, &ret);
+		return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
+	}
+
+	/* Default to false if the battery power supply is not registered. */
+	pr_debug("battery power supply is not registered\n");
+	return false;
+}
+
 static bool is_batfet_open(struct qpnp_bms_chip *chip)
 {
 	union power_supply_propval ret = {0,};
@@ -1583,7 +1626,7 @@
 	 */
 
 	/* if not charging, return last soc */
-	if (chip->start_percent == -EINVAL)
+	if (!is_battery_charging(chip))
 		return prev_soc;
 
 	chg_time_sec = DIV_ROUND_UP(chip->charge_time_us, USEC_PER_SEC);
@@ -1658,7 +1701,7 @@
 	 * account for charge time - limit it to SOC_CATCHUP_SEC to
 	 * avoid overflows when charging continues for extended periods
 	 */
-	if (chip->start_percent != -EINVAL) {
+	if (is_battery_charging(chip)) {
 		if (chip->charge_time_us == 0) {
 			/*
 			 * calculating soc for the first time
@@ -2005,13 +2048,12 @@
 
 static inline void bms_initialize_constants(struct qpnp_bms_chip *chip)
 {
-	chip->start_percent = -EINVAL;
-	chip->end_percent = -EINVAL;
 	chip->prev_pc_unusable = -EINVAL;
 	chip->soc_at_cv = -EINVAL;
 	chip->calculated_soc = -EINVAL;
 	chip->last_soc = -EINVAL;
 	chip->last_soc_est = -EINVAL;
+	chip->last_cc_uah = INT_MIN;
 	chip->first_time_calc_soc = 1;
 	chip->first_time_calc_uuc = 1;
 }
@@ -2087,6 +2129,7 @@
 static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
 {
 	u8 iadc_channel_select;
+	int32_t rds_rsense_nohm;
 	int rc;
 
 	rc = qpnp_read_wrapper(chip, &iadc_channel_select,
@@ -2097,10 +2140,17 @@
 	}
 
 	iadc_channel_select &= ADC_CH_SEL_MASK;
-	if (iadc_channel_select == INTERNAL_RSENSE) {
-		pr_debug("Internal rsense used\n");
-		if (chip->use_external_rsense) {
-			pr_debug("Changing rsense to external\n");
+	if (iadc_channel_select != EXTERNAL_RSENSE
+			&& iadc_channel_select != INTERNAL_RSENSE) {
+		pr_err("IADC1_BMS_IADC configured incorrectly. Selected channel = %d\n",
+						iadc_channel_select);
+		return -EINVAL;
+	}
+
+	if (chip->use_external_rsense) {
+		pr_debug("External rsense selected\n");
+		if (iadc_channel_select == INTERNAL_RSENSE) {
+			pr_debug("Internal rsense detected; Changing rsense to external\n");
 			rc = qpnp_masked_write_iadc(chip,
 					IADC1_BMS_ADC_CH_SEL_CTL,
 					ADC_CH_SEL_MASK,
@@ -2113,10 +2163,10 @@
 			}
 			reset_cc(chip);
 		}
-	} else if (iadc_channel_select == EXTERNAL_RSENSE) {
-		pr_debug("External rsense used\n");
-		if (!chip->use_external_rsense) {
-			pr_debug("Changing rsense to internal\n");
+	} else {
+		pr_debug("Internal rsense selected\n");
+		if (iadc_channel_select == EXTERNAL_RSENSE) {
+			pr_debug("External rsense detected; Changing rsense to internal\n");
 			rc = qpnp_masked_write_iadc(chip,
 					IADC1_BMS_ADC_CH_SEL_CTL,
 					ADC_CH_SEL_MASK,
@@ -2129,10 +2179,16 @@
 			}
 			reset_cc(chip);
 		}
-	} else {
-		pr_err("IADC1_BMS_IADC configured incorrectly. Selected channel = %d\n",
-							iadc_channel_select);
-		return -EINVAL;
+
+		rc = qpnp_iadc_get_rsense(&rds_rsense_nohm);
+		if (rc) {
+			pr_err("Unable to read RDS resistance value from IADC; rc = %d\n",
+								rc);
+			return rc;
+		}
+		chip->r_sense_mohm = rds_rsense_nohm/1000000;
+		pr_debug("rds_rsense = %d nOhm, saved as %d mOhm\n",
+					rds_rsense_nohm, chip->r_sense_mohm);
 	}
 	return 0;
 }
@@ -2238,10 +2294,9 @@
 	vbatt = 0;
 	get_battery_voltage(&vbatt);
 
-	pr_debug("OK battery_capacity_at_boot=%d vbatt = %d\n",
+	pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_mohm = %u\n",
 				get_prop_bms_capacity(chip),
-				vbatt);
-	pr_info("probe success\n");
+				vbatt, chip->last_ocv_uv, chip->r_sense_mohm);
 	return 0;
 
 unregister_dc:
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 8ff6cff..19e2151 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -2751,7 +2751,7 @@
 		ret = msm_hs_sps_init(msm_uport);
 		if (unlikely(ret)) {
 			pr_err("SPS Initialization failed ! err=%d", ret);
-			goto unmap_memory;
+			goto workqueue_destroy;
 		}
 	}
 
@@ -2761,18 +2761,12 @@
 
 	ret = uartdm_init_port(uport);
 	if (unlikely(ret)) {
-		clk_disable_unprepare(msm_uport->clk);
-		if (msm_uport->pclk)
-			clk_disable_unprepare(msm_uport->pclk);
-		goto unmap_memory;
+		goto err_clock;
 	}
 
 	/* configure the CR Protection to Enable */
 	msm_hs_write(uport, UARTDM_CR_ADDR, CR_PROTECTION_EN);
 
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
 
 	/*
 	 * Enable Command register protection before going ahead as this hw
@@ -2789,7 +2783,7 @@
 
 	ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_clock.attr);
 	if (unlikely(ret))
-		goto unmap_memory;
+		goto err_clock;
 
 	msm_serial_debugfs_init(msm_uport, pdev->id);
 
@@ -2797,9 +2791,19 @@
 	if (pdata != NULL && pdata->userid && pdata->userid <= UARTDM_NR)
 		uport->line = pdata->userid;
 	ret = uart_add_one_port(&msm_hs_driver, uport);
-	if (!ret)
+	if (!ret) {
+		clk_disable_unprepare(msm_uport->clk);
+		if (msm_uport->pclk)
+			clk_disable_unprepare(msm_uport->pclk);
 		return ret;
+	}
 
+err_clock:
+	clk_disable_unprepare(msm_uport->clk);
+	if (msm_uport->pclk)
+		clk_disable_unprepare(msm_uport->pclk);
+workqueue_destroy:
+	destroy_workqueue(msm_uport->hsuart_wq);
 unmap_memory:
 	iounmap(uport->membase);
 	if (is_blsp_uart(msm_uport))
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index 20d6781..9fa4f55 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -215,7 +215,7 @@
 #ifdef CONFIG_MSM_UARTDM_Core_v14
 
 /* write only register */
-#define UARTDM_CSR_ADDR    0x0a
+#define UARTDM_CSR_ADDR    0xa0
 
 /* write only register */
 #define UARTDM_TF_ADDR   0x100
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index 085d0bd..70192de 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -408,6 +408,7 @@
 {
 	pr_debug("qdss_unbind\n");
 
+	clear_eps(f);
 	clear_desc(c->cdev->gadget, f);
 }
 
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 00744fb..fe39700 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -652,7 +652,8 @@
 
 static void gbam2bam_disconnect_work(struct work_struct *w)
 {
-	struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
+	struct gbam_port *port =
+			container_of(w, struct gbam_port, disconnect_w);
 	struct bam_ch_info *d = &port->data_ch;
 	int ret;
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 2c26998..df41b4f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2464,7 +2464,7 @@
 	/* Wait for the configure endpoint command to complete */
 	timeleft = wait_for_completion_interruptible_timeout(
 			cmd_completion,
-			USB_CTRL_SET_TIMEOUT);
+			XHCI_CMD_DEFAULT_TIMEOUT);
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for %s command\n",
 				timeleft == 0 ? "Timeout" : "Signal",
@@ -3433,7 +3433,7 @@
 
 	/* XXX: how much time for xHC slot assignment? */
 	timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
-			USB_CTRL_SET_TIMEOUT);
+			XHCI_CMD_DEFAULT_TIMEOUT);
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for a slot\n",
 				timeleft == 0 ? "Timeout" : "Signal");
@@ -3549,7 +3549,7 @@
 
 	/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
 	timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
-			USB_CTRL_SET_TIMEOUT);
+			XHCI_CMD_DEFAULT_TIMEOUT);
 	/* FIXME: From section 4.3.4: "Software shall be responsible for timing
 	 * the SetAddress() "recovery interval" required by USB and aborting the
 	 * command on a timeout.
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 127b0e9..8f3651b 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1248,6 +1248,9 @@
 	union xhci_trb		*last_trb;
 };
 
+/* xHCI command default timeout value */
+#define XHCI_CMD_DEFAULT_TIMEOUT	(5 * HZ)
+
 struct xhci_dequeue_state {
 	struct xhci_segment *new_deq_seg;
 	union xhci_trb *new_deq_ptr;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index a4bb7b2..2439af0 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1197,7 +1197,7 @@
 		motg->chg_type == USB_ACA_C_CHARGER))
 		charger_type = POWER_SUPPLY_TYPE_USB_ACA;
 	else
-		charger_type = POWER_SUPPLY_TYPE_BATTERY;
+		charger_type = POWER_SUPPLY_TYPE_UNKNOWN;
 
 	if (!psy) {
 		pr_err("No USB power supply registered!\n");
@@ -2276,6 +2276,11 @@
 	case USB_CHG_STATE_SECONDARY_DONE:
 		motg->chg_state = USB_CHG_STATE_DETECTED;
 	case USB_CHG_STATE_DETECTED:
+		/*
+		 * Notify the charger type to power supply
+		 * owner as soon as we determine the charger.
+		 */
+		msm_otg_notify_chg_type(motg);
 		msm_chg_block_off(motg);
 		msm_chg_enable_aca_det(motg);
 		/*
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 4858073..38fc969 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -634,6 +634,7 @@
 #if defined(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL)
 	if (isr & INTR_OVERLAY2_DONE) {
 		mdp4_stat.intr_overlay2++;
+		mdp_pipe_ctrl(MDP_OVERLAY2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 		/* disable DTV interrupt */
 		if (panel & MDP4_PANEL_WRITEBACK)
 			mdp4_overlay2_done_wfd(&dma_wb_data);
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index b6ac126..a7f0148 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -340,6 +340,7 @@
 #define MDSS_MDP_REG_DSPP_HIST_LUT_BASE			0x230
 #define MDSS_MDP_REG_DSPP_PA_BASE			0x238
 #define MDSS_MDP_REG_DSPP_GAMUT_BASE			0x2DC
+#define MDSS_MDP_REG_DSPP_GC_BASE			0x2B0
 
 enum mdss_mpd_intf_index {
 	MDSS_MDP_NO_INTF,
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 1482935..7fd6a58 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -131,6 +131,7 @@
 	u32 enhist_sts;
 	u32 dither_sts;
 	u32 gamut_sts;
+	u32 pgc_sts;
 };
 
 #define PP_FLAGS_DIRTY_PA	0x1
@@ -141,6 +142,7 @@
 #define PP_FLAGS_DIRTY_DITHER	0x20
 #define PP_FLAGS_DIRTY_GAMUT	0x40
 #define PP_FLAGS_DIRTY_HIST_COL	0x80
+#define PP_FLAGS_DIRTY_PGC	0x100
 
 #define PP_STS_ENABLE	0x1
 #define PP_STS_GAMUT_FIRST	0x2
@@ -160,6 +162,7 @@
 	struct mdp_pa_cfg_data pa_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_pcc_cfg_data pcc_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_igc_lut_data igc_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	struct mdp_pgc_lut_data argc_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_pgc_lut_data pgc_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_hist_lut_data enhist_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_dither_cfg_data dither_disp_cfg[MDSS_BLOCK_DISP_NUM];
@@ -287,6 +290,7 @@
 	struct mdp_pgc_lut_data *pgc_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))
@@ -299,7 +303,7 @@
 	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
 	/* GC_LUT is in layer mixer */
 	if (flags & PP_FLAGS_DIRTY_ARGC) {
-		pgc_config = &mdss_pp_res->pgc_disp_cfg[disp_num];
+		pgc_config = &mdss_pp_res->argc_disp_cfg[disp_num];
 		if (pgc_config->flags & MDP_PP_OPS_WRITE) {
 			offset = MDSS_MDP_REG_LM_OFFSET(disp_num) +
 				MDSS_MDP_REG_LM_GC_LUT_BASE;
@@ -378,10 +382,12 @@
 	struct mdp_hist_lut_data *enhist_cfg;
 	struct mdp_dither_cfg_data *dither_cfg;
 	struct pp_hist_col_info *hist_info;
+	struct mdp_pgc_lut_data *pgc_config;
 	struct pp_sts_type *pp_sts;
 	u32 data, tbl_idx, col_state;
 	unsigned long flag;
 	int i;
+
 	dspp_num = mixer->num;
 	/* no corresponding dspp */
 	if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
@@ -533,6 +539,20 @@
 			opmode |= (1 << 24); /* GAMUT_ORDER */
 	}
 
+	if (flags & PP_FLAGS_DIRTY_PGC) {
+		pgc_config = &mdss_pp_res->pgc_disp_cfg[disp_num];
+		if (pgc_config->flags & MDP_PP_OPS_WRITE) {
+			offset = base + MDSS_MDP_REG_DSPP_GC_BASE;
+			pp_update_argc_lut(offset, pgc_config);
+		}
+		if (pgc_config->flags & MDP_PP_OPS_DISABLE)
+			pp_sts->pgc_sts &= ~PP_STS_ENABLE;
+		else if (pgc_config->flags & MDP_PP_OPS_ENABLE)
+			pp_sts->pgc_sts |= PP_STS_ENABLE;
+	}
+	if (pp_sts->pgc_sts & PP_STS_ENABLE)
+		opmode |= (1 << 22);
+
 	MDSS_MDP_REG_WRITE(base + MDSS_MDP_REG_DSPP_OP_MODE, opmode);
 	ctl->flush_bits |= BIT(13 + dspp_num); /* DSPP */
 	return 0;
@@ -1039,18 +1059,40 @@
 int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config, u32 *copyback)
 {
 	int ret = 0;
-	u32 argc_offset, disp_num, dspp_num = 0;
+	u32 argc_offset = 0, disp_num, dspp_num = 0;
 	struct mdp_pgc_lut_data local_cfg;
+	struct mdp_pgc_lut_data *pgc_ptr;
 	u32 tbl_size;
 
-	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
-		(config->block >= MDP_BLOCK_MAX))
+	if ((PP_BLOCK(config->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(PP_BLOCK(config->block) >= MDP_BLOCK_MAX))
 		return -EINVAL;
 
 	mutex_lock(&mdss_pp_mutex);
-	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+	disp_num = PP_BLOCK(config->block) - MDP_LOGICAL_BLOCK_DISP_0;
+	switch (config->block & MDSS_PP_LOCATION_MASK) {
+	case MDSS_PP_LM_CFG:
+		argc_offset = MDSS_MDP_REG_LM_OFFSET(dspp_num) +
+			MDSS_MDP_REG_LM_GC_LUT_BASE;
+		pgc_ptr = &mdss_pp_res->argc_disp_cfg[disp_num];
+		mdss_pp_res->pp_disp_flags[disp_num] |=
+			PP_FLAGS_DIRTY_ARGC;
+		break;
+	case MDSS_PP_DSPP_CFG:
+		argc_offset = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
+					MDSS_MDP_REG_DSPP_GC_BASE;
+		pgc_ptr = &mdss_pp_res->pgc_disp_cfg[disp_num];
+		mdss_pp_res->pp_disp_flags[disp_num] |=
+			PP_FLAGS_DIRTY_PGC;
+		break;
+	default:
+		goto argc_config_exit;
+		break;
+	}
 
 	tbl_size = GC_LUT_SEGMENTS * sizeof(struct mdp_ar_gc_lut_data);
+
 	if (config->flags & MDP_PP_OPS_READ) {
 		ret = pp_get_dspp_num(disp_num, &dspp_num);
 		if (ret) {
@@ -1059,10 +1101,6 @@
 			goto argc_config_exit;
 		}
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-
-		argc_offset = MDSS_MDP_REG_LM_OFFSET(dspp_num) +
-				MDSS_MDP_REG_LM_GC_LUT_BASE;
-		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 		local_cfg = *config;
 		local_cfg.r_data =
 			&mdss_pp_res->gc_lut_r[disp_num][0];
@@ -1104,14 +1142,14 @@
 			ret = -EFAULT;
 			goto argc_config_exit;
 		}
-		mdss_pp_res->pgc_disp_cfg[disp_num] = *config;
-		mdss_pp_res->pgc_disp_cfg[disp_num].r_data =
+
+		*pgc_ptr = *config;
+		pgc_ptr->r_data =
 			&mdss_pp_res->gc_lut_r[disp_num][0];
-		mdss_pp_res->pgc_disp_cfg[disp_num].g_data =
+		pgc_ptr->g_data =
 			&mdss_pp_res->gc_lut_g[disp_num][0];
-		mdss_pp_res->pgc_disp_cfg[disp_num].b_data =
+		pgc_ptr->b_data =
 			&mdss_pp_res->gc_lut_b[disp_num][0];
-		mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_ARGC;
 	}
 argc_config_exit:
 	mutex_unlock(&mdss_pp_mutex);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 1b7bed6..582744c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -491,9 +491,6 @@
 	struct ddl_encoder_data *encoder =
 		&ddl->codec_data.encoder;
 	u32 vcd_status = VCD_S_SUCCESS;
-	struct vcd_transc *transc;
-	transc = (struct vcd_transc *)(ddl->client_data);
-	DDL_MSG_LOW("%s: transc = 0x%x", __func__, (u32)ddl->client_data);
 	if (encoder->slice_delivery_info.enable) {
 		return ddl_encode_frame_batch(ddl_handle,
 					input_frame,
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 729fb2e..77faee3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -506,6 +506,8 @@
 
 	width_round_up  = width;
 	height_round_up = height;
+	align = SZ_4K;
+
 	if (format == DDL_YUV_BUF_TYPE_TILE) {
 		width_round_up  = DDL_ALIGN(width, DDL_TILE_ALIGN_WIDTH);
 		height_round_up = DDL_ALIGN(height, DDL_TILE_ALIGN_HEIGHT);
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 163af21..64cc570 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
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1811,8 +1811,10 @@
 	slice_output = (struct vidc_1080p_enc_slice_batch_out_param *)
 		(encoder->batch_frame.slice_batch_out.align_virtual_addr);
 	DDL_MSG_LOW(" after get no of slices = %d\n", num_slices_comp);
-	if (slice_output == NULL)
+	if (slice_output == NULL) {
 		DDL_MSG_ERROR(" slice_output is NULL\n");
+		return; /* Bail out */
+	}
 	encoder->slice_delivery_info.num_slices_enc += num_slices_comp;
 	if (vidc_msg_timing) {
 		ddl_calc_core_proc_time_cnt(__func__, ENC_SLICE_OP_TIME,
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 d9cadef..c15218d 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
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -160,9 +160,13 @@
 static void res_trk_pmem_free(struct ddl_buf_addr *addr)
 {
 	struct ddl_context *ddl_context;
+
+	if (!addr)
+		return;
+
 	ddl_context = ddl_get_context();
 	if (ddl_context->video_ion_client) {
-		if (addr && addr->alloc_handle) {
+		if (addr->alloc_handle) {
 			ion_free(ddl_context->video_ion_client,
 			 addr->alloc_handle);
 			addr->alloc_handle = NULL;
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 48f127a..afc5130 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2485,7 +2485,7 @@
 	}
 
 	client_index = vid_dec_get_empty_client_index();
-	if (client_index == -1) {
+	if (client_index < 0) {
 		ERR("%s() : No free clients client_index == -1\n", __func__);
 		rc = -ENOMEM;
 		goto client_failure;
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index c18bb92..0648257 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -557,7 +557,7 @@
 
 	client_index = vid_enc_get_empty_client_index();
 
-	if (client_index == -1) {
+	if (client_index < 0) {
 		ERR("%s() : No free clients client_index == -1\n",
 			__func__);
 		rc = -ENODEV;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 884050b..14c8030 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -1628,6 +1628,7 @@
 	if (!cctxt || to_state >= VCD_CLIENT_STATE_MAX) {
 		VCD_MSG_ERROR("Bad parameters. cctxt=%p, to_state=%d",
 			      cctxt, to_state);
+		return;
 	}
 
 	state_ctxt = &cctxt->clnt_state;
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 f670a4a..9074358 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -36,6 +36,7 @@
 	if (!drv_ctxt || to_state >= VCD_DEVICE_STATE_MAX) {
 		VCD_MSG_ERROR("Bad parameters. drv_ctxt=%p, to_state=%d",
 				  drv_ctxt, to_state);
+		return;
 	}
 
 	state_ctxt = &drv_ctxt->dev_state;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
index ab21bac..fe0e131 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -88,8 +88,13 @@
 			prop_hdr.sz = sizeof(cctxt->frm_p_units);
 			rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr,
 						  &cctxt->frm_p_units);
-			VCD_FAILED_RETURN(rc,
-				"Failed: Get DDL_I_FRAME_PROC_UNITS");
+			if (VCD_FAILED(rc)) {
+				kfree(sched_cctxt);
+				VCD_MSG_ERROR(
+					"Failed: Get DDL_I_FRAME_PROC_UNITS");
+				return rc;
+			}
+
 			if (cctxt->decoding) {
 				cctxt->frm_rate.fps_numerator =
 					VCD_DEC_INITIAL_FRAME_RATE;
@@ -99,8 +104,12 @@
 				prop_hdr.sz = sizeof(cctxt->frm_rate);
 				rc = ddl_get_property(cctxt->ddl_handle,
 						&prop_hdr, &cctxt->frm_rate);
-				VCD_FAILED_RETURN(rc,
-					"Failed: Get VCD_I_FRAME_RATE");
+				if (VCD_FAILED(rc)) {
+					kfree(sched_cctxt);
+					VCD_MSG_ERROR(
+						"Failed: Get VCD_I_FRAME_RATE");
+					return rc;
+				}
 			}
 			if (!cctxt->perf_set_by_client)
 				cctxt->reqd_perf_lvl = cctxt->frm_p_units *
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 78d77d1..09cd91d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2022,6 +2022,11 @@
 	orig_frame = vcd_find_buffer_pool_entry(&cctxt->in_buf_pool,
 					 transc->ip_buf_entry->virtual);
 
+	if (!orig_frame) {
+		rc = VCD_ERR_ILLEGAL_PARM;
+		VCD_FAILED_RETURN(rc, "Couldn't find buffer");
+	}
+
 	if ((transc->ip_buf_entry->frame.virtual !=
 		 frame->vcd_frm.virtual)
 		|| !transc->ip_buf_entry->in_use) {
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 8260ef7..4effce6 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -172,6 +172,7 @@
 	__s32		disable_ipv6;
 	__s32		accept_dad;
 	__s32		force_tllao;
+	__s32		accept_ra_prefix_route;
 	void		*sysctl;
 };
 
@@ -213,6 +214,7 @@
 	DEVCONF_DISABLE_IPV6,
 	DEVCONF_ACCEPT_DAD,
 	DEVCONF_FORCE_TLLAO,
+	DEVCONF_ACCEPT_RA_PREFIX_ROUTE,
 	DEVCONF_MAX
 };
 
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index fdb8fb6..56eda83 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -286,6 +286,18 @@
 #define MDP_PP_IGC_FLAG_ROM0	0x10
 #define MDP_PP_IGC_FLAG_ROM1	0x20
 
+#define MDSS_PP_DSPP_CFG	0x0000
+#define MDSS_PP_SSPP_CFG	0x4000
+#define MDSS_PP_LM_CFG	0x8000
+#define MDSS_PP_WB_CFG	0xC000
+
+#define MDSS_PP_LOCATION_MASK	0xC000
+#define MDSS_PP_LOGICAL_MASK	0x3FFF
+
+#define PP_LOCAT(var) ((var) & MDSS_PP_LOCATION_MASK)
+#define PP_BLOCK(var) ((var) & MDSS_PP_LOGICAL_MASK)
+
+
 struct mdp_qseed_cfg {
 	uint32_t table_num;
 	uint32_t ops;
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 3ab7b9d..903cc3f 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1228,6 +1228,12 @@
 int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
 				struct qpnp_iadc_result *result);
 /**
+ * qpnp_iadc_get_rsense() - Reads the RDS resistance value from the
+			trim registers.
+ * @rsense:	RDS resistance in nOhms.
+ */
+int32_t qpnp_iadc_get_rsense(int32_t *rsense);
+/**
  * qpnp_iadc_get_gain_and_offset() - Performs gain calibration
  *				over 17.8571mV and offset over selected
  *				channel. Channel can be internal rsense,
@@ -1314,6 +1320,8 @@
 { return -ENXIO; }
 static inline int32_t qpnp_adc_tm_is_ready(void)
 { return -ENXIO; }
+static inline int32_t qpnp_iadc_get_rsense(int32_t *rsense)
+{ return -ENXIO; }
 #endif
 
 #endif
diff --git a/include/media/Kbuild b/include/media/Kbuild
index fc764eb..43cc3b9 100644
--- a/include/media/Kbuild
+++ b/include/media/Kbuild
@@ -9,3 +9,7 @@
 header-y += msm_jpeg.h
 header-y += msm_media_info.h
 header-y += msm_vidc.h
+header-y += msmb_camera.h
+header-y += msm_cam_sensor.h
+header-y += msmb_isp.h
+header-y += msmb_ispif.h
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
new file mode 100644
index 0000000..a96a067
--- /dev/null
+++ b/include/media/msm_cam_sensor.h
@@ -0,0 +1,303 @@
+#ifndef __LINUX_MSM_CAM_SENSOR_H
+#define __LINUX_MSM_CAM_SENSOR_H
+
+#ifdef MSM_CAMERA_BIONIC
+#include <sys/types.h>
+#endif
+#include <linux/types.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/i2c.h>
+
+#define I2C_SEQ_REG_SETTING_MAX   5
+#define I2C_SEQ_REG_DATA_MAX      20
+#define MAX_CID                   16
+
+#define MSM_SENSOR_MCLK_8HZ   8000000
+#define MSM_SENSOR_MCLK_16HZ  16000000
+#define MSM_SENSOR_MCLK_24HZ  24000000
+
+#define GPIO_OUT_LOW          (0 << 1)
+#define GPIO_OUT_HIGH         (1 << 1)
+
+#define CSI_EMBED_DATA        0x12
+#define CSI_RESERVED_DATA_0   0x13
+#define CSI_YUV422_8          0x1E
+#define CSI_RAW8              0x2A
+#define CSI_RAW10             0x2B
+#define CSI_RAW12             0x2C
+
+#define CSI_DECODE_6BIT         0
+#define CSI_DECODE_8BIT         1
+#define CSI_DECODE_10BIT        2
+#define CSI_DECODE_DPCM_10_8_10 5
+
+#define MAX_SENSOR_NAME 32
+
+enum msm_camera_i2c_reg_addr_type {
+	MSM_CAMERA_I2C_BYTE_ADDR = 1,
+	MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+enum msm_camera_i2c_data_type {
+	MSM_CAMERA_I2C_BYTE_DATA = 1,
+	MSM_CAMERA_I2C_WORD_DATA,
+	MSM_CAMERA_I2C_SET_BYTE_MASK,
+	MSM_CAMERA_I2C_UNSET_BYTE_MASK,
+	MSM_CAMERA_I2C_SET_WORD_MASK,
+	MSM_CAMERA_I2C_UNSET_WORD_MASK,
+	MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA,
+};
+
+enum msm_sensor_power_seq_type_t {
+	SENSOR_CLK,
+	SENSOR_GPIO,
+	SENSOR_VREG,
+	SENSOR_I2C_MUX,
+};
+
+enum msm_sensor_clk_type_t {
+	SENSOR_CAM_MCLK,
+	SENSOR_CAM_CLK,
+	SENSOR_CAM_CLK_MAX,
+};
+
+enum msm_sensor_power_seq_gpio_t {
+	SENSOR_GPIO_RESET,
+	SENSOR_GPIO_STANDBY,
+	SENSOR_GPIO_MAX,
+};
+
+enum msm_camera_vreg_name_t {
+	CAM_VDIG,
+	CAM_VIO,
+	CAM_VANA,
+	CAM_VAF,
+	CAM_VREG_MAX,
+};
+
+enum msm_sensor_resolution_t {
+	MSM_SENSOR_RES_FULL,
+	MSM_SENSOR_RES_QTR,
+	MSM_SENSOR_RES_2,
+	MSM_SENSOR_RES_3,
+	MSM_SENSOR_RES_4,
+	MSM_SENSOR_RES_5,
+	MSM_SENSOR_RES_6,
+	MSM_SENSOR_RES_7,
+	MSM_SENSOR_INVALID_RES,
+};
+
+enum sensor_sub_module_t {
+	SUB_MODULE_SENSOR,
+	SUB_MODULE_CHROMATIX,
+	SUB_MODULE_ACTUATOR,
+	SUB_MODULE_EEPROM,
+	SUB_MODULE_LED_FLASH,
+	SUB_MODULE_STROBE_FLASH,
+	SUB_MODULE_CSIPHY,
+	SUB_MODULE_CSIPHY_3D,
+	SUB_MODULE_CSID,
+	SUB_MODULE_CSID_3D,
+	SUB_MODULE_MAX,
+};
+
+enum csid_cfg_type_t {
+	CSID_INIT,
+	CSID_CFG,
+	CSID_RELEASE,
+};
+
+enum csiphy_cfg_type_t {
+	CSIPHY_INIT,
+	CSIPHY_CFG,
+	CSIPHY_RELEASE,
+};
+
+enum camera_vreg_type {
+	REG_LDO,
+	REG_VS,
+	REG_GPIO,
+};
+
+struct msm_sensor_power_setting {
+	enum msm_sensor_power_seq_type_t seq_type;
+	uint16_t seq_val;
+	long config_val;
+	uint16_t delay;
+	void *data[10];
+};
+
+struct msm_sensor_power_setting_array {
+	struct msm_sensor_power_setting *power_setting;
+	uint16_t size;
+};
+
+struct msm_sensor_id_info_t {
+	uint16_t sensor_id_reg_addr;
+	uint16_t sensor_id;
+};
+
+struct msm_camera_sensor_slave_info {
+	uint16_t slave_addr;
+	enum msm_camera_i2c_reg_addr_type addr_type;
+	struct msm_sensor_id_info_t sensor_id_info;
+	struct msm_sensor_power_setting_array power_setting_array;
+};
+
+struct msm_camera_i2c_reg_array {
+	uint16_t reg_addr;
+	uint16_t reg_data;
+};
+
+struct msm_camera_i2c_reg_setting {
+	struct msm_camera_i2c_reg_array *reg_setting;
+	uint16_t size;
+	enum msm_camera_i2c_reg_addr_type addr_type;
+	enum msm_camera_i2c_data_type data_type;
+	uint16_t delay;
+};
+
+struct msm_camera_i2c_seq_reg_array {
+	uint16_t reg_addr;
+	uint8_t reg_data[I2C_SEQ_REG_DATA_MAX];
+	uint16_t reg_data_size;
+};
+
+struct msm_camera_i2c_seq_reg_setting {
+	struct msm_camera_i2c_seq_reg_array *reg_setting;
+	uint16_t size;
+	enum msm_camera_i2c_reg_addr_type addr_type;
+	uint16_t delay;
+};
+
+struct msm_camera_csid_vc_cfg {
+	uint8_t cid;
+	uint8_t dt;
+	uint8_t decode_format;
+};
+
+struct msm_camera_csid_lut_params {
+	uint8_t num_cid;
+	struct msm_camera_csid_vc_cfg *vc_cfg[MAX_CID];
+};
+
+struct msm_camera_csid_params {
+	uint8_t lane_cnt;
+	uint16_t lane_assign;
+	uint8_t phy_sel;
+	struct msm_camera_csid_lut_params lut_params;
+};
+
+struct msm_camera_csiphy_params {
+	uint8_t lane_cnt;
+	uint8_t settle_cnt;
+	uint16_t lane_mask;
+	uint8_t combo_mode;
+};
+
+struct msm_camera_csi2_params {
+	struct msm_camera_csid_params csid_params;
+	struct msm_camera_csiphy_params csiphy_params;
+};
+
+struct msm_camera_csi_lane_params {
+	uint16_t csi_lane_assign;
+	uint16_t csi_lane_mask;
+};
+
+struct csi_lane_params_t {
+	uint16_t csi_lane_assign;
+	uint8_t csi_lane_mask;
+	uint8_t csi_if;
+	uint8_t csid_core[2];
+	uint8_t csi_phy_sel;
+};
+
+struct msm_sensor_info_t {
+	char sensor_name[MAX_SENSOR_NAME];
+	int32_t    session_id;
+	int32_t     subdev_id[SUB_MODULE_MAX];
+};
+
+struct camera_vreg_t {
+	const char *reg_name;
+	enum camera_vreg_type type;
+	int min_voltage;
+	int max_voltage;
+	int op_mode;
+	uint32_t delay;
+};
+
+enum camb_position_t {
+	BACK_CAMERA_B,
+	FRONT_CAMERA_B,
+};
+
+enum camerab_mode_t {
+	CAMERA_MODE_2D_B = (1<<0),
+	CAMERA_MODE_3D_B = (1<<1)
+};
+
+struct msm_sensor_init_params {
+	/* mask of modes supported: 2D, 3D */
+	int                 modes_supported;
+	/* sensor position: front, back */
+	enum camb_position_t position;
+	/* sensor mount angle */
+	uint32_t            sensor_mount_angle;
+};
+
+struct sensorb_cfg_data {
+	int cfgtype;
+	union {
+		struct msm_sensor_info_t      sensor_info;
+		struct msm_sensor_init_params sensor_init_params;
+		void                         *setting;
+	} cfg;
+};
+
+struct csid_cfg_data {
+	enum csid_cfg_type_t cfgtype;
+	union {
+		uint32_t csid_version;
+		struct msm_camera_csid_params *csid_params;
+	} cfg;
+};
+
+struct csiphy_cfg_data {
+	enum csiphy_cfg_type_t cfgtype;
+	union {
+		struct msm_camera_csiphy_params *csiphy_params;
+		struct msm_camera_csi_lane_params *csi_lane_params;
+	} cfg;
+};
+
+enum msm_sensor_cfg_type_t {
+	CFG_SET_SLAVE_INFO,
+	CFG_WRITE_I2C_ARRAY,
+	CFG_WRITE_I2C_SEQ_ARRAY,
+	CFG_POWER_UP,
+	CFG_POWER_DOWN,
+	CFG_SET_STOP_STREAM_SETTING,
+	CFG_GET_SENSOR_INFO,
+	CFG_GET_SENSOR_INIT_PARAMS,
+};
+
+#define VIDIOC_MSM_SENSOR_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct sensorb_cfg_data)
+
+#define VIDIOC_MSM_SENSOR_RELEASE \
+	_IO('V', BASE_VIDIOC_PRIVATE + 2)
+
+#define VIDIOC_MSM_SENSOR_GET_SUBDEV_ID \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 3, uint32_t)
+
+#define VIDIOC_MSM_CSIPHY_IO_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csid_cfg_data)
+
+#define VIDIOC_MSM_CSID_IO_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct csiphy_cfg_data)
+
+#define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
+
+#endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 971c9b3..9c310a9 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1595,6 +1595,19 @@
 	REG_GPIO,
 };
 
+enum msm_camera_vreg_name_t {
+	CAM_VDIG,
+	CAM_VIO,
+	CAM_VANA,
+	CAM_VAF,
+	CAM_VREG_MAX,
+};
+
+struct msm_camera_csi_lane_params {
+	uint16_t csi_lane_assign;
+	uint16_t csi_lane_mask;
+};
+
 struct camera_vreg_t {
 	const char *reg_name;
 	enum camera_vreg_type type;
diff --git a/include/media/msmb_camera.h b/include/media/msmb_camera.h
new file mode 100644
index 0000000..732f60b
--- /dev/null
+++ b/include/media/msmb_camera.h
@@ -0,0 +1,159 @@
+#ifndef __LINUX_MSMB_CAMERA_H
+#define __LINUX_MSMB_CAMERA_H
+
+#include <linux/videodev2.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define MSM_CAM_V4L2_IOCTL_NOTIFY \
+	_IOW('V', BASE_VIDIOC_PRIVATE + 30, struct v4l2_event)
+
+#define MSM_CAM_V4L2_IOCTL_NOTIFY_META \
+	_IOW('V', BASE_VIDIOC_PRIVATE + 31, struct v4l2_event)
+
+#define MSM_CAM_V4L2_IOCTL_CMD_ACK \
+	_IOW('V', BASE_VIDIOC_PRIVATE + 32, struct v4l2_event)
+
+#define QCAMERA_DEVICE_GROUP_ID	1
+#define QCAMERA_VNODE_GROUP_ID	2
+#define MSM_CAMERA_NAME					"msm_camera"
+#define MSM_CONFIGURATION_NAME	"msm_config"
+
+#define MSM_CAMERA_SUBDEV_CSIPHY       0
+#define MSM_CAMERA_SUBDEV_CSID         1
+#define MSM_CAMERA_SUBDEV_ISPIF        2
+#define MSM_CAMERA_SUBDEV_VFE          3
+#define MSM_CAMERA_SUBDEV_AXI          4
+#define MSM_CAMERA_SUBDEV_VPE          5
+#define MSM_CAMERA_SUBDEV_SENSOR       6
+#define MSM_CAMERA_SUBDEV_ACTUATOR     7
+#define MSM_CAMERA_SUBDEV_EEPROM       8
+#define MSM_CAMERA_SUBDEV_CPP          9
+#define MSM_CAMERA_SUBDEV_CCI          10
+#define MSM_CAMERA_SUBDEV_LED_FLASH    11
+#define MSM_CAMERA_SUBDEV_STROBE_FLASH 12
+
+#define MSM_MAX_CAMERA_SENSORS  5
+
+/* featur base */
+#define MSM_CAMERA_FEATURE_BASE     0x00010000
+#define MSM_CAMERA_FEATURE_SHUTDOWN (MSM_CAMERA_FEATURE_BASE + 1)
+
+#define MSM_CAMERA_STATUS_BASE      0x00020000
+#define MSM_CAMERA_STATUS_FAIL      (MSM_CAMERA_STATUS_BASE + 1)
+#define MSM_CAMERA_STATUS_SUCCESS   (MSM_CAMERA_STATUS_BASE + 2)
+
+/* event type */
+#define MSM_CAMERA_V4L2_EVENT_TYPE (V4L2_EVENT_PRIVATE_START + 0x00002000)
+
+/* event id */
+#define MSM_CAMERA_EVENT_MIN    0
+#define MSM_CAMERA_NEW_SESSION  (MSM_CAMERA_EVENT_MIN + 1)
+#define MSM_CAMERA_DEL_SESSION  (MSM_CAMERA_EVENT_MIN + 2)
+#define MSM_CAMERA_SET_PARM     (MSM_CAMERA_EVENT_MIN + 3)
+#define MSM_CAMERA_GET_PARM     (MSM_CAMERA_EVENT_MIN + 4)
+#define MSM_CAMERA_MAPPING_CFG  (MSM_CAMERA_EVENT_MIN + 5)
+#define MSM_CAMERA_MAPPING_SES  (MSM_CAMERA_EVENT_MIN + 6)
+#define MSM_CAMERA_MSM_NOTIFY   (MSM_CAMERA_EVENT_MIN + 7)
+#define MSM_CAMERA_EVENT_MAX    (MSM_CAMERA_EVENT_MIN + 8)
+
+/* data.command */
+#define MSM_CAMERA_PRIV_S_CROP		 (V4L2_CID_PRIVATE_BASE + 1)
+#define MSM_CAMERA_PRIV_G_CROP		 (V4L2_CID_PRIVATE_BASE + 2)
+#define MSM_CAMERA_PRIV_G_FMT			 (V4L2_CID_PRIVATE_BASE + 3)
+#define MSM_CAMERA_PRIV_S_FMT			 (V4L2_CID_PRIVATE_BASE + 4)
+#define MSM_CAMERA_PRIV_TRY_FMT		 (V4L2_CID_PRIVATE_BASE + 5)
+#define MSM_CAMERA_PRIV_METADATA	 (V4L2_CID_PRIVATE_BASE + 6)
+#define MSM_CAMERA_PRIV_QUERY_CAP  (V4L2_CID_PRIVATE_BASE + 7)
+#define MSM_CAMERA_PRIV_STREAM_ON  (V4L2_CID_PRIVATE_BASE + 8)
+#define MSM_CAMERA_PRIV_STREAM_OFF (V4L2_CID_PRIVATE_BASE + 9)
+#define MSM_CAMERA_PRIV_NEW_STREAM (V4L2_CID_PRIVATE_BASE + 10)
+#define MSM_CAMERA_PRIV_DEL_STREAM (V4L2_CID_PRIVATE_BASE + 11)
+#define MSM_CAMERA_PRIV_SHUTDOWN   (V4L2_CID_PRIVATE_BASE + 12)
+#define MSM_CAMERA_PRIV_STREAM_INFO_SYNC \
+	(V4L2_CID_PRIVATE_BASE + 13)
+
+/* data.status - success */
+#define MSM_CAMERA_CMD_SUCESS      0x00000001
+#define MSM_CAMERA_BUF_MAP_SUCESS  0x00000002
+
+/* data.status - error */
+#define MSM_CAMERA_ERR_EVT_BASE 0x00010000
+#define MSM_CAMERA_ERR_CMD_FAIL (MSM_CAMERA_ERR_EVT_BASE + 1)
+#define MSM_CAMERA_ERR_MAPPING  (MSM_CAMERA_ERR_EVT_BASE + 2)
+
+/* The msm_v4l2_event_data structure should match the
+ * v4l2_event.u.data field.
+ * should not exceed 16 elements */
+struct msm_v4l2_event_data {
+	/*word 0*/
+	unsigned int command;
+	/*word 1*/
+	unsigned int status;
+	/*word 2*/
+	unsigned int session_id;
+	/*word 3*/
+	unsigned int stream_id;
+	/*word 4*/
+	unsigned int map_op;
+	/*word 5*/
+	unsigned int map_buf_idx;
+	/*word 6*/
+	unsigned int notify;
+	/*word 7*/
+	unsigned int nop1;
+	/*word 8*/
+	unsigned int nop2;
+	/*word 9*/
+	unsigned int nop3;
+	/*word 10*/
+	unsigned int nop4;
+	/*word 11*/
+	unsigned int nop5;
+	/*word 12*/
+	unsigned int nop6;
+	/*word 13*/
+	unsigned int nop7;
+	/*word 14*/
+	unsigned int nop8;
+	/*word 15*/
+	unsigned int nop9;
+};
+
+/* map to v4l2_format.fmt.raw_data */
+struct msm_v4l2_format_data {
+	enum v4l2_buf_type type;
+	unsigned int width;
+	unsigned int height;
+	unsigned int pixelformat; /* FOURCC */
+	unsigned char num_planes;
+	unsigned int plane_sizes[VIDEO_MAX_PLANES];
+};
+
+/*  MSM Four-character-code (FOURCC) */
+#define msm_v4l2_fourcc(a, b, c, d)\
+	((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) |\
+	((__u32)(d) << 24))
+
+/* Composite stats */
+#define MSM_V4L2_PIX_FMT_STATS_COMB v4l2_fourcc('S', 'T', 'C', 'M')
+/* AEC stats */
+#define MSM_V4L2_PIX_FMT_STATS_AE   v4l2_fourcc('S', 'T', 'A', 'E')
+/* AF stats */
+#define MSM_V4L2_PIX_FMT_STATS_AF   v4l2_fourcc('S', 'T', 'A', 'F')
+/* AWB stats */
+#define MSM_V4L2_PIX_FMT_STATS_AWB  v4l2_fourcc('S', 'T', 'W', 'B')
+/* IHIST stats */
+#define MSM_V4L2_PIX_FMT_STATS_IHST v4l2_fourcc('I', 'H', 'S', 'T')
+/* Column count stats */
+#define MSM_V4L2_PIX_FMT_STATS_CS   v4l2_fourcc('S', 'T', 'C', 'S')
+/* Row count stats */
+#define MSM_V4L2_PIX_FMT_STATS_RS   v4l2_fourcc('S', 'T', 'R', 'S')
+/* Bayer Grid stats */
+#define MSM_V4L2_PIX_FMT_STATS_BG   v4l2_fourcc('S', 'T', 'B', 'G')
+/* Bayer focus stats */
+#define MSM_V4L2_PIX_FMT_STATS_BF   v4l2_fourcc('S', 'T', 'B', 'F')
+/* Bayer hist stats */
+#define MSM_V4L2_PIX_FMT_STATS_BHST v4l2_fourcc('B', 'H', 'S', 'T')
+
+#endif /* __LINUX_MSMB_CAMERA_H */
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
new file mode 100644
index 0000000..01276bd
--- /dev/null
+++ b/include/media/msmb_isp.h
@@ -0,0 +1,320 @@
+#ifndef __MSMB_ISP__
+#define __MSMB_ISP__
+
+#include <linux/videodev2.h>
+
+#define MAX_PLANES_PER_STREAM 3
+#define MAX_NUM_STREAM 7
+
+#define ISP_VERSION_40        40
+#define ISP_VERSION_32        32
+
+
+enum ISP_START_PIXEL_PATTERN {
+	ISP_BAYER_RGRGRG,
+	ISP_BAYER_GRGRGR,
+	ISP_BAYER_BGBGBG,
+	ISP_BAYER_GBGBGB,
+	ISP_YUV_YCbYCr,
+	ISP_YUV_YCrYCb,
+	ISP_YUV_CbYCrY,
+	ISP_YUV_CrYCbY,
+	ISP_PIX_PATTERN_MAX
+};
+
+enum msm_vfe_plane_fmt {
+	Y_PLANE,
+	CB_PLANE,
+	CR_PLANE,
+	CRCB_PLANE,
+	CBCR_PLANE,
+	VFE_PLANE_FMT_MAX
+};
+
+enum msm_vfe_input_src {
+	VFE_PIX_0,
+	VFE_RAW_0,
+	VFE_RAW_1,
+	VFE_RAW_2,
+	VFE_SRC_MAX,
+};
+
+enum msm_vfe_axi_stream_src {
+	PIX_ENCODER,
+	PIX_VIEWFINDER,
+	CAMIF_RAW,
+	IDEAL_RAW,
+	RDI,
+	VFE_AXI_SRC_MAX
+};
+
+enum msm_vfe_frame_skip_pattern {
+	NO_SKIP,
+	EVERY_2FRAME,
+	EVERY_4FRAME,
+	EVERY_8FRAME,
+	EVERY_16FRAME,
+	EVERY_32FRAME,
+	MAX_SKIP,
+};
+
+enum msm_vfe_camif_input {
+	CAMIF_DISABLED,
+	CAMIF_PAD_REG_INPUT,
+	CAMIF_MIDDI_INPUT,
+	CAMIF_MIPI_INPUT,
+};
+
+struct msm_vfe_camif_cfg {
+	uint32_t lines_per_frame;
+	uint32_t pixels_per_line;
+	uint32_t first_pixel;
+	uint32_t last_pixel;
+	uint32_t first_line;
+	uint32_t last_line;
+	uint32_t epoch_line0;
+	uint32_t epoch_line1;
+	enum msm_vfe_camif_input camif_input;
+};
+
+enum msm_vfe_inputmux {
+	CAMIF,
+	TESTGEN,
+	EXTERNAL_READ,
+};
+
+struct msm_vfe_pix_cfg {
+	struct msm_vfe_camif_cfg camif_cfg;
+	enum msm_vfe_inputmux input_mux;
+	enum ISP_START_PIXEL_PATTERN pixel_pattern;
+};
+
+struct msm_vfe_input_cfg {
+	union {
+		struct msm_vfe_pix_cfg pix_cfg;
+	} d;
+	enum msm_vfe_input_src input_src;
+
+};
+
+struct msm_vfe_axi_plane_cfg {
+	uint32_t output_width; /*Include padding*/
+	uint32_t output_height;
+	uint32_t output_stride;
+	uint32_t output_scan_lines;
+	uint32_t output_plane_format; /*Y/Cb/Cr/CbCr*/
+
+	uint8_t csid_src; /*RDI 0-2*/
+	uint8_t rdi_cid;/*CID 1-16*/
+};
+
+struct msm_vfe_axi_stream_request_cmd {
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t output_format;/*Planar/RAW/Misc*/
+	enum msm_vfe_axi_stream_src stream_src; /*CAMIF/IDEAL/RDIs*/
+	struct msm_vfe_axi_plane_cfg plane_cfg[MAX_PLANES_PER_STREAM];
+
+	uint32_t burst_count;
+	uint32_t hfr_mode;
+	uint8_t frame_base;
+
+	uint32_t init_frame_drop; /*MAX 31 Frames*/
+	enum msm_vfe_frame_skip_pattern frame_skip_pattern;
+	uint8_t buf_divert; /* if TRUE no vb2 buf done. */
+	/*Return values*/
+	uint32_t axi_stream_handle;
+};
+
+struct msm_vfe_axi_stream_release_cmd {
+	uint32_t stream_handle;
+};
+
+enum msm_vfe_axi_stream_cmd {
+	STOP_STREAM,
+	START_STREAM,
+};
+
+struct msm_vfe_axi_stream_cfg_cmd {
+	uint8_t num_streams;
+	uint32_t stream_handle[MAX_NUM_STREAM];
+	enum msm_vfe_axi_stream_cmd cmd;
+};
+
+enum msm_isp_stats_type {
+	MSM_ISP_STATS_AEC,   /* legacy based AEC */
+	MSM_ISP_STATS_AF,    /* legacy based AF */
+	MSM_ISP_STATS_AWB,   /* legacy based AWB */
+	MSM_ISP_STATS_RS,    /* legacy based RS */
+	MSM_ISP_STATS_CS,    /* legacy based CS */
+	MSM_ISP_STATS_IHIST, /* legacy based HIST */
+	MSM_ISP_STATS_SKIN,  /* legacy based SKIN */
+	MSM_ISP_STATS_BG,    /* Bayer Grids */
+	MSM_ISP_STATS_BF,    /* Bayer Focus */
+	MSM_ISP_STATS_BE,    /* Bayer Exposure*/
+	MSM_ISP_STATS_BHIST, /* Bayer Hist */
+	MSM_ISP_STATS_MAX    /* MAX */
+};
+
+struct msm_vfe_stats_stream_request_cmd {
+	uint32_t session_id;
+	uint32_t stream_id;
+	enum msm_isp_stats_type stats_type;
+	uint32_t stream_handle;
+};
+struct msm_vfe_stats_stream_release_cmd {
+	uint32_t stream_handle;
+};
+struct msm_vfe_stats_stream_cfg_cmd {
+	uint8_t num_streams;
+	uint32_t stream_handle[MSM_ISP_STATS_MAX];
+	uint8_t enable;
+};
+enum msm_vfe_reg_cfg_type {
+	VFE_WRITE,
+	VFE_WRITE_MB,
+	VFE_READ,
+	VFE_WRITE_MASK,
+	VFE_CLEAR_MASK,
+	VFE_WRITE_AUTO_INCREMENT,
+};
+
+struct msm_vfe_cfg_cmd2 {
+	uint16_t num_cfg;
+	uint16_t cmd_len;
+	void __user *cfg_data;
+	void __user *cfg_cmd;
+};
+
+struct msm_vfe_reg_cfg_cmd {
+	uint32_t reg_offset;
+	uint32_t cmd_data;
+	uint32_t len;
+	enum msm_vfe_reg_cfg_type cmd_type;
+};
+
+struct msm_isp_buf_request {
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint8_t num_buf;
+	uint32_t handle;
+};
+
+struct msm_isp_qbuf_info {
+	uint32_t handle;
+	int buf_idx;
+	/*Only used for prepare buffer*/
+	struct v4l2_buffer buffer;
+};
+
+struct msm_vfe_axi_src_state {
+	enum msm_vfe_input_src input_src;
+	uint32_t src_active;
+};
+
+enum msm_isp_event_idx {
+	ISP_REG_UPDATE      = 0,
+	ISP_START_ACK       = 1,
+	ISP_STOP_ACK        = 2,
+	ISP_IRQ_VIOLATION   = 3,
+	ISP_WM_BUS_OVERFLOW = 4,
+	ISP_STATS_OVERFLOW  = 5,
+	ISP_CAMIF_ERROR     = 6,
+	ISP_STATS_NOTIFY    = 7,
+	ISP_SOF             = 8,
+	ISP_EOF             = 9,
+	ISP_BUF_DIVERT      = 10,
+	ISP_EVENT_MAX       = 11
+};
+
+#define ISP_EVENT_BASE            (V4L2_EVENT_PRIVATE_START + 1)
+#define ISP_EVENT_REG_UPDATE      (ISP_EVENT_BASE + ISP_REG_UPDATE)
+#define ISP_EVENT_START_ACK       (ISP_EVENT_BASE + ISP_START_ACK)
+#define ISP_EVENT_STOP_ACK        (ISP_EVENT_BASE + ISP_STOP_ACK)
+#define ISP_EVENT_IRQ_VIOLATION   (ISP_EVENT_BASE + ISP_IRQ_VIOLATION)
+#define ISP_EVENT_WM_BUS_OVERFLOW (ISP_EVENT_BASE + ISP_WM_BUS_OVERFLOW)
+#define ISP_EVENT_STATS_OVERFLOW  (ISP_EVENT_BASE + ISP_STATS_OVERFLOW)
+#define ISP_EVENT_CAMIF_ERROR     (ISP_EVENT_BASE + ISP_CAMIF_ERROR)
+#define ISP_EVENT_STATS_NOTIFY    (ISP_EVENT_BASE + ISP_STATS_NOTIFY)
+#define ISP_EVENT_SOF             (ISP_EVENT_BASE + ISP_SOF)
+#define ISP_EVENT_EOF             (ISP_EVENT_BASE + ISP_EOF)
+#define ISP_EVENT_BUF_DIVERT      (ISP_EVENT_BASE + ISP_BUF_DIVERT)
+
+
+/* The msm_v4l2_event_data structure should match the
+ * v4l2_event.u.data field.
+ * should not exceed 64 bytes */
+
+struct msm_isp_buf_event {
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t handle;
+	int8_t buf_idx;
+};
+struct msm_isp_stats_event {
+	uint32_t stats_mask;                        /* 4 bytes */
+	uint8_t stats_buf_idxs[MSM_ISP_STATS_MAX];  /* 11 bytes */
+};
+
+struct msm_isp_stream_ack {
+	uint32_t session_id;
+	uint32_t stream_id;
+	uint32_t handle;
+};
+
+struct msm_isp_event_data {
+	struct timeval timestamp;
+	/* if pix is a src frame_id is from camif */
+	uint32_t frame_id;
+	union {
+		/* START_ACK, STOP_ACK */
+		struct msm_isp_stream_ack stream_ack;
+		/* REG_UPDATE_TRIGGER, bus over flow */
+		enum msm_vfe_input_src input_src;
+		/* stats notify */
+		struct msm_isp_stats_event stats;
+		/* IRQ_VIOLATION, STATS_OVER_FLOW, WM_OVER_FLOW */
+		uint32_t irq_status_mask;
+		struct msm_isp_buf_event buf_done;
+	} u; /* union can have max 52 bytes */
+};
+
+#define VIDIOC_MSM_VFE_REG_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE, struct msm_vfe_cfg_cmd2)
+
+#define VIDIOC_MSM_ISP_REQUEST_BUF \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+1, struct msm_isp_buf_request)
+
+#define VIDIOC_MSM_ISP_ENQUEUE_BUF \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+2, struct msm_isp_qbuf_info)
+
+#define VIDIOC_MSM_ISP_RELEASE_BUF \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+3, struct msm_isp_buf_request)
+
+#define VIDIOC_MSM_ISP_REQUEST_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+4, struct msm_vfe_axi_stream_request_cmd)
+
+#define VIDIOC_MSM_ISP_CFG_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+5, struct msm_vfe_axi_stream_cfg_cmd)
+
+#define VIDIOC_MSM_ISP_RELEASE_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+6, struct msm_vfe_axi_stream_release_cmd)
+
+#define VIDIOC_MSM_ISP_INPUT_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+7, struct msm_vfe_input_cfg)
+
+#define VIDIOC_MSM_ISP_SET_SRC_STATE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+8, struct msm_vfe_axi_src_state)
+
+#define VIDIOC_MSM_ISP_REQUEST_STATS_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+9, \
+	struct msm_vfe_stats_stream_request_cmd)
+
+#define VIDIOC_MSM_ISP_CFG_STATS_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+10, struct msm_vfe_stats_stream_cfg_cmd)
+
+#define VIDIOC_MSM_ISP_RELEASE_STATS_STREAM \
+	_IOWR('V', BASE_VIDIOC_PRIVATE+11, \
+	struct msm_vfe_stats_stream_release_cmd)
+
+#endif /* __MSMB_ISP__ */
diff --git a/include/media/msmb_ispif.h b/include/media/msmb_ispif.h
new file mode 100644
index 0000000..fc27ef6
--- /dev/null
+++ b/include/media/msmb_ispif.h
@@ -0,0 +1,103 @@
+#ifndef MSM_CAM_ISPIF_H
+#define MSM_CAM_ISPIF_H
+
+#define CSID_VERSION_V2                       0x02000011
+#define CSID_VERSION_V3                       0x30000000
+
+enum msm_ispif_vfe_intf {
+	VFE0,
+	VFE1,
+	VFE_MAX
+};
+#define VFE0_MASK    (1 << VFE0)
+#define VFE1_MASK    (1 << VFE1)
+
+enum msm_ispif_intftype {
+	PIX0,
+	RDI0,
+	PIX1,
+	RDI1,
+	RDI2,
+	INTF_MAX
+};
+#define PIX0_MASK (1 << PIX0)
+#define PIX1_MASK (1 << PIX1)
+#define RDI0_MASK (1 << RDI0)
+#define RDI1_MASK (1 << RDI1)
+#define RDI2_MASK (1 << RDI2)
+
+
+enum msm_ispif_vc {
+	VC0,
+	VC1,
+	VC2,
+	VC3,
+	VC_MAX
+};
+
+enum msm_ispif_cid {
+	CID0,
+	CID1,
+	CID2,
+	CID3,
+	CID4,
+	CID5,
+	CID6,
+	CID7,
+	CID8,
+	CID9,
+	CID10,
+	CID11,
+	CID12,
+	CID13,
+	CID14,
+	CID15,
+	CID_MAX
+};
+
+enum msm_ispif_csid {
+	CSID0,
+	CSID1,
+	CSID2,
+	CSID3,
+	CSID_MAX
+};
+
+struct msm_ispif_params_entry {
+	enum msm_ispif_intftype intftype;
+	int num_cids;
+	enum msm_ispif_cid cids[3];
+	enum msm_ispif_csid csid;
+};
+
+struct msm_ispif_param_data {
+	enum msm_ispif_vfe_intf vfe_intf;
+	uint32_t num;
+	struct msm_ispif_params_entry entries[INTF_MAX];
+};
+
+enum ispif_cfg_type_t {
+	ISPIF_CLK_ENABLE,
+	ISPIF_CLK_DISABLE,
+	ISPIF_INIT,
+	ISPIF_CFG,
+	ISPIF_START_FRAME_BOUNDARY,
+	ISPIF_STOP_FRAME_BOUNDARY,
+	ISPIF_STOP_IMMEDIATELY,
+	ISPIF_RELEASE,
+	ISPIF_ENABLE_REG_DUMP,
+};
+
+struct ispif_cfg_data {
+	enum ispif_cfg_type_t cfg_type;
+	union {
+		int reg_dump;                        /* ISPIF_ENABLE_REG_DUMP */
+		uint32_t csid_version;               /* ISPIF_INIT */
+		struct msm_ispif_param_data params;  /* CFG, START, STOP */
+	};
+};
+
+#define VIDIOC_MSM_ISPIF_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE, struct ispif_cfg_data)
+
+#endif /* MSM_CAM_ISPIF_H */
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 88acdfc..3571fad 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -6369,4 +6369,135 @@
 
 /*bharath, adsp_error_codes.h */
 
+/* LPASS clock for I2S Interface */
+
+/* Supported OSR clock values */
+#define Q6AFE_LPASS_OSR_CLK_12_P288_MHZ		0xBB8000
+#define Q6AFE_LPASS_OSR_CLK_8_P192_MHZ		0x7D0000
+#define Q6AFE_LPASS_OSR_CLK_6_P144_MHZ		0x5DC000
+#define Q6AFE_LPASS_OSR_CLK_4_P096_MHZ		0x3E8000
+#define Q6AFE_LPASS_OSR_CLK_3_P072_MHZ		0x2EE000
+#define Q6AFE_LPASS_OSR_CLK_2_P048_MHZ		0x1F4000
+#define Q6AFE_LPASS_OSR_CLK_1_P536_MHZ		0x177000
+#define Q6AFE_LPASS_OSR_CLK_1_P024_MHZ		 0xFA000
+#define Q6AFE_LPASS_OSR_CLK_768_kHZ		 0xBB800
+#define Q6AFE_LPASS_OSR_CLK_512_kHZ		 0x7D000
+#define Q6AFE_LPASS_OSR_CLK_DISABLE		     0x0
+
+/* Supported Bit clock values */
+#define Q6AFE_LPASS_IBIT_CLK_8_P192_MHZ		0x7D0000
+#define Q6AFE_LPASS_IBIT_CLK_6_P144_MHZ		0x5DC000
+#define Q6AFE_LPASS_IBIT_CLK_4_P096_MHZ		0x3E8000
+#define Q6AFE_LPASS_IBIT_CLK_3_P072_MHZ		0x2EE000
+#define Q6AFE_LPASS_IBIT_CLK_2_P048_MHZ		0x1F4000
+#define Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ		0x177000
+#define Q6AFE_LPASS_IBIT_CLK_1_P024_MHZ		 0xFA000
+#define Q6AFE_LPASS_IBIT_CLK_768_KHZ		 0xBB800
+#define Q6AFE_LPASS_IBIT_CLK_512_KHZ		 0x7D000
+#define Q6AFE_LPASS_IBIT_CLK_DISABLE		     0x0
+
+/* Supported LPASS CLK sources */
+#define Q6AFE_LPASS_CLK_SRC_EXTERNAL 0
+#define Q6AFE_LPASS_CLK_SRC_INTERNAL 1
+
+/* Supported LPASS CLK root*/
+#define Q6AFE_LPASS_CLK_ROOT_DEFAULT 0
+
+enum afe_lpass_clk_mode {
+	Q6AFE_LPASS_MODE_BOTH_INVALID,
+	Q6AFE_LPASS_MODE_CLK1_VALID,
+	Q6AFE_LPASS_MODE_CLK2_VALID,
+	Q6AFE_LPASS_MODE_BOTH_VALID,
+} __packed;
+
+struct afe_clk_cfg {
+/* Minor version used for tracking the version of the I2S
+ * configuration interface.
+ * Supported values: #AFE_API_VERSION_I2S_CONFIG
+ */
+	u32                  i2s_cfg_minor_version;
+
+/* clk value 1 in MHz. */
+	u32                  clk_val1;
+
+/* clk value 2 in MHz. */
+	u32                  clk_val2;
+
+/* clk_src
+ * #Q6AFE_LPASS_CLK_SRC_EXTERNAL
+ * #Q6AFE_LPASS_CLK_SRC_INTERNAL
+ */
+
+	u16                  clk_src;
+
+/* clk_root -0 for default */
+	u16                  clk_root;
+
+/* clk_set_mode
+ * #Q6AFE_LPASS_MODE_BOTH_INVALID
+ * #Q6AFE_LPASS_MODE_CLK1_VALID
+ * #Q6AFE_LPASS_MODE_CLK2_VALID
+ * #Q6AFE_LPASS_MODE_BOTH_VALID
+ */
+	u16                  clk_set_mode;
+
+/* This param id is used to configure I2S clk */
+	u16                  reserved;
+} __packed;
+
+/* This param id is used to configure I2S clk */
+#define AFE_PARAM_ID_LPAIF_CLK_CONFIG	0x00010238
+
+
+struct afe_lpass_clk_config_command {
+	struct apr_hdr			 hdr;
+	struct afe_port_cmd_set_param_v2 param;
+	struct afe_port_param_data_v2    pdata;
+	struct afe_clk_cfg clk_cfg;
+} __packed;
+
+enum afe_lpass_digital_clk_src {
+	Q6AFE_LPASS_DIGITAL_ROOT_INVALID,
+	Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR,
+	Q6AFE_LPASS_DIGITAL_ROOT_SEC_MI2S_OSR,
+	Q6AFE_LPASS_DIGITAL_ROOT_TER_MI2S_OSR,
+	Q6AFE_LPASS_DIGITAL_ROOT_QUAD_MI2S_OSR,
+	Q6AFE_LPASS_DIGITAL_ROOT_CDC_ROOT_CLK,
+} __packed;
+
+/* This param id is used to configure internal clk */
+#define AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG	0x00010239
+
+struct afe_digital_clk_cfg {
+/* Minor version used for tracking the version of the I2S
+ * configuration interface.
+ * Supported values: #AFE_API_VERSION_I2S_CONFIG
+ */
+	u32                  i2s_cfg_minor_version;
+
+/* clk value in MHz. */
+	u32                  clk_val;
+
+/*	INVALID
+ *	PRI_MI2S_OSR
+ *	SEC_MI2S_OSR
+ *	TER_MI2S_OSR
+ *	QUAD_MI2S_OSR
+ *	DIGT_CDC_ROOT
+ */
+	u16                  clk_root;
+
+/* This field must be set to zero. */
+	u16                  reserved;
+} __packed;
+
+
+struct afe_lpass_digital_clk_config_command {
+	struct apr_hdr			 hdr;
+	struct afe_port_cmd_set_param_v2 param;
+	struct afe_port_param_data_v2    pdata;
+	struct afe_digital_clk_cfg clk_cfg;
+} __packed;
+
+
 #endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 3da152c..e39d45c 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -155,4 +155,9 @@
 
 int afe_pseudo_port_start_nowait(u16 port_id);
 int afe_pseudo_port_stop_nowait(u16 port_id);
+int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg);
+int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
+				struct afe_digital_clk_cfg *cfg);
+int q6afe_check_osr_clk_freq(u32 freq);
+
 #endif /* __Q6AFE_V2_H__ */
diff --git a/include/sound/q6audio-v2.h b/include/sound/q6audio-v2.h
index 1a5dce1..fd6a490 100644
--- a/include/sound/q6audio-v2.h
+++ b/include/sound/q6audio-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,8 @@
 
 int q6audio_validate_port(u16 port_id);
 
+int q6audio_is_digital_pcm_interface(u16 port_id);
+
 int q6audio_get_port_id(u16 port_id);
 
 #endif
diff --git a/kernel/panic.c b/kernel/panic.c
index 8c6babc..4716d16 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/nmi.h>
 #include <linux/dmi.h>
+#include <linux/coresight.h>
 
 #define PANIC_TIMER_STEP 100
 #define PANIC_BLINK_SPD 18
@@ -80,6 +81,7 @@
 	long i, i_next = 0;
 	int state = 0;
 
+	coresight_abort();
 	/*
 	 * Disable local interrupts. This will prevent panic_smp_self_stop
 	 * from deadlocking the first cpu that invokes the panic, since
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index d42c279..acb60be 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -524,6 +524,7 @@
 	{ CTL_INT,	NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN,	"accept_ra_rt_info_max_plen" },
 	{ CTL_INT,	NET_IPV6_PROXY_NDP,			"proxy_ndp" },
 	{ CTL_INT,	NET_IPV6_ACCEPT_SOURCE_ROUTE,		"accept_source_route" },
+	{ CTL_INT,	NET_IPV6_ACCEPT_RA_PREFIX_ROUTE,	"accept_ra_prefix_route" },
 	{}
 };
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f897841..5bb2847 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -36,6 +36,8 @@
  *	YOSHIFUJI Hideaki @USAGI	:	improved source address
  *						selection; consider scope,
  *						status etc.
+ *	Harout S. Hedeshian		:	procfs flag to toggle automatic
+ *						addition of prefix route
  */
 
 #include <linux/errno.h>
@@ -197,6 +199,7 @@
 	.accept_source_route	= 0,	/* we do not accept RH0 by default. */
 	.disable_ipv6		= 0,
 	.accept_dad		= 1,
+	.accept_ra_prefix_route = 1,
 };
 
 static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -231,6 +234,7 @@
 	.accept_source_route	= 0,	/* we do not accept RH0 by default. */
 	.disable_ipv6		= 0,
 	.accept_dad		= 1,
+	.accept_ra_prefix_route = 1,
 };
 
 /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -1908,8 +1912,10 @@
 				flags |= RTF_EXPIRES;
 				expires = jiffies_to_clock_t(rt_expires);
 			}
-			addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
-					      dev, expires, flags);
+			if (dev->ip6_ptr->cnf.accept_ra_prefix_route) {
+				addrconf_prefix_route(&pinfo->prefix,
+					pinfo->prefix_len, dev, expires, flags);
+			}
 		}
 		if (rt)
 			dst_release(&rt->dst);
@@ -4598,6 +4604,13 @@
 			.proc_handler   = proc_dointvec
 		},
 		{
+			.procname	= "accept_ra_prefix_route",
+			.data		= &ipv6_devconf.accept_ra_prefix_route,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= proc_dointvec,
+		},
+		{
 			/* sentinel */
 		}
 	},
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 2d8d9ca..58a07d6 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,7 @@
 #include <linux/jiffies.h>
 #include <linux/uaccess.h>
 #include <linux/atomic.h>
+#include <linux/err.h>
 
 #include <mach/qdsp6v2/audio_dev_ctl.h>
 #include <mach/qdsp6v2/audio_acdb.h>
@@ -54,6 +55,14 @@
 	int index;
 
 	pr_debug("SRS - %s", __func__);
+
+	index = afe_get_port_index(port_id);
+
+	if (IS_ERR_VALUE(index)) {
+		pr_err("%s: invald port id\n", __func__);
+		return index;
+	}
+
 	switch (srs_tech_id) {
 	case SRS_ID_GLOBAL: {
 		struct srs_trumedia_params_GLOBAL *glb_params = NULL;
@@ -199,7 +208,6 @@
 	open->hdr.src_port = port_id;
 	open->hdr.dest_svc = APR_SVC_ADM;
 	open->hdr.dest_domain = APR_DOMAIN_ADSP;
-	index = afe_get_port_index(port_id);
 	open->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
 	open->hdr.token = port_id;
 	open->hdr.opcode = ADM_CMD_SET_PARAMS;
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 2d44a41..f29f02e 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, .qualcomm.com. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1587,7 +1587,7 @@
 				goto afe_error;
 			}
 
-			if (param[1] < 0 || param[1] > 100) {
+			if (param[1] > 100) {
 				pr_err("%s: Error, volume shoud be 0 to 100"
 					" percentage param = %lu\n",
 					__func__, param[1]);
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 1d11907..58eec3c 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -1,6 +1,6 @@
 snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o msm-compr-q6-v2.o  msm-multi-ch-pcm-q6-v2.o
 snd-soc-qdsp6v2-objs += msm-pcm-lpa-v2.o msm-pcm-afe-v2.o msm-pcm-voip-v2.o msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o
 obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o
-obj-y += q6adm.o q6afe.o q6asm.o q6audio-v2.o q6voice.o q6core.o
+obj-y += q6adm.o q6afe.o q6asm.o q6audio-v2.o q6voice.o q6core.o audio_acdb.o rtac.o
 ocmem-audio-objs += audio_ocmem.o
 obj-$(CONFIG_AUDIO_OCMEM) += ocmem-audio.o
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
new file mode 100644
index 0000000..7061efa
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -0,0 +1,967 @@
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/msm_ion.h>
+#include <linux/mm.h>
+#include "audio_acdb.h"
+
+
+#define MAX_NETWORKS			15
+#define MAX_IOCTL_DATA			(MAX_NETWORKS * 2)
+#define MAX_COL_SIZE			324
+
+#define ACDB_BLOCK_SIZE			4096
+#define NUM_VOCPROC_BLOCKS		(6 * MAX_NETWORKS)
+#define ACDB_TOTAL_VOICE_ALLOCATION	(ACDB_BLOCK_SIZE * NUM_VOCPROC_BLOCKS)
+
+
+struct sidetone_atomic_cal {
+	atomic_t	enable;
+	atomic_t	gain;
+};
+
+
+struct acdb_data {
+	struct mutex		acdb_mutex;
+
+	/* ANC Cal */
+	struct acdb_atomic_cal_block	anc_cal;
+
+	/* AudProc Cal */
+	atomic_t			asm_topology;
+	atomic_t			adm_topology[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audproc_cal[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audstrm_cal[MAX_AUDPROC_TYPES];
+	struct acdb_atomic_cal_block	audvol_cal[MAX_AUDPROC_TYPES];
+
+	/* VocProc Cal */
+	atomic_t			voice_rx_topology;
+	atomic_t			voice_tx_topology;
+	struct acdb_atomic_cal_block	vocproc_cal;
+	struct acdb_atomic_cal_block	vocstrm_cal;
+	struct acdb_atomic_cal_block	vocvol_cal;
+
+	/* Voice Column data */
+	struct acdb_atomic_cal_block	vocproc_col_cal[MAX_VOCPROC_TYPES];
+	uint32_t			*col_data[MAX_VOCPROC_TYPES];
+
+	/* VocProc dev cfg cal*/
+	struct acdb_atomic_cal_block	vocproc_dev_cal;
+
+	/* AFE cal */
+	struct acdb_atomic_cal_block	afe_cal[MAX_AUDPROC_TYPES];
+
+	/* Sidetone Cal */
+	struct sidetone_atomic_cal	sidetone_cal;
+
+	/* Allocation information */
+	struct ion_client		*ion_client;
+	struct ion_handle		*ion_handle;
+	atomic_t			map_handle;
+	atomic64_t			paddr;
+	atomic64_t			kvaddr;
+	atomic64_t			mem_len;
+};
+
+static struct acdb_data		acdb_data;
+static atomic_t usage_count;
+
+uint32_t get_voice_rx_topology(void)
+{
+	return atomic_read(&acdb_data.voice_rx_topology);
+}
+
+void store_voice_rx_topology(uint32_t topology)
+{
+	atomic_set(&acdb_data.voice_rx_topology, topology);
+}
+
+uint32_t get_voice_tx_topology(void)
+{
+	return atomic_read(&acdb_data.voice_tx_topology);
+}
+
+void store_voice_tx_topology(uint32_t topology)
+{
+	atomic_set(&acdb_data.voice_tx_topology, topology);
+}
+
+uint32_t get_adm_rx_topology(void)
+{
+	return atomic_read(&acdb_data.adm_topology[RX_CAL]);
+}
+
+void store_adm_rx_topology(uint32_t topology)
+{
+	atomic_set(&acdb_data.adm_topology[RX_CAL], topology);
+}
+
+uint32_t get_adm_tx_topology(void)
+{
+	return atomic_read(&acdb_data.adm_topology[TX_CAL]);
+}
+
+void store_adm_tx_topology(uint32_t topology)
+{
+	atomic_set(&acdb_data.adm_topology[TX_CAL], topology);
+}
+
+uint32_t get_asm_topology(void)
+{
+	return atomic_read(&acdb_data.asm_topology);
+}
+
+void store_asm_topology(uint32_t topology)
+{
+	atomic_set(&acdb_data.asm_topology, topology);
+}
+
+void get_voice_cal_allocation(struct acdb_cal_block *cal_block)
+{
+	cal_block->cal_size = ACDB_TOTAL_VOICE_ALLOCATION;
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal.cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal.cal_kvaddr);
+}
+
+void get_anc_cal(struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.anc_cal.cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.anc_cal.cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.anc_cal.cal_kvaddr);
+done:
+	return;
+}
+
+void store_anc_cal(struct cal_block *cal_block)
+{
+	pr_debug("%s,\n", __func__);
+
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		goto done;
+	}
+
+	atomic_set(&acdb_data.anc_cal.cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.anc_cal.cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.anc_cal.cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+done:
+	return;
+}
+
+void store_afe_cal(int32_t path, struct cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		goto done;
+	}
+	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.afe_cal[path].cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.afe_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.afe_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+done:
+	return;
+}
+
+void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.afe_cal[path].cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.afe_cal[path].cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.afe_cal[path].cal_kvaddr);
+done:
+	return;
+}
+
+void store_audproc_cal(int32_t path, struct cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		goto done;
+	}
+	if (path >= MAX_AUDPROC_TYPES) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.audproc_cal[path].cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.audproc_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audproc_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+done:
+	return;
+}
+
+void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+	if (path >= MAX_AUDPROC_TYPES) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audproc_cal[path].cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audproc_cal[path].cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audproc_cal[path].cal_kvaddr);
+done:
+	return;
+}
+
+void store_audstrm_cal(int32_t path, struct cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		goto done;
+	}
+	if (path >= MAX_AUDPROC_TYPES) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.audstrm_cal[path].cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.audstrm_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audstrm_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+done:
+	return;
+}
+
+void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+	if (path >= MAX_AUDPROC_TYPES) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audstrm_cal[path].cal_kvaddr);
+done:
+	return;
+}
+
+void store_audvol_cal(int32_t path, struct cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		goto done;
+	}
+	if (path >= MAX_AUDPROC_TYPES) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.audvol_cal[path].cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.audvol_cal[path].cal_paddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.audvol_cal[path].cal_kvaddr,
+		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+done:
+	return;
+}
+
+void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s, path = %d\n", __func__, path);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+	if (path >= MAX_AUDPROC_TYPES || path < 0) {
+		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+			__func__, path);
+		goto done;
+	}
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.audvol_cal[path].cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.audvol_cal[path].cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.audvol_cal[path].cal_kvaddr);
+done:
+	return;
+}
+
+void store_voice_col_data(uint32_t vocproc_type, uint32_t cal_size,
+			  uint32_t *cal_block)
+{
+	if (cal_size > MAX_COL_SIZE) {
+		pr_err("%s: col size is to big %d\n", __func__,
+				cal_size);
+		goto done;
+	}
+	if (copy_from_user(acdb_data.col_data[vocproc_type],
+			(void *)((uint8_t *)cal_block + sizeof(cal_size)),
+			cal_size)) {
+		pr_err("%s: fail to copy col size %d\n",
+			__func__, cal_size);
+		goto done;
+	}
+	atomic_set(&acdb_data.vocproc_col_cal[vocproc_type].cal_size,
+		cal_size);
+done:
+	return;
+}
+
+void get_voice_col_data(uint32_t vocproc_type,
+			struct acdb_cal_block *cal_block)
+{
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+
+	cal_block->cal_size = atomic_read(&acdb_data.
+				vocproc_col_cal[vocproc_type].cal_size);
+	cal_block->cal_paddr = atomic_read(&acdb_data.
+				vocproc_col_cal[vocproc_type].cal_paddr);
+	cal_block->cal_kvaddr = atomic_read(&acdb_data.
+				vocproc_col_cal[vocproc_type].cal_kvaddr);
+done:
+	return;
+}
+
+void store_vocproc_dev_cfg_cal(struct cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+
+	if (cal_block->cal_offset >
+				atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		atomic_set(&acdb_data.vocproc_dev_cal.cal_size, 0);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.vocproc_dev_cal.cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.vocproc_dev_cal.cal_paddr,
+		cal_block->cal_offset +
+	atomic64_read(&acdb_data.paddr));
+			atomic_set(&acdb_data.vocproc_dev_cal.cal_kvaddr,
+			cal_block->cal_offset +
+			atomic64_read(&acdb_data.kvaddr));
+
+done:
+	return;
+}
+
+void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_dev_cal.cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_dev_cal.cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_dev_cal.cal_kvaddr);
+}
+
+
+
+void store_vocproc_cal(struct cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	if (cal_block->cal_offset >
+				atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		atomic_set(&acdb_data.vocproc_cal.cal_size, 0);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.vocproc_cal.cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.vocproc_cal.cal_paddr,
+		cal_block->cal_offset +
+		atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.vocproc_cal.cal_kvaddr,
+		cal_block->cal_offset +
+		atomic64_read(&acdb_data.kvaddr));
+
+done:
+	return;
+}
+
+void get_vocproc_cal(struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_cal.cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal.cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal.cal_kvaddr);
+done:
+	return;
+}
+
+void store_vocstrm_cal(struct cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	if (cal_block->cal_offset >
+			atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		atomic_set(&acdb_data.vocstrm_cal.cal_size, 0);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.vocstrm_cal.cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.vocstrm_cal.cal_paddr,
+		cal_block->cal_offset +
+		atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.vocstrm_cal.cal_kvaddr,
+		cal_block->cal_offset +
+		atomic64_read(&acdb_data.kvaddr));
+
+done:
+	return;
+}
+
+void get_vocstrm_cal(struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocstrm_cal.cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocstrm_cal.cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocstrm_cal.cal_kvaddr);
+done:
+	return;
+}
+
+void store_vocvol_cal(struct cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	if (cal_block->cal_offset >
+			atomic64_read(&acdb_data.mem_len)) {
+		pr_err("%s: offset %d is > mem_len %ld\n",
+			__func__, cal_block->cal_offset,
+			(long)atomic64_read(&acdb_data.mem_len));
+		atomic_set(&acdb_data.vocvol_cal.cal_size, 0);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.vocvol_cal.cal_size,
+		cal_block->cal_size);
+	atomic_set(&acdb_data.vocvol_cal.cal_paddr,
+		cal_block->cal_offset +
+		atomic64_read(&acdb_data.paddr));
+	atomic_set(&acdb_data.vocvol_cal.cal_kvaddr,
+		cal_block->cal_offset +
+		atomic64_read(&acdb_data.kvaddr));
+
+done:
+	return;
+}
+
+void get_vocvol_cal(struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocvol_cal.cal_size);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocvol_cal.cal_paddr);
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocvol_cal.cal_kvaddr);
+done:
+	return;
+}
+
+void store_sidetone_cal(struct sidetone_cal *cal_data)
+{
+	pr_debug("%s\n", __func__);
+
+	atomic_set(&acdb_data.sidetone_cal.enable, cal_data->enable);
+	atomic_set(&acdb_data.sidetone_cal.gain, cal_data->gain);
+}
+
+
+void get_sidetone_cal(struct sidetone_cal *cal_data)
+{
+	pr_debug("%s\n", __func__);
+
+	if (cal_data == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+
+	cal_data->enable = atomic_read(&acdb_data.sidetone_cal.enable);
+	cal_data->gain = atomic_read(&acdb_data.sidetone_cal.gain);
+done:
+	return;
+}
+
+static int acdb_open(struct inode *inode, struct file *f)
+{
+	s32 result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (atomic64_read(&acdb_data.mem_len)) {
+		pr_debug("%s: ACDB opened but memory allocated, using existing allocation!\n",
+			__func__);
+	}
+
+	atomic_inc(&usage_count);
+	return result;
+}
+
+static int deregister_memory(void)
+{
+	int i;
+
+	if (atomic64_read(&acdb_data.mem_len)) {
+		mutex_lock(&acdb_data.acdb_mutex);
+		atomic64_set(&acdb_data.mem_len, 0);
+
+		for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
+			kfree(acdb_data.col_data[i]);
+			acdb_data.col_data[i] = NULL;
+		}
+		ion_unmap_kernel(acdb_data.ion_client, acdb_data.ion_handle);
+		ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+		ion_client_destroy(acdb_data.ion_client);
+		mutex_unlock(&acdb_data.acdb_mutex);
+	}
+	return 0;
+}
+
+static int register_memory(void)
+{
+	int			result;
+	int			i;
+	unsigned long		paddr;
+	void                    *kvptr;
+	unsigned long		kvaddr;
+	unsigned long		mem_len;
+
+	mutex_lock(&acdb_data.acdb_mutex);
+	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
+		acdb_data.col_data[i] = kmalloc(MAX_COL_SIZE, GFP_KERNEL);
+		atomic_set(&acdb_data.vocproc_col_cal[i].cal_kvaddr,
+			(uint32_t)acdb_data.col_data[i]);
+	}
+
+	acdb_data.ion_client =
+		msm_ion_client_create(UINT_MAX, "audio_acdb_client");
+	if (IS_ERR_OR_NULL(acdb_data.ion_client)) {
+		pr_err("%s: Could not register ION client!!!\n", __func__);
+		result = PTR_ERR(acdb_data.ion_client);
+		goto err;
+	}
+
+	acdb_data.ion_handle = ion_import_dma_buf(acdb_data.ion_client,
+		atomic_read(&acdb_data.map_handle));
+	if (IS_ERR_OR_NULL(acdb_data.ion_handle)) {
+		pr_err("%s: Could not import map handle!!!\n", __func__);
+		result = PTR_ERR(acdb_data.ion_handle);
+		goto err_ion_client;
+	}
+
+	result = ion_phys(acdb_data.ion_client, acdb_data.ion_handle,
+				&paddr, (size_t *)&mem_len);
+	if (result != 0) {
+		pr_err("%s: Could not get phys addr!!!\n", __func__);
+		goto err_ion_handle;
+	}
+
+	kvptr = ion_map_kernel(acdb_data.ion_client,
+		acdb_data.ion_handle);
+	if (IS_ERR_OR_NULL(kvptr)) {
+		pr_err("%s: Could not get kernel virt addr!!!\n", __func__);
+		result = PTR_ERR(kvptr);
+		goto err_ion_handle;
+	}
+	kvaddr = (unsigned long)kvptr;
+	atomic64_set(&acdb_data.paddr, paddr);
+	atomic64_set(&acdb_data.kvaddr, kvaddr);
+	atomic64_set(&acdb_data.mem_len, mem_len);
+	mutex_unlock(&acdb_data.acdb_mutex);
+
+	pr_debug("%s done! paddr = 0x%lx, kvaddr = 0x%lx, len = x%lx\n",
+		 __func__,
+		(long)atomic64_read(&acdb_data.paddr),
+		(long)atomic64_read(&acdb_data.kvaddr),
+		(long)atomic64_read(&acdb_data.mem_len));
+
+	return result;
+err_ion_handle:
+	ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+err_ion_client:
+	ion_client_destroy(acdb_data.ion_client);
+err:
+	atomic64_set(&acdb_data.mem_len, 0);
+	mutex_unlock(&acdb_data.acdb_mutex);
+	return result;
+}
+static long acdb_ioctl(struct file *f,
+		unsigned int cmd, unsigned long arg)
+{
+	int32_t			result = 0;
+	int32_t			size;
+	int32_t			map_fd;
+	uint32_t		topology;
+	uint32_t		data[MAX_IOCTL_DATA];
+	pr_debug("%s\n", __func__);
+
+	switch (cmd) {
+	case AUDIO_REGISTER_PMEM:
+		pr_debug("AUDIO_REGISTER_PMEM\n");
+		if (atomic_read(&acdb_data.mem_len)) {
+			deregister_memory();
+			pr_debug("Remove the existing memory\n");
+		}
+
+		if (copy_from_user(&map_fd, (void *)arg, sizeof(map_fd))) {
+			pr_err("%s: fail to copy memory handle!\n", __func__);
+			result = -EFAULT;
+		} else {
+			atomic_set(&acdb_data.map_handle, map_fd);
+			result = register_memory();
+		}
+		goto done;
+
+	case AUDIO_DEREGISTER_PMEM:
+		pr_debug("AUDIO_DEREGISTER_PMEM\n");
+		deregister_memory();
+		goto done;
+	case AUDIO_SET_VOICE_RX_TOPOLOGY:
+		if (copy_from_user(&topology, (void *)arg,
+				sizeof(topology))) {
+			pr_err("%s: fail to copy topology!\n", __func__);
+			result = -EFAULT;
+		}
+		store_voice_rx_topology(topology);
+		goto done;
+	case AUDIO_SET_VOICE_TX_TOPOLOGY:
+		if (copy_from_user(&topology, (void *)arg,
+				sizeof(topology))) {
+			pr_err("%s: fail to copy topology!\n", __func__);
+			result = -EFAULT;
+		}
+		store_voice_tx_topology(topology);
+		goto done;
+	case AUDIO_SET_ADM_RX_TOPOLOGY:
+		if (copy_from_user(&topology, (void *)arg,
+				sizeof(topology))) {
+			pr_err("%s: fail to copy topology!\n", __func__);
+			result = -EFAULT;
+		}
+		store_adm_rx_topology(topology);
+		goto done;
+	case AUDIO_SET_ADM_TX_TOPOLOGY:
+		if (copy_from_user(&topology, (void *)arg,
+				sizeof(topology))) {
+			pr_err("%s: fail to copy topology!\n", __func__);
+			result = -EFAULT;
+		}
+		store_adm_tx_topology(topology);
+		goto done;
+	case AUDIO_SET_ASM_TOPOLOGY:
+		if (copy_from_user(&topology, (void *)arg,
+				sizeof(topology))) {
+			pr_err("%s: fail to copy topology!\n", __func__);
+			result = -EFAULT;
+		}
+		store_asm_topology(topology);
+		goto done;
+	}
+
+	if (copy_from_user(&size, (void *) arg, sizeof(size))) {
+
+		result = -EFAULT;
+		goto done;
+	}
+
+	if (size <= 0) {
+		pr_err("%s: Invalid size sent to driver: %d\n",
+			__func__, size);
+		result = -EFAULT;
+		goto done;
+	}
+
+	switch (cmd) {
+	case AUDIO_SET_VOCPROC_COL_CAL:
+		store_voice_col_data(VOCPROC_CAL, size, (uint32_t *)arg);
+		goto done;
+	case AUDIO_SET_VOCSTRM_COL_CAL:
+		store_voice_col_data(VOCSTRM_CAL, size, (uint32_t *)arg);
+		goto done;
+	case AUDIO_SET_VOCVOL_COL_CAL:
+		store_voice_col_data(VOCVOL_CAL, size, (uint32_t *)arg);
+		goto done;
+	}
+
+	if (copy_from_user(data, (void *)(arg + sizeof(size)), size)) {
+
+		pr_err("%s: fail to copy table size %d\n", __func__, size);
+		result = -EFAULT;
+		goto done;
+	}
+
+	if (data == NULL) {
+		pr_err("%s: NULL pointer sent to driver!\n", __func__);
+		result = -EFAULT;
+		goto done;
+	}
+
+	if (size > sizeof(struct cal_block))
+		pr_err("%s: More cal data for ioctl 0x%x then expected, size received: %d\n",
+			__func__, cmd, size);
+
+	switch (cmd) {
+	case AUDIO_SET_AUDPROC_TX_CAL:
+		store_audproc_cal(TX_CAL, (struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_AUDPROC_RX_CAL:
+		store_audproc_cal(RX_CAL, (struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
+		store_audstrm_cal(TX_CAL, (struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
+		store_audstrm_cal(RX_CAL, (struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_AUDPROC_TX_VOL_CAL:
+		store_audvol_cal(TX_CAL, (struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_AUDPROC_RX_VOL_CAL:
+		store_audvol_cal(RX_CAL, (struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_AFE_TX_CAL:
+		store_afe_cal(TX_CAL, (struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_AFE_RX_CAL:
+		store_afe_cal(RX_CAL, (struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_VOCPROC_CAL:
+		store_vocproc_cal((struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_VOCPROC_STREAM_CAL:
+		store_vocstrm_cal((struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_VOCPROC_VOL_CAL:
+		store_vocvol_cal((struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_VOCPROC_DEV_CFG_CAL:
+		store_vocproc_dev_cfg_cal((struct cal_block *)data);
+		goto done;
+	case AUDIO_SET_SIDETONE_CAL:
+		store_sidetone_cal((struct sidetone_cal *)data);
+		goto done;
+	case AUDIO_SET_ANC_CAL:
+		store_anc_cal((struct cal_block *)data);
+		goto done;
+	default:
+		pr_err("ACDB=> ACDB ioctl not found!\n");
+	}
+
+done:
+	return result;
+}
+
+static int acdb_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	int result = 0;
+	int size = vma->vm_end - vma->vm_start;
+
+	pr_debug("%s\n", __func__);
+
+	if (atomic64_read(&acdb_data.mem_len)) {
+		if (size <= atomic64_read(&acdb_data.mem_len)) {
+			vma->vm_page_prot = pgprot_noncached(
+						vma->vm_page_prot);
+			result = remap_pfn_range(vma,
+				vma->vm_start,
+				atomic64_read(&acdb_data.paddr) >> PAGE_SHIFT,
+				size,
+				vma->vm_page_prot);
+		} else {
+			pr_err("%s: Not enough memory!\n", __func__);
+			result = -ENOMEM;
+		}
+	} else {
+		pr_err("%s: memory is not allocated, yet!\n", __func__);
+		result = -ENODEV;
+	}
+
+	return result;
+}
+
+static int acdb_release(struct inode *inode, struct file *f)
+{
+	s32 result = 0;
+
+	atomic_dec(&usage_count);
+	atomic_read(&usage_count);
+
+	pr_debug("%s: ref count %d!\n", __func__,
+		atomic_read(&usage_count));
+
+	if (atomic_read(&usage_count) >= 1)
+		result = -EBUSY;
+	else
+		result = deregister_memory();
+
+	return result;
+}
+
+static const struct file_operations acdb_fops = {
+	.owner = THIS_MODULE,
+	.open = acdb_open,
+	.release = acdb_release,
+	.unlocked_ioctl = acdb_ioctl,
+	.mmap = acdb_mmap,
+};
+
+struct miscdevice acdb_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_acdb",
+	.fops	= &acdb_fops,
+};
+
+static int __init acdb_init(void)
+{
+	memset(&acdb_data, 0, sizeof(acdb_data));
+	mutex_init(&acdb_data.acdb_mutex);
+	atomic_set(&usage_count, 0);
+
+	return misc_register(&acdb_misc);
+}
+
+static void __exit acdb_exit(void)
+{
+}
+
+module_init(acdb_init);
+module_exit(acdb_exit);
+
+MODULE_DESCRIPTION("SoC QDSP6v2 Audio ACDB driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.h b/sound/soc/msm/qdsp6v2/audio_acdb.h
new file mode 100644
index 0000000..c31823b
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _AUDIO_ACDB_H
+#define _AUDIO_ACDB_H
+
+#include <linux/msm_audio_acdb.h>
+#include <sound/q6adm-v2.h>
+
+enum {
+	RX_CAL,
+	TX_CAL,
+	MAX_AUDPROC_TYPES
+};
+
+enum {
+	VOCPROC_CAL,
+	VOCSTRM_CAL,
+	VOCVOL_CAL,
+	MAX_VOCPROC_TYPES
+};
+
+struct acdb_cal_block {
+	uint32_t		cal_size;
+	uint32_t		cal_kvaddr;
+	uint32_t		cal_paddr;
+};
+
+struct acdb_atomic_cal_block {
+	atomic_t		cal_size;
+	atomic_t		cal_kvaddr;
+	atomic_t		cal_paddr;
+};
+
+uint32_t get_voice_rx_topology(void);
+uint32_t get_voice_tx_topology(void);
+uint32_t get_adm_rx_topology(void);
+uint32_t get_adm_tx_topology(void);
+uint32_t get_asm_topology(void);
+void get_voice_cal_allocation(struct acdb_cal_block *cal_block);
+void get_anc_cal(struct acdb_cal_block *cal_block);
+void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
+void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
+void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
+void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
+void get_voice_col_data(uint32_t vocproc_type,
+	struct acdb_cal_block *cal_block);
+void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block);
+void get_vocproc_cal(struct acdb_cal_block *cal_block);
+void get_vocstrm_cal(struct acdb_cal_block *cal_block);
+void get_vocvol_cal(struct acdb_cal_block *cal_block);
+void get_sidetone_cal(struct sidetone_cal *cal_data);
+
+#endif
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 1e0ad9e..660e6a8 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,7 +18,6 @@
 #include <linux/atomic.h>
 #include <linux/wait.h>
 
-#include <mach/qdsp6v2/audio_acdb.h>
 #include <mach/qdsp6v2/rtac.h>
 
 #include <sound/apr_audio-v2.h>
@@ -27,6 +26,9 @@
 #include <sound/q6audio-v2.h>
 #include <sound/q6afe-v2.h>
 
+#include "audio_acdb.h"
+
+
 #define TIMEOUT_MS 1000
 
 #define RESET_COPP_ID 99
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index d836610..846c80e 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,12 +19,12 @@
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/msm_ion.h>
-#include <mach/qdsp6v2/audio_acdb.h>
 #include <sound/apr_audio-v2.h>
 #include <sound/q6afe-v2.h>
-
 #include <sound/q6audio-v2.h>
 
+#include "audio_acdb.h"
+
 
 struct afe_ctl {
 	void *apr;
@@ -2019,6 +2019,175 @@
 	return ret;
 }
 
+int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg)
+{
+	struct afe_lpass_clk_config_command clk_cfg;
+	int index = 0;
+	int ret = 0;
+
+	if (!cfg) {
+		pr_err("%s: clock cfg is NULL\n", __func__);
+		ret = -EINVAL;
+		return ret;
+	}
+	index = q6audio_get_port_index(port_id);
+	if (q6audio_is_digital_pcm_interface(port_id) < 0)
+		return -EINVAL;
+
+	ret = afe_q6_interface_prepare();
+	if (ret != 0)
+		return ret;
+
+	clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
+	clk_cfg.hdr.src_port = 0;
+	clk_cfg.hdr.dest_port = 0;
+	clk_cfg.hdr.token = index;
+
+	clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+	clk_cfg.param.port_id = q6audio_get_port_id(port_id);
+	clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
+						- sizeof(clk_cfg.param);
+	clk_cfg.param.payload_address_lsw = 0x00;
+	clk_cfg.param.payload_address_msw = 0x00;
+	clk_cfg.param.mem_map_handle = 0x00;
+	clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
+	clk_cfg.pdata.param_id = AFE_PARAM_ID_LPAIF_CLK_CONFIG;
+	clk_cfg.pdata.param_size =  sizeof(clk_cfg.clk_cfg);
+	clk_cfg.clk_cfg = *cfg;
+
+	pr_debug("%s: Minor version =%x clk val1 = %d\n"
+		 "clk val2 = %d, clk src = %x\n"
+		 "clk root = %x clk mode = %x resrv = %x\n"
+		 "port id = %x\n",
+		 __func__, cfg->i2s_cfg_minor_version,
+		 cfg->clk_val1, cfg->clk_val2, cfg->clk_src,
+		 cfg->clk_root, cfg->clk_set_mode,
+		 cfg->reserved, q6audio_get_port_id(port_id));
+
+	atomic_set(&this_afe.state, 1);
+	atomic_set(&this_afe.status, 0);
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
+	if (ret < 0) {
+		pr_err("%s: AFE enable for port %d\n",
+		       __func__, port_id);
+		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\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;
+	}
+
+fail_cmd:
+	return ret;
+}
+
+int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
+			struct afe_digital_clk_cfg *cfg)
+{
+	struct afe_lpass_digital_clk_config_command clk_cfg;
+	int index = 0;
+	int ret = 0;
+
+	if (!cfg) {
+		pr_err("%s: clock cfg is NULL\n", __func__);
+		ret = -EINVAL;
+		return ret;
+	}
+	index = q6audio_get_port_index(port_id);
+	if (q6audio_is_digital_pcm_interface(port_id) < 0)
+		return -EINVAL;
+
+	ret = afe_q6_interface_prepare();
+	if (ret != 0)
+		return ret;
+
+	clk_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	clk_cfg.hdr.pkt_size = sizeof(clk_cfg);
+	clk_cfg.hdr.src_port = 0;
+	clk_cfg.hdr.dest_port = 0;
+	clk_cfg.hdr.token = index;
+
+	clk_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+	clk_cfg.param.port_id = q6audio_get_port_id(port_id);
+	clk_cfg.param.payload_size = sizeof(clk_cfg) - sizeof(struct apr_hdr)
+						- sizeof(clk_cfg.param);
+	clk_cfg.param.payload_address_lsw = 0x00;
+	clk_cfg.param.payload_address_msw = 0x00;
+	clk_cfg.param.mem_map_handle = 0x00;
+	clk_cfg.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
+	clk_cfg.pdata.param_id = AFE_PARAM_ID_INTERNAL_DIGIATL_CDC_CLK_CONFIG;
+	clk_cfg.pdata.param_size =  sizeof(clk_cfg.clk_cfg);
+	clk_cfg.clk_cfg = *cfg;
+
+	pr_debug("%s: Minor version =%x clk val = %d\n"
+		 "clk root = %x resrv = %x port id = %x\n",
+		 __func__, cfg->i2s_cfg_minor_version,
+		 cfg->clk_val, cfg->clk_root, cfg->reserved,
+		 q6audio_get_port_id(port_id));
+
+	atomic_set(&this_afe.state, 1);
+	atomic_set(&this_afe.status, 0);
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &clk_cfg);
+	if (ret < 0) {
+		pr_err("%s: AFE enable for port %d\n",
+		       __func__, port_id);
+		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\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;
+	}
+
+fail_cmd:
+	return ret;
+}
+
+int q6afe_check_osr_clk_freq(u32 freq)
+{
+	int ret = 0;
+	switch (freq) {
+	case Q6AFE_LPASS_OSR_CLK_12_P288_MHZ:
+	case Q6AFE_LPASS_OSR_CLK_8_P192_MHZ:
+	case Q6AFE_LPASS_OSR_CLK_6_P144_MHZ:
+	case Q6AFE_LPASS_OSR_CLK_4_P096_MHZ:
+	case Q6AFE_LPASS_OSR_CLK_3_P072_MHZ:
+	case Q6AFE_LPASS_OSR_CLK_2_P048_MHZ:
+	case Q6AFE_LPASS_OSR_CLK_1_P536_MHZ:
+	case Q6AFE_LPASS_OSR_CLK_1_P024_MHZ:
+	case Q6AFE_LPASS_OSR_CLK_768_kHZ:
+	case Q6AFE_LPASS_OSR_CLK_512_kHZ:
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
 static int __init afe_init(void)
 {
 	int i = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 0cbd136..8d579c6 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -34,13 +34,15 @@
 
 #include <mach/memory.h>
 #include <mach/debug_mm.h>
-#include <mach/qdsp6v2/audio_acdb.h>
 #include <mach/qdsp6v2/rtac.h>
 #include <mach/msm_subsystem_map.h>
 
 #include <sound/apr_audio-v2.h>
 #include <sound/q6asm-v2.h>
 
+#include "audio_acdb.h"
+
+
 #define TRUE        0x01
 #define FALSE       0x00
 #define READDONE_IDX_STATUS 0
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 5e2e618..985a33d 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -123,6 +123,31 @@
 	return ret;
 }
 
+int q6audio_is_digital_pcm_interface(u16 port_id)
+{
+	int ret = 0;
+
+	switch (port_id) {
+	case PRIMARY_I2S_RX:
+	case PRIMARY_I2S_TX:
+	case PCM_RX:
+	case PCM_TX:
+	case SECONDARY_I2S_RX:
+	case SECONDARY_I2S_TX:
+	case MI2S_RX:
+	case MI2S_TX:
+	case AFE_PORT_ID_TERTIARY_MI2S_TX:
+	case AFE_PORT_ID_TERTIARY_MI2S_RX:
+	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
+	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 int q6audio_validate_port(u16 port_id)
 {
 	int ret;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 349fcf2..63741ec 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1,4 +1,4 @@
-/*  Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/*  Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,7 +18,6 @@
 #include <linux/mutex.h>
 
 #include <asm/mach-types.h>
-#include <mach/qdsp6v2/audio_acdb.h>
 #include <mach/qdsp6v2/rtac.h>
 #include <mach/socinfo.h>
 #include <mach/qdsp6v2/apr_tal.h>
@@ -26,8 +25,10 @@
 #include "sound/apr_audio-v2.h"
 #include "sound/q6afe-v2.h"
 
+#include "audio_acdb.h"
 #include "q6voice.h"
 
+
 #define TIMEOUT_MS 200
 
 
@@ -1456,7 +1457,7 @@
 		goto fail;
 	}
 
-	get_all_vocstrm_cal(&cal_block);
+	get_vocstrm_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVS cal size is 0\n", __func__);
 
@@ -1524,7 +1525,7 @@
 		goto fail;
 	}
 
-	get_all_vocstrm_cal(&cal_block);
+	get_vocstrm_cal(&cal_block);
 	if (cal_block.cal_size == 0)
 		return 0;
 
@@ -1714,7 +1715,7 @@
 		goto fail;
 	}
 
-	get_all_vocproc_cal(&cal_block);
+	get_vocproc_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVP cal size is 0\n", __func__);
 
@@ -1782,7 +1783,7 @@
 		goto fail;
 	}
 
-	get_all_vocproc_cal(&cal_block);
+	get_vocproc_cal(&cal_block);
 	if (cal_block.cal_size == 0)
 		return 0;
 
@@ -1843,7 +1844,7 @@
 		goto fail;
 	}
 
-	get_all_vocvol_cal(&cal_block);
+	get_vocvol_cal(&cal_block);
 	if (cal_block.cal_size == 0) {
 		pr_err("%s: CVP vol cal size is 0\n", __func__);
 
@@ -1914,7 +1915,7 @@
 		goto fail;
 	}
 
-	get_all_vocvol_cal(&cal_block);
+	get_vocvol_cal(&cal_block);
 	if (cal_block.cal_size == 0)
 		return 0;
 
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac_v2.c b/sound/soc/msm/qdsp6v2/rtac.c
similarity index 98%
rename from arch/arm/mach-msm/qdsp6v2/rtac_v2.c
rename to sound/soc/msm/qdsp6v2/rtac.c
index 409d796..1f2a487 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac_v2.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,13 +19,15 @@
 #include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/msm_audio_acdb.h>
-#include <asm/atomic.h>
-#include <mach/qdsp6v2/audio_acdb.h>
+#include <linux/atomic.h>
 #include <mach/qdsp6v2/rtac.h>
-#include "q6audio_common.h"
+#include <sound/q6asm-v2.h>
 #include <sound/q6afe-v2.h>
 #include <sound/apr_audio-v2.h>
 
+#include "audio_acdb.h"
+
+
 #ifndef CONFIG_RTAC
 
 void rtac_add_adm_device(u32 port_id, u32 copp_id, u32 path_id, u32 popp_id) {}
@@ -1041,7 +1043,7 @@
 
 module_init(rtac_init);
 
-MODULE_DESCRIPTION("MSM 8x60 Real-Time Audio Calibration driver");
+MODULE_DESCRIPTION("SoC QDSP6v2 Real-Time Audio Calibration driver");
 MODULE_LICENSE("GPL v2");
 
 #endif