Merge "ASoC: mpq8064: Add FE dai link for multi channel pcm audio." into msm-3.0
diff --git a/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt b/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
index dff6a3e..7cab09b 100644
--- a/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
@@ -24,27 +24,26 @@
 
 Required properties :
  - reg : Specify the spmi offset and size for this gpio device.
- - qcom,qpnp-gpio-num : Specify the PMIC GPIO number for this gpio device.
+ - qcom,gpio-num : Specify the PMIC GPIO number for this gpio device.
 
-Optional properties :
- - qcom,qpnp-gpio-cfg : Specify the PMIC gpio configuration.
-   The format of this configuration is specified in a tuple of 9 entries.
-   These entries should be specified in the same order as the entries listed
-   in this following discription.
-
-   @direction:		indicates whether the gpio should be input, output, or
+Optional configuration properties :
+ -  qcom,direction:	indicates whether the gpio should be input, output, or
 			both.
+			QPNP_GPIO_DIR_IN   = 0,
 			QPNP_GPIO_DIR_OUT  = 1,
-			QPNP_GPIO_DIR_IN   = 2,
-			QPNP_GPIO_DIR_BOTH = 3
+			QPNP_GPIO_DIR_BOTH = 2
 
-   @output_type:	indicates gpio should be configured as CMOS or open
+ - qcom,output-type:	indicates gpio should be configured as CMOS or open
 			drain.
-			QPNP_GPIO_OUT_BUF_OPEN_DRAIN = 1,
 			QPNP_GPIO_OUT_BUF_CMOS = 0
+			QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS = 1,
+			QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS = 2,
 
-   @output_value:	The gpio output value of the gpio line - 0 or 1
-   @pull:		Indicates whether a pull up or pull down should be
+ - qcom,invert:		Invert the signal of the gpio line -
+			QPNP_GPIO_INVERT_DISABLE = 0
+			QPNP_GPIO_INVERT_ENABLE = 1
+
+ - qcom,pull:		Indicates whether a pull up or pull down should be
 			applied. If a pullup is required the current strength
 			needs to be specified. Current values of 30uA, 1.5uA,
 			31.5uA, 1.5uA with 30uA boost are supported.
@@ -55,7 +54,7 @@
 			QPNP_GPIO_PULL_DN	 = 4,
 			QPNP_GPIO_PULL_NO	 = 5
 
-  @vin_sel:		specifies the voltage level when the output is set to 1.
+  - qcom,vin-sel:	specifies the voltage level when the output is set to 1.
 			For an input gpio specifies the voltage level at which
 			the input is interpreted as a logical 1.
 			QPNP_GPIO_VIN0 = 0,
@@ -67,27 +66,32 @@
 			QPNP_GPIO_VIN6 = 6,
 			QPNP_GPIO_VIN7 = 7
 
-  @out_strength:	the amount of current supplied for an output gpio.
-			QPNP_GPIO_OUT_STRENGTH_HIGH = 1,
+  - qcom,out-strength:	the amount of current supplied for an output gpio.
+			QPNP_GPIO_OUT_STRENGTH_LOW  = 1
 			QPNP_GPIO_OUT_STRENGTH_MED  = 2,
-			QPNP_GPIO_OUT_STRENGTH_LOW  = 3
+			QPNP_GPIO_OUT_STRENGTH_HIGH = 3,
 
-  @source_sel:		choose alternate function for the gpio. Certain gpios
+  - qcom,source-sel:	choose alternate function for the gpio. Certain gpios
 			can be paired (shorted) with each other. Some gpio pin
 			can act as alternate functions.
 			QPNP_GPIO_FUNC_NORMAL   = 0,
 			QPNP_GPIO_FUNC_PAIRED   = 1
 			QPNP_GPIO_FUNC_1	= 2,
-			QPNP_GPIO_FUNC_3	= 3,
+			QPNP_GPIO_FUNC_2	= 3,
 			QPNP_GPIO_DTEST1	= 4,
 			QPNP_GPIO_DTEST2	= 5,
 			QPNP_GPIO_DTEST3	= 6,
 			QPNP_GPIO_DTEST4	= 7
 
-  @master_en:		1 = Enable features within the GPIO block based on
-			configurations.
-			0 = Completely disable the GPIO block and let the pin
-			float with high impedance regardless of other settings.
+ - qcom,master-en:	1 = Enable features within the
+			GPIO block based on configurations.
+			0 = Completely disable the GPIO
+			block and let the pin float with high impedance
+			regardless of other settings.
+
+*Note: If any of the configuration properties are not specified, then the
+       qpnp-gpio driver will not modify that respective configuration in
+       hardware.
 
 [PMIC GPIO clients]
 
@@ -116,15 +120,16 @@
 				#address-cells = <1>;
 				#size-cells = <1>;
 
-				qcom,pm8941_gpio1@0xc000 {
+				gpio@c000 {
 					reg = <0xc000 0x100>;
-					qcom,qpnp-gpio-num = <62>;
+					qcom,gpio-num = <62>;
 				};
 
-				qcom,pm8941_gpio2@0xc100 {
+				gpio@c100 {
 					reg = <0xc100 0x100>;
-					qcom,qpnp-gpio-num = <20>;
-					qcom,qpnp-gpio-cfg = <0x1 0x1 0x1 0x2 0x3 0x2 0x0 0x0 0x1>;
+					qcom,gpio-num = <20>;
+					qcom,source_sel = <2>;
+					qcom,pull = <5>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index c8a4ff9..2698ea7 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -17,6 +17,238 @@
 		interrupt-controller;
 		#interrupt-cells = <3>;
 
+		qcom,pm8941@0 {
+			spmi-slave-container;
+			reg = <0x0>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			pm8941_gpios {
+				spmi-dev-container;
+				compatible = "qcom,qpnp-gpio";
+				gpio-controller;
+				#gpio-cells = <2>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				gpio@c000 {
+					reg = <0xc000 0x100>;
+					qcom,gpio-num = <1>;
+					status = "disabled";
+				};
+
+				gpio@c100 {
+					reg = <0xc100 0x100>;
+					qcom,gpio-num = <2>;
+					status = "disabled";
+				};
+
+				gpio@c200 {
+					reg = <0xc200 0x100>;
+					qcom,gpio-num = <3>;
+					status = "disabled";
+				};
+
+				gpio@c300 {
+					reg = <0xc300 0x100>;
+					qcom,gpio-num = <4>;
+					status = "disabled";
+				};
+
+				gpio@c400 {
+					reg = <0xc400 0x100>;
+					qcom,gpio-num = <5>;
+					status = "disabled";
+				};
+
+				gpio@c500 {
+					reg = <0xc500 0x100>;
+					qcom,gpio-num = <6>;
+					status = "disabled";
+				};
+
+				gpio@c600 {
+					reg = <0xc600 0x100>;
+					qcom,gpio-num = <7>;
+					status = "disabled";
+				};
+
+				gpio@c700 {
+					reg = <0xc700 0x100>;
+					qcom,gpio-num = <8>;
+					status = "disabled";
+				};
+
+				gpio@c800 {
+					reg = <0xc800 0x100>;
+					qcom,gpio-num = <9>;
+					status = "disabled";
+				};
+
+				gpio@c900 {
+					reg = <0xc900 0x100>;
+					qcom,gpio-num = <10>;
+					status = "disabled";
+				};
+
+				gpio@ca00 {
+					reg = <0xca00 0x100>;
+					qcom,gpio-num = <11>;
+					status = "disabled";
+				};
+
+				gpio@cb00 {
+					reg = <0xcb00 0x100>;
+					qcom,gpio-num = <12>;
+					status = "disabled";
+				};
+
+				gpio@cc00 {
+					reg = <0xcc00 0x100>;
+					qcom,gpio-num = <13>;
+					status = "disabled";
+				};
+
+				gpio@cd00 {
+					reg = <0xcd00 0x100>;
+					qcom,gpio-num = <14>;
+					status = "disabled";
+				};
+
+				gpio@ce00 {
+					reg = <0xce00 0x100>;
+					qcom,gpio-num = <15>;
+					status = "disabled";
+				};
+
+				gpio@cf00 {
+					reg = <0xcf00 0x100>;
+					qcom,gpio-num = <16>;
+					status = "disabled";
+				};
+
+				gpio@d000 {
+					reg = <0xd000 0x100>;
+					qcom,gpio-num = <17>;
+					status = "disabled";
+				};
+
+				gpio@d100 {
+					reg = <0xd100 0x100>;
+					qcom,gpio-num = <18>;
+					status = "disabled";
+				};
+
+				gpio@d200 {
+					reg = <0xd200 0x100>;
+					qcom,gpio-num = <19>;
+					status = "disabled";
+				};
+
+				gpio@d300 {
+					reg = <0xd300 0x100>;
+					qcom,gpio-num = <20>;
+					status = "disabled";
+				};
+
+				gpio@d400 {
+					reg = <0xd400 0x100>;
+					qcom,gpio-num = <21>;
+					status = "disabled";
+				};
+
+				gpio@d500 {
+					reg = <0xd500 0x100>;
+					qcom,gpio-num = <22>;
+					status = "disabled";
+				};
+
+				gpio@d600 {
+					reg = <0xd600 0x100>;
+					qcom,gpio-num = <23>;
+					status = "disabled";
+				};
+
+				gpio@d700 {
+					reg = <0xd700 0x100>;
+					qcom,gpio-num = <24>;
+					status = "disabled";
+				};
+
+				gpio@d800 {
+					reg = <0xd800 0x100>;
+					qcom,gpio-num = <25>;
+					status = "disabled";
+				};
+
+				gpio@d900 {
+					reg = <0xd900 0x100>;
+					qcom,gpio-num = <26>;
+					status = "disabled";
+				};
+
+				gpio@da00 {
+					reg = <0xda00 0x100>;
+					qcom,gpio-num = <27>;
+					status = "disabled";
+				};
+
+				gpio@db00 {
+					reg = <0xdb00 0x100>;
+					qcom,gpio-num = <28>;
+					status = "disabled";
+				};
+
+				gpio@dc00 {
+					reg = <0xdc00 0x100>;
+					qcom,gpio-num = <29>;
+					status = "disabled";
+				};
+
+				gpio@dd00 {
+					reg = <0xdd00 0x100>;
+					qcom,gpio-num = <30>;
+					status = "disabled";
+				};
+
+				gpio@de00 {
+					reg = <0xde00 0x100>;
+					qcom,gpio-num = <31>;
+					status = "disabled";
+				};
+
+				gpio@df00 {
+					reg = <0xdf00 0x100>;
+					qcom,gpio-num = <32>;
+					status = "disabled";
+				};
+
+				gpio@e000 {
+					reg = <0xe000 0x100>;
+					qcom,gpio-num = <33>;
+					status = "disabled";
+				};
+
+				gpio@e100 {
+					reg = <0xe100 0x100>;
+					qcom,gpio-num = <34>;
+					status = "disabled";
+				};
+
+				gpio@e200 {
+					reg = <0xe200 0x100>;
+					qcom,gpio-num = <35>;
+					status = "disabled";
+				};
+
+				gpio@e300 {
+					reg = <0xe300 0x100>;
+					qcom,gpio-num = <36>;
+					status = "disabled";
+				};
+			};
+		};
+
 		qcom,pm8941@1 {
 			spmi-slave-container;
 			reg = <0x1>;
diff --git a/arch/arm/boot/dts/msmcopper-gpio.dtsi b/arch/arm/boot/dts/msmcopper-gpio.dtsi
new file mode 100644
index 0000000..7c3f5ce
--- /dev/null
+++ b/arch/arm/boot/dts/msmcopper-gpio.dtsi
@@ -0,0 +1,214 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	qcom,spmi@fc4c0000 {
+
+		qcom,pm8941@0 {
+
+			pm8941_gpios: pm8941_gpios {
+
+				gpio@c000 {
+					qcom,gpio-num = <1>;
+					status = "ok";
+				};
+
+				gpio@c100 {
+					qcom,gpio-num = <2>;
+					status = "ok";
+				};
+
+				gpio@c200 {
+					qcom,gpio-num = <3>;
+					status = "ok";
+				};
+
+				gpio@c300 {
+					qcom,gpio-num = <4>;
+					status = "ok";
+				};
+
+				gpio@c400 {
+					qcom,gpio-num = <5>;
+					status = "ok";
+				};
+
+				gpio@c500 {
+					qcom,gpio-num = <6>;
+					status = "ok";
+				};
+
+				gpio@c600 {
+					qcom,gpio-num = <7>;
+					status = "ok";
+				};
+
+				gpio@c700 {
+					qcom,gpio-num = <8>;
+					status = "ok";
+				};
+
+				gpio@c800 {
+					qcom,gpio-num = <9>;
+					status = "ok";
+				};
+
+				gpio@c900 {
+					qcom,gpio-num = <10>;
+					status = "ok";
+				};
+
+				gpio@ca00 {
+					qcom,gpio-num = <11>;
+					status = "ok";
+				};
+
+				gpio@cb00 {
+					qcom,gpio-num = <12>;
+					status = "ok";
+				};
+
+				gpio@cc00 {
+					qcom,gpio-num = <13>;
+					status = "ok";
+				};
+
+				gpio@cd00 {
+					qcom,gpio-num = <14>;
+					status = "ok";
+				};
+
+				gpio@ce00 {
+					qcom,gpio-num = <15>;
+					status = "ok";
+				};
+
+				gpio@cf00 {
+					qcom,gpio-num = <16>;
+					status = "ok";
+				};
+
+				gpio@d000 {
+					qcom,gpio-num = <17>;
+					status = "ok";
+				};
+
+				gpio@d100 {
+					qcom,gpio-num = <18>;
+					status = "ok";
+				};
+
+				gpio@d200 {
+					qcom,gpio-num = <19>;
+					status = "ok";
+				};
+
+				gpio@d300 {
+					qcom,gpio-num = <20>;
+					status = "ok";
+				};
+
+				gpio@d400 {
+					qcom,gpio-num = <21>;
+					status = "ok";
+				};
+
+				gpio@d500 {
+					qcom,gpio-num = <22>;
+					status = "ok";
+				};
+
+				gpio@d600 {
+					qcom,gpio-num = <23>;
+					status = "ok";
+				};
+
+				gpio@d700 {
+					qcom,gpio-num = <24>;
+					status = "ok";
+				};
+
+				gpio@d800 {
+					qcom,gpio-num = <25>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@d900 {
+					qcom,gpio-num = <26>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@da00 {
+					qcom,gpio-num = <27>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@db00 {
+					qcom,gpio-num = <28>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@dc00 {
+					qcom,gpio-num = <29>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@dd00 {
+					qcom,gpio-num = <30>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@de00 {
+					qcom,gpio-num = <31>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@df00 {
+					qcom,gpio-num = <32>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@e000 {
+					qcom,gpio-num = <33>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@e100 {
+					qcom,gpio-num = <34>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@e200 {
+					qcom,gpio-num = <35>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+
+				gpio@e300 {
+					qcom,gpio-num = <36>;
+					qcom,out-strength = <1>;
+					status = "ok";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 4821290..e998ca9 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -14,6 +14,7 @@
 /include/ "msm-pm8841.dtsi"
 /include/ "msm-pm8941.dtsi"
 /include/ "msmcopper-regulator.dtsi"
+/include/ "msmcopper-gpio.dtsi"
 
 / {
 	model = "Qualcomm MSM Copper";
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 1107412..875b479 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -1113,3 +1113,113 @@
 	return 0;
 }
 #endif
+#ifdef CONFIG_ARCH_MSM8625
+ /*
+  *  Check for any interrupts which are enabled are pending
+  *  in the pending set or not.
+  *  Return :
+  *       0 : No pending interrupts
+  *       1 : Pending interrupts other than A9_M2A_5
+  */
+unsigned int msm_gic_spi_ppi_pending(void)
+{
+	unsigned int i, bit = 0;
+	unsigned int pending_enb = 0, pending = 0;
+	unsigned long value = 0;
+	struct gic_chip_data *gic = &gic_data[0];
+	void __iomem *base = gic_data_dist_base(gic);
+
+	raw_spin_lock(&irq_controller_lock);
+	/*
+	 * PPI and SGI to be included.
+	 * MSM8625_INT_A9_M2A_5 needs to be ignored, as A9_M2A_5
+	 * requesting sleep triggers it
+	 */
+	for (i = 0; (i * 32) < gic->max_irq; i++) {
+		pending = readl_relaxed(base +
+				GIC_DIST_PENDING_SET + i * 4);
+		pending_enb = readl_relaxed(base +
+				GIC_DIST_ENABLE_SET + i * 4);
+		value = pending & pending_enb;
+
+		if (value) {
+			for (bit = 0; bit < 32; bit++) {
+				bit = find_next_bit(&value, 32, bit);
+				if ((bit + 32 * i) != MSM8625_INT_A9_M2A_5) {
+					raw_spin_unlock(&irq_controller_lock);
+					return 1;
+				}
+			}
+		}
+	}
+	raw_spin_unlock(&irq_controller_lock);
+
+	return 0;
+}
+
+void msm_gic_save(bool modem_wake, int from_idle)
+{
+	unsigned int i;
+	struct gic_chip_data *gic = &gic_data[0];
+	void __iomem *base = gic_data_dist_base(gic);
+
+	gic_cpu_save(0);
+	gic_dist_save(0);
+	 /* Disable all the Interrupts, if we enter from idle pc */
+	if (from_idle) {
+		for (i = 0; (i * 32) < gic->max_irq; i++) {
+			raw_spin_lock(&irq_controller_lock);
+			writel_relaxed(0xffffffff, base
+					+ GIC_DIST_ENABLE_CLEAR + i * 4);
+			raw_spin_unlock(&irq_controller_lock);
+		}
+	}
+}
+
+void msm_gic_restore(void)
+{
+	gic_dist_restore(0);
+	gic_cpu_restore(0);
+}
+
+/*
+ * Configure the GIC after we come out of power collapse.
+ * This function will configure some of the GIC registers so as to prepare the
+ * core1 to receive an SPI(ACSR_MP_CORE_IPC1, (32 + 8)), which will bring
+ * core1 out of GDFS.
+ */
+void core1_gic_configure_and_raise(void)
+{
+	struct gic_chip_data *gic = &gic_data[0];
+	void __iomem *base = gic_data_dist_base(gic);
+	unsigned int value = 0;
+
+	raw_spin_lock(&irq_controller_lock);
+
+	value = __raw_readl(base + GIC_DIST_ACTIVE_BIT + 0x4);
+	value |= BIT(8);
+	__raw_writel(value, base + GIC_DIST_ACTIVE_BIT + 0x4);
+	mb();
+
+	value = __raw_readl(base + GIC_DIST_TARGET + 0x24);
+	value |= BIT(13);
+	__raw_writel(value, base + GIC_DIST_TARGET + 0x24);
+	mb();
+
+	value = __raw_readl(base + GIC_DIST_TARGET + 0x28);
+	value |= BIT(1);
+	__raw_writel(value, base + GIC_DIST_TARGET + 0x28);
+	mb();
+
+	value =  __raw_readl(base + GIC_DIST_ENABLE_SET + 0x4);
+	value |= BIT(8);
+	__raw_writel(value, base + GIC_DIST_ENABLE_SET + 0x4);
+	mb();
+
+	value =  __raw_readl(base + GIC_DIST_PENDING_SET + 0x4);
+	value |= BIT(8);
+	__raw_writel(value, base + GIC_DIST_PENDING_SET + 0x4);
+	mb();
+	raw_spin_unlock(&irq_controller_lock);
+}
+#endif
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 5b77374..f195d68 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -309,6 +309,7 @@
 CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_MSM_PDM=y
+CONFIG_LEDS_PMIC_MPP=y
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 287e7fb..9952818 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -309,6 +309,7 @@
 CONFIG_MMC_MSM_SDC3_SUPPORT=y
 CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
 CONFIG_LEDS_MSM_PDM=y
+CONFIG_LEDS_PMIC_MPP=y
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 5668e75..7e1989e 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -63,4 +63,10 @@
 
 #endif
 
+#ifdef CONFIG_ARCH_MSM8625
+void msm_gic_save(bool modem_wake, int from_idle);
+void msm_gic_restore(void);
+void core1_gic_configure_and_raise(void);
+#endif
+
 #endif
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 99a3fa1..3431cd0 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -433,6 +433,19 @@
 	.drv = GPIOMUX_DRV_12MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
+
+static struct gpiomux_setting sx150x_suspended_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sx150x_active_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct gpiomux_setting cyts_sleep_sus_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_6MA,
@@ -968,6 +981,16 @@
 	},
 };
 
+static struct msm_gpiomux_config sx150x_int_configs[] __initdata = {
+	{
+		.gpio      = 81,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &sx150x_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &sx150x_active_cfg,
+		},
+	},
+};
+
 void __init apq8064_init_gpiomux(void)
 {
 	int rc;
@@ -989,6 +1012,8 @@
 		msm_gpiomux_install(vcap_configs,
 				ARRAY_SIZE(vcap_configs));
 #endif
+		msm_gpiomux_install(sx150x_int_configs,
+				ARRAY_SIZE(sx150x_int_configs));
 	} else {
 		#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 		msm_gpiomux_install(apq8064_ethernet_configs,
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 5b0b9c3..d08fe01 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -154,7 +154,7 @@
 	.memory_type = MEMTYPE_EBI1,
 };
 
-static struct platform_device android_pmem_device = {
+static struct platform_device apq8064_android_pmem_device = {
 	.name = "android_pmem",
 	.id = 0,
 	.dev = {.platform_data = &android_pmem_pdata},
@@ -166,7 +166,7 @@
 	.cached = 0,
 	.memory_type = MEMTYPE_EBI1,
 };
-static struct platform_device android_pmem_adsp_device = {
+static struct platform_device apq8064_android_pmem_adsp_device = {
 	.name = "android_pmem",
 	.id = 2,
 	.dev = { .platform_data = &android_pmem_adsp_pdata },
@@ -179,7 +179,7 @@
 	.memory_type = MEMTYPE_EBI1,
 };
 
-static struct platform_device android_pmem_audio_device = {
+static struct platform_device apq8064_android_pmem_audio_device = {
 	.name = "android_pmem",
 	.id = 4,
 	.dev = { .platform_data = &android_pmem_audio_pdata },
@@ -199,7 +199,7 @@
 };
 
 #if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data msm_rtb_pdata = {
+static struct msm_rtb_platform_data apq8064_rtb_pdata = {
 	.size = SZ_1M,
 };
 
@@ -208,17 +208,17 @@
 	int s;
 
 	s = memparse(p, NULL);
-	msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+	apq8064_rtb_pdata.size = ALIGN(s, SZ_4K);
 	return 0;
 }
 early_param("msm_rtb_size", msm_rtb_set_buffer_size);
 
 
-static struct platform_device msm_rtb_device = {
+static struct platform_device apq8064_rtb_device = {
 	.name           = "msm_rtb",
 	.id             = -1,
 	.dev            = {
-		.platform_data = &msm_rtb_pdata,
+		.platform_data = &apq8064_rtb_pdata,
 	},
 };
 #endif
@@ -226,7 +226,7 @@
 static void __init reserve_rtb_memory(void)
 {
 #if defined(CONFIG_MSM_RTB)
-	apq8064_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+	apq8064_reserve_table[MEMTYPE_EBI1].size += apq8064_rtb_pdata.size;
 #endif
 }
 
@@ -270,22 +270,22 @@
 
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mm_apq8064_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
 };
 
-static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mfc_apq8064_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
 };
 
-static struct ion_co_heap_pdata co_ion_pdata = {
+static struct ion_co_heap_pdata co_apq8064_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
 };
 
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
+static struct ion_co_heap_pdata fw_co_apq8064_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
 };
@@ -302,7 +302,7 @@
  * to each other.
  * Don't swap the order unless you know what you are doing!
  */
-static struct ion_platform_data ion_pdata = {
+static struct ion_platform_data apq8064_ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
 		{
@@ -317,7 +317,7 @@
 			.name	= ION_MM_HEAP_NAME,
 			.size	= MSM_ION_MM_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &cp_mm_ion_pdata,
+			.extra_data = (void *) &cp_mm_apq8064_ion_pdata,
 		},
 		{
 			.id	= ION_MM_FIRMWARE_HEAP_ID,
@@ -325,7 +325,7 @@
 			.name	= ION_MM_FIRMWARE_HEAP_NAME,
 			.size	= MSM_ION_MM_FW_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &fw_co_ion_pdata,
+			.extra_data = (void *) &fw_co_apq8064_ion_pdata,
 		},
 		{
 			.id	= ION_CP_MFC_HEAP_ID,
@@ -333,7 +333,7 @@
 			.name	= ION_MFC_HEAP_NAME,
 			.size	= MSM_ION_MFC_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &cp_mfc_ion_pdata,
+			.extra_data = (void *) &cp_mfc_apq8064_ion_pdata,
 		},
 #ifndef CONFIG_MSM_IOMMU
 		{
@@ -342,7 +342,7 @@
 			.name	= ION_SF_HEAP_NAME,
 			.size	= MSM_ION_SF_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_apq8064_ion_pdata,
 		},
 #endif
 		{
@@ -356,7 +356,7 @@
 			.name	= ION_QSECOM_HEAP_NAME,
 			.size	= MSM_ION_QSECOM_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_apq8064_ion_pdata,
 		},
 		{
 			.id	= ION_AUDIO_HEAP_ID,
@@ -364,16 +364,16 @@
 			.name	= ION_AUDIO_HEAP_NAME,
 			.size	= MSM_ION_AUDIO_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_apq8064_ion_pdata,
 		},
 #endif
 	}
 };
 
-static struct platform_device ion_dev = {
+static struct platform_device apq8064_ion_dev = {
 	.name = "ion-msm",
 	.id = 1,
-	.dev = { .platform_data = &ion_pdata },
+	.dev = { .platform_data = &apq8064_ion_pdata },
 };
 #endif
 
@@ -1889,13 +1889,13 @@
 	&msm_device_iris_fm,
 #ifdef CONFIG_ANDROID_PMEM
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	&android_pmem_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
+	&apq8064_android_pmem_device,
+	&apq8064_android_pmem_adsp_device,
+	&apq8064_android_pmem_audio_device,
 #endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
 #endif /*CONFIG_ANDROID_PMEM*/
 #ifdef CONFIG_ION_MSM
-	&ion_dev,
+	&apq8064_ion_dev,
 #endif
 	&msm8064_device_watchdog,
 	&msm8064_device_saw_regulator_core0,
@@ -1964,7 +1964,7 @@
 	&msm_pil_vidc,
 	&msm_gss,
 #ifdef CONFIG_MSM_RTB
-	&msm_rtb_device,
+	&apq8064_rtb_device,
 #endif
 	&apq8064_cpu_idle_device,
 	&apq8064_msm_gov_device,
@@ -2356,6 +2356,7 @@
 };
 
 #define SX150X_EXP1_INT_N	PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9)
+#define SX150X_EXP2_INT_N	MSM_GPIO_TO_INT(81)
 
 struct sx150x_platform_data mpq8064_sx150x_pdata[] = {
 	[SX150X_EXP1] = {
@@ -2375,7 +2376,8 @@
 		.io_pulldn_ena	= 0x0,
 		.io_open_drain_ena = 0x0,
 		.io_polarity	= 0,
-		.irq_summary	= -1,
+		.irq_summary	= SX150X_EXP2_INT_N,
+		.irq_base	= SX150X_EXP2_IRQ_BASE,
 	},
 	[SX150X_EXP3] = {
 		.gpio_base	= SX150X_EXP3_GPIO_BASE,
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 24e6a79..1cf1935 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -185,7 +185,7 @@
 	.memory_type = MEMTYPE_EBI1,
 };
 
-static struct platform_device android_pmem_device = {
+static struct platform_device msm8930_android_pmem_device = {
 	.name = "android_pmem",
 	.id = 0,
 	.dev = {.platform_data = &android_pmem_pdata},
@@ -197,7 +197,7 @@
 	.cached = 0,
 	.memory_type = MEMTYPE_EBI1,
 };
-static struct platform_device android_pmem_adsp_device = {
+static struct platform_device msm8930_android_pmem_adsp_device = {
 	.name = "android_pmem",
 	.id = 2,
 	.dev = { .platform_data = &android_pmem_adsp_pdata },
@@ -210,7 +210,7 @@
 	.memory_type = MEMTYPE_EBI1,
 };
 
-static struct platform_device android_pmem_audio_device = {
+static struct platform_device msm8930_android_pmem_audio_device = {
 	.name = "android_pmem",
 	.id = 4,
 	.dev = { .platform_data = &android_pmem_audio_pdata },
@@ -250,7 +250,7 @@
 };
 
 #if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data msm_rtb_pdata = {
+static struct msm_rtb_platform_data msm8930_rtb_pdata = {
 	.size = SZ_1M,
 };
 
@@ -259,17 +259,17 @@
 	int s;
 
 	s = memparse(p, NULL);
-	msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+	msm8930_rtb_pdata.size = ALIGN(s, SZ_4K);
 	return 0;
 }
 early_param("msm_rtb_size", msm_rtb_set_buffer_size);
 
 
-static struct platform_device msm_rtb_device = {
+static struct platform_device msm8930_rtb_device = {
 	.name           = "msm_rtb",
 	.id             = -1,
 	.dev            = {
-		.platform_data = &msm_rtb_pdata,
+		.platform_data = &msm8930_rtb_pdata,
 	},
 };
 #endif
@@ -277,7 +277,7 @@
 static void __init reserve_rtb_memory(void)
 {
 #if defined(CONFIG_MSM_RTB)
-	msm8930_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+	msm8930_reserve_table[MEMTYPE_EBI1].size += msm8930_rtb_pdata.size;
 #endif
 }
 
@@ -320,20 +320,20 @@
 
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mm_msm8930_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
 };
 
-static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mfc_msm8930_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
 };
-static struct ion_co_heap_pdata co_ion_pdata = {
+static struct ion_co_heap_pdata co_msm8930_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
 };
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
+static struct ion_co_heap_pdata fw_co_msm8930_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
 };
@@ -350,7 +350,7 @@
  * to each other.
  * Don't swap the order unless you know what you are doing!
  */
-static struct ion_platform_data ion_pdata = {
+static struct ion_platform_data msm8930_ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
 		{
@@ -365,7 +365,7 @@
 			.name	= ION_MM_HEAP_NAME,
 			.size	= MSM_ION_MM_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &cp_mm_ion_pdata,
+			.extra_data = (void *) &cp_mm_msm8930_ion_pdata,
 		},
 		{
 			.id	= ION_MM_FIRMWARE_HEAP_ID,
@@ -373,7 +373,7 @@
 			.name	= ION_MM_FIRMWARE_HEAP_NAME,
 			.size	= MSM_ION_MM_FW_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &fw_co_ion_pdata,
+			.extra_data = (void *) &fw_co_msm8930_ion_pdata,
 		},
 		{
 			.id	= ION_CP_MFC_HEAP_ID,
@@ -381,7 +381,7 @@
 			.name	= ION_MFC_HEAP_NAME,
 			.size	= MSM_ION_MFC_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &cp_mfc_ion_pdata,
+			.extra_data = (void *) &cp_mfc_msm8930_ion_pdata,
 		},
 		{
 			.id	= ION_SF_HEAP_ID,
@@ -389,7 +389,7 @@
 			.name	= ION_SF_HEAP_NAME,
 			.size	= MSM_ION_SF_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_msm8930_ion_pdata,
 		},
 		{
 			.id	= ION_IOMMU_HEAP_ID,
@@ -402,7 +402,7 @@
 			.name	= ION_QSECOM_HEAP_NAME,
 			.size	= MSM_ION_QSECOM_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_msm8930_ion_pdata,
 		},
 		{
 			.id	= ION_AUDIO_HEAP_ID,
@@ -410,16 +410,16 @@
 			.name	= ION_AUDIO_HEAP_NAME,
 			.size	= MSM_ION_AUDIO_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_msm8930_ion_pdata,
 		},
 #endif
 	}
 };
 
-static struct platform_device ion_dev = {
+static struct platform_device msm8930_ion_dev = {
 	.name = "ion-msm",
 	.id = 1,
-	.dev = { .platform_data = &ion_pdata },
+	.dev = { .platform_data = &msm8930_ion_pdata },
 };
 #endif
 
@@ -1286,30 +1286,35 @@
 	},
 };
 
-#/* TODO: Remove this once PM8038 physically becomes
- * available.
- */
 #define ISA1200_HAP_EN_GPIO	77
 #define ISA1200_HAP_LEN_GPIO	78
 #define ISA1200_HAP_CLK		PM8038_GPIO_PM_TO_SYS(7)
 
 static int isa1200_power(int on)
 {
+	int rc = 0;
+
 	gpio_set_value_cansleep(ISA1200_HAP_CLK, !!on);
 
-	return 0;
+	if (on)
+		rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_1, true);
+	else
+		rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_NONE, true);
+
+	if (rc) {
+		pr_err("%s: unable to write aux clock register(%d)\n",
+			__func__, rc);
+	}
+
+	return rc;
 }
 
 static int isa1200_dev_setup(bool enable)
 {
 	int rc = 0;
 
-	rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_1, enable);
-	if (rc) {
-		pr_err("%s: unable to write aux clock register(%d)\n",
-			__func__, rc);
-		return rc;
-	}
+	if (!enable)
+		goto fail_gpio_dir;
 
 	rc = gpio_request(ISA1200_HAP_CLK, "haptics_clk");
 	if (rc) {
@@ -1749,9 +1754,9 @@
 #endif
 #ifdef CONFIG_ANDROID_PMEM
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	&android_pmem_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
+	&msm8930_android_pmem_device,
+	&msm8930_android_pmem_adsp_device,
+	&msm8930_android_pmem_audio_device,
 #endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
 #endif /*CONFIG_ANDROID_PMEM*/
 	&msm_device_bam_dmux,
@@ -1764,7 +1769,7 @@
 	&msm8930_rpm_log_device,
 	&msm8930_rpm_stat_device,
 #ifdef CONFIG_ION_MSM
-	&ion_dev,
+	&msm8930_ion_dev,
 #endif
 	&msm_device_tz_log,
 
@@ -1781,7 +1786,7 @@
 	&gpio_keys_8930,
 #endif
 #ifdef CONFIG_MSM_RTB
-	&msm_rtb_device,
+	&msm8930_rtb_device,
 #endif
 	&msm8930_cpu_idle_device,
 	&msm8930_msm_gov_device,
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 6328ab3..defa33b 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -224,7 +224,7 @@
 	.memory_type = MEMTYPE_EBI1,
 };
 
-static struct platform_device android_pmem_device = {
+static struct platform_device msm8960_android_pmem_device = {
 	.name = "android_pmem",
 	.id = 0,
 	.dev = {.platform_data = &android_pmem_pdata},
@@ -236,7 +236,7 @@
 	.cached = 0,
 	.memory_type = MEMTYPE_EBI1,
 };
-static struct platform_device android_pmem_adsp_device = {
+static struct platform_device msm8960_android_pmem_adsp_device = {
 	.name = "android_pmem",
 	.id = 2,
 	.dev = { .platform_data = &android_pmem_adsp_pdata },
@@ -249,7 +249,7 @@
 	.memory_type = MEMTYPE_EBI1,
 };
 
-static struct platform_device android_pmem_audio_device = {
+static struct platform_device msm8960_android_pmem_audio_device = {
 	.name = "android_pmem",
 	.id = 4,
 	.dev = { .platform_data = &android_pmem_audio_pdata },
@@ -257,7 +257,7 @@
 #endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
 #endif /*CONFIG_ANDROID_PMEM*/
 
-struct fmem_platform_data fmem_pdata = {
+struct fmem_platform_data msm8960_fmem_pdata = {
 };
 
 #define DSP_RAM_BASE_8960 0x8da00000
@@ -292,7 +292,7 @@
 };
 
 #if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data msm_rtb_pdata = {
+static struct msm_rtb_platform_data msm8960_rtb_pdata = {
 	.size = SZ_1M,
 };
 
@@ -301,17 +301,17 @@
 	int s;
 
 	s = memparse(p, NULL);
-	msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+	msm8960_rtb_pdata.size = ALIGN(s, SZ_4K);
 	return 0;
 }
 early_param("msm_rtb_size", msm_rtb_set_buffer_size);
 
 
-static struct platform_device msm_rtb_device = {
+static struct platform_device msm8960_rtb_device = {
 	.name           = "msm_rtb",
 	.id             = -1,
 	.dev            = {
-		.platform_data = &msm_rtb_pdata,
+		.platform_data = &msm8960_rtb_pdata,
 	},
 };
 #endif
@@ -319,7 +319,7 @@
 static void __init reserve_rtb_memory(void)
 {
 #if defined(CONFIG_MSM_RTB)
-	msm8960_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+	msm8960_reserve_table[MEMTYPE_EBI1].size += msm8960_rtb_pdata.size;
 #endif
 }
 
@@ -372,7 +372,7 @@
 
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mm_msm8960_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
 	.reusable = FMEM_ENABLED,
@@ -380,7 +380,7 @@
 	.fixed_position = FIXED_MIDDLE,
 };
 
-static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mfc_msm8960_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
 	.reusable = 0,
@@ -388,13 +388,13 @@
 	.fixed_position = FIXED_HIGH,
 };
 
-static struct ion_co_heap_pdata co_ion_pdata = {
+static struct ion_co_heap_pdata co_msm8960_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
 	.mem_is_fmem = 0,
 };
 
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
+static struct ion_co_heap_pdata fw_co_msm8960_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
 	.mem_is_fmem = FMEM_ENABLED,
@@ -413,7 +413,7 @@
  * to each other.
  * Don't swap the order unless you know what you are doing!
  */
-static struct ion_platform_data ion_pdata = {
+static struct ion_platform_data msm8960_ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
 		{
@@ -428,7 +428,7 @@
 			.name	= ION_MM_HEAP_NAME,
 			.size	= MSM_ION_MM_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &cp_mm_ion_pdata,
+			.extra_data = (void *) &cp_mm_msm8960_ion_pdata,
 		},
 		{
 			.id	= ION_MM_FIRMWARE_HEAP_ID,
@@ -436,7 +436,7 @@
 			.name	= ION_MM_FIRMWARE_HEAP_NAME,
 			.size	= MSM_ION_MM_FW_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &fw_co_ion_pdata,
+			.extra_data = (void *) &fw_co_msm8960_ion_pdata,
 		},
 		{
 			.id	= ION_CP_MFC_HEAP_ID,
@@ -444,7 +444,7 @@
 			.name	= ION_MFC_HEAP_NAME,
 			.size	= MSM_ION_MFC_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &cp_mfc_ion_pdata,
+			.extra_data = (void *) &cp_mfc_msm8960_ion_pdata,
 		},
 #ifndef CONFIG_MSM_IOMMU
 		{
@@ -453,7 +453,7 @@
 			.name	= ION_SF_HEAP_NAME,
 			.size	= MSM_ION_SF_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_msm8960_ion_pdata,
 		},
 #endif
 		{
@@ -467,7 +467,7 @@
 			.name	= ION_QSECOM_HEAP_NAME,
 			.size	= MSM_ION_QSECOM_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_msm8960_ion_pdata,
 		},
 		{
 			.id	= ION_AUDIO_HEAP_ID,
@@ -475,23 +475,23 @@
 			.name	= ION_AUDIO_HEAP_NAME,
 			.size	= MSM_ION_AUDIO_SIZE,
 			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
+			.extra_data = (void *) &co_msm8960_ion_pdata,
 		},
 #endif
 	}
 };
 
-static struct platform_device ion_dev = {
+static struct platform_device msm8960_ion_dev = {
 	.name = "ion-msm",
 	.id = 1,
-	.dev = { .platform_data = &ion_pdata },
+	.dev = { .platform_data = &msm8960_ion_pdata },
 };
 #endif
 
-struct platform_device fmem_device = {
+struct platform_device msm8960_fmem_device = {
 	.name = "fmem",
 	.id = 1,
-	.dev = { .platform_data = &fmem_pdata },
+	.dev = { .platform_data = &msm8960_fmem_pdata },
 };
 
 static void __init adjust_mem_for_liquid(void)
@@ -507,9 +507,10 @@
 
 		if (machine_is_msm8960_liquid() ||
 			msm8960_hdmi_as_primary_selected()) {
-			for (i = 0; i < ion_pdata.nr; i++) {
-				if (ion_pdata.heaps[i].id == ION_SF_HEAP_ID) {
-					ion_pdata.heaps[i].size =
+			for (i = 0; i < msm8960_ion_pdata.nr; i++) {
+				if (msm8960_ion_pdata.heaps[i].id ==
+							ION_SF_HEAP_ID) {
+					msm8960_ion_pdata.heaps[i].size =
 						msm_ion_sf_size;
 					pr_debug("msm_ion_sf_size 0x%x\n",
 						msm_ion_sf_size);
@@ -566,9 +567,9 @@
 	unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
 
 	adjust_mem_for_liquid();
-	fmem_pdata.size = 0;
-	fmem_pdata.reserved_size_low = 0;
-	fmem_pdata.reserved_size_high = 0;
+	msm8960_fmem_pdata.size = 0;
+	msm8960_fmem_pdata.reserved_size_low = 0;
+	msm8960_fmem_pdata.reserved_size_high = 0;
 	fixed_low_size = 0;
 	fixed_middle_size = 0;
 	fixed_high_size = 0;
@@ -576,8 +577,9 @@
 	/* We only support 1 reusable heap. Check if more than one heap
 	 * is specified as reusable and set as non-reusable if found.
 	 */
-	for (i = 0; i < ion_pdata.nr; ++i) {
-		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+	for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap =
+						&(msm8960_ion_pdata.heaps[i]);
 
 		if (heap->type == ION_HEAP_TYPE_CP && heap->extra_data) {
 			struct ion_cp_heap_pdata *data = heap->extra_data;
@@ -593,8 +595,9 @@
 		}
 	}
 
-	for (i = 0; i < ion_pdata.nr; ++i) {
-		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+	for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap =
+						&(msm8960_ion_pdata.heaps[i]);
 
 		if (heap->extra_data) {
 			int fixed_position = NOT_FIXED;
@@ -630,16 +633,16 @@
 				fixed_high_size += heap->size;
 
 			if (mem_is_fmem)
-				fmem_pdata.size += heap->size;
+				msm8960_fmem_pdata.size += heap->size;
 		}
 	}
 
 	if (!fixed_size)
 		return;
 
-	if (fmem_pdata.size) {
-		fmem_pdata.reserved_size_low = fixed_low_size;
-		fmem_pdata.reserved_size_high = fixed_high_size;
+	if (msm8960_fmem_pdata.size) {
+		msm8960_fmem_pdata.reserved_size_low = fixed_low_size;
+		msm8960_fmem_pdata.reserved_size_high = fixed_high_size;
 	}
 
 	/* Since the fixed area may be carved out of lowmem,
@@ -653,8 +656,8 @@
 	fixed_middle_start = fixed_low_start + fixed_low_size;
 	fixed_high_start = fixed_middle_start + fixed_middle_size;
 
-	for (i = 0; i < ion_pdata.nr; ++i) {
-		struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+	for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
+		struct ion_platform_heap *heap = &(msm8960_ion_pdata.heaps[i]);
 
 		if (heap->extra_data) {
 			int fixed_position = NOT_FIXED;
@@ -696,15 +699,15 @@
 }
 
 #if defined(CONFIG_MSM_CACHE_DUMP)
-static struct msm_cache_dump_platform_data msm_cache_dump_pdata = {
+static struct msm_cache_dump_platform_data msm8960_cache_dump_pdata = {
 	.l2_size = L2_BUFFER_SIZE,
 };
 
-static struct platform_device msm_cache_dump_device = {
+static struct platform_device msm8960_cache_dump_device = {
 	.name           = "msm_cache_dump",
 	.id             = -1,
 	.dev            = {
-		.platform_data = &msm_cache_dump_pdata,
+		.platform_data = &msm8960_cache_dump_pdata,
 	},
 };
 
@@ -736,8 +739,8 @@
 	total = l1_size + l2_size;
 
 	msm8960_reserve_table[MEMTYPE_EBI1].size += total;
-	msm_cache_dump_pdata.l1_size = l1_size;
-	msm_cache_dump_pdata.l2_size = l2_size;
+	msm8960_cache_dump_pdata.l1_size = l1_size;
+	msm8960_cache_dump_pdata.l2_size = l2_size;
 #endif
 }
 
@@ -841,16 +844,17 @@
 {
 	msm8960_set_display_params(prim_panel_name, ext_panel_name);
 	msm_reserve();
-	if (fmem_pdata.size) {
+	if (msm8960_fmem_pdata.size) {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-		fmem_pdata.phys = reserve_info->fixed_area_start +
+		msm8960_fmem_pdata.phys = reserve_info->fixed_area_start +
 			MSM_MM_FW_SIZE;
 		pr_info("mm fw at %lx (fixed) size %x\n",
 			reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
 		pr_info("fmem start %lx (fixed) size %lx\n",
-			fmem_pdata.phys, fmem_pdata.size);
+			msm8960_fmem_pdata.phys, msm8960_fmem_pdata.size);
 #else
-		fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
+		msm8960_fmem_pdata.phys =
+			reserve_memory_for_fmem(msm8960_fmem_pdata.size);
 #endif
 	}
 }
@@ -2539,12 +2543,12 @@
 #ifdef CONFIG_MSM_FAKE_BATTERY
 	&fish_battery_device,
 #endif
-	&fmem_device,
+	&msm8960_fmem_device,
 #ifdef CONFIG_ANDROID_PMEM
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	&android_pmem_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
+	&msm8960_android_pmem_device,
+	&msm8960_android_pmem_adsp_device,
+	&msm8960_android_pmem_audio_device,
 #endif
 #endif
 	&msm_device_vidc,
@@ -2563,7 +2567,7 @@
 	&msm_device_rng,
 #endif
 #ifdef CONFIG_ION_MSM
-	&ion_dev,
+	&msm8960_ion_dev,
 #endif
 	&msm8960_rpm_device,
 	&msm8960_rpm_log_device,
@@ -2579,13 +2583,13 @@
 	&msm_device_dspcrashd_8960,
 	&msm8960_device_watchdog,
 #ifdef CONFIG_MSM_RTB
-	&msm_rtb_device,
+	&msm8960_rtb_device,
 #endif
 	&msm8960_cpu_idle_device,
 	&msm8960_msm_gov_device,
 	&msm8960_device_cache_erp,
 #ifdef CONFIG_MSM_CACHE_DUMP
-	&msm_cache_dump_device,
+	&msm8960_cache_dump_device,
 #endif
 	&msm8960_iommu_domain_device,
 };
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index e622dfe..7f84920 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -25,6 +25,7 @@
 #include <asm/gpio.h>
 #include <asm/mach-types.h>
 #include <mach/rpc_server_handset.h>
+#include <mach/pmic.h>
 
 #include "devices.h"
 #include "board-msm7627a.h"
@@ -653,6 +654,24 @@
 	},
 };
 
+static struct led_info ctp_backlight_info = {
+	.name           = "button-backlight",
+	.flags          = PM_MPP__I_SINK__LEVEL_40mA << 16 | PM_MPP_7,
+};
+
+static struct led_platform_data ctp_backlight_pdata = {
+	.leds = &ctp_backlight_info,
+	.num_leds = 1,
+};
+
+static struct platform_device pmic_mpp_leds_pdev = {
+	.name   = "pmic-mpp-leds",
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &ctp_backlight_pdata,
+	},
+};
+
 void __init msm7627a_add_io_devices(void)
 {
 	/* touchscreen */
@@ -752,5 +771,6 @@
 		}
 
 		platform_device_register(&gpio_leds_8625);
+		platform_device_register(&pmic_mpp_leds_pdev);
 	}
 }
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 0997e8bd..0832a03 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1412,7 +1412,12 @@
 		.freq_hz = f, \
 		.src_clk = &s##_clk.c, \
 	}
-static struct clk_freq_tbl clk_tbl_prng[] = {
+static struct clk_freq_tbl clk_tbl_prng_32[] = {
+	F_PRNG(32000000, pll8),
+	F_END
+};
+
+static struct clk_freq_tbl clk_tbl_prng_64[] = {
 	F_PRNG(64000000, pll8),
 	F_END
 };
@@ -1426,12 +1431,12 @@
 		.halt_bit = 10,
 	},
 	.set_rate = set_rate_nop,
-	.freq_tbl = clk_tbl_prng,
+	.freq_tbl = clk_tbl_prng_32,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "prng_clk",
 		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
+		VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000),
 		CLK_INIT(prng_clk.c),
 	},
 };
@@ -4927,8 +4932,6 @@
 	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	""),
 	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	""),
 	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	""),
-	CLK_LOOKUP("iface_clk",		ce1_p_clk.c,		""),
-	CLK_LOOKUP("core_clk",		ce1_core_clk.c,		""),
 	CLK_LOOKUP("ref_clk",		sata_phy_ref_clk.c,	""),
 	CLK_LOOKUP("cfg_clk",		sata_phy_cfg_clk.c,	""),
 	CLK_LOOKUP("iface_clk",		ce3_p_clk.c,		"qce.0"),
@@ -6010,6 +6013,8 @@
 		pll15_clk.c.rate = 900000000;
 		gmem_axi_clk.c.depends = &gfx3d_axi_clk_8930.c;
 	}
+	if ((readl_relaxed(PRNG_CLK_NS_REG) & 0x7F) == 0x2B)
+		prng_clk.freq_tbl = clk_tbl_prng_64;
 
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
 
@@ -6034,7 +6039,7 @@
 
 	/* Initialize rates for clocks that only support one. */
 	clk_set_rate(&pdm_clk.c, 27000000);
-	clk_set_rate(&prng_clk.c, 64000000);
+	clk_set_rate(&prng_clk.c, prng_clk.freq_tbl->freq_hz);
 	clk_set_rate(&mdp_vsync_clk.c, 27000000);
 	clk_set_rate(&tsif_ref_clk.c, 105000);
 	clk_set_rate(&tssc_clk.c, 27000000);
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 26ccaa3..5bfd348 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -75,6 +75,7 @@
 #define PLLTEST_PAD_CFG_REG			REG(0x2FA4)
 #define PMEM_ACLK_CTL_REG			REG(0x25A0)
 #define PPSS_HCLK_CTL_REG			REG(0x2580)
+#define PRNG_CLK_NS_REG				REG(0x2E80)
 #define RINGOSC_NS_REG				REG(0x2DC0)
 #define RINGOSC_STATUS_REG			REG(0x2DCC)
 #define RINGOSC_TCXO_CTL_REG			REG(0x2DC4)
@@ -1139,7 +1140,12 @@
 		.freq_hz = f, \
 		.src_clk = &s##_clk.c, \
 	}
-static struct clk_freq_tbl clk_tbl_prng[] = {
+static struct clk_freq_tbl clk_tbl_prng_32[] = {
+	F_PRNG(32000000, pll8),
+	F_END
+};
+
+static struct clk_freq_tbl clk_tbl_prng_64[] = {
 	F_PRNG(64000000, pll8),
 	F_END
 };
@@ -1153,12 +1159,12 @@
 		.halt_bit = 10,
 	},
 	.set_rate = set_rate_nop,
-	.freq_tbl = clk_tbl_prng,
+	.freq_tbl = clk_tbl_prng_32,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
 		.dbg_name = "prng_clk",
 		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
+		VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000),
 		CLK_INIT(prng_clk.c),
 	},
 };
@@ -3788,6 +3794,9 @@
 	/* Set the dsi_byte_clk src to the DSI PHY PLL,
 	 * dsi_esc_clk to PXO/2, and the hdmi_app_clk src to PXO */
 	rmwreg(0x400001, MISC_CC2_REG, 0x424003);
+
+	if ((readl_relaxed(PRNG_CLK_NS_REG) & 0x7F) == 0x2B)
+		prng_clk.freq_tbl = clk_tbl_prng_64;
 }
 
 static void __init msm8660_clock_post_init(void)
@@ -3805,7 +3814,7 @@
 
 	/* Initialize rates for clocks that only support one. */
 	clk_set_rate(&pdm_clk.c, 27000000);
-	clk_set_rate(&prng_clk.c, 64000000);
+	clk_set_rate(&prng_clk.c, prng_clk.freq_tbl->freq_hz);
 	clk_set_rate(&mdp_vsync_clk.c, 27000000);
 	clk_set_rate(&tsif_ref_clk.c, 105000);
 	clk_set_rate(&tssc_clk.c, 27000000);
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 55282b6..e8e88d7 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -316,7 +316,7 @@
 				  void __iomem *cbcr_reg,
 				  enum branch_state br_status)
 {
-	char *status_str = (br_status == BRANCH_ON) ? "on" : "off";
+	char *status_str = (br_status == BRANCH_ON) ? "off" : "on";
 
 	/*
 	 * Use a memory barrier since some halt status registers are
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index bde7713..eb334b9 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -634,10 +634,14 @@
 		else
 			fs->clk_data = mdp_8660_clks;
 	} else if (pdev->id == FS_GFX3D) {
-		if (cpu_is_msm8930() || cpu_is_apq8064())
+		if (cpu_is_apq8064()) {
 			fs->clk_data = gfx3d_8064_clks;
-		else
+			fs->bus_port1 = MSM_BUS_MASTER_GRAPHICS_3D_PORT1;
+		} else if (cpu_is_msm8930()) {
+			fs->clk_data = gfx3d_8064_clks;
+		} else {
 			fs->clk_data = gfx3d_8660_clks;
+		}
 	} else if (pdev->id == FS_VED) {
 		if (cpu_is_apq8064()) {
 			fs->bus_port0 = MSM_BUS_MASTER_VIDEO_ENC;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 7857e69..90d236b 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -343,13 +343,6 @@
 	enum msm_st_frame_packing s_snap_packing;
 };
 
-struct msm_actuator_ctrl {
-	int (*a_power_up)(void *);
-	int (*a_power_down)(void *);
-	int (*a_create_subdevice)(void *, void *);
-	int (*a_config)(void __user *);
-};
-
 struct msm_strobe_flash_ctrl {
 	int (*strobe_flash_init)
 		(struct msm_camera_sensor_strobe_flash_data *);
@@ -382,6 +375,11 @@
 	const char *name;
 };
 
+struct msm_mctl_stats_t {
+	struct hlist_head pmem_stats_list;
+	spinlock_t pmem_stats_spinlock;
+};
+
 struct msm_sync {
 	/* These two queues are accessed from a process context only
 	 * They contain pmem descriptors for the preview frames and the stats
@@ -416,7 +414,6 @@
 	struct msm_camvpe_fn vpefn;
 	struct msm_sensor_ctrl sctrl;
 	struct msm_strobe_flash_ctrl sfctrl;
-	struct msm_actuator_ctrl actctrl;
 	struct wake_lock wake_lock;
 	struct platform_device *pdev;
 	int16_t ignore_qcmd_type;
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 4934c0f..2966509 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -282,6 +282,19 @@
  * @returns Pointer to subsystem name or NULL if not found
  */
 const char *smd_pid_to_subsystem(uint32_t pid);
+
+/*
+ * Checks to see if a new packet has arrived on the channel.  Only to be
+ * called with interrupts disabled.
+ *
+ * @ch: channel to check if a packet has arrived
+ *
+ * Returns:
+ *      0 - packet not available
+ *      1 - packet available
+ *      -EINVAL - NULL parameter or non-packet based channel provided
+ */
+int smd_is_pkt_avail(smd_channel_t *ch);
 #else
 
 static inline int smd_open(const char *name, smd_channel_t **ch, void *priv,
@@ -393,6 +406,11 @@
 {
 	return NULL;
 }
+
+static inline int smd_is_pkt_avail(smd_channel_t *ch)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index 6b88103..fa966d2 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -25,20 +25,14 @@
 #include <asm/hardware/gic.h>
 #include <mach/msm_smsm.h>
 
+#include "mpm-8625.h"
+
 #define NUM_REGS_ENABLE		2
 /* (NR_MSM_IRQS/32) 96 max irqs supported */
 #define NUM_REGS_DISABLE	3
 #define GIC_IRQ_MASK(irq)	BIT(irq % 32)
 #define GIC_IRQ_INDEX(irq)	(irq / 32)
 
-#ifdef CONFIG_PM
-u32 saved_spi_enable[DIV_ROUND_UP(256, 32)];
-u32 saved_spi_conf[DIV_ROUND_UP(256, 16)];
-u32 saved_spi_target[DIV_ROUND_UP(256, 4)];
-u32 __percpu *saved_ppi_enable;
-u32 __percpu *saved_ppi_conf;
-#endif
-
 enum {
 	IRQ_DEBUG_SLEEP_INT_TRIGGER	= BIT(0),
 	IRQ_DEBUG_SLEEP_INT		= BIT(1),
@@ -54,10 +48,6 @@
 static uint32_t msm_gic_irq_smsm_wake_enable[NUM_REGS_ENABLE];
 static uint32_t msm_gic_irq_idle_disable[NUM_REGS_DISABLE];
 
-static DEFINE_RAW_SPINLOCK(gic_controller_lock);
-static void __iomem *dist_base, *cpu_base;
-static unsigned int max_irqs;
-
  /*
   * Some of the interrupts which will not be considered as wake capable
   * should be marked as FAKE.
@@ -162,158 +152,17 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static void __init msm_gic_pm_init(void)
-{
-	saved_ppi_enable =  __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
-						sizeof(u32));
-	BUG_ON(!saved_ppi_enable);
-
-	saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
-						sizeof(u32));
-	BUG_ON(!saved_ppi_conf);
-}
-#endif
-
 void __init msm_gic_irq_extn_init(void __iomem *db, void __iomem *cb)
 {
-	dist_base = db;
-	cpu_base = cb;
-	max_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x11f;
-	max_irqs = (max_irqs + 1) * 32;
-
 	gic_arch_extn.irq_mask	= msm_gic_mask_irq;
 	gic_arch_extn.irq_unmask = msm_gic_unmask_irq;
 	gic_arch_extn.irq_disable = msm_gic_mask_irq;
 	gic_arch_extn.irq_set_wake = msm_gic_set_irq_wake;
-
-#ifdef CONFIG_PM
-	msm_gic_pm_init();
-#endif
-}
-
-/* GIC APIs */
-
- /*
-  * Save the GIC cpu and distributor context before PC and
-  * restor it back after coming out of PC.
-  */
-static void msm_gic_save(void)
-{
-	int i;
-	u32 *ptr;
-
-	/* Save the Per CPU PPI's */
-	ptr = __this_cpu_ptr(saved_ppi_enable);
-	/* 0 - 31 the SGI and PPI */
-	ptr[0] = readl_relaxed(dist_base +  GIC_DIST_ENABLE_SET);
-
-	ptr = __this_cpu_ptr(saved_ppi_conf);
-	for (i = 0; i < 2; i++)
-		ptr[i] =  readl_relaxed(dist_base +  GIC_DIST_CONFIG + i * 4);
-
-	/* Save the SPIs */
-	for (i = 0; (i * 16) < max_irqs; i++)
-		saved_spi_conf[i] =
-			readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
-
-	for (i = 0; (i * 4) < max_irqs; i++)
-		saved_spi_target[i] =
-			readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
-
-	for (i = 0; (i * 32) < max_irqs; i++)
-		saved_spi_enable[i] =
-		readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
-}
-
-static void msm_gic_restore(void)
-{
-	int i;
-	u32 *ptr;
-
-	/* restore CPU Interface */
-	/* Per CPU SGIs and PPIs */
-	ptr = __this_cpu_ptr(saved_ppi_enable);
-	writel_relaxed(ptr[0], dist_base + GIC_DIST_ENABLE_SET);
-
-	ptr = __this_cpu_ptr(saved_ppi_conf);
-	for (i = 0; i < 2; i++)
-		writel_relaxed(ptr[i], dist_base +  GIC_DIST_CONFIG + i * 4);
-
-	for (i = 0; (i * 4) < max_irqs; i++)
-		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
-
-	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
-	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
-
-	/* restore Distributor */
-	writel_relaxed(0, dist_base + GIC_DIST_CTRL);
-
-	for (i = 0; (i * 16) < max_irqs; i++)
-		writel_relaxed(saved_spi_conf[i],
-				dist_base + GIC_DIST_CONFIG + i * 4);
-
-	for (i = 0; (i * 4) < max_irqs; i++)
-		writel_relaxed(0xa0a0a0a0,
-				dist_base + GIC_DIST_PRI + i * 4);
-
-	for (i = 0; (i * 4) < max_irqs; i++)
-		writel_relaxed(saved_spi_target[i],
-				dist_base + GIC_DIST_TARGET + i * 4);
-
-	for (i = 0; (i * 32) < max_irqs; i++)
-		writel_relaxed(saved_spi_enable[i],
-				dist_base + GIC_DIST_ENABLE_SET + i * 4);
-
-	writel_relaxed(1, dist_base + GIC_DIST_CTRL);
-
-	mb();
 }
 
 /* Power APIs */
 
  /*
-  *  Check for any interrupts which are enabled are pending
-  *  in the pending set or not.
-  *  Return :
-  *       0 : No pending interrupts
-  *       1 : Pending interrupts other than A9_M2A_5
-  */
-unsigned int msm_gic_spi_ppi_pending(void)
-{
-	unsigned int i, bit = 0;
-	unsigned int pending_enb = 0, pending = 0;
-	unsigned long value = 0;
-
-	raw_spin_lock(&gic_controller_lock);
-	/*
-	 * PPI and SGI to be included.
-	 * MSM8625_INT_A9_M2A_5 needs to be ignored, as A9_M2A_5
-	 * requesting sleep triggers it
-	 */
-	for (i = 0; (i * 32) < max_irqs; i++) {
-		pending = readl_relaxed(dist_base +
-				GIC_DIST_PENDING_SET + i * 4);
-		pending_enb = readl_relaxed(dist_base +
-				GIC_DIST_ENABLE_SET + i * 4);
-		value = pending & pending_enb;
-
-		if (value) {
-			for (bit = 0; bit < 32; bit++) {
-				bit = find_next_bit(&value, 32, bit);
-				if ((bit + 32 * i) != MSM8625_INT_A9_M2A_5) {
-					raw_spin_unlock(&gic_controller_lock);
-					return 1;
-				}
-			}
-		}
-	}
-	raw_spin_unlock(&gic_controller_lock);
-
-	return 0;
-}
-
- /*
   * Iterate over the disable list
   */
 
@@ -352,8 +201,6 @@
   */
 int msm_gic_irq_enter_sleep2(bool modem_wake, int from_idle)
 {
-	int i;
-
 	if (from_idle && !modem_wake)
 		return 0;
 
@@ -371,14 +218,10 @@
 	}
 
 	if (modem_wake) {
-		/* save the contents of GIC CPU interface and Distributor */
-		msm_gic_save();
-		/* Disable all the Interrupts, if we enter from idle pc */
-		if (from_idle) {
-			for (i = 0; (i * 32) < max_irqs; i++)
-				writel_relaxed(0xffffffff, dist_base
-					+ GIC_DIST_ENABLE_CLEAR + i * 4);
-		}
+		/* save the contents of GIC CPU interface and Distributor
+		 * Disable all the Interrupts, if we enter from idle pc
+		 */
+		msm_gic_save(modem_wake, from_idle);
 		irq_set_irq_type(MSM8625_INT_A9_M2A_6, IRQF_TRIGGER_RISING);
 		enable_irq(MSM8625_INT_A9_M2A_6);
 		pr_debug("%s going for sleep now\n", __func__);
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 60ae4d9..5eac539 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -114,7 +114,12 @@
 	struct resource *res;
 
 	desc = pil_q6v5_init(pdev);
+	if (IS_ERR(desc))
+		return PTR_ERR(desc);
+
 	drv = platform_get_drvdata(pdev);
+	if (drv == NULL)
+		return -ENODEV;
 
 	desc->ops = &pil_lpass_ops;
 	desc->owner = THIS_MODULE;
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 23ca454..393f1bd 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -60,7 +60,6 @@
 }
 
 static DEFINE_SPINLOCK(boot_lock);
-static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
 /*
  * MP_CORE_IPC will be used to generate interrupt and can be used by either
@@ -79,51 +78,14 @@
 	mb();
 }
 
-/*
- * Configure the GIC after we come out of power collapse.
- * This function will configure some of the GIC registers so as to prepare the
- * core1 to receive an SPI(ACSR_MP_CORE_IPC1, (32 + 8)), which will bring
- * core1 out of GDFS.
- */
-static void core1_gic_configure_and_raise(void)
-{
-	unsigned int value = 0;
-
-	raw_spin_lock(&irq_controller_lock);
-
-	value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_ACTIVE_BIT + 0x4);
-	value |= BIT(8);
-	__raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_ACTIVE_BIT + 0x4);
-	mb();
-
-	value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x24);
-	value |= BIT(13);
-	__raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x24);
-	mb();
-
-	value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x28);
-	value |= BIT(1);
-	__raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x28);
-	mb();
-
-	value =  __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET + 0x4);
-	value |= BIT(8);
-	__raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET + 0x4);
-	mb();
-
-	value =  __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_PENDING_SET + 0x4);
-	value |= BIT(8);
-	__raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_PENDING_SET + 0x4);
-	mb();
-
-	raise_clear_spi(1, true);
-	raw_spin_unlock(&irq_controller_lock);
-}
-
 static void clear_pending_spi(unsigned int irq)
 {
-	/* Clear the IRQ from the ENABLE_SET */
+	struct irq_data *d = irq_get_irq_data(irq);
+	struct irq_chip *c = irq_data_get_irq_chip(d);
+
+	c->irq_mask(d);
 	local_irq_disable();
+	/* Clear the IRQ from the ENABLE_SET */
 	gic_clear_spi_pending(irq);
 	local_irq_enable();
 }
@@ -234,10 +196,12 @@
 	 * needs to be brought out by raising an SPI.
 	 */
 
-	if (power_collapsed)
+	if (power_collapsed) {
 		core1_gic_configure_and_raise();
-	else
+		raise_clear_spi(1, true);
+	} else {
 		gic_raise_softirq(cpumask_of(cpu), 1);
+	}
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 06e3d37..5382102 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -241,7 +241,7 @@
 	dload_mode_addr = MSM_IMEM_BASE + DLOAD_MODE_ADDR;
 
 	/* Reset detection is switched on below.*/
-	set_dload_mode(1);
+	set_dload_mode(download_mode);
 #endif
 	msm_tmr0_base = msm_timer_get_timer0_base();
 	restart_reason = MSM_IMEM_BASE + RESTART_REASON_ADDR;
diff --git a/arch/arm/mach-msm/rpc_server_handset.c b/arch/arm/mach-msm/rpc_server_handset.c
index b011aeb..6d173fb 100644
--- a/arch/arm/mach-msm/rpc_server_handset.c
+++ b/arch/arm/mach-msm/rpc_server_handset.c
@@ -1,6 +1,6 @@
 /* arch/arm/mach-msm/rpc_server_handset.c
  *
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2010,2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -517,7 +517,7 @@
 	return 0;
 }
 
-static int __init hs_rpc_cb_init(void)
+static int __devinit hs_rpc_cb_init(void)
 {
 	int rc = 0, i, num_vers;
 
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 6b42325..dac0a37 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -2207,6 +2207,20 @@
 }
 EXPORT_SYMBOL(smd_tiocmset);
 
+int smd_is_pkt_avail(smd_channel_t *ch)
+{
+	if (!ch || !ch->is_pkt_ch)
+		return -EINVAL;
+
+	if (ch->current_packet)
+		return 1;
+
+	update_packet_state(ch);
+
+	return ch->current_packet ? 1 : 0;
+}
+EXPORT_SYMBOL(smd_is_pkt_avail);
+
 
 /* -------------------------------------------------------------------------- */
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 8328ee2..cf024cf 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -485,4 +485,12 @@
 	help
 	  Say 'y' here to include support for the Qualcomm QPNP gpio
 	  support. QPNP is a SPMI based PMIC implementation.
+
+config GPIO_QPNP_DEBUG
+	depends on GPIO_QPNP
+	depends on DEBUG_FS
+	bool "Qualcomm QPNP GPIO debug support"
+	help
+	  Say 'y' here to include debug support for the Qualcomm
+	  QPNP gpio support
 endif
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
index 90cc798..bc0904ec 100644
--- a/drivers/gpio/qpnp-gpio.c
+++ b/drivers/gpio/qpnp-gpio.c
@@ -10,10 +10,13 @@
  * GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/spmi.h>
 #include <linux/platform_device.h>
+#include <linux/debugfs.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -27,49 +30,97 @@
 		((q_spec)->offset + reg_index)
 
 #define Q_REG_STATUS1			0x8
-#define Q_NUM_CTL_REGS			5
+#define Q_NUM_CTL_REGS			7
+
+/* type registers base address offsets */
+#define Q_REG_TYPE			0x10
+#define Q_REG_SUBTYPE			0x11
+
+/* gpio peripheral type and subtype values */
+#define Q_GPIO_TYPE			0x10
+#define Q_GPIO_SUBTYPE_GPIO_4CH		0x1
+#define Q_GPIO_SUBTYPE_GPIOC_4CH	0x5
+#define Q_GPIO_SUBTYPE_GPIO_8CH		0x9
+#define Q_GPIO_SUBTYPE_GPIOC_8CH	0xD
 
 /* control register base address offsets */
-#define Q_REG_IO_CTL1			0x42
-#define Q_REG_INPUT_CTL1		0x43
-#define Q_REG_OUTPUT_CTL1		0x44
-#define Q_REG_OUTPUT_CTL2		0x45
-#define Q_REG_EN_CTL1			0x46
+#define Q_REG_MODE_CTL			0x40
+#define Q_REG_DIG_PULL_CTL		0x42
+#define Q_REG_DIG_IN_CTL		0x43
+#define Q_REG_DIG_VIN_CTL		0x44
+#define Q_REG_DIG_OUT_CTL		0x45
+#define Q_REG_EN_CTL			0x46
 
 /* control register regs array indices */
-#define Q_REG_I_IO_CTL1			0
-#define Q_REG_I_INPUT_CTL1		1
-#define Q_REG_I_OUTPUT_CTL1		2
-#define Q_REG_I_OUTPUT_CTL2		3
-#define Q_REG_I_EN_CTL1			4
+#define Q_REG_I_MODE_CTL		0
+#define Q_REG_I_DIG_PULL_CTL		2
+#define Q_REG_I_DIG_IN_CTL		3
+#define Q_REG_I_DIG_VIN_CTL		4
+#define Q_REG_I_DIG_OUT_CTL		5
+#define Q_REG_I_EN_CTL			6
 
-/* control register configuration */
-#define Q_REG_VIN_SHIFT			0
-#define Q_REG_VIN_MASK			0x7
-#define Q_REG_PULL_SHIFT		4
-#define Q_REG_PULL_MASK			0x70
-#define Q_REG_INPUT_EN_SHIFT		7
-#define Q_REG_INPUT_EN_MASK		0x80
-#define Q_REG_OUT_STRENGTH_SHIFT	0
-#define Q_REG_OUT_STRENGTH_MASK		0x3
-#define Q_REG_OUT_TYPE_SHIFT		6
-#define Q_REG_OUT_TYPE_MASK		0x40
+/* control reg: mode */
 #define Q_REG_OUT_INVERT_SHIFT		0
 #define Q_REG_OUT_INVERT_MASK		0x1
 #define Q_REG_SRC_SEL_SHIFT		1
 #define Q_REG_SRC_SEL_MASK		0xE
-#define Q_REG_OUTPUT_EN_SHIFT		7
-#define Q_REG_OUTPUT_EN_MASK		0x80
+#define Q_REG_MODE_SEL_SHIFT		4
+#define Q_REG_MODE_SEL_MASK		0x70
+
+/* control reg: dig_vin */
+#define Q_REG_VIN_SHIFT			0
+#define Q_REG_VIN_MASK			0x7
+
+/* control reg: dig_pull */
+#define Q_REG_PULL_SHIFT		0
+#define Q_REG_PULL_MASK			0x7
+
+/* control reg: dig_out */
+#define Q_REG_OUT_STRENGTH_SHIFT	0
+#define Q_REG_OUT_STRENGTH_MASK		0x3
+#define Q_REG_OUT_TYPE_SHIFT		4
+#define Q_REG_OUT_TYPE_MASK		0x30
+
+/* control reg: en */
 #define Q_REG_MASTER_EN_SHIFT		7
 #define Q_REG_MASTER_EN_MASK		0x80
 
+enum qpnp_gpio_param_type {
+	Q_GPIO_CFG_DIRECTION,
+	Q_GPIO_CFG_OUTPUT_TYPE,
+	Q_GPIO_CFG_INVERT,
+	Q_GPIO_CFG_PULL,
+	Q_GPIO_CFG_VIN_SEL,
+	Q_GPIO_CFG_OUT_STRENGTH,
+	Q_GPIO_CFG_SRC_SELECT,
+	Q_GPIO_CFG_MASTER_EN,
+	Q_GPIO_CFG_INVALID,
+};
+
+#define Q_NUM_PARAMS			Q_GPIO_CFG_INVALID
+
+/* param error checking */
+#define QPNP_GPIO_DIR_INVALID		3
+#define QPNP_GPIO_INVERT_INVALID	2
+#define QPNP_GPIO_OUT_BUF_INVALID	3
+#define QPNP_GPIO_VIN_INVALID		8
+#define QPNP_GPIO_PULL_INVALID		6
+#define QPNP_GPIO_OUT_STRENGTH_INVALID	4
+#define QPNP_GPIO_SRC_INVALID		8
+#define QPNP_GPIO_MASTER_INVALID	2
 
 struct qpnp_gpio_spec {
 	uint8_t slave;			/* 0-15 */
 	uint16_t offset;		/* 0-255 */
 	uint32_t gpio_chip_idx;		/* offset from gpio_chip base */
+	uint32_t pmic_gpio;		/* PMIC gpio number */
 	int irq;			/* logical IRQ number */
 	u8 regs[Q_NUM_CTL_REGS];	/* Control regs */
+	u8 type;			/* peripheral type */
+	u8 subtype;			/* peripheral subtype */
+	struct device_node *node;
+	enum qpnp_gpio_param_type params[Q_NUM_PARAMS];
+	struct qpnp_gpio_chip *q_chip;
 };
 
 struct qpnp_gpio_chip {
@@ -81,6 +132,7 @@
 	uint32_t		pmic_gpio_highest;
 	struct device_node	*int_ctrl;
 	struct list_head	chip_list;
+	struct dentry		*dfs_dir;
 };
 
 static LIST_HEAD(qpnp_gpio_chips);
@@ -121,6 +173,131 @@
 	q_chip->chip_gpios[chip_gpio] = spec;
 }
 
+static int qpnp_gpio_check_config(struct qpnp_gpio_spec *q_spec,
+				  struct qpnp_gpio_cfg *param)
+{
+	int gpio = q_spec->pmic_gpio;
+
+	if (param->direction >= QPNP_GPIO_DIR_INVALID)
+		pr_err("invalid direction for gpio %d\n", gpio);
+	else if (param->invert >= QPNP_GPIO_INVERT_INVALID)
+		pr_err("invalid invert polarity for gpio %d\n", gpio);
+	else if (param->src_select >= QPNP_GPIO_SRC_INVALID)
+		pr_err("invalid source select for gpio %d\n", gpio);
+	else if (param->out_strength >= QPNP_GPIO_OUT_STRENGTH_INVALID ||
+		 param->out_strength == 0)
+		pr_err("invalid out strength for gpio %d\n", gpio);
+	else if (param->output_type >= QPNP_GPIO_OUT_BUF_INVALID)
+		pr_err("invalid out type for gpio %d\n", gpio);
+	else if ((param->output_type == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS ||
+		 param->output_type == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS) &&
+		 (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
+		 (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_8CH)))
+		pr_err("invalid out type for gpio %d\n"
+		       "gpioc does not support open-drain\n", gpio);
+	else if (param->vin_sel >= QPNP_GPIO_VIN_INVALID)
+		pr_err("invalid vin select value for gpio %d\n", gpio);
+	else if (param->pull >= QPNP_GPIO_PULL_INVALID)
+		pr_err("invalid pull value for gpio %d\n", gpio);
+	else if (param->master_en >= QPNP_GPIO_MASTER_INVALID)
+		pr_err("invalid master_en value for gpio %d\n", gpio);
+	else
+		return 0;
+
+	return -EINVAL;
+}
+
+static inline u8 q_reg_get(u8 *reg, int shift, int mask)
+{
+	return (*reg & mask) >> shift;
+}
+
+static inline void q_reg_set(u8 *reg, int shift, int mask, int value)
+{
+	*reg |= (value << shift) & mask;
+}
+
+static inline void q_reg_clr_set(u8 *reg, int shift, int mask, int value)
+{
+	*reg &= ~mask;
+	*reg |= (value << shift) & mask;
+}
+
+static int qpnp_gpio_cache_regs(struct qpnp_gpio_chip *q_chip,
+				struct qpnp_gpio_spec *q_spec)
+{
+	int rc;
+	struct device *dev = &q_chip->spmi->dev;
+
+	rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
+				     Q_REG_ADDR(q_spec, Q_REG_MODE_CTL),
+				     &q_spec->regs[Q_REG_I_MODE_CTL],
+				     Q_NUM_CTL_REGS);
+	if (rc)
+		dev_err(dev, "%s: unable to read control regs\n", __func__);
+
+	return rc;
+}
+
+static int _qpnp_gpio_config(struct qpnp_gpio_chip *q_chip,
+			     struct qpnp_gpio_spec *q_spec,
+			     struct qpnp_gpio_cfg *param)
+{
+	struct device *dev = &q_chip->spmi->dev;
+	int rc;
+
+	rc = qpnp_gpio_check_config(q_spec, param);
+	if (rc)
+		goto gpio_cfg;
+
+	/* set direction */
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+			  Q_REG_MODE_SEL_SHIFT, Q_REG_MODE_SEL_MASK,
+			  param->direction);
+
+	/* output specific configuration */
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+			  Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK,
+			  param->invert);
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+			  Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK,
+			  param->src_select);
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
+			  Q_REG_OUT_STRENGTH_SHIFT, Q_REG_OUT_STRENGTH_MASK,
+			  param->out_strength);
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
+			  Q_REG_OUT_TYPE_SHIFT, Q_REG_OUT_TYPE_MASK,
+			  param->output_type);
+
+	/* config applicable for both input / output */
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_VIN_CTL],
+			  Q_REG_VIN_SHIFT, Q_REG_VIN_MASK,
+			  param->vin_sel);
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_PULL_CTL],
+			  Q_REG_PULL_SHIFT, Q_REG_PULL_MASK,
+			  param->pull);
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_EN_CTL],
+			  Q_REG_MASTER_EN_SHIFT, Q_REG_MASTER_EN_MASK,
+			  param->master_en);
+
+	rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
+			      Q_REG_ADDR(q_spec, Q_REG_MODE_CTL),
+			      &q_spec->regs[Q_REG_I_MODE_CTL], Q_NUM_CTL_REGS);
+	if (rc) {
+		dev_err(&q_chip->spmi->dev, "%s: unable to write master"
+						" enable\n", __func__);
+		goto gpio_cfg;
+	}
+
+	return 0;
+
+gpio_cfg:
+	dev_err(dev, "%s: unable to set default config for"
+		     " pmic gpio %d\n", __func__, q_spec->pmic_gpio);
+
+	return rc;
+}
+
 int qpnp_gpio_config(int gpio, struct qpnp_gpio_cfg *param)
 {
 	int rc, chip_offset;
@@ -146,47 +323,8 @@
 		}
 	}
 	mutex_unlock(&qpnp_gpio_chips_lock);
-	if (!q_spec) {
-		pr_err("gpio %d not handled by any pmic\n", gpio);
-		return -EINVAL;
-	}
 
-	q_spec->regs[Q_REG_I_IO_CTL1] = (param->vin_sel <<
-					Q_REG_VIN_SHIFT) & Q_REG_VIN_MASK;
-	q_spec->regs[Q_REG_I_IO_CTL1] |= (param->pull <<
-					Q_REG_PULL_SHIFT) & Q_REG_PULL_MASK;
-	q_spec->regs[Q_REG_I_INPUT_CTL1] = ((param->direction &
-			QPNP_GPIO_DIR_IN) ? ((1 << Q_REG_INPUT_EN_SHIFT)) : 0);
-
-	if (param->direction & QPNP_GPIO_DIR_OUT) {
-		q_spec->regs[Q_REG_I_OUTPUT_CTL1] = (param->out_strength
-			 << Q_REG_OUT_STRENGTH_SHIFT) & Q_REG_OUT_STRENGTH_MASK;
-		q_spec->regs[Q_REG_I_OUTPUT_CTL1] |= (param->output_type
-			 << Q_REG_OUT_TYPE_SHIFT) & Q_REG_OUT_TYPE_MASK;
-	} else {
-		q_spec->regs[Q_REG_I_OUTPUT_CTL1] = 0;
-	}
-
-	if (param->direction & QPNP_GPIO_DIR_OUT) {
-		q_spec->regs[Q_REG_I_OUTPUT_CTL2] = (param->output_value
-			    << Q_REG_OUT_INVERT_SHIFT) & Q_REG_OUT_INVERT_MASK;
-		q_spec->regs[Q_REG_I_OUTPUT_CTL2] |= (param->src_select
-			    << Q_REG_SRC_SEL_SHIFT) & Q_REG_SRC_SEL_MASK;
-		q_spec->regs[Q_REG_I_OUTPUT_CTL2] |= (1 <<
-			      Q_REG_OUTPUT_EN_SHIFT) & Q_REG_OUTPUT_EN_MASK;
-	} else {
-		q_spec->regs[Q_REG_I_OUTPUT_CTL2] = 0;
-	}
-
-	q_spec->regs[Q_REG_I_EN_CTL1] = (param->master_en <<
-				Q_REG_MASTER_EN_SHIFT) & Q_REG_MASTER_EN_MASK;
-
-	rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
-			      Q_REG_ADDR(q_spec, Q_REG_IO_CTL1),
-			      &q_spec->regs[Q_REG_I_IO_CTL1], Q_NUM_CTL_REGS);
-	if (rc)
-		dev_err(&q_chip->spmi->dev, "%s: unable to write master"
-						" enable\n", __func__);
+	rc = _qpnp_gpio_config(q_chip, q_spec, param);
 
 	return rc;
 }
@@ -242,7 +380,8 @@
 		return -ENODEV;
 
 	/* gpio val is from RT status iff input is enabled */
-	if (q_spec->regs[Q_REG_I_INPUT_CTL1] & Q_REG_INPUT_EN_MASK) {
+	if ((q_spec->regs[Q_REG_I_MODE_CTL] & Q_REG_MODE_SEL_MASK)
+						== QPNP_GPIO_DIR_IN) {
 		/* INT_RT_STS */
 		rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
 				Q_REG_ADDR(q_spec, Q_REG_STATUS1),
@@ -250,7 +389,7 @@
 		return buf[0];
 
 	} else {
-		ret_val = (q_spec->regs[Q_REG_I_OUTPUT_CTL2] &
+		ret_val = (q_spec->regs[Q_REG_I_MODE_CTL] &
 			       Q_REG_OUT_INVERT_MASK) >> Q_REG_OUT_INVERT_SHIFT;
 		return ret_val;
 	}
@@ -266,15 +405,16 @@
 	if (!q_chip || !q_spec)
 		return -EINVAL;
 
-	q_spec->regs[Q_REG_I_OUTPUT_CTL2] &= ~(1 << Q_REG_OUT_INVERT_SHIFT);
-
 	if (value)
-		q_spec->regs[Q_REG_I_OUTPUT_CTL2] |=
-					    (1 << Q_REG_OUT_INVERT_SHIFT);
+		q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+			  Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK, 1);
+	else
+		q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+			  Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK, 0);
 
 	rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
-			      Q_REG_ADDR(q_spec, Q_REG_OUTPUT_CTL2),
-			      &q_spec->regs[Q_REG_I_OUTPUT_CTL2], 1);
+			      Q_REG_ADDR(q_spec, Q_REG_I_MODE_CTL),
+			      &q_spec->regs[Q_REG_I_MODE_CTL], 1);
 	if (rc)
 		dev_err(&q_chip->spmi->dev, "%s: spmi write failed\n",
 								__func__);
@@ -306,21 +446,19 @@
 	if (!q_chip || !q_spec)
 		return -EINVAL;
 
-	if (direction & QPNP_GPIO_DIR_IN) {
-		q_spec->regs[Q_REG_I_INPUT_CTL1] |=
-					(1 << Q_REG_INPUT_EN_SHIFT);
-		q_spec->regs[Q_REG_I_OUTPUT_CTL2] &=
-					~(1 << Q_REG_OUTPUT_EN_SHIFT);
-	} else {
-		q_spec->regs[Q_REG_I_INPUT_CTL1] &=
-					~(1 << Q_REG_INPUT_EN_SHIFT);
-		q_spec->regs[Q_REG_I_OUTPUT_CTL2] |=
-					(1 << Q_REG_OUTPUT_EN_SHIFT);
+	if (direction >= QPNP_GPIO_DIR_INVALID) {
+		pr_err("invalid direction specification %d\n", direction);
+		return -EINVAL;
 	}
 
+	q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+			Q_REG_MODE_SEL_SHIFT,
+			Q_REG_MODE_SEL_MASK,
+			direction);
+
 	rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
-			      Q_REG_ADDR(q_spec, Q_REG_INPUT_CTL1),
-			      &q_spec->regs[Q_REG_I_INPUT_CTL1], 3);
+			      Q_REG_ADDR(q_spec, Q_REG_I_MODE_CTL),
+			      &q_spec->regs[Q_REG_I_MODE_CTL], 1);
 	return rc;
 }
 
@@ -374,14 +512,13 @@
 	u32 n = be32_to_cpup(gpio);
 
 	if (WARN_ON(gpio_chip->of_gpio_n_cells < 2)) {
-		pr_err("%s: of_gpio_n_cells < 2\n", __func__);
+		pr_err("of_gpio_n_cells < 2\n");
 		return -EINVAL;
 	}
 
 	q_spec = qpnp_pmic_gpio_get_spec(q_chip, n);
 	if (!q_spec) {
-		pr_err("%s: no such PMIC gpio %u in device topology\n",
-							__func__, n);
+		pr_err("no such PMIC gpio %u in device topology\n", n);
 		return -EINVAL;
 	}
 
@@ -391,32 +528,54 @@
 	return q_spec->gpio_chip_idx;
 }
 
-static int qpnp_gpio_config_default(struct spmi_device *spmi,
-					const __be32 *prop, int gpio)
+static int qpnp_gpio_apply_config(struct qpnp_gpio_chip *q_chip,
+				  struct qpnp_gpio_spec *q_spec)
 {
 	struct qpnp_gpio_cfg param;
+	struct device_node *node = q_spec->node;
 	int rc;
 
-	dev_dbg(&spmi->dev, "%s: p[0]: 0x%x p[1]: 0x%x p[2]: 0x%x p[3]:"
-		" 0x%x p[4]: 0x%x p[5]: 0x%x p[6]: 0x%x p[7]: 0x%x\n", __func__,
-		be32_to_cpup(&prop[0]), be32_to_cpup(&prop[1]),
-		be32_to_cpup(&prop[2]), be32_to_cpup(&prop[3]),
-		be32_to_cpup(&prop[4]), be32_to_cpup(&prop[5]),
-		be32_to_cpup(&prop[6]), be32_to_cpup(&prop[7]));
+	param.direction    = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+				       Q_REG_MODE_SEL_SHIFT,
+				       Q_REG_MODE_SEL_MASK);
+	param.output_type  = q_reg_get(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
+				       Q_REG_OUT_TYPE_SHIFT,
+				       Q_REG_OUT_TYPE_MASK);
+	param.invert	   = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+				       Q_REG_OUT_INVERT_MASK,
+				       Q_REG_OUT_INVERT_MASK);
+	param.pull	   = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+				       Q_REG_PULL_SHIFT, Q_REG_PULL_MASK);
+	param.vin_sel	   = q_reg_get(&q_spec->regs[Q_REG_I_DIG_VIN_CTL],
+				       Q_REG_VIN_SHIFT, Q_REG_VIN_MASK);
+	param.out_strength = q_reg_get(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
+				       Q_REG_OUT_STRENGTH_SHIFT,
+				       Q_REG_OUT_STRENGTH_MASK);
+	param.src_select   = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+				       Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK);
+	param.master_en    = q_reg_get(&q_spec->regs[Q_REG_I_EN_CTL],
+				       Q_REG_MASTER_EN_SHIFT,
+				       Q_REG_MASTER_EN_MASK);
 
-	param.direction    =	be32_to_cpup(&prop[0]);
-	param.output_type  =	be32_to_cpup(&prop[1]);
-	param.output_value =	be32_to_cpup(&prop[2]);
-	param.pull	   =	be32_to_cpup(&prop[3]);
-	param.vin_sel	   =	be32_to_cpup(&prop[4]);
-	param.out_strength =	be32_to_cpup(&prop[5]);
-	param.src_select   =	be32_to_cpup(&prop[6]);
-	param.master_en    =	be32_to_cpup(&prop[7]);
+	of_property_read_u32(node, "qcom,direction",
+		&param.direction);
+	of_property_read_u32(node, "qcom,output-type",
+		&param.output_type);
+	of_property_read_u32(node, "qcom,invert",
+		&param.invert);
+	of_property_read_u32(node, "qcom,pull",
+		&param.pull);
+	of_property_read_u32(node, "qcom,vin-sel",
+		&param.vin_sel);
+	of_property_read_u32(node, "qcom,out-strength",
+		&param.out_strength);
+	of_property_read_u32(node, "qcom,src-select",
+		&param.src_select);
+	rc = of_property_read_u32(node, "qcom,master-en",
+		&param.master_en);
 
-	rc = qpnp_gpio_config(gpio, &param);
-	if (rc)
-		dev_err(&spmi->dev, "%s: unable to set default config for"
-				" gpio %d\n", __func__, gpio);
+	rc = _qpnp_gpio_config(q_chip, q_spec, &param);
+
 	return rc;
 }
 
@@ -442,15 +601,255 @@
 	return rc;
 }
 
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+struct qpnp_gpio_reg {
+	uint32_t addr;
+	uint32_t idx;
+	uint32_t shift;
+	uint32_t mask;
+};
+
+static struct dentry *driver_dfs_dir;
+
+static int qpnp_gpio_reg_attr(enum qpnp_gpio_param_type type,
+			     struct qpnp_gpio_reg *cfg)
+{
+	switch (type) {
+	case Q_GPIO_CFG_DIRECTION:
+		cfg->addr = Q_REG_MODE_CTL;
+		cfg->idx = Q_REG_I_MODE_CTL;
+		cfg->shift = Q_REG_MODE_SEL_SHIFT;
+		cfg->mask = Q_REG_MODE_SEL_MASK;
+		break;
+	case Q_GPIO_CFG_OUTPUT_TYPE:
+		cfg->addr = Q_REG_DIG_OUT_CTL;
+		cfg->idx = Q_REG_I_DIG_OUT_CTL;
+		cfg->shift = Q_REG_OUT_TYPE_SHIFT;
+		cfg->mask = Q_REG_OUT_TYPE_MASK;
+		break;
+	case Q_GPIO_CFG_INVERT:
+		cfg->addr = Q_REG_MODE_CTL;
+		cfg->idx = Q_REG_I_MODE_CTL;
+		cfg->shift = Q_REG_OUT_INVERT_SHIFT;
+		cfg->mask = Q_REG_OUT_INVERT_MASK;
+		break;
+	case Q_GPIO_CFG_PULL:
+		cfg->addr = Q_REG_DIG_PULL_CTL;
+		cfg->idx = Q_REG_I_DIG_PULL_CTL;
+		cfg->shift = Q_REG_PULL_SHIFT;
+		cfg->mask = Q_REG_PULL_MASK;
+		break;
+	case Q_GPIO_CFG_VIN_SEL:
+		cfg->addr = Q_REG_DIG_VIN_CTL;
+		cfg->idx = Q_REG_I_DIG_VIN_CTL;
+		cfg->shift = Q_REG_VIN_SHIFT;
+		cfg->mask = Q_REG_VIN_MASK;
+		break;
+	case Q_GPIO_CFG_OUT_STRENGTH:
+		cfg->addr = Q_REG_DIG_OUT_CTL;
+		cfg->idx = Q_REG_I_DIG_OUT_CTL;
+		cfg->shift = Q_REG_OUT_STRENGTH_SHIFT;
+		cfg->mask = Q_REG_OUT_STRENGTH_MASK;
+		break;
+	case Q_GPIO_CFG_SRC_SELECT:
+		cfg->addr = Q_REG_MODE_CTL;
+		cfg->idx = Q_REG_I_MODE_CTL;
+		cfg->shift = Q_REG_SRC_SEL_SHIFT;
+		cfg->mask = Q_REG_SRC_SEL_MASK;
+		break;
+	case Q_GPIO_CFG_MASTER_EN:
+		cfg->addr = Q_REG_EN_CTL;
+		cfg->idx = Q_REG_I_EN_CTL;
+		cfg->shift = Q_REG_MASTER_EN_SHIFT;
+		cfg->mask = Q_REG_MASTER_EN_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int qpnp_gpio_debugfs_get(void *data, u64 *val)
+{
+	enum qpnp_gpio_param_type *idx = data;
+	struct qpnp_gpio_spec *q_spec;
+	struct qpnp_gpio_reg cfg = {};
+	int rc;
+
+	rc = qpnp_gpio_reg_attr(*idx, &cfg);
+	if (rc)
+		return rc;
+	q_spec = container_of(idx, struct qpnp_gpio_spec, params[*idx]);
+	*val = q_reg_get(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask);
+	return 0;
+}
+
+static int qpnp_gpio_check_reg_val(enum qpnp_gpio_param_type idx,
+				   struct qpnp_gpio_spec *q_spec,
+				   uint32_t val)
+{
+	switch (idx) {
+	case Q_GPIO_CFG_DIRECTION:
+		if (val >= QPNP_GPIO_DIR_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_OUTPUT_TYPE:
+		if ((val >= QPNP_GPIO_OUT_BUF_INVALID) ||
+		   ((val == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS ||
+		   val == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS) &&
+		   (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
+		   (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_8CH))))
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_INVERT:
+		if (val >= QPNP_GPIO_INVERT_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_PULL:
+		if (val >= QPNP_GPIO_PULL_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_VIN_SEL:
+		if (val >= QPNP_GPIO_VIN_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_OUT_STRENGTH:
+		if (val >= QPNP_GPIO_OUT_STRENGTH_INVALID ||
+		    val == 0)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_SRC_SELECT:
+		if (val >= QPNP_GPIO_SRC_INVALID)
+			return -EINVAL;
+		break;
+	case Q_GPIO_CFG_MASTER_EN:
+		if (val >= QPNP_GPIO_MASTER_INVALID)
+			return -EINVAL;
+		break;
+	default:
+		pr_err("invalid param type %u specified\n", idx);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int qpnp_gpio_debugfs_set(void *data, u64 val)
+{
+	enum qpnp_gpio_param_type *idx = data;
+	struct qpnp_gpio_spec *q_spec;
+	struct qpnp_gpio_chip *q_chip;
+	struct qpnp_gpio_reg cfg = {};
+	int rc;
+
+	q_spec = container_of(idx, struct qpnp_gpio_spec, params[*idx]);
+	q_chip = q_spec->q_chip;
+
+	rc = qpnp_gpio_check_reg_val(*idx, q_spec, val);
+	if (rc)
+		return rc;
+
+	rc = qpnp_gpio_reg_attr(*idx, &cfg);
+	if (rc)
+		return rc;
+	q_reg_clr_set(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask, val);
+	rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
+				      Q_REG_ADDR(q_spec, cfg.addr),
+				      &q_spec->regs[cfg.idx], 1);
+
+	return rc;
+}
+DEFINE_SIMPLE_ATTRIBUTE(qpnp_gpio_fops, qpnp_gpio_debugfs_get,
+			qpnp_gpio_debugfs_set, "%llu\n");
+
+#define DEBUGFS_BUF_SIZE 11 /* supports 2^32 in decimal */
+
+struct qpnp_gpio_debugfs_args {
+	enum qpnp_gpio_param_type type;
+	const char *filename;
+};
+
+static struct qpnp_gpio_debugfs_args dfs_args[] = {
+	{ Q_GPIO_CFG_DIRECTION, "direction" },
+	{ Q_GPIO_CFG_OUTPUT_TYPE, "output_type" },
+	{ Q_GPIO_CFG_INVERT, "invert" },
+	{ Q_GPIO_CFG_PULL, "pull" },
+	{ Q_GPIO_CFG_VIN_SEL, "vin_sel" },
+	{ Q_GPIO_CFG_OUT_STRENGTH, "out_strength" },
+	{ Q_GPIO_CFG_SRC_SELECT, "src_select" },
+	{ Q_GPIO_CFG_MASTER_EN, "master_en" }
+};
+
+static int qpnp_gpio_debugfs_create(struct qpnp_gpio_chip *q_chip)
+{
+	struct spmi_device *spmi = q_chip->spmi;
+	struct device *dev = &spmi->dev;
+	struct qpnp_gpio_spec *q_spec;
+	enum qpnp_gpio_param_type *params;
+	enum qpnp_gpio_param_type type;
+	char pmic_gpio[DEBUGFS_BUF_SIZE];
+	const char *filename;
+	struct dentry *dfs, *dfs_io_dir;
+	int i, j;
+
+	BUG_ON(Q_NUM_PARAMS != ARRAY_SIZE(dfs_args));
+
+	q_chip->dfs_dir = debugfs_create_dir(dev->of_node->name,
+							driver_dfs_dir);
+	if (q_chip->dfs_dir == NULL) {
+		dev_err(dev, "%s: cannot register chip debugfs directory %s\n",
+						__func__, dev->of_node->name);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < spmi->num_dev_node; i++) {
+		q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
+		params = q_spec->params;
+		snprintf(pmic_gpio, DEBUGFS_BUF_SIZE, "%u", q_spec->pmic_gpio);
+		dfs_io_dir = debugfs_create_dir(pmic_gpio,
+							q_chip->dfs_dir);
+		if (dfs_io_dir == NULL)
+			goto dfs_err;
+
+		for (j = 0; j < Q_NUM_PARAMS; j++) {
+			type = dfs_args[j].type;
+			filename = dfs_args[j].filename;
+
+			params[type] = type;
+			dfs = debugfs_create_file(
+					filename,
+					S_IRUGO | S_IWUSR,
+					dfs_io_dir,
+					&q_spec->params[type],
+					&qpnp_gpio_fops);
+			if (dfs == NULL)
+				goto dfs_err;
+		}
+	}
+	return 0;
+dfs_err:
+	dev_err(dev, "%s: cannot register debugfs for pmic gpio %u on"
+				     " chip %s\n", __func__,
+				     q_spec->pmic_gpio, dev->of_node->name);
+	debugfs_remove_recursive(q_chip->dfs_dir);
+	return -ENFILE;
+}
+#else
+static int qpnp_gpio_debugfs_create(struct qpnp_gpio_chip *q_chip)
+{
+	return 0;
+}
+#endif
+
 static int qpnp_gpio_probe(struct spmi_device *spmi)
 {
 	struct qpnp_gpio_chip *q_chip;
 	struct resource *res;
 	struct qpnp_gpio_spec *q_spec;
-	const __be32 *prop;
-	int i, rc, ret, gpio, len;
-	int lowest_gpio = INT_MAX, highest_gpio = INT_MIN;
-	u32 intspec[3];
+	int i, rc;
+	int lowest_gpio = UINT_MAX, highest_gpio = 0;
+	u32 intspec[3], gpio;
+	char buf[2];
 
 	q_chip = kzalloc(sizeof(*q_chip), GFP_KERNEL);
 	if (!q_chip) {
@@ -467,21 +866,14 @@
 
 	/* first scan through nodes to find the range required for allocation */
 	for (i = 0; i < spmi->num_dev_node; i++) {
-		prop = of_get_property(spmi->dev_node[i].of_node,
-						"qcom,qpnp-gpio-num", &len);
-		if (!prop) {
+		rc = of_property_read_u32(spmi->dev_node[i].of_node,
+							"qcom,gpio-num", &gpio);
+		if (rc) {
 			dev_err(&spmi->dev, "%s: unable to get"
-				" qcom,qpnp-gpio-num property\n", __func__);
-			ret = -EINVAL;
-			goto err_probe;
-		} else if (len != sizeof(__be32)) {
-			dev_err(&spmi->dev, "%s: Invalid qcom,qpnp-gpio-num"
-				" property\n", __func__);
-			ret = -EINVAL;
+				" qcom,gpio-num property\n", __func__);
 			goto err_probe;
 		}
 
-		gpio = be32_to_cpup(prop);
 		if (gpio < lowest_gpio)
 			lowest_gpio = gpio;
 		if (gpio > highest_gpio)
@@ -491,12 +883,12 @@
 	if (highest_gpio < lowest_gpio) {
 		dev_err(&spmi->dev, "%s: no device nodes specified in"
 					" topology\n", __func__);
-		ret = -EINVAL;
+		rc = -EINVAL;
 		goto err_probe;
 	} else if (lowest_gpio == 0) {
 		dev_err(&spmi->dev, "%s: 0 is not a valid PMIC GPIO\n",
 								__func__);
-		ret = -EINVAL;
+		rc = -EINVAL;
 		goto err_probe;
 	}
 
@@ -512,7 +904,7 @@
 	if (!q_chip->pmic_gpios || !q_chip->chip_gpios) {
 		dev_err(&spmi->dev, "%s: unable to allocate memory\n",
 								__func__);
-		ret = -ENOMEM;
+		rc = -ENOMEM;
 		goto err_probe;
 	}
 
@@ -521,7 +913,7 @@
 	if (!q_chip->int_ctrl) {
 		dev_err(&spmi->dev, "%s: Can't find interrupt parent\n",
 								__func__);
-		ret = -EINVAL;
+		rc = -EINVAL;
 		goto err_probe;
 	}
 
@@ -534,20 +926,13 @@
 				__func__, spmi->dev_node[i].of_node->full_name);
 		}
 
-		prop = of_get_property(spmi->dev_node[i].of_node,
-				"qcom,qpnp-gpio-num", &len);
-		if (!prop) {
+		rc = of_property_read_u32(spmi->dev_node[i].of_node,
+							"qcom,gpio-num", &gpio);
+		if (rc) {
 			dev_err(&spmi->dev, "%s: unable to get"
-				" qcom,qpnp-gpio-num property\n", __func__);
-			ret = -EINVAL;
-			goto err_probe;
-		} else if (len != sizeof(__be32)) {
-			dev_err(&spmi->dev, "%s: Invalid qcom,qpnp-gpio-num"
-				" property\n", __func__);
-			ret = -EINVAL;
+				" qcom,gpio-num property\n", __func__);
 			goto err_probe;
 		}
-		gpio = be32_to_cpup(prop);
 
 		q_spec = kzalloc(sizeof(struct qpnp_gpio_spec),
 							GFP_KERNEL);
@@ -555,13 +940,26 @@
 			dev_err(&spmi->dev, "%s: unable to allocate"
 						" memory\n",
 					__func__);
-			ret = -ENOMEM;
+			rc = -ENOMEM;
 			goto err_probe;
 		}
 
 		q_spec->slave = spmi->sid;
 		q_spec->offset = res->start;
 		q_spec->gpio_chip_idx = i;
+		q_spec->pmic_gpio = gpio;
+		q_spec->node = spmi->dev_node[i].of_node;
+		q_spec->q_chip = q_chip;
+
+		rc = spmi_ext_register_readl(spmi->ctrl, q_spec->slave,
+				Q_REG_ADDR(q_spec, Q_REG_TYPE), &buf[0], 2);
+		if (rc) {
+			dev_err(&spmi->dev, "%s: unable to read type regs\n",
+						__func__);
+			goto err_probe;
+		}
+		q_spec->type	= buf[0];
+		q_spec->subtype = buf[1];
 
 		/* call into irq_domain to get irq mapping */
 		intspec[0] = q_chip->spmi->sid;
@@ -572,10 +970,10 @@
 		if (!q_spec->irq) {
 			dev_err(&spmi->dev, "%s: invalid irq for gpio"
 					" %u\n", __func__, gpio);
-			ret = -EINVAL;
+			rc = -EINVAL;
 			goto err_probe;
 		}
-		/* initialize lookup table entries */
+		/* initialize lookup table params */
 		qpnp_pmic_gpio_set_spec(q_chip, gpio, q_spec);
 		qpnp_chip_gpio_set_spec(q_chip, i, q_spec);
 	}
@@ -597,69 +995,49 @@
 	if (rc) {
 		dev_err(&spmi->dev, "%s: Can't add gpio chip, rc = %d\n",
 								__func__, rc);
-		ret = rc;
 		goto err_probe;
 	}
 
-	/* now configure gpio defaults if they exist */
+	/* now configure gpio config defaults if they exist */
 	for (i = 0; i < spmi->num_dev_node; i++) {
 		q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
-		if (WARN_ON(!q_spec))
-			return -ENODEV;
-
-		/* It's not an error to not config a default */
-		prop = of_get_property(spmi->dev_node[i].of_node,
-				"qcom,qpnp-gpio-cfg", &len);
-		/* 8 data values constitute one tuple */
-		if (prop && (len != (8 * sizeof(__be32)))) {
-			dev_err(&spmi->dev, "%s: invalid format for"
-				" qcom,qpnp-gpio-cfg property\n",
-							__func__);
-			ret = -EINVAL;
+		if (WARN_ON(!q_spec)) {
+			rc = -ENODEV;
 			goto err_probe;
-		} else if (prop) {
-			rc = qpnp_gpio_config_default(spmi, prop,
-				     q_chip->gpio_chip.base + i);
-			if (rc) {
-				ret = rc;
-				goto err_probe;
-			}
-		} else {
-			/* initialize with hardware defaults */
-			rc = spmi_ext_register_readl(
-				q_chip->spmi->ctrl, q_spec->slave,
-				Q_REG_ADDR(q_spec, Q_REG_IO_CTL1),
-				&q_spec->regs[Q_REG_I_IO_CTL1],
-				Q_NUM_CTL_REGS);
-			q_spec->regs[Q_REG_I_EN_CTL1] |=
-				(1 << Q_REG_MASTER_EN_SHIFT);
-			rc = spmi_ext_register_writel(
-				q_chip->spmi->ctrl, q_spec->slave,
-				Q_REG_ADDR(q_spec, Q_REG_EN_CTL1),
-				&q_spec->regs[Q_REG_EN_CTL1], 1);
-			if (rc) {
-				dev_err(&spmi->dev, "%s: spmi write"
-						" failed\n", __func__);
-				ret = rc;
-				goto err_probe;
-			}
 		}
+
+		rc = qpnp_gpio_cache_regs(q_chip, q_spec);
+		if (rc)
+			goto err_probe;
+
+		rc = qpnp_gpio_apply_config(q_chip, q_spec);
+		if (rc)
+			goto err_probe;
 	}
 
 	dev_dbg(&spmi->dev, "%s: gpio_chip registered between %d-%u\n",
 			__func__, q_chip->gpio_chip.base,
 			(q_chip->gpio_chip.base + q_chip->gpio_chip.ngpio) - 1);
+
+	rc = qpnp_gpio_debugfs_create(q_chip);
+	if (rc) {
+		dev_err(&spmi->dev, "%s: debugfs creation failed\n", __func__);
+		goto err_probe;
+	}
+
 	return 0;
 
 err_probe:
 	qpnp_gpio_free_chip(q_chip);
-	return ret;
+	return rc;
 }
 
 static int qpnp_gpio_remove(struct spmi_device *spmi)
 {
 	struct qpnp_gpio_chip *q_chip = dev_get_drvdata(&spmi->dev);
 
+	debugfs_remove_recursive(q_chip->dfs_dir);
+
 	return qpnp_gpio_free_chip(q_chip);
 }
 
@@ -687,11 +1065,21 @@
 
 static int __init qpnp_gpio_init(void)
 {
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+	driver_dfs_dir = debugfs_create_dir("qpnp_gpio", NULL);
+	if (driver_dfs_dir == NULL)
+		pr_err("Cannot register top level debugfs directory\n");
+#endif
+
 	return spmi_driver_register(&qpnp_gpio_driver);
 }
 
 static void __exit qpnp_gpio_exit(void)
 {
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+	debugfs_remove_recursive(driver_dfs_dir);
+#endif
+	spmi_driver_unregister(&qpnp_gpio_driver);
 }
 
 MODULE_DESCRIPTION("QPNP PMIC gpio driver");
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 00dba96..7c152721 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -263,7 +263,7 @@
 	 */
 
 	if (adreno_is_a3xx(adreno_dev)) {
-		kgsl_mmu_device_setstate(device, flags);
+		kgsl_mmu_device_setstate(&device->mmu, flags);
 		return;
 	}
 
@@ -349,7 +349,7 @@
 		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
 					&link[0], sizedwords);
 	} else {
-		kgsl_mmu_device_setstate(device, flags);
+		kgsl_mmu_device_setstate(&device->mmu, flags);
 	}
 }
 
@@ -575,7 +575,7 @@
 	}
 
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
-	kgsl_mmu_stop(device);
+	kgsl_mmu_stop(&device->mmu);
 error_clk_off:
 	kgsl_pwrctrl_disable(device);
 
@@ -590,7 +590,7 @@
 
 	adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
 
-	kgsl_mmu_stop(device);
+	kgsl_mmu_stop(&device->mmu);
 
 	device->ftbl->irqctrl(device, 0);
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 050fd83..e10edea 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1510,7 +1510,7 @@
 
 	if (context == NULL) {
 		/* No context - set the default apgetable and thats it */
-		kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
+		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable);
 		return;
 	}
 
@@ -1523,7 +1523,7 @@
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
 	cmds[4] = context->id;
 	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
-	kgsl_mmu_setstate(device, context->pagetable);
+	kgsl_mmu_setstate(&device->mmu, context->pagetable);
 
 #ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
 	kgsl_cffdump_syncmem(NULL, &context->gpustate,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 6b58545..8c5d76a 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2257,7 +2257,7 @@
 
 	if (context == NULL) {
 		/* No context - set the default pagetable and thats it */
-		kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
+		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable);
 		return;
 	}
 
@@ -2270,7 +2270,7 @@
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
 	cmds[4] = context->id;
 	adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
-	kgsl_mmu_setstate(device, context->pagetable);
+	kgsl_mmu_setstate(&device->mmu, context->pagetable);
 
 	/*
 	 * Restore GMEM.  (note: changes shader.
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 6bdf284..9d68c60 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -661,7 +661,7 @@
 
 	kgsl_regread(device, MH_MMU_MPU_END, &r1);
 	kgsl_regread(device, MH_MMU_VA_RANGE, &r2);
-	r3 = kgsl_mmu_get_current_ptbase(device);
+	r3 = kgsl_mmu_get_current_ptbase(&device->mmu);
 	KGSL_LOG_DUMP(device,
 		"        MPU_END    = %08X | VA_RANGE = %08X | PT_BASE  ="
 		" %08X\n", r1, r2, r3);
@@ -706,7 +706,7 @@
 	else if (adreno_is_a3xx(adreno_dev))
 		adreno_dump_a3xx(device);
 
-	pt_base = kgsl_mmu_get_current_ptbase(device);
+	pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
 	cur_pt_base = pt_base;
 
 	kgsl_regread(device, REG_CP_RB_BASE, &cp_rb_base);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index fe01764..d4089b9 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -235,10 +235,8 @@
 	if (rb->flags & KGSL_FLAGS_STARTED)
 		return 0;
 
-	if (init_ram) {
+	if (init_ram)
 		rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
-		GSL_RB_INIT_TIMESTAMP(rb);
-	}
 
 	kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
 			   sizeof(struct kgsl_rbmemptrs));
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index 7c93b3b..ae2e4c7 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -70,7 +70,6 @@
 
 /* enable timestamp (...scratch0) memory shadowing */
 #define GSL_RB_MEMPTRS_SCRATCH_MASK 0x1
-#define GSL_RB_INIT_TIMESTAMP(rb)
 
 /* mem rptr */
 #define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 2dc6f6c..a0907d7 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -531,7 +531,7 @@
 	int skip_pktsize = 1;
 
 	/* Get the physical address of the MMU pagetable */
-	ptbase = kgsl_mmu_get_current_ptbase(device);
+	ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
 
 	/* Get the current read pointers for the RB */
 	kgsl_regread(device, REG_CP_RB_RPTR, &rptr);
@@ -792,7 +792,7 @@
 	memset(vbo, 0, sizeof(vbo));
 
 	/* Get the physical address of the MMU pagetable */
-	ptbase = kgsl_mmu_get_current_ptbase(device);
+	ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
 
 	/* Dump the ringbuffer */
 	snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_RB,
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 1d80a30..5a10654 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -686,12 +686,10 @@
 	return 0;
 }
 
-static int kgsl_gpummu_stop(struct kgsl_mmu *mmu)
+static void kgsl_gpummu_stop(struct kgsl_mmu *mmu)
 {
 	kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
 	mmu->flags &= ~KGSL_FLAGS_STARTED;
-
-	return 0;
 }
 
 static int kgsl_gpummu_close(struct kgsl_mmu *mmu)
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index bf2a4ee..21f14ac 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -298,7 +298,7 @@
 	return ret;
 }
 
-static int kgsl_iommu_stop(struct kgsl_mmu *mmu)
+static void kgsl_iommu_stop(struct kgsl_mmu *mmu)
 {
 	/*
 	 *  stop device mmu
@@ -312,8 +312,6 @@
 
 		mmu->flags &= ~KGSL_FLAGS_STARTED;
 	}
-
-	return 0;
 }
 
 static int kgsl_iommu_close(struct kgsl_mmu *mmu)
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 2b359ec..e11b119 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -322,16 +322,6 @@
 		return 0;
 }
 
-unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_device *device)
-{
-	struct kgsl_mmu *mmu = &device->mmu;
-	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
-		return 0;
-	else
-		return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
-}
-EXPORT_SYMBOL(kgsl_mmu_get_current_ptbase);
-
 int
 kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base)
 {
@@ -351,19 +341,6 @@
 }
 EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase);
 
-void kgsl_mmu_setstate(struct kgsl_device *device,
-			struct kgsl_pagetable *pagetable)
-{
-	struct kgsl_mmu *mmu = &device->mmu;
-
-	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
-		return;
-	else
-		mmu->mmu_ops->mmu_setstate(mmu,
-					pagetable);
-}
-EXPORT_SYMBOL(kgsl_mmu_setstate);
-
 int kgsl_mmu_init(struct kgsl_device *device)
 {
 	struct kgsl_mmu *mmu = &device->mmu;
@@ -555,16 +532,6 @@
 }
 EXPORT_SYMBOL(kgsl_setstate);
 
-void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags)
-{
-	struct kgsl_mmu *mmu = &device->mmu;
-	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
-		return;
-	else if (mmu->mmu_ops->mmu_device_setstate)
-		mmu->mmu_ops->mmu_device_setstate(mmu, flags);
-}
-EXPORT_SYMBOL(kgsl_mmu_device_setstate);
-
 void kgsl_mh_start(struct kgsl_device *device)
 {
 	struct kgsl_mh *mh = &device->mh;
@@ -746,17 +713,6 @@
 }
 EXPORT_SYMBOL(kgsl_mmu_map_global);
 
-int kgsl_mmu_stop(struct kgsl_device *device)
-{
-	struct kgsl_mmu *mmu = &device->mmu;
-
-	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
-		return 0;
-	else
-		return mmu->mmu_ops->mmu_stop(mmu);
-}
-EXPORT_SYMBOL(kgsl_mmu_stop);
-
 int kgsl_mmu_close(struct kgsl_device *device)
 {
 	struct kgsl_mmu *mmu = &device->mmu;
@@ -814,16 +770,6 @@
 }
 EXPORT_SYMBOL(kgsl_mmu_enabled);
 
-int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
-			unsigned int pt_base)
-{
-	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
-		return true;
-	else
-		return pt->pt_ops->mmu_pt_equal(pt, pt_base);
-}
-EXPORT_SYMBOL(kgsl_mmu_pt_equal);
-
 enum kgsl_mmutype kgsl_mmu_get_mmutype(void)
 {
 	return kgsl_mmu_type;
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index e35f368..b476add 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -122,7 +122,7 @@
 	int (*mmu_init) (struct kgsl_mmu *mmu);
 	int (*mmu_close) (struct kgsl_mmu *mmu);
 	int (*mmu_start) (struct kgsl_mmu *mmu);
-	int (*mmu_stop) (struct kgsl_mmu *mmu);
+	void (*mmu_stop) (struct kgsl_mmu *mmu);
 	void (*mmu_setstate) (struct kgsl_mmu *mmu,
 		struct kgsl_pagetable *pagetable);
 	void (*mmu_device_setstate) (struct kgsl_mmu *mmu,
@@ -169,7 +169,6 @@
 void kgsl_mh_intrcallback(struct kgsl_device *device);
 int kgsl_mmu_init(struct kgsl_device *device);
 int kgsl_mmu_start(struct kgsl_device *device);
-int kgsl_mmu_stop(struct kgsl_device *device);
 int kgsl_mmu_close(struct kgsl_device *device);
 int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
 		 struct kgsl_memdesc *memdesc,
@@ -180,19 +179,57 @@
 		    struct kgsl_memdesc *memdesc);
 unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
 void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags);
-void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags);
-void kgsl_mmu_setstate(struct kgsl_device *device,
-			struct kgsl_pagetable *pt);
 int kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base);
 int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
 			enum kgsl_deviceid id);
 void kgsl_mmu_ptpool_destroy(void *ptpool);
 void *kgsl_mmu_ptpool_init(int entries);
 int kgsl_mmu_enabled(void);
-int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
-			unsigned int pt_base);
 void kgsl_mmu_set_mmutype(char *mmutype);
-unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_device *device);
 enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
 unsigned int kgsl_mmu_get_ptsize(void);
+
+/*
+ * Static inline functions of MMU that simply call the SMMU specific
+ * function using a function pointer. These functions can be thought
+ * of as wrappers around the actual function
+ */
+
+static inline unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_current_ptbase)
+		return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
+	else
+		return 0;
+}
+
+static inline void kgsl_mmu_setstate(struct kgsl_mmu *mmu,
+			struct kgsl_pagetable *pagetable)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_setstate)
+		mmu->mmu_ops->mmu_setstate(mmu, pagetable);
+}
+
+static inline void kgsl_mmu_device_setstate(struct kgsl_mmu *mmu,
+						uint32_t flags)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_device_setstate)
+		mmu->mmu_ops->mmu_device_setstate(mmu, flags);
+}
+
+static inline void kgsl_mmu_stop(struct kgsl_mmu *mmu)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_stop)
+		mmu->mmu_ops->mmu_stop(mmu);
+}
+
+static inline int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
+			unsigned int pt_base)
+{
+	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_get_mmutype())
+		return 1;
+	else
+		return pt->pt_ops->mmu_pt_equal(pt, pt_base);
+}
+
 #endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 24ea571..f61c74f 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -122,7 +122,7 @@
 	header->current_context = -1;
 
 	/* Get the current PT base */
-	header->ptbase = kgsl_mmu_get_current_ptbase(device);
+	header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
 	/* And the PID for the task leader */
 	pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(header->ptbase);
 
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 3ca9e18..2df4c80 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -464,7 +464,7 @@
 	    (ctrl & KGSL_CONTEXT_CTX_SWITCH)) {
 		KGSL_CMD_INFO(device, "context switch %d -> %d\n",
 			context->id, z180_dev->ringbuffer.prevctx);
-		kgsl_mmu_setstate(device, pagetable);
+		kgsl_mmu_setstate(&device->mmu, pagetable);
 		cnt = PACKETSIZE_STATESTREAM;
 		ofs = 0;
 	}
@@ -613,7 +613,7 @@
 
 	del_timer_sync(&device->idle_timer);
 
-	kgsl_mmu_stop(device);
+	kgsl_mmu_stop(&device->mmu);
 
 	/* Disable the clocks before the power rail. */
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 60c200e..4706c1c 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -194,6 +194,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called leds-msm-pdm.
 
+config LEDS_PMIC_MPP
+        tristate "LED Support for Qualcomm PMIC MPP connected LEDs"
+        depends on LEDS_CLASS && MSM_SMD
+        help
+          This option enables support for LEDs connected to  PMIC MPPs
+	  on Qualcomm reference boards.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called leds-pmic-mpp.
+
 config LEDS_GPIO_PLATFORM
 	bool "Platform device bindings for GPIO LEDs"
 	depends on LEDS_GPIO
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 819abc0..de6dcd1 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -47,6 +47,7 @@
 obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)		+= leds-asic3.o
 obj-$(CONFIG_LEDS_PMIC8058)		+= leds-pmic8058.o
+obj-$(CONFIG_LEDS_PMIC_MPP)		+= leds-pmic-mpp.o
 obj-$(CONFIG_LEDS_QCIBL)		+= leds-qci-backlight.o
 obj-$(CONFIG_LEDS_MSM_PDM)		+= leds-msm-pdm.o
 
diff --git a/drivers/leds/leds-pmic-mpp.c b/drivers/leds/leds-pmic-mpp.c
new file mode 100644
index 0000000..0de41de
--- /dev/null
+++ b/drivers/leds/leds-pmic-mpp.c
@@ -0,0 +1,140 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+
+#include <mach/pmic.h>
+
+#define LED_MPP(x)		((x) & 0xFF)
+#define LED_CURR(x)		((x) >> 16)
+
+struct pmic_mpp_led_data {
+	struct led_classdev cdev;
+	int curr;
+	int mpp;
+};
+
+static void pm_mpp_led_set(struct led_classdev *led_cdev,
+	enum led_brightness value)
+{
+	struct pmic_mpp_led_data *led;
+	int ret;
+
+	led = container_of(led_cdev, struct pmic_mpp_led_data, cdev);
+
+	if (value < LED_OFF || value > led->cdev.max_brightness) {
+		dev_err(led->cdev.dev, "Invalid brightness value");
+		return;
+	}
+
+	ret = pmic_secure_mpp_config_i_sink(led->mpp, led->curr,
+			value ? PM_MPP__I_SINK__SWITCH_ENA :
+				PM_MPP__I_SINK__SWITCH_DIS);
+	if (ret)
+		dev_err(led_cdev->dev, "can't set mpp led\n");
+}
+
+static int pmic_mpp_led_probe(struct platform_device *pdev)
+{
+	const struct led_platform_data *pdata = pdev->dev.platform_data;
+	struct pmic_mpp_led_data *led, *tmp_led;
+	int i, rc;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data not supplied\n");
+		return -EINVAL;
+	}
+
+	led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
+	if (!led) {
+		dev_err(&pdev->dev, "failed to alloc memory\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, led);
+
+	for (i = 0; i < pdata->num_leds; i++) {
+		tmp_led	= &led[i];
+		tmp_led->cdev.name = pdata->leds[i].name;
+		tmp_led->cdev.brightness_set = pm_mpp_led_set;
+		tmp_led->cdev.brightness = LED_OFF;
+		tmp_led->cdev.max_brightness = LED_FULL;
+		tmp_led->mpp = LED_MPP(pdata->leds[i].flags);
+		tmp_led->curr = LED_CURR(pdata->leds[i].flags);
+
+		if (tmp_led->curr < PM_MPP__I_SINK__LEVEL_5mA ||
+			tmp_led->curr > PM_MPP__I_SINK__LEVEL_40mA) {
+			dev_err(&pdev->dev, "invalid current\n");
+			goto unreg_led_cdev;
+		}
+
+		rc = led_classdev_register(&pdev->dev, &tmp_led->cdev);
+		if (rc) {
+			dev_err(&pdev->dev, "failed to register led\n");
+			goto unreg_led_cdev;
+		}
+	}
+
+	return 0;
+
+unreg_led_cdev:
+	while (i)
+		led_classdev_unregister(&led[--i].cdev);
+
+	kfree(led);
+	return rc;
+
+}
+
+static int __devexit pmic_mpp_led_remove(struct platform_device *pdev)
+{
+	const struct led_platform_data *pdata = pdev->dev.platform_data;
+	struct pmic_mpp_led_data *led = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < pdata->num_leds; i++)
+		led_classdev_unregister(&led[i].cdev);
+
+	kfree(led);
+
+	return 0;
+}
+
+static struct platform_driver pmic_mpp_led_driver = {
+	.probe		= pmic_mpp_led_probe,
+	.remove		= __devexit_p(pmic_mpp_led_remove),
+	.driver		= {
+		.name	= "pmic-mpp-leds",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init pmic_mpp_led_init(void)
+{
+	return platform_driver_register(&pmic_mpp_led_driver);
+}
+module_init(pmic_mpp_led_init);
+
+static void __exit pmic_mpp_led_exit(void)
+{
+	platform_driver_unregister(&pmic_mpp_led_driver);
+}
+module_exit(pmic_mpp_led_exit);
+
+MODULE_DESCRIPTION("PMIC MPP LEDs driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:pmic-mpp-leds");
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index a276e84..72fba82 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -963,7 +963,8 @@
 
 	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
 		HCI_OCF_FM_DEFAULT_DATA_WRITE);
-	return radio_hci_send_cmd(hdev, opcode, sizeof((*def_data_wr)),
+
+	return radio_hci_send_cmd(hdev, opcode, (def_data_wr->length+2),
 	def_data_wr);
 }
 
@@ -2470,7 +2471,7 @@
 			radio->fm_hdev);
 	if (retval < 0)
 		FMDERR("Disable Failed after calibration %d", retval);
-		return retval;
+	return retval;
 }
 static int iris_vidioc_g_ctrl(struct file *file, void *priv,
 		struct v4l2_control *ctrl)
@@ -2726,10 +2727,44 @@
 	case V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT:
 		data = (ctrl->controls[0]).string;
 		memset(&default_data, 0, sizeof(default_data));
-		if (copy_from_user(&default_data, data, sizeof(default_data)))
+		/*
+		 * Check if length of the 'FM Default Data' to be sent
+		 * is within the maximum  'FM Default Data' packet limit.
+		 * Max. 'FM Default Data' packet length is 251 bytes:
+		 *	1 byte    - XFR Mode
+		 *	1 byte    - length of the default data
+		 *	249 bytes - actual data to be configured
+		 */
+		if (ctrl->controls[0].size > (DEFAULT_DATA_SIZE + 2)) {
+			pr_err("%s: Default data buffer overflow!\n", __func__);
+			return -EINVAL;
+		}
+
+		/* copy only 'size' bytes of data as requested by user */
+		retval = copy_from_user(&default_data, data,
+			ctrl->controls[0].size);
+		if (retval > 0) {
+			pr_err("%s: Failed to copy %d bytes of default data"
+				" passed by user\n", __func__, retval);
 			return -EFAULT;
+		}
+		FMDBG("%s: XFR Mode\t: 0x%x\n", __func__, default_data.mode);
+		FMDBG("%s: XFR Data Length\t: %d\n", __func__,
+			default_data.length);
+		/*
+		 * Check if the 'length' of the actual XFR data to be configured
+		 * is valid or not. Length of actual XFR data should be always
+		 * 2 bytes less than the total length of the 'FM Default Data'.
+		 * Length of 'FM Default Data' DEF_DATA_LEN: (1+1+XFR Data Size)
+		 * Length of 'Actual XFR Data' XFR_DATA_LEN: (DEF_DATA_LEN - 2)
+		 */
+		if (default_data.length != (ctrl->controls[0].size - 2)) {
+			pr_err("%s: Invalid 'length' parameter passed for "
+				"actual xfr data\n", __func__);
+			return -EINVAL;
+		}
 		retval = hci_def_data_write(&default_data, radio->fm_hdev);
-			break;
+		break;
 	case V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION:
 		data = (ctrl->controls[0]).string;
 		bytes_to_copy = (ctrl->controls[0]).size;
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 4fd6e49..85157f7 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -8,6 +8,7 @@
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
   EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
   EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
+  EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
   obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
   obj-$(CONFIG_MSM_CAMERA) += sensors/ actuators/ csi/
 else
diff --git a/drivers/media/video/msm/actuators/msm_actuator.c b/drivers/media/video/msm/actuators/msm_actuator.c
index e16766c..e4d8368 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.c
+++ b/drivers/media/video/msm/actuators/msm_actuator.c
@@ -368,9 +368,8 @@
 	return rc;
 }
 
-int32_t msm_actuator_af_power_down(void *cfg_data)
+int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
 {
-	struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
 	int32_t rc = 0;
 	int16_t step_pos = 0;
 	int16_t i = 0;
@@ -501,9 +500,9 @@
 }
 
 
-int32_t msm_actuator_config(void __user *argp)
+int32_t msm_actuator_config(struct msm_actuator_ctrl_t *a_ctrl,
+							void __user *argp)
 {
-	struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
 	struct msm_actuator_cfg_data cdata;
 	int32_t rc = 0;
 	if (copy_from_user(&cdata,
@@ -554,13 +553,19 @@
 	}
 
 	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
-	i2c_set_clientdata(client, (void *)&act_ctrl_t->actuator_ext_ctrl);
-	CDBG("%s client = %x act ctrl t = %x\n",
-		__func__,
-		(unsigned int) client,
-		(unsigned int)&act_ctrl_t->actuator_ext_ctrl);
+	CDBG("%s client = %x\n",
+		__func__, (unsigned int) client);
 	act_ctrl_t->i2c_client.client = client;
 
+	/* Assign name for sub device */
+	snprintf(act_ctrl_t->sdev.name, sizeof(act_ctrl_t->sdev.name),
+			 "%s", act_ctrl_t->i2c_driver->driver.name);
+
+	/* Initialize sub device */
+	v4l2_i2c_subdev_init(&act_ctrl_t->sdev,
+		act_ctrl_t->i2c_client.client,
+		act_ctrl_t->act_v4l2_subdev_ops);
+
 	CDBG("%s succeeded\n", __func__);
 	return rc;
 
@@ -569,16 +574,11 @@
 	return rc;
 }
 
-int32_t msm_actuator_power_up(void *act_info)
+int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
 {
 	int rc = 0;
-	struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
-	struct msm_actuator_info *ptr;
 	CDBG("%s called\n", __func__);
 
-	ptr = act_info;
-	a_ctrl->vcm_pwd = ptr->vcm_pwd;
-	a_ctrl->vcm_enable = ptr->vcm_enable;
 	CDBG("vcm info: %x %x\n", a_ctrl->vcm_pwd,
 		a_ctrl->vcm_enable);
 	if (a_ctrl->vcm_enable) {
@@ -591,31 +591,6 @@
 	return rc;
 }
 
-
-int32_t msm_actuator_create_subdevice(void *info, void *dev)
-{
-	struct msm_actuator_info *act_info = (struct msm_actuator_info *)info;
-	struct i2c_board_info const *board_info = act_info->board_info;
-	struct v4l2_subdev *sdev = (struct v4l2_subdev *)dev;
-	struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
-	int32_t rc = -EFAULT;
-
-	CDBG("%s called\n", __func__);
-
-	/* Store the sub device in actuator structure */
-	a_ctrl->sdev = sdev;
-
-	/* Assign name for sub device */
-	snprintf(sdev->name, sizeof(sdev->name), "%s", board_info->type);
-
-	/* Initialize sub device */
-	v4l2_i2c_subdev_init(sdev,
-		a_ctrl->i2c_client.client,
-		a_ctrl->act_v4l2_subdev_ops);
-
-	return rc;
-}
-
 DEFINE_MUTEX(msm_actuator_mutex);
 
 static const struct i2c_device_id msm_actuator_i2c_id[] = {
@@ -639,7 +614,41 @@
 	return i2c_add_driver(msm_actuator_t.i2c_driver);
 }
 
-static struct v4l2_subdev_core_ops msm_actuator_subdev_core_ops;
+long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct msm_actuator_ctrl_t *a_ctrl = get_actrl(sd);
+	void __user *argp = (void __user *)arg;
+	switch (cmd) {
+	case VIDIOC_MSM_ACTUATOR_CFG:
+		return msm_actuator_config(a_ctrl, argp);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
+{
+	int rc = 0;
+	struct msm_actuator_ctrl_t *a_ctrl = get_actrl(sd);
+	mutex_lock(a_ctrl->actuator_mutex);
+	if (on)
+		rc = msm_actuator_power_up(a_ctrl);
+	else
+		rc = msm_actuator_power_down(a_ctrl);
+	mutex_unlock(a_ctrl->actuator_mutex);
+	return rc;
+}
+
+struct msm_actuator_ctrl_t *get_actrl(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct msm_actuator_ctrl_t, sdev);
+}
+
+static struct v4l2_subdev_core_ops msm_actuator_subdev_core_ops = {
+	.ioctl = msm_actuator_subdev_ioctl,
+	.s_power = msm_actuator_power,
+};
 
 static struct v4l2_subdev_ops msm_actuator_subdev_ops = {
 	.core = &msm_actuator_subdev_core_ops,
@@ -648,12 +657,6 @@
 static struct msm_actuator_ctrl_t msm_actuator_t = {
 	.i2c_driver = &msm_actuator_i2c_driver,
 	.act_v4l2_subdev_ops = &msm_actuator_subdev_ops,
-	.actuator_ext_ctrl = {
-		.a_power_up = msm_actuator_power_up,
-		.a_create_subdevice = msm_actuator_create_subdevice,
-		.a_config = msm_actuator_config,
-		.a_power_down = msm_actuator_af_power_down,
-	},
 
 	.curr_step_pos = 0,
 	.curr_region_index = 0,
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index 803a641b..4f936e7 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.h
@@ -51,8 +51,6 @@
 			struct msm_actuator_move_params_t *);
 	int32_t (*actuator_move_focus) (struct msm_actuator_ctrl_t *,
 			struct msm_actuator_move_params_t *);
-	int (*actuator_power_down) (struct msm_actuator_ctrl_t *);
-	int32_t (*actuator_config)(void __user *);
 	int32_t (*actuator_i2c_write)(struct msm_actuator_ctrl_t *,
 			int16_t, uint32_t);
 	int32_t (*actuator_write_focus)(struct msm_actuator_ctrl_t *,
@@ -71,10 +69,9 @@
 	struct i2c_driver *i2c_driver;
 	struct msm_camera_i2c_client i2c_client;
 	struct mutex *actuator_mutex;
-	struct msm_actuator_ctrl actuator_ext_ctrl;
 	struct msm_actuator_func_tbl *func_tbl;
 	enum msm_actuator_data_type i2c_data_type;
-	struct v4l2_subdev *sdev;
+	struct v4l2_subdev sdev;
 	struct v4l2_subdev_ops *act_v4l2_subdev_ops;
 
 	int16_t curr_step_pos;
@@ -92,6 +89,7 @@
 	uint16_t initial_code;
 };
 
+struct msm_actuator_ctrl_t *get_actrl(struct v4l2_subdev *sd);
 int32_t msm_actuator_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
 		int16_t next_lens_position, uint32_t hw_params);
 int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
@@ -100,7 +98,6 @@
 int32_t msm_actuator_i2c_write_b_af(struct msm_actuator_ctrl_t *a_ctrl,
 		uint8_t msb,
 		uint8_t lsb);
-int32_t msm_actuator_config(void __user *cfg_data);
 int32_t msm_actuator_move_focus(struct msm_actuator_ctrl_t *a_ctrl,
 		struct msm_actuator_move_params_t *move_params);
 int32_t msm_actuator_piezo_move_focus(
@@ -113,7 +110,6 @@
 int32_t msm_actuator_piezo_set_default_focus(
 		struct msm_actuator_ctrl_t *a_ctrl,
 		struct msm_actuator_move_params_t *move_params);
-int32_t msm_actuator_af_power_down(void *cfg_data);
 int32_t msm_actuator_i2c_probe(struct i2c_client *client,
 		const struct i2c_device_id *id);
 int32_t msm_actuator_write_focus(struct msm_actuator_ctrl_t *a_ctrl,
@@ -122,6 +118,11 @@
 int32_t msm_actuator_write_focus2(struct msm_actuator_ctrl_t *a_ctrl,
 		uint16_t curr_lens_pos, struct damping_params_t *damping_params,
 		int8_t sign_direction, int16_t code_boundary);
-int32_t msm_actuator_create_subdevice(void *info, void *dev);
+long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg);
+int32_t msm_actuator_power(struct v4l2_subdev *sd, int on);
+
+#define VIDIOC_MSM_ACTUATOR_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 11, void __user *)
 
 #endif
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index b4adbaf..6a5a647 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -379,6 +379,8 @@
 	.core = &msm_csic_subdev_core_ops,
 };
 
+static const struct v4l2_subdev_internal_ops msm_csic_internal_ops;
+
 static int __devinit csic_probe(struct platform_device *pdev)
 {
 	struct csic_device *new_csic_dev;
@@ -391,6 +393,10 @@
 	}
 
 	v4l2_subdev_init(&new_csic_dev->subdev, &msm_csic_subdev_ops);
+	new_csic_dev->subdev.internal_ops = &msm_csic_internal_ops;
+	new_csic_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(new_csic_dev->subdev.name,
+			ARRAY_SIZE(new_csic_dev->subdev.name), "msm_csic");
 	v4l2_set_subdevdata(&new_csic_dev->subdev, new_csic_dev);
 	platform_set_drvdata(pdev, &new_csic_dev->subdev);
 	mutex_init(&new_csic_dev->mutex);
@@ -431,6 +437,8 @@
 	new_csic_dev->base = NULL;
 
 	new_csic_dev->pdev = pdev;
+	msm_cam_register_subdev_node(
+		&new_csic_dev->subdev, CSIC_DEV, pdev->id);
 	return 0;
 
 csic_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 0cd2cf0..e643def 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -275,6 +275,8 @@
 	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,
@@ -296,6 +298,10 @@
 	}
 
 	v4l2_subdev_init(&new_csid_dev->subdev, &msm_csid_subdev_ops);
+	new_csid_dev->subdev.internal_ops = &msm_csid_internal_ops;
+	new_csid_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(new_csid_dev->subdev.name,
+			ARRAY_SIZE(new_csid_dev->subdev.name), "msm_csid");
 	v4l2_set_subdevdata(&new_csid_dev->subdev, new_csid_dev);
 	platform_set_drvdata(pdev, &new_csid_dev->subdev);
 	mutex_init(&new_csid_dev->mutex);
@@ -334,6 +340,7 @@
 	disable_irq(new_csid_dev->irq->start);
 
 	new_csid_dev->pdev = pdev;
+	msm_cam_register_subdev_node(&new_csid_dev->subdev, CSID_DEV, pdev->id);
 	return 0;
 
 csid_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index aef017f..7c59ae8 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -263,6 +263,8 @@
 	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,
@@ -284,6 +286,10 @@
 	}
 
 	v4l2_subdev_init(&new_csiphy_dev->subdev, &msm_csiphy_subdev_ops);
+	new_csiphy_dev->subdev.internal_ops = &msm_csiphy_internal_ops;
+	new_csiphy_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(new_csiphy_dev->subdev.name,
+			ARRAY_SIZE(new_csiphy_dev->subdev.name), "msm_csiphy");
 	v4l2_set_subdevdata(&new_csiphy_dev->subdev, new_csiphy_dev);
 	platform_set_drvdata(pdev, &new_csiphy_dev->subdev);
 
@@ -323,6 +329,8 @@
 	disable_irq(new_csiphy_dev->irq->start);
 
 	new_csiphy_dev->pdev = pdev;
+	msm_cam_register_subdev_node(
+		&new_csiphy_dev->subdev, CSIPHY_DEV, pdev->id);
 	return 0;
 
 csiphy_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index cbb9e03..728e510 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -599,6 +599,8 @@
 	.video = &msm_ispif_subdev_video_ops,
 };
 
+static const struct v4l2_subdev_internal_ops msm_ispif_internal_ops;
+
 static int __devinit ispif_probe(struct platform_device *pdev)
 {
 	int rc = 0;
@@ -610,6 +612,10 @@
 	}
 
 	v4l2_subdev_init(&ispif->subdev, &msm_ispif_subdev_ops);
+	ispif->subdev.internal_ops = &msm_ispif_internal_ops;
+	ispif->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(ispif->subdev.name,
+			ARRAY_SIZE(ispif->subdev.name), "msm_ispif");
 	v4l2_set_subdevdata(&ispif->subdev, ispif);
 	platform_set_drvdata(pdev, &ispif->subdev);
 	snprintf(ispif->subdev.name, sizeof(ispif->subdev.name),
@@ -645,6 +651,7 @@
 	}
 
 	ispif->pdev = pdev;
+	msm_cam_register_subdev_node(&ispif->subdev, ISPIF_DEV, pdev->id);
 	return 0;
 
 ispif_no_mem:
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index ff97fa3..eff64be 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -19,7 +19,12 @@
 #include <linux/spinlock.h>
 #include <linux/proc_fs.h>
 #include "msm.h"
+#include "msm_csid.h"
+#include "msm_csic.h"
+#include "msm_csiphy.h"
+#include "msm_ispif.h"
 #include "msm_sensor.h"
+#include "msm_actuator.h"
 
 #define MSM_MAX_CAMERA_SENSORS 5
 
@@ -84,7 +89,7 @@
 static int32_t msm_find_free_queue(void)
 {
 	int i;
-	for (i = 0; i < NUM_SERVER_QUEUE; i++) {
+	for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
 		struct msm_cam_server_queue *queue;
 		queue = &g_server_dev.server_queue[i];
 		if (!queue->queue_active)
@@ -93,11 +98,50 @@
 	return -EINVAL;
 }
 
+uint32_t msm_camera_get_mctl_handle(void)
+{
+	uint32_t i;
+	if ((g_server_dev.mctl_handle_cnt << 8) == 0)
+		g_server_dev.mctl_handle_cnt++;
+	for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
+		if (g_server_dev.mctl[i].handle == 0) {
+			g_server_dev.mctl[i].handle =
+				(++g_server_dev.mctl_handle_cnt) << 8 | i;
+			memset(&g_server_dev.mctl[i].mctl,
+				   0, sizeof(g_server_dev.mctl[i].mctl));
+			return g_server_dev.mctl[i].handle;
+		}
+	}
+	return 0;
+}
+
+struct msm_cam_media_controller *msm_camera_get_mctl(uint32_t handle)
+{
+	uint32_t mctl_index;
+	mctl_index = handle & 0xff;
+	if ((mctl_index < MAX_NUM_ACTIVE_CAMERA) &&
+		(g_server_dev.mctl[mctl_index].handle == handle))
+		return &g_server_dev.mctl[mctl_index].mctl;
+	return NULL;
+}
+
+void msm_camera_free_mctl(uint32_t handle)
+{
+	uint32_t mctl_index;
+	mctl_index = handle & 0xff;
+	if ((mctl_index < MAX_NUM_ACTIVE_CAMERA) &&
+		(g_server_dev.mctl[mctl_index].handle == handle))
+		g_server_dev.mctl[mctl_index].handle = 0;
+	else
+		pr_err("%s: invalid free handle\n", __func__);
+}
+
 /* callback function from all subdevices of a msm_cam_v4l2_device */
 static void msm_cam_v4l2_subdev_notify(struct v4l2_subdev *sd,
 				unsigned int notification, void *arg)
 {
 	struct msm_cam_v4l2_device *pcam;
+	struct msm_cam_media_controller *pmctl;
 
 	if (sd == NULL)
 		return;
@@ -107,10 +151,9 @@
 	if (pcam == NULL)
 		return;
 
-	/* forward to media controller for any changes*/
-	if (pcam->mctl.mctl_notify) {
-		pcam->mctl.mctl_notify(&pcam->mctl, notification, arg);
-	}
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	if (pmctl == NULL)
+		return;
 }
 
 static int msm_ctrl_cmd_done(void *arg)
@@ -1166,6 +1209,7 @@
 	int rc;
 	/* get the video device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_media_controller *pmctl;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -1176,8 +1220,12 @@
 		(void *)pfmt->fmt.pix.priv);
 	WARN_ON(pctx != f->private_data);
 
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	if (pmctl == NULL)
+		return -EINVAL;
+
 	if (!pcam_inst->vbqueue_initialized) {
-		pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+		pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE);
 		pcam_inst->vbqueue_initialized = 1;
 	}
@@ -1199,6 +1247,7 @@
 {
 	int rc;
 	struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+	struct msm_cam_media_controller *pmctl;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 			struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -1206,8 +1255,12 @@
 	D("%s Inst %p\n", __func__, pcam_inst);
 	WARN_ON(pctx != f->private_data);
 
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	if (pmctl == NULL)
+		return -EINVAL;
+
 	if (!pcam_inst->vbqueue_initialized) {
-		pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+		pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 		pcam_inst->vbqueue_initialized = 1;
 	}
@@ -1443,6 +1496,8 @@
 	struct msm_cam_v4l2_device *pcam)
 {
 	int rc = 0;
+	struct msm_cam_media_controller *pmctl;
+
 	D("%s\n", __func__);
 
 	if (!ps || !pcam) {
@@ -1465,19 +1520,13 @@
 	D("config pcam = 0x%p\n", ps->pcam_active);
 
 	/* initialization the media controller module*/
-	msm_mctl_init_module(pcam);
+	msm_mctl_init(pcam);
 
-	/*yyan: for single VFE msms (8660, 8960v1), just populate the session
+	/*for single VFE msms (8660, 8960v1), just populate the session
 	with our VFE devices that registered*/
-	pcam->mctl.isp_sdev = ps->isp_subdev[0];
-
-
-	/*yyan: 8960 bring up - no VPE and flash; populate later*/
-	pcam->mctl.vpe_sdev = NULL;
-	pcam->mctl.flash_sdev = NULL;
-
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	pmctl->isp_sdev = ps->isp_subdev[0];
 	return rc;
-
 }
 
 /* close an active camera session to server */
@@ -1496,6 +1545,7 @@
 	atomic_dec(&ps->number_pcam_active);
 	ps->pcam_active = NULL;
 
+	msm_mctl_free(pcam);
 	return rc;
 }
 /* v4l2_file_operations */
@@ -1511,6 +1561,7 @@
 	/* get the video device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_media_controller *pmctl = NULL;
 
 	D("%s\n", __func__);
 
@@ -1568,13 +1619,17 @@
 			__func__, rc);
 			goto err;
 		}
+
+		pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-		pcam->mctl.client = msm_ion_client_create(-1, "camera");
-		kref_init(&pcam->mctl.refcount);
+		pmctl->client = msm_ion_client_create(-1, "camera");
+		kref_init(&pmctl->refcount);
 		ion_client_created = 1;
 #endif
+
 		/* Should be set to sensor ops if any but right now its OK!! */
-		if (!pcam->mctl.mctl_open) {
+		if (!pmctl->mctl_open) {
 			D("%s: media contoller is not inited\n",
 				 __func__);
 			rc = -ENODEV;
@@ -1583,29 +1638,14 @@
 
 		/* Now we really have to activate the camera */
 		D("%s: call mctl_open\n", __func__);
-		rc = pcam->mctl.mctl_open(&(pcam->mctl), MSM_APPS_ID_V4L2);
+		rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
 
 		if (rc < 0) {
 			pr_err("%s: HW open failed rc = 0x%x\n",  __func__, rc);
 			goto err;
 		}
-		pcam->mctl.sync.pcam_sync = pcam;
+		pmctl->pcam_ptr = pcam;
 
-		/* Register isp subdev */
-		rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
-					pcam->mctl.isp_sdev->sd);
-		if (rc < 0) {
-			pr_err("%s: v4l2_device_register_subdev failed rc = %d\n",
-				__func__, rc);
-			goto err;
-		}
-		if (pcam->mctl.isp_sdev->sd_vpe) {
-			rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
-						pcam->mctl.isp_sdev->sd_vpe);
-			if (rc < 0) {
-				goto err;
-			}
-		}
 		rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
 							pcam->pvdev);
 		if (rc < 0) {
@@ -1639,7 +1679,7 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		if (ion_client_created) {
 			pr_err("%s: destroy ion client", __func__);
-			kref_put(&pcam->mctl.refcount, msm_release_ion_client);
+			kref_put(&pmctl->refcount, msm_release_ion_client);
 		}
 #endif
 		pcam->dev_inst[i] = NULL;
@@ -1656,10 +1696,16 @@
 	int phyaddr;
 	int retval;
 	unsigned long size;
-	struct msm_sync *sync = &pcam_inst->pcam->mctl.sync;
 	int rc = 0;
+	struct msm_cam_media_controller *mctl;
 
-	rc = msm_pmem_region_get_phy_addr(&sync->pmem_stats,
+	mctl = msm_camera_get_mctl(pcam_inst->pcam->mctl_handle);
+	if (!mctl) {
+		pr_err("%s: invalid mctl pointer", __func__);
+		return -EFAULT;
+	}
+
+	rc = msm_pmem_region_get_phy_addr(&mctl->stats_info.pmem_stats_list,
 			&pcam_inst->mem_map,
 			&phyaddr);
 	if (rc) {
@@ -1722,6 +1768,7 @@
 	struct msm_cam_v4l2_device *pcam;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	struct msm_cam_server_queue *queue;
+	struct msm_cam_media_controller *pmctl;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 	pcam = pcam_inst->pcam;
@@ -1730,17 +1777,23 @@
 		return -EINVAL;
 	}
 
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s NULL mctl pointer\n", __func__);
+		return -EINVAL;
+	}
+
 	mutex_lock(&pcam->vid_lock);
 
 	if (pcam_inst->streamon) {
 		/*something went wrong since instance
 		is closing without streamoff*/
-		if (pcam->mctl.mctl_release) {
-			rc = pcam->mctl.mctl_release(&(pcam->mctl));
+		if (pmctl->mctl_release) {
+			rc = pmctl->mctl_release(pmctl);
 			if (rc < 0)
 				pr_err("mctl_release fails %d\n", rc);
 		}
-		pcam->mctl.mctl_release = NULL;/*so that it isn't closed again*/
+		pmctl->mctl_release = NULL;/*so that it isn't closed again*/
 	}
 
 	pcam_inst->streamon = 0;
@@ -1760,24 +1813,18 @@
 	f->private_data = NULL;
 
 	if (pcam->use_count == 0) {
-		v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd);
-		v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd_vpe);
-		rc = msm_cam_server_close_session(&g_server_dev, pcam);
-		if (rc < 0)
-			pr_err("msm_cam_server_close_session fails %d\n", rc);
-
 		if (g_server_dev.use_count > 0) {
 			rc = msm_send_close_server(pcam);
 			if (rc < 0)
 				pr_err("msm_send_close_server failed %d\n", rc);
 		}
-		if (pcam->mctl.mctl_release) {
-			rc = pcam->mctl.mctl_release(&(pcam->mctl));
+		if (pmctl->mctl_release) {
+			rc = pmctl->mctl_release(pmctl);
 			if (rc < 0)
 				pr_err("mctl_release fails %d\n", rc);
 		}
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-		kref_put(&pcam->mctl.refcount, msm_release_ion_client);
+		kref_put(&pmctl->refcount, msm_release_ion_client);
 #endif
 		queue = &g_server_dev.server_queue[pcam->server_queue_idx];
 		queue->queue_active = 0;
@@ -1787,6 +1834,10 @@
 		queue->ctrl_data = NULL;
 		msm_queue_drain(&queue->ctrl_q, list_control);
 		msm_drain_eventq(&queue->eventData_q);
+		rc = msm_cam_server_close_session(&g_server_dev, pcam);
+		if (rc < 0)
+			pr_err("msm_cam_server_close_session fails %d\n", rc);
+
 		if (g_server_dev.use_count == 0)
 			mutex_unlock(&g_server_dev.server_lock);
 	}
@@ -2077,7 +2128,7 @@
 		return -EFAULT;
 	}
 
-	pcam = mctl->sync.pcam_sync;
+	pcam = mctl->pcam_ptr;
 	ktime_get_ts(&v4l2_ev.timestamp);
 	v4l2_event_queue(pcam->pvdev, &v4l2_ev);
 	return 0;
@@ -2098,13 +2149,13 @@
 		/* memory management shall be handeld here*/
 	case MSM_CAM_IOCTL_REGISTER_PMEM:
 		return msm_register_pmem(
-			&config_cam->p_mctl->sync.pmem_stats,
+			&config_cam->p_mctl->stats_info.pmem_stats_list,
 			(void __user *)arg, config_cam->p_mctl->client);
 		break;
 
 	case MSM_CAM_IOCTL_UNREGISTER_PMEM:
 		return msm_pmem_table_del(
-			&config_cam->p_mctl->sync.pmem_stats,
+			&config_cam->p_mctl->stats_info.pmem_stats_list,
 			(void __user *)arg, config_cam->p_mctl->client);
 		break;
 	case VIDIOC_SUBSCRIBE_EVENT:
@@ -2277,7 +2328,6 @@
 static int msm_open_config(struct inode *inode, struct file *fp)
 {
 	int rc;
-
 	struct msm_cam_config_dev *config_cam =
 	container_of(inode->i_cdev, struct msm_cam_config_dev, config_cdev);
 
@@ -2292,10 +2342,11 @@
 
 	/*config_cam->isp_subdev = g_server_dev.pcam_active->mctl.isp_sdev;*/
 	/* assume there is only one active camera possible*/
-	config_cam->p_mctl = &g_server_dev.pcam_active->mctl;
+	config_cam->p_mctl =
+		msm_camera_get_mctl(g_server_dev.pcam_active->mctl_handle);
 
-	INIT_HLIST_HEAD(&config_cam->p_mctl->sync.pmem_stats);
-	spin_lock_init(&config_cam->p_mctl->sync.pmem_stats_spinlock);
+	INIT_HLIST_HEAD(&config_cam->p_mctl->stats_info.pmem_stats_list);
+	spin_lock_init(&config_cam->p_mctl->stats_info.pmem_stats_spinlock);
 
 	config_cam->p_mctl->config_device = config_cam;
 	kref_get(&config_cam->p_mctl->refcount);
@@ -2439,6 +2490,150 @@
 
 }
 
+static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
+				unsigned int notification, void *arg)
+{
+	int rc = -EINVAL;
+	struct msm_sensor_ctrl_t *s_ctrl;
+	struct msm_camera_sensor_info *sinfo;
+	struct msm_camera_device_platform_data *camdev;
+	uint8_t csid_core = 0;
+
+	if (notification == NOTIFY_CID_CHANGE ||
+		notification == NOTIFY_ISPIF_STREAM ||
+		notification == NOTIFY_PCLK_CHANGE ||
+		notification == NOTIFY_CSIPHY_CFG ||
+		notification == NOTIFY_CSID_CFG ||
+		notification == NOTIFY_CSIC_CFG) {
+		s_ctrl = get_sctrl(sd);
+		sinfo = (struct msm_camera_sensor_info *) s_ctrl->sensordata;
+		camdev = sinfo->pdata;
+		csid_core = camdev->csid_core;
+	}
+
+	switch (notification) {
+	case NOTIFY_CID_CHANGE:
+		/* reconfig the ISPIF*/
+		if (g_server_dev.ispif_device) {
+			struct msm_ispif_params_list ispif_params;
+			ispif_params.len = 1;
+			ispif_params.params[0].intftype = PIX0;
+			ispif_params.params[0].cid_mask = 0x0001;
+			ispif_params.params[0].csid = csid_core;
+
+			rc = v4l2_subdev_call(
+				g_server_dev.ispif_device, core, ioctl,
+				VIDIOC_MSM_ISPIF_CFG, &ispif_params);
+			if (rc < 0)
+				return;
+		}
+		break;
+	case NOTIFY_ISPIF_STREAM:
+		/* call ISPIF stream on/off */
+		rc = v4l2_subdev_call(g_server_dev.ispif_device, video,
+				s_stream, (int)arg);
+		if (rc < 0)
+			return;
+
+		break;
+	case NOTIFY_ISP_MSG_EVT:
+	case NOTIFY_VFE_MSG_OUT:
+	case NOTIFY_VFE_MSG_STATS:
+	case NOTIFY_VFE_MSG_COMP_STATS:
+	case NOTIFY_VFE_BUF_EVT:
+	case NOTIFY_VFE_BUF_FREE_EVT:
+		if (g_server_dev.isp_subdev[0] &&
+			g_server_dev.isp_subdev[0]->isp_notify) {
+			rc = g_server_dev.isp_subdev[0]->isp_notify(
+				g_server_dev.vfe_device[0], notification, arg);
+		}
+		break;
+	case NOTIFY_VPE_MSG_EVT:
+		if (g_server_dev.isp_subdev[0] &&
+			g_server_dev.isp_subdev[0]->isp_notify) {
+			rc = g_server_dev.isp_subdev[0]->isp_notify(
+				g_server_dev.vpe_device[0], notification, arg);
+		}
+		break;
+	case NOTIFY_PCLK_CHANGE:
+		rc = v4l2_subdev_call(g_server_dev.vfe_device[0], video,
+			s_crystal_freq, *(uint32_t *)arg, 0);
+		break;
+	case NOTIFY_CSIPHY_CFG:
+		rc = v4l2_subdev_call(g_server_dev.csiphy_device[csid_core],
+			core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
+		break;
+	case NOTIFY_CSID_CFG:
+		rc = v4l2_subdev_call(g_server_dev.csid_device[csid_core],
+			core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
+		break;
+	case NOTIFY_CSIC_CFG:
+		rc = v4l2_subdev_call(g_server_dev.csic_device[csid_core],
+			core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
+		break;
+	default:
+		break;
+	}
+
+	return;
+}
+
+int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
+	enum msm_cam_subdev_type sdev_type, uint8_t index)
+{
+	struct video_device *vdev;
+	int err = 0;
+
+	if (sdev_type == CSIPHY_DEV) {
+		if (index >= MAX_NUM_CSIPHY_DEV)
+			return -EINVAL;
+		g_server_dev.csiphy_device[index] = sd;
+	} else if (sdev_type == CSID_DEV) {
+		if (index >= MAX_NUM_CSID_DEV)
+			return -EINVAL;
+		g_server_dev.csid_device[index] = sd;
+	} else if (sdev_type == CSIC_DEV) {
+		if (index >= MAX_NUM_CSIC_DEV)
+			return -EINVAL;
+		g_server_dev.csic_device[index] = sd;
+	} else if (sdev_type == ISPIF_DEV) {
+		g_server_dev.ispif_device = sd;
+	} else if (sdev_type == VFE_DEV) {
+		if (index >= MAX_NUM_VFE_DEV)
+			return -EINVAL;
+		g_server_dev.vfe_device[index] = sd;
+	} else if (sdev_type == VPE_DEV) {
+		if (index >= MAX_NUM_VPE_DEV)
+			return -EINVAL;
+		g_server_dev.vpe_device[index] = sd;
+	}
+
+	err = v4l2_device_register_subdev(&g_server_dev.v4l2_dev, sd);
+	if (err < 0)
+		return err;
+
+	/* 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 err;
+
+	vdev = &sd->devnode;
+	strlcpy(vdev->name, sd->name, sizeof(vdev->name));
+	vdev->v4l2_dev = &g_server_dev.v4l2_dev;
+	vdev->fops = &v4l2_subdev_fops;
+	vdev->release = video_device_release_empty;
+	err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+						  sd->owner);
+	if (err < 0)
+		return err;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	sd->entity.v4l.major = VIDEO_MAJOR;
+	sd->entity.v4l.minor = vdev->minor;
+#endif
+	return 0;
+}
+
 static int msm_setup_server_dev(struct platform_device *pdev)
 {
 	int rc = -ENODEV, i;
@@ -2446,7 +2641,7 @@
 	D("%s\n", __func__);
 	g_server_dev.server_pdev = pdev;
 	g_server_dev.v4l2_dev.dev = &pdev->dev;
-
+	g_server_dev.v4l2_dev.notify = msm_cam_server_subdev_notify;
 	rc = v4l2_device_register(g_server_dev.v4l2_dev.dev,
 			&g_server_dev.v4l2_dev);
 	if (rc < 0)
@@ -2496,7 +2691,7 @@
 	if (rc < 0)
 		pr_err("%s failed to initialize event queue\n", __func__);
 
-	for (i = 0; i < NUM_SERVER_QUEUE; i++) {
+	for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
 		struct msm_cam_server_queue *queue;
 		queue = &g_server_dev.server_queue[i];
 		queue->queue_active = 0;
@@ -2510,7 +2705,7 @@
 {
 	int rc = -ENOMEM;
 	struct video_device *pvdev = NULL;
-	struct i2c_client *client = v4l2_get_subdevdata(pcam->mctl.sensor_sdev);
+	struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
 	D("%s\n", __func__);
 
 	/* first register the v4l2 device */
@@ -2529,20 +2724,20 @@
 		return rc;
 	}
 
-	strlcpy(pcam->mctl.media_dev.model, QCAMERA_NAME,
-			sizeof(pcam->mctl.media_dev.model));
-	pcam->mctl.media_dev.dev = &client->dev;
-	rc = media_device_register(&pcam->mctl.media_dev);
+	strlcpy(pcam->media_dev.model, QCAMERA_NAME,
+			sizeof(pcam->media_dev.model));
+	pcam->media_dev.dev = &client->dev;
+	rc = media_device_register(&pcam->media_dev);
 	pvdev->v4l2_dev = &pcam->v4l2_dev;
-	pcam->v4l2_dev.mdev = &pcam->mctl.media_dev;
+	pcam->v4l2_dev.mdev = &pcam->media_dev;
 
 	/* init video device's driver interface */
 	D("sensor name = %s, sizeof(pvdev->name)=%d\n",
-		pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
+		pcam->sensor_sdev->name, sizeof(pvdev->name));
 
 	/* device info - strlcpy is safer than strncpy but
 	   only if architecture supports*/
-	strlcpy(pvdev->name, pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
+	strlcpy(pvdev->name, pcam->sensor_sdev->name, sizeof(pvdev->name));
 
 	pvdev->release   = video_device_release;
 	pvdev->fops	  = &g_msm_fops;
@@ -2589,23 +2784,13 @@
 	return rc;
 }
 
-static int msm_sync_destroy(struct msm_sync *sync)
+static struct v4l2_subdev *msm_actuator_probe(
+	struct msm_actuator_info *actuator_info)
 {
-	if (sync) {
-		mutex_destroy(&sync->lock);
-		wake_lock_destroy(&sync->wake_lock);
-	}
-	return 0;
-}
-
-static int msm_actuator_probe(struct msm_actuator_info *actuator_info,
-			      struct v4l2_subdev *act_sdev,
-			      struct msm_actuator_ctrl *actctrl)
-{
-	int rc = 0;
+	struct v4l2_subdev *act_sdev;
 	struct i2c_adapter *adapter = NULL;
+	struct msm_actuator_ctrl_t *actrl;
 	void *act_client = NULL;
-	struct msm_actuator_ctrl *a_ext_ctrl = NULL;
 
 	D("%s called\n", __func__);
 
@@ -2620,14 +2805,19 @@
 	if (!act_client)
 		goto device_fail;
 
-	a_ext_ctrl = (struct msm_actuator_ctrl *)i2c_get_clientdata(act_client);
-	if (!a_ext_ctrl)
+	act_sdev = (struct v4l2_subdev *)i2c_get_clientdata(act_client);
+	if (act_sdev == NULL)
 		goto client_fail;
 
-	*actctrl = *a_ext_ctrl;
-	a_ext_ctrl->a_create_subdevice((void *)actuator_info,
-				       (void *)act_sdev);
-	return rc;
+	if (actuator_info->vcm_enable) {
+		actrl = get_actrl(act_sdev);
+		if (actrl) {
+			actrl->vcm_enable = actuator_info->vcm_enable;
+			actrl->vcm_pwd = actuator_info->vcm_pwd;
+		}
+	}
+
+	return act_sdev;
 
 client_fail:
 	i2c_unregister_device(act_client);
@@ -2635,21 +2825,7 @@
 	i2c_put_adapter(adapter);
 	adapter = NULL;
 probe_fail:
-	actctrl->a_power_up = NULL;
-	actctrl->a_power_down = NULL;
-	actctrl->a_config = NULL;
-	actctrl->a_create_subdevice = NULL;
-	return rc;
-}
-
-static int msm_sync_init(struct msm_sync *sync,
-	struct platform_device *pdev)
-{
-	int rc = 0;
-	wake_lock_init(&sync->wake_lock, WAKE_LOCK_IDLE, "msm_camera");
-	sync->opencnt = 0;
-	mutex_init(&sync->lock);
-	return rc;
+	return NULL;
 }
 
 /* register a msm sensor into the msm device, which will probe the
@@ -2661,8 +2837,6 @@
 	struct msm_camera_sensor_info *sdata;
 	struct msm_cam_v4l2_device *pcam;
 	struct msm_sensor_ctrl_t *s_ctrl;
-	struct v4l2_subdev *act_sdev = NULL;
-	struct msm_actuator_ctrl *actctrl = NULL;
 
 	D("%s for %s\n", __func__, sensor_sd->name);
 
@@ -2674,34 +2848,15 @@
 		return -ENOMEM;
 	}
 
-	pcam->mctl.sensor_sdev = sensor_sd;
+	pcam->sensor_sdev = sensor_sd;
 	s_ctrl = get_sctrl(sensor_sd);
 	sdata = (struct msm_camera_sensor_info *) s_ctrl->sensordata;
 
-	pcam->mctl.act_sdev = kzalloc(sizeof(struct v4l2_subdev),
-								  GFP_KERNEL);
-	if (!pcam->mctl.act_sdev) {
-		pr_err("%s: could not allocate mem for actuator v4l2_subdev\n",
-			   __func__);
-		kfree(pcam);
-		return -ENOMEM;
-	}
+	pcam->act_sdev = msm_actuator_probe(sdata->actuator_info);
 
-	act_sdev = pcam->mctl.act_sdev;
-	actctrl = &pcam->mctl.sync.actctrl;
-
-	msm_actuator_probe(sdata->actuator_info,
-					   act_sdev, actctrl);
-
-	/* setup a manager object*/
-	rc = msm_sync_init(&pcam->mctl.sync, NULL);
-	if (rc < 0)
-		goto failure;
 	D("%s: pcam =0x%p\n", __func__, pcam);
-	D("%s: &pcam->mctl.sync =0x%p\n", __func__, &pcam->mctl.sync);
 
-	pcam->mctl.sync.sdata = sdata;
-	pcam->mctl.sync.pcam_sync = pcam;
+	pcam->sdata = sdata;
 
 	/* init the user count and lock*/
 	pcam->use_count = 0;
@@ -2751,8 +2906,8 @@
 	/*Temporary solution to store info in media device structure
 	  until we can expand media device structure to support more
 	  device info*/
-	snprintf(pcam->mctl.media_dev.serial,
-			sizeof(pcam->mctl.media_dev.serial),
+	snprintf(pcam->media_dev.serial,
+			sizeof(pcam->media_dev.serial),
 			"%s-%d-%d", QCAMERA_NAME,
 			sdata->sensor_platform_info->mount_angle,
 			sdata->camera_type);
@@ -2765,15 +2920,16 @@
 		g_server_dev.camera_info.num_cameras);
 
 	/* register the subdevice, must be done for callbacks */
-	rc = v4l2_device_register_subdev(&pcam->v4l2_dev, sensor_sd);
+	rc = msm_cam_register_subdev_node(sensor_sd, SENSOR_DEV, vnode_count);
 	if (rc < 0) {
 		D("%s sensor sub device register failed\n",
 			__func__);
 		goto failure;
 	}
 
-	if (sdata->actuator_info) {
-		rc = v4l2_device_register_subdev(&pcam->v4l2_dev, act_sdev);
+	if (pcam->act_sdev) {
+		rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
+				pcam->act_sdev);
 		if (rc < 0) {
 			D("%s actuator sub device register failed\n",
 			  __func__);
@@ -2785,10 +2941,6 @@
 	return rc;
 
 failure:
-	/* mutex_destroy not needed at this moment as the associated
-	implemenation of mutex_init is not consuming resources */
-	msm_sync_destroy(&pcam->mctl.sync);
-	kfree(act_sdev);
 	kzfree(pcam);
 	return rc;
 }
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index c4373a7..77b654d 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -50,6 +50,24 @@
 #define MSM_GEMINI_DRV_NAME "msm_gemini"
 #define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
 
+#define MAX_NUM_CSIPHY_DEV 3
+#define MAX_NUM_CSID_DEV 3
+#define MAX_NUM_CSIC_DEV 3
+#define MAX_NUM_ISPIF_DEV 1
+#define MAX_NUM_VFE_DEV 2
+#define MAX_NUM_VPE_DEV 1
+
+enum msm_cam_subdev_type {
+	CSIPHY_DEV,
+	CSID_DEV,
+	CSIC_DEV,
+	ISPIF_DEV,
+	VFE_DEV,
+	VPE_DEV,
+	SENSOR_DEV,
+	ACTUATOR_DEV,
+};
+
 /* msm queue management APIs*/
 
 #define msm_dequeue(queue, member) ({	   \
@@ -204,8 +222,6 @@
 	int (*mctl_open)(struct msm_cam_media_controller *p_mctl,
 					 const char *const apps_id);
 	int (*mctl_cb)(void);
-	int (*mctl_notify)(struct msm_cam_media_controller *p_mctl,
-			unsigned int notification, void *arg);
 	int (*mctl_cmd)(struct msm_cam_media_controller *p_mctl,
 					unsigned int cmd, unsigned long arg);
 	int (*mctl_release)(struct msm_cam_media_controller *p_mctl);
@@ -214,38 +230,35 @@
 				struct vb2_queue *q, enum v4l2_buf_type type);
 	int (*mctl_ufmt_init)(struct msm_cam_media_controller *p_mctl);
 
-	struct v4l2_fh  eventHandle; /* event queue to export events */
-	/* most-frequently accessed manager object*/
-	struct msm_sync sync;
-
-	/*Media device node*/
-	struct media_device media_dev;
-
 	/* the following reflect the HW topology information*/
-	/*mandatory*/
 	struct v4l2_subdev *sensor_sdev; /* sensor sub device */
-	struct v4l2_subdev mctl_sdev;   /*  media control sub device */
-	struct platform_device *plat_dev;
-	/*optional*/
-	struct msm_isp_ops *isp_sdev;    /* isp sub device : camif/VFE */
-	struct v4l2_subdev *vpe_sdev;    /* vpe sub device : VPE */
-	struct v4l2_subdev *flash_sdev;    /* vpe sub device : VPE */
-	struct msm_cam_config_dev *config_device;
+	struct v4l2_subdev *act_sdev; /* actuator sub device */
 	struct v4l2_subdev *csiphy_sdev; /*csiphy sub device*/
 	struct v4l2_subdev *csid_sdev; /*csid sub device*/
 	struct v4l2_subdev *csic_sdev; /*csid sub device*/
 	struct v4l2_subdev *ispif_sdev; /* ispif sub device */
-	struct v4l2_subdev *act_sdev; /* actuator sub device */
 	struct v4l2_subdev *gemini_sdev; /* gemini sub device */
 
+	struct msm_isp_ops *isp_sdev;    /* isp sub device : camif/VFE */
+	struct msm_cam_config_dev *config_device;
+
+	/*mctl session control information*/
+	uint8_t opencnt; /*mctl ref count*/
+	const char *apps_id; /*ID for app that open this session*/
+	struct mutex lock;
+	struct wake_lock wake_lock; /*avoid low power mode when active*/
 	struct pm_qos_request_list pm_qos_req_list;
 	struct msm_mctl_pp_info pp_info;
+	struct msm_mctl_stats_t stats_info; /*stats pmem info*/
+	uint32_t vfe_output_mode; /* VFE output mode */
 	struct ion_client *client;
 	struct kref refcount;
-	/* VFE output mode.
-	* Used to interpret the Primary/Secondary messages
-	* to preview/video/main/thumbnail image types*/
-	uint32_t vfe_output_mode;
+
+	/*pcam ptr*/
+	struct msm_cam_v4l2_device *pcam_ptr;
+
+	/*sensor info*/
+	struct msm_camera_sensor_info *sdata;
 };
 
 /* abstract camera device represents a VFE and connected sensor */
@@ -254,13 +267,12 @@
 
 	/*int (*isp_init)(struct msm_cam_v4l2_device *pcam);*/
 	int (*isp_open)(struct v4l2_subdev *sd, struct v4l2_subdev *sd_vpe,
-		struct v4l2_subdev *gemini_sdev, struct msm_sync *sync);
+		struct msm_cam_media_controller *mctl);
 	int (*isp_config)(struct msm_cam_media_controller *pmctl,
 		 unsigned int cmd, unsigned long arg);
 	int (*isp_notify)(struct v4l2_subdev *sd,
 		unsigned int notification, void *arg);
-	void (*isp_release)(struct msm_sync *psync,
-		struct v4l2_subdev *gemini_sdev);
+	void (*isp_release)(struct v4l2_subdev *sd);
 	int (*isp_pp_cmd)(struct msm_cam_media_controller *pmctl,
 		 struct msm_mctl_pp_cmd, void *data);
 
@@ -314,57 +326,32 @@
 
 /* abstract camera device for each sensor successfully probed*/
 struct msm_cam_v4l2_device {
-	/* standard device interfaces */
-	/* parent of video device to trace back */
-	struct device dev;
-	/* sensor's platform device*/
-	struct platform_device *pdev;
-	/* V4l2 device */
-	struct v4l2_device v4l2_dev;
-	/* will be registered as /dev/video*/
-	struct video_device *pvdev;
+
+	/* device node information */
+	int vnode_id;
+	struct v4l2_device v4l2_dev; /* V4l2 device */
+	struct video_device *pvdev; /* registered as /dev/video*/
+	struct msm_cam_mctl_node mctl_node; /* node for buffer management */
+	struct media_device media_dev; /* node to get video node info*/
+
+	/* device session information */
 	int use_count;
-	/* will be used to init/release HW */
-	struct msm_cam_media_controller mctl;
-
-	/* parent device */
-	struct device *parent_dev;
-
 	struct mutex vid_lock;
+	uint32_t server_queue_idx;
+	uint32_t mctl_handle;
+	struct msm_cam_v4l2_dev_inst *dev_inst[MSM_DEV_INST_MAX];
+	struct msm_cam_v4l2_dev_inst *dev_inst_map[MSM_MAX_IMG_MODE];
+	int op_mode;
+
 	/* v4l2 format support */
 	struct msm_isp_color_fmt *usr_fmts;
 	int num_fmts;
-	/* preview or snapshot */
-	u32 mode;
-	u32 memsize;
 
-	int op_mode;
-	int vnode_id;
-	struct msm_cam_v4l2_dev_inst *dev_inst[MSM_DEV_INST_MAX];
-	struct msm_cam_v4l2_dev_inst *dev_inst_map[MSM_MAX_IMG_MODE];
-	/* native config device */
-	struct cdev cdev;
-
-	/* The message queue is used by the control thread to send commands
-	 * to the config thread, and also by the HW to send messages to the
-	 * config thread.  Thus it is the only queue that is accessed from
-	 * both interrupt and process context.
-	 */
-	/* struct msm_device_queue event_q; */
-
-	/* This queue used by the config thread to send responses back to the
-	 * control thread.  It is accessed only from a process context.
-	 * TO BE REMOVED
-	 */
-	uint32_t server_queue_idx;
-	struct msm_device_queue ctrl_q;
-
-	struct mutex lock;
-	uint8_t ctrl_data[max_control_command_size];
-	struct msm_ctrl_cmd ctrl;
-	uint32_t event_mask;
-	struct msm_cam_mctl_node mctl_node;
+	struct v4l2_subdev *sensor_sdev; /* sensor sub device */
+	struct v4l2_subdev *act_sdev; /* actuator sub device */
+	struct msm_camera_sensor_info *sdata;
 };
+
 static inline struct msm_cam_v4l2_device *to_pcam(
 	struct v4l2_device *v4l2_dev)
 {
@@ -388,7 +375,7 @@
 	struct msm_mem_map_info mem_map;
 };
 
-#define NUM_SERVER_QUEUE 5
+#define MAX_NUM_ACTIVE_CAMERA 2
 
 struct msm_cam_server_queue {
 	uint32_t queue_active;
@@ -399,6 +386,11 @@
 	uint32_t evt_id;
 };
 
+struct msm_cam_server_mctl_inst {
+	struct msm_cam_media_controller mctl;
+	uint32_t handle;
+};
+
 /* abstract camera server device for all sensor successfully probed*/
 struct msm_cam_server_dev {
 
@@ -422,9 +414,12 @@
 	/* This queue used by the config thread to send responses back to the
 	 * control thread.  It is accessed only from a process context.
 	 */
-	struct msm_cam_server_queue server_queue[NUM_SERVER_QUEUE];
+	struct msm_cam_server_queue server_queue[MAX_NUM_ACTIVE_CAMERA];
 	uint32_t server_evt_id;
 
+	struct msm_cam_server_mctl_inst mctl[MAX_NUM_ACTIVE_CAMERA];
+	uint32_t mctl_handle_cnt;
+
 	int use_count;
 	/* all the registered ISP subdevice*/
 	struct msm_isp_ops *isp_subdev[MSM_MAX_CAMERA_CONFIGS];
@@ -432,6 +427,13 @@
 	struct msm_mctl_node_info mctl_node_info;
 	struct mutex server_lock;
 	struct mutex server_queue_lock;
+	/*v4l2 subdevs*/
+	struct v4l2_subdev *csiphy_device[MAX_NUM_CSIPHY_DEV];
+	struct v4l2_subdev *csid_device[MAX_NUM_CSID_DEV];
+	struct v4l2_subdev *csic_device[MAX_NUM_CSIC_DEV];
+	struct v4l2_subdev *ispif_device;
+	struct v4l2_subdev *vfe_device[MAX_NUM_VFE_DEV];
+	struct v4l2_subdev *vpe_device[MAX_NUM_VPE_DEV];
 };
 
 /* camera server related functions */
@@ -447,7 +449,8 @@
 int msm_sensor_register(struct v4l2_subdev *);
 int msm_isp_init_module(int g_num_config_nodes);
 
-int msm_mctl_init_module(struct msm_cam_v4l2_device *pcam);
+int msm_mctl_init(struct msm_cam_v4l2_device *pcam);
+int msm_mctl_free(struct msm_cam_v4l2_device *pcam);
 int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam);
 int msm_mctl_init_user_formats(struct msm_cam_v4l2_device *pcam);
 int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
@@ -475,22 +478,23 @@
 					struct msm_pmem_region *reg,
 					uint8_t maxcount);
 unsigned long msm_pmem_stats_vtop_lookup(
-				struct msm_sync *sync,
+				struct msm_cam_media_controller *mctl,
 				unsigned long buffer,
 				int fd);
-unsigned long msm_pmem_stats_ptov_lookup(struct msm_sync *sync,
-						unsigned long addr, int *fd);
+unsigned long msm_pmem_stats_ptov_lookup(
+	struct msm_cam_media_controller *mctl,
+	unsigned long addr, int *fd);
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
-					struct platform_device *pdev);
-void msm_vfe_subdev_release(struct platform_device *pdev);
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+			struct msm_cam_media_controller *mctl);
+void msm_vfe_subdev_release(struct v4l2_subdev *sd);
 
 int msm_isp_subdev_ioctl(struct v4l2_subdev *sd,
 	struct msm_vfe_cfg_cmd *cfgcmd, void *data);
-int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
-	struct platform_device *pdev);
-int msm_gemini_subdev_init(struct v4l2_subdev *sd);
-void msm_vpe_subdev_release(struct platform_device *pdev);
+int msm_vpe_subdev_init(struct v4l2_subdev *sd,
+			struct msm_cam_media_controller *mctl);
+int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
+void msm_vpe_subdev_release(void);
 void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
 int msm_isp_subdev_ioctl_vpe(struct v4l2_subdev *isp_subdev,
 	struct msm_mctl_pp_cmd *cmd, void *data);
@@ -549,6 +553,11 @@
 int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
 					void __user *arg);
 void msm_release_ion_client(struct kref *ref);
+int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
+			enum msm_cam_subdev_type sdev_type, uint8_t index);
+uint32_t msm_camera_get_mctl_handle(void);
+struct msm_cam_media_controller *msm_camera_get_mctl(uint32_t handle);
+void msm_camera_free_mctl(uint32_t handle);
 #endif /* __KERNEL__ */
 
 #endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 59e37dd..9ab4895 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -150,9 +150,9 @@
 	struct msm_free_buf free_buf, temp_free_buf;
 	struct msm_camvfe_params vfe_params;
 	struct msm_vfe_cfg_cmd cfgcmd;
-	struct msm_sync *sync =
-		(struct msm_sync *)v4l2_get_subdev_hostdata(sd);
-	struct msm_cam_v4l2_device *pcam = sync->pcam_sync;
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
 
 	int vfe_id = vdata->evt_msg.msg_id;
 	if (!pcam) {
@@ -161,7 +161,7 @@
 		return rc;
 	}
 	/* Convert the vfe msg to the image mode */
-	image_mode = msm_isp_vfe_msg_to_img_mode(&pcam->mctl, vfe_id);
+	image_mode = msm_isp_vfe_msg_to_img_mode(pmctl, vfe_id);
 	BUG_ON(image_mode < 0);
 	switch (vdata->type) {
 	case VFE_MSG_V32_START:
@@ -169,14 +169,14 @@
 	case VFE_MSG_V2X_PREVIEW:
 		D("%s Got V32_START_*: Getting ping addr id = %d",
 						__func__, vfe_id);
-		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+		msm_mctl_reserve_free_buf(pmctl, NULL,
 					image_mode, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
 		cfgcmd.value = &vfe_id;
 		vfe_params.vfe_cfg = &cfgcmd;
 		vfe_params.data = (void *)&free_buf;
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
-		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+		msm_mctl_reserve_free_buf(pmctl, NULL,
 					image_mode, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
 		cfgcmd.value = &vfe_id;
@@ -188,7 +188,7 @@
 	case VFE_MSG_V2X_CAPTURE:
 		pr_debug("%s Got V32_CAPTURE: getting buffer for id = %d",
 						__func__, vfe_id);
-		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+		msm_mctl_reserve_free_buf(pmctl, NULL,
 					image_mode, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
 		cfgcmd.value = &vfe_id;
@@ -196,7 +196,7 @@
 		vfe_params.data = (void *)&free_buf;
 		rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
 		temp_free_buf = free_buf;
-		if (msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+		if (msm_mctl_reserve_free_buf(pmctl, NULL,
 					image_mode, &free_buf)) {
 			/* Write the same buffer into PONG */
 			free_buf = temp_free_buf;
@@ -234,7 +234,7 @@
 	case VFE_MSG_OUTPUT_IRQ:
 		D("%s Got OUTPUT_IRQ: Getting free buf id = %d",
 						__func__, vfe_id);
-		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+		msm_mctl_reserve_free_buf(pmctl, NULL,
 					image_mode, &free_buf);
 		cfgcmd.cmd_type = CMD_CONFIG_FREE_BUF_ADDR;
 		cfgcmd.value = &vfe_id;
@@ -259,12 +259,11 @@
 	int rc = 0;
 	struct v4l2_event v4l2_evt;
 	struct msm_isp_event_ctrl *isp_event;
-	struct msm_sync *sync =
-		(struct msm_sync *)v4l2_get_subdev_hostdata(sd);
-	struct msm_cam_media_controller *pmctl = &sync->pcam_sync->mctl;
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct msm_free_buf buf;
 
-	if (!sync) {
+	if (!pmctl) {
 		pr_err("%s: no context in dsp callback.\n", __func__);
 		rc = -EINVAL;
 		return rc;
@@ -347,17 +346,17 @@
 		struct msm_stats_buf *stats_buf = NULL;
 
 		isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE;
-		stats->aec.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+		stats->aec.buff = msm_pmem_stats_ptov_lookup(pmctl,
 					stats->aec.buff, &(stats->aec.fd));
-		stats->awb.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+		stats->awb.buff = msm_pmem_stats_ptov_lookup(pmctl,
 					stats->awb.buff, &(stats->awb.fd));
-		stats->af.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+		stats->af.buff = msm_pmem_stats_ptov_lookup(pmctl,
 					stats->af.buff, &(stats->af.fd));
-		stats->ihist.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+		stats->ihist.buff = msm_pmem_stats_ptov_lookup(pmctl,
 					stats->ihist.buff, &(stats->ihist.fd));
-		stats->rs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+		stats->rs.buff = msm_pmem_stats_ptov_lookup(pmctl,
 					stats->rs.buff, &(stats->rs.fd));
-		stats->cs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+		stats->cs.buff = msm_pmem_stats_ptov_lookup(pmctl,
 					stats->cs.buff, &(stats->cs.fd));
 
 		stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC);
@@ -379,7 +378,7 @@
 		isp_event->isp_data.isp_msg.msg_id = isp_stats->id;
 		isp_event->isp_data.isp_msg.frame_id =
 			isp_stats->frameCounter;
-		stats.buffer = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+		stats.buffer = msm_pmem_stats_ptov_lookup(pmctl,
 						isp_stats->buffer,
 						&(stats.fd));
 		switch (isp_stats->id) {
@@ -450,15 +449,15 @@
 
 static int msm_isp_notify_vpe(struct v4l2_subdev *sd, void *arg)
 {
-	struct msm_sync *sync =
-		(struct msm_sync *)v4l2_get_subdev_hostdata(sd);
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
-	if (sync == NULL) {
+	if (pmctl == NULL) {
 		pr_err("%s: VPE subdev hostdata not set\n", __func__);
 		return -EINVAL;
 	}
 
-	msm_mctl_pp_notify(&sync->pcam_sync->mctl,
+	msm_mctl_pp_notify(pmctl,
 		(struct msm_mctl_pp_frame_info *)vdata->extdata);
 	return 0;
 }
@@ -474,25 +473,24 @@
 
 /* This function is called by open() function, so we need to init HW*/
 static int msm_isp_open(struct v4l2_subdev *sd,
-	struct v4l2_subdev *sd_vpe, struct v4l2_subdev *gemini_sdev,
-	struct msm_sync *sync)
+	struct v4l2_subdev *sd_vpe,
+	struct msm_cam_media_controller *mctl)
 {
 	/* init vfe and senor, register sync callbacks for init*/
 	int rc = 0;
 	D("%s\n", __func__);
-	if (!sync) {
+	if (!mctl) {
 		pr_err("%s: param is NULL", __func__);
 		return -EINVAL;
 	}
 
-
-	rc = msm_vfe_subdev_init(sd, sync, sync->pdev);
+	rc = msm_vfe_subdev_init(sd, mctl);
 	if (rc < 0) {
 		pr_err("%s: vfe_init failed at %d\n",
 					__func__, rc);
 	}
 	D("%s: init vpe subdev", __func__);
-	rc = msm_vpe_subdev_init(sd_vpe, sync, sync->pdev);
+	rc = msm_vpe_subdev_init(sd_vpe, mctl);
 	if (rc < 0) {
 		pr_err("%s: vpe_init failed at %d\n",
 					__func__, rc);
@@ -500,16 +498,16 @@
 	return rc;
 }
 
-static void msm_isp_release(struct msm_sync *psync,
-		struct v4l2_subdev *gemini_sdev)
+static void msm_isp_release(
+	struct v4l2_subdev *sd)
 {
 	D("%s\n", __func__);
-	msm_vfe_subdev_release(psync->pdev);
-	msm_vpe_subdev_release(psync->pdev);
+	msm_vfe_subdev_release(sd);
+	msm_vpe_subdev_release();
 }
 
 static int msm_config_vfe(struct v4l2_subdev *sd,
-	struct msm_sync *sync, void __user *arg)
+	struct msm_cam_media_controller *mctl, void __user *arg)
 {
 	struct msm_vfe_cfg_cmd cfgcmd;
 	struct msm_pmem_region region[8];
@@ -525,9 +523,10 @@
 	switch (cfgcmd.cmd_type) {
 	case CMD_STATS_AF_ENABLE:
 		axi_data.bufnum1 =
-			msm_pmem_region_lookup(&sync->pmem_stats,
-					MSM_PMEM_AF, &region[0],
-					NUM_STAT_OUTPUT_BUFFERS);
+			msm_pmem_region_lookup(
+				&mctl->stats_info.pmem_stats_list,
+				MSM_PMEM_AF, &region[0],
+				NUM_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
 			pr_err("%s %d: pmem region lookup error\n",
 				__func__, __LINE__);
@@ -538,9 +537,10 @@
 							&axi_data);
 	case CMD_STATS_AEC_ENABLE:
 		axi_data.bufnum1 =
-			msm_pmem_region_lookup(&sync->pmem_stats,
-			MSM_PMEM_AEC, &region[0],
-			NUM_STAT_OUTPUT_BUFFERS);
+			msm_pmem_region_lookup(
+				&mctl->stats_info.pmem_stats_list,
+				MSM_PMEM_AEC, &region[0],
+				NUM_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
 			pr_err("%s %d: pmem region lookup error\n",
 				__func__, __LINE__);
@@ -551,9 +551,10 @@
 							&axi_data);
 	case CMD_STATS_AWB_ENABLE:
 		axi_data.bufnum1 =
-			msm_pmem_region_lookup(&sync->pmem_stats,
-			MSM_PMEM_AWB, &region[0],
-			NUM_STAT_OUTPUT_BUFFERS);
+			msm_pmem_region_lookup(
+				&mctl->stats_info.pmem_stats_list,
+				MSM_PMEM_AWB, &region[0],
+				NUM_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
 			pr_err("%s %d: pmem region lookup error\n",
 				__func__, __LINE__);
@@ -564,9 +565,10 @@
 							&axi_data);
 	case CMD_STATS_AEC_AWB_ENABLE:
 		axi_data.bufnum1 =
-			msm_pmem_region_lookup(&sync->pmem_stats,
-			MSM_PMEM_AEC_AWB, &region[0],
-			NUM_STAT_OUTPUT_BUFFERS);
+			msm_pmem_region_lookup(
+				&mctl->stats_info.pmem_stats_list,
+				MSM_PMEM_AEC_AWB, &region[0],
+				NUM_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
 			pr_err("%s %d: pmem region lookup error\n",
 				__func__, __LINE__);
@@ -577,9 +579,10 @@
 							&axi_data);
 	case CMD_STATS_IHIST_ENABLE:
 		axi_data.bufnum1 =
-			msm_pmem_region_lookup(&sync->pmem_stats,
-			MSM_PMEM_IHIST, &region[0],
-			NUM_STAT_OUTPUT_BUFFERS);
+			msm_pmem_region_lookup(
+				&mctl->stats_info.pmem_stats_list,
+				MSM_PMEM_IHIST, &region[0],
+				NUM_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
 			pr_err("%s %d: pmem region lookup error\n",
 				__func__, __LINE__);
@@ -590,9 +593,10 @@
 							&axi_data);
 	case CMD_STATS_RS_ENABLE:
 		axi_data.bufnum1 =
-			msm_pmem_region_lookup(&sync->pmem_stats,
-			MSM_PMEM_RS, &region[0],
-			NUM_STAT_OUTPUT_BUFFERS);
+			msm_pmem_region_lookup(
+				&mctl->stats_info.pmem_stats_list,
+				MSM_PMEM_RS, &region[0],
+				NUM_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
 			pr_err("%s %d: pmem region lookup error\n",
 				__func__, __LINE__);
@@ -603,9 +607,10 @@
 							&axi_data);
 	case CMD_STATS_CS_ENABLE:
 		axi_data.bufnum1 =
-			msm_pmem_region_lookup(&sync->pmem_stats,
-			MSM_PMEM_CS, &region[0],
-			NUM_STAT_OUTPUT_BUFFERS);
+			msm_pmem_region_lookup(
+				&mctl->stats_info.pmem_stats_list,
+				MSM_PMEM_CS, &region[0],
+				NUM_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
 			pr_err("%s %d: pmem region lookup error\n",
 				__func__, __LINE__);
@@ -626,51 +631,8 @@
 	return -EINVAL;
 }
 
-static int msm_vpe_frame_cfg(struct msm_sync *sync,
-				void *cfgcmdin)
-{
-	int rc = -EIO;
-	struct axidata axi_data;
-	void *data = &axi_data;
-	struct msm_pmem_region region[8];
-	int pmem_type;
-
-	struct msm_vpe_cfg_cmd *cfgcmd;
-	cfgcmd = (struct msm_vpe_cfg_cmd *)cfgcmdin;
-
-	memset(&axi_data, 0, sizeof(axi_data));
-	CDBG("In vpe_frame_cfg cfgcmd->cmd_type = %d\n",
-		cfgcmd->cmd_type);
-	switch (cfgcmd->cmd_type) {
-	case CMD_AXI_CFG_VPE:
-		pmem_type = MSM_PMEM_VIDEO_VPE;
-		axi_data.bufnum1 =
-			msm_pmem_region_lookup_2(&sync->pmem_frames, pmem_type,
-								&region[0], 8);
-		CDBG("axi_data.bufnum1 = %d\n", axi_data.bufnum1);
-		if (!axi_data.bufnum1) {
-			pr_err("%s %d: pmem region lookup error\n",
-				__func__, __LINE__);
-			return -EINVAL;
-		}
-		pmem_type = MSM_PMEM_VIDEO;
-		break;
-	default:
-		pr_err("%s: unknown command type %d\n",
-			__func__, cfgcmd->cmd_type);
-		break;
-	}
-	axi_data.region = &region[0];
-	CDBG("out vpe_frame_cfg cfgcmd->cmd_type = %d\n",
-		cfgcmd->cmd_type);
-	/* send the AXI configuration command to driver */
-	if (sync->vpefn.vpe_config)
-		rc = sync->vpefn.vpe_config(cfgcmd, data);
-	return rc;
-}
-
 static int msm_stats_axi_cfg(struct v4l2_subdev *sd,
-		struct msm_sync *sync, struct msm_vfe_cfg_cmd *cfgcmd)
+	struct msm_cam_media_controller *mctl, struct msm_vfe_cfg_cmd *cfgcmd)
 {
 	int rc = -EIO;
 	struct axidata axi_data;
@@ -695,7 +657,8 @@
 
 	if (cfgcmd->cmd_type != CMD_GENERAL) {
 		axi_data.bufnum1 =
-			msm_pmem_region_lookup(&sync->pmem_stats, pmem_type,
+			msm_pmem_region_lookup(
+				&mctl->stats_info.pmem_stats_list, pmem_type,
 				&region[0], NUM_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
 			pr_err("%s %d: pmem region lookup error\n",
@@ -711,7 +674,7 @@
 }
 
 static int msm_axi_config(struct v4l2_subdev *sd,
-			struct msm_sync *sync, void __user *arg)
+		struct msm_cam_media_controller *mctl, void __user *arg)
 {
 	struct msm_vfe_cfg_cmd cfgcmd;
 
@@ -739,13 +702,10 @@
 		 * controller free queue.
 		 */
 		return msm_isp_subdev_ioctl(sd, &cfgcmd, NULL);
-	case CMD_AXI_CFG_VPE:
-		return 0;
-		return msm_vpe_frame_cfg(sync, (void *)&cfgcmd);
 
 	case CMD_STATS_AXI_CFG:
 	case CMD_STATS_AF_AXI_CFG:
-		return msm_stats_axi_cfg(sd, sync, &cfgcmd);
+		return msm_stats_axi_cfg(sd, mctl, &cfgcmd);
 
 	default:
 		pr_err("%s: unknown command type %d\n",
@@ -757,39 +717,8 @@
 	return 0;
 }
 
-static int msm_set_crop(struct msm_sync *sync, void __user *arg)
-{
-	struct crop_info crop;
-
-	if (copy_from_user(&crop,
-				arg,
-				sizeof(struct crop_info))) {
-		ERR_COPY_FROM_USER();
-		return -EFAULT;
-	}
-
-	if (!sync->croplen) {
-		sync->cropinfo = kmalloc(crop.len, GFP_KERNEL);
-		if (!sync->cropinfo)
-			return -ENOMEM;
-	} else if (sync->croplen < crop.len)
-		return -EINVAL;
-
-	if (copy_from_user(sync->cropinfo,
-				crop.info,
-				crop.len)) {
-		ERR_COPY_FROM_USER();
-		kfree(sync->cropinfo);
-		return -EFAULT;
-	}
-
-	sync->croplen = crop.len;
-
-	return 0;
-}
-
 static int msm_put_stats_buffer(struct v4l2_subdev *sd,
-			struct msm_sync *sync, void __user *arg)
+			struct msm_cam_media_controller *mctl, void __user *arg)
 {
 	int rc = -EIO;
 
@@ -804,7 +733,7 @@
 	}
 
 	CDBG("%s\n", __func__);
-	pphy = msm_pmem_stats_vtop_lookup(sync, buf.buffer, buf.fd);
+	pphy = msm_pmem_stats_vtop_lookup(mctl, buf.buffer, buf.fd);
 
 	if (pphy != 0) {
 		if (buf.type == STAT_AF)
@@ -862,7 +791,7 @@
 
 	case MSM_CAM_IOCTL_CONFIG_VFE:
 		/* Coming from config thread for update */
-		rc = msm_config_vfe(sd, &pmctl->sync, argp);
+		rc = msm_config_vfe(sd, pmctl, argp);
 		break;
 
 	case MSM_CAM_IOCTL_CONFIG_VPE:
@@ -874,15 +803,11 @@
 	case MSM_CAM_IOCTL_AXI_CONFIG:
 	case MSM_CAM_IOCTL_AXI_VPE_CONFIG:
 		D("Received MSM_CAM_IOCTL_AXI_CONFIG\n");
-		rc = msm_axi_config(sd, &pmctl->sync, argp);
-		break;
-
-	case MSM_CAM_IOCTL_SET_CROP:
-		rc = msm_set_crop(&pmctl->sync, argp);
+		rc = msm_axi_config(sd, pmctl, argp);
 		break;
 
 	case MSM_CAM_IOCTL_RELEASE_STATS_BUFFER:
-		rc = msm_put_stats_buffer(sd, &pmctl->sync, argp);
+		rc = msm_put_stats_buffer(sd, pmctl, argp);
 		break;
 
 	default:
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 37a1ff2..1f6f32a 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -33,6 +33,7 @@
 #include "msm_csiphy.h"
 #include "msm_ispif.h"
 #include "msm_sensor.h"
+#include "msm_actuator.h"
 
 #ifdef CONFIG_MSM_CAMERA_DEBUG
 #define D(fmt, args...) pr_debug("msm_mctl: " fmt, ##args)
@@ -127,57 +128,14 @@
 
 };
 
-/*
- *  V4l2 subdevice operations
- */
-static	int mctl_subdev_log_status(struct v4l2_subdev *sd)
-{
-	return -EINVAL;
-}
-
-static long mctl_subdev_ioctl(struct v4l2_subdev *sd,
-				 unsigned int cmd, void *arg)
-{
-	struct msm_cam_media_controller *pmctl = NULL;
-	if (!sd) {
-		pr_err("%s: param is NULL", __func__);
-		return -EINVAL;
-	} else
-		pmctl = (struct msm_cam_media_controller *)
-		v4l2_get_subdevdata(sd);
-
-
-	return -EINVAL;
-}
-
-
-static int mctl_subdev_g_mbus_fmt(struct v4l2_subdev *sd,
-					 struct v4l2_mbus_framefmt *mf)
-{
-	return -EINVAL;
-}
-
-static struct v4l2_subdev_core_ops mctl_subdev_core_ops = {
-	.log_status = mctl_subdev_log_status,
-	.ioctl = mctl_subdev_ioctl,
-};
-
-static struct v4l2_subdev_video_ops mctl_subdev_video_ops = {
-	.g_mbus_fmt = mctl_subdev_g_mbus_fmt,
-};
-
-static struct v4l2_subdev_ops mctl_subdev_ops = {
-	.core = &mctl_subdev_core_ops,
-	.video  = &mctl_subdev_video_ops,
-};
-
-static int msm_get_sensor_info(struct msm_sync *sync,
-				void __user *arg)
+static int msm_get_sensor_info(
+	struct msm_cam_media_controller *mctl,
+	void __user *arg)
 {
 	int rc = 0;
 	struct msm_camsensor_info info;
 	struct msm_camera_sensor_info *sdata;
-	struct msm_cam_v4l2_device *pcam = sync->pcam_sync;
+	struct msm_cam_v4l2_device *pcam = mctl->pcam_ptr;
 	if (copy_from_user(&info,
 			arg,
 			sizeof(struct msm_camsensor_info))) {
@@ -185,7 +143,7 @@
 		return -EFAULT;
 	}
 
-	sdata = sync->sdata;
+	sdata = mctl->sdata;
 	D("%s: sensor_name %s\n", __func__, sdata->sensor_name);
 
 	memcpy(&info.name[0], sdata->sensor_name, MAX_SENSOR_NAME);
@@ -209,110 +167,6 @@
 	return rc;
 }
 
-/* called by other subdev to notify any changes*/
-
-static int msm_mctl_notify(struct msm_cam_media_controller *p_mctl,
-	unsigned int notification, void *arg)
-{
-	int rc = -EINVAL;
-	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
-	struct msm_camera_sensor_info *sinfo =
-		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
-	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-	uint8_t csid_core = camdev->csid_core;
-	switch (notification) {
-	case NOTIFY_CID_CHANGE:
-		/* reconfig the ISPIF*/
-		if (p_mctl->ispif_sdev) {
-			struct msm_ispif_params_list ispif_params;
-			ispif_params.len = 1;
-			ispif_params.params[0].intftype = PIX0;
-			ispif_params.params[0].cid_mask = 0x0001;
-			ispif_params.params[0].csid = csid_core;
-
-			rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
-				VIDIOC_MSM_ISPIF_CFG, &ispif_params);
-		} else {
-			pr_err("%s: invalid ispif_sdev\n", __func__);
-		}
-		break;
-	case NOTIFY_ISPIF_STREAM:
-		/* call ISPIF stream on/off */
-		if (p_mctl->ispif_sdev) {
-			rc = v4l2_subdev_call(p_mctl->ispif_sdev, video,
-					s_stream, (int)arg);
-		} else {
-			pr_err("%s: invalid ispif_sdev\n", __func__);
-		}
-
-		break;
-	case NOTIFY_ISP_MSG_EVT:
-	case NOTIFY_VFE_MSG_OUT:
-	case NOTIFY_VFE_MSG_STATS:
-	case NOTIFY_VFE_MSG_COMP_STATS:
-	case NOTIFY_VFE_BUF_EVT:
-	case NOTIFY_VFE_BUF_FREE_EVT:
-		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
-			rc = p_mctl->isp_sdev->isp_notify(
-				p_mctl->isp_sdev->sd, notification, arg);
-		} else {
-			pr_err("%s: invalid isp_sdev\n", __func__);
-		}
-
-		break;
-	case NOTIFY_VPE_MSG_EVT:
-		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
-			rc = p_mctl->isp_sdev->isp_notify(
-				p_mctl->isp_sdev->sd_vpe, notification, arg);
-		} else {
-			pr_err("%s: invalid isp_sdev\n", __func__);
-		}
-
-		break;
-	case NOTIFY_PCLK_CHANGE:
-		if (p_mctl->isp_sdev && p_mctl->isp_sdev->sd) {
-			rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
-					s_crystal_freq, *(uint32_t *)arg, 0);
-		} else {
-			pr_err("%s: invalid ispif_sdev\n", __func__);
-		}
-
-		break;
-	case NOTIFY_CSIPHY_CFG:
-		if (p_mctl->csiphy_sdev) {
-			rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
-					core, ioctl, VIDIOC_MSM_CSIPHY_CFG,
-					arg);
-		} else {
-			pr_err("%s: invalid csiphy_sdev\n", __func__);
-		}
-
-		break;
-	case NOTIFY_CSID_CFG:
-		if (p_mctl->csid_sdev) {
-			rc = v4l2_subdev_call(p_mctl->csid_sdev,
-					core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
-		} else {
-			pr_err("%s: invalid csid_sdev\n", __func__);
-		}
-
-		break;
-	case NOTIFY_CSIC_CFG:
-		if (p_mctl->csic_sdev) {
-			rc = v4l2_subdev_call(p_mctl->csic_sdev,
-					core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
-		} else {
-			pr_err("%s: invalid csic_sdev\n", __func__);
-		}
-
-		break;
-	default:
-		break;
-	}
-
-	return rc;
-}
-
 static int msm_mctl_set_vfe_output_mode(struct msm_cam_media_controller
 					*p_mctl, void __user *arg)
 {
@@ -345,7 +199,7 @@
 	switch (cmd) {
 		/* sensor config*/
 	case MSM_CAM_IOCTL_GET_SENSOR_INFO:
-			rc = msm_get_sensor_info(&p_mctl->sync, argp);
+			rc = msm_get_sensor_info(p_mctl, argp);
 			break;
 
 	case MSM_CAM_IOCTL_SENSOR_IO_CFG:
@@ -394,8 +248,6 @@
 
 	case MSM_CAM_IOCTL_GET_ACTUATOR_INFO: {
 		struct msm_actuator_cfg_data cdata;
-		CDBG("%s: act_config: %p\n", __func__,
-			p_mctl->sync.actctrl.a_config);
 		if (copy_from_user(&cdata,
 			(void *)argp,
 			sizeof(struct msm_actuator_cfg_data))) {
@@ -405,10 +257,10 @@
 		cdata.is_af_supported = 0;
 		rc = 0;
 
-		if (p_mctl->sync.actctrl.a_config) {
+		if (p_mctl->act_sdev) {
 			struct msm_camera_sensor_info *sdata;
 
-			sdata = p_mctl->sync.sdata;
+			sdata = p_mctl->sdata;
 			CDBG("%s: Act_cam_Name %d\n", __func__,
 				sdata->actuator_info->cam_name);
 
@@ -433,8 +285,9 @@
 
 	case MSM_CAM_IOCTL_ACTUATOR_IO_CFG: {
 		struct msm_actuator_cfg_data act_data;
-		if (p_mctl->sync.actctrl.a_config) {
-			rc = p_mctl->sync.actctrl.a_config(argp);
+		if (p_mctl->act_sdev) {
+			rc = v4l2_subdev_call(p_mctl->act_sdev,
+				core, ioctl, VIDIOC_MSM_ACTUATOR_CFG, argp);
 		} else {
 			rc = copy_from_user(
 				&act_data,
@@ -475,7 +328,7 @@
 			ERR_COPY_FROM_USER();
 			rc = -EFAULT;
 		} else {
-			rc = msm_flash_ctrl(p_mctl->sync.sdata, &flash_info);
+			rc = msm_flash_ctrl(p_mctl->sdata, &flash_info);
 		}
 		break;
 	}
@@ -671,7 +524,6 @@
 				 const char *const apps_id)
 {
 	int rc = 0;
-	struct msm_sync *sync = NULL;
 	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
 	struct msm_camera_sensor_info *sinfo =
 		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
@@ -683,14 +535,11 @@
 		return -EINVAL;
 	}
 
-	/* msm_sync_init() muct be called before*/
-	sync = &(p_mctl->sync);
-
-	mutex_lock(&sync->lock);
+	mutex_lock(&p_mctl->lock);
 	/* open sub devices - once only*/
-	if (!sync->opencnt) {
+	if (!p_mctl->opencnt) {
 		uint32_t csid_version;
-		wake_lock(&sync->wake_lock);
+		wake_lock(&p_mctl->wake_lock);
 
 		csid_core = camdev->csid_core;
 		rc = msm_mctl_register_subdevs(p_mctl, csid_core);
@@ -707,9 +556,9 @@
 			pr_err("%s: isp init failed: %d\n", __func__, rc);
 			goto msm_open_done;
 		}
-		if (sync->actctrl.a_power_up)
-			rc = sync->actctrl.a_power_up(
-				sync->sdata->actuator_info);
+		if (p_mctl->act_sdev)
+			rc = v4l2_subdev_call(p_mctl->act_sdev,
+					core, s_power, 1);
 
 		if (rc < 0) {
 			pr_err("%s: act power failed:%d\n", __func__, rc);
@@ -750,8 +599,7 @@
 			rc = p_mctl->isp_sdev->isp_open(
 				p_mctl->isp_sdev->sd,
 				p_mctl->isp_sdev->sd_vpe,
-				p_mctl->gemini_sdev,
-				sync);
+				p_mctl);
 		if (rc < 0) {
 			pr_err("%s: isp init failed: %d\n", __func__, rc);
 			goto msm_open_done;
@@ -774,12 +622,12 @@
 			pm_qos_update_request(&p_mctl->pm_qos_req_list,
 					MSM_V4L2_SWFI_LATENCY);
 		}
-		sync->apps_id = apps_id;
-		sync->opencnt++;
+		p_mctl->apps_id = apps_id;
+		p_mctl->opencnt++;
 	}
 
 msm_open_done:
-	mutex_unlock(&sync->lock);
+	mutex_unlock(&p_mctl->lock);
 	return rc;
 }
 
@@ -805,8 +653,8 @@
 	}
 
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
-		p_mctl->isp_sdev->isp_release(&p_mctl->sync,
-				p_mctl->gemini_sdev);
+		p_mctl->isp_sdev->isp_release(
+			p_mctl->isp_sdev->sd);
 
 	if (camdev->is_csid) {
 		v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
@@ -823,19 +671,19 @@
 				PM_QOS_DEFAULT_VALUE);
 		pm_qos_remove_request(&p_mctl->pm_qos_req_list);
 	}
-	if (p_mctl->sync.actctrl.a_power_down)
-		p_mctl->sync.actctrl.a_power_down(
-			p_mctl->sync.sdata->actuator_info);
+
+	if (p_mctl->act_sdev)
+		v4l2_subdev_call(p_mctl->act_sdev, core, s_power, 0);
 
 	v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
 
-	wake_unlock(&p_mctl->sync.wake_lock);
+	wake_unlock(&p_mctl->wake_lock);
 	return rc;
 }
 
 int msm_mctl_init_user_formats(struct msm_cam_v4l2_device *pcam)
 {
-	struct v4l2_subdev *sd = pcam->mctl.sensor_sdev;
+	struct v4l2_subdev *sd = pcam->sensor_sdev;
 	enum v4l2_mbus_pixelcode pxlcode;
 	int numfmt_sensor = 0;
 	int numfmt = 0;
@@ -893,35 +741,69 @@
 }
 
 /* this function plug in the implementation of a v4l2_subdev */
-int msm_mctl_init_module(struct msm_cam_v4l2_device *pcam)
+int msm_mctl_init(struct msm_cam_v4l2_device *pcam)
 {
 	struct msm_cam_media_controller *pmctl = NULL;
 	D("%s\n", __func__);
 	if (!pcam) {
 		pr_err("%s: param is NULL", __func__);
 		return -EINVAL;
-	} else
-		pmctl = &pcam->mctl;
+	}
+	pcam->mctl_handle = msm_camera_get_mctl_handle();
+	if (pcam->mctl_handle == 0) {
+		pr_err("%s: cannot get mctl handle", __func__);
+		return -EINVAL;
+	}
 
-	pmctl->sync.opencnt = 0;
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s: invalid mctl controller", __func__);
+		return -EINVAL;
+	}
+
+	wake_lock_init(&pmctl->wake_lock, WAKE_LOCK_IDLE, "msm_camera");
+	mutex_init(&pmctl->lock);
+	pmctl->opencnt = 0;
 
 	/* init module operations*/
 	pmctl->mctl_open = msm_mctl_open;
 	pmctl->mctl_cmd = msm_mctl_cmd;
-	pmctl->mctl_notify = msm_mctl_notify;
 	pmctl->mctl_release = msm_mctl_release;
 	/* init mctl buf */
 	msm_mctl_buf_init(pcam);
 	memset(&pmctl->pp_info, 0, sizeof(pmctl->pp_info));
 	pmctl->vfe_output_mode = 0;
 	spin_lock_init(&pmctl->pp_info.lock);
-	/* init sub device*/
-	v4l2_subdev_init(&(pmctl->mctl_sdev), &mctl_subdev_ops);
-	v4l2_set_subdevdata(&(pmctl->mctl_sdev), pmctl);
+
+	pmctl->act_sdev = pcam->act_sdev;
+	pmctl->sensor_sdev = pcam->sensor_sdev;
+	pmctl->sdata = pcam->sdata;
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	pmctl->client = msm_ion_client_create(-1, "camera");
+	kref_init(&pmctl->refcount);
+#endif
 
 	return 0;
 }
 
+int msm_mctl_free(struct msm_cam_v4l2_device *pcam)
+{
+	int rc = 0;
+	struct msm_cam_media_controller *pmctl = NULL;
+	D("%s\n", __func__);
+
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s: invalid mctl controller", __func__);
+		return -EINVAL;
+	}
+
+	mutex_destroy(&pmctl->lock);
+	wake_lock_destroy(&pmctl->wake_lock);
+	msm_camera_free_mctl(pcam->mctl_handle);
+	return rc;
+}
 
 /* mctl node v4l2_file_operations */
 static int msm_mctl_dev_open(struct file *f)
@@ -930,6 +812,7 @@
 	/* get the video device */
 	struct msm_cam_v4l2_device *pcam  = NULL;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_media_controller *pmctl;
 	D("%s : E ", __func__);
 
 	if (f == NULL) {
@@ -942,6 +825,7 @@
 		pr_err("%s NULL pointer passed in!\n", __func__);
 		return rc;
 	}
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
 
 	mutex_lock(&pcam->mctl_node.dev_lock);
 	for (i = 0; i < MSM_DEV_INST_MAX; i++) {
@@ -966,7 +850,6 @@
 
 	D("%s pcam_inst %p my_index = %d\n", __func__,
 		pcam_inst, pcam_inst->my_index);
-	D("%s for %s\n", __func__, pcam->mctl.sensor_sdev->name);
 	rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
 					pcam->mctl_node.pvdev);
 	if (rc < 0) {
@@ -974,7 +857,7 @@
 		return rc;
 	}
 	pcam_inst->vbqueue_initialized = 0;
-	kref_get(&pcam->mctl.refcount);
+	kref_get(&pmctl->refcount);
 	f->private_data = &pcam_inst->eventHandle;
 
 	D("f->private_data = 0x%x, pcam = 0x%x\n",
@@ -1024,6 +907,7 @@
 	int rc = 0;
 	struct msm_cam_v4l2_device *pcam;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_media_controller *pmctl;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
 	pcam = pcam_inst->pcam;
@@ -1034,6 +918,7 @@
 		return -EINVAL;
 	}
 
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
 	mutex_lock(&pcam->mctl_node.dev_lock);
 	pcam_inst->streamon = 0;
 	pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] = NULL;
@@ -1045,7 +930,7 @@
 	v4l2_fh_exit(&pcam_inst->eventHandle);
 
 	kfree(pcam_inst);
-	kref_put(&pcam->mctl.refcount, msm_release_ion_client);
+	kref_put(&pmctl->refcount, msm_release_ion_client);
 	f->private_data = NULL;
 	mutex_unlock(&pcam->mctl_node.dev_lock);
 	D("%s : X ", __func__);
@@ -1085,8 +970,8 @@
 		return -EINVAL;
 	}
 
-	strlcpy(pcaps->driver, pcam->mctl.sensor_sdev->name,
-		sizeof(pcaps->driver));
+	strlcpy(pcaps->driver, pcam->media_dev.dev->driver->name,
+			sizeof(pcaps->driver));
 	pcaps->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 	return 0;
 }
@@ -1437,6 +1322,7 @@
 	int rc = 0;
 	/* get the video device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
+	struct msm_cam_media_controller *pmctl;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 		struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -1447,8 +1333,9 @@
 		(void *)pfmt->fmt.pix.priv);
 	WARN_ON(pctx != f->private_data);
 
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
 	if (!pcam_inst->vbqueue_initialized) {
-		pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+		pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE);
 		pcam_inst->vbqueue_initialized = 1;
 	}
@@ -1461,6 +1348,7 @@
 {
 	int rc = 0, i;
 	struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+	struct msm_cam_media_controller *pmctl;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	pcam_inst = container_of(f->private_data,
 			struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -1469,8 +1357,9 @@
 		pcam_inst, pcam_inst->vbqueue_initialized);
 	WARN_ON(pctx != f->private_data);
 
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
 	if (!pcam_inst->vbqueue_initialized) {
-		pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+		pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 		pcam_inst->vbqueue_initialized = 1;
 	}
@@ -1657,7 +1546,7 @@
 {
 	int rc = -EINVAL;
 	struct video_device *pvdev = NULL;
-	struct i2c_client *client = v4l2_get_subdevdata(pcam->mctl.sensor_sdev);
+	struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
 
 	D("%s\n", __func__);
 
@@ -1679,11 +1568,11 @@
 
 	/* init video device's driver interface */
 	D("sensor name = %s, sizeof(pvdev->name)=%d\n",
-			pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
+			pcam->sensor_sdev->name, sizeof(pvdev->name));
 
 	/* device info - strlcpy is safer than strncpy but
 	   only if architecture supports*/
-	strlcpy(pvdev->name, pcam->mctl.sensor_sdev->name,
+	strlcpy(pvdev->name, pcam->sensor_sdev->name,
 			sizeof(pvdev->name));
 
 	pvdev->release   = video_device_release;
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 8148f1f..5bc81a7 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -75,6 +75,7 @@
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	struct msm_cam_v4l2_device *pcam;
+	struct msm_cam_media_controller *pmctl;
 	struct videobuf2_contig_pmem *mem;
 	struct vb2_queue	*vq;
 	uint32_t buf_idx;
@@ -112,6 +113,7 @@
 			pcam_inst->plane_info.plane[0].offset;
 	}
 	buf_idx = vb->v4l2_buf.index;
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
 	for (i = 0; i < vb->num_planes; i++) {
 		mem = vb2_plane_cookie(vb, i);
 		if (buf_type == VIDEOBUF2_MULTIPLE_PLANES)
@@ -122,7 +124,7 @@
 			rc = videobuf2_pmem_contig_user_get(mem, &offset,
 				buf_type,
 				pcam_inst->buf_offset[buf_idx][i].addr_offset,
-				pcam_inst->path, pcam->mctl.client);
+				pcam_inst->path, pmctl->client);
 		else
 			rc = videobuf2_pmem_contig_mmap_get(mem, &offset,
 				buf_type, pcam_inst->path);
@@ -194,6 +196,7 @@
 static void msm_vb2_ops_buf_cleanup(struct vb2_buffer *vb)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
+	struct msm_cam_media_controller *pmctl;
 	struct msm_cam_v4l2_device *pcam;
 	struct videobuf2_contig_pmem *mem;
 	struct msm_frame_buffer *buf, *tmp;
@@ -248,9 +251,10 @@
 		}
 		spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
 	}
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
 	for (i = 0; i < vb->num_planes; i++) {
 		mem = vb2_plane_cookie(vb, i);
-		videobuf2_pmem_contig_user_put(mem, pcam->mctl.client);
+		videobuf2_pmem_contig_user_put(mem, pmctl->client);
 	}
 	buf->state = MSM_BUFFER_STATE_UNUSED;
 }
@@ -328,12 +332,12 @@
 					int image_mode, int node_type)
 {
 	if ((image_mode >= 0) && node_type &&
-		pmctl->sync.pcam_sync->mctl_node.dev_inst_map[image_mode])
-		return pmctl->sync.pcam_sync->
+		pmctl->pcam_ptr->mctl_node.dev_inst_map[image_mode])
+		return pmctl->pcam_ptr->
 				mctl_node.dev_inst_map[image_mode]->my_index;
 	else if ((image_mode >= 0) &&
-		pmctl->sync.pcam_sync->dev_inst_map[image_mode])
-		return	pmctl->sync.pcam_sync->
+		pmctl->pcam_ptr->dev_inst_map[image_mode])
+		return	pmctl->pcam_ptr->
 				dev_inst_map[image_mode]->my_index;
 	else
 		return -EINVAL;
@@ -440,7 +444,7 @@
 				__func__);
 			return idx;
 		}
-		pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
+		pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
 		rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
 				image_mode, fbuf,
 				&frame_id, 1);
@@ -450,7 +454,9 @@
 
 int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam)
 {
-	pcam->mctl.mctl_vbqueue_init = msm_vbqueue_init;
+	struct msm_cam_media_controller *pmctl;
+	pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+	pmctl->mctl_vbqueue_init = msm_vbqueue_init;
 	return 0;
 }
 
@@ -475,7 +481,7 @@
 				int image_mode)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
-	struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
 	int idx;
 
 	if (image_mode >= 0) {
@@ -646,9 +652,9 @@
 		return idx;
 	}
 	if (node_type)
-		pcam_inst = pmctl->sync.pcam_sync->mctl_node.dev_inst[idx];
+		pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
 	else
-		pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+		pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
 	if (!pcam_inst) {
 		pr_err("%s Invalid instance, cannot send buf to user",
 			__func__);
@@ -682,7 +688,7 @@
 		pr_err("%s Invalid instance, cant get buffer\n", __func__);
 		return NULL;
 	}
-	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+	pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
 	if (!pcam_inst->streamon) {
 		D("%s: stream 0x%p is off\n", __func__, pcam_inst);
 		return NULL;
@@ -721,7 +727,7 @@
 		pr_err("%s Invalid instance, cant put buffer\n", __func__);
 		return idx;
 	}
-	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+	pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
 	if (!pcam_inst->streamon) {
 		D("%s: stream 0x%p is off\n", __func__, pcam_inst);
 		return rc;
@@ -756,7 +762,7 @@
 		pr_err("%s Invalid instance, cant delete buffer\n", __func__);
 		return idx;
 	}
-	pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+	pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
 	D("%s: idx = %d, pinst=0x%p", __func__, idx, pcam_inst);
 	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
 	if (!list_empty(&pcam_inst->free_vq)) {
@@ -780,7 +786,7 @@
 	int idx = 0;
 	struct msm_frame_buffer *buf = NULL;
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
-	struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
 	unsigned long flags = 0;
 
 	if (pcam->mctl_node.dev_inst_map[image_mode]) {
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 82c5bf7..2e46728 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -156,7 +156,7 @@
 		int image_mode, struct msm_free_buf *fbuf, int *node_type)
 {
 	struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
-	struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+	struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
 	int idx;
 
 	if (image_mode >= 0) {
@@ -559,14 +559,14 @@
 				zoom->pp_frame_cmd.cookie,
 				zoom->pp_frame_cmd.vpe_output_action,
 				zoom->pp_frame_cmd.path);
-		idx = msm_mctl_pp_path_to_inst_index(p_mctl->sync.pcam_sync,
+		idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr,
 			zoom->pp_frame_cmd.path);
 		if (idx < 0) {
 			pr_err("%s Invalid path, returning\n", __func__);
 			kfree(zoom);
 			return idx;
 		}
-		pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
+		pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
 		if (!pcam_inst) {
 			pr_err("%s Invalid instance, returning\n", __func__);
 			kfree(zoom);
@@ -809,7 +809,7 @@
 		return -EINVAL;
 	}
 	/* Always reserve the buffer from user's video node */
-	pcam_inst = p_mctl->sync.pcam_sync->dev_inst[image_mode];
+	pcam_inst = p_mctl->pcam_ptr->dev_inst[image_mode];
 	if (!pcam_inst) {
 		pr_err("%s Instance already closed ", __func__);
 		return -EINVAL;
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index 4f7e5d2..751626a 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -346,14 +346,15 @@
 }
 
 unsigned long msm_pmem_stats_vtop_lookup(
-				struct msm_sync *sync,
+				struct msm_cam_media_controller *mctl,
 				unsigned long buffer,
 				int fd)
 {
 	struct msm_pmem_region *region;
 	struct hlist_node *node, *n;
 
-	hlist_for_each_entry_safe(region, node, n, &sync->pmem_stats, list) {
+	hlist_for_each_entry_safe(region, node, n,
+	&mctl->stats_info.pmem_stats_list, list) {
 		if (((unsigned long)(region->info.vaddr) == buffer) &&
 						(region->info.fd == fd) &&
 						region->info.active == 0) {
@@ -365,13 +366,15 @@
 	return 0;
 }
 
-unsigned long msm_pmem_stats_ptov_lookup(struct msm_sync *sync,
-						unsigned long addr, int *fd)
+unsigned long msm_pmem_stats_ptov_lookup(
+		struct msm_cam_media_controller *mctl,
+		unsigned long addr, int *fd)
 {
 	struct msm_pmem_region *region;
 	struct hlist_node *node, *n;
 
-	hlist_for_each_entry_safe(region, node, n, &sync->pmem_stats, list) {
+	hlist_for_each_entry_safe(region, node, n,
+	&mctl->stats_info.pmem_stats_list, list) {
 		if (addr == region->paddr && region->info.active) {
 			/* offset since we could pass vaddr inside a
 			 * registered pmem buffer */
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index d60f4b7..90ba214 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -54,7 +54,6 @@
 #define CAMIF_CFG_RMSK             0x1fffff
 
 static struct vfe31_ctrl_type *vfe31_ctrl;
-static void  *vfe_syncdata;
 static uint32_t vfe_clk_rate;
 
 struct vfe31_isr_queue_cmd {
@@ -748,31 +747,26 @@
 	atomic_set(&vfe31_ctrl->vstate, 1);
 }
 
-static int vfe31_start_recording(void)
+static int vfe31_start_recording(struct msm_cam_media_controller *pmctl)
 {
-	struct msm_sync *sync = vfe_syncdata;
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
 	vfe31_ctrl->recording_state = VFE_STATE_START_REQUESTED;
 	msm_camera_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	return 0;
 }
 
-static int vfe31_stop_recording(void)
+static int vfe31_stop_recording(struct msm_cam_media_controller *pmctl)
 {
-	struct msm_sync *sync = vfe_syncdata;
 	vfe31_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
 	msm_camera_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	return 0;
 }
 
-static void vfe31_start_liveshot(void){
-	struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
-	if (p_sync)
-		p_sync->liveshot_enabled = true;
-
+static void vfe31_start_liveshot(struct msm_cam_media_controller *pmctl)
+{
 	/* Hardcode 1 live snapshot for now. */
 	vfe31_ctrl->outpath.out0.capture_cnt = 1;
 	vfe31_ctrl->vfe_capture_count = vfe31_ctrl->outpath.out0.capture_cnt;
@@ -781,9 +775,8 @@
 	msm_camera_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 }
 
-static int vfe31_zsl(void)
+static int vfe31_zsl(struct msm_cam_media_controller *pmctl)
 {
-	struct msm_sync *sync = vfe_syncdata;
 	uint32_t irq_comp_mask = 0;
 	/* capture command is valid for both idle and active state. */
 	irq_comp_mask	=
@@ -845,16 +838,17 @@
 	msm_camera_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	vfe31_start_common();
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_ZSL);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
 
 	msm_camera_io_w(1, vfe31_ctrl->vfebase + 0x18C);
 	msm_camera_io_w(1, vfe31_ctrl->vfebase + 0x188);
 	return 0;
 }
-static int vfe31_capture_raw(uint32_t num_frames_capture)
+static int vfe31_capture_raw(
+	struct msm_cam_media_controller *pmctl,
+	uint32_t num_frames_capture)
 {
 	uint32_t irq_comp_mask = 0;
-	struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
 
 	vfe31_ctrl->outpath.out0.capture_cnt = num_frames_capture;
 	vfe31_ctrl->vfe_capture_count = num_frames_capture;
@@ -870,19 +864,16 @@
 
 	msm_camera_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camio_bus_scale_cfg(
-		p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 	vfe31_start_common();
 	return 0;
 }
 
-static int vfe31_capture(uint32_t num_frames_capture)
+static int vfe31_capture(
+	struct msm_cam_media_controller *pmctl,
+	uint32_t num_frames_capture)
 {
 	uint32_t irq_comp_mask = 0;
-	struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
-	if (p_sync) {
-		p_sync->snap_count = num_frames_capture;
-		p_sync->thumb_count = num_frames_capture;
-	}
 	/* capture command is valid for both idle and active state. */
 	vfe31_ctrl->outpath.out1.capture_cnt = num_frames_capture;
 	if (vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
@@ -932,7 +923,7 @@
 	msm_camera_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camera_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camio_bus_scale_cfg(
-		p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 
 	vfe31_start_common();
 	/* for debug */
@@ -941,10 +932,9 @@
 	return 0;
 }
 
-static int vfe31_start(void)
+static int vfe31_start(struct msm_cam_media_controller *pmctl)
 {
 	uint32_t irq_comp_mask = 0;
-	struct msm_sync *sync = vfe_syncdata;
 
 	irq_comp_mask	=
 		msm_camera_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
@@ -1007,7 +997,7 @@
 		break;
 	}
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	vfe31_start_common();
 	return 0;
 }
@@ -1241,7 +1231,9 @@
 		NOTIFY_ISP_MSG_EVT, (void *)&isp_msg_evt);
 }
 
-static int vfe31_proc_general(struct msm_isp_cmd *cmd)
+static int vfe31_proc_general(
+	struct msm_cam_media_controller *pmctl,
+	struct msm_isp_cmd *cmd)
 {
 	int i , rc = 0;
 	uint32_t old_val = 0 , new_val = 0;
@@ -1278,7 +1270,7 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe31_start();
+		rc = vfe31_start(pmctl);
 		break;
 	case VFE_CMD_UPDATE:
 		vfe31_update();
@@ -1298,7 +1290,7 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe31_capture_raw(snapshot_cnt);
+		rc = vfe31_capture_raw(pmctl, snapshot_cnt);
 		break;
 	case VFE_CMD_CAPTURE:
 		if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
@@ -1339,7 +1331,7 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe31_capture(snapshot_cnt);
+		rc = vfe31_capture(pmctl, snapshot_cnt);
 		break;
 	case VFE_CMD_START_RECORDING:
 		pr_info("vfe31_proc_general: cmdID = %s\n",
@@ -1360,12 +1352,12 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe31_start_recording();
+		rc = vfe31_start_recording(pmctl);
 		break;
 	case VFE_CMD_STOP_RECORDING:
 		pr_info("vfe31_proc_general: cmdID = %s\n",
 			vfe31_general_cmd[cmd->id]);
-		rc = vfe31_stop_recording();
+		rc = vfe31_stop_recording(pmctl);
 		break;
 	case VFE_CMD_OPERATION_CFG:
 		if (cmd->length != V31_OPERATION_CFG_LEN) {
@@ -1756,7 +1748,7 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		vfe31_start_liveshot();
+		vfe31_start_liveshot(pmctl);
 		break;
 
 	case VFE_CMD_DEMOSAICV3:
@@ -2057,7 +2049,7 @@
 		if (rc < 0)
 			goto proc_general_done;
 
-		rc = vfe31_zsl();
+		rc = vfe31_zsl(pmctl);
 		break;
 
 	case VFE_CMD_ASF_CFG:
@@ -3316,6 +3308,8 @@
 static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int subdev_cmd, void *arg)
 {
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct msm_isp_cmd vfecmd;
 	struct msm_camvfe_params *vfe_params =
 		(struct msm_camvfe_params *)arg;
@@ -3419,7 +3413,7 @@
 	}
 	switch (cmd->cmd_type) {
 	case CMD_GENERAL: {
-		rc = vfe31_proc_general(&vfecmd);
+		rc = vfe31_proc_general(pmctl, &vfecmd);
 		}
 		break;
 	case CMD_CONFIG_PING_ADDR: {
@@ -3685,13 +3679,11 @@
 	usleep_range(10000, 15000);
 }
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
-	struct platform_device *pdev)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+		struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
-	struct msm_sync *sync = data;
-	v4l2_set_subdev_hostdata(sd, data);
-	vfe_syncdata = data;
+	v4l2_set_subdev_hostdata(sd, mctl);
 
 	spin_lock_init(&vfe31_ctrl->stop_flag_lock);
 	spin_lock_init(&vfe31_ctrl->state_lock);
@@ -3722,7 +3714,7 @@
 		pr_err("%s: vfe ioremap failed\n", __func__);
 		goto vfe_remap_failed;
 	}
-	if (!sync->sdata->csi_if) {
+	if (!mctl->sdata->csi_if) {
 		vfe31_ctrl->camifbase = ioremap(vfe31_ctrl->camifmem->start,
 			resource_size(vfe31_ctrl->camifmem));
 		if (!vfe31_ctrl->camifbase) {
@@ -3754,7 +3746,7 @@
 	if (rc < 0)
 		goto vfe_clk_enable_failed;
 
-	if (!sync->sdata->csi_if) {
+	if (!mctl->sdata->csi_if) {
 		rc = msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
 			vfe_camif_clk_info,
 			vfe31_ctrl->vfe_camif_clk,
@@ -3765,9 +3757,9 @@
 	}
 
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_INIT);
+		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	vfe31_ctrl->register_total = VFE31_REGISTER_TOTAL;
 
 	enable_irq(vfe31_ctrl->vfeirq->start);
@@ -3779,7 +3771,7 @@
 	regulator_put(vfe31_ctrl->fs_vfe);
 	vfe31_ctrl->fs_vfe = NULL;
 vfe_fs_failed:
-	if (!sync->sdata->csi_if)
+	if (!mctl->sdata->csi_if)
 		iounmap(vfe31_ctrl->camifbase);
 camif_remap_failed:
 	iounmap(vfe31_ctrl->vfebase);
@@ -3788,13 +3780,14 @@
 	return rc;
 }
 
-void msm_vfe_subdev_release(struct platform_device *pdev)
+void msm_vfe_subdev_release(struct v4l2_subdev *sd)
 {
-	struct msm_sync *sync = vfe_syncdata;
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	disable_irq(vfe31_ctrl->vfeirq->start);
 	tasklet_kill(&vfe31_tasklet);
 
-	if (!sync->sdata->csi_if)
+	if (!pmctl->sdata->csi_if)
 		msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
 			vfe_camif_clk_info,
 			vfe31_ctrl->vfe_camif_clk,
@@ -3808,7 +3801,7 @@
 		vfe31_ctrl->fs_vfe = NULL;
 	}
 	CDBG("%s, 31ee_irq\n", __func__);
-	if (!sync->sdata->csi_if)
+	if (!pmctl->sdata->csi_if)
 		iounmap(vfe31_ctrl->camifbase);
 	iounmap(vfe31_ctrl->vfebase);
 
@@ -3816,10 +3809,10 @@
 		pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
 
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_EXIT);
-	vfe_syncdata = NULL;
+		pmctl->sdata->pdata->cam_bus_scale_table, S_EXIT);
 }
 
+static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
 
 static int __devinit vfe31_probe(struct platform_device *pdev)
 {
@@ -3832,6 +3825,8 @@
 	}
 
 	v4l2_subdev_init(&vfe31_ctrl->subdev, &msm_vfe_subdev_ops);
+	vfe31_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
+	vfe31_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	snprintf(vfe31_ctrl->subdev.name,
 			 sizeof(vfe31_ctrl->subdev.name), "vfe3.1");
 	v4l2_set_subdevdata(&vfe31_ctrl->subdev, vfe31_ctrl);
@@ -3894,6 +3889,7 @@
 	disable_irq(vfe31_ctrl->vfeirq->start);
 
 	vfe31_ctrl->pdev = pdev;
+	msm_cam_register_subdev_node(&vfe31_ctrl->subdev, VFE_DEV, 0);
 	return 0;
 
 vfe31_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index b8344fb..0ce4983 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -48,7 +48,6 @@
 	vfe32_put_ch_ping_addr((chn), (addr)))
 
 static struct vfe32_ctrl_type *vfe32_ctrl;
-static void  *vfe_syncdata;
 static uint32_t vfe_clk_rate;
 
 struct vfe32_isr_queue_cmd {
@@ -726,31 +725,26 @@
 	atomic_set(&vfe32_ctrl->vstate, 1);
 }
 
-static int vfe32_start_recording(void)
+static int vfe32_start_recording(struct msm_cam_media_controller *pmctl)
 {
-	struct msm_sync *sync = vfe_syncdata;
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
 	vfe32_ctrl->recording_state = VFE_STATE_START_REQUESTED;
 	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	return 0;
 }
 
-static int vfe32_stop_recording(void)
+static int vfe32_stop_recording(struct msm_cam_media_controller *pmctl)
 {
-	struct msm_sync *sync = vfe_syncdata;
 	vfe32_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
 	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	return 0;
 }
 
-static void vfe32_start_liveshot(void){
-	struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
-	if (p_sync)
-		p_sync->liveshot_enabled = true;
-
+static void vfe32_start_liveshot(struct msm_cam_media_controller *pmctl)
+{
 	/* Hardcode 1 live snapshot for now. */
 	vfe32_ctrl->outpath.out0.capture_cnt = 1;
 	vfe32_ctrl->vfe_capture_count = vfe32_ctrl->outpath.out0.capture_cnt;
@@ -759,9 +753,8 @@
 	msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
 }
 
-static int vfe32_zsl(void)
+static int vfe32_zsl(struct msm_cam_media_controller *pmctl)
 {
-	struct msm_sync *sync = vfe_syncdata;
 	uint32_t irq_comp_mask = 0;
 	/* capture command is valid for both idle and active state. */
 	irq_comp_mask	=
@@ -823,16 +816,17 @@
 	msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	vfe32_start_common();
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_ZSL);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
 
 	msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x18C);
 	msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x188);
 	return 0;
 }
-static int vfe32_capture_raw(uint32_t num_frames_capture)
+static int vfe32_capture_raw(
+	struct msm_cam_media_controller *pmctl,
+	uint32_t num_frames_capture)
 {
 	uint32_t irq_comp_mask = 0;
-	struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
 
 	vfe32_ctrl->outpath.out0.capture_cnt = num_frames_capture;
 	vfe32_ctrl->vfe_capture_count = num_frames_capture;
@@ -848,19 +842,17 @@
 
 	msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camio_bus_scale_cfg(
-		p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 	vfe32_start_common();
 	return 0;
 }
 
-static int vfe32_capture(uint32_t num_frames_capture)
+static int vfe32_capture(
+	struct msm_cam_media_controller *pmctl,
+	uint32_t num_frames_capture)
 {
 	uint32_t irq_comp_mask = 0;
-	struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
-	if (p_sync) {
-		p_sync->snap_count = num_frames_capture;
-		p_sync->thumb_count = num_frames_capture;
-	}
+
 	/* capture command is valid for both idle and active state. */
 	vfe32_ctrl->outpath.out1.capture_cnt = num_frames_capture;
 	if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
@@ -910,7 +902,7 @@
 	msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
 	msm_camio_bus_scale_cfg(
-		p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
 
 	vfe32_start_common();
 	/* for debug */
@@ -919,10 +911,9 @@
 	return 0;
 }
 
-static int vfe32_start(void)
+static int vfe32_start(struct msm_cam_media_controller *pmctl)
 {
 	uint32_t irq_comp_mask = 0;
-	struct msm_sync *sync = vfe_syncdata;
 
 	irq_comp_mask	=
 		msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
@@ -986,7 +977,7 @@
 	}
 
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 	vfe32_start_common();
 	return 0;
 }
@@ -1259,7 +1250,9 @@
 			(void *)&isp_msg_evt);
 }
 
-static int vfe32_proc_general(struct msm_isp_cmd *cmd)
+static int vfe32_proc_general(
+	struct msm_cam_media_controller *pmctl,
+	struct msm_isp_cmd *cmd)
 {
 	int i , rc = 0;
 	uint32_t old_val = 0 , new_val = 0;
@@ -1296,7 +1289,7 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe32_start();
+		rc = vfe32_start(pmctl);
 		break;
 	case VFE_CMD_UPDATE:
 		vfe32_update();
@@ -1316,7 +1309,7 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe32_capture_raw(snapshot_cnt);
+		rc = vfe32_capture_raw(pmctl, snapshot_cnt);
 		break;
 	case VFE_CMD_CAPTURE:
 		if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
@@ -1357,7 +1350,7 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe32_capture(snapshot_cnt);
+		rc = vfe32_capture(pmctl, snapshot_cnt);
 		break;
 	case VFE_CMD_START_RECORDING:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
@@ -1378,12 +1371,12 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		rc = vfe32_start_recording();
+		rc = vfe32_start_recording(pmctl);
 		break;
 	case VFE_CMD_STOP_RECORDING:
 		pr_info("vfe32_proc_general: cmdID = %s\n",
 			vfe32_general_cmd[cmd->id]);
-		rc = vfe32_stop_recording();
+		rc = vfe32_stop_recording(pmctl);
 		break;
 	case VFE_CMD_OPERATION_CFG: {
 		if (cmd->length != V32_OPERATION_CFG_LEN) {
@@ -1793,7 +1786,7 @@
 			rc = -EINVAL;
 			goto proc_general_done;
 		}
-		vfe32_start_liveshot();
+		vfe32_start_liveshot(pmctl);
 		break;
 
 	case VFE_CMD_LINEARIZATION_CFG:
@@ -2242,7 +2235,7 @@
 		if (rc < 0)
 			goto proc_general_done;
 
-		rc = vfe32_zsl();
+		rc = vfe32_zsl(pmctl);
 		break;
 
 	case VFE_CMD_ASF_CFG:
@@ -3640,6 +3633,8 @@
 static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int subdev_cmd, void *arg)
 {
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct msm_isp_cmd vfecmd;
 	struct msm_camvfe_params *vfe_params =
 		(struct msm_camvfe_params *)arg;
@@ -3743,7 +3738,7 @@
 	}
 	switch (cmd->cmd_type) {
 	case CMD_GENERAL:
-		rc = vfe32_proc_general(&vfecmd);
+		rc = vfe32_proc_general(pmctl, &vfecmd);
 		break;
 
 	case CMD_CONFIG_PING_ADDR: {
@@ -3941,13 +3936,11 @@
 	.video = &msm_vfe_subdev_video_ops,
 };
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
-	struct platform_device *pdev)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+			struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
-	struct msm_sync *sync = data;
-	v4l2_set_subdev_hostdata(sd, data);
-	vfe_syncdata = data;
+	v4l2_set_subdev_hostdata(sd, mctl);
 
 	spin_lock_init(&vfe32_ctrl->stop_flag_lock);
 	spin_lock_init(&vfe32_ctrl->state_lock);
@@ -4004,9 +3997,9 @@
 		goto vfe_clk_enable_failed;
 
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_INIT);
+		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+		mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
 
 	if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
 		VFE32_HW_NUMBER)
@@ -4028,9 +4021,10 @@
 	return rc;
 }
 
-void msm_vfe_subdev_release(struct platform_device *pdev)
+void msm_vfe_subdev_release(struct v4l2_subdev *sd)
 {
-	struct msm_sync *sync = vfe_syncdata;
+	struct msm_cam_media_controller *pmctl =
+		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	CDBG("%s, free_irq\n", __func__);
 	disable_irq(vfe32_ctrl->vfeirq->start);
 	tasklet_kill(&vfe32_tasklet);
@@ -4048,10 +4042,11 @@
 		pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
 
 	msm_camio_bus_scale_cfg(
-		sync->sdata->pdata->cam_bus_scale_table, S_EXIT);
-	vfe_syncdata = NULL;
+		pmctl->sdata->pdata->cam_bus_scale_table, S_EXIT);
 }
 
+static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
+
 static int __devinit vfe32_probe(struct platform_device *pdev)
 {
 	int rc = 0;
@@ -4063,6 +4058,8 @@
 	}
 
 	v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
+	vfe32_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
+	vfe32_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	snprintf(vfe32_ctrl->subdev.name,
 			 sizeof(vfe32_ctrl->subdev.name), "vfe3.2");
 	v4l2_set_subdevdata(&vfe32_ctrl->subdev, vfe32_ctrl);
@@ -4104,6 +4101,7 @@
 	disable_irq(vfe32_ctrl->vfeirq->start);
 
 	vfe32_ctrl->pdev = pdev;
+	msm_cam_register_subdev_node(&vfe32_ctrl->subdev, VFE_DEV, 0);
 	return 0;
 
 vfe32_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index acd9158..40154ef 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -340,7 +340,6 @@
 static uint32_t extlen;
 
 struct mutex vfe_lock;
-static void     *vfe_syncdata;
 static int apps_reset;
 static uint8_t vfestopped;
 
@@ -1643,12 +1642,11 @@
 	{"vfe_clk", 192000000},
 };
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
-	struct platform_device *pdev)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+		struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
-	v4l2_set_subdev_hostdata(sd, data);
-	vfe_syncdata = data;
+	v4l2_set_subdev_hostdata(sd, mctl);
 
 	spin_lock_init(&vfe2x_ctrl->sd_notify_lock);
 	spin_lock_init(&vfe2x_ctrl->table_lock);
@@ -1702,24 +1700,24 @@
 	return rc;
 }
 
-int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
-	struct platform_device *pdev)
+int msm_vpe_subdev_init(struct v4l2_subdev *sd,
+			struct msm_cam_media_controller *mctl)
 {
 	return 0;
 }
 
-void msm_vpe_subdev_release(struct platform_device *pdev)
+void msm_vpe_subdev_release(void)
 {
 	return;
 }
 
-void msm_vfe_subdev_release(struct platform_device *pdev)
+void msm_vfe_subdev_release(struct v4l2_subdev *sd)
 {
 	CDBG("msm_cam_clk_enable: disable vfe_clk\n");
 	msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
 			vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 0);
-	vfe_syncdata = NULL;
 	apps_reset = 1;
+
 	msm_adsp_disable(qcam_mod);
 	msm_adsp_disable(vfe_mod);
 
@@ -1739,6 +1737,8 @@
 	.core = &msm_vfe_subdev_core_ops,
 };
 
+static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
+
 static int __devinit vfe2x_probe(struct platform_device *pdev)
 {
 	CDBG("%s: device id = %d\n", __func__, pdev->id);
@@ -1749,12 +1749,15 @@
 	}
 
 	v4l2_subdev_init(&vfe2x_ctrl->subdev, &msm_vfe_subdev_ops);
+	vfe2x_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
+	vfe2x_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	snprintf(vfe2x_ctrl->subdev.name,
 			 sizeof(vfe2x_ctrl->subdev.name), "vfe2.x");
 	v4l2_set_subdevdata(&vfe2x_ctrl->subdev, vfe2x_ctrl);
 	platform_set_drvdata(pdev, &vfe2x_ctrl->subdev);
 
 	vfe2x_ctrl->pdev = pdev;
+	msm_cam_register_subdev_node(&vfe2x_ctrl->subdev, VFE_DEV, 0);
 	return 0;
 }
 
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index cd503f9..0ab6531 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -640,10 +640,10 @@
 	.core = &msm_vpe_subdev_core_ops,
 };
 
-static int msm_vpe_resource_init(struct platform_device *pdev);
+static int msm_vpe_resource_init(void);
 
-int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
-	struct platform_device *pdev)
+int msm_vpe_subdev_init(struct v4l2_subdev *sd,
+		struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
 	CDBG("%s:begin", __func__);
@@ -653,19 +653,19 @@
 	}
 	atomic_set(&vpe_init_done, 1);
 
-	rc = msm_vpe_resource_init(pdev);
+	rc = msm_vpe_resource_init();
 	if (rc < 0) {
 		atomic_set(&vpe_init_done, 0);
 		return rc;
 	}
-	v4l2_set_subdev_hostdata(sd, data);
+	v4l2_set_subdev_hostdata(sd, mctl);
 	spin_lock_init(&vpe_ctrl->lock);
 	CDBG("%s:end", __func__);
 	return rc;
 }
 EXPORT_SYMBOL(msm_vpe_subdev_init);
 
-static int msm_vpe_resource_init(struct platform_device *pdev)
+static int msm_vpe_resource_init(void)
 {
 	int rc = 0;
 
@@ -686,7 +686,7 @@
 	return rc;  /* this rc should have error code. */
 }
 
-void msm_vpe_subdev_release(struct platform_device *pdev)
+void msm_vpe_subdev_release(void)
 {
 	if (!atomic_read(&vpe_init_done)) {
 		/* no VPE object created */
@@ -702,6 +702,8 @@
 }
 EXPORT_SYMBOL(msm_vpe_subdev_release);
 
+static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops;
+
 static int __devinit vpe_probe(struct platform_device *pdev)
 {
 	int rc = 0;
@@ -714,6 +716,8 @@
 
 	v4l2_subdev_init(&vpe_ctrl->subdev, &msm_vpe_subdev_ops);
 	v4l2_set_subdevdata(&vpe_ctrl->subdev, vpe_ctrl);
+	vpe_ctrl->subdev.internal_ops = &msm_vpe_internal_ops;
+	vpe_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	snprintf(vpe_ctrl->subdev.name, sizeof(vpe_ctrl->subdev.name), "vpe");
 	platform_set_drvdata(pdev, &vpe_ctrl->subdev);
 
@@ -753,6 +757,7 @@
 	disable_irq(vpe_ctrl->vpeirq->start);
 
 	vpe_ctrl->pdev = pdev;
+	msm_cam_register_subdev_node(&vpe_ctrl->subdev, VPE_DEV, pdev->id);
 	return 0;
 
 vpe_no_resource:
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index e9c710a..b7ae0f4 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -244,9 +244,11 @@
 		WFD_MSG_DBG("EVENT: not expected = %d\n", event);
 		venc_stop_done(client_ctx, status);
 		break;
-	case VCD_EVT_RESP_PAUSE:
 	case VCD_EVT_RESP_FLUSH_INPUT_DONE:
 	case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+		venc_notify_client(client_ctx);
+		break;
+	case VCD_EVT_RESP_PAUSE:
 	case VCD_EVT_IND_OUTPUT_RECONFIG:
 		WFD_MSG_DBG("EVENT: not expected = %d\n", event);
 		break;
@@ -1935,6 +1937,46 @@
 					 (u8 *)kernel_vaddr);
 }
 
+static long venc_flush_buffers(struct v4l2_subdev *sd, void *arg)
+{
+	int rc = 0;
+	struct venc_inst *inst = sd->dev_priv;
+	struct video_client_ctx *client_ctx = &inst->venc_client;
+	if (!client_ctx) {
+		WFD_MSG_ERR("Invalid input\n");
+		return -EINVAL;
+	}
+	rc = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_INPUT);
+	if (rc) {
+		WFD_MSG_ERR("Failed to flush input buffers\n");
+		rc = -EIO;
+		goto flush_failed;
+	}
+	wait_for_completion(&client_ctx->event);
+	if (client_ctx->event_status) {
+		WFD_MSG_ERR("callback for vcd_flush input returned error: %u",
+				client_ctx->event_status);
+		rc = -EIO;
+		goto flush_failed;
+	}
+	rc = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_OUTPUT);
+	if (rc) {
+		WFD_MSG_ERR("Failed to flush output buffers\n");
+		rc = -EIO;
+		goto flush_failed;
+	}
+	wait_for_completion(&client_ctx->event);
+	if (client_ctx->event_status) {
+		WFD_MSG_ERR("callback for vcd_flush output returned error: %u",
+				client_ctx->event_status);
+		rc = -EIO;
+		goto flush_failed;
+	}
+
+flush_failed:
+	return rc;
+}
+
 static long venc_free_input_buffer(struct v4l2_subdev *sd, void *arg)
 {
 	int del_rc = 0, free_rc = 0;
@@ -2203,6 +2245,9 @@
 	case FREE_RECON_BUFFERS:
 		rc = venc_free_recon_buffers(sd, arg);
 		break;
+	case ENCODE_FLUSH:
+		rc = venc_flush_buffers(sd, arg);
+		break;
 	default:
 		rc = -1;
 		break;
diff --git a/drivers/media/video/msm/wfd/enc-subdev.h b/drivers/media/video/msm/wfd/enc-subdev.h
index cafc9d5..5873e62 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.h
+++ b/drivers/media/video/msm/wfd/enc-subdev.h
@@ -74,6 +74,7 @@
 #define FREE_OUTPUT_BUFFER _IOWR('V', 21, struct mem_region *)
 #define FREE_INPUT_BUFFER _IOWR('V', 22, struct mem_region *)
 #define FREE_RECON_BUFFERS _IO('V', 23)
+#define ENCODE_FLUSH _IO('V', 24)
 
 extern int venc_init(struct v4l2_subdev *sd, u32 val);
 extern int venc_load_fw(struct v4l2_subdev *sd);
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 7ab5d17..0a2b1c1 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -614,6 +614,10 @@
 		WFD_MSG_ERR("Failed to stop VSG\n");
 
 	kthread_stop(inst->mdp_task);
+	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+			ENCODE_FLUSH, (void *)inst->venc_inst);
+	if (rc)
+		WFD_MSG_ERR("Failed to flush encoder\n");
 	WFD_MSG_DBG("enc stop\n");
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
 			ENCODE_STOP, (void *)inst->venc_inst);
diff --git a/drivers/mfd/marimba-core.c b/drivers/mfd/marimba-core.c
index e168c49..8b41518 100644
--- a/drivers/mfd/marimba-core.c
+++ b/drivers/mfd/marimba-core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -748,7 +748,7 @@
 	}
 }
 
-static int marimba_probe(struct i2c_client *client,
+static int __devinit marimba_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct marimba_platform_data *pdata = client->dev.platform_data;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 39bcf16..ea5b851 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -697,7 +697,7 @@
 
 	for (i = 0; total < prop->length; total += l, p += l) {
 		l = strlen(p) + 1;
-		if ((*p != 0) && (i++ == index)) {
+		if (i++ == index) {
 			*output = p;
 			return 0;
 		}
@@ -735,11 +735,9 @@
 
 	p = prop->value;
 
-	for (i = 0; total < prop->length; total += l, p += l) {
+	for (i = 0; total < prop->length; total += l, p += l, i++)
 		l = strlen(p) + 1;
-		if (*p != 0)
-			i++;
-	}
+
 	return i;
 }
 EXPORT_SYMBOL_GPL(of_property_count_strings);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 8e9d753..de5e741 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -77,6 +77,7 @@
 #define CHG_ITRIM		0x35B
 #define CHG_TTRIM		0x35C
 #define CHG_COMP_OVR		0x20A
+#define IUSB_FINE_RES		0x2B6
 
 /* check EOC every 10 seconds */
 #define EOC_CHECK_PERIOD_MS	10000
@@ -243,6 +244,7 @@
 	bool				keep_btm_on_suspend;
 	bool				ext_charging;
 	bool				ext_charge_done;
+	bool				iusb_fine_res;
 	DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
 	struct work_struct		battery_id_valid_work;
 	int64_t				batt_id_min;
@@ -657,50 +659,110 @@
 }
 
 struct usb_ma_limit_entry {
-	int usb_ma;
+	int	usb_ma;
+	u8	value;
 };
 
 static struct usb_ma_limit_entry usb_ma_table[] = {
-	{100},
-	{500},
-	{700},
-	{850},
-	{900},
-	{1100},
-	{1300},
-	{1500},
+	{100, 0x0},
+	{200, 0x1},
+	{500, 0x2},
+	{600, 0x3},
+	{700, 0x4},
+	{800, 0x5},
+	{850, 0x6},
+	{900, 0x8},
+	{950, 0x7},
+	{1000, 0x9},
+	{1100, 0xA},
+	{1200, 0xB},
+	{1300, 0xC},
+	{1400, 0xD},
+	{1500, 0xE},
+	{1600, 0xF},
 };
 
 #define PM8921_CHG_IUSB_MASK 0x1C
+#define PM8921_CHG_IUSB_SHIFT 2
 #define PM8921_CHG_IUSB_MAX  7
 #define PM8921_CHG_IUSB_MIN  0
+#define PM8917_IUSB_FINE_RES BIT(0)
 static int pm_chg_iusbmax_set(struct pm8921_chg_chip *chip, int reg_val)
 {
-	u8 temp;
+	u8 temp, fineres;
+	int rc;
+
+	fineres = PM8917_IUSB_FINE_RES & usb_ma_table[reg_val].value;
+	reg_val = usb_ma_table[reg_val].value >> 1;
 
 	if (reg_val < PM8921_CHG_IUSB_MIN || reg_val > PM8921_CHG_IUSB_MAX) {
 		pr_err("bad mA=%d asked to set\n", reg_val);
 		return -EINVAL;
 	}
-	temp = reg_val << 2;
-	return pm_chg_masked_write(chip, PBL_ACCESS2, PM8921_CHG_IUSB_MASK,
-					 temp);
+	temp = reg_val << PM8921_CHG_IUSB_SHIFT;
+
+	/* IUSB_FINE_RES */
+	if (chip->iusb_fine_res) {
+		/* Clear IUSB_FINE_RES bit to avoid overshoot */
+		rc = pm_chg_masked_write(chip, IUSB_FINE_RES,
+			PM8917_IUSB_FINE_RES, 0);
+
+		rc |= pm_chg_masked_write(chip, PBL_ACCESS2,
+			PM8921_CHG_IUSB_MASK, temp);
+
+		if (rc) {
+			pr_err("Failed to write PBL_ACCESS2 rc=%d\n", rc);
+			return rc;
+		}
+
+		if (fineres) {
+			rc = pm_chg_masked_write(chip, IUSB_FINE_RES,
+				PM8917_IUSB_FINE_RES, fineres);
+			if (rc)
+				pr_err("Failed to write ISUB_FINE_RES rc=%d\n",
+					rc);
+		}
+	} else {
+		rc = pm_chg_masked_write(chip, PBL_ACCESS2,
+			PM8921_CHG_IUSB_MASK, temp);
+		if (rc)
+			pr_err("Failed to write PBL_ACCESS2 rc=%d\n", rc);
+	}
+
+	return rc;
 }
 
 static int pm_chg_iusbmax_get(struct pm8921_chg_chip *chip, int *mA)
 {
-	u8 temp;
-	int rc;
+	u8 temp, fineres;
+	int rc, i;
 
+	fineres = 0;
 	*mA = 0;
 	rc = pm8xxx_readb(chip->dev->parent, PBL_ACCESS2, &temp);
 	if (rc) {
 		pr_err("err=%d reading PBL_ACCESS2\n", rc);
 		return rc;
 	}
+
+	if (chip->iusb_fine_res) {
+		rc = pm8xxx_readb(chip->dev->parent, IUSB_FINE_RES, &fineres);
+		if (rc) {
+			pr_err("err=%d reading IUSB_FINE_RES\n", rc);
+			return rc;
+		}
+	}
 	temp &= PM8921_CHG_IUSB_MASK;
-	temp = temp >> 2;
-	*mA = usb_ma_table[temp].usb_ma;
+	temp = temp >> PM8921_CHG_IUSB_SHIFT;
+
+	temp = (temp << 1) | (fineres & PM8917_IUSB_FINE_RES);
+	for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
+		if (usb_ma_table[i].value == temp)
+			break;
+	}
+
+	*mA = usb_ma_table[i].usb_ma;
+
 	return rc;
 }
 
@@ -1450,8 +1512,12 @@
 static void __pm8921_charger_vbus_draw(unsigned int mA)
 {
 	int i, rc;
+	if (!the_chip) {
+		pr_err("called before init\n");
+		return;
+	}
 
-	if (mA > 0 && mA <= 2) {
+	if (mA >= 0 && mA <= 2) {
 		usb_chg_current = 0;
 		rc = pm_chg_iusbmax_set(the_chip, 0);
 		if (rc) {
@@ -1468,6 +1534,11 @@
 			if (usb_ma_table[i].usb_ma <= mA)
 				break;
 		}
+
+		/* Check if IUSB_FINE_RES is available */
+		if ((usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
+				&& !the_chip->iusb_fine_res)
+			i--;
 		if (i < 0)
 			i = 0;
 		rc = pm_chg_iusbmax_set(the_chip, i);
@@ -1972,6 +2043,12 @@
 
 		if (i < (ARRAY_SIZE(usb_ma_table) - 1))
 			i++;
+		/* Get next correct entry if IUSB_FINE_RES is not available */
+		while (!the_chip->iusb_fine_res
+			&& (usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
+			&& i < (ARRAY_SIZE(usb_ma_table) - 1))
+			i++;
+
 		*value = usb_ma_table[i].usb_ma;
 	}
 }
@@ -3411,6 +3488,10 @@
 	if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0)
 		pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xAC);
 
+	/* Enable isub_fine resolution AICL for PM8917 */
+	if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
+		chip->iusb_fine_res = true;
+
 	pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD9);
 
 	/* Disable EOC FSM processing */
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 1457ab2..a83f6d3 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -40,6 +40,8 @@
 #include <mach/msm_xo.h>
 #include <linux/spinlock.h>
 
+#define RUNTIME_SUSP_DELAY 500
+
 #define MSM_USB_BASE (hcd->regs)
 
 struct msm_hsic_hcd {
@@ -57,6 +59,7 @@
 	int			peripheral_status_irq;
 	int			wakeup_irq;
 	bool			wakeup_irq_enabled;
+	bool			pm_resume;
 	uint32_t		bus_perf_client;
 };
 
@@ -766,8 +769,6 @@
 	debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
 }
 
-
-
 static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
@@ -954,6 +955,7 @@
 
 	ehci_hsic_msm_debugfs_cleanup();
 	device_init_wakeup(&pdev->dev, 0);
+	mehci->pm_resume = false;
 	pm_runtime_set_suspended(&pdev->dev);
 
 	usb_remove_hcd(hcd);
@@ -979,6 +981,8 @@
 	if (device_may_wakeup(dev))
 		enable_irq_wake(hcd->irq);
 
+	mehci->pm_resume = false;
+
 	return msm_hsic_suspend(mehci);
 }
 
@@ -1015,6 +1019,8 @@
 		disable_irq_nosync(mehci->wakeup_irq);
 	}
 
+	mehci->pm_resume = true;
+
 	ret = msm_hsic_resume(mehci);
 	if (ret)
 		return ret;
@@ -1031,8 +1037,17 @@
 #ifdef CONFIG_PM_RUNTIME
 static int msm_hsic_runtime_idle(struct device *dev)
 {
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+
 	dev_dbg(dev, "EHCI runtime idle\n");
 
+	if (mehci->pm_resume) {
+		mehci->pm_resume = false;
+		pm_schedule_suspend(dev, RUNTIME_SUSP_DELAY);
+		return -EAGAIN;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 6ebc955..8156505 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -300,6 +300,27 @@
 				encoder->seq_header.virtual_base_addr,
 				encoder->seq_header.buffer_size,
 				ION_IOC_CLEAN_INV_CACHES);
+	if (encoder->slice_delivery_info.enable) {
+		DDL_MSG_LOW("%s: slice mode allocate memory for struct\n",
+					__func__);
+		ptr = ddl_pmem_alloc(&encoder->batch_frame.slice_batch_in,
+				DDL_ENC_SLICE_BATCH_INPSTRUCT_SIZE,
+				DDL_LINEAR_BUFFER_ALIGN_BYTES);
+		if (ptr) {
+			ptr = ddl_pmem_alloc(
+				&encoder->batch_frame.slice_batch_out,
+				DDL_ENC_SLICE_BATCH_OUTSTRUCT_SIZE,
+				DDL_LINEAR_BUFFER_ALIGN_BYTES);
+		}
+		if (!ptr) {
+			ddl_pmem_free(&encoder->batch_frame.slice_batch_in);
+			ddl_pmem_free(&encoder->batch_frame.slice_batch_out);
+			ddl_free_enc_hw_buffers(ddl);
+			ddl_pmem_free(&encoder->seq_header);
+			DDL_MSG_ERROR("ddlEncStart:SeqHdrAllocFailed");
+			return VCD_ERR_ALLOC_FAIL;
+		}
+	}
 	if (!ddl_take_command_channel(ddl_context, ddl, client_data))
 		return VCD_ERR_BUSY;
 	ddl_vidc_channel_set(ddl);
@@ -451,7 +472,17 @@
 	struct ddl_client_context *ddl =
 		(struct ddl_client_context *) ddl_handle;
 	struct ddl_context *ddl_context;
+	struct ddl_encoder_data *encoder =
+		&ddl->codec_data.encoder;
 	u32 vcd_status = VCD_S_SUCCESS;
+	if (encoder->slice_delivery_info.enable) {
+		return ddl_encode_frame_batch(ddl_handle,
+					input_frame,
+					output_bit,
+					1,
+					encoder->slice_delivery_info.num_slices,
+					client_data);
+	}
 
 	DDL_MSG_HIGH("ddl_encode_frame");
 	if (vidc_msg_timing)
@@ -519,6 +550,76 @@
 	return vcd_status;
 }
 
+u32 ddl_encode_frame_batch(u32 *ddl_handle,
+	struct ddl_frame_data_tag *input_frame,
+	struct ddl_frame_data_tag *output_bit,
+	u32 num_in_frames, u32 num_out_frames,
+	void *client_data)
+{
+	struct ddl_client_context *ddl =
+		(struct ddl_client_context *) ddl_handle;
+	struct ddl_context *ddl_context;
+	u32 vcd_status = VCD_S_SUCCESS;
+	struct ddl_encoder_data *encoder;
+
+	DDL_MSG_LOW("ddl_encode_frame_batch");
+	ddl_context = ddl_get_context();
+	if (!DDL_IS_INITIALIZED(ddl_context)) {
+		DDL_MSG_ERROR("ddl_enc_frame:Not_inited");
+		return VCD_ERR_ILLEGAL_OP;
+	}
+	if (DDL_IS_BUSY(ddl_context)) {
+		DDL_MSG_ERROR("ddl_enc_frame:Ddl_busy");
+		return VCD_ERR_BUSY;
+	}
+	if (!ddl || ddl->decoding) {
+		DDL_MSG_ERROR("ddl_enc_frame:Bad_handle");
+	return VCD_ERR_BAD_HANDLE;
+	}
+	if (!input_frame || !input_frame->vcd_frm.physical	||
+		!input_frame->vcd_frm.data_len) {
+		DDL_MSG_ERROR("ddl_enc_frame:Bad_input_params");
+		return VCD_ERR_ILLEGAL_PARM;
+	}
+	if ((((u32) input_frame->vcd_frm.physical +
+		input_frame->vcd_frm.offset) &
+		(DDL_STREAMBUF_ALIGN_GUARD_BYTES))) {
+		DDL_MSG_ERROR("ddl_enc_frame:Un_aligned_yuv_start_address");
+		return VCD_ERR_ILLEGAL_PARM;
+	}
+	if (!output_bit || !output_bit->vcd_frm.physical ||
+		!output_bit->vcd_frm.alloc_len) {
+		DDL_MSG_ERROR("ddl_enc_frame:Bad_output_params");
+		return VCD_ERR_ILLEGAL_PARM;
+	}
+	if ((ddl->codec_data.encoder.output_buf_req.sz +
+		output_bit->vcd_frm.offset) >
+		output_bit->vcd_frm.alloc_len)
+		DDL_MSG_ERROR("ddl_enc_frame:offset_large,"
+			"Exceeds_min_buf_size");
+	if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME)) {
+		DDL_MSG_ERROR("ddl_enc_frame:Wrong_state");
+		return VCD_ERR_ILLEGAL_OP;
+	}
+	if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+		return VCD_ERR_BUSY;
+	encoder = &ddl->codec_data.encoder;
+	if (encoder->slice_delivery_info.enable) {
+		DDL_MEMCPY((void *)&(encoder->batch_frame.output_frame[0]),
+			(void *)output_bit,
+			sizeof(struct ddl_frame_data_tag) * num_out_frames);
+		encoder->batch_frame.num_output_frames = num_out_frames;
+		ddl->input_frame = *input_frame;
+		vcd_status = ddl_insert_input_frame_to_pool(ddl, input_frame);
+		if (!vcd_status)
+			ddl_vidc_encode_slice_batch_run(ddl);
+		else
+			DDL_MSG_ERROR("insert to frame pool failed %u",
+					vcd_status);
+	}
+	return vcd_status;
+}
+
 u32 ddl_decode_end(u32 *ddl_handle, void *client_data)
 {
 	struct ddl_client_context *ddl =
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index c3874fa..d05e542 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -113,6 +113,7 @@
 	DDL_CMD_ENCODE_FRAME    = 0x8,
 	DDL_CMD_EOS             = 0x9,
 	DDL_CMD_CHANNEL_END     = 0xA,
+	DDL_CMD_ENCODE_CONTINUE = 0xB,
 	DDL_CMD_32BIT           = 0x7FFFFFFF
 };
 enum ddl_client_state{
@@ -129,6 +130,7 @@
 	DDL_CLIENT_WAIT_FOR_CHEND          = 0xA,
 	DDL_CLIENT_FATAL_ERROR             = 0xB,
 	DDL_CLIENT_FAVIDC_ERROR            = 0xC,
+	DDL_CLIENT_WAIT_FOR_CONTINUE       = 0xD,
 	DDL_CLIENT_32BIT                   = 0x7FFFFFFF
 };
 struct ddl_hw_interface{
@@ -215,6 +217,15 @@
 struct ddl_codec_data_hdr{
 	u32  decoding;
 };
+struct ddl_batch_frame_data {
+	struct ddl_buf_addr slice_batch_in;
+	struct ddl_buf_addr slice_batch_out;
+	struct ddl_frame_data_tag input_frame;
+	struct ddl_frame_data_tag output_frame
+			[DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH];
+	u32 num_output_frames;
+	u32 out_frm_next_frmindex;
+};
 struct ddl_encoder_data{
 	struct ddl_codec_data_hdr   hdr;
 	struct vcd_property_codec   codec;
@@ -262,6 +273,8 @@
 	u32  ext_enc_control_val;
 	u32  num_references_for_p_frame;
 	u32  closed_gop;
+	struct vcd_property_slice_delivery_info slice_delivery_info;
+	struct ddl_batch_frame_data batch_frame;
 };
 struct ddl_decoder_data {
 	struct ddl_codec_data_hdr  hdr;
@@ -344,6 +357,8 @@
 		(struct vidc_1080p_enc_seq_start_param *param);
 	void(*vidc_encode_frame_start[2])
 		(struct vidc_1080p_enc_frame_start_param *param);
+	void(*vidc_encode_slice_batch_start[2])
+		(struct vidc_1080p_enc_frame_start_param *param);
 	u32 frame_channel_depth;
 };
 struct ddl_client_context{
@@ -375,9 +390,12 @@
 void ddl_vidc_channel_end(struct ddl_client_context *);
 void ddl_vidc_encode_init_codec(struct ddl_client_context *);
 void ddl_vidc_decode_init_codec(struct ddl_client_context *);
+void ddl_vidc_encode_frame_continue(struct ddl_client_context *);
 void ddl_vidc_encode_frame_run(struct ddl_client_context *);
+void ddl_vidc_encode_slice_batch_run(struct ddl_client_context *);
 void ddl_vidc_decode_frame_run(struct ddl_client_context *);
 void ddl_vidc_decode_eos_run(struct ddl_client_context *ddl);
+void ddl_vidc_encode_eos_run(struct ddl_client_context *ddl);
 void ddl_release_context_buffers(struct ddl_context *);
 void ddl_release_client_internal_buffers(struct ddl_client_context *ddl);
 u32  ddl_vidc_decode_set_buffers(struct ddl_client_context *);
@@ -438,9 +456,10 @@
 
 u32 ddl_get_input_frame_from_pool(struct ddl_client_context *ddl,
 	u8 *input_buffer_address);
+u32 ddl_get_stream_buf_from_batch_pool(struct ddl_client_context *ddl,
+	struct ddl_frame_data_tag *stream_buffer);
 u32 ddl_insert_input_frame_to_pool(struct ddl_client_context *ddl,
 	struct ddl_frame_data_tag *ddl_input_frame);
-
 void ddl_decoder_chroma_dpb_change(struct ddl_client_context *ddl);
 u32  ddl_check_reconfig(struct ddl_client_context *ddl);
 void ddl_handle_reconfig(u32 res_change, struct ddl_client_context *ddl);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
index 433dad4..5c1ee21 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
@@ -62,6 +62,11 @@
 	u32 disable_static_region_as_flag;
 	u32 disable_activity_region_flag;
 };
+struct vcd_property_slice_delivery_info {
+	u32  enable;
+	u32  num_slices;
+	u32  num_slices_enc;
+};
 struct ddl_property_dec_pic_buffers{
 	struct ddl_frame_data_tag *dec_pic_buffers;
 	u32 no_of_dec_pic_buf;
@@ -94,6 +99,11 @@
 u32 ddl_encode_frame(u32 *ddl_handle,
 	struct ddl_frame_data_tag *input_frame,
 	struct ddl_frame_data_tag *output_bit, void *client_data);
+u32 ddl_encode_frame_batch(u32 *ddl_handle,
+	struct ddl_frame_data_tag *input_frame,
+	struct ddl_frame_data_tag *output_bit,
+	u32 num_in_frames, u32 num_out_frames,
+	void *client_data);
 u32 ddl_encode_end(u32 *ddl_handle, void *client_data);
 u32 ddl_decode_start(u32 *ddl_handle, struct vcd_sequence_hdr *header,
 	void *client_data);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index a8ccebf..41604b0 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -64,13 +64,20 @@
 #define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE  (DDL_KILO_BYTE(800))
 #define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE      (DDL_KILO_BYTE(800))
 #define DDL_FW_H264ENC_CONTEXT_SPACE_SIZE      (DDL_KILO_BYTE(20))
-#define DDL_FW_OTHER_CONTEXT_SPACE_SIZE        (DDL_KILO_BYTE(10))
+#define DDL_FW_OTHER_CONTEXT_SPACE_SIZE        (DDL_KILO_BYTE(20))
 
 #define VCD_DEC_CPB_SIZE         (DDL_KILO_BYTE(512))
 #define DDL_DBG_CORE_DUMP_SIZE   (DDL_KILO_BYTE(10))
+#define DDL_VIDC_1080P_BASE_OFFSET_SHIFT        11
 
 #define DDL_BUFEND_PAD                    256
 #define DDL_ENC_SEQHEADER_SIZE            (512+DDL_BUFEND_PAD)
+#define DDL_ENC_SLICE_BATCH_FACTOR         5
+#define DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH   8
+#define DDL_ENC_SLICE_BATCH_INPSTRUCT_SIZE (128 + \
+				32 * DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH)
+#define DDL_ENC_SLICE_BATCH_OUTSTRUCT_SIZE (64 + \
+				64 * DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH)
 #define DDL_MAX_BUFFER_COUNT              32
 #define DDL_MIN_BUFFER_COUNT              1
 
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 62f0976..0d0ba3e 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -375,6 +375,8 @@
 		struct ddl_encoder_data *encoder =
 			&(ddl->codec_data.encoder);
 		ddl_pmem_free(&encoder->seq_header);
+		ddl_pmem_free(&encoder->batch_frame.slice_batch_in);
+		ddl_pmem_free(&encoder->batch_frame.slice_batch_out);
 		ddl_vidc_encode_dynamic_property(ddl, false);
 		encoder->dynamic_prop_change = 0;
 		ddl_free_enc_hw_buffers(ddl);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index 830c777c3..79e6c5d 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
@@ -29,7 +29,11 @@
 	enum vidc_1080p_encode_frame frame_type);
 static void ddl_get_dec_profile_level(struct ddl_decoder_data *decoder,
 	u32 profile, u32 level);
-static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl);
+static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl,
+	u32 eos_present);
+static void ddl_handle_slice_done_slice_batch(struct ddl_client_context *ddl);
+static void ddl_handle_enc_frame_done_slice_mode(
+		struct ddl_client_context *ddl, u32 eos_present);
 
 static void ddl_fw_status_done_callback(struct ddl_context *ddl_context)
 {
@@ -141,7 +145,7 @@
 {
 	struct ddl_encoder_data *encoder;
 
-	DDL_MSG_MED("ddl_encoder_seq_done_callback");
+	DDL_MSG_HIGH("ddl_encoder_seq_done_callback");
 	if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) {
 		DDL_MSG_ERROR("STATE-CRITICAL-INITCODEC");
 		ddl_client_fatal_cb(ddl);
@@ -486,9 +490,9 @@
 		&(ddl->codec_data.encoder);
 	struct vcd_frame_data *output_frame =
 		&(ddl->output_frame.vcd_frm);
-	u32 bottom_frame_tag;
+	u32 eos_present = false;
 
-	DDL_MSG_MED("ddl_encoder_frame_run_callback");
+	DDL_MSG_MED("ddl_encoder_frame_run_callback\n");
 	if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE) &&
 		!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
 		DDL_MSG_ERROR("STATE-CRITICAL-ENCFRMRUN");
@@ -499,47 +503,28 @@
 		DDL_MSG_LOW("ENC_FRM_RUN_DONE");
 		ddl->cmd_state = DDL_CMD_INVALID;
 		vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
-		vidc_sm_get_frame_tags(&ddl->shared_mem
-			[ddl->command_channel],
-			&output_frame->ip_frm_tag, &bottom_frame_tag);
 
 		if (encoder->meta_data_enable_flag)
 			vidc_sm_get_metadata_status(&ddl->shared_mem
 				[ddl->command_channel],
 				&encoder->enc_frame_info.meta_data_exists);
 
+		if (VCD_FRAME_FLAG_EOS & ddl->input_frame.vcd_frm.flags) {
+				DDL_MSG_LOW("%s EOS detected\n", __func__);
+				eos_present = true;
+		}
+
 		if (encoder->enc_frame_info.enc_frame_size ||
 			(encoder->enc_frame_info.enc_frame ==
 			VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED) ||
 			DDLCLIENT_STATE_IS(ddl,
 			DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
-			u8 *input_buffer_address = NULL;
-			output_frame->data_len =
-				encoder->enc_frame_info.enc_frame_size;
-			output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
-			ddl_get_encoded_frame(output_frame,
-				encoder->codec.codec,
-				encoder->enc_frame_info.enc_frame);
-			ddl_process_encoder_metadata(ddl);
-			ddl_vidc_encode_dynamic_property(ddl, false);
-			ddl->input_frame.frm_trans_end = false;
-			input_buffer_address = ddl_context->dram_base_a.\
-				align_physical_addr +
-				encoder->enc_frame_info.enc_luma_address;
-			ddl_get_input_frame_from_pool(ddl,
-				input_buffer_address);
-			ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
-				VCD_S_SUCCESS, &(ddl->input_frame),
-				sizeof(struct ddl_frame_data_tag),
-				(u32 *)ddl, ddl->client_data);
-			ddl->output_frame.frm_trans_end =
-				DDLCLIENT_STATE_IS(ddl,
-				DDL_CLIENT_WAIT_FOR_EOS_DONE) ? false : true;
-			ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
-				VCD_S_SUCCESS, &(ddl->output_frame),
-				sizeof(struct ddl_frame_data_tag),
-				(u32 *)ddl, ddl->client_data);
-
+			if (encoder->slice_delivery_info.enable) {
+				ddl_handle_enc_frame_done_slice_mode(ddl,
+								eos_present);
+			} else {
+				ddl_handle_enc_frame_done(ddl, eos_present);
+			}
 			if (DDLCLIENT_STATE_IS(ddl,
 				DDL_CLIENT_WAIT_FOR_EOS_DONE) &&
 				encoder->i_period.b_frames) {
@@ -547,7 +532,7 @@
 					(ddl->extra_output_buf_count >
 					encoder->i_period.b_frames)) {
 					DDL_MSG_ERROR("Invalid B frame output"
-								"buffer index");
+								  "buffer index");
 				} else {
 					struct vidc_1080p_enc_frame_start_param
 						enc_param;
@@ -581,7 +566,11 @@
 					ddl_context->vidc_encode_frame_start
 						[ddl->command_channel]
 						(&enc_param);
-				} } else {
+					}
+				} else if (eos_present &&
+					encoder->slice_delivery_info.enable) {
+					ddl_vidc_encode_eos_run(ddl);
+				} else {
 				DDL_MSG_LOW("ddl_state_transition: %s ~~>"
 					"DDL_CLIENT_WAIT_FOR_FRAME",
 					ddl_get_state_string(
@@ -885,6 +874,7 @@
 	vidc_1080p_clear_returned_channel_inst_id();
 	ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
 			ddl_context->response_cmd_ch_id);
+	DDL_MSG_LOW("ddl_encoder_eos_done\n");
 	if (ddl == NULL) {
 		DDL_MSG_ERROR("NO_DDL_CONTEXT");
 	} else {
@@ -896,9 +886,11 @@
 				&(ddl->codec_data.encoder);
 			vidc_1080p_get_encode_frame_info(
 				&encoder->enc_frame_info);
-			ddl_handle_enc_frame_done(ddl);
+			if (!encoder->slice_delivery_info.enable) {
+				ddl_handle_enc_frame_done(ddl, true);
+				ddl->cmd_state = DDL_CMD_INVALID;
+			}
 			DDL_MSG_LOW("encoder_eos_done");
-			ddl->cmd_state = DDL_CMD_INVALID;
 			DDL_MSG_LOW("ddl_state_transition: %s ~~>"
 				"DDL_CLIENT_WAIT_FOR_FRAME",
 				ddl_get_state_string(ddl->client_state));
@@ -913,6 +905,35 @@
 	}
 }
 
+static u32 ddl_slice_done_callback(struct ddl_context *ddl_context)
+{
+	struct ddl_client_context *ddl;
+	u32 channel_inst_id;
+	u32 return_status = true;
+	DDL_MSG_LOW("ddl_sliceDoneCallback");
+	vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+	vidc_1080p_clear_returned_channel_inst_id();
+	ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+			ddl_context->response_cmd_ch_id);
+	if (ddl == NULL) {
+		DDL_MSG_ERROR("NO_DDL_CONTEXT");
+		return_status = false;
+	} else if (ddl->cmd_state == DDL_CMD_ENCODE_FRAME) {
+			ddl->cmd_state = DDL_CMD_INVALID;
+			if (DDLCLIENT_STATE_IS(ddl,
+				DDL_CLIENT_WAIT_FOR_FRAME_DONE)) {
+				ddl_handle_slice_done_slice_batch(ddl);
+			} else {
+				DDL_MSG_ERROR("STATE-CRITICAL-ENCFRMRUN : %s\n",
+					 __func__);
+				ddl_client_fatal_cb(ddl);
+			}
+	} else {
+		DDL_MSG_ERROR("UNKNOWN_SLICEDONE : %s\n", __func__);
+	}
+	return return_status;
+}
+
 static u32 ddl_process_intr_status(struct ddl_context *ddl_context,
 	u32 intr_status)
 {
@@ -931,6 +952,9 @@
 	case VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET:
 		return_status = ddl_frame_run_callback(ddl_context);
 	break;
+	case VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET:
+		 ddl_slice_done_callback(ddl_context);
+	break;
 	case VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET:
 		ddl_sys_init_done_callback(ddl_context,
 			ddl_context->response_cmd_ch_id);
@@ -963,6 +987,8 @@
 {
 	struct ddl_context *ddl_context;
 	struct ddl_hw_interface  *ddl_hw_response;
+	struct ddl_client_context *ddl;
+	struct ddl_encoder_data *encoder;
 
 	ddl_context = ddl_get_context();
 	if (!ddl_context->core_virtual_base_addr) {
@@ -971,12 +997,37 @@
 		ddl_hw_response = &ddl_context->ddl_hw_response;
 		vidc_1080p_get_risc2host_cmd(&ddl_hw_response->cmd,
 			&ddl_hw_response->arg1, &ddl_hw_response->arg2,
-			&ddl_hw_response->arg3, &ddl_hw_response->arg4);
+			&ddl_hw_response->arg3,
+			&ddl_hw_response->arg4);
+		DDL_MSG_LOW("%s vidc_1080p_get_risc2host_cmd cmd = %u"
+			"arg1 = %u arg2 = %u arg3 = %u"
+			"arg4 = %u\n",
+			__func__, ddl_hw_response->cmd,
+			ddl_hw_response->arg1, ddl_hw_response->arg2,
+			ddl_hw_response->arg3,
+			ddl_hw_response->arg4);
+		ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+			ddl_context->response_cmd_ch_id);
+		if (ddl) {
+			encoder = &(ddl->codec_data.encoder);
+			if (encoder && encoder->slice_delivery_info.enable
+			&&
+			((ddl_hw_response->cmd ==
+				VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET)
+			|| (ddl_hw_response->cmd ==
+				VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET))) {
+				vidc_sm_set_encoder_slice_batch_int_ctrl(
+				&ddl->shared_mem[ddl->command_channel],
+				1);
+			}
+		}
 		vidc_1080p_clear_risc2host_cmd();
 		vidc_1080p_clear_interrupt();
 		vidc_1080p_get_risc2host_cmd_status(ddl_hw_response->arg2,
 			&ddl_context->cmd_err_status,
 			&ddl_context->disp_pic_err_status);
+		DDL_MSG_LOW("%s cmd_err_status = %d\n", __func__,
+				ddl_context->cmd_err_status);
 		ddl_context->response_cmd_ch_id = ddl_hw_response->arg1;
 	}
 }
@@ -1638,39 +1689,214 @@
 	decoder->level.level = level;
 }
 
-static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl)
+static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl,
+					u32 eos_present)
 {
 	struct ddl_context       *ddl_context = ddl->ddl_context;
 	struct ddl_encoder_data  *encoder = &(ddl->codec_data.encoder);
 	struct vcd_frame_data    *output_frame = &(ddl->output_frame.vcd_frm);
 	u32 bottom_frame_tag;
-	u8  *input_buffer_address = NULL;
+	u8 *input_buffer_address = NULL;
 
 	vidc_sm_get_frame_tags(&ddl->shared_mem[ddl->command_channel],
 		&output_frame->ip_frm_tag, &bottom_frame_tag);
 	output_frame->data_len = encoder->enc_frame_info.enc_frame_size;
 	output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
 	(void)ddl_get_encoded_frame(output_frame,
-		encoder->codec.codec, encoder->enc_frame_info.enc_frame);
+		encoder->codec.codec, encoder->enc_frame_info.enc_frame
+								);
 	ddl_process_encoder_metadata(ddl);
 	ddl_vidc_encode_dynamic_property(ddl, false);
 	ddl->input_frame.frm_trans_end = false;
 	input_buffer_address = ddl_context->dram_base_a.align_physical_addr +
 			encoder->enc_frame_info.enc_luma_address;
 	ddl_get_input_frame_from_pool(ddl, input_buffer_address);
-
 	ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
-		VCD_S_SUCCESS, &(ddl->input_frame),
-		sizeof(struct ddl_frame_data_tag),
-		(u32 *) ddl, ddl->client_data);
-
-	ddl->output_frame.frm_trans_end =
-		DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)
-			? false : true;
-
+					VCD_S_SUCCESS, &(ddl->input_frame),
+					sizeof(struct ddl_frame_data_tag),
+					(u32 *) ddl, ddl->client_data);
+	ddl->output_frame.frm_trans_end = eos_present ?
+		false : true;
 	ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
-		VCD_S_SUCCESS, &(ddl->output_frame),
-		sizeof(struct ddl_frame_data_tag),
-		(u32 *) ddl, ddl->client_data);
+				VCD_S_SUCCESS, &(ddl->output_frame),
+				sizeof(struct ddl_frame_data_tag),
+				(u32 *) ddl, ddl->client_data);
+}
 
+static void ddl_handle_slice_done_slice_batch(struct ddl_client_context *ddl)
+{
+	struct ddl_context       *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data  *encoder = &(ddl->codec_data.encoder);
+	struct vcd_frame_data    *output_frame = NULL;
+	u32 bottom_frame_tag;
+	struct vidc_1080p_enc_slice_batch_out_param *slice_output = NULL;
+	u32 num_slices_comp = 0;
+	u32 index = 0;
+	u32 start_bfr_idx = 0;
+	u32 actual_idx = 0;
+
+	DDL_MSG_LOW("%s\n", __func__);
+	vidc_sm_get_num_slices_comp(
+			&ddl->shared_mem[ddl->command_channel],
+			&num_slices_comp);
+	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)
+		DDL_MSG_ERROR(" slice_output is NULL\n");
+	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,
+					num_slices_comp);
+		ddl_set_core_start_time(__func__, ENC_SLICE_OP_TIME);
+	}
+	DDL_MSG_LOW("%s : Slices Completed %d Total slices %d OutBfrInfo:"
+			"Cmd %d Size %d\n",
+			__func__,
+			num_slices_comp,
+			encoder->slice_delivery_info.num_slices_enc,
+			slice_output->cmd_type,
+			slice_output->output_size);
+	start_bfr_idx = encoder->batch_frame.out_frm_next_frmindex;
+	for (index = 0; index < num_slices_comp; index++) {
+		actual_idx =
+		slice_output->slice_info[start_bfr_idx+index].stream_buffer_idx;
+		DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d\n",
+			actual_idx,
+			slice_output->slice_info[start_bfr_idx+index].
+			stream_buffer_size);
+		output_frame = &(
+			encoder->batch_frame.output_frame[actual_idx].vcd_frm);
+		DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+			"frmbfr(physical) 0x%x\n",
+			&output_frame,
+			output_frame.virtual_base_addr,
+			output_frame.physical_base_addr);
+		vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
+		vidc_sm_get_frame_tags(&ddl->shared_mem
+			[ddl->command_channel],
+			&output_frame->ip_frm_tag, &bottom_frame_tag);
+		ddl_get_encoded_frame(output_frame,
+				encoder->codec.codec,
+				encoder->enc_frame_info.enc_frame);
+		output_frame->data_len =
+			slice_output->slice_info[actual_idx].stream_buffer_size;
+		ddl->output_frame =
+			encoder->batch_frame.output_frame[actual_idx];
+		ddl->output_frame.frm_trans_end = false;
+		ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+				VCD_S_SUCCESS, &(ddl->output_frame),
+				sizeof(struct ddl_frame_data_tag),
+				(u32 *) ddl, ddl->client_data);
+		ddl->input_frame.frm_trans_end = false;
+		DDL_MSG_LOW("%s Set i/p o/p transactions to false\n", __func__);
+	}
+	encoder->batch_frame.out_frm_next_frmindex = start_bfr_idx + index;
+	ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+	vidc_sm_set_encoder_slice_batch_int_ctrl(
+			&ddl->shared_mem[ddl->command_channel],
+			0);
+}
+
+static void ddl_handle_enc_frame_done_slice_mode(
+		struct ddl_client_context *ddl, u32 eos_present)
+{
+	struct ddl_context       *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data  *encoder = &(ddl->codec_data.encoder);
+	struct vcd_frame_data    *output_frame = NULL;
+	u32 bottom_frame_tag;
+	u8 *input_buffer_address = NULL;
+	struct vidc_1080p_enc_slice_batch_out_param *slice_output = NULL;
+	u32 num_slices_comp = 0;
+	u32 index = 0;
+	u32 start_bfr_idx = 0;
+	u32 actual_idx = 0;
+	struct vcd_transc *transc;
+
+	DDL_MSG_LOW("%s\n", __func__);
+	vidc_sm_get_num_slices_comp(
+				&ddl->shared_mem[ddl->command_channel],
+				&num_slices_comp);
+	slice_output = (struct vidc_1080p_enc_slice_batch_out_param *)
+		encoder->batch_frame.slice_batch_out.align_virtual_addr;
+	encoder->slice_delivery_info.num_slices_enc += num_slices_comp;
+	if (vidc_msg_timing) {
+		ddl_calc_core_proc_time_cnt(__func__, ENC_OP_TIME,
+					num_slices_comp);
+	}
+	DDL_MSG_LOW("%s Slices Completed %d Total slices done = %d"
+		" OutBfrInfo: Cmd %d Size %d",
+		__func__,
+		num_slices_comp,
+		encoder->slice_delivery_info.num_slices_enc,
+		slice_output->cmd_type,
+		slice_output->output_size);
+	start_bfr_idx = encoder->batch_frame.out_frm_next_frmindex;
+	if ((encoder->slice_delivery_info.num_slices_enc %
+		encoder->batch_frame.num_output_frames) != 0) {
+		DDL_MSG_ERROR("ERROR : %d %d\n",
+		encoder->slice_delivery_info.num_slices_enc,
+		encoder->batch_frame.num_output_frames);
+	}
+	for (index = 0; index < num_slices_comp; index++) {
+		actual_idx =
+			slice_output->slice_info[start_bfr_idx+index]. \
+			stream_buffer_idx;
+		DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d",
+			actual_idx,
+			slice_output->slice_info[start_bfr_idx+index]. \
+			stream_buffer_size, 0);
+		output_frame =
+		&(encoder->batch_frame.output_frame[actual_idx].vcd_frm);
+		DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+				"frmbfr(physical) 0x%x",
+				&output_frame,
+				output_frame.virtual_base_addr,
+				output_frame.physical_base_addr);
+		vidc_1080p_get_encode_frame_info(
+			&encoder->enc_frame_info);
+		vidc_sm_get_frame_tags(&ddl->shared_mem
+			[ddl->command_channel],
+			&output_frame->ip_frm_tag, &bottom_frame_tag);
+		ddl_get_encoded_frame(output_frame,
+				encoder->codec.codec,
+				encoder->enc_frame_info.enc_frame);
+		output_frame->data_len =
+			slice_output->slice_info[actual_idx].stream_buffer_size;
+		ddl->output_frame =
+			encoder->batch_frame.output_frame[actual_idx];
+		DDL_MSG_LOW(" %s actual_idx = %d"
+		"encoder->batch_frame.num_output_frames = %d\n", __func__,
+		actual_idx, encoder->batch_frame.num_output_frames);
+		if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
+			output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+			ddl_vidc_encode_dynamic_property(ddl, false);
+			ddl->input_frame.frm_trans_end = true;
+			DDL_MSG_LOW("%s End of frame detected\n", __func__);
+			input_buffer_address =
+				ddl_context->dram_base_a.align_physical_addr +
+				encoder->enc_frame_info.enc_luma_address;
+			ddl_get_input_frame_from_pool(ddl,
+				input_buffer_address);
+			transc = (struct vcd_transc *)(ddl->client_data);
+			if (eos_present)
+				ddl->output_frame.frm_trans_end = false;
+			else
+				ddl->output_frame.frm_trans_end = true;
+		}
+		DDL_MSG_LOW("%s Before output done cb\n", __func__);
+		transc = (struct vcd_transc *)(ddl->client_data);
+		ddl->output_frame.vcd_frm = *output_frame;
+		ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+				VCD_S_SUCCESS, &(ddl->output_frame),
+				sizeof(struct ddl_frame_data_tag),
+				(u32 *) ddl, ddl->client_data);
+	}
+	if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
+		DDL_MSG_LOW("%s sending input done\n", __func__);
+		ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
+				VCD_S_SUCCESS, &(ddl->input_frame),
+				sizeof(struct ddl_frame_data_tag),
+				(u32 *) ddl, ddl->client_data);
+	}
 }
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 7b284e9..2138c9c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -287,6 +287,9 @@
 				ddl_set_default_decoder_buffer_req(decoder,
 					true);
 			}
+			DDL_MSG_LOW("set  VCD_I_FRAME_SIZE width = %d"
+				" height = %d\n",
+				frame_size->width, frame_size->height);
 			vcd_status = VCD_S_SUCCESS;
 		}
 	}
@@ -608,7 +611,15 @@
 		struct vcd_property_multi_slice *multi_slice =
 			(struct vcd_property_multi_slice *)
 				property_value;
-
+		DDL_MSG_HIGH("VCD_I_MULTI_SLICE eMSliceSel %d  nMSliceSize %d"
+				"Tot#of MB %d encoder->frame_size.width = %d"
+				"encoder->frame_size.height = %d",
+				(int)multi_slice->m_slice_sel,
+				multi_slice->m_slice_size,
+				DDL_NO_OF_MB(encoder->frame_size.width,
+					encoder->frame_size.height),
+				encoder->frame_size.width,
+				encoder->frame_size.height);
 		switch (multi_slice->m_slice_sel) {
 		case VCD_MSLICE_OFF:
 			vcd_status = VCD_S_SUCCESS;
@@ -618,11 +629,14 @@
 				vcd_status = VCD_S_SUCCESS;
 		break;
 		case VCD_MSLICE_BY_MB_COUNT:
-			if (multi_slice->m_slice_size >= 1 &&
+		{
+			if ((multi_slice->m_slice_size >= 1) &&
 				(multi_slice->m_slice_size <=
 				DDL_NO_OF_MB(encoder->frame_size.width,
-				encoder->frame_size.height)))
+					encoder->frame_size.height))) {
 				vcd_status = VCD_S_SUCCESS;
+			}
+		}
 		break;
 		case VCD_MSLICE_BY_BYTE_COUNT:
 			if (multi_slice->m_slice_size > 0)
@@ -850,6 +864,9 @@
 			encoder->client_output_buf_req.sz =
 				DDL_ALIGN(buffer_req->sz,
 				DDL_KILO_BYTE(4));
+			DDL_MSG_LOW("%s encoder->client_output_buf_req.sz"
+				"  = %d\n", __func__,
+				encoder->client_output_buf_req.sz);
 			vcd_status = VCD_S_SUCCESS;
 		}
 	}
@@ -920,8 +937,14 @@
 	case VCD_I_METADATA_HEADER:
 		DDL_MSG_LOW("Meta Data Interface is Requested");
 		if (!res_trk_check_for_sec_session()) {
-			vcd_status = ddl_set_metadata_params(ddl,
-				property_hdr, property_value);
+			if (!encoder->slice_delivery_info.enable) {
+				vcd_status = ddl_set_metadata_params(ddl,
+						property_hdr, property_value);
+			} else {
+				DDL_MSG_ERROR("Ignoring meta data settting in "
+					"slice mode: %s\n", __func__);
+				vcd_status = VCD_S_SUCCESS;
+			}
 		} else {
 			DDL_MSG_ERROR("Meta Data Interface is not "
 				"supported in secure session");
@@ -946,6 +969,70 @@
 		}
 		break;
 	}
+	case VCD_I_SLICE_DELIVERY_MODE:
+	{
+		size_t output_buf_size;
+		u32 num_mb, num_slices;
+		struct vcd_property_hdr slice_property_hdr;
+		struct vcd_property_meta_data_enable slice_meta_data;
+		DDL_MSG_HIGH("Set property VCD_I_SLICE_DELIVERY_MODE\n");
+		if (sizeof(u32) == property_hdr->sz &&
+			encoder->codec.codec == VCD_CODEC_H264 &&
+			encoder->multi_slice.m_slice_sel
+				 == VCD_MSLICE_BY_MB_COUNT &&
+			DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+			encoder->slice_delivery_info.enable
+				= *(u32 *)property_value;
+			DDL_MSG_HIGH("set encoder->slice_delivery_mode"
+				"  = %u\n",
+				encoder->slice_delivery_info.enable);
+			output_buf_size =
+				encoder->client_output_buf_req.sz;
+			num_mb = DDL_NO_OF_MB(encoder->frame_size.width,
+					encoder->frame_size.height);
+			num_slices = num_mb/
+				encoder->multi_slice.m_slice_size;
+			num_slices = ((num_mb - num_slices *
+				encoder->multi_slice.m_slice_size) > 0)
+				? (num_slices + 1) : num_slices;
+			encoder->slice_delivery_info.num_slices =
+				num_slices;
+			if (num_slices <= DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH) {
+				encoder->client_output_buf_req.min_count
+				= ((DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2)
+				> DDL_MAX_BUFFER_COUNT)
+				? DDL_MAX_BUFFER_COUNT :
+				(DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2);
+				output_buf_size =
+				encoder->client_output_buf_req.sz/num_slices;
+				encoder->client_output_buf_req.sz =
+				DDL_ALIGN(output_buf_size, DDL_KILO_BYTE(4));
+				encoder->output_buf_req =
+				encoder->client_output_buf_req;
+				DDL_MSG_HIGH("%s num_mb = %u num_slices = %u "
+				"output_buf_count = %u "
+				"output_buf_size = %u aligned size = %u\n",
+				__func__, num_mb, num_slices,
+				encoder->client_output_buf_req.min_count,
+				output_buf_size,
+				encoder->client_output_buf_req.sz);
+				slice_property_hdr.prop_id =
+					VCD_I_METADATA_ENABLE;
+				slice_property_hdr.sz =
+				sizeof(struct vcd_property_meta_data_enable);
+				ddl_get_metadata_params(ddl,
+						&slice_property_hdr,
+						&slice_meta_data);
+				slice_meta_data.meta_data_enable_flag
+					&= ~VCD_METADATA_ENC_SLICE;
+				ddl_set_metadata_params(ddl,
+						&slice_property_hdr,
+						&slice_meta_data);
+				vcd_status = VCD_S_SUCCESS;
+			}
+		}
+		break;
+	}
 	case VCD_REQ_PERF_LEVEL:
 		vcd_status = VCD_S_SUCCESS;
 		break;
@@ -1354,7 +1441,10 @@
 			property_hdr->sz) {
 				*(struct vcd_buffer_requirement *)
 			property_value = encoder->client_output_buf_req;
-				vcd_status = VCD_S_SUCCESS;
+			DDL_MSG_LOW("%s encoder->client_output_buf_req = %d\n",
+				 __func__,
+				encoder->client_output_buf_req.sz);
+			vcd_status = VCD_S_SUCCESS;
 		}
 	break;
 	case VCD_I_BUFFER_FORMAT:
@@ -1421,6 +1511,14 @@
 			vcd_status = VCD_S_SUCCESS;
 		}
 	break;
+	case VCD_I_SLICE_DELIVERY_MODE:
+		if (sizeof(struct vcd_property_slice_delivery_info) ==
+			property_hdr->sz) {
+			*(struct vcd_property_slice_delivery_info *)
+				property_value = encoder->slice_delivery_info;
+			vcd_status = VCD_S_SUCCESS;
+		}
+		break;
 	default:
 		vcd_status = VCD_ERR_ILLEGAL_OP;
 		break;
@@ -1579,6 +1677,9 @@
 		encoder->closed_gop = true;
 	ddl_set_default_metadata_flag(ddl);
 	ddl_set_default_encoder_buffer_req(encoder);
+	encoder->slice_delivery_info.enable = 0;
+	encoder->slice_delivery_info.num_slices = 0;
+	encoder->slice_delivery_info.num_slices_enc = 0;
 }
 
 static void ddl_set_default_enc_profile(struct ddl_encoder_data *encoder)
@@ -1725,8 +1826,7 @@
 	encoder->client_input_buf_req = encoder->input_buf_req;
 	memset(&encoder->output_buf_req , 0 ,
 		sizeof(struct vcd_buffer_requirement));
-	encoder->output_buf_req.min_count    =
-		encoder->i_period.b_frames + 2;
+	encoder->output_buf_req.min_count = encoder->i_period.b_frames + 2;
 	encoder->output_buf_req.actual_count =
 		encoder->output_buf_req.min_count + 3;
 	encoder->output_buf_req.max_count    = DDL_MAX_BUFFER_COUNT;
@@ -1737,6 +1837,8 @@
 		DDL_ALIGN(y_cb_cr_size, DDL_KILO_BYTE(4));
 	ddl_set_default_encoder_metadata_buffer_size(encoder);
 	encoder->client_output_buf_req = encoder->output_buf_req;
+	DDL_MSG_LOW("%s encoder->client_output_buf_req.sz = %d\n",
+		__func__, encoder->client_output_buf_req.sz);
 }
 
 u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index cce779e..ac81916 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -156,6 +156,24 @@
 #define VIDC_SM_NEW_I_PERIOD_VALUE_BMASK       0xffffffff
 #define VIDC_SM_NEW_I_PERIOD_VALUE_SHFT        0
 
+#define VIDC_SM_BATCH_INPUT_ADDR                                  0x00a4
+#define VIDC_SM_BATCH_INPUT_ADDR_VALUE_BMSK                       0xffffffff
+#define VIDC_SM_BATCH_INPUT_ADDRL_VALUE_SHFT                      0
+#define VIDC_SM_BATCH_OUTPUT_ADDR                                 0x00a8
+#define VIDC_SM_BATCH_OUTPUT_ADDR_VALUE_BMSK                      0xffffffff
+#define VIDC_SM_BATCH_OUTPUT_ADDR_VALUE_SHFT                      0
+#define VIDC_SM_BATCH_OUTPUT_SIZE_ADDR                            0x00ac
+#define VIDC_SM_BATCH_OUTPUT_SIZE_VALUE_BMSK                      0xffffffff
+#define VIDC_SM_BATCH_OUTPUT_SIZE_VALUE_SHFT                      0
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_ADDR                     0x01c8
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_VALUE_BMSK               0x1
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_VALUE_SHFT               0
+#define VIDC_SM_ENC_NUM_OF_SLICE_ADDR                             0x01cc
+#define VIDC_SM_ENC_NUM_OF_SLICE_VALUE_BMSK                       0xffffffff
+#define VIDC_SM_ENC_NUM_OF_SLICE_VALUE_SHFT                       0
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_ADDR                        0x01d0
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_VALUE_BMSK                  0xffffffff
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_VALUE_SHFT                  0
 
 #define VIDC_SM_ALLOCATED_LUMA_DPB_SIZE_ADDR               0x0064
 #define VIDC_SM_ALLOCATED_CHROMA_DPB_SIZE_ADDR             0x0068
@@ -799,3 +817,48 @@
 			VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
 	}
 }
+
+void vidc_sm_set_encoder_slice_batch_int_ctrl(struct ddl_buf_addr *shared_mem,
+	u32 slice_batch_int_enable)
+{
+	u32 slice_batch_int_ctrl = VIDC_SETFIELD((slice_batch_int_enable) ?
+				1 : 0,
+				VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_SHFT,
+				VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_BMSK);
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_ADDR,
+			slice_batch_int_ctrl);
+}
+
+void vidc_sm_get_num_slices_comp(struct ddl_buf_addr *shared_mem,
+	u32 *num_slices_comp)
+{
+	*num_slices_comp = DDL_MEM_READ_32(shared_mem,
+				VIDC_SM_ENC_NUM_OF_SLICE_COMP_ADDR);
+}
+
+void vidc_sm_set_encoder_batch_config(struct ddl_buf_addr *shared_mem,
+				u32 num_slices,
+				u32 input_addr, u32 output_addr,
+				u32 output_buffer_size)
+{
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_ENC_NUM_OF_SLICE_ADDR,
+			num_slices);
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_BATCH_INPUT_ADDR,
+			input_addr);
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_BATCH_OUTPUT_ADDR,
+			output_addr);
+	DDL_MEM_WRITE_32(shared_mem,
+			VIDC_SM_BATCH_OUTPUT_SIZE_ADDR,
+			output_buffer_size);
+}
+
+void vidc_sm_get_encoder_batch_output_size(struct ddl_buf_addr *shared_mem,
+	u32 *output_buffer_size)
+{
+	*output_buffer_size = DDL_MEM_READ_32(shared_mem,
+			VIDC_SM_BATCH_OUTPUT_SIZE_ADDR);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
index b0e6758..7d9896f 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -181,4 +181,14 @@
 	enum vidc_sm_num_stuff_bytes_consume_info consume_info);
 void vidc_sm_get_aspect_ratio_info(struct ddl_buf_addr *shared_mem,
 	struct vcd_aspect_ratio *aspect_ratio_info);
+void vidc_sm_set_encoder_slice_batch_int_ctrl(struct ddl_buf_addr *shared_mem,
+	u32 slice_batch_int_enable);
+void vidc_sm_get_num_slices_comp(struct ddl_buf_addr *shared_mem,
+	u32 *num_slices_comp);
+void vidc_sm_set_encoder_batch_config(struct ddl_buf_addr *shared_mem,
+				u32 num_slices,
+				u32 input_addr, u32 output_addr,
+				u32 output_buffer_size);
+void vidc_sm_get_encoder_batch_output_size(struct ddl_buf_addr *shared_mem,
+	u32 *output_buffer_size);
 #endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 126698c..27d3b5b 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -385,6 +385,36 @@
 	}
 }
 
+void ddl_calc_core_proc_time_cnt(const char *func_name, u32 index, u32 count)
+{
+	struct time_data *time_data = &proc_time[index];
+	if (time_data->ddl_t1) {
+		int ddl_t2;
+		struct timeval ddl_tv;
+		do_gettimeofday(&ddl_tv);
+		ddl_t2 = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+		time_data->ddl_ttotal += (ddl_t2 - time_data->ddl_t1);
+		time_data->ddl_count += count;
+		DDL_MSG_TIME("\n%s(): cnt(%u) End Time (%u) Diff(%u) Avg(%u)",
+			func_name, time_data->ddl_count, ddl_t2,
+			ddl_t2 - time_data->ddl_t1,
+			time_data->ddl_ttotal/time_data->ddl_count);
+		time_data->ddl_t1 = 0;
+	}
+}
+
+void ddl_update_core_start_time(const char *func_name, u32 index)
+{
+	u32 act_time;
+	struct timeval ddl_tv;
+	struct time_data *time_data = &proc_time[index];
+	do_gettimeofday(&ddl_tv);
+	act_time = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+	time_data->ddl_t1 = act_time;
+	DDL_MSG_LOW("\n%s(): Start time updated Act(%u)",
+				func_name, act_time);
+}
+
 void ddl_reset_core_time_variables(u32 index)
 {
 	proc_time[index].ddl_t1 = 0;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
index 10b3404..13bef35 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -24,6 +24,7 @@
 	DEC_OP_TIME,
 	DEC_IP_TIME,
 	ENC_OP_TIME,
+	ENC_SLICE_OP_TIME,
 	MAX_TIME_DATA
 };
 
@@ -65,9 +66,12 @@
 
 #define DDL_MIN(x, y)  ((x < y) ? x : y)
 #define DDL_MAX(x, y)  ((x > y) ? x : y)
+#define DDL_MEMCPY(dest, src, len)  memcpy((dest), (src), (len))
+#define DDL_MEMSET(src, value, len) memset((src), (value), (len))
 
 void ddl_set_core_start_time(const char *func_name, u32 index);
 void ddl_calc_core_proc_time(const char *func_name, u32 index);
 void ddl_reset_core_time_variables(u32 index);
-
+void ddl_calc_core_proc_time_cnt(const char *func_name, u32 index, u32 count);
+void ddl_update_core_start_time(const char *func_name, u32 index);
 #endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index 66e129c..d288ba3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -21,6 +21,7 @@
 #else
 #define DDL_PIX_CACHE_ENABLE  true
 #endif
+static unsigned int run_cnt;
 
 void ddl_vidc_core_init(struct ddl_context *ddl_context)
 {
@@ -57,6 +58,10 @@
 		vidc_1080p_encode_frame_start_ch0;
 	ddl_context->vidc_encode_frame_start[1] =
 		vidc_1080p_encode_frame_start_ch1;
+	ddl_context->vidc_encode_slice_batch_start[0] =
+		vidc_1080p_encode_slice_batch_start_ch0;
+	ddl_context->vidc_encode_slice_batch_start[1] =
+		vidc_1080p_encode_slice_batch_start_ch1;
 	vidc_1080p_release_sw_reset();
 	ddl_context->pix_cache_enable = DDL_PIX_CACHE_ENABLE;
 	if (ddl_context->pix_cache_enable) {
@@ -515,6 +520,29 @@
 		i_multi_slice_size, i_multi_slice_byte);
 }
 
+static void ddl_vidc_encode_set_batch_slice_info(
+	struct ddl_client_context *ddl)
+{
+	struct ddl_context *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+	DDL_MSG_LOW("%s\n", __func__);
+	encoder->batch_frame.slice_batch_out.buffer_size =
+					encoder->output_buf_req.sz;
+	DDL_MSG_LOW("encoder->batch_frame.slice_batch_out.buffer_size = %d\n",
+			encoder->batch_frame.slice_batch_out.buffer_size);
+	vidc_sm_set_encoder_batch_config(
+			&ddl->shared_mem[ddl->command_channel],
+			1,
+			DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+			encoder->batch_frame.slice_batch_in),
+			DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+			encoder->batch_frame.slice_batch_out),
+			encoder->batch_frame.slice_batch_out.buffer_size);
+	vidc_sm_set_encoder_slice_batch_int_ctrl(
+			&ddl->shared_mem[ddl->command_channel],
+			0);
+}
+
 void ddl_vidc_encode_init_codec(struct ddl_client_context *ddl)
 {
 	struct ddl_context *ddl_context = ddl->ddl_context;
@@ -724,6 +752,7 @@
 	u32 dpb_addr_y[4], dpb_addr_c[4];
 	u32 index, y_addr, c_addr;
 
+	DDL_MSG_LOW("%s\n", __func__);
 	ddl_vidc_encode_set_metadata_output_buf(ddl);
 
 	encoder->enc_frame_info.meta_data_exists = false;
@@ -769,6 +798,7 @@
 	if (encoder->intra_frame_insertion)
 		encoder->intra_frame_insertion = false;
 	enc_param.input_flush = false;
+	enc_param.slice_enable = false;
 		vidc_sm_set_encoder_vop_time(
 			&ddl->shared_mem[ddl->command_channel], true,
 			encoder->vop_timing.vop_time_resolution,
@@ -800,6 +830,142 @@
 		&enc_param);
 }
 
+void ddl_vidc_encode_frame_continue(struct ddl_client_context *ddl)
+{
+	struct ddl_context *ddl_context = ddl->ddl_context;
+	struct vcd_frame_data *input_vcd_frm = &(ddl->input_frame.vcd_frm);
+	u32 address_offset;
+	address_offset = (u32)(ddl->output_frame.vcd_frm.physical -
+			ddl_context->dram_base_a.align_physical_addr) >>
+			DDL_VIDC_1080P_BASE_OFFSET_SHIFT;
+	DDL_MSG_LOW("%s\n", __func__);
+	if (VCD_FRAME_FLAG_EOS & input_vcd_frm->flags)
+		ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+	else
+		ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+	ddl->cmd_state = DDL_CMD_ENCODE_CONTINUE;
+	vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_CONTINUE_ENC,
+		address_offset,
+		0, 0, 0);
+}
+
+void ddl_vidc_encode_slice_batch_run(struct ddl_client_context *ddl)
+{
+	struct vidc_1080p_enc_frame_start_param enc_param;
+	struct ddl_context *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data  *encoder = &(ddl->codec_data.encoder);
+	struct ddl_enc_buffers *enc_buffers = &(encoder->hw_bufs);
+	struct vcd_frame_data *input_vcd_frm =
+		&(ddl->input_frame.vcd_frm);
+	u32 dpb_addr_y[4], dpb_addr_c[4];
+	u32 index, y_addr, c_addr;
+	u32 bitstream_size;
+	struct vidc_1080p_enc_slice_batch_in_param *slice_batch_in =
+		(struct vidc_1080p_enc_slice_batch_in_param *)
+		encoder->batch_frame.slice_batch_in.align_virtual_addr;
+	DDL_MSG_LOW("%s\n", __func__);
+	DDL_MEMSET(slice_batch_in, 0,
+		sizeof(struct vidc_1080p_enc_slice_batch_in_param));
+	DDL_MEMSET(encoder->batch_frame.slice_batch_in.align_virtual_addr, 0,
+		sizeof(struct vidc_1080p_enc_slice_batch_in_param));
+	encoder->batch_frame.out_frm_next_frmindex = 0;
+	bitstream_size = encoder->batch_frame.output_frame[0].vcd_frm.alloc_len;
+	encoder->output_buf_req.sz = bitstream_size;
+	y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
+			input_vcd_frm->physical);
+	c_addr = (y_addr + encoder->input_buf_size.size_y);
+	enc_param.encode = VIDC_1080P_ENC_TYPE_SLICE_BATCH_START;
+	DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+		"DDL_CLIENT_WAIT_FOR_FRAME_DONE",
+		ddl_get_state_string(ddl->client_state));
+	slice_batch_in->cmd_type = VIDC_1080P_ENC_TYPE_SLICE_BATCH_START;
+	ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+	ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+	vidc_1080p_set_encode_circular_intra_refresh(
+		encoder->intra_refresh.cir_mb_number);
+	ddl_vidc_encode_set_multi_slice_info(encoder);
+	enc_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+	enc_param.inst_id = ddl->instance_id;
+	enc_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+			ddl_context->dram_base_a,
+			ddl->shared_mem[ddl->command_channel]);
+	enc_param.current_y_addr_offset = y_addr;
+	enc_param.current_c_addr_offset = c_addr;
+	enc_param.stream_buffer_size = bitstream_size;
+	slice_batch_in->num_stream_buffer =
+		encoder->batch_frame.num_output_frames;
+	slice_batch_in->stream_buffer_size = bitstream_size;
+	DDL_MSG_LOW("%s slice_batch_in->num_stream_buffer = %u size = %u\n",
+			 __func__, slice_batch_in->num_stream_buffer,
+			slice_batch_in->stream_buffer_size);
+	for (index = 0; index < encoder->batch_frame.num_output_frames;
+		index++) {
+		slice_batch_in->stream_buffer_addr_offset[index] =
+		((DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
+		encoder->batch_frame.output_frame[index].vcd_frm.physical)) >>
+			DDL_VIDC_1080P_BASE_OFFSET_SHIFT);
+	}
+	slice_batch_in->input_size = VIDC_1080P_SLICE_BATCH_IN_SIZE(index);
+	enc_param.intra_frame = encoder->intra_frame_insertion;
+	if (encoder->intra_frame_insertion)
+		encoder->intra_frame_insertion = false;
+	enc_param.input_flush = false;
+	enc_param.slice_enable =
+		encoder->slice_delivery_info.enable;
+	vidc_sm_set_encoder_vop_time(
+			&ddl->shared_mem[ddl->command_channel], true,
+			encoder->vop_timing.vop_time_resolution,
+			ddl->input_frame.frm_delta);
+	vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+			ddl->input_frame.vcd_frm.ip_frm_tag);
+	DDL_MSG_LOW("%sdpb_count = %d\n", __func__, enc_buffers->dpb_count);
+	if (ddl_context->pix_cache_enable) {
+		for (index = 0; index < enc_buffers->dpb_count;
+			index++) {
+			dpb_addr_y[index] =
+				(u32) VIDC_1080P_DEC_DPB_RESET_VALUE;
+			dpb_addr_c[index] = (u32) enc_buffers->dpb_c
+				[index].align_physical_addr;
+		}
+
+		dpb_addr_y[index] = (u32) input_vcd_frm->physical;
+		dpb_addr_c[index] = (u32) input_vcd_frm->physical +
+				encoder->input_buf_size.size_y;
+
+		vidc_pix_cache_init_luma_chroma_base_addr(
+			enc_buffers->dpb_count + 1, dpb_addr_y, dpb_addr_c);
+		vidc_pix_cache_set_frame_size(encoder->frame_size.width,
+			encoder->frame_size.height);
+		vidc_pix_cache_set_frame_range(enc_buffers->sz_dpb_y,
+			enc_buffers->sz_dpb_c);
+		vidc_pix_cache_clear_cache_tags();
+	}
+	if ((!encoder->rc_level.frame_level_rc) &&
+		(!encoder->rc_level.mb_level_rc)) {
+		encoder->session_qp.p_frame_qp++;
+		if (encoder->session_qp.p_frame_qp > encoder->qp_range.max_qp)
+			encoder->session_qp.p_frame_qp =
+						encoder->qp_range.min_qp;
+		vidc_sm_set_pand_b_frame_qp(
+			&ddl->shared_mem[ddl->command_channel],
+				encoder->session_qp.b_frame_qp,
+				encoder->session_qp.p_frame_qp);
+	}
+
+	if (vidc_msg_timing) {
+		if (run_cnt < 2) {
+			ddl_reset_core_time_variables(ENC_OP_TIME);
+			ddl_reset_core_time_variables(ENC_SLICE_OP_TIME);
+			run_cnt++;
+		 }
+		ddl_update_core_start_time(__func__, ENC_SLICE_OP_TIME);
+		ddl_set_core_start_time(__func__, ENC_OP_TIME);
+	}
+	ddl_vidc_encode_set_batch_slice_info(ddl);
+	ddl_context->vidc_encode_slice_batch_start[ddl->command_channel] (
+			&enc_param);
+}
+
 u32 ddl_vidc_decode_set_buffers(struct ddl_client_context *ddl)
 {
 	struct ddl_context *ddl_context = ddl->ddl_context;
@@ -976,3 +1142,29 @@
 	ddl_context->vidc_decode_frame_start[ddl->command_channel] (
 		&dec_param);
 }
+
+void ddl_vidc_encode_eos_run(struct ddl_client_context *ddl)
+{
+	struct vidc_1080p_enc_frame_start_param enc_param;
+	struct ddl_context *ddl_context = ddl->ddl_context;
+	struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+	DDL_MSG_LOW("%s\n", __func__);
+	ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+	ddl_vidc_encode_dynamic_property(ddl, true);
+	ddl->client_state = DDL_CMD_EOS;
+	DDL_MEMSET(&enc_param, 0, sizeof(enc_param));
+	enc_param.encode = VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA;
+	enc_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+	enc_param.inst_id = ddl->instance_id;
+	enc_param.shared_mem_addr_offset =
+		DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+		ddl->shared_mem[ddl->command_channel]);
+	enc_param.current_y_addr_offset = 0;
+	enc_param.current_c_addr_offset = 0;
+	enc_param.stream_buffer_size = 0;
+	enc_param.intra_frame = encoder->intra_frame_insertion;
+	vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+				ddl->input_frame.vcd_frm.ip_frm_tag);
+	ddl_context->vidc_encode_frame_start[ddl->command_channel](
+						&enc_param);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c
index 75014cc..d399847 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -77,6 +77,10 @@
 #define VIDC_1080P_ENC_TYPE_FRAME_DATA       0x00020000
 #define VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA  0x00030000
 
+#define VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK   0x00004000
+#define VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT   14
+#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK      0x80000000
+#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT      31
 #define VIDC_1080P_MAX_INTRA_PERIOD 0xffff
 
 u8 *VIDC_BASE_PTR;
@@ -779,6 +783,7 @@
 void vidc_1080p_encode_frame_start_ch0(
 	struct vidc_1080p_enc_frame_start_param *param)
 {
+	u32 input_flush;
 	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
 	VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
 	VIDC_HWIO_OUT(REG_117192,
@@ -791,8 +796,15 @@
 		VIDC_1080P_BASE_OFFSET_SHIFT);
 	VIDC_HWIO_OUT(REG_190381, param->intra_frame);
 	VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
-	VIDC_HWIO_OUT(REG_404623, param->input_flush);
+	input_flush = VIDC_SETFIELD(param->input_flush,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+	input_flush |= VIDC_SETFIELD(param->slice_enable,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+	VIDC_HWIO_OUT(REG_404623, input_flush);
 	VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+
 	VIDC_HWIO_OUT(REG_666957, (u32)param->encode |
 		param->inst_id);
 }
@@ -800,7 +812,7 @@
 void vidc_1080p_encode_frame_start_ch1(
 	struct vidc_1080p_enc_frame_start_param *param)
 {
-
+	u32 input_flush;
 	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
 	VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
 	VIDC_HWIO_OUT(REG_980194,
@@ -813,12 +825,71 @@
 		VIDC_1080P_BASE_OFFSET_SHIFT);
 	VIDC_HWIO_OUT(REG_887095, param->intra_frame);
 	VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
-	VIDC_HWIO_OUT(REG_404623, param->input_flush);
+	input_flush = VIDC_SETFIELD(param->input_flush,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+	input_flush |= VIDC_SETFIELD(param->slice_enable,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+
+	VIDC_HWIO_OUT(REG_404623, input_flush);
 	VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
 	VIDC_HWIO_OUT(REG_313350, (u32)param->encode |
 		param->inst_id);
 }
 
+void vidc_1080p_encode_slice_batch_start_ch0(
+	struct vidc_1080p_enc_frame_start_param *param)
+{
+	u32 input_flush;
+	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+	VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+	VIDC_HWIO_OUT(REG_612810, param->current_y_addr_offset >>
+		VIDC_1080P_BASE_OFFSET_SHIFT);
+	VIDC_HWIO_OUT(REG_175608, param->current_c_addr_offset >>
+		VIDC_1080P_BASE_OFFSET_SHIFT);
+	VIDC_HWIO_OUT(REG_190381, param->intra_frame);
+	VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
+	input_flush = VIDC_SETFIELD(param->input_flush,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+	input_flush |= VIDC_SETFIELD(param->slice_enable,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+	VIDC_HWIO_OUT(REG_404623, input_flush);
+	VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+
+	VIDC_HWIO_OUT(REG_666957, (u32)param->encode |
+		param->inst_id);
+
+}
+
+void vidc_1080p_encode_slice_batch_start_ch1(
+	struct vidc_1080p_enc_frame_start_param *param)
+{
+	u32 input_flush;
+	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+	VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+	VIDC_HWIO_OUT(REG_655721, param->current_y_addr_offset >>
+		VIDC_1080P_BASE_OFFSET_SHIFT);
+	VIDC_HWIO_OUT(REG_548308,  param->current_c_addr_offset >>
+		VIDC_1080P_BASE_OFFSET_SHIFT);
+	VIDC_HWIO_OUT(REG_887095, param->intra_frame);
+	VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
+	input_flush = VIDC_SETFIELD(param->input_flush,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+	input_flush |= VIDC_SETFIELD(param->slice_enable,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+			VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+
+	VIDC_HWIO_OUT(REG_404623, input_flush);
+	VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
+	VIDC_HWIO_OUT(REG_313350, (u32)param->encode |
+		param->inst_id);
+
+}
+
 void vidc_1080p_set_encode_picture(u32 number_p, u32 number_b)
 {
 	u32 picture, ifrm_ctrl;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
index 7573ee8..7460ef3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -21,11 +21,13 @@
 #define VIDC_1080P_RISC2HOST_CMD_CLOSE_CH_RET        2
 #define VIDC_1080P_RISC2HOST_CMD_SEQ_DONE_RET        4
 #define VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET      5
+#define VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET      6
 #define VIDC_1080P_RISC2HOST_CMD_ENC_COMPLETE_RET    7
 #define VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET        8
 #define VIDC_1080P_RISC2HOST_CMD_FW_STATUS_RET       9
 #define VIDC_1080P_RISC2HOST_CMD_FLUSH_COMMAND_RET  12
 #define VIDC_1080P_RISC2HOST_CMD_ABORT_RET          13
+#define VIDC_1080P_RISC2HOST_CMD_BATCH_ENC_RET      14
 #define VIDC_1080P_RISC2HOST_CMD_INIT_BUFFERS_RET   15
 #define VIDC_1080P_RISC2HOST_CMD_EDFU_INT_RET       16
 #define VIDC_1080P_RISC2HOST_CMD_ERROR_RET          32
@@ -188,7 +190,9 @@
 #define VIDC_1080P_ITLB_MISS_EXCEPTION_HANDLER        0x100
 #define VIDC_1080P_DATA_PAGE_FAULT_EXCEPTION_HANDLER  0x200
 #define VIDC_1080P_INST_PAGE_FAULT_EXCEPTION_HANDLER  0x400
-
+#define VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR           8
+#define VIDC_1080P_SLICE_BATCH_IN_SIZE(idx)           (4 * sizeof(u32) + \
+							idx * sizeof(u32))
 enum vidc_1080p_reset{
 	VIDC_1080P_RESET_IN_SEQ_FIRST_STAGE   = 0x0,
 	VIDC_1080P_RESET_IN_SEQ_SECOND_STAGE  = 0x1,
@@ -318,10 +322,11 @@
 	VIDC_1080P_DEC_TYPE_32BIT            = 0x7FFFFFFF
 };
 enum vidc_1080p_encode{
-	VIDC_1080P_ENC_TYPE_SEQ_HEADER       = 0x00010000,
-	VIDC_1080P_ENC_TYPE_FRAME_DATA       = 0x00020000,
-	VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA  = 0x00030000,
-	VIDC_1080P_ENC_TYPE_32BIT            = 0x7FFFFFFF
+	VIDC_1080P_ENC_TYPE_SEQ_HEADER        = 0x00010000,
+	VIDC_1080P_ENC_TYPE_FRAME_DATA        = 0x00020000,
+	VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA   = 0x00030000,
+	VIDC_1080P_ENC_TYPE_SLICE_BATCH_START = 0x00070000,
+	VIDC_1080P_ENC_TYPE_32BIT             = 0x7FFFFFFF
 };
 struct vidc_1080p_dec_seq_start_param{
 	u32 cmd_seq_num;
@@ -391,6 +396,7 @@
 	u32 stream_buffer_size;
 	u32 intra_frame;
 	u32 input_flush;
+	u32 slice_enable;
 	enum vidc_1080p_encode encode;
 };
 struct vidc_1080p_enc_frame_info{
@@ -402,6 +408,23 @@
 	enum vidc_1080p_encode_frame enc_frame;
 	u32 meta_data_exists;
 };
+struct vidc_1080p_enc_slice_batch_in_param {
+	u32 cmd_type;
+	u32 input_size;
+	u32 num_stream_buffer;
+	u32 stream_buffer_size;
+	u32 stream_buffer_addr_offset[VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR];
+};
+struct vidc_1080p_enc_slice_info {
+	u32 stream_buffer_idx;
+	u32 stream_buffer_size;
+};
+struct vidc_1080p_enc_slice_batch_out_param {
+	u32 cmd_type;
+	u32 output_size;
+	struct vidc_1080p_enc_slice_info slice_info
+		[VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR];
+};
 struct vidc_1080p_dec_disp_info{
 	u32 disp_resl_change;
 	u32 dec_resl_change;
@@ -519,6 +542,10 @@
 	struct vidc_1080p_enc_frame_start_param *param);
 void vidc_1080p_encode_frame_start_ch1(
 	struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_encode_slice_batch_start_ch0(
+	struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_encode_slice_batch_start_ch1(
+	struct vidc_1080p_enc_frame_start_param *param);
 void vidc_1080p_set_encode_picture(u32 ifrm_ctrl, u32 number_b);
 void vidc_1080p_set_encode_multi_slice_control(
 	enum vidc_1080p_MSlice_selection multiple_slice_selection,
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
index 9dc495b..7e201cf 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
@@ -57,6 +57,12 @@
 	u32 activity_region_flag;
 };
 
+struct vcd_property_slice_delivery_info {
+	u32  enable;
+	u32  num_slices;
+	u32  num_slices_enc;
+};
+
 struct ddl_frame_data_tag;
 
 struct ddl_property_dec_pic_buffers {
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index d93d07e..5542856 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1604,6 +1604,20 @@
 		}
 		if (!result) {
 			ERR("setting VEN_IOCTL_(G)SET_LIVE_MODE failed\n");
+		}
+		break;
+	}
+	case VEN_IOCTL_SET_SLICE_DELIVERY_MODE:
+	{
+		struct vcd_property_hdr vcd_property_hdr;
+		u32 vcd_status = VCD_ERR_FAIL;
+		u32 enable = true;
+		vcd_property_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
+		vcd_property_hdr.sz = sizeof(u32);
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+						&vcd_property_hdr, &enable);
+		if (vcd_status) {
+			pr_err(" Setting slice delivery mode failed");
 			return -EIO;
 		}
 		break;
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 6fdb1c6..55bbe00 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -63,7 +63,7 @@
 static irqreturn_t vidc_isr(int irq, void *dev);
 static spinlock_t vidc_spin_lock;
 
-u32 vidc_msg_timing, vidc_msg_pmem;
+u32 vidc_msg_timing, vidc_msg_pmem, vidc_msg_register;
 
 #ifdef VIDC_ENABLE_DBGFS
 struct dentry *vidc_debugfs_root;
@@ -311,6 +311,8 @@
 				(u32 *) &vidc_msg_timing);
 		vidc_debugfs_file_create(root, "vidc_msg_pmem",
 				(u32 *) &vidc_msg_pmem);
+		vidc_debugfs_file_create(root, "vidc_msg_register",
+				(u32 *) &vidc_msg_register);
 	}
 #endif
 	return 0;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index 0d1ff7e..e557dab 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -393,4 +393,6 @@
 u32 vcd_req_perf_level(struct vcd_clnt_ctxt *cctxt,
 	struct vcd_property_perf_level *);
 
+u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt);
+
 #endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index e33c8cd..d228146 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -185,6 +185,7 @@
 	u32 live;
 	u32 decoding;
 	u32 bframe;
+	u32 num_slices;
 
 	struct vcd_property_frame_rate frm_rate;
 	u32 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 fd8d02a..d49f233 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -19,6 +19,7 @@
 
 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
 #define MAP_TABLE_SZ 64
+#define VCD_ENC_MAX_OUTBFRS_PER_FRAME 8
 
 struct vcd_msm_map_buffer {
 	phys_addr_t phy_addr;
@@ -942,7 +943,6 @@
 		list_del(&entry->list);
 		pool->q_len--;
 	}
-
 	return entry;
 }
 
@@ -1122,6 +1122,7 @@
 	cctxt->bframe = 0;
 	cctxt->cmd_q.pending_cmd = VCD_CMD_NONE;
 	cctxt->status.last_evt = VCD_EVT_RESP_BASE;
+	cctxt->num_slices = 1;
 	return rc;
 }
 
@@ -1293,6 +1294,7 @@
 		}
 
 	} else {
+		vcd_set_num_slices(transc->cctxt);
 		rc = ddl_encode_start(transc->cctxt->ddl_handle,
 					  (void *)transc);
 	}
@@ -1492,7 +1494,8 @@
 	u32 rc = VCD_S_SUCCESS;
 	u32 evcode = 0;
 	struct ddl_frame_data_tag ddl_ip_frm;
-	struct ddl_frame_data_tag ddl_op_frm;
+	struct ddl_frame_data_tag *ddl_op_frm;
+	u32 out_buf_cnt = 0;
 
 	VCD_MSG_LOW("vcd_submit_frame:");
 	cctxt = transc->cctxt;
@@ -1504,34 +1507,52 @@
 	transc->flags = ip_frm_entry->flags;
 	ip_frm_entry->ip_frm_tag = (u32) transc;
 	memset(&ddl_ip_frm, 0, sizeof(ddl_ip_frm));
-	memset(&ddl_op_frm, 0, sizeof(ddl_op_frm));
 	if (cctxt->decoding) {
 		evcode = CLIENT_STATE_EVENT_NUMBER(decode_frame);
 		ddl_ip_frm.vcd_frm = *ip_frm_entry;
 		rc = ddl_decode_frame(cctxt->ddl_handle, &ddl_ip_frm,
-							   (void *) transc);
+							(void *) transc);
 	} else {
-		op_buf_entry = vcd_buffer_pool_entry_de_q(
-			&cctxt->out_buf_pool);
-		if (!op_buf_entry) {
-			VCD_MSG_ERROR("Sched provided frame when no"
-				"op buffer was present");
-			rc = VCD_ERR_FAIL;
-		} else {
+		ddl_op_frm = (struct ddl_frame_data_tag *)
+			kmalloc((sizeof(struct ddl_frame_data_tag) *
+			VCD_ENC_MAX_OUTBFRS_PER_FRAME), GFP_KERNEL);
+		if (!ddl_op_frm) {
+			VCD_MSG_ERROR("Memory allocation failure");
+			return VCD_ERR_ALLOC_FAIL;
+		}
+		memset(ddl_op_frm, 0, (sizeof(struct ddl_frame_data_tag) *
+			VCD_ENC_MAX_OUTBFRS_PER_FRAME));
+		for (out_buf_cnt = 0; out_buf_cnt < cctxt->num_slices ;
+				out_buf_cnt++) {
+			op_buf_entry = vcd_buffer_pool_entry_de_q(
+				&cctxt->out_buf_pool);
+			if (!op_buf_entry) {
+				VCD_MSG_ERROR("Sched provided frame when no"
+					"op buffer was present");
+				rc = VCD_ERR_FAIL;
+				break;
+			}
 			op_buf_entry->in_use = true;
 			cctxt->out_buf_pool.in_use++;
-			ddl_ip_frm.vcd_frm = *ip_frm_entry;
-			ddl_ip_frm.frm_delta =
-				vcd_calculate_frame_delta(cctxt,
-					ip_frm_entry);
-
-			ddl_op_frm.vcd_frm = op_buf_entry->frame;
-
-			evcode = CLIENT_STATE_EVENT_NUMBER(encode_frame);
-
-			rc = ddl_encode_frame(cctxt->ddl_handle,
-				&ddl_ip_frm, &ddl_op_frm, (void *) transc);
+			ddl_op_frm[out_buf_cnt].vcd_frm = op_buf_entry->frame;
+			VCD_MSG_LOW("%s : buffer_cnt = %d framebfr(virtual)"
+				" 0x%p", __func__, out_buf_cnt,
+				op_buf_entry->frame.virtual);
+			VCD_MSG_LOW("framebfr(physical) 0x%p bfrlength %d",
+				op_buf_entry->frame.physical,
+				op_buf_entry->frame.alloc_len);
 		}
+		ddl_ip_frm.vcd_frm = *ip_frm_entry;
+		ddl_ip_frm.frm_delta =
+			vcd_calculate_frame_delta(cctxt,
+				ip_frm_entry);
+		evcode = CLIENT_STATE_EVENT_NUMBER(encode_frame);
+
+		if (!VCD_FAILED(rc)) {
+			rc = ddl_encode_frame(cctxt->ddl_handle,
+				&ddl_ip_frm, &ddl_op_frm[0], (void *) transc);
+		}
+		kfree(ddl_op_frm);
 	}
 	ip_frm_entry->ip_frm_tag = transc->ip_frm_tag;
 	if (!VCD_FAILED(rc)) {
@@ -1875,8 +1896,10 @@
 
 void vcd_release_trans_tbl_entry(struct vcd_transc *trans_entry)
 {
-	if (trans_entry)
+	if (trans_entry) {
 		trans_entry->in_use = false;
+		VCD_MSG_LOW("%s in_use set to false\n", __func__);
+	}
 }
 
 u32 vcd_handle_input_done(
@@ -1888,6 +1911,7 @@
 		(struct ddl_frame_data_tag *) payload;
 	struct vcd_buffer_entry *orig_frame = NULL;
 	u32 rc;
+	VCD_MSG_LOW("%s\n", __func__);
 
 	if (!cctxt->status.frame_submitted &&
 		!cctxt->status.frame_delayed) {
@@ -1935,8 +1959,11 @@
 	transc->ip_buf_entry = NULL;
 	transc->input_done = true;
 
-	if (transc->input_done && transc->frame_done)
+	if (transc->input_done && transc->frame_done) {
+		VCD_MSG_LOW("%s Calling vcd_release_trans_tbl_entry\n",
+		__func__);
 		vcd_release_trans_tbl_entry(transc);
+	}
 
 	if (VCD_FAILED(status)) {
 		VCD_MSG_ERROR("INPUT_DONE returned err = 0x%x", status);
@@ -1975,6 +2002,7 @@
 		(struct ddl_frame_data_tag *) payload;
 	u32 rc = VCD_ERR_FAIL, codec_config = false;
 	u32 core_type = res_trk_get_core_type();
+	VCD_MSG_LOW("%s\n", __func__);
 	rc = vcd_validate_io_done_pyld(cctxt, payload, status);
 	if (rc == VCD_ERR_CLIENT_FATAL)
 		vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
@@ -2080,6 +2108,7 @@
 	struct ddl_frame_data_tag *frame =
 		(struct ddl_frame_data_tag *)payload;
 	u32 rc = VCD_S_SUCCESS;
+	VCD_MSG_LOW("%s\n", __func__);
 
 	if (!cctxt->status.frame_submitted &&
 		!cctxt->status.frame_delayed) {
@@ -2140,6 +2169,7 @@
 	struct vcd_transc *transc;
 	struct ddl_frame_data_tag *frame =
 		(struct ddl_frame_data_tag *)payload;
+	VCD_MSG_LOW("%s\n", __func__);
 
 	rc = vcd_validate_io_done_pyld(cctxt, payload, VCD_S_SUCCESS);
 	if (rc == VCD_ERR_CLIENT_FATAL)
@@ -2173,6 +2203,7 @@
 	struct vcd_transc *transc;
 	u32 rc;
 	s64 time_stamp;
+	VCD_MSG_LOW("%s\n", __func__);
 
 	rc = vcd_validate_io_done_pyld(cctxt, payload, status);
 	if (rc == VCD_ERR_CLIENT_FATAL)
@@ -2262,7 +2293,7 @@
 	struct ddl_frame_data_tag *frame =
 		(struct ddl_frame_data_tag *) payload;
 	u32 rc = VCD_S_SUCCESS;
-	VCD_MSG_LOW("vcd_handle_frame_done_in_eos:");
+	VCD_MSG_LOW("%s\n", __func__);
 	rc = vcd_validate_io_done_pyld(cctxt, payload, status);
 	if (rc == VCD_ERR_CLIENT_FATAL)
 		vcd_handle_clnt_fatal(cctxt, frame->frm_trans_end);
@@ -3326,3 +3357,24 @@
 		 0, cctxt, cctxt->client_data);
 	}
 }
+
+u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt)
+{
+	struct vcd_property_hdr prop_hdr;
+	struct vcd_property_slice_delivery_info slice_delivery_info;
+	u32 rc = VCD_S_SUCCESS;
+	prop_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
+	prop_hdr.sz = prop_hdr.sz =
+		sizeof(struct vcd_property_slice_delivery_info);
+	rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr,
+				&slice_delivery_info);
+	VCD_FAILED_RETURN(rc, "Failed: Get VCD_I_SLICE_DELIVERY_MODE");
+	if (slice_delivery_info.enable) {
+		cctxt->num_slices = slice_delivery_info.num_slices;
+		VCD_MSG_LOW("%s slice delivery mode num_slices = %u\n",
+					__func__, cctxt->num_slices);
+	} else {
+		cctxt->num_slices = 1;
+	}
+	return rc;
+}
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index bf149eb..519c537 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -454,6 +454,10 @@
 #define VEN_IOCTL_GET_EXTRADATA \
 	_IOR(VEN_IOCTLBASE_ENC, 49, struct venc_ioctl_msg)
 
+/*IOCTL params:SET: InputData - NULL, OutputData - NULL.*/
+#define VEN_IOCTL_SET_SLICE_DELIVERY_MODE \
+	_IO(VEN_IOCTLBASE_ENC, 50)
+
 struct venc_switch{
 	unsigned char	status;
 };
diff --git a/include/linux/qpnp/gpio.h b/include/linux/qpnp/gpio.h
index a31b7f3..e7fb53e 100644
--- a/include/linux/qpnp/gpio.h
+++ b/include/linux/qpnp/gpio.h
@@ -12,12 +12,16 @@
 
 #include <mach/qpnp.h>
 
+#define QPNP_GPIO_DIR_IN			0
 #define QPNP_GPIO_DIR_OUT			1
-#define QPNP_GPIO_DIR_IN			2
-#define QPNP_GPIO_DIR_BOTH	(QPNP_GPIO_DIR_OUT | QPNP_GPIO_DIR_IN)
+#define QPNP_GPIO_DIR_BOTH			2
 
-#define QPNP_GPIO_OUT_BUF_OPEN_DRAIN		1
+#define QPNP_GPIO_INVERT_DISABLE		0
+#define QPNP_GPIO_INVERT_ENABLE			1
+
 #define QPNP_GPIO_OUT_BUF_CMOS			0
+#define QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS	1
+#define QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS	2
 
 #define QPNP_GPIO_VIN0				0
 #define QPNP_GPIO_VIN1				1
@@ -39,14 +43,17 @@
 #define QPNP_GPIO_OUT_STRENGTH_MED		2
 #define QPNP_GPIO_OUT_STRENGTH_HIGH		3
 
-#define QPNP_GPIO_FUNC_NORMAL			0
-#define QPNP_GPIO_FUNC_PAIRED			1
-#define QPNP_GPIO_FUNC_1			2
-#define QPNP_GPIO_FUNC_2			3
-#define QPNP_GPIO_DTEST1			4
-#define QPNP_GPIO_DTEST2			5
-#define QPNP_GPIO_DTEST3			6
-#define QPNP_GPIO_DTEST4			7
+#define QPNP_GPIO_SRC_FUNC_NORMAL		0
+#define QPNP_GPIO_SRC_FUNC_PAIRED		1
+#define QPNP_GPIO_SRC_FUNC_1			2
+#define QPNP_GPIO_SRC_FUNC_2			3
+#define QPNP_GPIO_SRC_DTEST1			4
+#define QPNP_GPIO_SRC_DTEST2			5
+#define QPNP_GPIO_SRC_DTEST3			6
+#define QPNP_GPIO_SRC_DTEST4			7
+
+#define QPNP_GPIO_MASTER_DISABLE		0
+#define QPNP_GPIO_MASTER_ENABLE			1
 
 /**
  * struct qpnp_gpio_cfg - structure to specify gpio configurtion values
@@ -54,7 +61,8 @@
  *			both. Should be of the type QPNP_GPIO_DIR_*
  * @output_type:	indicates gpio should be configured as CMOS or open
  *			drain. Should be of the type QPNP_GPIO_OUT_BUF_*
- * @output_value:	The gpio output value of the gpio line - 0 or 1
+ * @invert:		Invert the signal of the gpio line -
+ *			QPNP_GPIO_INVERT_DISABLE or QPNP_GPIO_INVERT_ENABLE
  * @pull:		Indicates whether a pull up or pull down should be
  *			applied. If a pullup is required the current strength
  *			needs to be specified. Current values of 30uA, 1.5uA,
@@ -68,21 +76,22 @@
  * @source_sel:		choose alternate function for the gpio. Certain gpios
  *			can be paired (shorted) with each other. Some gpio pin
  *			can act as alternate functions. This parameter should
- *			be of type QPNP_GPIO_FUNC_*
- * @master_en:		1 = Enable features within the GPIO block based on
- *			configurations.
- *			0 = Completely disable the GPIO block and let the pin
- *			float with high impedance regardless of other settings.
+ *			be of type QPNP_GPIO_SRC_*.
+ * @master_en:		QPNP_GPIO_MASTER_ENABLE = Enable features within the
+ *			GPIO block based on configurations.
+ *			QPNP_GPIO_MASTER_DISABLE = Completely disable the GPIO
+ *			block and let the pin float with high impedance
+ *			regardless of other settings.
  */
 struct qpnp_gpio_cfg {
-	int		direction;
-	int		output_type;
-	int		output_value;
-	int		pull;
-	int		vin_sel;
-	int		out_strength;
-	int		src_select;
-	int		master_en;
+	unsigned int direction;
+	unsigned int output_type;
+	unsigned int invert;
+	unsigned int pull;
+	unsigned int vin_sel;
+	unsigned int out_strength;
+	unsigned int src_select;
+	unsigned int master_en;
 };
 
 /**
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 51cc78f..e776d41 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -52,6 +52,7 @@
 #define VCD_I_DISABLE_DMX_SUPPORT (VCD_START_BASE + 0x24)
 #define VCD_I_ENABLE_SPS_PPS_FOR_IDR (VCD_START_BASE + 0x25)
 #define VCD_REQ_PERF_LEVEL (VCD_START_BASE + 0x26)
+#define VCD_I_SLICE_DELIVERY_MODE (VCD_START_BASE + 0x27)
 
 #define VCD_START_REQ      (VCD_START_BASE + 0x1000)
 #define VCD_I_REQ_IFRAME   (VCD_START_REQ + 0x1)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 7e9f5f4..d218fab 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -99,6 +99,28 @@
  */
 #define BT_AMP_POLICY_PREFER_AMP       2
 
+#define BT_LE_PARAMS	100
+
+#define BT_LE_SCAN_WINDOW_MIN		0x0004
+#define BT_LE_SCAN_WINDOW_MAX		0x4000
+#define BT_LE_SCAN_WINDOW_DEF		0x0004
+
+#define BT_LE_SCAN_INTERVAL_MIN		0x0004
+#define BT_LE_SCAN_INTERVAL_MAX		0x4000
+#define BT_LE_SCAN_INTERVAL_DEF		0x0008
+
+#define BT_LE_CONN_INTERVAL_MIN		0x0006
+#define BT_LE_CONN_INTERVAL_MAX		0x0C80
+#define BT_LE_CONN_INTERVAL_MIN_DEF	0x0008
+#define BT_LE_CONN_INTERVAL_MAX_DEF	0x0100
+
+#define BT_LE_LATENCY_MAX		0x01F4
+#define BT_LE_LATENCY_DEF		0x0000
+
+#define BT_LE_SUP_TO_MIN		0x000A
+#define BT_LE_SUP_TO_MAX		0x0C80
+#define BT_LE_SUP_TO_DEFAULT		0X03E8
+
 #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
 #define BT_ERR(fmt, arg...)  printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
 #define BT_DBG(fmt, arg...)  pr_debug("%s: " fmt "\n" , __func__ , ## arg)
@@ -142,6 +164,20 @@
 
 #define bt_sk(__sk) ((struct bt_sock *) __sk)
 
+struct bt_le_params {
+	__u8  prohibit_remote_chg;
+	__u8  filter_policy;
+	__u16 scan_interval;
+	__u16 scan_window;
+	__u16 interval_min;
+	__u16 interval_max;
+	__u16 latency;
+	__u16 supervision_timeout;
+	__u16 min_ce_len;
+	__u16 max_ce_len;
+	__u16 conn_timeout;
+};
+
 struct bt_sock {
 	struct sock sk;
 	bdaddr_t    src;
@@ -149,6 +185,7 @@
 	struct list_head accept_q;
 	struct sock *parent;
 	u32 defer_setup;
+	struct bt_le_params le_params;
 };
 
 struct bt_sock_list {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5053bd8..5749293 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -304,6 +304,7 @@
 	__u8		auth_initiator;
 	__u8		power_save;
 	__u16		disc_timeout;
+	__u16		conn_timeout;
 	unsigned long	pend;
 
 	__u8		remote_cap;
@@ -597,6 +598,10 @@
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
 					__u16 pkt_type, bdaddr_t *dst,
 					__u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_le_connect(struct hci_dev *hdev, __u16 pkt_type,
+					bdaddr_t *dst, __u8 sec_level,
+					__u8 auth_type,
+					struct bt_le_params *le_params);
 int hci_conn_check_link_mode(struct hci_conn *conn);
 int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
 int hci_conn_change_link_key(struct hci_conn *conn);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index b903c5c..a098f3e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -685,6 +685,7 @@
 int l2cap_ertm_tx(struct sock *sk, struct bt_l2cap_control *control,
 			struct sk_buff_head *skbs, u8 event);
 
+int l2cap_sock_le_params_valid(struct bt_le_params *le_params);
 void l2cap_sock_set_timer(struct sock *sk, long timeout);
 void l2cap_sock_clear_timer(struct sock *sk);
 void __l2cap_sock_close(struct sock *sk, int reason);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d60bf00..25b559b1 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -44,33 +44,77 @@
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
 
-static void hci_le_connect(struct hci_conn *conn)
+struct hci_conn *hci_le_connect(struct hci_dev *hdev, __u16 pkt_type,
+				bdaddr_t *dst, __u8 sec_level, __u8 auth_type,
+				struct bt_le_params *le_params)
 {
-	struct hci_dev *hdev = conn->hdev;
+	struct hci_conn *le;
 	struct hci_cp_le_create_conn cp;
+	struct adv_entry *entry;
+	struct link_key *key;
 
-	BT_DBG("%p", conn);
+	BT_DBG("%p", hdev);
 
-	conn->state = BT_CONNECT;
-	conn->out = 1;
-	conn->link_mode |= HCI_LM_MASTER;
-	conn->sec_level = BT_SECURITY_LOW;
-	conn->type = LE_LINK;
+	le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
+	if (le) {
+		hci_conn_hold(le);
+		return le;
+	}
+
+	key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
+	if (!key) {
+		entry = hci_find_adv_entry(hdev, dst);
+		if (entry)
+			le = hci_le_conn_add(hdev, dst,
+					entry->bdaddr_type);
+		else
+			le = hci_le_conn_add(hdev, dst, 0);
+	} else {
+		le = hci_le_conn_add(hdev, dst, key->addr_type);
+	}
+
+	if (!le)
+		return ERR_PTR(-ENOMEM);
+
+	hci_conn_hold(le);
+
+	le->state = BT_CONNECT;
+	le->out = 1;
+	le->link_mode |= HCI_LM_MASTER;
+	le->sec_level = BT_SECURITY_LOW;
+	le->type = LE_LINK;
 
 	memset(&cp, 0, sizeof(cp));
-	cp.scan_interval = cpu_to_le16(0x0004);
-	cp.scan_window = cpu_to_le16(0x0004);
-	bacpy(&cp.peer_addr, &conn->dst);
-	cp.peer_addr_type = conn->dst_type;
-	cp.conn_interval_min = cpu_to_le16(0x0008);
-	cp.conn_interval_max = cpu_to_le16(0x0100);
-	cp.supervision_timeout = cpu_to_le16(1000);
-	cp.min_ce_len = cpu_to_le16(0x0001);
-	cp.max_ce_len = cpu_to_le16(0x0001);
+	if (l2cap_sock_le_params_valid(le_params)) {
+		cp.supervision_timeout =
+				cpu_to_le16(le_params->supervision_timeout);
+		cp.scan_interval = cpu_to_le16(le_params->scan_interval);
+		cp.scan_window = cpu_to_le16(le_params->scan_window);
+		cp.conn_interval_min = cpu_to_le16(le_params->interval_min);
+		cp.conn_interval_max = cpu_to_le16(le_params->interval_max);
+		cp.conn_latency = cpu_to_le16(le_params->latency);
+		cp.min_ce_len = cpu_to_le16(le_params->min_ce_len);
+		cp.max_ce_len = cpu_to_le16(le_params->max_ce_len);
+		le->conn_timeout = le_params->conn_timeout;
+	} else {
+		cp.supervision_timeout = cpu_to_le16(BT_LE_SUP_TO_DEFAULT);
+		cp.scan_interval = cpu_to_le16(BT_LE_SCAN_INTERVAL_DEF);
+		cp.scan_window = cpu_to_le16(BT_LE_SCAN_WINDOW_DEF);
+		cp.conn_interval_min = cpu_to_le16(BT_LE_CONN_INTERVAL_MIN_DEF);
+		cp.conn_interval_max = cpu_to_le16(BT_LE_CONN_INTERVAL_MAX_DEF);
+		cp.conn_latency = cpu_to_le16(BT_LE_LATENCY_DEF);
+		le->conn_timeout = 5;
+	}
+	bacpy(&cp.peer_addr, &le->dst);
+	cp.peer_addr_type = le->dst_type;
 
 	hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
+
+	return le;
 }
+EXPORT_SYMBOL(hci_le_connect);
 
 static void hci_le_connect_cancel(struct hci_conn *conn)
 {
@@ -685,41 +729,12 @@
 {
 	struct hci_conn *acl;
 	struct hci_conn *sco;
-	struct hci_conn *le;
 
 	BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
-	if (type == LE_LINK) {
-		struct adv_entry *entry;
-		struct link_key *key;
-
-		le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
-		if (le) {
-			hci_conn_hold(le);
-			return le;
-		}
-
-		key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
-		if (!key) {
-			entry = hci_find_adv_entry(hdev, dst);
-			if (entry)
-				le = hci_le_conn_add(hdev, dst,
-						entry->bdaddr_type);
-			else
-				le = hci_le_conn_add(hdev, dst, 0);
-		} else {
-			le = hci_le_conn_add(hdev, dst, key->addr_type);
-		}
-
-		if (!le)
-			return ERR_PTR(-ENOMEM);
-
-		hci_le_connect(le);
-
-		hci_conn_hold(le);
-
-		return le;
-	}
+	if (type == LE_LINK)
+		return hci_le_connect(hdev, pkt_type, dst, sec_level,
+							auth_type, NULL);
 
 	acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
 	if (!acl) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 598c310..395a95c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1368,6 +1368,7 @@
 {
 	struct hci_cp_le_create_conn *cp;
 	struct hci_conn *conn;
+	unsigned long exp = msecs_to_jiffies(5000);
 
 	BT_DBG("%s status 0x%x", hdev->name, status);
 
@@ -1396,11 +1397,11 @@
 				conn->out = 1;
 			else
 				BT_ERR("No memory for new connection");
-		}
+		} else
+			exp = msecs_to_jiffies(conn->conn_timeout * 1000);
 
-		if (conn)
-			mod_timer(&conn->disc_timer,
-					jiffies + msecs_to_jiffies(5000));
+		if (conn && exp)
+			mod_timer(&conn->disc_timer, jiffies + exp);
 	}
 
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 37ee9b1..9f9f17d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1277,8 +1277,9 @@
 		conn = hcon->l2cap_data;
 	} else {
 		if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
-			hcon = hci_connect(hdev, LE_LINK, 0, dst,
-					l2cap_pi(sk)->sec_level, auth_type);
+			hcon = hci_le_connect(hdev, 0, dst,
+					l2cap_pi(sk)->sec_level, auth_type,
+					&bt_sk(sk)->le_params);
 		else
 			hcon = hci_connect(hdev, ACL_LINK, 0, dst,
 					l2cap_pi(sk)->sec_level, auth_type);
@@ -1308,7 +1309,17 @@
 		sk->sk_state_change(sk);
 	} else {
 		sk->sk_state = BT_CONNECT;
-		l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+		/* If we have valid LE Params, let timeout override default */
+		if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA &&
+			l2cap_sock_le_params_valid(&bt_sk(sk)->le_params)) {
+			u16 timeout = bt_sk(sk)->le_params.conn_timeout;
+
+			if (timeout)
+				l2cap_sock_set_timer(sk,
+						msecs_to_jiffies(timeout*1000));
+		} else
+			l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+
 		sk->sk_state_change(sk);
 
 		if (hcon->state == BT_CONNECTED) {
@@ -5668,7 +5679,8 @@
 	struct hci_conn *hcon = conn->hcon;
 	struct l2cap_conn_param_update_req *req;
 	struct l2cap_conn_param_update_rsp rsp;
-	u16 min, max, latency, to_multiplier, cmd_len;
+	struct sock *sk;
+	u16 min, max, latency, timeout, cmd_len;
 	int err;
 
 	if (!(hcon->link_mode & HCI_LM_MASTER))
@@ -5678,28 +5690,32 @@
 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
 		return -EPROTO;
 
-	req = (struct l2cap_conn_param_update_req *) data;
-	min		= __le16_to_cpu(req->min);
-	max		= __le16_to_cpu(req->max);
-	latency		= __le16_to_cpu(req->latency);
-	to_multiplier	= __le16_to_cpu(req->to_multiplier);
-
-	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
-						min, max, latency, to_multiplier);
-
 	memset(&rsp, 0, sizeof(rsp));
+	rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
 
-	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
-	if (err)
-		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
-	else
-		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+	sk = l2cap_find_sock_by_fixed_cid_and_dir(4, conn->src, conn->dst, 0);
+
+	if (sk && !bt_sk(sk)->le_params.prohibit_remote_chg) {
+		req = (struct l2cap_conn_param_update_req *) data;
+		min = __le16_to_cpu(req->min);
+		max = __le16_to_cpu(req->max);
+		latency = __le16_to_cpu(req->latency);
+		timeout = __le16_to_cpu(req->to_multiplier);
+
+		err = l2cap_check_conn_param(min, max, latency, timeout);
+		if (!err) {
+			rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+			hci_le_conn_update(hcon, min, max, latency, timeout);
+			bt_sk(sk)->le_params.interval_min = min;
+			bt_sk(sk)->le_params.interval_max = max;
+			bt_sk(sk)->le_params.latency = latency;
+			bt_sk(sk)->le_params.supervision_timeout = timeout;
+		}
+	}
 
 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
 							sizeof(rsp), &rsp);
 
-	if (!err)
-		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
 
 	return 0;
 }
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 8eb1e16..33d5d22 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -78,6 +78,23 @@
 	sk_stop_timer(sk, &sk->sk_timer);
 }
 
+int l2cap_sock_le_params_valid(struct bt_le_params *le_params)
+{
+	if (!le_params || le_params->latency > BT_LE_LATENCY_MAX ||
+			le_params->scan_window > BT_LE_SCAN_WINDOW_MAX ||
+			le_params->scan_interval < BT_LE_SCAN_INTERVAL_MIN ||
+			le_params->scan_window > le_params->scan_interval ||
+			le_params->interval_min < BT_LE_CONN_INTERVAL_MIN ||
+			le_params->interval_max > BT_LE_CONN_INTERVAL_MAX ||
+			le_params->interval_min > le_params->interval_max ||
+			le_params->supervision_timeout < BT_LE_SUP_TO_MIN ||
+			le_params->supervision_timeout > BT_LE_SUP_TO_MAX) {
+		return 0;
+	}
+
+	return 1;
+}
+
 static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
 {
 	struct sock *sk;
@@ -547,6 +564,17 @@
 			err = -EFAULT;
 		break;
 
+	case BT_LE_PARAMS:
+		if (l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (copy_to_user(optval, (char *) &bt_sk(sk)->le_params,
+						sizeof(bt_sk(sk)->le_params)))
+			err = -EFAULT;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -671,6 +699,7 @@
 	struct sock *sk = sock->sk;
 	struct bt_security sec;
 	struct bt_power pwr;
+	struct bt_le_params le_params;
 	struct l2cap_conn *conn;
 	int len, err = 0;
 	u32 opt;
@@ -786,6 +815,41 @@
 
 		break;
 
+	case BT_LE_PARAMS:
+		if (l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user((char *) &le_params, optval,
+					sizeof(struct bt_le_params))) {
+			err = -EFAULT;
+			break;
+		}
+
+		conn = l2cap_pi(sk)->conn;
+		if (!conn || !conn->hcon ||
+				l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+			memcpy(&bt_sk(sk)->le_params, &le_params,
+							sizeof(le_params));
+			break;
+		}
+
+		if (!conn->hcon->out ||
+				!l2cap_sock_le_params_valid(&le_params)) {
+			err = -EINVAL;
+			break;
+		}
+
+		memcpy(&bt_sk(sk)->le_params, &le_params, sizeof(le_params));
+
+		hci_le_conn_update(conn->hcon,
+				le_params.interval_min,
+				le_params.interval_max,
+				le_params.latency,
+				le_params.supervision_timeout);
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e15609c..80f4bd6 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1623,8 +1623,8 @@
 
 	entry = hci_find_adv_entry(hdev, &cp->bdaddr);
 	if (entry && entry->flags & 0x04) {
-		conn = hci_connect(hdev, LE_LINK, 0, &cp->bdaddr, sec_level,
-								auth_type);
+		conn = hci_le_connect(hdev, 0, &cp->bdaddr, sec_level,
+							auth_type, NULL);
 	} else {
 		/* ACL-SSP does not support io_cap 0x04 (KeyboadDisplay) */
 		if (io_cap == 0x04)
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 1fe28a2..6b590c9 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -234,7 +234,7 @@
 		return -EINVAL;
 	}
 
-	pr_err("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+	pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
 
 	return 0;
 }
@@ -277,7 +277,7 @@
 		snd_soc_read(codec, (SITAR_A_CDC_IIR1_CTL + 16 * iir_idx)) &
 		(1 << band_idx);
 
-	pr_err("%s: IIR #%d band #%d enable %d\n", __func__,
+	pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
 		iir_idx, band_idx,
 		(uint32_t)ucontrol->value.integer.value[0]);
 	return 0;
@@ -298,7 +298,7 @@
 	snd_soc_update_bits(codec, (SITAR_A_CDC_IIR1_CTL + 16 * iir_idx),
 		(1 << band_idx), (value << band_idx));
 
-	pr_err("%s: IIR #%d band #%d enable %d\n", __func__,
+	pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
 		iir_idx, band_idx, value);
 	return 0;
 }
@@ -344,7 +344,7 @@
 	ucontrol->value.integer.value[4] =
 		get_iir_band_coeff(codec, iir_idx, band_idx, 4);
 
-	pr_err("%s: IIR #%d band #%d b0 = 0x%x\n"
+	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
 		"%s: IIR #%d band #%d b1 = 0x%x\n"
 		"%s: IIR #%d band #%d b2 = 0x%x\n"
 		"%s: IIR #%d band #%d a1 = 0x%x\n"
@@ -412,7 +412,7 @@
 	set_iir_band_coeff(codec, iir_idx, band_idx, 4,
 				ucontrol->value.integer.value[4]);
 
-	pr_err("%s: IIR #%d band #%d b0 = 0x%x\n"
+	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
 		"%s: IIR #%d band #%d b1 = 0x%x\n"
 		"%s: IIR #%d band #%d b2 = 0x%x\n"
 		"%s: IIR #%d band #%d a1 = 0x%x\n"
@@ -743,7 +743,7 @@
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 
-	pr_err("%s %d\n", __func__, enable);
+	pr_debug("%s %d\n", __func__, enable);
 
 	if (enable) {
 		sitar->adc_count++;
@@ -765,7 +765,7 @@
 	struct snd_soc_codec *codec = w->codec;
 	u16 adc_reg;
 
-	pr_err("%s %d\n", __func__, event);
+	pr_debug("%s %d\n", __func__, event);
 
 	if (w->reg == SITAR_A_TX_1_2_EN)
 		adc_reg = SITAR_A_TX_1_2_TEST_CTL;
@@ -818,7 +818,7 @@
 	struct snd_soc_codec *codec = w->codec;
 	u16 lineout_gain_reg;
 
-	pr_err("%s %d %s\n", __func__, event, w->name);
+	pr_debug("%s %d %s\n", __func__, event, w->name);
 
 	switch (w->shift) {
 	case 0:
@@ -838,7 +838,7 @@
 		snd_soc_update_bits(codec, lineout_gain_reg, 0x10, 0x10);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
-		pr_err("%s: sleeping 16 ms after %s PA turn on\n",
+		pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
 				__func__, w->name);
 		usleep_range(16000, 16000);
 		break;
@@ -886,7 +886,7 @@
 	tx_mux_ctl_reg = SITAR_A_CDC_TX1_MUX_CTL + 8 * (dmic - 1);
 	tx_dmic_ctl_reg = SITAR_A_CDC_TX1_DMIC_CTL + 8 * (dmic - 1);
 
-	pr_err("%s %d\n", __func__, event);
+	pr_debug("%s %d\n", __func__, event);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -974,7 +974,7 @@
 			sitar->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
 		if (mbhc_was_polling)
 			sitar_codec_start_hs_polling(codec);
-		pr_err("%s: CFILT mode change (%x to %x)\n", __func__,
+		pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
 			cur_mode_val, reg_mode_val);
 	} else {
 		pr_err("%s: CFILT Value is already %x\n",
@@ -1113,7 +1113,7 @@
 			sitar_codec_start_hs_polling(codec);
 
 			sitar->mbhc_micbias_switched = true;
-			pr_err("%s: Enabled MBHC Mic bias to VDDIO Switch\n",
+			pr_debug("%s: Enabled MBHC Mic bias to VDDIO Switch\n",
 				__func__);
 		}
 		break;
@@ -1138,7 +1138,7 @@
 				sitar_codec_start_hs_polling(codec);
 
 			sitar->mbhc_micbias_switched = false;
-			pr_err("%s: Disabled MBHC Mic bias to VDDIO Switch\n",
+			pr_debug("%s: Disabled MBHC Mic bias to VDDIO Switch\n",
 				__func__);
 		}
 		break;
@@ -1156,7 +1156,7 @@
 	char *internal1_text = "Internal1";
 	char *internal2_text = "Internal2";
 
-	pr_err("%s %d\n", __func__, event);
+	pr_debug("%s %d\n", __func__, event);
 	switch (w->reg) {
 	case SITAR_A_MICB_1_CTL:
 		micb_int_reg = SITAR_A_MICB_1_INT_RBIAS;
@@ -1218,7 +1218,7 @@
 	struct snd_soc_codec *codec = w->codec;
 	u16 dec_reset_reg;
 
-	pr_err("%s %d\n", __func__, event);
+	pr_debug("%s %d\n", __func__, event);
 
 	if (w->reg == SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL)
 		dec_reset_reg = SITAR_A_CDC_CLK_TX_RESET_B1_CTL;
@@ -1242,7 +1242,7 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 
-	pr_err("%s %d %s\n", __func__, event, w->name);
+	pr_debug("%s %d %s\n", __func__, event, w->name);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -1290,7 +1290,7 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 
-	pr_err("%s %d\n", __func__, event);
+	pr_debug("%s %d\n", __func__, event);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -1307,7 +1307,7 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 
-	pr_err("%s %s %d\n", __func__, w->name, event);
+	pr_debug("%s %s %d\n", __func__, w->name, event);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -1378,7 +1378,7 @@
 	struct snd_soc_codec *codec = w->codec;
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 	u8 mbhc_micb_ctl_val;
-	pr_err("%s: event = %d\n", __func__, event);
+	pr_debug("%s: event = %d\n", __func__, event);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -1416,7 +1416,7 @@
 		if (sitar->mbhc_micbias_switched)
 			sitar_codec_switch_micbias(codec, 0);
 
-		pr_err("%s: sleep 10 ms after %s PA disable.\n", __func__,
+		pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
 				w->name);
 		usleep_range(10000, 10000);
 
@@ -1471,7 +1471,7 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 
-	pr_err("%s %d\n", __func__, event);
+	pr_debug("%s %d\n", __func__, event);
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
@@ -1908,7 +1908,7 @@
 	* interrupt handlers
 	*/
 
-	pr_err("%s, choice is %d, current is %d\n", __func__, choice,
+	pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
 		sitar->bandgap_type);
 
 	if (sitar->bandgap_type == choice)
@@ -1978,7 +1978,7 @@
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 
-	pr_err("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 
 	if (config_mode) {
 		sitar_codec_enable_config_mode(codec, 1);
@@ -2005,7 +2005,7 @@
 static void sitar_codec_disable_clock_block(struct snd_soc_codec *codec)
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
-	pr_err("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
 	ndelay(160);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
@@ -2077,7 +2077,7 @@
 	if ((wcd9xxx != NULL) && (wcd9xxx->dev != NULL) &&
 			(wcd9xxx->dev->parent != NULL))
 		pm_runtime_get_sync(wcd9xxx->dev->parent);
-	pr_err("%s(): substream = %s  stream = %d\n" , __func__,
+	pr_debug("%s(): substream = %s  stream = %d\n" , __func__,
 		substream->name, substream->stream);
 
 	return 0;
@@ -2092,7 +2092,7 @@
 		pm_runtime_mark_last_busy(wcd9xxx->dev->parent);
 		pm_runtime_put(wcd9xxx->dev->parent);
 	}
-	pr_err("%s(): substream = %s  stream = %d\n" , __func__,
+	pr_debug("%s(): substream = %s  stream = %d\n" , __func__,
 		substream->name, substream->stream);
 }
 
@@ -2100,7 +2100,7 @@
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 
-	pr_err("%s() mclk_enable = %u\n", __func__, mclk_enable);
+	pr_debug("%s() mclk_enable = %u\n", __func__, mclk_enable);
 
 	if (mclk_enable) {
 		sitar->mclk_enabled = true;
@@ -2149,7 +2149,7 @@
 static int sitar_set_dai_sysclk(struct snd_soc_dai *dai,
 		int clk_id, unsigned int freq, int dir)
 {
-	pr_err("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 	return 0;
 }
 
@@ -2158,7 +2158,7 @@
 	u8 val = 0;
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
 
-	pr_err("%s\n", __func__);
+	pr_debug("%s\n", __func__);
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBS_CFS:
 		/* CPU is master */
@@ -2265,7 +2265,7 @@
 	u16 tx_fs_reg, rx_fs_reg;
 	u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
 
-	pr_err("%s: DAI-ID %x\n", __func__, dai->id);
+	pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
 
 	switch (params_rate(params)) {
 	case 8000:
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index cb760fa..8e4e205 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -49,7 +49,7 @@
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
 	.formats =	      SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_8000_48000,
+	.rates =		SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
 	.rate_min =	     8000,
 	.rate_max =	     48000,
 	.channels_min =	 1,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 23134ea..6c44cba 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -50,7 +50,8 @@
 	{
 		.playback = {
 			.stream_name = "Multimedia1 Playback",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
 			.channels_max = 2,
@@ -59,20 +60,22 @@
 		},
 		.capture = {
 			.stream_name = "Multimedia1 Capture",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
 			.channels_max = 4,
 			.rate_min =     8000,
 			.rate_max =	48000,
 		},
-		.ops = &msm_fe_dai_ops,
+		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia1",
 	},
 	{
 		.playback = {
 			.stream_name = "Multimedia2 Playback",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
 			.channels_max = 6,
@@ -81,14 +84,15 @@
 		},
 		.capture = {
 			.stream_name = "Multimedia2 Capture",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 1,
 			.channels_max = 2,
 			.rate_min =     8000,
 			.rate_max =	48000,
 		},
-		.ops = &msm_fe_dai_ops,
+		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia2",
 	},
 	{
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 0a8282c..b509a09 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -77,7 +77,7 @@
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
 	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =                SNDRV_PCM_RATE_8000_48000,
+	.rates =                SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
 	.rate_min =             8000,
 	.rate_max =             48000,
 	.channels_min =         1,
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 4686386..39ce436 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -71,7 +71,7 @@
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
 	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =                SNDRV_PCM_RATE_8000_48000,
+	.rates =                SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
 	.rate_min =             8000,
 	.rate_max =             48000,
 	.channels_min =         1,