Merge "media: dvb: mpq: Add Support to use Deinterlacer"
diff --git a/Documentation/devicetree/bindings/hwmon/epm_adc.txt b/Documentation/devicetree/bindings/hwmon/epm_adc.txt
index 89edc16..a0ca490 100644
--- a/Documentation/devicetree/bindings/hwmon/epm_adc.txt
+++ b/Documentation/devicetree/bindings/hwmon/epm_adc.txt
@@ -9,7 +9,7 @@
 EPM node
 
 Required properties:
-- compatible : should be "qcom,epm-adc" for EPM using PSoC5.
+- compatible : should be "cy,epm-adc-cy8c5568lti-114" for EPM using PSoC5.
 - reg : chip select for the device.
 - interrupt-parent : should be phandle of the interrupt controller
 		     servicing the interrupt for this device.
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index 51bf9e6..eda7cba 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -12,14 +12,14 @@
 - compatible	: should be "qcom,leds-qpnp"
 
 Each LED module is represented as a node of "leds-qpnp". This
-node will furthur contain the type of LED supported and its
+node will further contain the type of LED supported and its
 properties.
 
 Required properties:
 - qcom,id		: must be one of values supported in enum qpnp_led
-- qcom,label		: type of led that will be used, ie "wled"
+- label			: type of led that will be used, ie "wled"
 - qcom,max-current	: maximum current that the LED can sustain
-= qcom,name		: name the led will be called by in sysfs entry
+- linux,name		: name of the led that is used in led framework
 
 WLED is primarily used as display backlight. Display subsystem uses
 LED triggers for WLED to control the brightness as needed.
@@ -41,17 +41,22 @@
 
 	qcom,leds@d800 {
 			compatible = "qcom,leds-qpnp";
-			reg = <0xD800 0x100>;
-			linux,default-trigger = "bkl-trigger"
-			qcom,label = "wled";
-			qcom,cs-out-en;
-			qcom,op-fdbck;
-			qcom,default-state "off";
-			qcom,max-current = <25>;
-			qcom,ctrl-delay-us = <0>;
-			qcom,boost-curr-lim = <3>;
-			qcom,cp-sel = <0>;
-			qcom,switch-freq = <2>;
-			qcom,ovp-val = <2>;
-			qcom,num-strings = <1>;
-	}
+			status = "okay";
+			qcom,wled_0 {
+				linux,default-trigger = "bkl-trigger"
+				label = "wled";
+				qcom,cs-out-en;
+				qcom,op-fdbck;
+				qcom,default-state "off";
+				qcom,max-current = <25>;
+				qcom,ctrl-delay-us = <0>;
+				qcom,boost-curr-lim = <3>;
+				qcom,cp-sel = <0>;
+				qcom,switch-freq = <2>;
+				qcom,ovp-val = <2>;
+				qcom,num-strings = <1>;
+				qcom,id = <0>;
+				linux,name = "led:wled_backlight";
+			};
+	};
+
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index af841dd..99274d5 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -28,6 +28,8 @@
 - interrupt-names : Optional interrupt resource entries are:
     "hs_phy_irq" : Interrupt from HSPHY for asynchronous events in LPM.
 	This is not used if wakeup events are received externally (e.g. PMIC)
+- qcom,dwc-usb3-msm-otg-capability: If present then depends on PMIC
+  for VBUS notifications, otherwise depends on PHY.
 
 Example MSM USB3.0 controller device node :
 	usb@f9200000 {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 1d95407..de30884 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -996,61 +996,61 @@
 		qcom,leds@d800 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xd800 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@d900 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xd900 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@da00 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xda00 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@db00 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xdb00 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@dc00 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xdc00 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@dd00 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xdd00 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@de00 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xde00 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@df00 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xdf00 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@e000 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xe000 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		qcom,leds@e100 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xe100 0x100>;
-			qcom,label = "wled";
+			label = "wled";
 		};
 
 		pwm@b100 {
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index b63595b..c5fabab 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -177,6 +177,10 @@
 	qcom,hsusb-otg-otg-control = <2>;
 };
 
+&usb3 {
+	qcom,dwc-usb3-msm-otg-capability;
+};
+
 &pm8941_chg {
 	status = "ok";
 
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 3509e01..df3c520 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -261,6 +261,23 @@
 			<&msmgpio 54 0>, /* MISO */
 			<&msmgpio 53 0>; /* MOSI */
 		cs-gpios = <&msmgpio 55 0>;
+
+		epm-adc@0 {
+			compatible = "cy,epm-adc-cy8c5568lti-114";
+			reg = <0>;
+			interrupt-parent = <&msmgpio>;
+			spi-max-frequency = <960000>;
+			qcom,channels = <31>;
+			qcom,gain = <100 100 100 50 100 100 1 100 1 50
+					1 100 1 100 50 50 50 50 50 50
+					100 50 100 50 50 50 50 50 50 50
+					50>;
+			qcom,rsense = <2 2 2 200 20 2 1 2 1 30
+					1 10 1 30 50 30 500 30 100 30
+					100 500 20 200 1000 20 1000 1000 70 200
+					50>;
+			qcom,channel-type = <0x2a40>;
+		};
 	};
 
 	slim_msm: slim@fe12f000 {
@@ -511,19 +528,23 @@
 
 		qcom,pm8941@1 {
 			qcom,leds@d800 {
-				qcom,name = "wled:backlight";
-				linux,default-trigger = "bkl-trigger";
-				qcom,cs-out-en;
-				qcom,op-fdbck;
-				qcom,default-state = "on";
-				qcom,max-current = <25>;
-				qcom,ctrl-delay-us = <0>;
-				qcom,boost-curr-lim = <3>;
-				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
-				qcom,ovp-val = <2>;
-				qcom,num-strings = <1>;
 				status = "okay";
+				qcom,wled_0 {
+					label = "wled";
+					linux,name = "wled:backlight";
+					linux,default-trigger = "bkl-trigger";
+					qcom,cs-out-en;
+					qcom,op-fdbck;
+					qcom,default-state = "on";
+					qcom,max-current = <25>;
+					qcom,ctrl-delay-us = <0>;
+					qcom,boost-curr-lim = <3>;
+					qcom,cp-sel = <0>;
+					qcom,switch-freq = <2>;
+					qcom,ovp-val = <2>;
+					qcom,num-strings = <1>;
+					qcom,id = <0>;
+				};
 			};
 
 			qcom,leds@d900 {
@@ -630,12 +651,12 @@
 		l2_hfpll_b-supply = <&pm8941_l12_ao>;
 	};
 
-	qcom,ssusb@f9200000 {
+	usb3: qcom,ssusb@f9200000 {
 		compatible = "qcom,dwc-usb3-msm";
 		reg = <0xf9200000 0xfc000>,
 			  <0xfd4ab000 0x4>;
-		interrupts = <0 131 0 0 179 0>;
-		interrupt-names = "irq", "otg_irq";
+		interrupts = <0 131 0>, <0 179 0>, <0 133 0>;
+		interrupt-names = "irq", "otg_irq", "hs_phy_irq";
 		SSUSB_VDDCX-supply = <&pm8841_s2>;
 		SSUSB_1p8-supply = <&pm8941_l6>;
 		HSUSB_VDDCX-supply = <&pm8841_s2>;
@@ -1044,7 +1065,7 @@
 			qcom,dst-bam-physical-address = <0xf9304000>;
 			qcom,dst-bam-pipe-index = <2>;
 			qcom,data-fifo-offset = <0xf0000>;
-			qcom,data-fifo-size = <0x4000>;
+			qcom,data-fifo-size = <0x1800>;
 			qcom,descriptor-fifo-offset = <0xf4000>;
 			qcom,descriptor-fifo-size = <0x1400>;
 		};
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 53e6260..ec00b68 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -367,6 +367,7 @@
 CONFIG_S5K3L1YX=y
 CONFIG_IMX091=y
 CONFIG_MSM_WFD=y
+CONFIG_IMX135=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 # CONFIG_DVB_FE_CUSTOMISE is not set
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 5770859..33f7987 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -371,6 +371,7 @@
 CONFIG_S5K3L1YX=y
 CONFIG_IMX091=y
 CONFIG_MSM_WFD=y
+CONFIG_IMX135=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 # CONFIG_DVB_FE_CUSTOMISE is not set
diff --git a/arch/arm/mach-msm/acpuclock-krait-debug.c b/arch/arm/mach-msm/acpuclock-krait-debug.c
index 0ab70b4..a29735e 100644
--- a/arch/arm/mach-msm/acpuclock-krait-debug.c
+++ b/arch/arm/mach-msm/acpuclock-krait-debug.c
@@ -35,7 +35,7 @@
 	bool set;
 	bool enable;
 };
-static int l2_acg_en_val[MAX_SCALABLES];
+static int l2_acg_en_val;
 static struct dentry *base_dir;
 static struct dentry *sc_dir[MAX_SCALABLES];
 
@@ -51,8 +51,8 @@
 			val &= ~BIT(0);
 		else
 			val |= BIT(0);
-		asm volatile ("mcr p15, 7, %[l2cpdr], c15, c0, 5\n\t"
-				: : [l2cpdr]"r" (val));
+		asm volatile ("mcr p15, 7, %[cpmr0], c15, c0, 5\n\t"
+				: : [cpmr0]"r" (val));
 	} else {
 		action->enable = !(val & BIT(0));
 	}
@@ -65,7 +65,7 @@
 
 	if (sc_id == L2) {
 		regval = get_l2_indirect_reg(drv->scalable[sc_id].l2cpmr_iaddr);
-		l2_acg_en_val[sc_id] = regval & (0x3 << 10);
+		l2_acg_en_val = regval & (0x3 << 10);
 		regval |= (0x3 << 10);
 		set_l2_indirect_reg(drv->scalable[sc_id].l2cpmr_iaddr, regval);
 	} else {
@@ -82,7 +82,7 @@
 	if (sc_id == L2) {
 		regval = get_l2_indirect_reg(drv->scalable[sc_id].l2cpmr_iaddr);
 		regval &= ~(0x3 << 10);
-		regval |= l2_acg_en_val[sc_id];
+		regval |= l2_acg_en_val;
 		set_l2_indirect_reg(drv->scalable[sc_id].l2cpmr_iaddr, regval);
 	} else {
 		struct acg_action action = { .set = true, .enable = true };
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index a386e78..bf57eab 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -209,7 +209,8 @@
 }
 
 /* Set the CPU or L2 clock speed. */
-static void set_speed(struct scalable *sc, const struct core_speed *tgt_s)
+static void set_speed(struct scalable *sc, const struct core_speed *tgt_s,
+	bool skip_regulators)
 {
 	const struct core_speed *strt_s = sc->cur_speed;
 
@@ -232,10 +233,10 @@
 		set_pri_clk_src(sc, tgt_s->pri_src_sel);
 	} else if (strt_s->src == HFPLL && tgt_s->src != HFPLL) {
 		set_pri_clk_src(sc, tgt_s->pri_src_sel);
-		hfpll_disable(sc, false);
+		hfpll_disable(sc, skip_regulators);
 	} else if (strt_s->src != HFPLL && tgt_s->src == HFPLL) {
 		hfpll_set_rate(sc, tgt_s);
-		hfpll_enable(sc, false);
+		hfpll_enable(sc, skip_regulators);
 		set_pri_clk_src(sc, tgt_s->pri_src_sel);
 	}
 
@@ -426,6 +427,47 @@
 	return tgt->vdd_core + (enable_boost ? drv.boost_uv : 0);
 }
 
+static DEFINE_MUTEX(l2_regulator_lock);
+static int l2_vreg_count;
+
+static int enable_l2_regulators(void)
+{
+	int ret = 0;
+
+	mutex_lock(&l2_regulator_lock);
+	if (l2_vreg_count == 0) {
+		ret = enable_rpm_vreg(&drv.scalable[L2].vreg[VREG_HFPLL_A]);
+		if (ret)
+			goto out;
+		ret = enable_rpm_vreg(&drv.scalable[L2].vreg[VREG_HFPLL_B]);
+		if (ret) {
+			disable_rpm_vreg(&drv.scalable[L2].vreg[VREG_HFPLL_A]);
+			goto out;
+		}
+	}
+	l2_vreg_count++;
+out:
+	mutex_unlock(&l2_regulator_lock);
+
+	return ret;
+}
+
+static void disable_l2_regulators(void)
+{
+	mutex_lock(&l2_regulator_lock);
+
+	if (WARN(!l2_vreg_count, "L2 regulator votes are unbalanced!"))
+		goto out;
+
+	if (l2_vreg_count == 1) {
+		disable_rpm_vreg(&drv.scalable[L2].vreg[VREG_HFPLL_B]);
+		disable_rpm_vreg(&drv.scalable[L2].vreg[VREG_HFPLL_A]);
+	}
+	l2_vreg_count--;
+out:
+	mutex_unlock(&l2_regulator_lock);
+}
+
 /* Set the CPU's clock rate and adjust the L2 rate, voltage and BW requests. */
 static int acpuclk_krait_set_rate(int cpu, unsigned long rate,
 				  enum setrate_reason reason)
@@ -433,8 +475,9 @@
 	const struct core_speed *strt_acpu_s, *tgt_acpu_s;
 	const struct acpu_level *tgt;
 	int tgt_l2_l;
+	enum src_id prev_l2_src = NUM_SRC_ID;
 	struct vdd_data vdd_data;
-	unsigned long flags;
+	bool skip_regulators;
 	int rc = 0;
 
 	if (cpu > num_possible_cpus())
@@ -478,13 +521,31 @@
 		rc = increase_vdd(cpu, &vdd_data, reason);
 		if (rc)
 			goto out;
+
+		prev_l2_src =
+			drv.l2_freq_tbl[drv.scalable[cpu].l2_vote].speed.src;
+		/* Vote for the L2 regulators here if necessary. */
+		if (drv.l2_freq_tbl[tgt->l2_level].speed.src == HFPLL) {
+			rc = enable_l2_regulators();
+			if (rc)
+				goto out;
+		}
 	}
 
 	dev_dbg(drv.dev, "Switching from ACPU%d rate %lu KHz -> %lu KHz\n",
 		cpu, strt_acpu_s->khz, tgt_acpu_s->khz);
 
+	/*
+	 * If we are setting the rate as part of power collapse or in the resume
+	 * path after power collapse, skip the vote for the HFPLL regulators,
+	 * which are active-set-only votes that will be removed when apps enters
+	 * its sleep set. This is needed to avoid voting for regulators with
+	 * sleeping APIs from an atomic context.
+	 */
+	skip_regulators = (reason == SETRATE_PC);
+
 	/* Set the new CPU speed. */
-	set_speed(&drv.scalable[cpu], tgt_acpu_s);
+	set_speed(&drv.scalable[cpu], tgt_acpu_s, skip_regulators);
 
 	/*
 	 * Update the L2 vote and apply the rate change. A spinlock is
@@ -493,15 +554,23 @@
 	 * called from an atomic context and the driver_lock mutex is not
 	 * acquired.
 	 */
-	spin_lock_irqsave(&l2_lock, flags);
+	spin_lock(&l2_lock);
 	tgt_l2_l = compute_l2_level(&drv.scalable[cpu], tgt->l2_level);
-	set_speed(&drv.scalable[L2], &drv.l2_freq_tbl[tgt_l2_l].speed);
-	spin_unlock_irqrestore(&l2_lock, flags);
+	set_speed(&drv.scalable[L2],
+			&drv.l2_freq_tbl[tgt_l2_l].speed, true);
+	spin_unlock(&l2_lock);
 
 	/* Nothing else to do for power collapse or SWFI. */
 	if (reason == SETRATE_PC || reason == SETRATE_SWFI)
 		goto out;
 
+	/*
+	 * Remove the vote for the L2 HFPLL regulators only if the L2
+	 * was already on an HFPLL source.
+	 */
+	if (prev_l2_src == HFPLL)
+		disable_l2_regulators();
+
 	/* Update bus bandwith request. */
 	set_bus_bw(drv.l2_freq_tbl[tgt_l2_l].bw_level);
 
@@ -663,6 +732,14 @@
 		goto err_core_conf;
 	}
 
+	/*
+	 * Increment the L2 HFPLL regulator refcount if _this_ CPU's frequency
+	 * requires a corresponding target L2 frequency that needs the L2 to
+	 * run off of an HFPLL.
+	 */
+	if (drv.l2_freq_tbl[acpu_level->l2_level].speed.src == HFPLL)
+		l2_vreg_count++;
+
 	return 0;
 
 err_core_conf:
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index c0e325a..c973bd5 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -143,6 +143,7 @@
 
 static struct pm8xxx_gpio_init pm8921_mpq8064_hrd_gpios[] __initdata = {
 	PM8921_GPIO_OUTPUT(37, 0, LOW),	/* MUX1_SEL */
+	PM8921_GPIO_INPUT(40, PM_GPIO_PULL_UP_30), /* irq for sx150 exp2 */
 };
 
 static struct pm8xxx_gpio_init touchscreen_gpios[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 379d7ae..28f7f63 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -383,6 +383,14 @@
 				apq8064_sdc3_pdata->pin_data->pad_data->\
 					drv->on[i].val = GPIO_CFG_10MA;
 		}
+		if (machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
+			apq8064_sdc3_pdata->pin_data->pad_data->\
+				drv->on[0].val = GPIO_CFG_16MA;
+			apq8064_sdc3_pdata->pin_data->pad_data->\
+				drv->on[1].val = GPIO_CFG_10MA;
+			apq8064_sdc3_pdata->pin_data->pad_data->\
+				drv->on[2].val = GPIO_CFG_10MA;
+		}
 		apq8064_add_sdcc(3, apq8064_sdc3_pdata);
 	}
 
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 9e5e4f5..6a3e78e 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2401,6 +2401,7 @@
 static struct platform_device *common_mpq_devices[] __initdata = {
 	&mpq_cpudai_sec_i2s_rx,
 	&mpq_cpudai_mi2s_tx,
+	&mpq_cpudai_pseudo,
 };
 
 static struct platform_device *common_i2s_devices[] __initdata = {
@@ -2945,6 +2946,83 @@
 	},
 };
 
+#define MPQ_HRD_HOME_GPIO	SX150X_EXP2_GPIO_BASE
+#define MPQ_HRD_VOL_UP_GPIO	(SX150X_EXP2_GPIO_BASE + 1)
+#define MPQ_HRD_VOL_DOWN_GPIO	(SX150X_EXP2_GPIO_BASE + 2)
+#define MPQ_HRD_RIGHT_GPIO	(SX150X_EXP2_GPIO_BASE + 3)
+#define MPQ_HRD_LEFT_GPIO	(SX150X_EXP2_GPIO_BASE + 4)
+#define MPQ_HRD_ENTER_GPIO	(SX150X_EXP2_GPIO_BASE + 5)
+
+static struct gpio_keys_button mpq_hrd_keys[] = {
+	{
+		.code		= KEY_HOME,
+		.gpio		= MPQ_HRD_HOME_GPIO,
+		.desc		= "home_key",
+		.active_low	= 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code		= KEY_VOLUMEUP,
+		.gpio		= MPQ_HRD_VOL_UP_GPIO,
+		.desc		= "volume_up_key",
+		.active_low	= 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code		= KEY_VOLUMEDOWN,
+		.gpio		= MPQ_HRD_VOL_DOWN_GPIO,
+		.desc		= "volume_down_key",
+		.active_low	= 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code		= KEY_RIGHT,
+		.gpio		= MPQ_HRD_RIGHT_GPIO,
+		.desc		= "right_key",
+		.active_low	= 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code		= KEY_LEFT,
+		.gpio		= MPQ_HRD_LEFT_GPIO,
+		.desc		= "left_key",
+		.active_low	= 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+	{
+		.code		= KEY_ENTER,
+		.gpio		= MPQ_HRD_ENTER_GPIO,
+		.desc		= "enter_key",
+		.active_low	= 1,
+		.type		= EV_KEY,
+		.wakeup		= 1,
+		.debounce_interval = 15,
+	},
+};
+
+static struct gpio_keys_platform_data mpq_hrd_keys_pdata = {
+		.buttons	= mpq_hrd_keys,
+		.nbuttons	= ARRAY_SIZE(mpq_hrd_keys),
+};
+
+static struct platform_device mpq_hrd_keys_pdev = {
+		.name	= "gpio-keys",
+		.id	= -1,
+		.dev	= {
+			.platform_data = &mpq_hrd_keys_pdata,
+		},
+};
+
 static struct gpio_keys_button mpq_keys[] = {
 	{
 		.code           = KEY_VOLUMEDOWN,
@@ -3300,6 +3378,15 @@
 	msm_clock_init(&apq8064_clock_init_data);
 	apq8064_init_gpiomux();
 	apq8064_i2c_init();
+
+	/* configure sx150x parameters for HRD */
+	if (machine_is_mpq8064_hrd()) {
+		mpq8064_sx150x_pdata[SX150X_EXP2].irq_summary    =
+					PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 40);
+		mpq8064_sx150x_pdata[SX150X_EXP2].io_pullup_ena  = 0xff;
+		mpq8064_sx150x_pdata[SX150X_EXP2].io_pulldn_ena  = 0x00;
+	}
+
 	register_i2c_devices();
 
 	apq8064_device_qup_spi_gsbi5.dev.platform_data =
@@ -3446,7 +3533,8 @@
 	if (machine_is_mpq8064_cdp()) {
 		platform_device_register(&mpq_gpio_keys_pdev);
 		platform_device_register(&mpq_keypad_device);
-	}
+	} else if (machine_is_mpq8064_hrd())
+		platform_device_register(&mpq_hrd_keys_pdev);
 }
 
 MACHINE_START(APQ8064_CDP, "QCT APQ8064 CDP")
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index e919d78..ce2531b 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -3287,7 +3287,13 @@
 	msm_spm_l2_init(msm_spm_l2_data);
 
 	msm8960_init_buses();
-	platform_add_devices(msm8960_footswitch, msm8960_num_footswitch);
+	if (cpu_is_msm8960ab()) {
+		platform_add_devices(msm8960ab_footswitch,
+				     msm8960ab_num_footswitch);
+	} else {
+		platform_add_devices(msm8960_footswitch,
+				     msm8960_num_footswitch);
+	}
 	if (machine_is_msm8960_liquid())
 		platform_device_register(&msm8960_device_ext_3p3v_vreg);
 	if (machine_is_msm8960_cdp())
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index d727c54..127c9ab 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -542,6 +542,10 @@
 	.id     = 0x4009,
 };
 
+struct platform_device mpq_cpudai_pseudo = {
+	.name   = "msm-dai-q6",
+	.id     = 0x8001,
+};
 #define MSM_TSIF0_PHYS       (0x18200000)
 #define MSM_TSIF1_PHYS       (0x18201000)
 #define MSM_TSIF_SIZE        (0x200)
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 30a99cd..322347b 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -1083,6 +1083,7 @@
 #endif
 	.disable_dmx = 1,
 	.disable_fullhd = 0,
+	.cont_mode_dpb_count = 18,
 	.fw_addr = 0x9fe00000,
 };
 
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 0f71bc4..f8132b4 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -2553,6 +2553,17 @@
 };
 unsigned msm8960_num_footswitch __initdata = ARRAY_SIZE(msm8960_footswitch);
 
+struct platform_device *msm8960ab_footswitch[] __initdata = {
+	FS_8X60(FS_MDP,    "vdd",	"mdp.0",	&mdp_fs_data),
+	FS_8X60(FS_ROT,    "vdd",	"msm_rotator.0", &rot_fs_data),
+	FS_8X60(FS_IJPEG,  "vdd",	"msm_gemini.0",	&ijpeg_fs_data),
+	FS_8X60(FS_VFE,    "vdd",	"msm_vfe.0",	&vfe_fs_data),
+	FS_8X60(FS_VPE,    "vdd",	"msm_vpe.0",	&vpe_fs_data),
+	FS_8X60(FS_GFX3D,  "vdd",	"kgsl-3d0.0",	&gfx3d_fs_data),
+	FS_8X60(FS_VED,    "vdd",	"msm_vidc.0",	&ved_fs_data),
+};
+unsigned msm8960ab_num_footswitch __initdata = ARRAY_SIZE(msm8960ab_footswitch);
+
 #ifdef CONFIG_MSM_ROTATOR
 static struct msm_bus_vectors rotator_init_vectors[] = {
 	{
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 8f02050..861f1d6 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -216,6 +216,7 @@
 extern struct platform_device msm_cpudai0;
 extern struct platform_device msm_cpudai1;
 extern struct platform_device mpq_cpudai_sec_i2s_rx;
+extern struct platform_device mpq_cpudai_pseudo;
 extern struct platform_device msm8960_cpudai_slimbus_2_rx;
 extern struct platform_device msm8960_cpudai_slimbus_2_tx;
 extern struct platform_device msm_cpudai_hdmi_rx;
@@ -300,6 +301,8 @@
 extern unsigned msm8660_num_footswitch;
 extern struct platform_device *msm8960_footswitch[];
 extern unsigned msm8960_num_footswitch;
+extern struct platform_device *msm8960ab_footswitch[];
+extern unsigned msm8960ab_num_footswitch;
 extern struct platform_device *apq8064_footswitch[];
 extern unsigned apq8064_num_footswitch;
 extern struct platform_device *msm8930_footswitch[];
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 20e56c2..3a632e5 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -96,6 +96,13 @@
 static struct list_head local_ports[LP_HASH_SIZE];
 static DEFINE_MUTEX(local_ports_lock);
 
+/*
+ * Server info is organized as a hash table. The server's service ID is
+ * used to index into the hash table. The instance ID of most of the servers
+ * are 1 or 2. The service IDs are well distributed compared to the instance
+ * IDs and hence choosing service ID to index into this hash table optimizes
+ * the hash table operations like add, lookup, destroy.
+ */
 #define SRV_HASH_SIZE 32
 static struct list_head server_list[SRV_HASH_SIZE];
 static DEFINE_MUTEX(server_list_lock);
@@ -581,6 +588,20 @@
 	return;
 }
 
+/**
+ * msm_ipc_router_lookup_server() - Lookup server information
+ * @service: Service ID of the server info to be looked up.
+ * @instance: Instance ID of the server info to be looked up.
+ * @node_id: Node/Processor ID in which the server is hosted.
+ * @port_id: Port ID within the node in which the server is hosted.
+ *
+ * @return: If found Pointer to server structure, else NULL.
+ *
+ * Note1: Lock the server_list_lock before accessing this function.
+ * Note2: If the <node_id:port_id> are <0:0>, then the lookup is restricted
+ *        to <service:instance>. Used only when a client wants to send a
+ *        message to any QMI server.
+ */
 static struct msm_ipc_server *msm_ipc_router_lookup_server(
 				uint32_t service,
 				uint32_t instance,
@@ -589,30 +610,39 @@
 {
 	struct msm_ipc_server *server;
 	struct msm_ipc_server_port *server_port;
-	int key = (instance & (SRV_HASH_SIZE - 1));
+	int key = (service & (SRV_HASH_SIZE - 1));
 
-	mutex_lock(&server_list_lock);
 	list_for_each_entry(server, &server_list[key], list) {
 		if ((server->name.service != service) ||
 		    (server->name.instance != instance))
 			continue;
-		if ((node_id == 0) && (port_id == 0)) {
-			mutex_unlock(&server_list_lock);
+		if ((node_id == 0) && (port_id == 0))
 			return server;
-		}
 		list_for_each_entry(server_port, &server->server_port_list,
 				    list) {
 			if ((server_port->server_addr.node_id == node_id) &&
-			    (server_port->server_addr.port_id == port_id)) {
-				mutex_unlock(&server_list_lock);
+			    (server_port->server_addr.port_id == port_id))
 				return server;
-			}
 		}
 	}
-	mutex_unlock(&server_list_lock);
 	return NULL;
 }
 
+/**
+ * msm_ipc_router_create_server() - Add server info to hash table
+ * @service: Service ID of the server info to be created.
+ * @instance: Instance ID of the server info to be created.
+ * @node_id: Node/Processor ID in which the server is hosted.
+ * @port_id: Port ID within the node in which the server is hosted.
+ * @xprt_info: XPRT through which the node hosting the server is reached.
+ *
+ * @return: Pointer to server structure on success, else NULL.
+ *
+ * This function adds the server info to the hash table. If the same
+ * server(i.e. <service_id:instance_id>) is hosted in different nodes,
+ * they are maintained as list of "server_port" under "server" structure.
+ * Note: Lock the server_list_lock before accessing this function.
+ */
 static struct msm_ipc_server *msm_ipc_router_create_server(
 					uint32_t service,
 					uint32_t instance,
@@ -622,9 +652,8 @@
 {
 	struct msm_ipc_server *server = NULL;
 	struct msm_ipc_server_port *server_port;
-	int key = (instance & (SRV_HASH_SIZE - 1));
+	int key = (service & (SRV_HASH_SIZE - 1));
 
-	mutex_lock(&server_list_lock);
 	list_for_each_entry(server, &server_list[key], list) {
 		if ((server->name.service == service) &&
 		    (server->name.instance == instance))
@@ -633,7 +662,6 @@
 
 	server = kmalloc(sizeof(struct msm_ipc_server), GFP_KERNEL);
 	if (!server) {
-		mutex_unlock(&server_list_lock);
 		pr_err("%s: Server allocation failed\n", __func__);
 		return NULL;
 	}
@@ -649,7 +677,6 @@
 			list_del(&server->list);
 			kfree(server);
 		}
-		mutex_unlock(&server_list_lock);
 		pr_err("%s: Server Port allocation failed\n", __func__);
 		return NULL;
 	}
@@ -657,11 +684,22 @@
 	server_port->server_addr.port_id = port_id;
 	server_port->xprt_info = xprt_info;
 	list_add_tail(&server_port->list, &server->server_port_list);
-	mutex_unlock(&server_list_lock);
 
 	return server;
 }
 
+/**
+ * msm_ipc_router_destroy_server() - Remove server info from hash table
+ * @server: Server info to be removed.
+ * @node_id: Node/Processor ID in which the server is hosted.
+ * @port_id: Port ID within the node in which the server is hosted.
+ *
+ * This function removes the server_port identified using <node_id:port_id>
+ * from the server structure. If the server_port list under server structure
+ * is empty after removal, then remove the server structure from the server
+ * hash table.
+ * Note: Lock the server_list_lock before accessing this function.
+ */
 static void msm_ipc_router_destroy_server(struct msm_ipc_server *server,
 					  uint32_t node_id, uint32_t port_id)
 {
@@ -670,7 +708,6 @@
 	if (!server)
 		return;
 
-	mutex_lock(&server_list_lock);
 	list_for_each_entry(server_port, &server->server_port_list, list) {
 		if ((server_port->server_addr.node_id == node_id) &&
 		    (server_port->server_addr.port_id == port_id))
@@ -684,7 +721,6 @@
 		list_del(&server->list);
 		kfree(server);
 	}
-	mutex_unlock(&server_list_lock);
 	return;
 }
 
@@ -1319,6 +1355,7 @@
 		}
 		mutex_unlock(&routing_table_lock);
 
+		mutex_lock(&server_list_lock);
 		server = msm_ipc_router_lookup_server(msg->srv.service,
 						      msg->srv.instance,
 						      msg->srv.node_id,
@@ -1328,6 +1365,7 @@
 				msg->srv.service, msg->srv.instance,
 				msg->srv.node_id, msg->srv.port_id, xprt_info);
 			if (!server) {
+				mutex_unlock(&server_list_lock);
 				pr_err("%s: Server Create failed\n", __func__);
 				return -ENOMEM;
 			}
@@ -1342,6 +1380,7 @@
 			}
 			wake_up(&newserver_wait);
 		}
+		mutex_unlock(&server_list_lock);
 
 		relay_msg(xprt_info, pkt);
 		post_control_ports(pkt);
@@ -1349,6 +1388,7 @@
 	case IPC_ROUTER_CTRL_CMD_REMOVE_SERVER:
 		RR("o REMOVE_SERVER service=%08x:%d\n",
 		   msg->srv.service, msg->srv.instance);
+		mutex_lock(&server_list_lock);
 		server = msm_ipc_router_lookup_server(msg->srv.service,
 						      msg->srv.instance,
 						      msg->srv.node_id,
@@ -1360,6 +1400,7 @@
 			relay_msg(xprt_info, pkt);
 			post_control_ports(pkt);
 		}
+		mutex_unlock(&server_list_lock);
 		break;
 	case IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT:
 		RR("o REMOVE_CLIENT id=%d:%08x\n",
@@ -1544,11 +1585,13 @@
 	if (name->addrtype != MSM_IPC_ADDR_NAME)
 		return -EINVAL;
 
+	mutex_lock(&server_list_lock);
 	server = msm_ipc_router_lookup_server(name->addr.port_name.service,
 					      name->addr.port_name.instance,
 					      IPC_ROUTER_NID_LOCAL,
 					      port_ptr->this_port.port_id);
 	if (server) {
+		mutex_unlock(&server_list_lock);
 		pr_err("%s: Server already present\n", __func__);
 		return -EINVAL;
 	}
@@ -1559,6 +1602,7 @@
 					      port_ptr->this_port.port_id,
 					      NULL);
 	if (!server) {
+		mutex_unlock(&server_list_lock);
 		pr_err("%s: Server Creation failed\n", __func__);
 		return -EINVAL;
 	}
@@ -1568,6 +1612,7 @@
 	ctl.srv.instance = server->name.instance;
 	ctl.srv.node_id = IPC_ROUTER_NID_LOCAL;
 	ctl.srv.port_id = port_ptr->this_port.port_id;
+	mutex_unlock(&server_list_lock);
 	broadcast_ctl_msg(&ctl);
 	spin_lock_irqsave(&port_ptr->port_lock, flags);
 	port_ptr->type = SERVER_PORT;
@@ -1598,11 +1643,13 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&server_list_lock);
 	server = msm_ipc_router_lookup_server(port_ptr->port_name.service,
 					      port_ptr->port_name.instance,
 					      port_ptr->this_port.node_id,
 					      port_ptr->this_port.port_id);
 	if (!server) {
+		mutex_unlock(&server_list_lock);
 		pr_err("%s: Server lookup failed\n", __func__);
 		return -ENODEV;
 	}
@@ -1612,9 +1659,10 @@
 	ctl.srv.instance = server->name.instance;
 	ctl.srv.node_id = IPC_ROUTER_NID_LOCAL;
 	ctl.srv.port_id = port_ptr->this_port.port_id;
-	broadcast_ctl_msg(&ctl);
 	msm_ipc_router_destroy_server(server, port_ptr->this_port.node_id,
 				      port_ptr->this_port.port_id);
+	mutex_unlock(&server_list_lock);
+	broadcast_ctl_msg(&ctl);
 	spin_lock_irqsave(&port_ptr->port_lock, flags);
 	port_ptr->type = CLIENT_PORT;
 	spin_unlock_irqrestore(&port_ptr->port_lock, flags);
@@ -1813,15 +1861,16 @@
 		dst_node_id = dest->addr.port_addr.node_id;
 		dst_port_id = dest->addr.port_addr.port_id;
 	} else if (dest->addrtype == MSM_IPC_ADDR_NAME) {
+		mutex_lock(&server_list_lock);
 		server = msm_ipc_router_lookup_server(
 					dest->addr.port_name.service,
 					dest->addr.port_name.instance,
 					0, 0);
 		if (!server) {
+			mutex_unlock(&server_list_lock);
 			pr_err("%s: Destination not reachable\n", __func__);
 			return -ENODEV;
 		}
-		mutex_lock(&server_list_lock);
 		server_port = list_first_entry(&server->server_port_list,
 					       struct msm_ipc_server_port,
 					       list);
@@ -2005,6 +2054,7 @@
 	mutex_unlock(&port_ptr->port_rx_q_lock);
 
 	if (port_ptr->type == SERVER_PORT) {
+		mutex_lock(&server_list_lock);
 		server = msm_ipc_router_lookup_server(
 				port_ptr->port_name.service,
 				port_ptr->port_name.instance,
@@ -2014,6 +2064,7 @@
 			msm_ipc_router_destroy_server(server,
 				port_ptr->this_port.node_id,
 				port_ptr->this_port.port_id);
+		mutex_unlock(&server_list_lock);
 	}
 
 	wake_lock_destroy(&port_ptr->port_rx_wake_lock);
@@ -2078,27 +2129,24 @@
 	mutex_lock(&server_list_lock);
 	if (!lookup_mask)
 		lookup_mask = 0xFFFFFFFF;
-	for (key = 0; key < SRV_HASH_SIZE; key++) {
-		list_for_each_entry(server, &server_list[key], list) {
-			if ((server->name.service != srv_name->service) ||
-			    ((server->name.instance & lookup_mask) !=
-				srv_name->instance))
-				continue;
+	key = (srv_name->service & (SRV_HASH_SIZE - 1));
+	list_for_each_entry(server, &server_list[key], list) {
+		if ((server->name.service != srv_name->service) ||
+		    ((server->name.instance & lookup_mask) !=
+			srv_name->instance))
+			continue;
 
-			list_for_each_entry(server_port,
-				&server->server_port_list, list) {
-				if (i < num_entries_in_array) {
-					srv_info[i].node_id =
+		list_for_each_entry(server_port,
+			&server->server_port_list, list) {
+			if (i < num_entries_in_array) {
+				srv_info[i].node_id =
 					  server_port->server_addr.node_id;
-					srv_info[i].port_id =
+				srv_info[i].port_id =
 					  server_port->server_addr.port_id;
-					srv_info[i].service =
-					  server->name.service;
-					srv_info[i].instance =
-					  server->name.instance;
-				}
-				i++;
+				srv_info[i].service = server->name.service;
+				srv_info[i].instance = server->name.instance;
 			}
+			i++;
 		}
 	}
 	mutex_unlock(&server_list_lock);
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 3731722..0f17a0b 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -8,6 +8,7 @@
 obj-y += q6voice.o
 obj-y += snddev_hdmi.o
 obj-y += audio_mvs.o
+obj-$(CONFIG_ARCH_MSM8X60) += pcm_in_proxy.o
 obj-$(CONFIG_FB_MSM_HDMI_MSM_PANEL) += lpa_if_hdmi.o
 endif
 obj-$(CONFIG_MSM_QDSP6_APR) += apr.o apr_v1.o apr_tal.o q6core.o dsp_debug.o
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.c b/arch/arm/mach-msm/qdsp6v2/adsprpc.c
index 49008de..822da91 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsprpc.c
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc.c
@@ -11,6 +11,7 @@
  * GNU General Public License for more details.
  *
  */
+#include <linux/scatterlist.h>
 #include "adsprpc.h"
 
 struct smq_invoke_ctx {
@@ -70,14 +71,25 @@
 static int alloc_mem(struct fastrpc_buf *buf)
 {
 	struct ion_client *clnt = gfa.iclient;
+	struct sg_table *sg;
 	int err = 0;
 
 	buf->handle = ion_alloc(clnt, buf->size, SZ_4K,
 				ION_HEAP(ION_AUDIO_HEAP_ID), 0);
-	VERIFY(0 == IS_ERR_OR_NULL(buf->handle));
+	VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle));
+	if (err)
+		goto bail;
 	buf->virt = 0;
-	VERIFY(0 != (buf->virt = ion_map_kernel(clnt, buf->handle)));
-	VERIFY(0 == ion_phys(clnt, buf->handle, &buf->phys, &buf->size));
+	VERIFY(err, 0 != (buf->virt = ion_map_kernel(clnt, buf->handle)));
+	if (err)
+		goto bail;
+	VERIFY(err, 0 != (sg = ion_sg_table(clnt, buf->handle)));
+	if (err)
+		goto bail;
+	VERIFY(err, 1 == sg->nents);
+	if (err)
+		goto bail;
+	buf->phys = sg_dma_address(sg->sgl);
  bail:
 	if (err && !IS_ERR_OR_NULL(buf->handle))
 		free_mem(buf);
@@ -87,7 +99,9 @@
 static int context_list_ctor(struct smq_context_list *me, int size)
 {
 	int err = 0;
-	VERIFY(0 != (me->ls = kzalloc(size, GFP_KERNEL)));
+	VERIFY(err, 0 != (me->ls = kzalloc(size, GFP_KERNEL)));
+	if (err)
+		goto bail;
 	me->size = size / sizeof(*me->ls);
 	me->last = 0;
  bail:
@@ -103,18 +117,18 @@
 static void context_list_alloc_ctx(struct smq_context_list *me,
 					struct smq_invoke_ctx **po)
 {
-	int ii = me->last;
+	int i = me->last;
 	struct smq_invoke_ctx *ctx;
 
 	for (;;) {
-		ii = ii % me->size;
-		ctx = &me->ls[ii];
+		i = i % me->size;
+		ctx = &me->ls[i];
 		if (atomic_read(&ctx->free) == 0)
-			if (0 == atomic_cmpxchg(&ctx->free, 0, 1))
+			if (atomic_cmpxchg(&ctx->free, 0, 1) == 0)
 				break;
-		ii++;
+		i++;
 	}
-	me->last = ii;
+	me->last = i;
 	ctx->retval = -1;
 	init_completion(&ctx->work);
 	*po = ctx;
@@ -134,13 +148,13 @@
 
 static void context_notify_all_users(struct smq_context_list *me)
 {
-	int ii;
+	int i;
 
 	if (!me->ls)
 		return;
-	for (ii = 0; ii < me->size; ++ii) {
-		if (atomic_read(&me->ls[ii].free) != 0)
-			complete(&me->ls[ii].work);
+	for (i = 0; i < me->size; ++i) {
+		if (atomic_read(&me->ls[i].free) != 0)
+			complete(&me->ls[i].work);
 	}
 }
 
@@ -149,11 +163,10 @@
 {
 	struct smq_phy_page *pgstart, *pages;
 	struct smq_invoke_buf *list;
-	int ii, rlen, err = 0;
+	int i, rlen, err = 0;
 	int inbufs = REMOTE_SCALARS_INBUFS(sc);
 	int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
 
-	VERIFY(0 != try_module_get(THIS_MODULE));
 	LOCK_MMAP(kernel);
 	*obuf = *ibuf;
  retry:
@@ -165,38 +178,46 @@
 		rlen = ((uint32_t)pages - (uint32_t)obuf->virt) - obuf->size;
 		obuf->size += buf_page_size(rlen);
 		obuf->handle = 0;
-		VERIFY(0 == alloc_mem(obuf));
+		VERIFY(err, 0 == alloc_mem(obuf));
+		if (err)
+			goto bail;
 		goto retry;
 	}
 	pgstart->addr = obuf->phys;
 	pgstart->size = obuf->size;
-	for (ii = 0; ii < inbufs + outbufs; ++ii) {
+	for (i = 0; i < inbufs + outbufs; ++i) {
 		void *buf;
 		int len, num;
 
-		len = pra[ii].buf.len;
+		list[i].num = 0;
+		list[i].pgidx = 0;
+		len = pra[i].buf.len;
 		if (!len)
 			continue;
-		buf = pra[ii].buf.pv;
+		buf = pra[i].buf.pv;
 		num = buf_num_pages(buf, len);
 		if (!kernel)
-			list[ii].num = buf_get_pages(buf, len, num,
-				ii >= inbufs, pages, rlen / sizeof(*pages));
+			list[i].num = buf_get_pages(buf, len, num,
+				i >= inbufs, pages, rlen / sizeof(*pages));
 		else
-			list[ii].num = 0;
-		VERIFY(list[ii].num >= 0);
-		if (list[ii].num) {
-			list[ii].pgidx = pages - pgstart;
-			pages = pages + list[ii].num;
+			list[i].num = 0;
+		VERIFY(err, list[i].num >= 0);
+		if (err)
+			goto bail;
+		if (list[i].num) {
+			list[i].pgidx = pages - pgstart;
+			pages = pages + list[i].num;
 		} else if (rlen > sizeof(*pages)) {
-			list[ii].pgidx = pages - pgstart;
+			list[i].pgidx = pages - pgstart;
 			pages = pages + 1;
 		} else {
 			if (obuf->handle != ibuf->handle)
 				free_mem(obuf);
 			obuf->size += buf_page_size(sizeof(*pages));
 			obuf->handle = 0;
-			VERIFY(0 == alloc_mem(obuf));
+			VERIFY(err, 0 == alloc_mem(obuf));
+			if (err)
+				goto bail;
 			goto retry;
 		}
 		rlen = obuf->size - ((uint32_t) pages - (uint32_t) obuf->virt);
@@ -206,7 +227,6 @@
 	if (err && (obuf->handle != ibuf->handle))
 		free_mem(obuf);
 	UNLOCK_MMAP(kernel);
-	module_put(THIS_MODULE);
 	return err;
 }
 
@@ -219,74 +239,86 @@
 	struct fastrpc_buf *pbuf = ibuf, *obufs = 0;
 	struct smq_phy_page *pages;
 	void *args;
-	int ii, rlen, size, used, inh, bufs = 0, err = 0;
+	int i, rlen, size, used, inh, bufs = 0, err = 0;
 	int inbufs = REMOTE_SCALARS_INBUFS(sc);
 	int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
 
 	list = smq_invoke_buf_start(rpra, sc);
 	pages = smq_phy_page_start(sc, list);
-	used = ALIGN_8(pbuf->used);
+	used = ALIGN(pbuf->used, BALIGN);
 	args = (void *)((char *)pbuf->virt + used);
 	rlen = pbuf->size - used;
-	for (ii = 0; ii < inbufs + outbufs; ++ii) {
+	for (i = 0; i < inbufs + outbufs; ++i) {
 		int num;
 
-		rpra[ii].buf.len = pra[ii].buf.len;
-		if (list[ii].num) {
-			rpra[ii].buf.pv = pra[ii].buf.pv;
+		rpra[i].buf.len = pra[i].buf.len;
+		if (!rpra[i].buf.len)
+			continue;
+		if (list[i].num) {
+			rpra[i].buf.pv = pra[i].buf.pv;
 			continue;
 		}
-		if (rlen < pra[ii].buf.len) {
+		if (rlen < pra[i].buf.len) {
 			struct fastrpc_buf *b;
 			pbuf->used = pbuf->size - rlen;
-			VERIFY(0 != (b = krealloc(obufs,
+			VERIFY(err, 0 != (b = krealloc(obufs,
 				 (bufs + 1) * sizeof(*obufs), GFP_KERNEL)));
+			if (err)
+				goto bail;
 			obufs = b;
 			pbuf = obufs + bufs;
-			pbuf->size = buf_num_pages(0, pra[ii].buf.len) *
+			pbuf->size = buf_num_pages(0, pra[i].buf.len) *
 								PAGE_SIZE;
-			VERIFY(0 == alloc_mem(pbuf));
+			VERIFY(err, 0 == alloc_mem(pbuf));
+			if (err)
+				goto bail;
 			bufs++;
 			args = pbuf->virt;
 			rlen = pbuf->size;
 		}
-		num = buf_num_pages(args, pra[ii].buf.len);
+		num = buf_num_pages(args, pra[i].buf.len);
 		if (pbuf == ibuf) {
-			list[ii].num = num;
-			list[ii].pgidx = 0;
+			list[i].num = num;
+			list[i].pgidx = 0;
 		} else {
-			list[ii].num = 1;
-			pages[list[ii].pgidx].addr =
+			list[i].num = 1;
+			pages[list[i].pgidx].addr =
 				buf_page_start((void *)(pbuf->phys +
 							 (pbuf->size - rlen)));
-			pages[list[ii].pgidx].size =
-				buf_page_size(pra[ii].buf.len);
+			pages[list[i].pgidx].size =
+				buf_page_size(pra[i].buf.len);
 		}
-		if (ii < inbufs) {
-			if (!kernel)
-				VERIFY(0 == copy_from_user(args, pra[ii].buf.pv,
-							pra[ii].buf.len));
-			else
-				memmove(args, pra[ii].buf.pv, pra[ii].buf.len);
+		if (i < inbufs) {
+			if (!kernel) {
+				VERIFY(err, 0 == copy_from_user(args,
+						pra[i].buf.pv, pra[i].buf.len));
+				if (err)
+					goto bail;
+			} else {
+				memmove(args, pra[i].buf.pv, pra[i].buf.len);
+			}
 		}
-		rpra[ii].buf.pv = args;
-		args = (void *)((char *)args + ALIGN_8(pra[ii].buf.len));
-		rlen -= ALIGN_8(pra[ii].buf.len);
+		rpra[i].buf.pv = args;
+		args = (void *)((char *)args + ALIGN(pra[i].buf.len, BALIGN));
+		rlen -= ALIGN(pra[i].buf.len, BALIGN);
 	}
-	for (ii = 0; ii < inbufs; ++ii) {
-		if (rpra[ii].buf.len)
-			dmac_flush_range(rpra[ii].buf.pv,
-				  (char *)rpra[ii].buf.pv + rpra[ii].buf.len);
+	for (i = 0; i < inbufs; ++i) {
+		if (rpra[i].buf.len)
+			dmac_flush_range(rpra[i].buf.pv,
+				  (char *)rpra[i].buf.pv + rpra[i].buf.len);
 	}
 	pbuf->used = pbuf->size - rlen;
 	size = sizeof(*rpra) * REMOTE_SCALARS_INHANDLES(sc);
 	if (size) {
 		inh = inbufs + outbufs;
-		if (!kernel)
-			VERIFY(0 == copy_from_user(&rpra[inh], &upra[inh],
+		if (!kernel) {
+			VERIFY(err, 0 == copy_from_user(&rpra[inh], &upra[inh],
 							size));
-		else
+			if (err)
+				goto bail;
+		} else {
 			memmove(&rpra[inh], &upra[inh], size);
+		}
 	}
 	dmac_flush_range(rpra, (char *)rpra + used);
  bail:
@@ -298,24 +330,30 @@
 static int put_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
 			remote_arg_t *rpra, remote_arg_t *upra)
 {
-	int ii, inbufs, outbufs, outh, size;
+	int i, inbufs, outbufs, outh, size;
 	int err = 0;
 
 	inbufs = REMOTE_SCALARS_INBUFS(sc);
 	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
-	for (ii = inbufs; ii < inbufs + outbufs; ++ii) {
-		if (rpra[ii].buf.pv != pra[ii].buf.pv)
-			VERIFY(0 == copy_to_user(pra[ii].buf.pv,
-					rpra[ii].buf.pv, rpra[ii].buf.len));
+	for (i = inbufs; i < inbufs + outbufs; ++i) {
+		if (rpra[i].buf.pv != pra[i].buf.pv) {
+			VERIFY(err, 0 == copy_to_user(pra[i].buf.pv,
+					rpra[i].buf.pv, rpra[i].buf.len));
+			if (err)
+				goto bail;
+		}
 	}
 	size = sizeof(*rpra) * REMOTE_SCALARS_OUTHANDLES(sc);
 	if (size) {
 		outh = inbufs + outbufs + REMOTE_SCALARS_INHANDLES(sc);
-		if (!kernel)
-			VERIFY(0 == copy_to_user(&upra[outh], &rpra[outh],
+		if (!kernel) {
+			VERIFY(err, 0 == copy_to_user(&upra[outh], &rpra[outh],
 						size));
-		else
+			if (err)
+				goto bail;
+		} else {
 			memmove(&upra[outh], &rpra[outh], size);
+		}
 	}
  bail:
 	return err;
@@ -323,24 +361,24 @@
 
 static void inv_args(uint32_t sc, remote_arg_t *rpra, int used)
 {
-	int ii, inbufs, outbufs;
+	int i, inbufs, outbufs;
 	int inv = 0;
 
 	inbufs = REMOTE_SCALARS_INBUFS(sc);
 	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
-	for (ii = inbufs; ii < inbufs + outbufs; ++ii) {
-		if (buf_page_start(rpra) == buf_page_start(rpra[ii].buf.pv))
+	for (i = inbufs; i < inbufs + outbufs; ++i) {
+		if (buf_page_start(rpra) == buf_page_start(rpra[i].buf.pv))
 			inv = 1;
-		else
-			dmac_inv_range(rpra[ii].buf.pv,
-				(char *)rpra[ii].buf.pv + rpra[ii].buf.len);
+		else if (rpra[i].buf.len)
+			dmac_inv_range(rpra[i].buf.pv,
+				(char *)rpra[i].buf.pv + rpra[i].buf.len);
 	}
 
 	if (inv || REMOTE_SCALARS_OUTHANDLES(sc))
 		dmac_inv_range(rpra, (char *)rpra + used);
 }
 
-static int fastrpc_invoke_send(struct fastrpc_apps *me, remote_handle_t handle,
+static int fastrpc_invoke_send(struct fastrpc_apps *me, uint32_t handle,
 				 uint32_t sc, struct smq_invoke_ctx *ctx,
 				 struct fastrpc_buf *buf)
 {
@@ -357,8 +395,7 @@
 	spin_lock(&me->wrlock);
 	len = smd_write(me->chan, &msg, sizeof(msg));
 	spin_unlock(&me->wrlock);
-	VERIFY(len == sizeof(msg));
- bail:
+	VERIFY(err, len == sizeof(msg));
 	return err;
 }
 
@@ -369,7 +406,8 @@
 	if (me->chan)
 		(void)smd_close(me->chan);
 	context_list_dtor(&me->clst);
-	ion_client_destroy(me->iclient);
+	if (me->iclient)
+		ion_client_destroy(me->iclient);
 	me->iclient = 0;
 	me->chan = 0;
 }
@@ -381,8 +419,10 @@
 	int err = 0;
 
 	do {
-		VERIFY(sizeof(rsp) ==
+		VERIFY(err, sizeof(rsp) ==
 				 smd_read_from_cb(me->chan, &rsp, sizeof(rsp)));
+		if (err)
+			goto bail;
 		context_notify_user(rsp.ctx, rsp.retval);
 	} while (!err);
  bail:
@@ -412,21 +452,29 @@
 	struct fastrpc_apps *me = &gfa;
 
 	if (me->chan == 0) {
-		int ii;
+		int i;
 		spin_lock_init(&me->hlock);
 		spin_lock_init(&me->wrlock);
 		init_completion(&me->work);
-		for (ii = 0; ii < RPC_HASH_SZ; ++ii)
-			INIT_HLIST_HEAD(&me->htbl[ii]);
-		VERIFY(0 == context_list_ctor(&me->clst, SZ_4K));
+		for (i = 0; i < RPC_HASH_SZ; ++i)
+			INIT_HLIST_HEAD(&me->htbl[i]);
+		VERIFY(err, 0 == context_list_ctor(&me->clst, SZ_4K));
+		if (err)
+			goto bail;
 		me->iclient = msm_ion_client_create(ION_HEAP_CARVEOUT_MASK,
 							DEVICE_NAME);
-		VERIFY(0 == IS_ERR_OR_NULL(me->iclient));
-		VERIFY(0 == smd_named_open_on_edge(FASTRPC_SMD_GUID,
+		VERIFY(err, 0 == IS_ERR_OR_NULL(me->iclient));
+		if (err)
+			goto bail;
+		VERIFY(err, 0 == smd_named_open_on_edge(FASTRPC_SMD_GUID,
 						SMD_APPS_QDSP, &me->chan,
 						me, smd_event_handler));
-		VERIFY(0 != wait_for_completion_timeout(&me->work,
+		if (err)
+			goto bail;
+		VERIFY(err, 0 != wait_for_completion_timeout(&me->work,
 							RPC_TIMEOUT));
+		if (err)
+			goto bail;
 	}
  bail:
 	if (err)
@@ -448,10 +496,16 @@
 	int err = 0;
 	struct fastrpc_device *fd = 0;
 
-	VERIFY(0 != try_module_get(THIS_MODULE));
-	VERIFY(0 != (fd = kzalloc(sizeof(*fd), GFP_KERNEL)));
+	VERIFY(err, 0 != try_module_get(THIS_MODULE));
+	if (err)
+		goto bail;
+	VERIFY(err, 0 != (fd = kzalloc(sizeof(*fd), GFP_KERNEL)));
+	if (err)
+		goto bail;
 	fd->buf.size = PAGE_SIZE;
-	VERIFY(0 == alloc_mem(&fd->buf));
+	VERIFY(err, 0 == alloc_mem(&fd->buf));
+	if (err)
+		goto bail;
 	fd->tgid = current->tgid;
 	INIT_HLIST_NODE(&fd->hn);
 	*dev = fd;
@@ -478,7 +532,9 @@
 		}
 	}
 	spin_unlock(&me->hlock);
-	VERIFY(dev != 0);
+	VERIFY(err, dev != 0);
+	if (err)
+		goto bail;
 	*rdev = dev;
  bail:
 	if (err) {
@@ -511,34 +567,49 @@
 	struct fastrpc_buf obuf, *abufs = 0, *b;
 	int interrupted = 0;
 	uint32_t sc;
-	int ii, nbufs = 0, err = 0;
+	int i, nbufs = 0, err = 0;
 
 	sc = invoke->sc;
 	obuf.handle = 0;
 	if (REMOTE_SCALARS_LENGTH(sc)) {
-		VERIFY(0 == get_dev(me, &dev));
-		VERIFY(0 == get_page_list(kernel, sc, pra, &dev->buf, &obuf));
+		VERIFY(err, 0 == get_dev(me, &dev));
+		if (err)
+			goto bail;
+		VERIFY(err, 0 == get_page_list(kernel, sc, pra, &dev->buf,
+						&obuf));
+		if (err)
+			goto bail;
 		rpra = (remote_arg_t *)obuf.virt;
-		VERIFY(0 == get_args(kernel, sc, pra, rpra, invoke->pra, &obuf,
-					&abufs, &nbufs));
+		VERIFY(err, 0 == get_args(kernel, sc, pra, rpra, invoke->pra,
+					&obuf, &abufs, &nbufs));
+		if (err)
+			goto bail;
 	}
 
 	context_list_alloc_ctx(&me->clst, &ctx);
-	VERIFY(0 == fastrpc_invoke_send(me, invoke->handle, sc, ctx, &obuf));
+	VERIFY(err, 0 == fastrpc_invoke_send(me, invoke->handle, sc, ctx,
+						&obuf));
+	if (err)
+		goto bail;
 	inv_args(sc, rpra, obuf.used);
-	VERIFY(0 == (interrupted =
+	VERIFY(err, 0 == (interrupted =
 			wait_for_completion_interruptible(&ctx->work)));
-	VERIFY(0 == (err = ctx->retval));
-	VERIFY(0 == put_args(kernel, sc, pra, rpra, invoke->pra));
+	if (err)
+		goto bail;
+	VERIFY(err, 0 == (err = ctx->retval));
+	if (err)
+		goto bail;
+	VERIFY(err, 0 == put_args(kernel, sc, pra, rpra, invoke->pra));
+	if (err)
+		goto bail;
  bail:
 	if (interrupted) {
-		init_completion(&ctx->work);
 		if (!kernel)
 			(void)fastrpc_release_current_dsp_process();
 		wait_for_completion(&ctx->work);
 	}
 	context_free(ctx);
-	for (ii = 0, b = abufs; ii < nbufs; ++ii, ++b)
+	for (i = 0, b = abufs; i < nbufs; ++i, ++b)
 		free_mem(b);
 	kfree(abufs);
 	if (dev) {
@@ -563,8 +634,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
 	ioctl.pra = ra;
-	VERIFY(0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
- bail:
+	VERIFY(err, 0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
 	return err;
 }
 
@@ -582,8 +652,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
 	ioctl.pra = ra;
-	VERIFY(0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
- bail:
+	VERIFY(err, 0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
 	return err;
 }
 
@@ -628,8 +697,7 @@
 		/* This call will cause a dev to be created
 		 * which will addref this module
 		 */
-		VERIFY(0 == fastrpc_create_current_dsp_process());
- bail:
+		VERIFY(err, 0 == fastrpc_create_current_dsp_process());
 		if (err)
 			cleanup_current_dev();
 		module_put(THIS_MODULE);
@@ -649,19 +717,28 @@
 
 	switch (ioctl_num) {
 	case FASTRPC_IOCTL_INVOKE:
-		VERIFY(0 == copy_from_user(&invoke, param, sizeof(invoke)));
+		VERIFY(err, 0 == copy_from_user(&invoke, param,
+						sizeof(invoke)));
+		if (err)
+			goto bail;
 		bufs = REMOTE_SCALARS_INBUFS(invoke.sc) +
 			REMOTE_SCALARS_OUTBUFS(invoke.sc);
 		if (bufs) {
 			bufs = bufs * sizeof(*pra);
-			VERIFY(0 != (pra = kmalloc(bufs, GFP_KERNEL)));
+			VERIFY(err, 0 != (pra = kmalloc(bufs, GFP_KERNEL)));
+			if (err)
+				goto bail;
 		}
-		VERIFY(0 == copy_from_user(pra, invoke.pra, bufs));
-		VERIFY(0 == (err = fastrpc_internal_invoke(me, 0, &invoke,
+		VERIFY(err, 0 == copy_from_user(pra, invoke.pra, bufs));
+		if (err)
+			goto bail;
+		VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, &invoke,
 								pra)));
+		if (err)
+			goto bail;
 		break;
 	default:
-		err = -EINVAL;
+		err = -ENOTTY;
 		break;
 	}
  bail:
@@ -680,13 +757,24 @@
 	struct fastrpc_apps *me = &gfa;
 	int err = 0;
 
-	VERIFY(0 == fastrpc_init());
-	VERIFY(0 == alloc_chrdev_region(&me->dev_no, 0, 1, DEVICE_NAME));
+	VERIFY(err, 0 == fastrpc_init());
+	if (err)
+		goto bail;
+	VERIFY(err, 0 == alloc_chrdev_region(&me->dev_no, 0, 1, DEVICE_NAME));
+	if (err)
+		goto bail;
 	cdev_init(&me->cdev, &fops);
 	me->cdev.owner = THIS_MODULE;
-	VERIFY(0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), 1));
+	VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), 1));
+	if (err)
+		goto bail;
 	pr_info("'mknod /dev/%s c %d 0'\n", DEVICE_NAME, MAJOR(me->dev_no));
  bail:
+	if (err) {
+		if (me->dev_no)
+			unregister_chrdev_region(me->dev_no, 1);
+		fastrpc_deinit();
+	}
 	return err;
 }
 
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.h b/arch/arm/mach-msm/qdsp6v2/adsprpc.h
index c6c7d23..3f1b4a7 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsprpc.h
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc.h
@@ -36,8 +36,7 @@
 #define RPC_TIMEOUT	(5 * HZ)
 #define RPC_HASH_BITS	5
 #define RPC_HASH_SZ	(1 << RPC_HASH_BITS)
-
-#define ALIGN_8(a)	ALIGN(a, 8)
+#define BALIGN		32
 
 #define LOCK_MMAP(kernel)\
 		do {\
@@ -84,18 +83,26 @@
 	struct vm_area_struct *vma;
 	uint32_t start = buf_page_start(addr);
 	uint32_t len = nr_pages << PAGE_SHIFT;
-	uint32_t pfn;
+	unsigned long pfn;
 	int n = -1, err = 0;
 
-	VERIFY(0 != access_ok(access ? VERIFY_WRITE : VERIFY_READ,
+	VERIFY(err, 0 != access_ok(access ? VERIFY_WRITE : VERIFY_READ,
 			      (void __user *)start, len));
-	VERIFY(0 != (vma = find_vma(current->mm, start)));
-	VERIFY(((uint32_t)addr + sz) <= vma->vm_end);
+	if (err)
+		goto bail;
+	VERIFY(err, 0 != (vma = find_vma(current->mm, start)));
+	if (err)
+		goto bail;
+	VERIFY(err, ((uint32_t)addr + sz) <= vma->vm_end);
+	if (err)
+		goto bail;
 	n = 0;
-	VERIFY(0 != (vma->vm_flags & VM_PFNMAP));
-	VERIFY(0 != (vma->vm_flags & VM_PFN_AT_MMAP));
-	VERIFY(nr_elems > 0);
-	pfn = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+	VERIFY(err, 0 == follow_pfn(vma, start, &pfn));
+	if (err)
+		goto bail;
+	VERIFY(err, nr_elems > 0);
+	if (err)
+		goto bail;
 	pages->addr = __pfn_to_phys(pfn);
 	pages->size = len;
 	n++;
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h b/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
index 04b1d4a..dc6ab6f 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
@@ -60,20 +60,18 @@
 #define __TOSTR__(x) __STR__(x)
 #define __FILE_LINE__ __FILE__ ":" __TOSTR__(__LINE__)
 
-#define VERIFY(val) \
+#define VERIFY(err, val) \
 do {\
 	VERIFY_IPRINTF(__FILE_LINE__"info: calling: " #val "\n");\
 	if (0 == (val)) {\
-		err = err == 0 ? -1 : err;\
-		VERIFY_EPRINTF(__FILE_LINE__"error: %d: " #val "\n", err);\
-		goto bail;\
+		(err) = (err) == 0 ? -1 : (err);\
+		VERIFY_EPRINTF(__FILE_LINE__"error: %d: " #val "\n", (err));\
 	} else {\
 		VERIFY_IPRINTF(__FILE_LINE__"info: passed: " #val "\n");\
 	} \
 } while (0)
 #endif
 
-#define remote_handle_t uint32_t
 #define remote_arg_t    union remote_arg
 
 struct remote_buf {
@@ -83,18 +81,18 @@
 
 union remote_arg {
 	struct remote_buf buf;	/* buffer info */
-	remote_handle_t h;	/* remote handle */
+	uint32_t h;		/* remote handle */
 };
 
 struct fastrpc_ioctl_invoke {
-	remote_handle_t handle;	/* remote handle */
+	uint32_t handle;	/* remote handle */
 	uint32_t sc;		/* scalars describing the data */
 	remote_arg_t *pra;	/* remote arguments list */
 };
 
 struct smq_null_invoke {
 	struct smq_invoke_ctx *ctx; /* invoke caller context */
-	remote_handle_t handle;	    /* handle to invoke */
+	uint32_t handle;	    /* handle to invoke */
 	uint32_t sc;		    /* scalars structure describing the data */
 };
 
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c b/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c
new file mode 100644
index 0000000..84f136a
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c
@@ -0,0 +1,596 @@
+
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/msm_audio.h>
+
+#include <asm/atomic.h>
+#include <mach/debug_mm.h>
+#include <mach/qdsp6v2/audio_dev_ctl.h>
+#include <sound/q6asm.h>
+#include <sound/apr_audio.h>
+#include <linux/wakelock.h>
+#include <mach/cpuidle.h>
+
+#define MAX_BUF 4
+
+struct dma_buf {
+	uint32_t addr;
+	uint32_t v_addr;
+	uint32_t used;
+};
+struct pcm {
+	struct mutex lock;
+	struct mutex read_lock;
+	wait_queue_head_t wait;
+	spinlock_t dsp_lock;
+	struct audio_client *ac;
+	uint32_t sample_rate;
+	uint32_t channel_count;
+	uint32_t buffer_size;
+	uint32_t buffer_count;
+	uint32_t cpu_idx;
+	uint32_t dsp_idx;
+	uint32_t start;
+	uint32_t dma_addr;
+	uint32_t dma_virt;
+	struct dma_buf dma_buf[MAX_BUF];
+	atomic_t in_count;
+	atomic_t in_enabled;
+	atomic_t in_opened;
+	atomic_t in_stopped;
+	int poll_time;
+	struct hrtimer hrt;
+};
+
+static enum hrtimer_restart afe_hrtimer_callback(struct hrtimer *hrt);
+
+static enum hrtimer_restart afe_hrtimer_callback(struct hrtimer *hrt)
+{
+	struct pcm *pcm =
+		container_of(hrt, struct pcm, hrt);
+	int rc = 0;
+	if (pcm->start) {
+		if (pcm->dsp_idx == pcm->buffer_count)
+			pcm->dsp_idx = 0;
+		rc = wait_event_timeout(pcm->wait,
+				(pcm->dma_buf[pcm->dsp_idx].used == 0) ||
+				atomic_read(&pcm->in_stopped), 1 * HZ);
+		if (!rc) {
+			pr_err("%s: wait_event_timeout failed\n", __func__);
+			goto fail;
+		}
+		if (atomic_read(&pcm->in_stopped)) {
+			pr_err("%s: Driver closed - return\n", __func__);
+			return HRTIMER_NORESTART;
+		}
+		rc = afe_rt_proxy_port_read(
+			pcm->dma_buf[pcm->dsp_idx].addr,
+			pcm->buffer_size);
+		if (rc < 0) {
+			pr_err("%s afe_rt_proxy_port_read fail\n", __func__);
+			goto fail;
+		}
+		pcm->dma_buf[pcm->dsp_idx].used = 1;
+		pcm->dsp_idx++;
+		pr_debug("%s: sending frame rec to DSP: poll_time: %d\n",
+				__func__, pcm->poll_time);
+fail:
+		hrtimer_forward_now(hrt, ns_to_ktime(pcm->poll_time
+				* 1000));
+
+		return HRTIMER_RESTART;
+	} else {
+		return HRTIMER_NORESTART;
+	}
+}
+
+static void pcm_afe_callback(uint32_t opcode,
+		uint32_t token, uint32_t *payload,
+		 void *priv)
+{
+	struct pcm *pcm = (struct pcm *)priv;
+	unsigned long dsp_flags;
+	uint16_t event;
+
+	if (pcm == NULL)
+		return;
+	pr_debug("%s\n", __func__);
+	spin_lock_irqsave(&pcm->dsp_lock, dsp_flags);
+	switch (opcode) {
+	case AFE_EVENT_RT_PROXY_PORT_STATUS: {
+		event = (uint16_t)((0xFFFF0000 & payload[0]) >> 0x10);
+		switch (event) {
+		case AFE_EVENT_RTPORT_START: {
+			pcm->dsp_idx = 0;
+			pcm->cpu_idx = 0;
+			pcm->poll_time = (unsigned long)
+						(((pcm->buffer_size*1000)/
+						(pcm->channel_count *
+						pcm->sample_rate * 2))*1000);
+			pr_debug("%s: poll_time:%d\n", __func__,
+						pcm->poll_time);
+			pcm->start = 1;
+			wake_up(&pcm->wait);
+			break;
+		}
+		case AFE_EVENT_RTPORT_STOP:
+			pr_debug("%s: event!=0\n", __func__);
+			pcm->start = 0;
+			atomic_set(&pcm->in_stopped, 1);
+			break;
+		case AFE_EVENT_RTPORT_LOW_WM:
+			pr_debug("%s: Underrun\n", __func__);
+			break;
+		case AFE_EVENT_RTPORT_HI_WM:
+			pr_debug("%s: Overrun\n", __func__);
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	case APR_BASIC_RSP_RESULT: {
+		switch (payload[0]) {
+		case AFE_SERVICE_CMD_RTPORT_RD:
+			pr_debug("%s: Read done\n", __func__);
+			atomic_inc(&pcm->in_count);
+			wake_up(&pcm->wait);
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&pcm->dsp_lock, dsp_flags);
+}
+
+static uint32_t getbuffersize(uint32_t samplerate)
+{
+	if (samplerate == 8000)
+		return 480*8;
+	else if (samplerate == 16000)
+		return 480*16;
+	else if (samplerate == 48000)
+		return 480*48;
+	return 0;
+}
+
+static int pcm_in_open(struct inode *inode, struct file *file)
+{
+	struct pcm *pcm;
+	int rc = 0;
+
+	pr_debug("%s: pcm proxy in open session\n", __func__);
+	pcm = kzalloc(sizeof(struct pcm), GFP_KERNEL);
+	if (!pcm)
+		return -ENOMEM;
+
+	pcm->channel_count = 1;
+	pcm->sample_rate = 8000;
+	pcm->buffer_size = getbuffersize(pcm->sample_rate);
+	pcm->buffer_count = MAX_BUF;
+
+	pcm->ac = q6asm_audio_client_alloc(NULL, (void *)pcm);
+	if (!pcm->ac) {
+		pr_err("%s: Could not allocate memory\n", __func__);
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	mutex_init(&pcm->lock);
+	mutex_init(&pcm->read_lock);
+	spin_lock_init(&pcm->dsp_lock);
+	init_waitqueue_head(&pcm->wait);
+
+	hrtimer_init(&pcm->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	pcm->hrt.function = afe_hrtimer_callback;
+
+	atomic_set(&pcm->in_stopped, 0);
+	atomic_set(&pcm->in_enabled, 0);
+	atomic_set(&pcm->in_count, 0);
+	atomic_set(&pcm->in_opened, 1);
+
+	file->private_data = pcm;
+	pr_debug("%s: pcm proxy open success session id:%d\n",
+				__func__, pcm->ac->session);
+	return 0;
+fail:
+	if (pcm->ac)
+		q6asm_audio_client_free(pcm->ac);
+	kfree(pcm);
+	return rc;
+}
+
+static int pcm_in_disable(struct pcm *pcm)
+{
+	int rc = 0;
+
+	if (atomic_read(&pcm->in_opened)) {
+		atomic_set(&pcm->in_enabled, 0);
+		atomic_set(&pcm->in_opened, 0);
+		atomic_set(&pcm->in_stopped, 1);
+		wake_up(&pcm->wait);
+	}
+	return rc;
+}
+
+static int config(struct pcm *pcm)
+{
+
+	int ret = 0, i;
+	struct audio_buffer *buf;
+
+	pr_debug("%s\n", __func__);
+
+	ret = q6asm_audio_client_buf_alloc_contiguous(OUT,
+			pcm->ac,
+			pcm->buffer_size,
+			pcm->buffer_count);
+	if (ret < 0) {
+		pr_err("%s: Audio Start: Buffer Allocation failed rc = %d\n",
+								__func__, ret);
+		return -ENOMEM;
+	}
+	buf = pcm->ac->port[OUT].buf;
+
+	if (buf == NULL || buf[0].data == NULL)
+		return -ENOMEM;
+
+	memset(buf[0].data, 0, pcm->buffer_size * pcm->buffer_count);
+	pcm->dma_addr = (u32) buf[0].phys;
+	pcm->dma_virt = (u32) buf[0].data;
+
+	for (i = 0; i < pcm->buffer_count; i++) {
+		pcm->dma_buf[i].addr = (u32) (buf[i].phys);
+		pcm->dma_buf[i].v_addr = (u32) (buf[i].data);
+		pcm->dma_buf[i].used = 0;
+	}
+
+	ret = afe_register_get_events(RT_PROXY_DAI_001_TX,
+			pcm_afe_callback, pcm);
+	if (ret < 0) {
+		pr_err("%s: afe-pcm:register for events failed\n", __func__);
+		return ret;
+	}
+	ret = afe_cmd_memory_map(pcm->dma_addr,
+			pcm->buffer_size * pcm->buffer_count);
+	if (ret < 0) {
+		pr_err("%s: fail to map memory to DSP\n", __func__);
+		return ret;
+	}
+
+	pr_debug("%s:success\n", __func__);
+	return ret;
+}
+static bool is_dma_buf_avail(struct pcm *pcm)
+{
+	return (pcm->dma_buf[pcm->cpu_idx].used == 1);
+}
+static ssize_t pcm_in_read(struct file *file, char __user *buf,
+			  size_t count, loff_t *pos)
+{
+	struct pcm *pcm = file->private_data;
+	const char __user *start = buf;
+	int rc = 0;
+	bool rc1 = false;
+	int len = 0;
+
+	if (!atomic_read(&pcm->in_enabled))
+		return -EFAULT;
+	mutex_lock(&pcm->read_lock);
+	while (count > 0) {
+		rc = wait_event_timeout(pcm->wait,
+				(atomic_read(&pcm->in_count) ||
+				atomic_read(&pcm->in_stopped)), 2 * HZ);
+		if (!rc) {
+			pr_err("%s: wait_event_timeout failed\n", __func__);
+			goto fail;
+		}
+		if (atomic_read(&pcm->in_stopped) &&
+					!atomic_read(&pcm->in_count)) {
+			pr_err("%s: count:%d/stopped:%d failed\n", __func__,
+					atomic_read(&pcm->in_count),
+					atomic_read(&pcm->in_stopped));
+			mutex_unlock(&pcm->read_lock);
+			return 0;
+		}
+
+		rc1 = is_dma_buf_avail(pcm);
+		if (!rc1) {
+			pr_err("%s: DMA buf not ready-returning from read\n",
+								__func__);
+			goto fail;
+		}
+		if (count >= pcm->buffer_size)
+			len = pcm->buffer_size;
+		else {
+			len = count;
+			pr_err("%s: short bytesavail[%d]"\
+				"bytesrequest[%d]"\
+				"bytesrejected%d]\n",\
+				__func__, pcm->buffer_size,
+				count, (pcm->buffer_size - count));
+		}
+		if (len) {
+			if (copy_to_user(buf,
+				(char *)(pcm->dma_buf[pcm->cpu_idx].v_addr),
+				len)) {
+				pr_err("%s copy_to_user failed len[%d]\n",
+							__func__, len);
+				rc = -EFAULT;
+				goto fail;
+			}
+			count -= len;
+			buf += len;
+		}
+		atomic_dec(&pcm->in_count);
+		memset((char *)(pcm->dma_buf[pcm->cpu_idx].v_addr),
+						0, pcm->buffer_size);
+		pcm->dma_buf[pcm->cpu_idx].used = 0;
+		wake_up(&pcm->wait);
+		pcm->cpu_idx++;
+		if (pcm->cpu_idx == pcm->buffer_count)
+			pcm->cpu_idx = 0;
+
+	}
+	rc = buf-start;
+	pr_debug("%s: pcm_in_read:rc:%d\n", __func__, rc);
+
+fail:
+	mutex_unlock(&pcm->read_lock);
+	return rc;
+}
+
+static int afe_start(struct pcm *pcm)
+{
+	union afe_port_config port_config;
+	port_config.rtproxy.num_ch =
+			pcm->channel_count;
+
+	pr_debug("%s: channel %d entered,port: %d,rate: %d\n", __func__,
+	port_config.rtproxy.num_ch, RT_PROXY_DAI_001_TX, pcm->sample_rate);
+
+	port_config.rtproxy.bitwidth = 16; /* Q6 only supports 16 */
+	port_config.rtproxy.interleaved = 1;
+	port_config.rtproxy.frame_sz = pcm->buffer_size;
+	port_config.rtproxy.jitter =
+				port_config.rtproxy.frame_sz/2;
+	port_config.rtproxy.lw_mark = 0;
+	port_config.rtproxy.hw_mark = 0;
+	port_config.rtproxy.rsvd = 0;
+	afe_open(RT_PROXY_DAI_001_TX, &port_config, pcm->sample_rate);
+	return 0;
+
+}
+
+static long pcm_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct pcm *pcm = file->private_data;
+	int rc = 0;
+
+	mutex_lock(&pcm->lock);
+	switch (cmd) {
+	case AUDIO_START: {
+		pr_debug("%s: AUDIO_START\n", __func__);
+		if (atomic_read(&pcm->in_enabled)) {
+			pr_info("%s:AUDIO_START already over\n", __func__);
+			rc = 0;
+			break;
+		}
+		rc = config(pcm);
+		if (rc) {
+			pr_err("%s: IN Configuration failed\n", __func__);
+			rc = -EFAULT;
+			break;
+		}
+		pr_debug("%s: call config done\n", __func__);
+		atomic_set(&pcm->in_enabled, 1);
+		afe_start(pcm);
+		rc = wait_event_timeout(pcm->wait,
+				((pcm->start == 1) ||
+				atomic_read(&pcm->in_stopped)), 5 * HZ);
+		if (!rc) {
+			pr_err("%s: wait_event_timeout failed\n", __func__);
+			goto fail;
+		}
+		pr_debug("%s: afe start done\n", __func__);
+		if (atomic_read(&pcm->in_stopped)) {
+			pr_err("%s: stopped unexpected before start!!\n",
+								__func__);
+			mutex_unlock(&pcm->lock);
+			return 0;
+		}
+
+		hrtimer_start(&pcm->hrt, ns_to_ktime(0),
+					HRTIMER_MODE_REL);
+		break;
+	}
+	case AUDIO_STOP:
+		break;
+	case AUDIO_FLUSH:
+		break;
+	case AUDIO_SET_CONFIG: {
+		struct msm_audio_config config;
+
+		if (copy_from_user(&config, (void *) arg, sizeof(config))) {
+			rc = -EFAULT;
+			break;
+		}
+		pr_debug("%s: SET_CONFIG: channel_count:%d"\
+			"sample_rate:%d\n", __func__,
+			config.channel_count,
+			config.sample_rate);
+
+		if (!config.channel_count || config.channel_count > 2) {
+			pr_err("%s: Channels(%d) not supported\n",
+				__func__, config.channel_count);
+			rc = -EINVAL;
+			break;
+		}
+
+		if (config.sample_rate != 8000 &&
+			config.sample_rate != 16000 &&
+			config.sample_rate != 48000) {
+			pr_err("%s: Sample rate(%d) not supported\n",
+				__func__, config.sample_rate);
+			rc = -EINVAL;
+			break;
+		}
+
+		pcm->sample_rate = config.sample_rate;
+		pcm->channel_count = config.channel_count;
+		pcm->buffer_size = getbuffersize(pcm->sample_rate);
+
+		pr_debug("%s: Calculated buff size %d", __func__,
+						pcm->buffer_size);
+		break;
+	}
+	case AUDIO_GET_CONFIG: {
+		struct msm_audio_config config;
+		config.buffer_size = pcm->buffer_size;
+		config.buffer_count = pcm->buffer_count;
+		config.sample_rate = pcm->sample_rate;
+		config.channel_count = pcm->channel_count;
+		config.unused[0] = 0;
+		config.unused[1] = 0;
+		config.unused[2] = 0;
+		if (copy_to_user((void *) arg, &config, sizeof(config)))
+			rc = -EFAULT;
+		break;
+	}
+	case AUDIO_PAUSE:
+		pr_debug("%s: AUDIO_PAUSE %ld\n", __func__, arg);
+		if (arg == 1) {
+			pcm->start = 0;
+		} else if (arg == 0) {
+			pcm->start = 1;
+			hrtimer_start(&pcm->hrt, ns_to_ktime(0),
+					HRTIMER_MODE_REL);
+		}
+	break;
+
+	default:
+		rc = -EINVAL;
+		break;
+	}
+fail:
+	mutex_unlock(&pcm->lock);
+	return rc;
+}
+
+static int pcm_in_release(struct inode *inode, struct file *file)
+{
+	int rc = 0;
+	struct pcm *pcm = file->private_data;
+
+	pr_debug("[%s:%s] release session id[%d]\n", __MM_FILE__,
+		__func__, pcm->ac->session);
+	mutex_lock(&pcm->lock);
+
+
+	/* remove this session from topology list */
+	auddev_cfg_tx_copp_topology(pcm->ac->session,
+				DEFAULT_COPP_TOPOLOGY);
+
+	rc = pcm_in_disable(pcm);
+	hrtimer_cancel(&pcm->hrt);
+	rc = afe_cmd_memory_unmap(pcm->dma_addr);
+	if (rc < 0)
+		pr_err("%s: AFE memory unmap failed\n", __func__);
+	rc =  afe_unregister_get_events(RT_PROXY_DAI_001_TX);
+	if (rc < 0)
+		pr_err("%s: AFE unregister for events failed\n", __func__);
+
+	afe_close(RT_PROXY_DAI_001_TX);
+	pr_debug("%s: release all buffer\n", __func__);
+	q6asm_audio_client_buf_free_contiguous(OUT,
+				pcm->ac);
+	msm_clear_session_id(pcm->ac->session);
+	q6asm_audio_client_free(pcm->ac);
+	mutex_unlock(&pcm->lock);
+	mutex_destroy(&pcm->lock);
+	mutex_destroy(&pcm->read_lock);
+	kfree(pcm);
+	return rc;
+}
+
+static const struct file_operations pcm_in_proxy_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pcm_in_open,
+	.read		= pcm_in_read,
+	.release	= pcm_in_release,
+	.unlocked_ioctl	= pcm_in_ioctl,
+};
+
+struct miscdevice pcm_in_proxy_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "msm_pcm_in_proxy",
+	.fops	= &pcm_in_proxy_fops,
+};
+
+static int snddev_rtproxy_open(struct msm_snddev_info *dev_info)
+{
+	return 0;
+}
+
+static int snddev_rtproxy_close(struct msm_snddev_info *dev_info)
+{
+	return 0;
+}
+
+static int snddev_rtproxy_set_freq(struct msm_snddev_info *dev_info,
+				u32 req_freq)
+{
+	return 48000;
+}
+
+static int __init pcm_in_proxy_init(void)
+{
+	struct msm_snddev_info *dev_info;
+
+	dev_info = kzalloc(sizeof(struct msm_snddev_info), GFP_KERNEL);
+	if (!dev_info) {
+		pr_err("unable to allocate memeory for msm_snddev_info\n");
+		return -ENOMEM;
+	}
+	dev_info->name = "rtproxy_rx";
+	dev_info->copp_id = RT_PROXY_PORT_001_RX;
+	dev_info->acdb_id = 0;
+	dev_info->private_data = NULL;
+	dev_info->dev_ops.open = snddev_rtproxy_open;
+	dev_info->dev_ops.close = snddev_rtproxy_close;
+	dev_info->dev_ops.set_freq = snddev_rtproxy_set_freq;
+	dev_info->capability = SNDDEV_CAP_RX;
+	dev_info->opened = 0;
+	msm_snddev_register(dev_info);
+	dev_info->sample_rate = 48000;
+
+	pr_debug("%s: init done for proxy\n", __func__);
+
+	return misc_register(&pcm_in_proxy_misc);
+}
+
+device_initcall(pcm_in_proxy_init);
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 2189747..7966177 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -228,6 +228,7 @@
 	}
 
 	flush_cache_all();
+	outer_flush_all();
 }
 
 void msm_restart(char mode, const char *cmd)
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index 368aac4..69a2f1c 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -1703,7 +1703,7 @@
 }
 
 static const struct of_device_id epm_adc_psoc_match_table[] = {
-	{	.compatible = "qcom,epm-adc",
+	{	.compatible = "cy,epm-adc-cy8c5568lti-114",
 	},
 	{}
 };
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index aa375d7..0a85b93 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -111,6 +111,13 @@
 #define QPNP_DATA1					0x61
 #define QPNP_CONV_TIMEOUT_ERR				2
 
+#define QPNP_IADC_SEC_ACCESS				0xD0
+#define QPNP_IADC_SEC_ACCESS_DATA			0xA5
+#define QPNP_IADC_MSB_OFFSET				0xF2
+#define QPNP_IADC_LSB_OFFSET				0xF3
+#define QPNP_IADC_NOMINAL_RSENSE			0xF4
+#define QPNP_IADC_ATE_GAIN_CALIB_OFFSET			0xF5
+
 #define QPNP_IADC_ADC_CH_SEL_CTL			0x48
 #define QPNP_IADC_ADC_CHX_SEL_SHIFT			3
 
@@ -127,15 +134,27 @@
 #define QPNP_ADC_CONV_TIME_MIN				8000
 #define QPNP_ADC_CONV_TIME_MAX				8200
 
-#define QPNP_ADC_GAIN_CALCULATION_UV			17857
-#define QPNP_IADC_RSENSE_MILLI_FACTOR			1000
+#define QPNP_ADC_GAIN_NV				17857
+#define QPNP_OFFSET_CALIBRATION_SHORT_CADC_LEADS_IDEAL	0
+#define QPNP_IADC_INTERNAL_RSENSE_N_OHMS_FACTOR		10000000
+#define QPNP_IADC_NANO_VOLTS_FACTOR			1000000000
+#define QPNP_IADC_CALIB_SECONDS				300000
+#define QPNP_IADC_RSENSE_LSB_N_OHMS_PER_BIT		15625
+#define QPNP_IADC_DIE_TEMP_CALIB_OFFSET			5000
+
+#define QPNP_RAW_CODE_16_BIT_MSB_MASK			0xff00
+#define QPNP_RAW_CODE_16_BIT_LSB_MASK			0xff
+#define QPNP_BIT_SHIFT_8				8
+#define QPNP_RSENSE_MSB_SIGN_CHECK			0x80
 
 struct qpnp_iadc_drv {
-	struct qpnp_adc_drv		*adc;
-	int32_t				rsense;
-	struct device			*iadc_hwmon;
-	bool				iadc_init_calib;
-	bool				iadc_initialized;
+	struct qpnp_adc_drv			*adc;
+	int32_t					rsense;
+	struct device				*iadc_hwmon;
+	bool					iadc_init_calib;
+	bool					iadc_initialized;
+	int64_t					die_temp_calib_offset;
+	struct delayed_work			iadc_work;
 	struct sensor_device_attribute		sens_attr[0];
 };
 
@@ -253,9 +272,10 @@
 	return 0;
 }
 
-static int32_t qpnp_iadc_read_conversion_result(int32_t *data)
+static int32_t qpnp_iadc_read_conversion_result(uint16_t *data)
 {
 	uint8_t rslt_lsb, rslt_msb;
+	uint16_t rslt;
 	int32_t rc;
 
 	rc = qpnp_iadc_read_reg(QPNP_IADC_DATA0, &rslt_lsb);
@@ -270,16 +290,18 @@
 		return rc;
 	}
 
-	*data = (rslt_msb << 8) | rslt_lsb;
+	rslt = (rslt_msb << 8) | rslt_lsb;
+	*data = rslt;
 
 	rc = qpnp_iadc_enable(false);
 	if (rc)
 		return rc;
+
 	return 0;
 }
 
 static int32_t qpnp_iadc_configure(enum qpnp_iadc_channels channel,
-						int32_t *result)
+						uint16_t *raw_code)
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
 	u8 qpnp_iadc_mode_reg = 0, qpnp_iadc_ch_sel_reg = 0;
@@ -346,7 +368,7 @@
 
 	wait_for_completion(&iadc->adc->adc_rslt_completion);
 
-	rc = qpnp_iadc_read_conversion_result(result);
+	rc = qpnp_iadc_read_conversion_result(raw_code);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
 		return rc;
@@ -355,32 +377,109 @@
 	return 0;
 }
 
-static int32_t qpnp_iadc_init_calib(void)
+static int32_t qpnp_convert_raw_offset_voltage(void)
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
-	int32_t rc = 0, result;
+	uint32_t num = 0;
 
-	rc = qpnp_iadc_configure(GAIN_CALIBRATION_25MV, &result);
+	num = iadc->adc->calib.offset_raw - iadc->adc->calib.offset_raw;
+
+	iadc->adc->calib.offset_uv = (num * QPNP_ADC_GAIN_NV)/
+		(iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
+
+	num = iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw;
+
+	iadc->adc->calib.gain_uv = (num * QPNP_ADC_GAIN_NV)/
+		(iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
+
+	return 0;
+}
+
+static int32_t qpnp_iadc_calibrate_for_trim(void)
+{
+	struct qpnp_iadc_drv *iadc = qpnp_iadc;
+	uint8_t rslt_lsb, rslt_msb;
+	int32_t rc = 0;
+	uint16_t raw_data;
+
+	rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV, &raw_data);
 	if (rc < 0) {
 		pr_err("qpnp adc result read failed with %d\n", rc);
 		goto fail;
 	}
 
-	iadc->adc->calib.gain = result;
+	iadc->adc->calib.gain_raw = raw_data;
 
 	rc = qpnp_iadc_configure(OFFSET_CALIBRATION_SHORT_CADC_LEADS,
-								&result);
+								&raw_data);
 	if (rc < 0) {
 		pr_err("qpnp adc result read failed with %d\n", rc);
 		goto fail;
 	}
 
-	iadc->adc->calib.offset = result;
+	iadc->adc->calib.offset_raw = raw_data;
+	if (rc < 0) {
+		pr_err("qpnp adc offset/gain calculation failed\n");
+		goto fail;
+	}
 
+	rc = qpnp_convert_raw_offset_voltage();
+
+	rslt_msb = (raw_data & QPNP_RAW_CODE_16_BIT_MSB_MASK) >>
+							QPNP_BIT_SHIFT_8;
+	rslt_lsb = raw_data & QPNP_RAW_CODE_16_BIT_LSB_MASK;
+
+	rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
+					QPNP_IADC_SEC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("qpnp iadc configure error for sec access\n");
+		goto fail;
+	}
+
+	rc = qpnp_iadc_write_reg(QPNP_IADC_MSB_OFFSET,
+						rslt_msb);
+	if (rc < 0) {
+		pr_err("qpnp iadc configure error for MSB write\n");
+		goto fail;
+	}
+
+	rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
+					QPNP_IADC_SEC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("qpnp iadc configure error for sec access\n");
+		goto fail;
+	}
+
+	rc = qpnp_iadc_write_reg(QPNP_IADC_LSB_OFFSET,
+						rslt_lsb);
+	if (rc < 0) {
+		pr_err("qpnp iadc configure error for LSB write\n");
+		goto fail;
+	}
 fail:
 	return rc;
 }
 
+static void qpnp_iadc_work(struct work_struct *work)
+{
+	struct qpnp_iadc_drv *iadc = qpnp_iadc;
+	int rc = 0;
+
+	mutex_lock(&iadc->adc->adc_lock);
+
+	rc = qpnp_iadc_calibrate_for_trim();
+	if (rc)
+		pr_err("periodic IADC calibration failed\n");
+
+	mutex_unlock(&iadc->adc->adc_lock);
+
+	schedule_delayed_work(&iadc->iadc_work,
+			round_jiffies_relative(msecs_to_jiffies
+					(QPNP_IADC_CALIB_SECONDS)));
+
+	return;
+}
+
 static int32_t qpnp_iadc_version_check(void)
 {
 	uint8_t revision;
@@ -411,40 +510,102 @@
 }
 EXPORT_SYMBOL(qpnp_iadc_is_ready);
 
-int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
-						int32_t *result)
+int32_t qpnp_iadc_get_rsense(int32_t *rsense)
+{
+	uint8_t	rslt_rsense;
+	int32_t	rc, sign_bit = 0;
+
+	rc = qpnp_iadc_read_reg(QPNP_IADC_NOMINAL_RSENSE, &rslt_rsense);
+	if (rc < 0) {
+		pr_err("qpnp adc rsense read failed with %d\n", rc);
+		return rc;
+	}
+
+	if (rslt_rsense & QPNP_RSENSE_MSB_SIGN_CHECK)
+		sign_bit = 1;
+
+	rslt_rsense &= ~QPNP_RSENSE_MSB_SIGN_CHECK;
+
+	if (sign_bit)
+		*rsense = QPNP_IADC_INTERNAL_RSENSE_N_OHMS_FACTOR -
+			(rslt_rsense * QPNP_IADC_RSENSE_LSB_N_OHMS_PER_BIT);
+	else
+		*rsense = QPNP_IADC_INTERNAL_RSENSE_N_OHMS_FACTOR +
+			(rslt_rsense * QPNP_IADC_RSENSE_LSB_N_OHMS_PER_BIT);
+
+	return rc;
+}
+
+int32_t qpnp_check_pmic_temp(void)
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
-	int32_t vsense_mv = 0, rc;
+	struct qpnp_vadc_result result_pmic_therm;
+	int rc;
+
+	rc = qpnp_vadc_read(DIE_TEMP, &result_pmic_therm);
+	if (rc < 0)
+		return rc;
+
+	if (((uint64_t) (result_pmic_therm.physical -
+				iadc->die_temp_calib_offset))
+			> QPNP_IADC_DIE_TEMP_CALIB_OFFSET) {
+		mutex_lock(&iadc->adc->adc_lock);
+
+		rc = qpnp_iadc_calibrate_for_trim();
+		if (rc)
+			pr_err("periodic IADC calibration failed\n");
+
+		mutex_unlock(&iadc->adc->adc_lock);
+	}
+
+	return 0;
+}
+
+int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
+				struct qpnp_iadc_result *result)
+{
+	struct qpnp_iadc_drv *iadc = qpnp_iadc;
+	int32_t rc, rsense_n_ohms, sign = 0, num;
+	int64_t result_current;
+	uint16_t raw_data;
 
 	if (!iadc || !iadc->iadc_initialized)
 		return -EPROBE_DEFER;
 
-	mutex_lock(&iadc->adc->adc_lock);
-
-	if (!iadc->iadc_init_calib) {
-		rc = qpnp_iadc_version_check();
-		if (rc)
-			goto fail;
-		rc = qpnp_iadc_init_calib();
-		if (rc) {
-			pr_err("Calibration failed\n");
-			goto fail;
-		} else
-			iadc->iadc_init_calib = true;
+	rc = qpnp_check_pmic_temp();
+	if (rc) {
+		pr_err("Error checking pmic therm temp\n");
+		return rc;
 	}
 
-	rc = qpnp_iadc_configure(channel, result);
+	mutex_lock(&iadc->adc->adc_lock);
+
+	rc = qpnp_iadc_configure(channel, &raw_data);
 	if (rc < 0) {
 		pr_err("qpnp adc result read failed with %d\n", rc);
 		goto fail;
 	}
 
-	*result = ((vsense_mv - iadc->adc->calib.offset) *
-				QPNP_ADC_GAIN_CALCULATION_UV)/
-			(iadc->adc->calib.gain - iadc->adc->calib.offset);
+	rc = qpnp_iadc_get_rsense(&rsense_n_ohms);
 
-	*result = (*result / (qpnp_iadc->rsense));
+	num = raw_data - iadc->adc->calib.offset_raw;
+	if (num < 0) {
+		sign = 1;
+		num = -num;
+	}
+
+	result->result_uv = (num * QPNP_ADC_GAIN_NV)/
+		(iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
+	result_current = result->result_uv;
+	result_current *= QPNP_IADC_NANO_VOLTS_FACTOR;
+	do_div(result_current, rsense_n_ohms);
+
+	if (sign) {
+		result->result_uv = -result->result_uv;
+		result_current = -result_current;
+	}
+
+	result->result_ua = (int32_t) result_current;
 fail:
 	mutex_unlock(&iadc->adc->adc_lock);
 
@@ -452,24 +613,39 @@
 }
 EXPORT_SYMBOL(qpnp_iadc_read);
 
-int32_t qpnp_iadc_get_gain(int32_t *result)
+int32_t qpnp_iadc_get_gain_and_offset(struct qpnp_iadc_calib *result)
 {
-	return qpnp_iadc_read(GAIN_CALIBRATION_25MV, result);
-}
-EXPORT_SYMBOL(qpnp_iadc_get_gain);
+	struct qpnp_iadc_drv *iadc = qpnp_iadc;
+	int rc;
 
-int32_t qpnp_iadc_get_offset(enum qpnp_iadc_channels channel,
-						int32_t *result)
-{
-	return qpnp_iadc_read(channel, result);
+	if (!iadc || !iadc->iadc_initialized)
+		return -EPROBE_DEFER;
+
+	rc = qpnp_check_pmic_temp();
+	if (rc) {
+		pr_err("Error checking pmic therm temp\n");
+		return rc;
+	}
+
+	mutex_lock(&iadc->adc->adc_lock);
+	result->gain_raw = iadc->adc->calib.gain_raw;
+	result->ideal_gain_nv = QPNP_ADC_GAIN_NV;
+	result->gain_uv = iadc->adc->calib.gain_uv;
+	result->offset_raw = iadc->adc->calib.offset_raw;
+	result->ideal_offset_uv =
+				QPNP_OFFSET_CALIBRATION_SHORT_CADC_LEADS_IDEAL;
+	result->offset_uv = iadc->adc->calib.offset_uv;
+	mutex_unlock(&iadc->adc->adc_lock);
+
+	return 0;
 }
-EXPORT_SYMBOL(qpnp_iadc_get_offset);
+EXPORT_SYMBOL(qpnp_iadc_get_gain_and_offset);
 
 static ssize_t qpnp_iadc_show(struct device *dev,
 			struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	int32_t result;
+	struct qpnp_iadc_result result;
 	int rc = -1;
 
 	rc = qpnp_iadc_read(attr->index, &result);
@@ -478,7 +654,7 @@
 		return 0;
 
 	return snprintf(buf, QPNP_ADC_HWMON_NAME_LENGTH,
-					"Result:%d\n", result);
+					"Result:%d\n", result.result_ua);
 }
 
 static struct sensor_device_attribute qpnp_adc_attr =
@@ -592,10 +768,28 @@
 
 	rc = qpnp_iadc_configure_interrupt();
 	if (rc) {
-		dev_err(&spmi->dev, "failed to configure interrupt");
+		dev_err(&spmi->dev, "failed to configure interrupt\n");
 		return rc;
 	}
 
+	rc = qpnp_iadc_version_check();
+	if (rc) {
+		dev_err(&spmi->dev, "IADC version not supported\n");
+		return rc;
+	}
+
+	rc = qpnp_iadc_calibrate_for_trim();
+	if (rc) {
+		dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
+		return rc;
+	}
+	iadc->iadc_init_calib = true;
+	INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
+	schedule_delayed_work(&iadc->iadc_work,
+			round_jiffies_relative(msecs_to_jiffies
+					(QPNP_IADC_CALIB_SECONDS)));
+	iadc->iadc_initialized = true;
+
 	return 0;
 }
 
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 13493b8..696c9f9 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -1,5 +1,5 @@
 
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -68,8 +68,6 @@
 #define WLED_SYNC_VAL			0x07
 #define WLED_SYNC_RESET_VAL		0x00
 
-#define WLED_TRIGGER_DEFAULT		"none"
-#define WLED_FLAGS_DEFAULT		0x00
 #define WLED_DEFAULT_STRINGS		0x01
 #define WLED_DEFAULT_OVP_VAL		0x02
 #define WLED_BOOST_LIM_DEFAULT		0x03
@@ -77,6 +75,8 @@
 #define WLED_CTRL_DLY_DEFAULT		0x00
 #define WLED_SWITCH_FREQ_DEFAULT	0x02
 
+#define LED_TRIGGER_DEFAULT		"none"
+
 /**
  * enum qpnp_leds - QPNP supported led ids
  * @QPNP_ID_WLED - White led backlight
@@ -119,9 +119,9 @@
 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
 	/* LED1 */
 	0x60, 0x61, 0x62, 0x63, 0x66,
-	/* LED1 */
+	/* LED2 */
 	0x70, 0x71, 0x72, 0x73, 0x76,
-	/* LED1 */
+	/* LED3 */
 	0x80, 0x81, 0x82, 0x83, 0x86,
 };
 
@@ -155,6 +155,7 @@
  * @base_reg - base register given in device tree
  * @lock - to protect the transactions
  * @reg - cached value of led register
+ * @num_leds - number of leds in the module
  * @max_current - maximum current supported by LED
  * @default_on - true: default state max, false, default state 0
  */
@@ -164,6 +165,7 @@
 	int			id;
 	u16			base;
 	u8			reg;
+	u8			num_leds;
 	spinlock_t		lock;
 	struct wled_config_data *wled_cfg;
 	int			max_current;
@@ -194,6 +196,22 @@
 	return rc;
 }
 
+static void qpnp_dump_regs(struct qpnp_led_data *led, u8 regs[], u8 array_size)
+{
+	int i;
+	u8 val;
+
+	pr_debug("===== %s LED register dump start =====\n", led->cdev.name);
+	for (i = 0; i < array_size; i++) {
+		spmi_ext_register_readl(led->spmi_dev->ctrl,
+					led->spmi_dev->sid,
+					led->base + regs[i],
+					&val, sizeof(val));
+		pr_debug("0x%x = 0x%x\n", led->base + regs[i], val);
+	}
+	pr_debug("===== %s LED register dump end =====\n", led->cdev.name);
+}
+
 static int qpnp_wled_set(struct qpnp_led_data *led)
 {
 	int rc, duty;
@@ -271,22 +289,6 @@
 	return 0;
 }
 
-static void qpnp_wled_dump_regs(struct qpnp_led_data *led)
-{
-	int i;
-	u8 val;
-
-	pr_debug("===== WLED register dump start =====\n");
-	for (i = 0; i < ARRAY_SIZE(wled_debug_regs); i++) {
-		spmi_ext_register_readl(led->spmi_dev->ctrl,
-					led->spmi_dev->sid,
-					led->base + wled_debug_regs[i],
-					&val, sizeof(val));
-		pr_debug("0x%x = 0x%x\n", led->base + wled_debug_regs[i], val);
-	}
-	pr_debug("===== WLED register dump end =====\n");
-}
-
 static void qpnp_led_set(struct led_classdev *led_cdev,
 				enum led_brightness value)
 {
@@ -294,9 +296,8 @@
 	struct qpnp_led_data *led;
 
 	led = container_of(led_cdev, struct qpnp_led_data, cdev);
-
 	if (value < LED_OFF || value > led->cdev.max_brightness) {
-		dev_err(led->cdev.dev, "Invalid brightness value\n");
+		dev_err(&led->spmi_dev->dev, "Invalid brightness value\n");
 		return;
 	}
 
@@ -307,11 +308,11 @@
 	case QPNP_ID_WLED:
 		rc = qpnp_wled_set(led);
 		if (rc < 0)
-			dev_err(led->cdev.dev,
+			dev_err(&led->spmi_dev->dev,
 				"WLED set brightness failed (%d)\n", rc);
 		break;
 	default:
-		dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		break;
 	}
 	spin_unlock(&led->lock);
@@ -324,7 +325,7 @@
 		led->cdev.max_brightness = WLED_MAX_LEVEL;
 		break;
 	default:
-		dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		return -EINVAL;
 	}
 
@@ -465,7 +466,7 @@
 	}
 
 	/* dump wled registers */
-	qpnp_wled_dump_regs(led);
+	qpnp_dump_regs(led, wled_debug_regs, ARRAY_SIZE(wled_debug_regs));
 
 	return 0;
 }
@@ -478,17 +479,43 @@
 	case QPNP_ID_WLED:
 		rc = qpnp_wled_init(led);
 		if (rc)
-			dev_err(led->cdev.dev,
+			dev_err(&led->spmi_dev->dev,
 				"WLED initialize failed(%d)\n", rc);
 		break;
 	default:
-		dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		rc = -EINVAL;
 	}
 
 	return rc;
 }
 
+static int __devinit qpnp_get_common_configs(struct qpnp_led_data *led,
+				struct device_node *node)
+{
+	int rc;
+	const char *temp_string;
+
+	led->cdev.default_trigger = LED_TRIGGER_DEFAULT;
+	rc = of_property_read_string(node, "linux,default-trigger",
+		&temp_string);
+	if (!rc)
+		led->cdev.default_trigger = temp_string;
+	else if (rc != -EINVAL)
+		return rc;
+
+	led->default_on = false;
+	rc = of_property_read_string(node, "qcom,default-state",
+		&temp_string);
+	if (!rc) {
+		if (strncmp(temp_string, "on", sizeof("on")) == 0)
+			led->default_on = true;
+	} else if (rc != -EINVAL)
+		return rc;
+
+	return 0;
+}
+
 /*
  * Handlers for alternative sources of platform_data
  */
@@ -497,9 +524,6 @@
 {
 	u32 val;
 	int rc;
-	const char *temp_string;
-
-	led->id = QPNP_ID_WLED;
 
 	led->wled_cfg = devm_kzalloc(&led->spmi_dev->dev,
 				sizeof(struct wled_config_data), GFP_KERNEL);
@@ -508,31 +532,6 @@
 		return -ENOMEM;
 	}
 
-	led->cdev.default_trigger = WLED_TRIGGER_DEFAULT;
-	rc = of_property_read_string(node, "linux,default-trigger",
-		&temp_string);
-	if (!rc)
-		led->cdev.default_trigger = temp_string;
-	else if (rc != -EINVAL)
-		return rc;
-
-
-	led->cdev.flags = WLED_FLAGS_DEFAULT;
-	rc = of_property_read_u32(node, "qcom,flags", &val);
-	if (!rc)
-		led->cdev.flags = (int) val;
-	else if (rc != -EINVAL)
-		return rc;
-
-	led->default_on = true;
-	rc = of_property_read_string(node, "qcom,default-state",
-		&temp_string);
-	if (!rc) {
-		if (!strncmp(temp_string, "off", sizeof("off")))
-			led->default_on = false;
-	} else if (rc != -EINVAL)
-		return rc;
-
 	led->wled_cfg->num_strings = WLED_DEFAULT_STRINGS;
 	rc = of_property_read_u32(node, "qcom,num-strings", &val);
 	if (!rc)
@@ -591,105 +590,135 @@
 {
 	struct qpnp_led_data *led;
 	struct resource *led_resource;
-	struct device_node *node;
-	int rc;
+	struct device_node *node, *temp;
+	int rc, i, num_leds = 0;
 	const char *led_label;
 
-	led = devm_kzalloc(&spmi->dev, (sizeof(struct qpnp_led_data)),
-		GFP_KERNEL);
+	node = spmi->dev.of_node;
+	if (node == NULL)
+		return -ENODEV;
+
+	temp = NULL;
+	while ((temp = of_get_next_child(node, temp)))
+		num_leds++;
+
+	led = devm_kzalloc(&spmi->dev,
+		(sizeof(struct qpnp_led_data) * num_leds), GFP_KERNEL);
 	if (!led) {
 		dev_err(&spmi->dev, "Unable to allocate memory\n");
 		return -ENOMEM;
 	}
 
-	led->spmi_dev = spmi;
+	led->num_leds = num_leds;
+	num_leds = 0;
 
-	led_resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
-	if (!led_resource) {
-		dev_err(&spmi->dev, "Unable to get LED base address\n");
-		return -ENXIO;
-	}
-	led->base = led_resource->start;
+	for_each_child_of_node(node, temp) {
+		led->spmi_dev = spmi;
 
-	dev_set_drvdata(&spmi->dev, led);
+		led_resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+		if (!led_resource) {
+			dev_err(&spmi->dev, "Unable to get LED base address\n");
+			return -ENXIO;
+		}
+		led->base = led_resource->start;
 
-	node = led->spmi_dev->dev.of_node;
-	if (node == NULL)
-		return -ENODEV;
+		dev_set_drvdata(&spmi->dev, led);
 
-	rc = of_property_read_string(node, "qcom,label", &led_label);
-	if (rc < 0) {
-		dev_err(&led->spmi_dev->dev,
-			"Failure reading label, rc = %d\n", rc);
-		return rc;
-	}
 
-	rc = of_property_read_string(node, "qcom,name", &led->cdev.name);
-	if (rc < 0) {
-		dev_err(&led->spmi_dev->dev,
-			"Failure reading led name, rc = %d\n", rc);
-		return rc;
-	}
-
-	rc = of_property_read_u32(node, "qcom,max-current", &led->max_current);
-	if (rc < 0) {
-		dev_err(&led->spmi_dev->dev,
-			"Failure reading max_current, rc =  %d\n", rc);
-		return rc;
-	}
-
-	led->cdev.brightness_set    = qpnp_led_set;
-	led->cdev.brightness_get    = qpnp_led_get;
-	led->cdev.brightness	= LED_OFF;
-
-	if (strncmp(led_label, "wled", sizeof("wled")) == 0) {
-		rc = qpnp_get_config_wled(led, node);
+		rc = of_property_read_string(temp, "label", &led_label);
 		if (rc < 0) {
 			dev_err(&led->spmi_dev->dev,
-				"Unable to read wled config data\n");
+				"Failure reading label, rc = %d\n", rc);
 			return rc;
 		}
-	} else {
-		dev_err(&led->spmi_dev->dev, "No LED matching label\n");
-		return -EINVAL;
+
+		rc = of_property_read_string(temp, "linux,name",
+			&led->cdev.name);
+		if (rc < 0) {
+			dev_err(&led->spmi_dev->dev,
+				"Failure reading led name, rc = %d\n", rc);
+			return rc;
+		}
+
+		rc = of_property_read_u32(temp, "qcom,max-current",
+			&led->max_current);
+		if (rc < 0) {
+			dev_err(&led->spmi_dev->dev,
+				"Failure reading max_current, rc =  %d\n", rc);
+			return rc;
+		}
+
+		rc = of_property_read_u32(temp, "qcom,id", &led->id);
+		if (rc < 0) {
+			dev_err(&led->spmi_dev->dev,
+				"Failure reading led id, rc =  %d\n", rc);
+			return rc;
+		}
+
+		rc = qpnp_get_common_configs(led, temp);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Failure reading common led configuration," \
+				" rc = %d\n", rc);
+			return rc;
+		}
+
+		led->cdev.brightness_set    = qpnp_led_set;
+		led->cdev.brightness_get    = qpnp_led_get;
+
+		if (strncmp(led_label, "wled", sizeof("wled")) == 0) {
+			rc = qpnp_get_config_wled(led, temp);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev,
+					"Unable to read wled config data\n");
+				return rc;
+			}
+		} else {
+			dev_err(&led->spmi_dev->dev, "No LED matching label\n");
+			return -EINVAL;
+		}
+
+		spin_lock_init(&led->lock);
+
+		rc =  qpnp_led_initialize(led);
+		if (rc < 0)
+			goto fail_id_check;
+
+		rc = qpnp_led_set_max_brightness(led);
+		if (rc < 0)
+			goto fail_id_check;
+
+		rc = led_classdev_register(&spmi->dev, &led->cdev);
+		if (rc) {
+			dev_err(&spmi->dev, "unable to register led %d,rc=%d\n",
+						 led->id, rc);
+			goto fail_id_check;
+		}
+		/* configure default state */
+		if (led->default_on)
+			led->cdev.brightness = led->cdev.max_brightness;
+		else
+			led->cdev.brightness = LED_OFF;
+
+		qpnp_led_set(&led->cdev, led->cdev.brightness);
+		led++;
+		num_leds++;
 	}
-
-	spin_lock_init(&led->lock);
-
-	rc =  qpnp_led_initialize(led);
-	if (rc < 0)
-		goto fail_id_check;
-
-	rc = qpnp_led_set_max_brightness(led);
-	if (rc < 0)
-		goto fail_id_check;
-
-
-	rc = led_classdev_register(&spmi->dev, &led->cdev);
-	if (rc) {
-		dev_err(&spmi->dev, "unable to register led %d,rc=%d\n",
-					 led->id, rc);
-		goto fail_id_check;
-	}
-
-	/* configure default state */
-	if (led->default_on)
-		led->cdev.brightness = led->cdev.max_brightness;
-
-	qpnp_led_set(&led->cdev, led->cdev.brightness);
-
 	return 0;
 
 fail_id_check:
-	led_classdev_unregister(&led->cdev);
+	for (i = 0; i < num_leds; i++)
+		led_classdev_unregister(&led[i].cdev);
 	return rc;
 }
 
 static int __devexit qpnp_leds_remove(struct spmi_device *spmi)
 {
 	struct qpnp_led_data *led  = dev_get_drvdata(&spmi->dev);
+	int i;
 
-	led_classdev_unregister(&led->cdev);
+	for (i = 0; i < led->num_leds; i++)
+		led_classdev_unregister(&led[i].cdev);
 
 	return 0;
 }
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index d9f62ad..cbd3b38 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -98,6 +98,18 @@
 	return index;
 }
 
+static inline int dvb_dmxdev_events_is_full(struct dmxdev_events_queue *events)
+{
+	int new_write_index;
+
+	new_write_index = dvb_dmxdev_advance_event_idx(events->write_index);
+	if (new_write_index == events->read_index)
+		return 1;
+
+	return 0;
+
+}
+
 static inline void dvb_dmxdev_flush_events(struct dmxdev_events_queue *events)
 {
 	events->read_index = 0;
@@ -788,6 +800,13 @@
 		spin_lock_irq(&dmxdev->lock);
 		dvb_dmxdev_update_events(&dmxdev->dvr_output_events, res);
 		spin_unlock_irq(&dmxdev->lock);
+
+		/*
+		 * in PULL mode, we might be stalling on
+		 * event queue, so need to wake-up waiters
+		 */
+		if (dmxdev->playback_mode == DMX_PB_MODE_PULL)
+			wake_up_all(&dmxdev->dvr_buffer.queue);
 	} else if (res == -EOVERFLOW) {
 		/*
 		 * When buffer overflowed, demux-dev flushed the
@@ -1037,6 +1056,13 @@
 
 	spin_unlock_irq(&dmxdev->lock);
 
+	/*
+	 * in PULL mode, we might be stalling on
+	 * event queue, so need to wake-up waiters
+	 */
+	if (dmxdev->playback_mode == DMX_PB_MODE_PULL)
+		wake_up_all(&dmxdev->dvr_buffer.queue);
+
 	return res;
 }
 
@@ -1303,13 +1329,17 @@
 {
 	struct dmxdev_filter *dmxdevfilter = filter->priv;
 	struct dvb_ringbuffer *src;
+	struct dmxdev_events_queue *events;
 	int ret;
 
 	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
-		|| dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
+		|| dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
 		src = &dmxdevfilter->buffer;
-	else
+		events = &dmxdevfilter->events;
+	} else {
 		src = &dmxdevfilter->dev->dvr_buffer;
+		events = &dmxdevfilter->dev->dvr_output_events;
+	}
 
 	do {
 		ret = 0;
@@ -1330,7 +1360,8 @@
 			return ret;
 		}
 
-		if (required_space <= dvb_ringbuffer_free(src)) {
+		if ((required_space <= dvb_ringbuffer_free(src)) &&
+			(!dvb_dmxdev_events_is_full(events))) {
 			spin_unlock(&dmxdevfilter->dev->lock);
 			return 0;
 		}
@@ -1339,7 +1370,8 @@
 
 		ret = wait_event_interruptible(src->queue,
 				(!src->data) ||
-				(dvb_ringbuffer_free(src) >= required_space) ||
+				((dvb_ringbuffer_free(src) >= required_space) &&
+				 (!dvb_dmxdev_events_is_full(events))) ||
 				(src->error != 0) ||
 				(dmxdevfilter->state != DMXDEV_STATE_GO) ||
 				dmxdevfilter->dev->dvr_in_exit);
@@ -1355,6 +1387,7 @@
 {
 	struct dmxdev_filter *dmxdevfilter = filter->priv;
 	struct dvb_ringbuffer *src = &dmxdevfilter->buffer;
+	struct dmxdev_events_queue *events = &dmxdevfilter->events;
 	int ret;
 
 	do {
@@ -1376,7 +1409,8 @@
 			return ret;
 		}
 
-		if (required_space <= dvb_ringbuffer_free(src)) {
+		if ((required_space <= dvb_ringbuffer_free(src)) &&
+			(!dvb_dmxdev_events_is_full(events))) {
 			spin_unlock(&dmxdevfilter->dev->lock);
 			return 0;
 		}
@@ -1385,7 +1419,8 @@
 
 		ret = wait_event_interruptible(src->queue,
 				(!src->data) ||
-				(dvb_ringbuffer_free(src) >= required_space) ||
+				((dvb_ringbuffer_free(src) >= required_space) &&
+				 (!dvb_dmxdev_events_is_full(events))) ||
 				(src->error != 0) ||
 				(dmxdevfilter->state != DMXDEV_STATE_GO) ||
 				dmxdevfilter->dev->dvr_in_exit);
@@ -1537,6 +1572,13 @@
 
 	spin_unlock_irq(&dmxdevfilter->dev->lock);
 
+	/*
+	 * in PULL mode, we might be stalling on
+	 * event queue, so need to wake-up waiters
+	 */
+	if (dmxdevfilter->dev->playback_mode == DMX_PB_MODE_PULL)
+		wake_up_all(&dmxdevfilter->buffer.queue);
+
 	return res;
 
 }
@@ -2608,6 +2650,13 @@
 		spin_lock_irq(&dmxdevfilter->dev->lock);
 		dvb_dmxdev_update_events(&dmxdevfilter->events, ret);
 		spin_unlock_irq(&dmxdevfilter->dev->lock);
+
+		/*
+		 * in PULL mode, we might be stalling on
+		 * event queue, so need to wake-up waiters
+		 */
+		if (dmxdevfilter->dev->playback_mode == DMX_PB_MODE_PULL)
+			wake_up_all(&dmxdevfilter->buffer.queue);
 	} else if (ret == -EOVERFLOW) {
 		/*
 		 * When buffer overflowed, demux-dev flushed the
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
index 627c5a2..2e783f6 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
@@ -30,15 +30,16 @@
 #define DMX_TSIF_CHUNKS_IN_BUF			16
 #define DMX_TSIF_TIME_LIMIT			10000
 
-/* TSIF_DRIVER_MODE: 3 means manual control from debugfs. use 1 normally. */
-#define DMX_TSIF_DRIVER_MODE_DEF		1
-
+/* TSIF_DRIVER_MODE: 3 means manual control from debugfs. use 2 normally. */
+#define DMX_TSIF_DRIVER_MODE_DEF		2
 
 /* module parameters for load time configuration: */
 static int threshold = DMX_TSIF_PACKETS_IN_CHUNK_DEF;
-static int mode = DMX_TSIF_DRIVER_MODE_DEF;
+static int tsif_mode = DMX_TSIF_DRIVER_MODE_DEF;
+static int clock_inv;
 module_param(threshold, int, S_IRUGO);
-module_param(mode, int, S_IRUGO);
+module_param(tsif_mode, int, S_IRUGO);
+module_param(clock_inv, int, S_IRUGO);
 
 /*
  * Work scheduled each time TSIF notifies dmx
@@ -273,7 +274,6 @@
 		tsif_driver = &(mpq_dmx_tsif_info.tsif[tsif].tsif_driver);
 
 		/* Attach to TSIF driver */
-
 		tsif_driver->tsif_handler =
 			tsif_attach(tsif, mpq_tsif_callback, (void *)tsif);
 		if (IS_ERR_OR_NULL(tsif_driver->tsif_handler)) {
@@ -284,12 +284,19 @@
 			return -ENODEV;
 		}
 
+		ret = tsif_set_clk_inverse(tsif_driver->tsif_handler,
+					clock_inv);
+		if (ret < 0) {
+			MPQ_DVB_ERR_PRINT(
+				"%s: tsif_set_clk_inverse (%d) failed\n",
+				__func__, clock_inv);
+		}
+
 		/* Set TSIF driver mode */
-		ret = tsif_set_mode(tsif_driver->tsif_handler,
-					mode);
+		ret = tsif_set_mode(tsif_driver->tsif_handler, tsif_mode);
 		if (ret < 0) {
 			MPQ_DVB_ERR_PRINT("%s: tsif_set_mode (%d) failed\n",
-				__func__, mode);
+				__func__, tsif_mode);
 		}
 
 		/* Set TSIF buffer configuration */
@@ -304,18 +311,6 @@
 			MPQ_DVB_ERR_PRINT("Using default TSIF driver values\n");
 		}
 
-
-		/* Set TSIF driver time limit */
-		/* TODO: needed?? */
-/*		ret = tsif_set_time_limit(tsif_driver->tsif_handler,
-						DMX_TSIF_TIME_LIMIT);
-		if (ret < 0) {
-			MPQ_DVB_ERR_PRINT(
-				"%s: tsif_set_time_limit (%d) failed\n",
-				__func__, DMX_TSIF_TIME_LIMIT);
-		}
-*/
-
 		/* Start TSIF driver */
 		ret = tsif_start(tsif_driver->tsif_handler);
 		if (ret < 0) {
@@ -705,11 +700,11 @@
 			__func__, DMX_TSIF_PACKETS_IN_CHUNK_DEF);
 		threshold = DMX_TSIF_PACKETS_IN_CHUNK_DEF;
 	}
-	if ((mode < 1) || (mode > 3)) {
+	if ((tsif_mode < 1) || (tsif_mode > 3)) {
 		MPQ_DVB_ERR_PRINT(
 			"%s: invalid mode parameter, using %d instead\n",
 			__func__, DMX_TSIF_DRIVER_MODE_DEF);
-		mode = DMX_TSIF_DRIVER_MODE_DEF;
+		tsif_mode = DMX_TSIF_DRIVER_MODE_DEF;
 	}
 
 	for (i = 0; i < TSIF_COUNT; i++) {
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
index 68af7e1..191a0c4 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
@@ -66,10 +66,10 @@
 #define TSPP_CHANNEL_TIMEOUT			16
 
 /* module parameters for load time configuration */
-static int tsif0_mode = TSPP_TSIF_MODE_2;
-static int tsif1_mode = TSPP_TSIF_MODE_2;
-module_param(tsif0_mode, int, S_IRUGO);
-module_param(tsif1_mode, int, S_IRUGO);
+static int clock_inv;
+static int tsif_mode = 2;
+module_param(tsif_mode, int, S_IRUGO);
+module_param(clock_inv, int, S_IRUGO);
 
 /*
  * Work scheduled each time TSPP notifies dmx
@@ -279,20 +279,30 @@
 	int channel_id;
 	int *channel_ref_count;
 
-	tspp_source.clk_inverse = 0;
+	tspp_source.clk_inverse = clock_inv;
 	tspp_source.data_inverse = 0;
 	tspp_source.sync_inverse = 0;
 	tspp_source.enable_inverse = 0;
 
+	switch (tsif_mode) {
+	case 1:
+		tspp_source.mode = TSPP_TSIF_MODE_1;
+		break;
+	case 2:
+		tspp_source.mode = TSPP_TSIF_MODE_2;
+		break;
+	default:
+		tspp_source.mode = TSPP_TSIF_MODE_LOOPBACK;
+		break;
+	}
+
 	/* determine the TSIF we are reading from */
 	if (mpq_demux->source == DMX_SOURCE_FRONT0) {
 		tsif = 0;
 		tspp_source.source = TSPP_SOURCE_TSIF0;
-		tspp_source.mode = (enum tspp_tsif_mode)tsif0_mode;
 	} else if (mpq_demux->source == DMX_SOURCE_FRONT1) {
 		tsif = 1;
 		tspp_source.source = TSPP_SOURCE_TSIF1;
-		tspp_source.mode = (enum tspp_tsif_mode)tsif1_mode;
 	} else {
 		/* invalid source */
 		MPQ_DVB_ERR_PRINT(
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 7d44fea..eb0cd8a 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -671,7 +671,6 @@
 	if (rc)
 		dprintk(VIDC_WARN,
 			"Failed in %s for release output buffers\n", __func__);
-	rc = msm_vidc_close(vidc_inst);
 	list_for_each_safe(ptr, next, &v4l2_inst->registered_bufs) {
 		bi = list_entry(ptr, struct buffer_info, list);
 		if (bi->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
@@ -686,6 +685,7 @@
 		}
 	}
 	msm_smem_delete_client(v4l2_inst->mem_client);
+	rc = msm_vidc_close(vidc_inst);
 	kfree(v4l2_inst);
 	return rc;
 }
@@ -958,17 +958,35 @@
 		rc = msm_v4l2_release_output_buffers(v4l2_inst);
 	if (rc)
 		dprintk(VIDC_WARN,
-			"Failed in %s for release output buffers\n", __func__);
+			"Failed to release dec output buffers: %d\n", rc);
 	return msm_vidc_decoder_cmd((void *)vidc_inst, dec);
 }
 
 static int msm_v4l2_encoder_cmd(struct file *file, void *fh,
 				struct v4l2_encoder_cmd *enc)
 {
+	struct msm_v4l2_vid_inst *v4l2_inst;
 	struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
+	int rc = 0;
+	v4l2_inst = get_v4l2_inst(file, NULL);
+	if (enc->cmd == V4L2_ENC_CMD_STOP)
+		rc = msm_v4l2_release_output_buffers(v4l2_inst);
+	if (rc)
+		dprintk(VIDC_WARN,
+			"Failed to release enc output buffers: %d\n", rc);
 	return msm_vidc_encoder_cmd((void *)vidc_inst, enc);
 }
-
+static int msm_v4l2_s_parm(struct file *file, void *fh,
+			struct v4l2_streamparm *a)
+{
+	struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
+	return msm_vidc_s_parm((void *)vidc_inst, a);
+}
+static int msm_v4l2_g_parm(struct file *file, void *fh,
+		struct v4l2_streamparm *a)
+{
+	return 0;
+}
 static const struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
 	.vidioc_querycap = msm_v4l2_querycap,
 	.vidioc_enum_fmt_vid_cap_mplane = msm_v4l2_enum_fmt,
@@ -989,6 +1007,8 @@
 	.vidioc_unsubscribe_event = msm_v4l2_unsubscribe_event,
 	.vidioc_decoder_cmd = msm_v4l2_decoder_cmd,
 	.vidioc_encoder_cmd = msm_v4l2_encoder_cmd,
+	.vidioc_s_parm = msm_v4l2_s_parm,
+	.vidioc_g_parm = msm_v4l2_g_parm
 };
 
 static const struct v4l2_ioctl_ops msm_v4l2_enc_ioctl_ops = {
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 058c835..3afc496 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -544,7 +544,42 @@
 	}
 	return rc;
 }
-
+int msm_vdec_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
+{
+	u32 us_per_frame = 0;
+	int rc = 0;
+	if (a->parm.output.timeperframe.denominator) {
+		switch (a->type) {
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+			us_per_frame = a->parm.output.timeperframe.numerator/
+				a->parm.output.timeperframe.denominator;
+			break;
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+			us_per_frame = a->parm.capture.timeperframe.numerator/
+				a->parm.capture.timeperframe.denominator;
+			break;
+		default:
+			dprintk(VIDC_ERR,
+				"Scale clocks : Unknown buffer type\n");
+			break;
+		}
+	}
+	if (!us_per_frame) {
+		dprintk(VIDC_ERR,
+				"Failed to scale clocks : time between frames is 0\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+	inst->prop.fps = (u8) (USEC_PER_SEC / us_per_frame);
+	if (inst->prop.fps) {
+		if (msm_comm_scale_clocks(inst->core, inst->session_type)) {
+			dprintk(VIDC_WARN,
+					"Failed to scale clocks\n");
+		}
+	}
+exit:
+	return rc;
+}
 int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 {
 	const struct msm_vidc_format *fmt = NULL;
diff --git a/drivers/media/video/msm_vidc/msm_vdec.h b/drivers/media/video/msm_vidc/msm_vdec.h
index b8326d8..419c8c1 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.h
+++ b/drivers/media/video/msm_vidc/msm_vdec.h
@@ -32,6 +32,7 @@
 int msm_vdec_streamon(struct msm_vidc_inst *inst, enum v4l2_buf_type i);
 int msm_vdec_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type i);
 int msm_vdec_cmd(struct msm_vidc_inst *inst, struct v4l2_decoder_cmd *dec);
+int msm_vdec_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a);
 struct vb2_ops *msm_vdec_get_vb2q_ops(void);
 
 #endif
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 0ea2a60..3f892b1 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -1274,6 +1274,14 @@
 			v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 			return rc;
 		}
+		rc = msm_comm_release_scratch_buffers(inst);
+		if (rc)
+			dprintk(VIDC_ERR, "Failed to release scratch buf:%d\n",
+				rc);
+		rc = msm_comm_release_persist_buffers(inst);
+		if (rc)
+			dprintk(VIDC_ERR, "Failed to release persist buf:%d\n",
+				rc);
 		rc = msm_comm_try_state(inst, MSM_VIDC_CLOSE_DONE);
 		break;
 	}
@@ -1331,6 +1339,55 @@
 	return rc;
 }
 
+int msm_venc_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
+{
+	u32 property_id = 0, us_per_frame = 0;
+	void *pdata;
+	int rc = 0;
+	struct hal_frame_rate frame_rate;
+	property_id = HAL_CONFIG_FRAME_RATE;
+	if (a->parm.output.timeperframe.denominator) {
+		switch (a->type) {
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+			us_per_frame = a->parm.output.timeperframe.numerator/
+				a->parm.output.timeperframe.denominator;
+			break;
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+			us_per_frame = a->parm.capture.timeperframe.numerator/
+				a->parm.capture.timeperframe.denominator;
+			break;
+		default:
+			dprintk(VIDC_ERR,
+				"Scale clocks : Unknown buffer type\n");
+			break;
+		}
+	}
+
+	if (!us_per_frame) {
+		dprintk(VIDC_ERR,
+			"Failed to scale clocks : time between frames is 0\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+	inst->prop.fps = (u8) (USEC_PER_SEC / us_per_frame);
+	if (inst->prop.fps) {
+		frame_rate.frame_rate = inst->prop.fps * (0x1<<16);
+		frame_rate.buffer_type = HAL_BUFFER_OUTPUT;
+		pdata = &frame_rate;
+		rc = vidc_hal_session_set_property((void *)inst->session,
+				property_id, pdata);
+		if (rc) {
+			dprintk(VIDC_WARN,
+				"Failed to set frame rate %d\n", rc);
+		}
+		if (msm_comm_scale_clocks(inst->core, inst->session_type)) {
+			dprintk(VIDC_WARN,
+				"Failed to scale clocks\n");
+		}
+	}
+exit:
+	return rc;
+}
 int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 {
 	const struct msm_vidc_format *fmt = NULL;
@@ -1507,6 +1564,43 @@
 	return rc;
 }
 
+int msm_venc_release_buf(struct msm_vidc_inst *inst,
+					struct v4l2_buffer *b)
+{
+	int rc = 0;
+	int i;
+	struct vidc_buffer_addr_info buffer_info;
+
+	switch (b->type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		break;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		for (i = 0; i < b->length; i++) {
+			dprintk(VIDC_DBG,
+				"Release device_addr = %ld, size = %d, %d\n",
+				b->m.planes[i].m.userptr,
+				b->m.planes[i].length, inst->state);
+			buffer_info.buffer_size = b->m.planes[i].length;
+			buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
+			buffer_info.num_buffers = 1;
+			buffer_info.align_device_addr =
+				 b->m.planes[i].m.userptr;
+			buffer_info.extradata_size = 0;
+			buffer_info.extradata_addr = 0;
+			rc = vidc_hal_session_release_buffers(
+				(void *)inst->session, &buffer_info);
+			if (rc)
+				dprintk(VIDC_ERR,
+					"vidc_hal_session_release_buffers failed\n");
+		}
+		break;
+	default:
+		dprintk(VIDC_ERR, "Buffer type not recognized: %d\n", b->type);
+		break;
+	}
+	return rc;
+}
+
 int msm_venc_qbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
 {
 	struct buf_queue *q = NULL;
diff --git a/drivers/media/video/msm_vidc/msm_venc.h b/drivers/media/video/msm_vidc/msm_venc.h
index 83610b3..ad63e7d 100644
--- a/drivers/media/video/msm_vidc/msm_venc.h
+++ b/drivers/media/video/msm_vidc/msm_venc.h
@@ -26,11 +26,13 @@
 int msm_venc_g_ctrl(void *instance, struct v4l2_control *a);
 int msm_venc_reqbufs(void *instance, struct v4l2_requestbuffers *b);
 int msm_venc_prepare_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
+int msm_venc_release_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
 int msm_venc_qbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
 int msm_venc_dqbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
 int msm_venc_streamon(struct msm_vidc_inst *inst, enum v4l2_buf_type i);
 int msm_venc_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type i);
 int msm_venc_cmd(struct msm_vidc_inst *inst, struct v4l2_encoder_cmd *enc);
+int msm_venc_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a);
 struct vb2_ops *msm_venc_get_vb2q_ops(void);
 
 #endif
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 7ceb017..1d0124f 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -109,6 +109,19 @@
 		return msm_venc_querycap(instance, cap);
 	return -EINVAL;
 }
+int msm_vidc_s_parm(void *instance,
+		struct v4l2_streamparm *a)
+{
+	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !a)
+		return -EINVAL;
+	if (inst->session_type == MSM_VIDC_DECODER)
+		return msm_vdec_s_parm(instance, a);
+	else if (inst->session_type == MSM_VIDC_ENCODER)
+		return msm_venc_s_parm(instance, a);
+	return -EINVAL;
+}
 int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f)
 {
 	struct msm_vidc_inst *inst = instance;
@@ -211,6 +224,8 @@
 
 	if (inst->session_type == MSM_VIDC_DECODER)
 		return msm_vdec_release_buf(instance, b);
+	if (inst->session_type == MSM_VIDC_ENCODER)
+		return msm_venc_release_buf(instance, b);
 	return -EINVAL;
 }
 
@@ -540,13 +555,13 @@
 			list_del(&inst->list);
 	}
 	mutex_unlock(&core->sync_lock);
+	cleanup_instance(inst);
 	if (inst->state != MSM_VIDC_CORE_INVALID &&
 		core->state != VIDC_CORE_INVALID)
 		rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
 	if (rc)
 		dprintk(VIDC_ERR,
 			"Failed to move video instance to uninit state\n");
-	cleanup_instance(inst);
 	pr_info(VIDC_DBG_TAG "Closed video instance: %p\n", VIDC_INFO, inst);
 	kfree(inst);
 	return 0;
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 54c3d5f..038f03e 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -528,6 +528,7 @@
 		dqevent.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
 		dqevent.id = 0;
 		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+		inst->session = NULL;
 		wake_up(&inst->kernel_event_queue);
 		show_stats(inst);
 	} else {
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 53e965c..7d1fdf0 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -219,6 +219,7 @@
 		dev_err(wcd9xxx->dev, "Failed to read interrupt status: %d\n",
 			ret);
 		dev_err(wcd9xxx->dev, "Disable irq %d\n", wcd9xxx->irq);
+		disable_irq_wake(wcd9xxx->irq);
 		disable_irq_nosync(wcd9xxx->irq);
 		wcd9xxx_unlock_sleep(wcd9xxx);
 		return IRQ_NONE;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 3aa38d2..48516b6 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2639,7 +2639,9 @@
 			mmc_card_is_removable(host))
 		return err;
 
-	mmc_claim_host(host);
+	if (!mmc_try_claim_host(host))
+		return -EBUSY;
+
 	if (card && mmc_card_mmc(card) &&
 			(card->ext_csd.cache_size > 0)) {
 		enable = !!enable;
diff --git a/drivers/net/ethernet/msm/msm_rmnet_smux.c b/drivers/net/ethernet/msm/msm_rmnet_smux.c
index 5f29406..e56a64e 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_smux.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_smux.c
@@ -482,7 +482,7 @@
 		p = netdev_priv(priv);
 		DBG0("[%s] Low WM hit dev:%s\n", __func__, dev->name);
 		spin_lock_irqsave(&p->tx_queue_lock, flags);
-		netif_start_queue(dev);
+		netif_wake_queue(dev);
 		spin_unlock_irqrestore(&p->tx_queue_lock, flags);
 		break;
 
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index d2d0c03..cf34df5 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -986,30 +986,6 @@
 					PM8921_CHG_LED_SRC_CONFIG_MASK, temp);
 }
 
-static void disable_input_voltage_regulation(struct pm8921_chg_chip *chip)
-{
-	u8 temp;
-	int rc;
-
-	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x70);
-	if (rc) {
-		pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
-		return;
-	}
-	rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
-	if (rc) {
-		pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
-		return;
-	}
-	/* set the input voltage disable bit and the write bit */
-	temp |= 0x81;
-	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
-	if (rc) {
-		pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
-		return;
-	}
-}
-
 static void enable_input_voltage_regulation(struct pm8921_chg_chip *chip)
 {
 	u8 temp;
@@ -2594,29 +2570,49 @@
 	return IRQ_HANDLED;
 }
 
-static int param_vin_disable_counter = 5;
-module_param(param_vin_disable_counter, int, 0644);
+enum {
+	PON_TIME_25NS	= 0x04,
+	PON_TIME_50NS	= 0x08,
+	PON_TIME_100NS	= 0x0C,
+};
 
-static void attempt_reverse_boost_fix(struct pm8921_chg_chip *chip,
-							int count, int usb_ma)
+static void set_min_pon_time(struct pm8921_chg_chip *chip, int pon_time_ns)
 {
-	if (usb_ma)
-		__pm8921_charger_vbus_draw(500);
-	pr_debug("count = %d iusb=500mA\n", count);
-	disable_input_voltage_regulation(chip);
-	pr_debug("count = %d disable_input_regulation\n", count);
+	u8 temp;
+	int rc;
 
-	msleep(20);
+	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x40);
+	if (rc) {
+		pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
+		return;
+	}
+	rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
+	if (rc) {
+		pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
+		return;
+	}
+	/* clear the min pon time select bit */
+	temp &= 0xF3;
+	/* set the pon time */
+	temp |= (u8)pon_time_ns;
+	/* write enable bank 4 */
+	temp |= 0x80;
+	rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
+	if (rc) {
+		pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
+		return;
+	}
+}
 
-	pr_debug("count = %d end sleep 20ms chg_gone=%d, usb_valid = %d\n",
-				count,
-				pm_chg_get_rt_status(chip, CHG_GONE_IRQ),
-				is_usb_chg_plugged_in(chip));
-	pr_debug("count = %d restoring input regulation and usb_ma = %d\n",
-		 count, usb_ma);
-	enable_input_voltage_regulation(chip);
-	if (usb_ma)
-		__pm8921_charger_vbus_draw(usb_ma);
+static void attempt_reverse_boost_fix(struct pm8921_chg_chip *chip)
+{
+	pr_debug("Start\n");
+	set_min_pon_time(chip, PON_TIME_100NS);
+	pm_chg_vinmin_set(chip, chip->vin_min + 200);
+	msleep(250);
+	pm_chg_vinmin_set(chip, chip->vin_min);
+	set_min_pon_time(chip, PON_TIME_25NS);
+	pr_debug("End\n");
 }
 
 #define VIN_ACTIVE_BIT BIT(0)
@@ -2647,11 +2643,6 @@
 		pr_debug("USB charger active\n");
 
 		pm_chg_iusbmax_get(chip, &usb_ma);
-		if (usb_ma == 500 && !usb_target_ma) {
-			pr_debug("Stopping Unplug Check Worker USB == 500mA\n");
-			disable_input_voltage_regulation(chip);
-			return;
-		}
 
 		if (usb_ma <= 100) {
 			pr_debug(
@@ -2661,8 +2652,10 @@
 		}
 	} else if (active_path & DC_ACTIVE_BIT) {
 		pr_debug("DC charger active\n");
-		/* Some board designs are not prone to reverse boost on DC
-		 * charging path */
+		/*
+		 * Some board designs are not prone to reverse boost on DC
+		 * charging path
+		 */
 		if (!chip->dc_unplug_check)
 			return;
 	} else {
@@ -2701,27 +2694,17 @@
 
 	ibat = get_prop_batt_current(chip);
 	if (reg_loop & VIN_ACTIVE_BIT) {
-		pr_debug("ibat = %d fsm = %d reg_loop = 0x%x\n",
-				ibat, pm_chg_get_fsm_state(chip), reg_loop);
 		if (ibat > 0) {
-			int count = 0;
-
-			while (count++ < param_vin_disable_counter
-					&& active_chg_plugged_in == 1) {
-				if (active_path & USB_ACTIVE_BIT)
-					attempt_reverse_boost_fix(chip,
-								count, usb_ma);
-				else
-					attempt_reverse_boost_fix(chip,
-								count, 0);
-				/* after reverse boost fix check if the active
-				 * charger was detected as removed */
-				active_chg_plugged_in
-					= is_active_chg_plugged_in(chip,
-						active_path);
-				pr_debug("active_chg_plugged_in = %d\n",
-						active_chg_plugged_in);
-			}
+			pr_debug("revboost ibat = %d fsm = %d loop = 0x%x\n",
+				ibat, pm_chg_get_fsm_state(chip), reg_loop);
+			attempt_reverse_boost_fix(chip);
+			/* after reverse boost fix check if the active
+			 * charger was detected as removed */
+			active_chg_plugged_in
+				= is_active_chg_plugged_in(chip,
+					active_path);
+			pr_debug("revboost post: active_chg_plugged_in = %d\n",
+					active_chg_plugged_in);
 		}
 	}
 
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index ef555f7..bc012ca 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -189,6 +189,7 @@
 	bool				chg_done;
 	bool				usb_present;
 	bool				dc_present;
+	bool				charging_disabled;
 	unsigned int			max_bat_chg_current;
 	unsigned int			safe_voltage_mv;
 	unsigned int			max_voltage_mv;
@@ -202,9 +203,6 @@
 	uint32_t			flags;
 };
 
-static struct qpnp_chg_chip *the_chip;
-static bool charging_disabled;
-
 static struct of_device_id qpnp_charger_match_table[] = {
 	{ .compatible = QPNP_CHARGER_DEV_NAME, },
 	{}
@@ -424,6 +422,20 @@
 	return IRQ_HANDLED;
 }
 
+static int
+qpnp_batt_property_is_writeable(struct power_supply *psy,
+						enum power_supply_property psp)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 static enum power_supply_property pm_power_props_mains[] = {
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_ONLINE,
@@ -462,7 +474,7 @@
 	case POWER_SUPPLY_PROP_PRESENT:
 	case POWER_SUPPLY_PROP_ONLINE:
 		val->intval = 0;
-		if (charging_disabled)
+		if (chip->charging_disabled)
 			return 0;
 
 		val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
@@ -753,7 +765,7 @@
 		val->intval = get_prop_full_design(chip);
 		break;
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
-		val->intval = !charging_disabled;
+		val->intval = !(chip->charging_disabled);
 		break;
 	default:
 		return -EINVAL;
@@ -776,7 +788,7 @@
 			qpnp_chg_charge_en(chip, val->intval);
 		else
 			qpnp_chg_charge_dis(chip, val->intval);
-		charging_disabled = !(val->intval);
+		chip->charging_disabled = !(val->intval);
 		break;
 	default:
 		return -EINVAL;
@@ -786,25 +798,6 @@
 	return 0;
 }
 
-static int
-qpnp_chg_set_disable_status_param(const char *val, struct kernel_param *kp)
-{
-	int ret;
-	struct qpnp_chg_chip *chip = the_chip;
-
-	ret = param_set_int(val, kp);
-	if (ret) {
-		pr_err("error setting value %d\n", ret);
-		return ret;
-	}
-	pr_info("factory set disable param to %d\n", charging_disabled);
-	if (chip)
-		qpnp_chg_charge_dis(chip, charging_disabled);
-	return 0;
-}
-module_param_call(disabled, qpnp_chg_set_disable_status_param, param_get_bool,
-					&charging_disabled, 0644);
-
 #define QPNP_CHG_VINMIN_MIN_MV		3400
 #define QPNP_CHG_VINMIN_HIGH_MIN_MV	5600
 #define QPNP_CHG_VINMIN_HIGH_MIN_VAL	0x2B
@@ -1146,7 +1139,7 @@
 	}
 
 	/* Get the charging-disabled property */
-	charging_disabled = of_property_read_bool(spmi->dev.of_node,
+	chip->charging_disabled = of_property_read_bool(spmi->dev.of_node,
 					"qcom,chg-charging-disabled");
 
 	spmi_for_each_container_dev(spmi_resource, spmi) {
@@ -1259,6 +1252,7 @@
 	chip->batt_psy.num_properties = ARRAY_SIZE(msm_batt_power_props);
 	chip->batt_psy.get_property = qpnp_batt_power_get_property;
 	chip->batt_psy.set_property = qpnp_batt_power_set_property;
+	chip->batt_psy.property_is_writeable = qpnp_batt_property_is_writeable;
 	chip->batt_psy.external_power_changed =
 				qpnp_batt_external_power_changed;
 
@@ -1280,9 +1274,8 @@
 	power_supply_set_present(chip->usb_psy,
 			qpnp_chg_is_usb_chg_plugged_in(chip));
 
-	qpnp_chg_charge_en(chip, 1);
-	the_chip = chip;
-	qpnp_chg_charge_dis(chip, charging_disabled);
+	qpnp_chg_charge_en(chip, !chip->charging_disabled);
+	qpnp_chg_charge_dis(chip, chip->charging_disabled);
 
 	pr_info("Probe success !\n");
 	return 0;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 0fd9ab5..0531f83 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -33,6 +33,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/regulator/consumer.h>
+#include <linux/power_supply.h>
 
 #include <mach/rpm-regulator.h>
 #include <mach/msm_xo.h>
@@ -157,6 +158,11 @@
 	u8			dcd_retries;
 	u32			bus_perf_client;
 	struct msm_bus_scale_pdata	*bus_scale_table;
+	struct power_supply	usb_psy;
+	unsigned int		online;
+	unsigned int		host_mode;
+	unsigned int		current_max;
+	bool			vbus_active;
 };
 
 #define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -1281,6 +1287,10 @@
 			dev_err(mdwc->dev, "Failed to reset bus bw vote\n");
 	}
 
+	if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability)
+		dwc3_hsusb_ldo_enable(0);
+
+	dwc3_hsusb_config_vddcx(0);
 	wake_unlock(&mdwc->wlock);
 	atomic_set(&mdwc->in_lpm, 1);
 
@@ -1315,6 +1325,10 @@
 		dev_err(mdwc->dev, "%s failed to vote for TCXO buffer%d\n",
 						__func__, ret);
 
+	if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability)
+		dwc3_hsusb_ldo_enable(1);
+
+	dwc3_hsusb_config_vddcx(1);
 	clk_prepare_enable(mdwc->ref_clk);
 	usleep_range(1000, 1200);
 
@@ -1373,10 +1387,13 @@
 			mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg,
 							DWC3_EVENT_PHY_RESUME);
 		pm_runtime_put_sync(mdwc->dev);
+		if (mdwc->otg_xceiv && (mdwc->ext_xceiv.otg_capability))
+			mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg,
+							DWC3_EVENT_XCEIV_STATE);
 	}
 }
 
-static bool debug_id, debug_bsv, debug_connect;
+static u32 debug_id, debug_bsv, debug_connect;
 
 static int dwc3_connect_show(struct seq_file *s, void *unused)
 {
@@ -1446,11 +1463,11 @@
 		return;
 
 	if (!debugfs_create_bool("id", S_IRUGO | S_IWUSR, dwc3_debugfs_root,
-				 (u32 *)&debug_id))
+				 &debug_id))
 		goto error;
 
 	if (!debugfs_create_bool("bsv", S_IRUGO | S_IWUSR, dwc3_debugfs_root,
-				 (u32 *)&debug_bsv))
+				 &debug_bsv))
 		goto error;
 
 	if (!debugfs_create_file("connect", S_IRUGO | S_IWUSR,
@@ -1479,6 +1496,90 @@
 	return IRQ_HANDLED;
 }
 
+static int dwc3_msm_power_get_property_usb(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  union power_supply_propval *val)
+{
+	struct dwc3_msm *mdwc = container_of(psy, struct dwc3_msm,
+								usb_psy);
+	switch (psp) {
+	case POWER_SUPPLY_PROP_SCOPE:
+		val->intval = mdwc->host_mode;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		val->intval = mdwc->current_max;
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = mdwc->vbus_active;
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = mdwc->online;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int dwc3_msm_power_set_property_usb(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  const union power_supply_propval *val)
+{
+	static bool init;
+	struct dwc3_msm *mdwc = container_of(psy, struct dwc3_msm,
+								usb_psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_SCOPE:
+		mdwc->host_mode = val->intval;
+		break;
+	/* Process PMIC notification in PRESENT prop */
+	case POWER_SUPPLY_PROP_PRESENT:
+		dev_dbg(mdwc->dev, "%s: notify xceiv event\n", __func__);
+		if (mdwc->otg_xceiv && (mdwc->ext_xceiv.otg_capability ||
+							!init)) {
+			mdwc->ext_xceiv.bsv = val->intval;
+			mdwc->ext_xceiv.id = DWC3_ID_FLOAT;
+			if (atomic_read(&mdwc->in_lpm)) {
+				dev_dbg(mdwc->dev,
+					"%s received in LPM\n", __func__);
+				queue_delayed_work(system_nrt_wq,
+							&mdwc->resume_work, 0);
+			} else {
+				mdwc->ext_xceiv.notify_ext_events(
+							mdwc->otg_xceiv->otg,
+							DWC3_EVENT_XCEIV_STATE);
+			}
+		}
+		if (!init)
+			init = true;
+		mdwc->vbus_active = val->intval;
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		mdwc->online = val->intval;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		mdwc->current_max = val->intval;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	power_supply_changed(&mdwc->usb_psy);
+	return 0;
+}
+
+static char *dwc3_msm_pm_power_supplied_to[] = {
+	"battery",
+};
+
+static enum power_supply_property dwc3_msm_pm_power_props_usb[] = {
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
+	POWER_SUPPLY_PROP_SCOPE,
+};
+
 static int __devinit dwc3_msm_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
@@ -1639,19 +1740,24 @@
 		goto free_hs_ldo_init;
 	}
 
-	/* DWC3 has separate IRQ line for OTG events (ID/BSV etc.) */
-	msm->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
-	if (msm->hs_phy_irq < 0) {
-		dev_dbg(&pdev->dev, "platform_get_irq for hs_phy_irq failed\n");
-		msm->hs_phy_irq = 0;
-	} else {
-		ret = request_irq(msm->hs_phy_irq, msm_dwc3_irq,
-			IRQF_TRIGGER_RISING, "msm_dwc3", msm);
-		if (ret) {
-			dev_err(&pdev->dev, "request irq failed (HSPHY INT)\n");
-			goto disable_hs_ldo;
+	msm->ext_xceiv.otg_capability = of_property_read_bool(node,
+				"qcom,dwc-usb3-msm-otg-capability");
+
+	if (!msm->ext_xceiv.otg_capability) {
+		/* DWC3 has separate IRQ line for OTG events (ID/BSV etc.) */
+		msm->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
+		if (msm->hs_phy_irq < 0) {
+			dev_dbg(&pdev->dev, "pget_irq for hs_phy_irq failed\n");
+			msm->hs_phy_irq = 0;
+		} else {
+			ret = request_irq(msm->hs_phy_irq, msm_dwc3_irq,
+					IRQF_TRIGGER_RISING, "msm_dwc3", msm);
+			if (ret) {
+				dev_err(&pdev->dev, "irqreq HSPHYINT failed\n");
+				goto disable_hs_ldo;
+			}
+			enable_irq_wake(msm->hs_phy_irq);
 		}
-		enable_irq_wake(msm->hs_phy_irq);
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -1742,17 +1848,35 @@
 		goto put_pdev;
 	}
 
+	msm->usb_psy.name = "usb";
+	msm->usb_psy.type = POWER_SUPPLY_TYPE_USB;
+	msm->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
+	msm->usb_psy.num_supplicants = ARRAY_SIZE(
+					dwc3_msm_pm_power_supplied_to);
+	msm->usb_psy.properties = dwc3_msm_pm_power_props_usb;
+	msm->usb_psy.num_properties = ARRAY_SIZE(dwc3_msm_pm_power_props_usb);
+	msm->usb_psy.get_property = dwc3_msm_power_get_property_usb;
+	msm->usb_psy.set_property = dwc3_msm_power_set_property_usb;
+
+	ret = power_supply_register(&pdev->dev, &msm->usb_psy);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+				"%s:power_supply_register usb failed\n",
+					__func__);
+		goto put_pdev;
+	}
+
 	ret = platform_device_add_resources(dwc3, pdev->resource,
 		pdev->num_resources);
 	if (ret) {
 		dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
-		goto put_pdev;
+		goto put_psupply;
 	}
 
 	ret = platform_device_add(dwc3);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register dwc3 device\n");
-		goto put_pdev;
+		goto put_psupply;
 	}
 
 	msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
@@ -1805,6 +1929,8 @@
 put_xcvr:
 	usb_put_transceiver(msm->otg_xceiv);
 	platform_device_del(dwc3);
+put_psupply:
+	power_supply_unregister(&msm->usb_psy);
 put_pdev:
 	platform_device_put(dwc3);
 free_hsphy_irq:
@@ -1906,9 +2032,14 @@
 		pm_runtime_enable(dev);
 
 		/* Let OTG know about resume event and update pm_count */
-		if (mdwc->otg_xceiv)
+		if (mdwc->otg_xceiv) {
 			mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg,
 							DWC3_EVENT_PHY_RESUME);
+			if (mdwc->ext_xceiv.otg_capability)
+				mdwc->ext_xceiv.notify_ext_events(
+							mdwc->otg_xceiv->otg,
+							DWC3_EVENT_XCEIV_STATE);
+		}
 	}
 
 	return ret;
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index f96b88a..1aa8519 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -25,6 +25,9 @@
 
 static void dwc3_otg_reset(struct dwc3_otg *dotg);
 
+static void dwc3_otg_notify_host_mode(struct usb_otg *otg, int host_mode);
+static void dwc3_otg_reset(struct dwc3_otg *dotg);
+
 /**
  * dwc3_otg_set_host_regs - reset dwc3 otg registers to host operation.
  *
@@ -124,6 +127,7 @@
 			return ret;
 		}
 
+		dwc3_otg_notify_host_mode(otg, on);
 		ret = regulator_enable(dotg->vbus_otg);
 		if (ret) {
 			dev_err(otg->phy->dev, "unable to enable vbus_otg\n");
@@ -143,6 +147,7 @@
 			dev_err(otg->phy->dev, "unable to disable vbus_otg\n");
 			return ret;
 		}
+		dwc3_otg_notify_host_mode(otg, on);
 
 		/* re-init core and OTG register as XHCI reset clears it */
 		dwc3_post_host_reset_core_init(dotg->dwc);
@@ -290,9 +295,11 @@
 static void dwc3_ext_event_notify(struct usb_otg *otg,
 					enum dwc3_ext_events event)
 {
+	static bool init;
 	struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
 	struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
 	struct usb_phy *phy = dotg->otg.phy;
+	int ret = 0;
 
 	if (event == DWC3_EVENT_PHY_RESUME) {
 		if (!pm_runtime_status_suspended(phy->dev)) {
@@ -300,7 +307,16 @@
 		} else {
 			dev_dbg(phy->dev, "ext PHY_RESUME event received\n");
 			/* ext_xceiver would have taken h/w out of LPM by now */
-			pm_runtime_get(phy->dev);
+			ret = pm_runtime_get(phy->dev);
+			if (ret == -EACCES) {
+				/* pm_runtime_get may fail during system
+				   resume with -EACCES error */
+				pm_runtime_disable(phy->dev);
+				pm_runtime_set_active(phy->dev);
+				pm_runtime_enable(phy->dev);
+			} else if (ret < 0) {
+				dev_warn(phy->dev, "pm_runtime_get failed!\n");
+			}
 		}
 	} else if (event == DWC3_EVENT_XCEIV_STATE) {
 		if (ext_xceiv->id == DWC3_ID_FLOAT)
@@ -308,11 +324,20 @@
 		else
 			clear_bit(ID, &dotg->inputs);
 
-		if (ext_xceiv->bsv)
+		if (ext_xceiv->bsv) {
+			dev_dbg(phy->dev, "XCVR: BSV set\n");
 			set_bit(B_SESS_VLD, &dotg->inputs);
-		else
+		} else {
+			dev_dbg(phy->dev, "XCVR: BSV clear\n");
 			clear_bit(B_SESS_VLD, &dotg->inputs);
+		}
 
+		if (!init) {
+			init = true;
+			complete(&dotg->dwc3_xcvr_vbus_init);
+			dev_dbg(phy->dev, "XCVR: BSV init complete\n");
+			return;
+		}
 		schedule_work(&dotg->sm_work);
 	}
 }
@@ -335,6 +360,72 @@
 	return 0;
 }
 
+static void dwc3_otg_notify_host_mode(struct usb_otg *otg, int host_mode)
+{
+	struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
+
+	if (!dotg->psy) {
+		dev_err(otg->phy->dev, "no usb power supply registered\n");
+		return;
+	}
+
+	if (host_mode)
+		power_supply_set_scope(dotg->psy, POWER_SUPPLY_SCOPE_SYSTEM);
+	else
+		power_supply_set_scope(dotg->psy, POWER_SUPPLY_SCOPE_DEVICE);
+}
+
+static int dwc3_otg_set_power(struct usb_phy *phy, unsigned mA)
+{
+	static int power_supply_type;
+	struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg);
+
+
+	if (!dotg->psy) {
+		dev_err(phy->dev, "no usb power supply registered\n");
+		return 0;
+	}
+
+	if (dotg->charger->chg_type == DWC3_SDP_CHARGER)
+		power_supply_type = POWER_SUPPLY_TYPE_USB;
+	else if (dotg->charger->chg_type == DWC3_CDP_CHARGER)
+		power_supply_type = POWER_SUPPLY_TYPE_USB_CDP;
+	else if (dotg->charger->chg_type == DWC3_DCP_CHARGER)
+		power_supply_type = POWER_SUPPLY_TYPE_USB_DCP;
+	else
+		power_supply_type = POWER_SUPPLY_TYPE_BATTERY;
+
+	power_supply_set_supply_type(dotg->psy, power_supply_type);
+
+	if (dotg->charger->max_power == mA)
+		return 0;
+
+	dev_info(phy->dev, "Avail curr from USB = %u\n", mA);
+
+	if (dotg->charger->max_power <= 2 && mA > 2) {
+		/* Enable charging */
+		if (power_supply_set_online(dotg->psy, true))
+			goto psy_error;
+		if (power_supply_set_current_limit(dotg->psy, 1000*mA))
+			goto psy_error;
+	} else if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) {
+		/* Disable charging */
+		if (power_supply_set_online(dotg->psy, false))
+			goto psy_error;
+		/* Set max current limit */
+		if (power_supply_set_current_limit(dotg->psy, 0))
+			goto psy_error;
+	}
+
+	power_supply_changed(dotg->psy);
+	dotg->charger->max_power = mA;
+	return 0;
+
+psy_error:
+	dev_dbg(phy->dev, "power supply error when setting property\n");
+	return -ENXIO;
+}
+
 /* IRQs which OTG driver is interested in handling */
 #define DWC3_OEVT_MASK		(DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT | \
 				 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)
@@ -401,23 +492,32 @@
 {
 	u32 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
 	struct usb_phy *phy = dotg->otg.phy;
-
-	/*
-	 * TODO: If using external notifications then wait here till initial
-	 * state is reported
-	 */
+	struct dwc3_ext_xceiv *ext_xceiv;
+	int ret;
 
 	dev_dbg(phy->dev, "Initialize OTG inputs, osts: 0x%x\n", osts);
 
-	if (osts & DWC3_OTG_OSTS_CONIDSTS)
-		set_bit(ID, &dotg->inputs);
-	else
-		clear_bit(ID, &dotg->inputs);
+	/*
+	 * VBUS initial state is reported after PMIC
+	 * driver initialization. Wait for it.
+	 */
+	ret = wait_for_completion_timeout(&dotg->dwc3_xcvr_vbus_init, HZ * 5);
+	if (!ret)
+		dev_err(phy->dev, "%s: completion timeout\n", __func__);
 
-	if (osts & DWC3_OTG_OSTS_BSESVALID)
-		set_bit(B_SESS_VLD, &dotg->inputs);
-	else
-		clear_bit(B_SESS_VLD, &dotg->inputs);
+	ext_xceiv = dotg->ext_xceiv;
+	dwc3_otg_reset(dotg);
+	if (ext_xceiv && !ext_xceiv->otg_capability) {
+		if (osts & DWC3_OTG_OSTS_CONIDSTS)
+			set_bit(ID, &dotg->inputs);
+		else
+			clear_bit(ID, &dotg->inputs);
+
+		if (osts & DWC3_OTG_OSTS_BSESVALID)
+			set_bit(B_SESS_VLD, &dotg->inputs);
+		else
+			clear_bit(B_SESS_VLD, &dotg->inputs);
+	}
 }
 
 /**
@@ -442,6 +542,14 @@
 	switch (phy->state) {
 	case OTG_STATE_UNDEFINED:
 		dwc3_otg_init_sm(dotg);
+		if (!dotg->psy) {
+			dotg->psy = power_supply_get_by_name("usb");
+
+			if (!dotg->psy)
+				dev_err(phy->dev,
+					 "couldn't get usb power supply\n");
+		}
+
 		/* Switch to A or B-Device according to ID / BSV */
 		if (!test_bit(ID, &dotg->inputs)) {
 			dev_dbg(phy->dev, "!id\n");
@@ -478,9 +586,13 @@
 				switch (charger->chg_type) {
 				case DWC3_DCP_CHARGER:
 					dev_dbg(phy->dev, "lpm, DCP charger\n");
+					dwc3_otg_set_power(phy,
+							DWC3_IDEV_CHG_MAX);
 					pm_runtime_put_sync(phy->dev);
 					break;
 				case DWC3_CDP_CHARGER:
+					dwc3_otg_set_power(phy,
+							DWC3_IDEV_CHG_MAX);
 					dwc3_otg_start_peripheral(&dotg->otg,
 									1);
 					phy->state = OTG_STATE_B_PERIPHERAL;
@@ -521,6 +633,7 @@
 					charger->chg_type =
 							DWC3_INVALID_CHARGER;
 			}
+			dwc3_otg_set_power(phy, 0);
 			dev_dbg(phy->dev, "No device, trying to suspend\n");
 			pm_runtime_put_sync(phy->dev);
 		}
@@ -587,6 +700,8 @@
 static void dwc3_otg_reset(struct dwc3_otg *dotg)
 {
 	static int once;
+	struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
+
 	/*
 	 * OCFG[2] - OTG-Version = 1
 	 * OCFG[1] - HNPCap = 0
@@ -612,9 +727,10 @@
 	dwc3_writel(dotg->regs, DWC3_OEVT, 0xFFFF);
 
 	/* Enable ID/BSV StsChngEn event*/
-	dwc3_writel(dotg->regs, DWC3_OEVTEN,
-			DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT |
-			DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT);
+	if (ext_xceiv && !ext_xceiv->otg_capability)
+		dwc3_writel(dotg->regs, DWC3_OEVTEN,
+				DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT |
+				DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT);
 }
 
 /**
@@ -687,6 +803,7 @@
 	dotg->dwc = dwc;
 	dotg->otg.phy->otg = &dotg->otg;
 	dotg->otg.phy->dev = dwc->dev;
+	dotg->otg.phy->set_power = dwc3_otg_set_power;
 
 	ret = usb_set_transceiver(dotg->otg.phy);
 	if (ret) {
@@ -696,10 +813,9 @@
 		goto err2;
 	}
 
-	dwc3_otg_reset(dotg);
-
 	dotg->otg.phy->state = OTG_STATE_UNDEFINED;
 
+	init_completion(&dotg->dwc3_xcvr_vbus_init);
 	INIT_WORK(&dotg->sm_work, dwc3_otg_sm_work);
 
 	ret = request_irq(dotg->irq, dwc3_otg_interrupt, IRQF_SHARED,
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index dd4cdf4..4384888 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -17,9 +17,12 @@
 #define __LINUX_USB_DWC3_OTG_H
 
 #include <linux/workqueue.h>
+#include <linux/power_supply.h>
 
 #include <linux/usb/otg.h>
 
+#define DWC3_IDEV_CHG_MAX 1500
+
 struct dwc3_charger;
 
 /**
@@ -43,6 +46,8 @@
 #define ID		0
 #define B_SESS_VLD	1
 	unsigned long inputs;
+	struct power_supply	*psy;
+	struct completion	dwc3_xcvr_vbus_init;
 };
 
 /**
@@ -64,6 +69,7 @@
 
 struct dwc3_charger {
 	enum dwc3_chg_type	chg_type;
+	unsigned		max_power;
 
 	/* start/stop charger detection, provided by external charger module */
 	void	(*start_detection)(struct dwc3_charger *charger, bool start);
@@ -91,6 +97,7 @@
 struct dwc3_ext_xceiv {
 	enum dwc3_id_state	id;
 	bool			bsv;
+	bool			otg_capability;
 
 	/* to notify OTG about LPM exit event, provided by OTG */
 	void	(*notify_ext_events)(struct usb_otg *otg,
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 451de18..9c1ebf8 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1455,6 +1455,17 @@
 	return 0;
 }
 
+static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned mA)
+{
+	struct dwc3		*dwc = gadget_to_dwc(g);
+	struct dwc3_otg		*dotg = dwc->dotg;
+
+	if (dotg && dotg->otg.phy)
+		return usb_phy_set_power(dotg->otg.phy, mA);
+
+	return -ENOTSUPP;
+}
+
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 {
 	struct dwc3		*dwc = gadget_to_dwc(g);
@@ -1658,6 +1669,7 @@
 	.wakeup			= dwc3_gadget_wakeup,
 	.set_selfpowered	= dwc3_gadget_set_selfpowered,
 	.vbus_session		= dwc3_gadget_vbus_session,
+	.vbus_draw		= dwc3_gadget_vbus_draw,
 	.pullup			= dwc3_gadget_pullup,
 	.udc_start		= dwc3_gadget_start,
 	.udc_stop		= dwc3_gadget_stop,
@@ -2083,6 +2095,7 @@
 static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 {
 	u32			reg;
+	struct dwc3_otg		*dotg = dwc->dotg;
 
 	dev_vdbg(dwc->dev, "%s\n", __func__);
 
@@ -2127,6 +2140,9 @@
 		dwc3_gadget_usb3_phy_suspend(dwc, false);
 	}
 
+	if (dotg && dotg->otg.phy)
+		usb_phy_set_power(dotg->otg.phy, 0);
+
 	if (dwc->gadget.speed != USB_SPEED_UNKNOWN)
 		dwc3_disconnect_gadget(dwc);
 
@@ -2334,6 +2350,13 @@
 		}
 	}
 
+	if (next == DWC3_LINK_STATE_U0) {
+		if (dwc->link_state == DWC3_LINK_STATE_U3)
+			dwc->gadget_driver->resume(&dwc->gadget);
+	} else if (next == DWC3_LINK_STATE_U3) {
+		dwc->gadget_driver->suspend(&dwc->gadget);
+	}
+
 	dwc->link_state = next;
 
 	dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index fa1bf43..9c7b1ec 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -75,7 +75,7 @@
  *****************************************************************************/
 
 #define DMA_ADDR_INVALID	(~(dma_addr_t)0)
-#define ATDTW_SET_DELAY		100 /* 100msec delay */
+#define USB_MAX_TIMEOUT		100 /* 100msec timeout */
 #define EP_PRIME_CHECK_DELAY	(jiffies + msecs_to_jiffies(1000))
 #define MAX_PRIME_CHECK_RETRY	3 /*Wait for 3sec for EP prime failure */
 
@@ -177,7 +177,8 @@
 
 /* maximum number of enpoints: valid only after hw_device_reset() */
 static unsigned hw_ep_max;
-
+static void dbg_usb_op_fail(u8 addr, const char *name,
+				const struct ci13xxx_ep *mep);
 /**
  * hw_ep_bit: calculates the bit number
  * @num: endpoint number
@@ -381,6 +382,27 @@
 	return 0;
 }
 
+static void debug_ept_flush_info(int ep_num, int dir)
+{
+	struct ci13xxx *udc = _udc;
+	struct ci13xxx_ep *mep;
+
+	if (dir)
+		mep = &udc->ci13xxx_ep[ep_num + hw_ep_max/2];
+	else
+		mep = &udc->ci13xxx_ep[ep_num];
+
+	pr_err_ratelimited("USB Registers\n");
+	pr_err_ratelimited("USBCMD:%x\n", hw_cread(CAP_USBCMD, ~0));
+	pr_err_ratelimited("USBSTS:%x\n", hw_cread(CAP_USBSTS, ~0));
+	pr_err_ratelimited("ENDPTLISTADDR:%x\n",
+			hw_cread(CAP_ENDPTLISTADDR, ~0));
+	pr_err_ratelimited("PORTSC:%x\n", hw_cread(CAP_PORTSC, ~0));
+	pr_err_ratelimited("USBMODE:%x\n", hw_cread(CAP_USBMODE, ~0));
+	pr_err_ratelimited("ENDPTSTAT:%x\n", hw_cread(CAP_ENDPTSTAT, ~0));
+
+	dbg_usb_op_fail(0xFF, "FLUSHF", mep);
+}
 /**
  * hw_ep_flush: flush endpoint fifo (execute without interruption)
  * @num: endpoint number
@@ -390,13 +412,25 @@
  */
 static int hw_ep_flush(int num, int dir)
 {
+	ktime_t start, diff;
 	int n = hw_ep_bit(num, dir);
 
+	start = ktime_get();
 	do {
 		/* flush any pending transfer */
 		hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n));
-		while (hw_cread(CAP_ENDPTFLUSH, BIT(n)))
+		while (hw_cread(CAP_ENDPTFLUSH, BIT(n))) {
 			cpu_relax();
+			diff = ktime_sub(ktime_get(), start);
+			if (ktime_to_ms(diff) > USB_MAX_TIMEOUT) {
+				printk_ratelimited(KERN_ERR
+					"%s: Failed to flush ep#%d %s\n",
+					__func__, num,
+					dir ? "IN" : "OUT");
+				debug_ept_flush_info(num, dir);
+				return 0;
+			}
+		}
 	} while (hw_cread(CAP_ENDPTSTAT, BIT(n)));
 
 	return 0;
@@ -1006,29 +1040,30 @@
 }
 
 /**
- * dbg_prime_fail: prints a PRIME FAIL event
+ * dbg_usb_op_fail: prints USB Operation FAIL event
  * @addr: endpoint address
  * @mEp:  endpoint structure
  */
-static void dbg_prime_fail(u8 addr, const char *name,
-				const struct ci13xxx_ep *mEp)
+static void dbg_usb_op_fail(u8 addr, const char *name,
+				const struct ci13xxx_ep *mep)
 {
 	char msg[DBG_DATA_MSG];
 	struct ci13xxx_req *req;
 	struct list_head *ptr = NULL;
 
-	if (mEp != NULL) {
+	if (mep != NULL) {
 		scnprintf(msg, sizeof(msg),
-			  "PRIME fail EP%d%s QH:%08X",
-			  mEp->num, mEp->dir ? "IN" : "OUT", mEp->qh.ptr->cap);
+			"%s Fail EP%d%s QH:%08X",
+			name, mep->num,
+			mep->dir ? "IN" : "OUT", mep->qh.ptr->cap);
 		dbg_print(addr, name, 0, msg);
 		scnprintf(msg, sizeof(msg),
 				"cap:%08X %08X %08X\n",
-				mEp->qh.ptr->curr, mEp->qh.ptr->td.next,
-				mEp->qh.ptr->td.token);
+				mep->qh.ptr->curr, mep->qh.ptr->td.next,
+				mep->qh.ptr->td.token);
 		dbg_print(addr, "QHEAD", 0, msg);
 
-		list_for_each(ptr, &mEp->qh.queue) {
+		list_for_each(ptr, &mep->qh.queue) {
 			req = list_entry(ptr, struct ci13xxx_req, queue);
 			scnprintf(msg, sizeof(msg),
 					"%08X:%08X:%08X\n",
@@ -1703,52 +1738,52 @@
 
 static void ep_prime_timer_func(unsigned long data)
 {
-	struct ci13xxx_ep *mEp = (struct ci13xxx_ep *)data;
+	struct ci13xxx_ep *mep = (struct ci13xxx_ep *)data;
 	struct ci13xxx_req *req;
 	struct list_head *ptr = NULL;
-	int n = hw_ep_bit(mEp->num, mEp->dir);
+	int n = hw_ep_bit(mep->num, mep->dir);
 	unsigned long flags;
 
 
-	spin_lock_irqsave(mEp->lock, flags);
+	spin_lock_irqsave(mep->lock, flags);
 	if (!hw_cread(CAP_ENDPTPRIME, BIT(n)))
 		goto out;
 
-	if (list_empty(&mEp->qh.queue))
+	if (list_empty(&mep->qh.queue))
 		goto out;
 
-	req = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue);
+	req = list_entry(mep->qh.queue.next, struct ci13xxx_req, queue);
 
 	mb();
 	if (!(TD_STATUS_ACTIVE & req->ptr->token))
 		goto out;
 
-	mEp->prime_timer_count++;
-	if (mEp->prime_timer_count == MAX_PRIME_CHECK_RETRY) {
-		mEp->prime_timer_count = 0;
+	mep->prime_timer_count++;
+	if (mep->prime_timer_count == MAX_PRIME_CHECK_RETRY) {
+		mep->prime_timer_count = 0;
 		pr_info("ep%d dir:%s QH:cap:%08x cur:%08x next:%08x tkn:%08x\n",
-				mEp->num, mEp->dir ? "IN" : "OUT",
-				mEp->qh.ptr->cap, mEp->qh.ptr->curr,
-				mEp->qh.ptr->td.next, mEp->qh.ptr->td.token);
-		list_for_each(ptr, &mEp->qh.queue) {
+				mep->num, mep->dir ? "IN" : "OUT",
+				mep->qh.ptr->cap, mep->qh.ptr->curr,
+				mep->qh.ptr->td.next, mep->qh.ptr->td.token);
+		list_for_each(ptr, &mep->qh.queue) {
 			req = list_entry(ptr, struct ci13xxx_req, queue);
 			pr_info("\treq:%08xnext:%08xtkn:%08xpage0:%08xsts:%d\n",
 					req->dma, req->ptr->next,
 					req->ptr->token, req->ptr->page[0],
 					req->req.status);
 		}
-		dbg_prime_fail(0xFF, "PRIMEF", mEp);
-		mEp->prime_fail_count++;
+		dbg_usb_op_fail(0xFF, "PRIMEF", mep);
+		mep->prime_fail_count++;
 	} else {
-		mod_timer(&mEp->prime_timer, EP_PRIME_CHECK_DELAY);
+		mod_timer(&mep->prime_timer, EP_PRIME_CHECK_DELAY);
 	}
 
-	spin_unlock_irqrestore(mEp->lock, flags);
+	spin_unlock_irqrestore(mep->lock, flags);
 	return;
 
 out:
-	mEp->prime_timer_count = 0;
-	spin_unlock_irqrestore(mEp->lock, flags);
+	mep->prime_timer_count = 0;
+	spin_unlock_irqrestore(mep->lock, flags);
 
 }
 
@@ -1874,7 +1909,7 @@
 			tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
 			diff = ktime_sub(ktime_get(), start);
 			/* poll for max. 100ms */
-			if (ktime_to_ms(diff) > ATDTW_SET_DELAY) {
+			if (ktime_to_ms(diff) > USB_MAX_TIMEOUT) {
 				if (hw_cread(CAP_USBCMD, USBCMD_ATDTW))
 					break;
 				printk_ratelimited(KERN_ERR
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 681435a..729910d 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -541,9 +541,7 @@
 	unsigned long			flags;
 	int				ret;
 
-	int notif_c = 0;
-
-	pr_info("dev:%p portno#%d\n", dev, dev->port_num);
+	pr_debug("dev:%p portno#%d\n", dev, dev->port_num);
 
 	spin_lock_irqsave(&dev->lock, flags);
 
@@ -565,8 +563,12 @@
 		return;
 	}
 
-	notif_c = atomic_inc_return(&dev->not_port.notify_count);
-	pr_info("atomic_inc_return[notif_c] = %d", notif_c);
+	if (atomic_inc_return(&dev->not_port.notify_count) != 1) {
+		pr_debug("delay ep_queue: notifications queue is busy[%d]",
+			atomic_read(&dev->not_port.notify_count));
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return;
+	}
 
 	event = req->buf;
 	event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
@@ -577,8 +579,6 @@
 	event->wLength = cpu_to_le16(0);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	pr_info("Call usb_ep_queue");
-
 	ret = usb_ep_queue(dev->not_port.notify,
 			   dev->not_port.notify_req, GFP_ATOMIC);
 	if (ret) {
@@ -586,7 +586,7 @@
 		pr_err("ep enqueue error %d\n", ret);
 	}
 
-	pr_info("Succcessfull Exit");
+	pr_debug("Successful Exit");
 }
 
 static int
@@ -672,7 +672,6 @@
 
 	mbim->ntb_input_size = NTB_DEFAULT_IN_SIZE;
 
-	atomic_set(&mbim->not_port.notify_count, 0);
 	atomic_set(&mbim->online, 0);
 }
 
@@ -750,6 +749,21 @@
 	switch (mbim->not_port.notify_state) {
 
 	case NCM_NOTIFY_NONE:
+		pr_debug("Notification %02x sent\n", event->bNotificationType);
+
+		if (atomic_read(&mbim->not_port.notify_count) <= 0) {
+			pr_debug("notify_none: done");
+			return;
+		}
+
+		spin_unlock(&mbim->lock);
+		status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
+		spin_lock(&mbim->lock);
+		if (status) {
+			atomic_dec(&mbim->not_port.notify_count);
+			pr_err("Queue notify request failed, err: %d", status);
+		}
+
 		return;
 
 	case NCM_NOTIFY_CONNECT:
@@ -782,20 +796,22 @@
 		mbim->not_port.notify_state = NCM_NOTIFY_CONNECT;
 		break;
 	}
+
 	event->bmRequestType = 0xA1;
 	event->wIndex = cpu_to_le16(mbim->ctrl_id);
 
-	mbim->not_port.notify_req = NULL;
 	/*
 	 * In double buffering if there is a space in FIFO,
 	 * completion callback can be called right after the call,
 	 * so unlocking
 	 */
+	atomic_inc(&mbim->not_port.notify_count);
+	pr_debug("queue request: notify_count = %d",
+		atomic_read(&mbim->not_port.notify_count));
 	spin_unlock(&mbim->lock);
 	status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
 	spin_lock(&mbim->lock);
-	if (status < 0) {
-		mbim->not_port.notify_req = req;
+	if (status) {
 		atomic_dec(&mbim->not_port.notify_count);
 		pr_err("usb_ep_queue failed, err: %d", status);
 	}
@@ -822,27 +838,14 @@
 	struct f_mbim			*mbim = req->context;
 	struct usb_cdc_notification	*event = req->buf;
 
-	int notif_c = 0;
-
-	pr_info("dev:%p\n", mbim);
+	pr_debug("dev:%p\n", mbim);
 
 	spin_lock(&mbim->lock);
 	switch (req->status) {
 	case 0:
-		pr_info("Notification %02x sent\n",
-			event->bNotificationType);
-
-		notif_c = atomic_dec_return(&mbim->not_port.notify_count);
-
-		if (notif_c != 0) {
-			pr_info("Continue to mbim_do_notify()");
-			break;
-		} else {
-			pr_info("notify_count decreased to 0. Do not notify");
-			spin_unlock(&mbim->lock);
-			return;
-		}
-
+		atomic_dec(&mbim->not_port.notify_count);
+		pr_debug("notify_count = %d",
+			atomic_read(&mbim->not_port.notify_count));
 		break;
 
 	case -ECONNRESET:
@@ -862,9 +865,7 @@
 		break;
 	}
 
-	mbim->not_port.notify_req = req;
 	mbim_do_notify(mbim);
-
 	spin_unlock(&mbim->lock);
 
 	pr_info("dev:%p Exit\n", mbim);
@@ -1308,12 +1309,13 @@
 
 				pr_info("Set mbim port out_desc = 0x%p",
 					mbim->bam_port.out->desc);
+
+				pr_debug("Activate mbim\n");
+				mbim_bam_connect(mbim);
+
 			} else {
 				pr_info("PORTS already SET");
 			}
-
-			pr_info("Activate mbim\n");
-			mbim_bam_connect(mbim);
 		}
 
 		spin_lock(&mbim->lock);
@@ -1368,6 +1370,8 @@
 		mbim->not_port.notify->driver_data = NULL;
 	}
 
+	atomic_set(&mbim->not_port.notify_count, 0);
+
 	pr_info("mbim deactivated\n");
 }
 
@@ -1789,7 +1793,6 @@
 
 	spin_lock(&_mbim_dev->lock);
 	_mbim_dev->is_open = true;
-	mbim_notify(_mbim_dev);
 	spin_unlock(&_mbim_dev->lock);
 
 	pr_info("Exit, mbim file opened\n");
@@ -1805,7 +1808,6 @@
 
 	spin_lock(&mbim->lock);
 	mbim->is_open = false;
-	mbim_notify(mbim);
 	spin_unlock(&mbim->lock);
 
 	mbim_unlock(&_mbim_dev->open_excl);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index c7f9e55..25da094 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -2838,15 +2838,7 @@
 		mfd->start_histogram = mdp_histogram_start;
 		mfd->stop_histogram = mdp_histogram_stop;
 		mdp4_display_intf_sel(if_no, DSI_CMD_INTF);
-
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		spin_lock_irqsave(&mdp_spin_lock, flag);
-		mdp_intr_mask |= INTR_OVERLAY0_DONE;
-		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-		spin_unlock_irqrestore(&mdp_spin_lock, flag);
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 #else
-
 		mfd->dma_fnc = mdp_dma2_update;
 		mfd->do_histogram = mdp_do_histogram;
 		mfd->start_histogram = mdp_histogram_start;
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 7c87c44..1bd697e 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1632,8 +1632,14 @@
 		data |= stage;
 	}
 
+	/*
+	 * stage_commit may be called from overlay_unset
+	 * for command panel, mdp clocks may be off at this time.
+	 * so mdp clock enabled is necessary
+	 */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	mdp_clk_ctrl(1);
+
 	mdp4_mixer_blend_setup(mixer);
 
 	off = 0;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index c5442a7..10410a7 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -31,14 +31,14 @@
 #include "mipi_dsi.h"
 #include "mdp4.h"
 
-static int dsi_state;
-
-#define TOUT_PERIOD	HZ	/* 1 second */
-#define MS_100		(HZ/10)	/* 100 ms */
-
 static int vsync_start_y_adjust = 4;
 
 #define MAX_CONTROLLER	1
+
+/*
+ * VSYNC_EXPIRE_TICK == 0 means clock always on
+ * VSYNC_EXPIRE_TICK == 4 is recommended
+ */
 #define VSYNC_EXPIRE_TICK 4
 
 static struct vsycn_ctrl {
@@ -51,10 +51,10 @@
 	u32 ov_done;
 	u32 dmap_koff;
 	u32 dmap_done;
+	u32 pan_display;
 	uint32 rdptr_intr_tot;
 	uint32 rdptr_sirq_tot;
 	atomic_t suspend;
-	atomic_t vsync_resume;
 	int wait_vsync_cnt;
 	int blt_change;
 	int blt_free;
@@ -71,7 +71,6 @@
 	int vsync_enabled;
 	int clk_enabled;
 	int clk_control;
-	int new_update;
 	ktime_t vsync_time;
 	struct work_struct clk_work;
 } vsync_ctrl_db[MAX_CONTROLLER];
@@ -229,8 +228,10 @@
 
 	vctrl = &vsync_ctrl_db[cndx];
 
-	if (atomic_read(&vctrl->suspend) > 0)
+	if (atomic_read(&vctrl->suspend)) {
+		pr_err("%s: suspended, no more pipe queue\n", __func__);
 		return;
+	}
 
 	mutex_lock(&vctrl->update_lock);
 	undx =  vctrl->update_ndx;
@@ -363,12 +364,14 @@
 		mdp4_dsi_cmd_blt_ov_update(pipe);
 		pipe->ov_cnt++;
 		vctrl->ov_koff++;
+		INIT_COMPLETION(vctrl->ov_comp);
 		vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
 	} else {
+		INIT_COMPLETION(vctrl->dmap_comp);
 		vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
 		vctrl->dmap_koff++;
 	}
-	pr_debug("%s: kickoff\n", __func__);
+	pr_debug("%s: kickoff, pid=%d\n", __func__, current->pid);
 	/* kickoff overlay engine */
 	mdp4_stat.kickoff_ov0++;
 	outpdw(MDP_BASE + 0x0004, 0);
@@ -392,15 +395,14 @@
 {
 	struct vsycn_ctrl *vctrl;
 	unsigned long flags;
-	int clk_set_on = 0;
 	int cndx = 0;
+	int clk_set_on = 0;
 
 	vctrl = &vsync_ctrl_db[cndx];
 
-	pr_debug("%s: clk_enabled=%d vsycn_enabeld=%d req=%d\n", __func__,
-		vctrl->clk_enabled, vctrl->vsync_enabled, enable);
-
 	mutex_lock(&vctrl->update_lock);
+	pr_debug("%s: clk_enabled=%d vsync_enabled=%d req=%d\n", __func__,
+		vctrl->clk_enabled, vctrl->vsync_enabled, enable);
 
 	if (vctrl->vsync_enabled == enable) {
 		mutex_unlock(&vctrl->update_lock);
@@ -410,6 +412,10 @@
 	vctrl->vsync_enabled = enable;
 
 	if (enable) {
+		spin_lock_irqsave(&vctrl->spin_lock, flags);
+		vctrl->clk_control = 0;
+		vctrl->expire_tick = 0;
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 		if (vctrl->clk_enabled == 0) {
 			pr_debug("%s: SET_CLK_ON\n", __func__);
 			mipi_dsi_clk_cfg(1);
@@ -417,26 +423,16 @@
 			vctrl->clk_enabled = 1;
 			clk_set_on = 1;
 		}
-		spin_lock_irqsave(&vctrl->spin_lock, flags);
-		vctrl->clk_control = 0;
-		vctrl->expire_tick = 0;
-		vctrl->new_update = 1;
 		if (clk_set_on) {
 			vsync_irq_enable(INTR_PRIMARY_RDPTR,
 						MDP_PRIM_RDPTR_TERM);
 		}
-		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 	} else {
 		spin_lock_irqsave(&vctrl->spin_lock, flags);
-		vctrl->clk_control = 1;
-		if (vctrl->clk_enabled)
-			vctrl->expire_tick = VSYNC_EXPIRE_TICK;
+		vctrl->expire_tick = VSYNC_EXPIRE_TICK;
 		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 	}
 	mutex_unlock(&vctrl->update_lock);
-
-	if (vctrl->vsync_enabled &&  atomic_read(&vctrl->suspend) == 0)
-		atomic_set(&vctrl->vsync_resume, 1);
 }
 
 void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
@@ -514,7 +510,8 @@
 	struct vsycn_ctrl *vctrl;
 
 	vctrl = &vsync_ctrl_db[cndx];
-	pr_debug("%s: ISR, cpu=%d\n", __func__, smp_processor_id());
+	pr_debug("%s: ISR, tick=%d pan=%d cpu=%d\n", __func__,
+		vctrl->expire_tick, vctrl->pan_display, smp_processor_id());
 	vctrl->rdptr_intr_tot++;
 
 	spin_lock(&vctrl->spin_lock);
@@ -525,8 +522,15 @@
 
 	if (vctrl->expire_tick) {
 		vctrl->expire_tick--;
-		if (vctrl->expire_tick == 0)
-			schedule_work(&vctrl->clk_work);
+		if (vctrl->expire_tick == 0) {
+			if (vctrl->pan_display <= 0) {
+				vctrl->clk_control = 1;
+				schedule_work(&vctrl->clk_work);
+			} else {
+				/* wait one more vsycn */
+				vctrl->expire_tick += 1;
+			}
+		}
 	}
 	spin_unlock(&vctrl->spin_lock);
 }
@@ -546,11 +550,15 @@
 	spin_lock(&vctrl->spin_lock);
 	vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
 	vctrl->dmap_done++;
+
+	if (vctrl->pan_display)
+		vctrl->pan_display--;
+
 	diff = vctrl->ov_done - vctrl->dmap_done;
 	pr_debug("%s: ov_koff=%d ov_done=%d dmap_koff=%d dmap_done=%d cpu=%d\n",
 		__func__, vctrl->ov_koff, vctrl->ov_done, vctrl->dmap_koff,
 		vctrl->dmap_done, smp_processor_id());
-	complete_all(&vctrl->dmap_comp);
+	complete(&vctrl->dmap_comp);
 	if (diff <= 0) {
 		if (vctrl->blt_wait)
 			vctrl->blt_wait = 0;
@@ -586,7 +594,7 @@
 	spin_lock(&vctrl->spin_lock);
 	vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
 	vctrl->ov_done++;
-	complete_all(&vctrl->ov_comp);
+	complete(&vctrl->ov_comp);
 	diff = vctrl->ov_done - vctrl->dmap_done;
 
 	pr_debug("%s: ov_koff=%d ov_done=%d dmap_koff=%d dmap_done=%d cpu=%d\n",
@@ -622,20 +630,24 @@
 
 static void clk_ctrl_work(struct work_struct *work)
 {
+	unsigned long flags;
 	struct vsycn_ctrl *vctrl =
 		container_of(work, typeof(*vctrl), clk_work);
-	unsigned long flags;
 
 	mutex_lock(&vctrl->update_lock);
+	spin_lock_irqsave(&vctrl->spin_lock, flags);
 	if (vctrl->clk_control && vctrl->clk_enabled) {
-		pr_debug("%s: SET_CLK_OFF\n", __func__);
-		mdp_clk_ctrl(0);
-		mipi_dsi_clk_cfg(0);
-		spin_lock_irqsave(&vctrl->spin_lock, flags);
 		vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
 		vctrl->clk_enabled = 0;
 		vctrl->clk_control = 0;
 		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+		/* make sure dsi link is idle */
+		mipi_dsi_mdp_busy_wait();
+		mipi_dsi_clk_cfg(0);
+		mdp_clk_ctrl(0);
+		pr_debug("%s: SET_CLK_OFF, pid=%d\n", __func__, current->pid);
+	} else {
+		spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 	}
 	mutex_unlock(&vctrl->update_lock);
 }
@@ -652,8 +664,7 @@
 	cndx = 0;
 	vctrl = &vsync_ctrl_db[0];
 
-	if (atomic_read(&vctrl->suspend) > 0 ||
-		atomic_read(&vctrl->vsync_resume) == 0)
+	if (atomic_read(&vctrl->suspend) > 0)
 		return 0;
 
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
@@ -671,6 +682,8 @@
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 
 	ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+	pr_debug("%s: UEVENT\n", __func__);
+
 	buf[strlen(buf) + 1] = '\0';
 	return ret;
 }
@@ -695,7 +708,6 @@
 	init_completion(&vctrl->dmap_comp);
 	init_completion(&vctrl->vsync_comp);
 	spin_lock_init(&vctrl->spin_lock);
-	atomic_set(&vctrl->vsync_resume, 1);
 	INIT_WORK(&vctrl->clk_work, clk_ctrl_work);
 }
 
@@ -704,20 +716,6 @@
 	primary_rdptr_isr(0);
 }
 
-void mdp4_overlay_dsi_state_set(int state)
-{
-	unsigned long flag;
-
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	dsi_state = state;
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-}
-
-int mdp4_overlay_dsi_state_get(void)
-{
-	return dsi_state;
-}
-
 static __u32 msm_fb_line_length(__u32 fb_index, __u32 xres, int bpp)
 {
 	/*
@@ -942,6 +940,7 @@
 	pipe->srcp0_addr = (uint32)src;
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	mdp_clk_ctrl(1);
 
 	mdp4_overlay_rgb_setup(pipe);
 
@@ -957,6 +956,7 @@
 
 	mdp4_mixer_stage_commit(pipe->mixer_num);
 	/* MDP cmd block disable */
+	mdp_clk_ctrl(0);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
@@ -991,9 +991,10 @@
 	struct msm_fb_data_type *mfd;
 	struct vsycn_ctrl *vctrl;
 
-	pr_debug("%s+:\n", __func__);
+	pr_debug("%s+: pid=%d\n", __func__, current->pid);
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	mfd->cont_splash_done = 1;
 
 	vctrl = &vsync_ctrl_db[cndx];
 	vctrl->mfd = mfd;
@@ -1006,7 +1007,6 @@
 	mdp4_iommu_attach();
 
 	atomic_set(&vctrl->suspend, 0);
-	pr_debug("%s-:\n", __func__);
 
 	if (!vctrl->sysfs_created) {
 		ret = sysfs_create_group(&vctrl->dev->kobj,
@@ -1022,6 +1022,8 @@
 		vctrl->sysfs_created = 1;
 	}
 
+	pr_debug("%s-:\n", __func__);
+
 	return ret;
 }
 
@@ -1034,8 +1036,9 @@
 	struct mdp4_overlay_pipe *pipe;
 	struct vsync_update *vp;
 	int undx;
+	int need_wait, cnt;
 
-	pr_debug("%s+:\n", __func__);
+	pr_debug("%s+: pid=%d\n", __func__, current->pid);
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
@@ -1046,26 +1049,40 @@
 		return ret;
 	}
 
+	need_wait = 0;
+	mutex_lock(&vctrl->update_lock);
 	atomic_set(&vctrl->suspend, 1);
-	atomic_set(&vctrl->vsync_resume, 0);
 
 	complete_all(&vctrl->vsync_comp);
 
+	pr_debug("%s: clk=%d pan=%d\n", __func__,
+			vctrl->clk_enabled, vctrl->pan_display);
+	if (vctrl->clk_enabled)
+		need_wait = 1;
+	mutex_unlock(&vctrl->update_lock);
+
+	cnt = 0;
+	if (need_wait) {
+		while (vctrl->clk_enabled) {
+			msleep(20);
+			cnt++;
+			if (cnt > 10)
+				break;
+		}
+	}
+
+	/* message for system suspnded */
+	if (cnt > 10)
+		pr_err("%s:Error,  mdp clocks NOT off\n", __func__);
+	else
+		pr_debug("%s: mdp clocks off at cnt=%d\n", __func__, cnt);
+
 	/* sanity check, free pipes besides base layer */
 	mdp4_overlay_unset_mixer(pipe->mixer_num);
 	mdp4_mixer_stage_down(pipe, 1);
 	mdp4_overlay_pipe_free(pipe);
 	vctrl->base_pipe = NULL;
 
-	if (vctrl->clk_enabled) {
-		/*
-		 * in case of suspend, vsycn_ctrl off is not
-		 * received from frame work which left clock on
-		 * then, clock need to be turned off here
-		 */
-		mdp_clk_ctrl(0);
-	}
-
 	undx =  vctrl->update_ndx;
 	vp = &vctrl->vlist[undx];
 	if (vp->update_cnt) {
@@ -1076,23 +1093,7 @@
 		vp->update_cnt = 0;     /* empty queue */
 	}
 
-	vctrl->clk_enabled = 0;
-	vctrl->vsync_enabled = 0;
-	vctrl->clk_control = 0;
-	vctrl->expire_tick = 0;
-
-	vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
-
-
 	pr_debug("%s-:\n", __func__);
-
-	/*
-	 * footswitch off
-	 * this will casue all mdp register
-	 * to be reset to default
-	 * after footswitch on later
-	 */
-
 	return ret;
 }
 
@@ -1127,7 +1128,7 @@
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
 	unsigned long flags;
-	long long tick;
+	int clk_set_on = 0;
 
 	mutex_lock(&mfd->dma->ov_mutex);
 	vctrl = &vsync_ctrl_db[cndx];
@@ -1145,25 +1146,32 @@
 	}
 
 	mutex_lock(&vctrl->update_lock);
-	if (!vctrl->clk_enabled) {
-		pr_err("%s: mdp clocks disabled\n", __func__);
+	if (atomic_read(&vctrl->suspend)) {
 		mutex_unlock(&vctrl->update_lock);
 		mutex_unlock(&mfd->dma->ov_mutex);
+		pr_err("%s: suspended, no more pan display\n", __func__);
 		return;
-
 	}
-	mutex_unlock(&vctrl->update_lock);
 
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
-	if (vctrl->expire_tick) {
-		/*
-		 * in the middle of shutting clocks down
-		 * delay to allow pan display to go through
-		 */
+	vctrl->clk_control = 0;
+	vctrl->pan_display++;
+	if (!vctrl->clk_enabled) {
+		clk_set_on = 1;
+		vctrl->clk_enabled = 1;
 		vctrl->expire_tick = VSYNC_EXPIRE_TICK;
 	}
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 
+	if (clk_set_on) {
+		pr_debug("%s: SET_CLK_ON\n", __func__);
+		mipi_dsi_clk_cfg(1);
+		mdp_clk_ctrl(1);
+		vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
+	}
+
+	mutex_unlock(&vctrl->update_lock);
+
 	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE) {
 		mdp4_mipi_vsync_enable(mfd, pipe, 0);
 		mdp4_overlay_setup_pipe_addr(mfd, pipe);
@@ -1172,8 +1180,6 @@
 
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 	mdp4_dsi_cmd_pipe_commit(cndx, 0);
-	mdp4_dsi_cmd_wait4vsync(cndx, &tick);
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
-
 }
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 7f41221..c2d5f28 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -1173,7 +1173,7 @@
 	if (rc) {
 		DEV_ERR("%s: core hdmi_msm_enable_power failed rc = %d\n",
 			__func__, rc);
-		goto disable_hpd_power;
+		return rc;
 	}
 	rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CEC_PM, 1);
 	if (rc) {
@@ -1185,8 +1185,6 @@
 	return rc;
 disable_core_power:
 	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CORE_PM, 0);
-disable_hpd_power:
-	hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, 0);
 	return rc;
 } /* hdmi_tx_core_on */
 
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index 7d534ed..a58010e 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -69,6 +69,8 @@
 	struct msm_fb_data_type *mfd;
 	struct msm_panel_info *pinfo;
 
+	pr_debug("%s+:\n", __func__);
+
 	mfd = platform_get_drvdata(pdev);
 	pinfo = &mfd->panel_info;
 
@@ -77,15 +79,14 @@
 	else
 		down(&mfd->dma->mutex);
 
-	mdp4_overlay_dsi_state_set(ST_DSI_SUSPEND);
+	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
+		mipi_dsi_prepare_clocks();
+		mipi_dsi_ahb_ctrl(1);
+		mipi_dsi_clk_enable();
 
-	/* make sure dsi clk is on so that
-	 * dcs commands can be sent
-	 */
-	mipi_dsi_clk_cfg(1);
-
-	/* make sure dsi_cmd_mdp is idle */
-	mipi_dsi_cmd_mdp_busy();
+		/* make sure dsi_cmd_mdp is idle */
+		mipi_dsi_cmd_mdp_busy();
+	}
 
 	/*
 	 * Desctiption: change to DSI_CMD_MODE since it needed to
@@ -146,6 +147,8 @@
 	u32 dummy_xres, dummy_yres;
 	int target_type = 0;
 
+	pr_debug("%s+:\n", __func__);
+
 	mfd = platform_get_drvdata(pdev);
 	fbi = mfd->fbi;
 	var = &fbi->var;
@@ -305,14 +308,15 @@
 			}
 			mipi_dsi_set_tear_on(mfd);
 		}
+		mipi_dsi_clk_disable();
+		mipi_dsi_ahb_ctrl(0);
+		mipi_dsi_unprepare_clocks();
 	}
 
 #ifdef CONFIG_MSM_BUS_SCALING
 	mdp_bus_scale_update_request(2);
 #endif
 
-	mdp4_overlay_dsi_state_set(ST_DSI_RESUME);
-
 	if (mdp_rev >= MDP_REV_41)
 		mutex_unlock(&mfd->dma->ov_mutex);
 	else
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 0f37f6f..2711c1a 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -319,7 +319,7 @@
 void mipi_dsi_post_kickoff_del(struct dsi_kickoff_action *act);
 void mipi_dsi_controller_cfg(int enable);
 void mipi_dsi_sw_reset(void);
-void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd);
+void mipi_dsi_mdp_busy_wait(void);
 
 irqreturn_t mipi_dsi_isr(int irq, void *ptr);
 
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 60311dc..bea6b4e 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -50,6 +50,7 @@
 static int dsi_ctrl_lock;
 static int dsi_mdp_busy;
 static struct mutex cmd_mutex;
+static struct mutex clk_mutex;
 
 static struct list_head pre_kickoff_list;
 static struct list_head post_kickoff_list;
@@ -99,6 +100,7 @@
 	spin_lock_init(&dsi_mdp_lock);
 	spin_lock_init(&dsi_clk_lock);
 	mutex_init(&cmd_mutex);
+	mutex_init(&clk_mutex);
 
 	INIT_LIST_HEAD(&pre_kickoff_list);
 	INIT_LIST_HEAD(&post_kickoff_list);
@@ -165,12 +167,12 @@
 
 void mipi_dsi_clk_cfg(int on)
 {
-	unsigned long flags;
 	static int dsi_clk_cnt;
 
-	spin_lock_irqsave(&mdp_spin_lock, flags);
+	mutex_lock(&clk_mutex);
 	if (on) {
 		if (dsi_clk_cnt == 0) {
+			mipi_dsi_prepare_clocks();
 			mipi_dsi_ahb_ctrl(1);
 			mipi_dsi_clk_enable();
 		}
@@ -181,10 +183,13 @@
 			if (dsi_clk_cnt == 0) {
 				mipi_dsi_clk_disable();
 				mipi_dsi_ahb_ctrl(0);
+				mipi_dsi_unprepare_clocks();
 			}
 		}
 	}
-	spin_unlock_irqrestore(&mdp_spin_lock, flags);
+	pr_debug("%s: on=%d clk_cnt=%d pid=%d\n", __func__,
+				on, dsi_clk_cnt, current->pid);
+	mutex_unlock(&clk_mutex);
 }
 
 void mipi_dsi_turn_on_clks(void)
@@ -1022,31 +1027,13 @@
 	wmb();
 }
 
-void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd)
+void mipi_dsi_mdp_busy_wait(void)
 {
-	unsigned long flag;
-	int need_wait = 0;
-
-	pr_debug("%s: start pid=%d\n",
-				__func__, current->pid);
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	if (dsi_mdp_busy == TRUE) {
-		INIT_COMPLETION(dsi_mdp_comp);
-		need_wait++;
-	}
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
-	if (need_wait) {
-		/* wait until DMA finishes the current job */
-		pr_debug("%s: pending pid=%d\n",
-				__func__, current->pid);
-		wait_for_completion(&dsi_mdp_comp);
-	}
-	pr_debug("%s: done pid=%d\n",
-				__func__, current->pid);
+	mutex_lock(&cmd_mutex);
+	mipi_dsi_cmd_mdp_busy();
+	mutex_unlock(&cmd_mutex);
 }
 
-
 void mipi_dsi_cmd_mdp_start(void)
 {
 	unsigned long flag;
@@ -1054,8 +1041,9 @@
 	mipi_dsi_mdp_stat_inc(STAT_DSI_START);
 
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	 mipi_dsi_enable_irq(DSI_MDP_TERM);
-	 dsi_mdp_busy = TRUE;
+	mipi_dsi_enable_irq(DSI_MDP_TERM);
+	dsi_mdp_busy = TRUE;
+	INIT_COMPLETION(dsi_mdp_comp);
 	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
 }
 
@@ -1089,14 +1077,28 @@
 
 void mipi_dsi_set_tear_on(struct msm_fb_data_type *mfd)
 {
-	mipi_dsi_buf_init(&dsi_tx_buf);
-	mipi_dsi_cmds_tx(&dsi_tx_buf, &dsi_tear_on_cmd, 1);
+	struct dcs_cmd_req cmdreq;
+
+	cmdreq.cmds = &dsi_tear_on_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mipi_dsi_cmdlist_put(&cmdreq);
 }
 
 void mipi_dsi_set_tear_off(struct msm_fb_data_type *mfd)
 {
-	mipi_dsi_buf_init(&dsi_tx_buf);
-	mipi_dsi_cmds_tx(&dsi_tx_buf, &dsi_tear_off_cmd, 1);
+	struct dcs_cmd_req cmdreq;
+
+	cmdreq.cmds = &dsi_tear_off_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mipi_dsi_cmdlist_put(&cmdreq);
 }
 
 int mipi_dsi_cmd_reg_tx(uint32 data)
@@ -1137,7 +1139,6 @@
 	struct dsi_cmd_desc *cm;
 	uint32 dsi_ctrl, ctrl;
 	int i, video_mode;
-	unsigned long flag;
 
 	/* turn on cmd mode
 	* for video mode, do not send cmds more than
@@ -1151,10 +1152,6 @@
 		MIPI_OUTP(MIPI_DSI_BASE + 0x0000, ctrl);
 	}
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = TRUE;
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
 	cm = cmds;
 	mipi_dsi_buf_init(tp);
 	for (i = 0; i < cnt; i++) {
@@ -1170,11 +1167,6 @@
 	if (video_mode)
 		MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl); /* restore */
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = FALSE;
-	complete(&dsi_mdp_comp);
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
 	return cnt;
 }
 
@@ -1204,7 +1196,6 @@
 {
 	int cnt, len, diff, pkt_size;
 	char cmd;
-	unsigned long flag;
 
 	if (mfd->panel_info.mipi.no_max_pkt_size) {
 		/* Only support rlen = 4*n */
@@ -1241,10 +1232,6 @@
 #endif
 	}
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = TRUE;
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
 	if (!mfd->panel_info.mipi.no_max_pkt_size) {
 		/* packet size need to be set at every read */
 		pkt_size = len;
@@ -1279,11 +1266,6 @@
 
 	mipi_dsi_cmd_dma_rx(rp, cnt);
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = FALSE;
-	complete(&dsi_mdp_comp);
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
 	if (mfd->panel_info.mipi.no_max_pkt_size) {
 		/*
 		 * remove extra 2 bytes from previous
@@ -1327,7 +1309,6 @@
 	struct dsi_cmd_desc *cmds;
 	int cnt, len, diff, pkt_size;
 	char cmd;
-	unsigned long flag;
 
 	if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
 		/* Only support rlen = 4*n */
@@ -1359,10 +1340,6 @@
 		cnt = len + 6; /* 4 bytes header + 2 bytes crc */
 	}
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = TRUE;
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
 	if (!(req->flags & CMD_REQ_NO_MAX_PKT_SIZE)) {
 
 
@@ -1399,11 +1376,6 @@
 
 	mipi_dsi_cmd_dma_rx(rp, cnt);
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = FALSE;
-	complete(&dsi_mdp_comp);
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
 	if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
 		/*
 		 * remove extra 2 bytes from previous
@@ -1515,24 +1487,43 @@
 	return rlen;
 }
 
-void mipi_dsi_cmd_mdp_busy(void)
+static void mipi_dsi_wait_for_video_eng_busy(void)
 {
 	u32 status;
+	int sleep_us = 4000;
+
+	/*
+	 * if video mode engine was not busy (in BLLP)
+	 * wait to pass BLLP
+	 */
+
+	/* check for VIDEO_MODE_ENGINE_BUSY */
+	readl_poll((MIPI_DSI_BASE + 0x0004), /* DSI_STATUS */
+				status,
+				(status & 0x08),
+				sleep_us);
+}
+
+void mipi_dsi_cmd_mdp_busy(void)
+{
 	unsigned long flags;
 	int need_wait = 0;
 
+	pr_debug("%s: start pid=%d\n",
+				__func__, current->pid);
 	spin_lock_irqsave(&dsi_mdp_lock, flags);
-	status = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */
-	if (status & 0x04) {	/* MDP BUSY */
-		INIT_COMPLETION(dsi_mdp_comp);
-		need_wait = 1;
-		pr_debug("%s: status=%x need_wait\n", __func__, (int)status);
-		mipi_dsi_enable_irq(DSI_MDP_TERM);
-	}
+	if (dsi_mdp_busy == TRUE)
+		need_wait++;
 	spin_unlock_irqrestore(&dsi_mdp_lock, flags);
 
-	if (need_wait)
+	if (need_wait) {
+		/* wait until DMA finishes the current job */
+		pr_debug("%s: pending pid=%d\n",
+				__func__, current->pid);
 		wait_for_completion(&dsi_mdp_comp);
+	}
+	pr_debug("%s: done pid=%d\n",
+				__func__, current->pid);
 }
 
 /*
@@ -1589,27 +1580,52 @@
 void mipi_dsi_cmdlist_commit(int from_mdp)
 {
 	struct dcs_cmd_req *req;
+	int video;
+	u32 dsi_ctrl;
 
 	mutex_lock(&cmd_mutex);
 	req = mipi_dsi_cmdlist_get();
-	if (req == NULL) {
-		mutex_unlock(&cmd_mutex);
-		return;
-	}
+
+	/* make sure dsi_cmd_mdp is idle */
+	mipi_dsi_cmd_mdp_busy();
+
+	if (req == NULL)
+		goto need_lock;
+
+	video = MIPI_INP(MIPI_DSI_BASE + 0x0000);
+	video &= 0x02; /* VIDEO_MODE */
+
+	if (!video)
+		mipi_dsi_clk_cfg(1);
 
 	pr_debug("%s:  from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
 
-	if (!from_mdp) { /* from put */
-		/* make sure dsi_cmd_mdp is idle */
-		mipi_dsi_cmd_mdp_busy();
+	dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
+	if (dsi_ctrl & 0x02) {
+		/* video mode, make sure dsi_cmd_mdp is busy
+		 * so dcs command will be txed at start of BLLP
+		 */
+		mipi_dsi_wait_for_video_eng_busy();
+	} else {
+		/* command mode */
+		if (!from_mdp) { /* cmdlist_put */
+			/* make sure dsi_cmd_mdp is idle */
+			mipi_dsi_cmd_mdp_busy();
+		}
 	}
 
-	mipi_dsi_clk_cfg(1);
 	if (req->flags & CMD_REQ_RX)
 		mipi_dsi_cmdlist_rx(req);
 	else
 		mipi_dsi_cmdlist_tx(req);
-	mipi_dsi_clk_cfg(0);
+
+	if (!video)
+		mipi_dsi_clk_cfg(0);
+
+need_lock:
+
+	if (from_mdp) /* from pipe_commit */
+		mipi_dsi_cmd_mdp_start();
 
 	mutex_unlock(&cmd_mutex);
 }
@@ -1762,8 +1778,8 @@
 		mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
 		spin_lock(&dsi_mdp_lock);
 		dsi_ctrl_lock = FALSE;
-		mipi_dsi_disable_irq_nosync(DSI_MDP_TERM);
 		dsi_mdp_busy = FALSE;
+		mipi_dsi_disable_irq_nosync(DSI_MDP_TERM);
 		complete(&dsi_mdp_comp);
 		spin_unlock(&dsi_mdp_lock);
 	}
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index b893cc7..69ca0a3 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -302,19 +302,29 @@
 static struct dsi_cmd_desc novatek_manufacture_id_cmd = {
 	DTYPE_DCS_READ, 1, 0, 1, 5, sizeof(manufacture_id), manufacture_id};
 
+static u32 manu_id;
+
+static void mipi_novatek_manufacture_cb(u32 data)
+{
+	manu_id = data;
+	pr_info("%s: manufacture_id=%x\n", __func__, manu_id);
+}
+
 static uint32 mipi_novatek_manufacture_id(struct msm_fb_data_type *mfd)
 {
-	struct dsi_buf *rp, *tp;
-	struct dsi_cmd_desc *cmd;
-	uint32 *lp;
+	struct dcs_cmd_req cmdreq;
 
-	tp = &novatek_tx_buf;
-	rp = &novatek_rx_buf;
-	cmd = &novatek_manufacture_id_cmd;
-	mipi_dsi_cmds_rx(mfd, tp, rp, cmd, 3);
-	lp = (uint32 *)rp->data;
-	pr_info("%s: manufacture_id=%x\n", __func__, *lp);
-	return *lp;
+	cmdreq.cmds = &novatek_manufacture_id_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_RX | CMD_REQ_COMMIT;
+	cmdreq.rlen = 3;
+	cmdreq.cb = mipi_novatek_manufacture_cb; /* call back */
+	mipi_dsi_cmdlist_put(&cmdreq);
+	/*
+	 * blocked here, untill call back called
+	 */
+
+	return manu_id;
 }
 
 static int fpga_addr;
@@ -380,6 +390,7 @@
 	struct msm_fb_data_type *mfd;
 	struct mipi_panel_info *mipi;
 	struct msm_panel_info *pinfo;
+	struct dcs_cmd_req cmdreq;
 
 	mfd = platform_get_drvdata(pdev);
 	if (!mfd)
@@ -394,23 +405,31 @@
 	mipi  = &mfd->panel_info.mipi;
 
 	if (mipi->mode == DSI_VIDEO_MODE) {
-		mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_video_on_cmds,
-				ARRAY_SIZE(novatek_video_on_cmds));
+		cmdreq.cmds = novatek_video_on_cmds;
+		cmdreq.cmds_cnt = ARRAY_SIZE(novatek_video_on_cmds);
+		cmdreq.flags = CMD_REQ_COMMIT;
+		cmdreq.rlen = 0;
+		cmdreq.cb = NULL;
+		mipi_dsi_cmdlist_put(&cmdreq);
 	} else {
-		mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_cmd_on_cmds,
-				ARRAY_SIZE(novatek_cmd_on_cmds));
+		cmdreq.cmds = novatek_cmd_on_cmds;
+		cmdreq.cmds_cnt = ARRAY_SIZE(novatek_cmd_on_cmds);
+		cmdreq.flags = CMD_REQ_COMMIT;
+		cmdreq.rlen = 0;
+		cmdreq.cb = NULL;
+		mipi_dsi_cmdlist_put(&cmdreq);
 
 		/* clean up ack_err_status */
 		mipi_dsi_cmd_bta_sw_trigger();
 		mipi_novatek_manufacture_id(mfd);
 	}
-
 	return 0;
 }
 
 static int mipi_novatek_lcd_off(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd;
+	struct dcs_cmd_req cmdreq;
 
 	mfd = platform_get_drvdata(pdev);
 
@@ -419,8 +438,13 @@
 	if (mfd->key != MFD_KEY)
 		return -EINVAL;
 
-	mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_display_off_cmds,
-			ARRAY_SIZE(novatek_display_off_cmds));
+	cmdreq.cmds = novatek_display_off_cmds;
+	cmdreq.cmds_cnt = ARRAY_SIZE(novatek_display_off_cmds);
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mipi_dsi_cmdlist_put(&cmdreq);
 
 	return 0;
 }
@@ -431,10 +455,10 @@
 static struct dsi_cmd_desc backlight_cmd = {
 	DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
 
-struct dcs_cmd_req cmdreq;
 
 static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd)
 {
+	struct dcs_cmd_req cmdreq;
 
 	if ((mipi_novatek_pdata->enable_wled_bl_ctrl)
 	    && (wled_trigger_initialized)) {
@@ -446,7 +470,7 @@
 
 	cmdreq.cmds = &backlight_cmd;
 	cmdreq.cmds_cnt = 1;
-	cmdreq.flags = 0;
+	cmdreq.flags = CMD_REQ_COMMIT;
 	cmdreq.rlen = 0;
 	cmdreq.cb = NULL;
 
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index f74db80..e5516ab 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -129,7 +129,7 @@
 	INTERNAL_RSENSE = 0,
 	EXTERNAL_RSENSE,
 	ALT_LEAD_PAIR,
-	GAIN_CALIBRATION_25MV,
+	GAIN_CALIBRATION_17P857MV,
 	OFFSET_CALIBRATION_SHORT_CADC_LEADS,
 	OFFSET_CALIBRATION_CSP_CSN,
 	OFFSET_CALIBRATION_CSP2_CSN2,
@@ -590,13 +590,31 @@
  * @channel - Channel for which the historical offset and gain is
  *	      calculated. Available channels are internal rsense,
  *	      external rsense and alternate lead pairs.
- * @offset - Offset value for the channel.
- * @gain - Gain of the channel.
+ * @offset_raw - raw Offset value for the channel.
+ * @gain_raw - raw Gain of the channel.
+ * @ideal_offset_uv - ideal offset value for the channel.
+ * @ideal_gain_nv - ideal gain for the channel.
+ * @offset_uv - converted value of offset in uV.
+ * @gain_uv - converted value of gain in uV.
  */
 struct qpnp_iadc_calib {
 	enum qpnp_iadc_channels		channel;
-	int32_t				offset;
-	int32_t				gain;
+	uint16_t			offset_raw;
+	uint16_t			gain_raw;
+	uint32_t			ideal_offset_uv;
+	uint32_t			ideal_gain_nv;
+	uint32_t			offset_uv;
+	uint32_t			gain_uv;
+};
+
+/**
+ * struct qpnp_iadc_result - IADC read result structure.
+ * @oresult_uv - Result of ADC in uV.
+ * @result_ua - Result of ADC in uA.
+ */
+struct qpnp_iadc_result {
+	int32_t				result_uv;
+	int32_t				result_ua;
 };
 
 /**
@@ -854,7 +872,7 @@
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
 { return -ENXIO; }
-static inline int32_t qpnp_vadc_is_read(void)
+static inline int32_t qpnp_vadc_is_ready(void)
 { return -ENXIO; }
 #endif
 
@@ -867,23 +885,18 @@
  * @result:	Current across rsens in mV.
  */
 int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
-							int32_t *result);
+				struct qpnp_iadc_result *result);
 /**
- * qpnp_iadc_get_gain() - Performs gain calibration over 25mV reference
- *			  across CCADC.
- * @result:	Gain result across 25mV reference.
+ * qpnp_iadc_get_gain_and_offset() - Performs gain calibration
+ *				over 17.8571mV and offset over selected
+ *				channel. Channel can be internal rsense,
+ *				external rsense and alternate lead pair.
+ * @result:	result structure where the gain and offset is stored of
+ *		type qpnp_iadc_calib.
  */
-int32_t qpnp_iadc_get_gain(int32_t *result);
+int32_t qpnp_iadc_get_gain_and_offset(struct qpnp_iadc_calib *result);
 
 /**
- * qpnp_iadc_get_offset() - Performs offset calibration over selected
- *			    channel. Channel can be internal rsense,
- *			    external rsense and alternate lead pair.
- * @result:	Gain result across 25mV reference.
- */
-int32_t qpnp_iadc_get_offset(enum qpnp_iadc_channels channel,
-						int32_t *result);
-/**
  * qpnp_iadc_is_ready() - Clients can use this API to check if the
  *			  device is ready to use.
  * @result:	0 on success and -EPROBE_DEFER when probe for the device
@@ -892,14 +905,12 @@
 int32_t qpnp_iadc_is_ready(void);
 #else
 static inline int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
-							int *result)
+						struct qpnp_iadc_result *result)
 { return -ENXIO; }
-static inline int32_t qpnp_iadc_get_gain(int32_t *result)
+static inline int32_t qpnp_iadc_get_gain_and_offset(struct qpnp_iadc_calib
+									*result)
 { return -ENXIO; }
-static inline int32_t qpnp_iadc_get_offset(enum qpnp_iadc_channels channel,
-						int32_t *result)
-{ return -ENXIO; }
-static inline int32_t qpnp_iadc_is_read(void)
+static inline int32_t qpnp_iadc_is_ready(void)
 { return -ENXIO; }
 #endif
 
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index 34464c6..0fd11a3 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -69,4 +69,5 @@
 		struct v4l2_event_subscription *sub);
 int msm_vidc_dqevent(void *instance, struct v4l2_event *event);
 int msm_vidc_wait(void *instance);
+int msm_vidc_s_parm(void *instance, struct v4l2_streamparm *a);
 #endif
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 1703c37..95df162 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -978,10 +978,15 @@
 	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
 };
 
-static const char * const rx_dsm_text[] = {
-	"CIC_OUT", "DSM_INV"
+static const char * const rx_rdac5_text[] = {
+	"DEM4", "DEM3_INV"
 };
 
+static const char * const rx_rdac7_text[] = {
+	"DEM6", "DEM5_INV"
+};
+
+
 static const char * const sb_tx1_mux_text[] = {
 	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
 		"DEC1"
@@ -1135,11 +1140,11 @@
 static const struct soc_enum rx7_mix2_inp2_chain_enum =
 	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 3, 5, rx_mix2_text);
 
-static const struct soc_enum rx4_dsm_enum =
-	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX4_B6_CTL, 4, 2, rx_dsm_text);
+static const struct soc_enum rx_rdac5_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
 
-static const struct soc_enum rx6_dsm_enum =
-	SOC_ENUM_SINGLE(TAIKO_A_CDC_RX6_B6_CTL, 4, 2, rx_dsm_text);
+static const struct soc_enum rx_rdac7_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_MISC, 1, 2, rx_rdac7_text);
 
 static const struct soc_enum sb_tx1_mux_enum =
 	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
@@ -1280,11 +1285,11 @@
 static const struct snd_kcontrol_new rx7_mix2_inp2_mux =
 	SOC_DAPM_ENUM("RX7 MIX2 INP2 Mux", rx7_mix2_inp2_chain_enum);
 
-static const struct snd_kcontrol_new rx4_dsm_mux =
-	SOC_DAPM_ENUM("RX4 DSM MUX Mux", rx4_dsm_enum);
+static const struct snd_kcontrol_new rx_dac5_mux =
+	SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
 
-static const struct snd_kcontrol_new rx6_dsm_mux =
-	SOC_DAPM_ENUM("RX6 DSM MUX Mux", rx6_dsm_enum);
+static const struct snd_kcontrol_new rx_dac7_mux =
+	SOC_DAPM_ENUM("RDAC7 MUX Mux", rx_rdac7_enum);
 
 static const struct snd_kcontrol_new sb_tx1_mux =
 	SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
@@ -2635,15 +2640,18 @@
 
 	{"LINEOUT1 DAC", NULL, "RX3 MIX1"},
 
-	{"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
-	{"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
-	{"LINEOUT3 DAC", NULL, "RX4 DSM MUX"},
+
+	{"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
+	{"RDAC5 MUX", "DEM4", "RX4 MIX1"},
+
+	{"LINEOUT3 DAC", NULL, "RDAC5 MUX"},
 
 	{"LINEOUT2 DAC", NULL, "RX5 MIX1"},
 
-	{"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
-	{"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
-	{"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
+	{"RDAC7 MUX", "DEM5_INV", "RX5 MIX1"},
+	{"RDAC7 MUX", "DEM6", "RX6 MIX1"},
+
+	{"LINEOUT4 DAC", NULL, "RDAC7 MUX"},
 
 	{"SPK PA", NULL, "SPK DAC"},
 	{"SPK DAC", NULL, "RX7 MIX2"},
@@ -3844,13 +3852,6 @@
 		0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 
-	SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0,
-		&rx4_dsm_mux, taiko_codec_enable_interpolator,
-		SND_SOC_DAPM_PRE_PMU),
-
-	SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0,
-		&rx6_dsm_mux, taiko_codec_enable_interpolator,
-		SND_SOC_DAPM_PRE_PMU),
 
 	SND_SOC_DAPM_MIXER("RX1 CHAIN", TAIKO_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("RX2 CHAIN", TAIKO_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
@@ -3898,6 +3899,11 @@
 	SND_SOC_DAPM_MUX("RX7 MIX2 INP2", SND_SOC_NOPM, 0, 0,
 		&rx7_mix2_inp2_mux),
 
+	SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac5_mux),
+	SND_SOC_DAPM_MUX("RDAC7 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac7_mux),
+
 	SND_SOC_DAPM_SUPPLY("CLASS_H_CLK", TAIKO_A_CDC_CLK_OTHR_CTL, 0, 0,
 		taiko_codec_enable_class_h_clk, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_PRE_PMD),
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 69256363..016ef94 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -845,6 +845,21 @@
 	return 0;
 }
 
+static int mpq8064_proxy_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+	pr_debug("%s ()\n", __func__);
+	rate->min = rate->max = 48000;
+	channels->min =  channels->max = 2;
+
+	return 0;
+}
+
 static int msm_be_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_hw_params *params)
 {
@@ -1570,6 +1585,7 @@
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+		.be_hw_params_fixup = mpq8064_proxy_be_params_fixup,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
 	},
 	{
@@ -1580,6 +1596,7 @@
 		.codec_name = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-tx",
 		.no_pcm = 1,
+		.be_hw_params_fixup = mpq8064_proxy_be_params_fixup,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
 	},
 	/* AUX PCM Backend DAI Links */
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index dc851ce..915c3c2 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1496,9 +1496,6 @@
 	struct snd_soc_dpcm_params *dpcm_params;
 	int ret = 0;
 
-	if ((cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) ||
-				(cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH))
-		return ret;
 
 	list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
 
@@ -1767,6 +1764,7 @@
 		if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
 		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
 			(be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
 		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
 			continue;