Merge "msm: camera: Support different clock rate for back and front camera"
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index c56f06a..ea626c8 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -230,8 +230,31 @@
 	qcom,rfr-gpio = <&msmgpio 44 0x00>;
 };
 
+&usb_otg {
+	status = "ok";
+	qcom,hsusb-otg-otg-control = <2>;
+	qcom,hsusb-otg-mode = <3>;
+	vbus_otg-supply = <&pm8941_mvs1>;
+	qcom,usb2-enable-hsphy2;
+	qcom,dp-manual-pullup;
+
+	#address-cells = <0>;
+	interrupt-parent = <&usb_otg>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 134 0
+		1 &intc 0 140 0
+		2 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "core_irq", "async_irq", "pmic_id_irq";
+};
+
 &usb3 {
 	qcom,charging-disabled;
+	vbus_dwc3-supply = <0>;
+	dwc3@f9200000 {
+		host-only-mode;
+	};
 };
 
 &slim_msm {
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 0db886b..d6d919b 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -205,6 +205,12 @@
 			};
 		};
 
+		qcom,leds@a100 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xa100 0x100>;
+			label = "mpp";
+		};
+
 		pm8226_gpios: gpios {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
@@ -382,6 +388,21 @@
 			};
 		};
 
+		pm8226_adc_tm: vadc@3400 {
+			compatible = "qcom,qpnp-adc-tm";
+			reg = <0x3400 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts =	<0x0 0x34 0x0>,
+					<0x0 0x34 0x3>,
+				     <0x0 0x34 0x4>;
+			interrupt-names =	"eoc-int-en-set",
+						"high-thr-en-set",
+						"low-thr-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc-vdd-reference = <1800>;
+		};
+
 		qcom,pm8226_rtc {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-rtc";
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 916345c..b96a9e1 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -18,7 +18,10 @@
 / {
 	model = "Qualcomm MSM 8226 CDP";
 	compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
-	qcom,msm-id = <145 1 0>;
+	qcom,msm-id = <145 1 0>,
+		      <158 1 0>,
+		      <159 1 0>,
+		      <198 1 0>;
 };
 
 &soc {
@@ -240,6 +243,24 @@
 };
 
 &spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = <2>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+
 	qcom,pm8226@1 {
 		qcom,leds@d800 {
 			status = "okay";
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 7c19bc0..e11c963 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -34,6 +34,11 @@
 		coresight-id = <1>;
 		coresight-name = "coresight-tpiu";
 		coresight-nr-inports = <1>;
+
+		vdd-supply = <&pm8226_l18>;
+
+		qcom,vdd-voltage-level = <2950000 2950000>;
+		qcom,vdd-current-level = <9000 800000>;
 	};
 
 	replicator: replicator@fc31c000 {
diff --git a/arch/arm/boot/dts/msm8226-fluid.dts b/arch/arm/boot/dts/msm8226-fluid.dts
index 7b11200..c58b43b 100644
--- a/arch/arm/boot/dts/msm8226-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-fluid.dts
@@ -16,7 +16,10 @@
 / {
 	model = "Qualcomm MSM 8226 FLUID";
 	compatible = "qcom,msm8226-fluid", "qcom,msm8226", "qcom,fluid";
-	qcom,msm-id = <145 3 0>;
+	qcom,msm-id = <145 3 0>,
+		      <158 3 0>,
+		      <159 3 0>,
+		      <198 3 0>;
 };
 
 &soc {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 589fe69..65b71e9 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -18,7 +18,10 @@
 / {
 	model = "Qualcomm MSM 8226 MTP";
 	compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
-	qcom,msm-id = <145 8 0>;
+	qcom,msm-id = <145 8 0>,
+		      <158 8 0>,
+		      <159 8 0>,
+		      <198 8 0>;
 };
 
 &soc {
@@ -228,6 +231,24 @@
 };
 
 &spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = <2>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+
 	qcom,pm8226@1 {
                 qcom,leds@d300 {
                         status = "okay";
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index f917d45..aba5c4a 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -18,7 +18,10 @@
 / {
 	model = "Qualcomm MSM 8226 QRD";
 	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0>;
+	qcom,msm-id = <145 11 0>,
+		      <158 11 0>,
+		      <159 11 0>,
+		      <198 11 0>;
 };
 
 &soc {
@@ -231,6 +234,24 @@
 };
 
 &spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = <2>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+
 	qcom,pm8226@1 {
                 qcom,leds@d300 {
                         status = "okay";
@@ -265,6 +286,18 @@
 	};
 };
 
+&pm8226_bms {
+	status = "okay";
+	qcom,batt-type = <4>;
+	qcom,max-voltage-uv = <4350000>;
+};
+
+&pm8226_chg {
+	status = "okay";
+	qcom,chg-vddmax-mv = <4350>;
+	qcom,chg-vddsafe-mv = <4350>;
+};
+
 &pm8226_gpios {
 	gpio@c000 { /* GPIO 1 */
 		/* XO_PMIC_CDC_MCLK enable for tapan codec */
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index 3cca8b0..2405646 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -17,7 +17,10 @@
 / {
 	model = "Qualcomm MSM 8226 Simulator";
 	compatible = "qcom,msm8226-sim", "qcom,msm8226", "qcom,sim";
-	qcom,msm-id = <145 16 0>;
+	qcom,msm-id = <145 16 0>,
+		      <158 16 0>,
+		      <159 16 0>,
+		      <198 16 0>;
 };
 
 &soc {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index b2933db..9d77312 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -1140,6 +1140,71 @@
 	};
 };
 
+&pm8226_adc_tm {
+	/* Channel Node */
+	chan@30 {
+		label = "batt_therm";
+		reg = <0x30>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <1>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x48>;
+	};
+
+	chan@8 {
+		label = "die_temp";
+		reg = <8>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <3>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x68>;
+	};
+
+	chan@6 {
+		label = "vbat_sns";
+		reg = <6>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x70>;
+	};
+
+	chan@14 {
+		label = "pa_therm0";
+		reg = <0x14>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,btm-channel-number = <0x78>;
+		qcom,thermal-node;
+	};
+
+	chan@17 {
+		label = "pa_therm1";
+		reg = <0x17>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,btm-channel-number = <0x80>;
+		qcom,thermal-node;
+	};
+};
+
 &pm8226_chg {
 	status = "ok";
 
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index e63b53b..04f2eb6 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -294,9 +294,19 @@
 		enable-active-high;
 	};
 
+	ath_chip_pwd_l: ath_chip_reset {
+		compatible = "regulator-fixed";
+		regulator-name = "ath_chip_pwd_l";
+		gpio = <&pm8941_gpios 33 0>;
+		enable-active-high;
+	};
+
 	bt_ar3002 {
 		compatible = "qca,ar3002";
 		qca,bt-reset-gpio = <&pm8941_gpios 34 0>;
+		qca,bt-chip-pwd-supply = <&ath_chip_pwd_l>;
+		qca,bt-vdd-io-supply = <&pm8941_s3>;
+		qca,bt-vdd-pa-supply = <&pm8941_l19>;
 	};
 
 	bt_ar3002_sleep {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0eecffd..be0daf3 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -145,7 +145,7 @@
 	select CPU_V7
 	select GPIO_MSM_V2
 	select MSM_GPIOMUX
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_DIRECT_SCLK_ACCESS
 	select REGULATOR
 	select MSM_RPM_REGULATOR
@@ -187,7 +187,7 @@
 	select CPU_V7
 	select GPIO_MSM_V2
 	select MSM_GPIOMUX
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_DIRECT_SCLK_ACCESS
 	select REGULATOR
 	select MSM_RPM_REGULATOR
@@ -223,7 +223,7 @@
 	select GPIO_MSM_V2
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MSM_REMOTE_SPINLOCK_SFPB
 	select MSM_PIL
@@ -257,7 +257,7 @@
 	select GPIO_MSM_V3
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_MULTIMEDIA_USE_ION
@@ -292,7 +292,7 @@
 	select GPIO_MSM_V3
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_NATIVE_RESTART
@@ -317,6 +317,25 @@
 	select SPARSE_IRQ
 	select MSM_NOPM
 
+config ARCH_FSM9900
+	bool "FSM9900"
+	select ARCH_MSM_KRAITMP
+	select GPIO_MSM_V3
+	select ARM_GIC
+	select CPU_V7
+	select MSM_SCM
+	select MSM_GPIOMUX
+	select MULTI_IRQ_HANDLER
+	select MSM_PIL
+	select MSM_NATIVE_RESTART
+	select MSM_RESTART_V2
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+	select REGULATOR
+	select ARM_HAS_SG_CHAIN
+	select MSM_RUN_QUEUE_STATS
+	select MSM_NOPM
+
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
 	select ARCH_MSM_SCORPION
@@ -378,7 +397,6 @@
 	select MSM_RESTART_V2
 	select MSM_SPM_V2
 	select MSM_PM8X60 if PM
-	select MSM_SCM if SMP
 	select MULTI_IRQ_HANDLER
 	select GPIO_MSM_V3
 	select MAY_HAVE_SPARSE_IRQ
@@ -414,7 +432,7 @@
 	select GIC_SECURE
 	select ARCH_MSM_CORTEXMP
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
@@ -456,7 +474,7 @@
 	select GIC_SECURE
 	select ARCH_MSM_CORTEXMP
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
@@ -1094,6 +1112,7 @@
 	default "0x00000000" if ARCH_MSM8226
 	default "0x00000000" if ARCH_MSM8610
 	default "0x10000000" if ARCH_FSM9XXX
+	default "0x00000000" if ARCH_FSM9900
 	default "0x00200000" if ARCH_MSM9625
 	default "0x00000000" if ARCH_MSMKRYPTON
 	default "0x00200000" if !MSM_STACKED_MEMORY
@@ -1257,6 +1276,14 @@
                 help
                   Say Y here if you want the debug print routines to direct
                   their output to the serial port on MSM9625 devices.
+
+	config DEBUG_FSM9900_UART
+		bool "Kernel low-level debugging messages via FSM9900 UART"
+		depends on ARCH_FSM9900
+		select MSM_HAS_DEBUG_UART_HS_V14
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on FSM9900 devices.
 endchoice
 
 choice
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 400f859..b8a2b2d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -121,6 +121,7 @@
 ifndef CONFIG_ARCH_MSM8610
 ifndef CONFIG_ARCH_APQ8084
 ifndef CONFIG_ARCH_MSMKRYPTON
+ifndef CONFIG_ARCH_FSM9900
 	obj-y += nand_partitions.o
 endif
 endif
@@ -132,6 +133,7 @@
 endif
 endif
 endif
+endif
 obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
 obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -230,6 +232,7 @@
 obj-$(CONFIG_ARCH_FSM9XXX) += clock-fsm9xxx.o clock-local.o acpuclock-fsm9xxx.o
 obj-$(CONFIG_ARCH_FSM9XXX) += dfe-fsm9xxx.o rfic-fsm9xxx.o
 obj-$(CONFIG_ARCH_FSM9XXX) += restart-fsm9xxx.o xo-fsm9xxx.o
+obj-$(CONFIG_ARCH_FSM9900) += board-fsm9900.o board-fsm9900-gpiomux.o
 
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog.o
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog_asm.o
@@ -288,7 +291,7 @@
 obj-$(CONFIG_MACH_MSM8930_FLUID) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
 obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o batterydata-lib.o
 obj-$(CONFIG_QPNP_BMS) += bms-batterydata.o bms-batterydata-desay.o batterydata-lib.o
-obj-$(CONFIG_QPNP_BMS) += bms-batterydata-oem.o
+obj-$(CONFIG_QPNP_BMS) += bms-batterydata-oem.o bms-batterydata-qrd-4v35-2000mah.o
 obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_LIQUID) += board-8064-all.o board-8064-regulator.o
@@ -377,6 +380,7 @@
 obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_APQ8084) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_FSM9900) += gpiomux-v2.o gpiomux.o
 
 obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
 obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_mpdecision.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 2827e65..07969e0 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -93,6 +93,11 @@
 params_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x10000100
 initrd_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x12000000
 
+# FSM9900
+   zreladdr-$(CONFIG_ARCH_FSM9900)	:= 0x00008000
+        dtb-$(CONFIG_ARCH_FSM9900)	:= fsm9900-rumi.dtb
+        dtb-$(CONFIG_ARCH_FSM9900)	:= fsm9900-sim.dtb
+
 # MPQ8092
    zreladdr-$(CONFIG_ARCH_MPQ8092)	:= 0x00008000
 
diff --git a/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c b/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
new file mode 100644
index 0000000..8adf8ca
--- /dev/null
+++ b/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
@@ -0,0 +1,117 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
+
+static struct single_row_lut fcc_temp = {
+	.x		= {-20, 0, 25, 40, 60},
+	.y		= {2096, 2124, 2121, 2118, 2103},
+	.cols	= 5
+};
+
+static struct single_row_lut fcc_sf = {
+	.x		= {0},
+	.y		= {100},
+	.cols	= 1
+};
+
+static struct sf_lut rbatt_sf = {
+	.rows		= 30,
+	.cols		= 5,
+	.row_entries		= {-20, 0, 25, 40, 60},
+	.percent	= {100, 95, 90, 85, 80, 75, 70, 65, 60,
+		55, 50, 45, 40, 35, 30, 25, 20, 16, 13,
+		11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
+	.sf		= {
+				{2422, 324, 100, 79, 72},
+				{2417, 325, 100, 79, 71},
+				{2344, 327, 100, 80, 72},
+				{2416, 336, 102, 81, 73},
+				{2072, 354, 107, 82, 73},
+				{1961, 372, 113, 84, 75},
+				{1929, 341, 118, 87, 77},
+				{1929, 321, 130, 93, 80},
+				{2041, 306, 140, 104, 85},
+				{2202, 292, 119, 96, 83},
+				{2374, 290, 98, 80, 73},
+				{2550, 292, 98, 79, 72},
+				{2727, 294, 99, 81, 73},
+				{2904, 303, 100, 82, 75},
+				{3091, 323, 100, 81, 73},
+				{3278, 348, 100, 80, 73},
+				{3470, 376, 99, 79, 72},
+				{3627, 386, 100, 79, 72},
+				{3672, 398, 100, 80, 71},
+				{3812, 424, 100, 80, 73},
+				{3895, 443, 101, 80, 73},
+				{3985, 465, 102, 82, 75},
+				{4094, 497, 105, 83, 76},
+				{4211, 533, 109, 85, 79},
+				{4335, 579, 113, 87, 80},
+				{4505, 612, 113, 85, 76},
+				{4693, 643, 113, 86, 77},
+				{4930, 712, 120, 90, 81},
+				{5283, 835, 145, 111, 107},
+				{10293, 15765, 5566, 6904, 2547},
+	}
+};
+
+static struct pc_temp_ocv_lut pc_temp_ocv = {
+	.rows		= 31,
+	.cols		= 5,
+	.temp		= {-20, 0, 25, 40, 60},
+	.percent	= {100, 95, 90, 85, 80, 75, 70, 65, 60,
+		55, 50, 45, 40, 35, 30, 25, 20, 16, 13,
+		11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
+	.ocv		= {
+				{4340, 4340, 4335, 4330, 4323},
+				{4217, 4260, 4265, 4263, 4258},
+				{4135, 4203, 4207, 4205, 4201},
+				{4084, 4150, 4152, 4150, 4146},
+				{3992, 4101, 4101, 4097, 4093},
+				{3934, 4049, 4051, 4046, 4044},
+				{3889, 3974, 3995, 3998, 3999},
+				{3852, 3926, 3958, 3961, 3959},
+				{3832, 3892, 3921, 3923, 3921},
+				{3819, 3859, 3874, 3877, 3877},
+				{3807, 3831, 3838, 3838, 3838},
+				{3796, 3809, 3815, 3815, 3814},
+				{3784, 3792, 3797, 3797, 3796},
+				{3770, 3780, 3783, 3782, 3781},
+				{3754, 3770, 3772, 3769, 3764},
+				{3737, 3758, 3763, 3754, 3742},
+				{3717, 3737, 3744, 3735, 3720},
+				{3700, 3713, 3718, 3710, 3696},
+				{3687, 3701, 3692, 3683, 3671},
+				{3674, 3695, 3689, 3681, 3669},
+				{3667, 3692, 3688, 3680, 3669},
+				{3659, 3690, 3687, 3680, 3668},
+				{3649, 3687, 3685, 3678, 3667},
+				{3636, 3683, 3683, 3676, 3664},
+				{3618, 3674, 3679, 3671, 3658},
+				{3596, 3652, 3663, 3652, 3632},
+				{3566, 3611, 3620, 3606, 3584},
+				{3522, 3547, 3555, 3540, 3517},
+				{3460, 3449, 3461, 3446, 3424},
+				{3356, 3282, 3312, 3299, 3273},
+				{3000, 3000, 3000, 3000, 3000}
+	}
+};
+
+
+struct bms_battery_data QRD_4v35_2000mAh_data = {
+	.fcc				= 2000,
+	.fcc_temp_lut			= &fcc_temp,
+	.fcc_sf_lut				= &fcc_sf,
+	.pc_temp_ocv_lut		= &pc_temp_ocv,
+	.rbatt_sf_lut			= &rbatt_sf,
+	.default_rbatt_mohm	= 172
+};
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 7fe3f97..f3de05a 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -169,11 +169,11 @@
 	VDD_DIG_NUM
 };
 
-static int *vdd_corner[] = {
-	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
-	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_corner[] = {
+	RPM_REGULATOR_CORNER_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_CORNER_NORMAL,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_DIG_HIGH */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
@@ -2753,11 +2753,11 @@
 	VDD_SR2_PLL_NUM
 };
 
-static int *vdd_sr2_levels[] = {
-	[VDD_SR2_PLL_OFF] = VDD_UV(0,       RPM_REGULATOR_CORNER_NONE),
-	[VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_sr2_levels[] = {
+	0,       RPM_REGULATOR_CORNER_NONE,		/* VDD_SR2_PLL_OFF */
+	1800000, RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_SR2_PLL_SVS */
+	1800000, RPM_REGULATOR_CORNER_NORMAL,		/* VDD_SR2_PLL_NOM */
+	1800000, RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_SR2_PLL_TUR */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2,
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 17468d2..340f1ef 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -434,11 +434,11 @@
 	VDD_DIG_NUM
 };
 
-static int *vdd_corner[] = {
-	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
-	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_corner[] = {
+	RPM_REGULATOR_CORNER_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_CORNER_NORMAL,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_DIG_HIGH */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
@@ -533,11 +533,11 @@
 	VDD_SR2_PLL_NUM
 };
 
-static int *vdd_sr2_levels[] = {
-	[VDD_SR2_PLL_OFF] = VDD_UV(0,       RPM_REGULATOR_CORNER_NONE),
-	[VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_sr2_levels[] = {
+	0,       RPM_REGULATOR_CORNER_NONE,		/* VDD_SR2_PLL_OFF */
+	1800000, RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_SR2_PLL_SVS */
+	1800000, RPM_REGULATOR_CORNER_NORMAL,		/* VDD_SR2_PLL_NOM */
+	1800000, RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_SR2_PLL_TUR */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2,
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index ec94f00..4a16b42 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -638,11 +638,11 @@
 	VDD_DIG_NUM
 };
 
-static int *vdd_corner[] = {
-	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
-	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_corner[] = {
+	RPM_REGULATOR_CORNER_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_CORNER_NORMAL,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_DIG_HIGH */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 5bfc4bb..3277d75 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -280,11 +280,11 @@
 	VDD_DIG_NUM
 };
 
-static int *vdd_corner[] = {
-	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
-	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_corner[] = {
+	RPM_REGULATOR_CORNER_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_CORNER_NORMAL,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_DIG_HIGH */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 08817c0..608018c 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -62,27 +62,31 @@
 {
 	int level, rc = 0, i;
 	struct regulator **r = vdd_class->regulator;
-	int **vdd_uv = vdd_class->vdd_uv;
-	int **vdd_ua = vdd_class->vdd_ua;
-	int max_level = vdd_class->num_levels - 1;
+	int *uv = vdd_class->vdd_uv;
+	int *ua = vdd_class->vdd_ua;
+	int n_reg = vdd_class->num_regulators;
+	int max_lvl = vdd_class->num_levels - 1;
+	int lvl_base;
 
-	for (level = max_level; level > 0; level--)
+	for (level = max_lvl; level > 0; level--)
 		if (vdd_class->level_votes[level])
 			break;
 
 	if (level == vdd_class->cur_level)
 		return 0;
 
+	max_lvl = max_lvl * n_reg;
+	lvl_base = level * n_reg;
 	for (i = 0; i < vdd_class->num_regulators; i++) {
-		rc = regulator_set_voltage(r[i], vdd_uv[level][i],
-			vdd_uv[max_level][i]);
+		rc = regulator_set_voltage(r[i], uv[lvl_base + i],
+					   uv[max_lvl + i]);
 		if (rc)
 			goto set_voltage_fail;
 
-		if (!vdd_ua)
+		if (!ua)
 			continue;
 
-		rc = regulator_set_optimum_mode(r[i], vdd_ua[level][i]);
+		rc = regulator_set_optimum_mode(r[i], ua[lvl_base + i]);
 		if (rc < 0)
 			goto set_mode_fail;
 	}
@@ -95,18 +99,17 @@
 	return 0;
 
 set_mode_fail:
-	regulator_set_voltage(r[i], vdd_uv[vdd_class->cur_level][i],
-				vdd_uv[max_level][i]);
+	regulator_set_voltage(r[i], uv[vdd_class->cur_level * n_reg + i],
+			      uv[max_lvl + i]);
 
 set_voltage_fail:
+	lvl_base = vdd_class->cur_level * n_reg;
 	for (i--; i >= 0; i--) {
-		regulator_set_voltage(r[i], vdd_uv[vdd_class->cur_level][i],
-					vdd_uv[max_level][i]);
+		regulator_set_voltage(r[i], uv[lvl_base + i], uv[max_lvl + i]);
 
-		if (!vdd_ua)
+		if (!ua)
 			continue;
-		regulator_set_optimum_mode(r[i],
-					vdd_ua[vdd_class->cur_level][i]);
+		regulator_set_optimum_mode(r[i], ua[lvl_base + i]);
 	}
 
 	return rc;
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 0dd4957..27c6df4 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -61,8 +61,8 @@
 	struct regulator **regulator;
 	int num_regulators;
 	int (*set_vdd)(struct clk_vdd_class *v_class, int level);
-	int **vdd_uv;
-	int **vdd_ua;
+	int *vdd_uv;
+	int *vdd_ua;
 	int *level_votes;
 	int num_levels;
 	unsigned long cur_level;
@@ -93,9 +93,6 @@
 		.lock = __MUTEX_INITIALIZER(_name.lock) \
 	}
 
-#define VDD_UV(...) ((int []){__VA_ARGS__})
-#define VDD_UA(...) ((int []){__VA_ARGS__})
-
 enum handoff {
 	HANDOFF_ENABLED_CLK,
 	HANDOFF_DISABLED_CLK,
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index da7c039..5ecc63b 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -101,6 +101,7 @@
 * @desc_mem_buf: descriptor fifo buffer.
 * @event: event for wakeup.
 * @enabled: true if pipe is enabled.
+* @ipa_clnt_hdl : pipe handle to ipa api.
 * @priv: private data to return upon activity_notify
 *	or inactivity_notify callbacks.
 * @activity_notify: callback to invoke on activity on one of the in pipes.
@@ -125,6 +126,7 @@
 	struct sps_mem_buffer desc_mem_buf;
 	struct usb_bam_event_info event;
 	bool enabled;
+	int ipa_clnt_hdl;
 	void *priv;
 	int (*activity_notify)(void *priv);
 	int (*inactivity_notify)(void *priv);
@@ -195,6 +197,14 @@
 		struct usb_bam_connect_ipa_params *ipa_params);
 
 /**
+ * Wait for Consumer granted from Resource Manager.
+ *
+ * @ipa_params - in/out parameters
+ *
+ */
+void usb_bam_wait_for_cons_granted(
+	struct usb_bam_connect_ipa_params *ipa_params);
+/**
  * Register a wakeup callback from peer BAM.
  *
  * @idx - Connection index.
@@ -221,6 +231,39 @@
 int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param);
 
 /**
+ * Register callbacks for start/stop of transfers.
+ *
+ * @start - the callback function that will be called in USB
+ *				driver to start transfers
+ * @stop - the callback function that will be called in USB
+ *				driver to stop transfers
+ *
+ * @param - context that the caller can supply
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param);
+
+/**
+ * Start usb suspend sequence
+ *
+ * @ipa_params -  in/out parameters
+ *
+ */
+void usb_bam_suspend(struct usb_bam_connect_ipa_params *ipa_params);
+
+/**
+ * Start usb resume sequence
+ *
+ * @ipa_params -  in/out parameters
+ *
+ */
+void usb_bam_resume(struct usb_bam_connect_ipa_params *ipa_params);
+/**
  * Disconnect USB-to-Periperal SPS connection.
  *
  * @idx - Connection index.
@@ -315,6 +358,12 @@
 	return -ENODEV;
 }
 
+static inline void usb_bam_wait_for_cons_granted(
+			struct usb_bam_connect_ipa_params *ipa_params)
+{
+	return;
+}
+
 static inline int usb_bam_register_wake_cb(u8 idx,
 	int (*callback)(void *), void* param)
 {
@@ -327,6 +376,20 @@
 	return -ENODEV;
 }
 
+static inline int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param)
+{
+	return -ENODEV;
+}
+
+static inline void usb_bam_suspend(
+	struct usb_bam_connect_ipa_params *ipa_params){}
+
+static inline void usb_bam_resume(
+	struct usb_bam_connect_ipa_params *ipa_params) {}
+
 static inline int usb_bam_disconnect_pipe(u8 idx)
 {
 	return -ENODEV;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 2c7ceab..62da5ac 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -364,7 +364,7 @@
 {
 	struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
 	void *sel_cdata;
-	int i;
+	long rounded_rate;
 
 	sel_cdata = fabric->cdata[ctx];
 
@@ -379,8 +379,17 @@
 	}
 
 	/* Enable clocks before accessing QoS registers */
-	for (i = 0; i < NUM_CTX; i++)
-		clk_prepare_enable(fabric->info.nodeclk[i].clk);
+	if (fabric->info.nodeclk[DUAL_CTX].clk)
+		if (fabric->info.nodeclk[DUAL_CTX].rate == 0) {
+			rounded_rate = clk_round_rate(fabric->
+				info.nodeclk[DUAL_CTX].clk, 1);
+		if (clk_set_rate(fabric->info.nodeclk[DUAL_CTX].clk,
+				rounded_rate))
+			MSM_BUS_ERR("Error: clk: en: Node: %d rate: %ld",
+				fabric->fabdev.id, rounded_rate);
+
+		clk_prepare_enable(fabric->info.nodeclk[DUAL_CTX].clk);
+	}
 
 	if (info->iface_clk.clk)
 		clk_prepare_enable(info->iface_clk.clk);
@@ -392,8 +401,9 @@
 		master_tiers, add_bw);
 
 	/* Disable clocks after accessing QoS registers */
-	for (i = 0; i < NUM_CTX; i++)
-		clk_disable_unprepare(fabric->info.nodeclk[i].clk);
+	if (fabric->info.nodeclk[DUAL_CTX].clk &&
+			fabric->info.nodeclk[DUAL_CTX].rate == 0)
+		clk_disable_unprepare(fabric->info.nodeclk[DUAL_CTX].clk);
 
 	if (info->iface_clk.clk) {
 		MSM_BUS_DBG("Commented: Will disable clock for info: %d\n",
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 5419bf0..7fd76ab 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -313,6 +313,7 @@
 	}
 
 	pr_err("riva: smsm state changed to smsm reset\n");
+	wcnss_riva_dump_pmic_regs();
 
 	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
 		&smem_reset_size);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 0c02b51..08456d7 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -324,6 +324,9 @@
 
 	/* 8226 IDs */
 	[145] = MSM_CPU_8226,
+	[158] = MSM_CPU_8226,
+	[159] = MSM_CPU_8226,
+	[198] = MSM_CPU_8226,
 
 	/* 8092 IDs */
 	[146] = MSM_CPU_8092,
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index c971896..b956649 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -41,6 +41,9 @@
 
 #include "smd_private.h"
 
+static int enable_debug;
+module_param(enable_debug, int, S_IRUGO | S_IWUSR);
+
 /**
  * enum p_subsys_state - state of a subsystem (private)
  * @SUBSYS_NORMAL: subsystem is operating normally
@@ -419,7 +422,7 @@
 {
 	int ret;
 
-	if (!subsys->desc->err_ready_irq)
+	if (!subsys->desc->err_ready_irq || enable_debug == 1)
 		return 0;
 
 	ret = wait_for_completion_timeout(&subsys->err_ready,
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 684f11d..292a0be 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -219,6 +219,7 @@
 	int num_clients;
 	int polling_reg_flag;
 	struct diag_write_device *buf_tbl;
+	unsigned int buf_tbl_size;
 	int use_device_tree;
 	/* DCI related variables */
 	struct dci_pkt_req_tracking_tbl *req_tracking_tbl;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 7022a6f..96e8b11 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1167,7 +1167,7 @@
 		/* place holder for number of data field */
 		ret += 4;
 
-		for (i = 0; i < driver->poolsize_write_struct; i++) {
+		for (i = 0; i < driver->buf_tbl_size; i++) {
 			if (driver->buf_tbl[i].length > 0) {
 #ifdef DIAG_DEBUG
 				pr_debug("diag: WRITING the buf address "
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 151e304..f76d41a 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -48,7 +48,8 @@
 
 int diag_debug_buf_idx;
 unsigned char diag_debug_buf[1024];
-static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
+/* Number of entries in table of buffers */
+static unsigned int buf_tbl_size = 10;
 struct diag_master_table entry;
 struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
@@ -467,7 +468,7 @@
 	if (driver->logging_mode == MEMORY_DEVICE_MODE) {
 		int hsic_updated = 0;
 		if (data_type == APPS_DATA) {
-			for (i = 0; i < driver->poolsize_write_struct; i++)
+			for (i = 0; i < driver->buf_tbl_size; i++)
 				if (driver->buf_tbl[i].length == 0) {
 					driver->buf_tbl[i].buf = buf;
 					driver->buf_tbl[i].length =
@@ -1768,6 +1769,12 @@
 	driver->read_len_legacy = 0;
 	driver->use_device_tree = has_device_tree();
 	driver->real_time_mode = 1;
+	/*
+	 * The number of entries in table of buffers
+	 * should not be any smaller than hdlc poolsize.
+	 */
+	driver->buf_tbl_size = (buf_tbl_size < driver->poolsize_hdlc) ?
+				driver->poolsize_hdlc : buf_tbl_size;
 	mutex_init(&driver->diag_hdlc_mutex);
 	mutex_init(&driver->diag_cntl_mutex);
 
@@ -1802,7 +1809,7 @@
 		goto err;
 	kmemleak_not_leak(driver->client_map);
 	if (driver->buf_tbl == NULL)
-			driver->buf_tbl = kzalloc(buf_tbl_size *
+			driver->buf_tbl = kzalloc(driver->buf_tbl_size *
 			  sizeof(struct diag_write_device), GFP_KERNEL);
 	if (driver->buf_tbl == NULL)
 		goto err;
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 3b01e54..a1fc5a2 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -268,7 +268,8 @@
 		 * timestamp on the event has passed - return that up a layer
 		 */
 
-		return device->ftbl->next_event(device, event);
+		if (device->ftbl->next_event)
+			return device->ftbl->next_event(device, event);
 	}
 
 	return 0;
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index b3b3b5e..4306b1d 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -83,6 +83,14 @@
 #define QPNP_VADC_M1_LOW_THR_MSB					0x6a
 #define QPNP_VADC_M1_HIGH_THR_LSB				0x6b
 #define QPNP_VADC_M1_HIGH_THR_MSB				0x6c
+#define QPNP_VADC_ACCESS					0xd0
+#define QPNP_VADC_ACCESS_DATA					0xa5
+#define QPNP_VADC_PERH_RESET_CTL3				0xda
+#define QPNP_FOLLOW_OTST2_RB					BIT(3)
+#define QPNP_FOLLOW_WARM_RB					BIT(2)
+#define QPNP_FOLLOW_SHUTDOWN1_RB				BIT(1)
+#define QPNP_FOLLOW_SHUTDOWN2_RB				BIT(0)
+
 #define QPNP_INT_TEST_VAL					0xE1
 
 #define QPNP_VADC_DATA0						0x60
@@ -150,6 +158,40 @@
 	return 0;
 }
 
+static int32_t qpnp_vadc_warm_rst_configure(void)
+{
+	int rc = 0;
+	u8 data = 0;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_PERH_RESET_CTL3, &data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 read failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	data |= QPNP_FOLLOW_WARM_RB;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_PERH_RESET_CTL3, data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 write failed\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int32_t qpnp_vadc_enable(bool state)
 {
 	int rc = 0;
@@ -1126,6 +1168,12 @@
 	}
 	vadc->id = fab_id;
 
+	rc = qpnp_vadc_warm_rst_configure();
+	if (rc < 0) {
+		pr_err("Setting perp reset on warm reset failed %d\n", rc);
+		return rc;
+	}
+
 	vadc->vadc_initialized = true;
 	vadc->vadc_iadc_sync_lock = false;
 
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index ed53c41..ba94178 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -2567,7 +2567,7 @@
 
 	if (rmi4_data->board->i2c_pull_up) {
 		retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
-			RMI4_I2C_LOAD_UA);
+			RMI4_I2C_LPM_LOAD_UA);
 		if (retval < 0) {
 			dev_err(&rmi4_data->i2c_client->dev,
 				"Regulator vcc_i2c set_opt failed rc=%d\n",
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index fcade49..2c2b339 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -75,7 +75,8 @@
 	DMX_FIFO_ERROR, /* Receiver FIFO overrun */
 	DMX_MISSED_ERROR, /* Receiver missed packet */
 	DMX_OK_DECODER_BUF, /* Received OK, new ES data in decoder buffer */
-	DMX_OK_IDX /* Received OK, new index event */
+	DMX_OK_IDX, /* Received OK, new index event */
+	DMX_OK_SCRAMBLING_STATUS, /* Received OK, new scrambling status */
 } ;
 
 
@@ -135,6 +136,7 @@
 		} marker;
 
 		struct dmx_index_event_info idx_event;
+		struct dmx_scrambling_status_event_info scrambling_bits;
 	};
 };
 
@@ -250,6 +252,7 @@
 	int (*ts_insertion_terminate)(struct dmx_ts_feed *feed);
 	int (*ts_insertion_insert_buffer)(struct dmx_ts_feed *feed,
 			char *data, size_t size);
+	int (*get_scrambling_bits)(struct dmx_ts_feed *feed, u8 *value);
 };
 
 /*--------------------------------------------------------------------------*/
@@ -300,6 +303,7 @@
 				struct dmx_secure_mode *sec_mode);
 	int (*oob_command) (struct dmx_section_feed *feed,
 				struct dmx_oob_command *cmd);
+	int (*get_scrambling_bits)(struct dmx_section_feed *feed, u8 *value);
 };
 
 /*--------------------------------------------------------------------------*/
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 2a750a6..6734da8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1796,6 +1796,35 @@
 	return 0;
 }
 
+static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter,
+	struct dmx_scrambling_bits *scrambling_bits)
+{
+	struct dmxdev_feed *feed;
+
+	if (!scrambling_bits ||
+		(filter->state != DMXDEV_STATE_GO))
+		return -EINVAL;
+
+	if (filter->type == DMXDEV_TYPE_SEC) {
+		if (filter->feed.sec.feed->get_scrambling_bits)
+			return filter->feed.sec.feed->get_scrambling_bits(
+						filter->feed.sec.feed,
+						&scrambling_bits->value);
+		return -EINVAL;
+	}
+
+	list_for_each_entry(feed, &filter->feed.ts, next) {
+		if (feed->pid == scrambling_bits->pid) {
+			if (feed->ts->get_scrambling_bits)
+				return feed->ts->get_scrambling_bits(feed->ts,
+						&scrambling_bits->value);
+			return -EINVAL;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void dvb_dmxdev_ts_insertion_work(struct work_struct *worker)
 {
 	struct ts_insertion_buffer *ts_buffer =
@@ -2519,6 +2548,13 @@
 			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
 			spin_unlock(&dmxdevfilter->dev->lock);
 			wake_up_all(&dmxdevfilter->buffer.queue);
+		} else if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
+			event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
+			event.params.scrambling_status =
+				dmx_data_ready->scrambling_bits;
+			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
+			spin_unlock(&dmxdevfilter->dev->lock);
+			wake_up_all(&dmxdevfilter->buffer.queue);
 		} else {
 			spin_unlock(&dmxdevfilter->dev->lock);
 		}
@@ -2635,6 +2671,16 @@
 		return 0;
 	}
 
+	if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
+		event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
+		event.params.scrambling_status =
+			dmx_data_ready->scrambling_bits;
+		dvb_dmxdev_add_event(events, &event);
+		spin_unlock(&dmxdevfilter->dev->lock);
+		wake_up_all(&buffer->queue);
+		return 0;
+	}
+
 	if (dmx_data_ready->status == DMX_OK_DECODER_BUF) {
 		event.type = DMX_EVENT_NEW_ES_DATA;
 		event.params.es_data.buf_handle = dmx_data_ready->buf.handle;
@@ -3938,6 +3984,15 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_GET_SCRAMBLING_BITS:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_get_scrambling_bits(dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -4193,6 +4248,7 @@
 	struct dmxdev_filter *filter;
 	int active_count = 0;
 	struct dmx_buffer_status buffer_status;
+	struct dmx_scrambling_bits scrambling_bits;
 	const char *pes_feeds[] = {"DEC", "PES", "DVR", "REC"};
 
 	if (!dmxdev)
@@ -4209,23 +4265,32 @@
 				seq_printf(s, "type: SEC, ");
 				seq_printf(s, "PID %04d ",
 						filter->params.sec.pid);
+				scrambling_bits.pid = filter->params.sec.pid;
 			} else {
 				seq_printf(s, "type: %s, ",
 					pes_feeds[filter->params.pes.output]);
 				seq_printf(s, "PID: %04d ",
 						filter->params.pes.pid);
+				scrambling_bits.pid = filter->params.pes.pid;
 			}
 
+			dvb_dmxdev_get_scrambling_bits(filter,
+				&scrambling_bits);
+
 			if (0 == dvb_dmxdev_get_buffer_status(
 						filter, &buffer_status)) {
 				seq_printf(s, "size: %08d, ",
 					buffer_status.size);
 				seq_printf(s, "fullness: %08d, ",
 					buffer_status.fullness);
-				seq_printf(s, "error: %d\n",
+				seq_printf(s, "error: %d, ",
 					buffer_status.error);
+				seq_printf(s, "scramble: %d\n",
+					scrambling_bits.value);
+
 			} else {
-				seq_printf(s, "\n");
+				seq_printf(s, "scramble: %d\n",
+					scrambling_bits.value);
 			}
 		}
 	}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 9844c64..8caa9dd 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -164,6 +164,11 @@
 	return ((buf[1] & 0x1f) << 8) + buf[2];
 }
 
+static inline u16 ts_scrambling_ctrl(const u8 *buf)
+{
+	return (buf[3] >> 6) & 0x3;
+}
+
 static inline u8 payload(const u8 *tsp)
 {
 	if (!(tsp[3] & 0x10))	// no payload?
@@ -1287,6 +1292,32 @@
 static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
 			const u8 *buf, const u8 timestamp[TIMESTAMP_LEN])
 {
+	u16 pid = ts_pid(buf);
+	u8 scrambling_bits = ts_scrambling_ctrl(buf);
+	struct dmx_data_ready dmx_data_ready;
+
+	/*
+	 * Notify on scrambling status change only when we move
+	 * from clear (0) to non-clear and vise-versa
+	 */
+	if ((scrambling_bits && !feed->scrambling_bits) ||
+		(!scrambling_bits && feed->scrambling_bits)) {
+		dmx_data_ready.status = DMX_OK_SCRAMBLING_STATUS;
+		dmx_data_ready.data_length = 0;
+		dmx_data_ready.scrambling_bits.pid = pid;
+		dmx_data_ready.scrambling_bits.old_value =
+			feed->scrambling_bits;
+		dmx_data_ready.scrambling_bits.new_value = scrambling_bits;
+
+		if (feed->type == DMX_TYPE_SEC)
+			feed->data_ready_cb.sec(&feed->filter->filter,
+					&dmx_data_ready);
+		else
+			feed->data_ready_cb.ts(&feed->feed.ts, &dmx_data_ready);
+	}
+
+	feed->scrambling_bits = scrambling_bits;
+
 	switch (feed->type) {
 	case DMX_TYPE_TS:
 		if (!feed->feed.ts.is_filtering)
@@ -2047,6 +2078,7 @@
 	}
 
 	feed->first_cc = 1;
+	feed->scrambling_bits = 0;
 
 	if ((feed->ts_type & TS_PACKET) &&
 		!(feed->ts_type & TS_PAYLOAD_ONLY)) {
@@ -2302,6 +2334,25 @@
 	return ret;
 }
 
+static int dvbdmx_ts_get_scrambling_bits(struct dmx_ts_feed *ts_feed,
+			u8 *value)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+
+	if (!ts_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return -EINVAL;
+	}
+
+	*value = feed->scrambling_bits;
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dvbdmx_ts_insertion_insert_buffer(struct dmx_ts_feed *ts_feed,
 			char *data, size_t size)
 {
@@ -2391,6 +2442,7 @@
 	(*ts_feed)->notify_data_read = NULL;
 	(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
 	(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
+	(*ts_feed)->get_scrambling_bits = dvbdmx_ts_get_scrambling_bits;
 	(*ts_feed)->ts_insertion_init = NULL;
 	(*ts_feed)->ts_insertion_terminate = NULL;
 	(*ts_feed)->ts_insertion_insert_buffer =
@@ -2557,6 +2609,7 @@
 	dvbdmxfeed->feed.sec.secbufp = 0;
 	dvbdmxfeed->feed.sec.seclen = 0;
 	dvbdmxfeed->first_cc = 1;
+	dvbdmxfeed->scrambling_bits = 0;
 
 	if (!dvbdmx->start_feed) {
 		mutex_unlock(&dvbdmx->mutex);
@@ -2723,6 +2776,25 @@
 	return ret;
 }
 
+static int dvbdmx_section_get_scrambling_bits(
+	struct dmx_section_feed *section_feed, u8 *value)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)section_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+
+	if (!section_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return -EINVAL;
+	}
+
+	*value = feed->scrambling_bits;
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
 					struct dmx_section_feed **feed,
 					dmx_section_cb callback)
@@ -2763,6 +2835,7 @@
 	(*feed)->notify_data_read = NULL;
 	(*feed)->set_secure_mode = dmx_section_set_secure_mode;
 	(*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
+	(*feed)->get_scrambling_bits = dvbdmx_section_get_scrambling_bits;
 
 	mutex_unlock(&dvbdmx->mutex);
 	return 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 879aad2..9fb1a12 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -187,6 +187,8 @@
 	int first_cc;
 	int pusi_seen;		/* prevents feeding of garbage from previous section */
 
+	u8 scrambling_bits;
+
 	struct dvb_demux_rec_info *rec_info;
 	u64 prev_tsp_num;
 	u64 prev_stc;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 59858b5..88f2f08 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -80,13 +80,20 @@
 }
 
 static uint32_t msm_isp_get_buf_handle(
-	struct msm_isp_buf_mgr *buf_mgr)
+	struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t session_id, uint32_t stream_id)
 {
 	int i;
 	if ((buf_mgr->buf_handle_cnt << 8) == 0)
 		buf_mgr->buf_handle_cnt++;
 
 	for (i = 0; i < buf_mgr->num_buf_q; i++) {
+		if (buf_mgr->bufq[i].session_id == session_id &&
+			buf_mgr->bufq[i].stream_id == stream_id)
+			return 0;
+	}
+
+	for (i = 0; i < buf_mgr->num_buf_q; i++) {
 		if (buf_mgr->bufq[i].bufq_handle == 0) {
 			memset(&buf_mgr->bufq[i],
 				0, sizeof(struct msm_isp_bufq));
@@ -604,7 +611,8 @@
 		return rc;
 	}
 
-	buf_request->handle = msm_isp_get_buf_handle(buf_mgr);
+	buf_request->handle = msm_isp_get_buf_handle(buf_mgr,
+		buf_request->session_id, buf_request->stream_id);
 	if (!buf_request->handle) {
 		pr_err("Invalid buffer handle\n");
 		return rc;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 7bc2b7d..6de6e74 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -38,6 +38,8 @@
 #define VFE_PING_FLAG 0xFFFFFFFF
 #define VFE_PONG_FLAG 0x0
 
+#define VFE_MAX_CFG_TIMEOUT 3000
+
 struct vfe_device;
 struct msm_vfe_axi_stream;
 struct msm_vfe_stats_stream;
@@ -88,7 +90,7 @@
 	void (*enable_wm) (struct vfe_device *vfe_dev,
 		uint8_t wm_idx, uint8_t enable);
 	void (*cfg_io_format) (struct vfe_device *vfe_dev,
-		struct msm_vfe_axi_stream_request_cmd *stream_req_cmd);
+		struct msm_vfe_axi_stream *stream_info);
 	void (*cfg_framedrop) (struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info);
 	void (*clear_framedrop) (struct vfe_device *vfe_dev,
@@ -103,13 +105,13 @@
 		struct msm_vfe_axi_stream *stream_info);
 
 	void (*cfg_wm_reg) (struct vfe_device *vfe_dev,
-		struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+		struct msm_vfe_axi_stream *stream_info,
 		uint8_t plane_idx);
 	void (*clear_wm_reg) (struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx);
 
 	void (*cfg_wm_xbar_reg) (struct vfe_device *vfe_dev,
-		struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+		struct msm_vfe_axi_stream *stream_info,
 		uint8_t plane_idx);
 	void (*clear_wm_xbar_reg) (struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx);
@@ -231,7 +233,8 @@
 	enum msm_vfe_axi_stream_src stream_src;
 	uint8_t num_planes;
 	uint8_t wm[MAX_PLANES_PER_STREAM];
-	uint32_t plane_offset[MAX_PLANES_PER_STREAM];
+	uint32_t output_format;/*Planar/RAW/Misc*/
+	struct msm_vfe_axi_plane_cfg plane_cfg[MAX_PLANES_PER_STREAM];
 	uint8_t comp_mask_index;
 	struct msm_isp_buffer *buf[2];
 	uint32_t session_id;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 679c5cb..3a94af3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -441,11 +441,11 @@
 }
 
 static void msm_vfe32_cfg_io_format(struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_req_cmd)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int bpp, bpp_reg = 0;
 	uint32_t io_format_reg;
-	bpp = msm_isp_get_bit_per_pixel(stream_req_cmd->output_format);
+	bpp = msm_isp_get_bit_per_pixel(stream_info->output_format);
 
 	switch (bpp) {
 	case 8:
@@ -459,7 +459,7 @@
 		break;
 	}
 	io_format_reg = msm_camera_io_r(vfe_dev->vfe_base + 0x6F8);
-	switch (stream_req_cmd->stream_src) {
+	switch (stream_info->stream_src) {
 	case CAMIF_RAW:
 		io_format_reg &= 0xFFFFCFFF;
 		io_format_reg |= bpp_reg << 12;
@@ -565,44 +565,40 @@
 
 static void msm_vfe32_axi_cfg_wm_reg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	struct msm_vfe_axi_stream *stream_info,
 	uint8_t plane_idx)
 {
 	uint32_t val;
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	uint32_t wm_base = VFE32_WM_BASE(stream_info->wm[plane_idx]);
 
 	if (!stream_info->frame_based) {
 		/*WR_IMAGE_SIZE*/
 		val =
 			((msm_isp_cal_word_per_line(
-			stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[plane_idx].
+			stream_info->output_format,
+			stream_info->plane_cfg[plane_idx].
 			output_width)+1)/2 - 1) << 16 |
-			(stream_cfg_cmd->plane_cfg[plane_idx].
+			(stream_info->plane_cfg[plane_idx].
 			output_height - 1);
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x10);
 
 		/*WR_BUFFER_CFG*/
 		val =
 			msm_isp_cal_word_per_line(
-			stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[plane_idx].
+			stream_info->output_format,
+			stream_info->plane_cfg[plane_idx].
 			output_stride) << 16 |
-			(stream_cfg_cmd->plane_cfg[plane_idx].
+			(stream_info->plane_cfg[plane_idx].
 			output_height - 1) << 4 | VFE32_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
 	} else {
 		msm_camera_io_w(0x2, vfe_dev->vfe_base + wm_base);
 		val =
 			msm_isp_cal_word_per_line(
-			stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[plane_idx].
+			stream_info->output_format,
+			stream_info->plane_cfg[plane_idx].
 			output_width) << 16 |
-			(stream_cfg_cmd->plane_cfg[plane_idx].
+			(stream_info->plane_cfg[plane_idx].
 			output_height - 1) << 4 | VFE32_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
 	}
@@ -624,19 +620,15 @@
 
 static void msm_vfe32_axi_cfg_wm_xbar_reg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
-	uint8_t plane_idx)
+	struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx)
 {
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	struct msm_vfe_axi_stream *stream_info =
-	 &axi_data->stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	struct msm_vfe_axi_plane_cfg *plane_cfg =
-		&stream_cfg_cmd->plane_cfg[plane_idx];
+		&stream_info->plane_cfg[plane_idx];
 	uint8_t wm = stream_info->wm[plane_idx];
 	uint32_t xbar_cfg = 0;
 	uint32_t xbar_reg_cfg = 0;
 
-	switch (stream_cfg_cmd->stream_src) {
+	switch (stream_info->stream_src) {
 	case PIX_ENCODER:
 	case PIX_VIEWFINDER: {
 		if (plane_cfg->output_plane_format != CRCB_PLANE &&
@@ -644,7 +636,7 @@
 			/*SINGLE_STREAM_SEL*/
 			xbar_cfg |= plane_cfg->output_plane_format << 5;
 		} else {
-			switch (stream_cfg_cmd->output_format) {
+			switch (stream_info->output_format) {
 			case V4L2_PIX_FMT_NV12:
 			case V4L2_PIX_FMT_NV16:
 				xbar_cfg |= 0x3 << 3; /*PAIR_STREAM_SWAP_CTRL*/
@@ -652,7 +644,7 @@
 			}
 			xbar_cfg |= BIT(1); /*PAIR_STREAM_EN*/
 		}
-		if (stream_cfg_cmd->stream_src == PIX_VIEWFINDER)
+		if (stream_info->stream_src == PIX_VIEWFINDER)
 			xbar_cfg |= 0x1; /*VIEW_STREAM_EN*/
 		break;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 94041ea..c4a1b63 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -523,14 +523,14 @@
 	comp_mask &= ~(0x7F << (comp_mask_index * 8));
 	comp_mask |= (axi_data->composite_info[comp_mask_index].
 		stream_composite_mask << (comp_mask_index * 8));
-	if (stream_info->plane_offset[0])
+	if (stream_info->plane_cfg[0].plane_addr_offset)
 		comp_mask |= (axi_data->composite_info[comp_mask_index].
 		stream_composite_mask << 24);
 	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x40);
 
 	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
 	irq_mask |= 1 << (comp_mask_index + 25);
-	if (stream_info->plane_offset[0] && (comp_mask >> 24))
+	if (stream_info->plane_cfg[0].plane_addr_offset && (comp_mask >> 24))
 		irq_mask |= BIT(28);
 	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
 }
@@ -544,14 +544,14 @@
 
 	comp_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x40);
 	comp_mask &= ~(0x7F << (comp_mask_index * 8));
-	if (stream_info->plane_offset[0])
+	if (stream_info->plane_cfg[0].plane_addr_offset)
 		comp_mask &= ~(axi_data->composite_info[comp_mask_index].
 		stream_composite_mask << 24);
 	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x40);
 
 	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
 	irq_mask &= ~(1 << (comp_mask_index + 25));
-	if (stream_info->plane_offset[0] && !(comp_mask >> 24))
+	if (stream_info->plane_cfg[0].plane_addr_offset && (comp_mask >> 24))
 		irq_mask &= ~BIT(28);
 	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
 }
@@ -614,11 +614,11 @@
 }
 
 static void msm_vfe40_cfg_io_format(struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_req_cmd)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int bpp, bpp_reg = 0;
 	uint32_t io_format_reg;
-	bpp = msm_isp_get_bit_per_pixel(stream_req_cmd->output_format);
+	bpp = msm_isp_get_bit_per_pixel(stream_info->output_format);
 
 	switch (bpp) {
 	case 8:
@@ -632,7 +632,7 @@
 		break;
 	}
 	io_format_reg = msm_camera_io_r(vfe_dev->vfe_base + 0x54);
-	switch (stream_req_cmd->stream_src) {
+	switch (stream_info->stream_src) {
 	case CAMIF_RAW:
 		io_format_reg &= 0xFFFFCFFF;
 		io_format_reg |= bpp_reg << 12;
@@ -753,43 +753,39 @@
 
 static void msm_vfe40_axi_cfg_wm_reg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	struct msm_vfe_axi_stream *stream_info,
 	uint8_t plane_idx)
 {
 	uint32_t val;
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	uint32_t wm_base = VFE40_WM_BASE(stream_info->wm[plane_idx]);
 
 	if (!stream_info->frame_based) {
 		/*WR_IMAGE_SIZE*/
 		val =
 			((msm_isp_cal_word_per_line(
-				stream_cfg_cmd->output_format,
-				stream_cfg_cmd->plane_cfg[plane_idx].
+				stream_info->output_format,
+				stream_info->plane_cfg[plane_idx].
 				output_width)+1)/2 - 1) << 16 |
-				(stream_cfg_cmd->plane_cfg[plane_idx].
+				(stream_info->plane_cfg[plane_idx].
 				output_height - 1);
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
 
 		/*WR_BUFFER_CFG*/
 		val =
-			msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[
+			msm_isp_cal_word_per_line(stream_info->output_format,
+			stream_info->plane_cfg[
 				plane_idx].output_stride) << 16 |
-			(stream_cfg_cmd->plane_cfg[
+			(stream_info->plane_cfg[
 				plane_idx].output_height - 1) << 4 |
 			VFE40_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x18);
 	} else {
 		msm_camera_io_w(0x2, vfe_dev->vfe_base + wm_base);
 		val =
-			msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[
+			msm_isp_cal_word_per_line(stream_info->output_format,
+			stream_info->plane_cfg[
 				plane_idx].output_width) << 16 |
-			(stream_cfg_cmd->plane_cfg[
+			(stream_info->plane_cfg[
 				plane_idx].output_height - 1) << 4 |
 			VFE40_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x18);
@@ -821,20 +817,16 @@
 
 static void msm_vfe40_axi_cfg_wm_xbar_reg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	struct msm_vfe_axi_stream *stream_info,
 	uint8_t plane_idx)
 {
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	struct msm_vfe_axi_plane_cfg *plane_cfg =
-		&stream_cfg_cmd->plane_cfg[plane_idx];
+		&stream_info->plane_cfg[plane_idx];
 	uint8_t wm = stream_info->wm[plane_idx];
 	uint32_t xbar_cfg = 0;
 	uint32_t xbar_reg_cfg = 0;
 
-	switch (stream_cfg_cmd->stream_src) {
+	switch (stream_info->stream_src) {
 	case PIX_ENCODER:
 	case PIX_VIEWFINDER: {
 		if (plane_cfg->output_plane_format != CRCB_PLANE &&
@@ -842,7 +834,7 @@
 			/*SINGLE_STREAM_SEL*/
 			xbar_cfg |= plane_cfg->output_plane_format << 8;
 		} else {
-			switch (stream_cfg_cmd->output_format) {
+			switch (stream_info->output_format) {
 			case V4L2_PIX_FMT_NV12:
 			case V4L2_PIX_FMT_NV16:
 				xbar_cfg |= 0x3 << 4; /*PAIR_STREAM_SWAP_CTRL*/
@@ -850,7 +842,7 @@
 			}
 			xbar_cfg |= 0x1 << 1; /*PAIR_STREAM_EN*/
 		}
-		if (stream_cfg_cmd->stream_src == PIX_VIEWFINDER)
+		if (stream_info->stream_src == PIX_VIEWFINDER)
 			xbar_cfg |= 0x1; /*VIEW_STREAM_EN*/
 		break;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 13160ee..e3d036f6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -136,23 +136,23 @@
 	}
 
 	for (i = 0; i < stream_info->num_planes; i++) {
-		stream_info->plane_offset[i] =
-			stream_cfg_cmd->plane_cfg[i].plane_addr_offset;
+		stream_info->plane_cfg[i] = stream_cfg_cmd->plane_cfg[i];
 		stream_info->max_width = max(stream_info->max_width,
 			stream_cfg_cmd->plane_cfg[i].output_width);
 	}
 
+	stream_info->output_format = stream_cfg_cmd->output_format;
 	stream_info->stream_src = stream_cfg_cmd->stream_src;
 	stream_info->frame_based = stream_cfg_cmd->frame_base;
 	return 0;
 }
 
 static uint32_t msm_isp_axi_get_plane_size(
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd, int plane_idx)
+	struct msm_vfe_axi_stream *stream_info, int plane_idx)
 {
 	uint32_t size = 0;
-	struct msm_vfe_axi_plane_cfg *plane_cfg = stream_cfg_cmd->plane_cfg;
-	switch (stream_cfg_cmd->output_format) {
+	struct msm_vfe_axi_plane_cfg *plane_cfg = stream_info->plane_cfg;
+	switch (stream_info->output_format) {
 	case V4L2_PIX_FMT_SBGGR8:
 	case V4L2_PIX_FMT_SGBRG8:
 	case V4L2_PIX_FMT_SGRBG8:
@@ -211,21 +211,17 @@
 }
 
 void msm_isp_axi_reserve_wm(struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int i, j;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
-
 	for (i = 0; i < stream_info->num_planes; i++) {
 		for (j = 0; j < axi_data->hw_info->num_wm; j++) {
 			if (!axi_data->free_wm[j]) {
 				axi_data->free_wm[j] =
-					stream_cfg_cmd->axi_stream_handle;
+					stream_info->stream_handle;
 				axi_data->wm_image_size[j] =
 					msm_isp_axi_get_plane_size(
-						stream_cfg_cmd, i);
+						stream_info, i);
 				axi_data->num_used_wm++;
 				break;
 			}
@@ -246,20 +242,17 @@
 
 void msm_isp_axi_reserve_comp_mask(
 	struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int i;
 	uint8_t comp_mask = 0;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
 	for (i = 0; i < stream_info->num_planes; i++)
 		comp_mask |= 1 << stream_info->wm[i];
 
 	for (i = 0; i < axi_data->hw_info->num_comp_mask; i++) {
 		if (!axi_data->composite_info[i].stream_handle) {
 			axi_data->composite_info[i].stream_handle =
-			stream_cfg_cmd->axi_stream_handle;
+				stream_info->stream_handle;
 			axi_data->composite_info[i].
 				stream_composite_mask = comp_mask;
 			axi_data->num_used_composite_mask++;
@@ -384,7 +377,7 @@
 		break;
 	}
 
-	sof_event.frame_id = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
+	sof_event.frame_id = vfe_dev->axi_data.src_info[frame_src].frame_id;
 	sof_event.timestamp = ts->event_time;
 	msm_isp_send_event(vfe_dev, ISP_EVENT_SOF, &sof_event);
 }
@@ -471,18 +464,18 @@
 
 	stream_info = &vfe_dev->axi_data.
 		stream_info[HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
-	msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_cfg_cmd);
+	msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_info);
 
 	if (stream_cfg_cmd->stream_src == CAMIF_RAW ||
 		stream_cfg_cmd->stream_src == IDEAL_RAW)
 			vfe_dev->hw_info->vfe_ops.axi_ops.
-				cfg_io_format(vfe_dev, stream_cfg_cmd);
+				cfg_io_format(vfe_dev, stream_info);
 
 	msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);
 
 	if (stream_info->num_planes > 1) {
 		msm_isp_axi_reserve_comp_mask(
-			&vfe_dev->axi_data, stream_cfg_cmd);
+			&vfe_dev->axi_data, stream_info);
 		vfe_dev->hw_info->vfe_ops.axi_ops.
 		cfg_comp_mask(vfe_dev, stream_info);
 	} else {
@@ -492,10 +485,10 @@
 
 	for (i = 0; i < stream_info->num_planes; i++) {
 		vfe_dev->hw_info->vfe_ops.axi_ops.
-			cfg_wm_reg(vfe_dev, stream_cfg_cmd, i);
+			cfg_wm_reg(vfe_dev, stream_info, i);
 
 		vfe_dev->hw_info->vfe_ops.axi_ops.
-			cfg_wm_xbar_reg(vfe_dev, stream_cfg_cmd, i);
+			cfg_wm_xbar_reg(vfe_dev, stream_info, i);
 	}
 	return rc;
 }
@@ -610,7 +603,7 @@
 		vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
 			vfe_dev, stream_info->wm[i],
 			VFE_PONG_FLAG, buf->mapped_info[i].paddr +
-			stream_info->plane_offset[i]);
+			stream_info->plane_cfg[i].plane_addr_offset);
 	stream_info->buf[1] = buf;
 }
 
@@ -657,7 +650,7 @@
 		vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
 			vfe_dev, stream_info->wm[i],
 			pingpong_status, buf->mapped_info[i].paddr +
-			stream_info->plane_offset[i]);
+			stream_info->plane_cfg[i].plane_addr_offset);
 
 	pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1);
 	stream_info->buf[pingpong_bit] = buf;
@@ -852,7 +845,7 @@
 	spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
 	rc = wait_for_completion_interruptible_timeout(
 		&vfe_dev->stream_config_complete,
-		msecs_to_jiffies(500));
+		msecs_to_jiffies(VFE_MAX_CFG_TIMEOUT));
 	if (rc == 0) {
 		pr_err("%s: wait timeout\n", __func__);
 		rc = -1;
@@ -976,18 +969,33 @@
 			enum msm_isp_camif_update_state camif_update)
 {
 	int i, rc = 0;
+	uint8_t wait_for_complete = 0;
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		stream_info = &axi_data->stream_info[
 			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+
 		stream_info->state = STOP_PENDING;
+		if (stream_info->stream_type == BURST_STREAM &&
+			stream_info->runtime_num_burst_capture == 0) {
+			/*Configure AXI writemasters to stop immediately
+			 *since for burst case, write masters already skip
+			 *all frames.
+			 */
+			msm_isp_axi_stream_enable_cfg(vfe_dev, stream_info);
+			stream_info->state = INACTIVE;
+		} else {
+			wait_for_complete = 1;
+		}
 	}
 
-	rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
-	if (rc < 0) {
-		pr_err("%s: wait for config done failed\n", __func__);
-		return rc;
+	if (wait_for_complete) {
+		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
+		if (rc < 0) {
+			pr_err("%s: wait for config done failed\n", __func__);
+			return rc;
+		}
 	}
 	msm_isp_update_stream_bandwidth(vfe_dev);
 	if (camif_update == DISABLE_CAMIF)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index f592a60..3d775f9 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -27,15 +27,11 @@
 
 void msm_isp_axi_reserve_wm(
 	struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
-
-void msm_isp_axi_reserve_rdi(
-	struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+	struct msm_vfe_axi_stream *stream_info);
 
 void msm_isp_axi_reserve_comp_mask(
 	struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+	struct msm_vfe_axi_stream *stream_info);
 
 int msm_isp_axi_check_stream_state(
 	struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index ce71235..d857a14 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -343,7 +343,7 @@
 	atomic_set(&vfe_dev->stats_data.stats_update, 2);
 	rc = wait_for_completion_interruptible_timeout(
 		&vfe_dev->stats_config_complete,
-		msecs_to_jiffies(500));
+		msecs_to_jiffies(VFE_MAX_CFG_TIMEOUT));
 	if (rc == 0) {
 		pr_err("%s: wait timeout\n", __func__);
 		rc = -1;
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index f837a06..c30f46f 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -31,6 +31,7 @@
 #include <linux/kthread.h>
 #include <linux/wait.h>
 #include <linux/uaccess.h>
+#include <linux/mfd/pm8xxx/misc.h>
 
 #include <mach/msm_smd.h>
 #include <mach/msm_iomap.h>
@@ -133,6 +134,21 @@
 	unsigned char  revision;
 };
 
+struct wcnss_pmic_dump {
+	char reg_name[10];
+	u16 reg_addr;
+};
+
+static struct wcnss_pmic_dump wcnss_pmic_reg_dump[] = {
+	{"S2", 0x1D8},
+	{"L4", 0xB4},
+	{"L10", 0xC0},
+	{"LVS2", 0x62},
+	{"S4", 0x1E8},
+	{"LVS7", 0x06C},
+	{"LVS1", 0x060},
+};
+
 #define NVBIN_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin"
 
 /*
@@ -342,6 +358,25 @@
 static DEVICE_ATTR(wcnss_version, S_IRUSR,
 		wcnss_version_show, NULL);
 
+void wcnss_riva_dump_pmic_regs(void)
+{
+	int i, rc;
+	u8  val;
+
+	for (i = 0; i < ARRAY_SIZE(wcnss_pmic_reg_dump); i++) {
+		val = 0;
+		rc = pm8xxx_read_register(wcnss_pmic_reg_dump[i].reg_addr,
+				&val);
+		if (rc)
+			pr_err("PMIC READ: Failed to read addr = %d\n",
+					wcnss_pmic_reg_dump[i].reg_addr);
+		else
+			pr_info_ratelimited("PMIC READ: %s addr = %x, value = %x\n",
+				wcnss_pmic_reg_dump[i].reg_name,
+				wcnss_pmic_reg_dump[i].reg_addr, val);
+	}
+}
+
 /* wcnss_reset_intr() is invoked when host drivers fails to
  * communicate with WCNSS over SMD; so logging these registers
  * helps to know WCNSS failure reason
@@ -366,6 +401,7 @@
 	ccu_reg = penv->riva_ccu_base + CCU_RIVA_LAST_ADDR2_OFFSET;
 	reg = readl_relaxed(ccu_reg);
 	pr_info_ratelimited("%s: CCU_CCPU_LAST_ADDR2 %08x\n", __func__, reg);
+	wcnss_riva_dump_pmic_regs();
 
 }
 EXPORT_SYMBOL(wcnss_riva_log_debug_regs);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 64e8d7a..fc85dba 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -129,15 +129,40 @@
 	[HSIC_BAM]  = hsic_cons_release_resource,
 };
 
-static enum ipa_rm_event cur_prod_state[MAX_BAMS];
-static enum ipa_rm_event cur_cons_state[MAX_BAMS];
-static int sched_lpm;
-static int lpm_wait_handshake;
-static struct completion prod_avail[MAX_BAMS];
-static struct completion cons_avail[MAX_BAMS];
-static struct completion cons_released[MAX_BAMS];
-static struct completion prod_released[MAX_BAMS];
+struct usb_bam_ipa_handshake_info {
+	enum ipa_rm_event cur_prod_state[MAX_BAMS];
+	enum ipa_rm_event cur_cons_state[MAX_BAMS];
 
+	int lpm_wait_handshake;
+	int connect_complete;
+	bool lpm_wait_pipes;
+	int bus_suspend;
+	bool in_lpm;
+
+	int (*wake_cb)(void *);
+	void *wake_param;
+	void (*start)(void *, enum usb_bam_pipe_dir);
+	void (*stop)(void *, enum usb_bam_pipe_dir);
+	void *start_stop_param;
+
+	u32 src_idx;
+	u32 dst_idx;
+	bool cons_stopped;
+	bool prod_stopped;
+
+	struct completion prod_avail[MAX_BAMS];
+	struct completion cons_avail[MAX_BAMS];
+	struct completion cons_released[MAX_BAMS];
+	struct completion prod_released[MAX_BAMS];
+
+	struct mutex suspend_resume_mutex;
+	struct work_struct resume_work;
+	struct work_struct suspend_work;
+	struct work_struct finish_suspend_work;
+};
+
+static spinlock_t usb_bam_ipa_handshake_info_lock;
+static struct usb_bam_ipa_handshake_info info;
 static spinlock_t usb_bam_peer_handshake_info_lock;
 static struct usb_bam_peer_handshake_info peer_handshake_info;
 static spinlock_t usb_bam_lock; /* Protect ctx and usb_bam_connections */
@@ -457,6 +482,7 @@
 		pr_err("%s: ipa_connect failed\n", __func__);
 		return ret;
 	}
+	pipe_connect->ipa_clnt_hdl = clnt_hdl;
 
 	*pipe = sps_alloc_endpoint();
 	if (*pipe == NULL) {
@@ -579,6 +605,31 @@
 	return 0;
 }
 
+static void usb_bam_resume_core(enum usb_bam cur_bam)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+
+	if (cur_bam != HSUSB_BAM)
+		return;
+	BUG_ON(trans == NULL);
+	pr_debug("%s: resume core", __func__);
+	pm_runtime_resume(trans->dev);
+}
+
+static void usb_bam_start_lpm(bool disconnect)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+	BUG_ON(trans == NULL);
+		pr_debug("%s: Going to LPM\n", __func__);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.lpm_wait_handshake = false;
+		info.lpm_wait_pipes = 0;
+	if (disconnect)
+		pm_runtime_put_noidle(trans->dev);
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	pm_runtime_suspend(trans->dev);
+}
+
 int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
 {
 	int ret;
@@ -608,26 +659,136 @@
 	}
 
 	spin_lock(&usb_bam_lock);
-
 	/* Check if BAM requires RESET before connect and reset of first pipe */
 	if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
 	    (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
 		sps_device_reset(ctx.h_bam[pipe_connect->bam_type]);
+	spin_unlock(&usb_bam_lock);
 
 	ret = connect_pipe(idx, bam_pipe_idx);
 	if (ret) {
 		pr_err("%s: pipe connection[%d] failure\n", __func__, idx);
-		spin_unlock(&usb_bam_lock);
 		return ret;
 	}
 
 	pipe_connect->enabled = 1;
+	spin_lock(&usb_bam_lock);
 	ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
-
 	spin_unlock(&usb_bam_lock);
+
 	return 0;
 }
 
+static int ipa_suspend_pipes(void)
+{
+	struct usb_bam_pipe_connect *dst_pipe_connect, *src_pipe_connect;
+	int ret1, ret2;
+
+	dst_pipe_connect = &usb_bam_connections[info.dst_idx];
+	src_pipe_connect = &usb_bam_connections[info.src_idx];
+
+	if (dst_pipe_connect->ipa_clnt_hdl == -1 ||
+		src_pipe_connect->ipa_clnt_hdl == -1) {
+		pr_err("%s: One of handles is -1, not connected?", __func__);
+	}
+
+	ret1 = ipa_suspend(dst_pipe_connect->ipa_clnt_hdl);
+	if (ret1)
+		pr_err("%s: ipa_suspend on dst failed with %d", __func__, ret1);
+	ret2 = ipa_suspend(src_pipe_connect->ipa_clnt_hdl);
+	if (ret2)
+		pr_err("%s: ipa_suspend on src failed with %d", __func__, ret2);
+
+	return ret1 | ret2;
+}
+
+static int ipa_resume_pipes(void)
+{
+	struct usb_bam_pipe_connect *dst_pipe_connect, *src_pipe_connect;
+	int ret1, ret2;
+
+	src_pipe_connect = &usb_bam_connections[info.src_idx];
+	dst_pipe_connect = &usb_bam_connections[info.dst_idx];
+
+	if (dst_pipe_connect->ipa_clnt_hdl == -1 ||
+		src_pipe_connect->ipa_clnt_hdl == -1) {
+		pr_err("%s: One of handles is -1, not connected?", __func__);
+	}
+
+	ret1 = ipa_resume(dst_pipe_connect->ipa_clnt_hdl);
+	if (ret1)
+		pr_err("%s: ipa_resume on dst failed with %d", __func__, ret1);
+	ret2 = ipa_resume(src_pipe_connect->ipa_clnt_hdl);
+	if (ret2)
+		pr_err("%s: ipa_resume on src failed with %d", __func__, ret2);
+
+	return ret1 | ret2;
+}
+
+static void usb_bam_finish_suspend(void)
+{
+	int ret;
+	u32 cons_empty;
+	struct sps_pipe *cons_pipe = ctx.usb_bam_sps.sps_pipes[info.dst_idx];
+	struct usb_bam_pipe_connect *pipe_connect = &
+			usb_bam_connections[info.dst_idx];
+	enum usb_bam cur_bam = pipe_connect->bam_type;
+
+	if (cur_bam != HSUSB_BAM) {
+		pr_err("%s: Wrong type of BAM=%s\n", __func__,
+			bam_enable_strings[cur_bam]);
+		return;
+	}
+
+	mutex_lock(&info.suspend_resume_mutex);
+
+	/* If resume was called don't finish this work */
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (!info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Bus suspend in progress\n", __func__);
+		goto no_lpm;
+	}
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	ret = sps_is_pipe_empty(cons_pipe, &cons_empty);
+	if (ret) {
+		pr_err("%s: sps_is_pipe_empty failed with %d\n", __func__, ret);
+		goto no_lpm;
+	}
+
+	/* Stop CONS transfers and go to lpm if no more data in the pipe */
+	if (cons_empty) {
+		if (info.stop && !info.cons_stopped)
+			info.stop(info.start_stop_param,
+					PEER_PERIPHERAL_TO_USB);
+		pr_err("%s: Starting LPM on Bus Suspend\n", __func__);
+		info.cons_stopped = 1;
+		if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED) {
+			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
+				ipa_rm_resource_cons[cur_bam]);
+		}
+		ipa_suspend_pipes();
+		mutex_unlock(&info.suspend_resume_mutex);
+		usb_bam_start_lpm(0);
+		return;
+	}
+
+no_lpm:
+
+	/* Finish the handshake. Resume Sequence will start automatically
+	   by the data in the pipes */
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
+				ipa_rm_resource_cons[cur_bam]);
+	mutex_unlock(&info.suspend_resume_mutex);
+}
+
+void usb_bam_finish_suspend_(struct work_struct *w)
+{
+	usb_bam_finish_suspend();
+}
+
 static void usb_prod_notify_cb(void *user_data, enum ipa_rm_event event,
 	unsigned long data)
 {
@@ -637,14 +798,14 @@
 	case IPA_RM_RESOURCE_GRANTED:
 		pr_debug("%s: %s_PROD resource granted\n",
 			__func__, bam_enable_strings[*cur_bam]);
-		cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_GRANTED;
-		complete_all(&prod_avail[*cur_bam]);
+		info.cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_GRANTED;
+		complete_all(&info.prod_avail[*cur_bam]);
 		break;
 	case IPA_RM_RESOURCE_RELEASED:
 		pr_debug("%s: %s_PROD resource released\n",
 			__func__, bam_enable_strings[*cur_bam]);
-		cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_RELEASED;
-		complete_all(&prod_released[*cur_bam]);
+		info.cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_RELEASED;
+		complete_all(&info.prod_released[*cur_bam]);
 		break;
 	default:
 		break;
@@ -657,12 +818,33 @@
 	pr_debug("%s: Request %s_CONS resource\n",
 			__func__, bam_enable_strings[cur_bam]);
 
-	cur_cons_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
-	complete_all(&cons_avail[cur_bam]);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.cur_cons_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
+	complete_all(&info.cons_avail[cur_bam]);
 
-	if (ctx.pipes_enabled_per_bam[cur_bam])
+	spin_lock(&usb_bam_lock);
+	if (ctx.pipes_enabled_per_bam[cur_bam] && info.connect_complete &&
+				!info.bus_suspend && !info.prod_stopped) {
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_debug("%s: ACK on cons_request", __func__);
 		return 0;
+	}
 
+	/* A2 wakeup from LPM */
+	if (cur_bam == HSUSB_BAM && ctx.pipes_enabled_per_bam[cur_bam] &&
+		info.connect_complete && info.bus_suspend) {
+		info.bus_suspend = 0;
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		if (info.wake_cb)
+			info.wake_cb(info.wake_param);
+	} else {
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+
+	pr_debug("%s: EINPROGRESS on cons_request", __func__);
 	return -EINPROGRESS;
 }
 
@@ -681,12 +863,23 @@
 	pr_debug("%s: Release %s_CONS resource\n",
 			__func__, bam_enable_strings[cur_bam]);
 
-	cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
-	complete_all(&cons_released[cur_bam]);
+	info.cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
+	complete_all(&info.cons_released[cur_bam]);
 
-	if (!ctx.pipes_enabled_per_bam[cur_bam])
+	spin_lock(&usb_bam_lock);
+	if (!ctx.pipes_enabled_per_bam[cur_bam]) {
+		spin_unlock(&usb_bam_lock);
+		pr_debug("%s: ACK on cons_release", __func__);
 		return 0;
+	}
+	spin_unlock(&usb_bam_lock);
 
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (cur_bam == HSUSB_BAM && info.bus_suspend)
+		queue_work(ctx.usb_bam_wq, &info.finish_suspend_work);
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	pr_debug("%s: EINPROGRESS cons_release", __func__);
 	return -EINPROGRESS;
 }
 
@@ -747,24 +940,24 @@
 
 	pr_debug("%s Request %s_PROD_RES\n", __func__,
 		bam_enable_strings[cur_bam]);
-	if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
 		pr_debug("%s: CONS already granted for some reason\n",
 			__func__);
-	if (cur_prod_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
+	if (info.cur_prod_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
 		pr_debug("%s: PROD already granted for some reason\n",
 			__func__);
 
-	init_completion(&prod_avail[cur_bam]);
-	init_completion(&cons_avail[cur_bam]);
+	init_completion(&info.prod_avail[cur_bam]);
+	init_completion(&info.cons_avail[cur_bam]);
 
 	ret = ipa_rm_request_resource(ipa_rm_resource_prod[cur_bam]);
 	if (!ret) {
-		cur_prod_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
-		complete_all(&prod_avail[cur_bam]);
+		info.cur_prod_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
+		complete_all(&info.prod_avail[cur_bam]);
 		pr_debug("%s: PROD_GRANTED without wait\n", __func__);
 	} else if (ret == -EINPROGRESS) {
 		pr_debug("%s: Waiting for PROD_GRANTED\n", __func__);
-		if (!wait_for_completion_timeout(&prod_avail[cur_bam],
+		if (!wait_for_completion_timeout(&info.prod_avail[cur_bam],
 			USB_BAM_TIMEOUT))
 			pr_err("%s: Timeout wainting for PROD_GRANTED\n",
 				__func__);
@@ -772,6 +965,261 @@
 		pr_err("%s: ipa_rm_request_resource ret =%d\n", __func__, ret);
 }
 
+void wait_for_cons_granted(enum usb_bam cur_bam)
+{
+	pr_debug("%s: Waiting for CONS\n", __func__);
+	if (info.cur_cons_state[cur_bam] != IPA_RM_RESOURCE_GRANTED) {
+		if (!wait_for_completion_timeout(&info.cons_avail[cur_bam],
+						USB_BAM_TIMEOUT*6))
+			pr_err("%s: Timeout wainting for CONS_REQUEST\n",
+			__func__);
+		pr_err("%s: Finished waiting for CONS\n", __func__);
+	}
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.connect_complete = 1;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	pr_debug("%s: CONS is granted\n", __func__);
+
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_GRANTED) {
+		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
+				 ipa_rm_resource_cons[HSUSB_BAM]);
+	}
+}
+
+void usb_bam_wait_for_cons_granted(
+	struct usb_bam_connect_ipa_params *ipa_params)
+{
+	struct usb_bam_pipe_connect *pipe_connect;
+	enum usb_bam cur_bam;
+	u8 src_idx;
+
+	src_idx = ipa_params->src_idx;
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+
+	wait_for_cons_granted(cur_bam);
+}
+
+static void wait_for_prod_release(enum usb_bam cur_bam)
+{
+	int ret;
+
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pr_debug("%s consumer already released\n", __func__);
+	 if (info.cur_prod_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pr_debug("%s producer already released\n", __func__);
+
+	init_completion(&info.prod_released[cur_bam]);
+	init_completion(&info.cons_released[cur_bam]);
+	pr_debug("%s: Releasing %s_PROD\n", __func__,
+				bam_enable_strings[cur_bam]);
+	ret = ipa_rm_release_resource(ipa_rm_resource_prod[cur_bam]);
+	if (!ret) {
+		pr_debug("%s: Released without waiting\n", __func__);
+		info.cur_prod_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
+		complete_all(&info.prod_released[cur_bam]);
+	} else if (ret == -EINPROGRESS) {
+		pr_debug("%s: Waiting for PROD_RELEASED\n", __func__);
+		if (!wait_for_completion_timeout(&info.prod_released[cur_bam],
+						USB_BAM_TIMEOUT))
+			pr_err("%s: Timeout waiting for PROD_RELEASED\n",
+			__func__);
+	} else
+		pr_err("%s: ipa_rm_request_resource ret =%d", __func__, ret);
+}
+
+static int check_pipes_empty(u8 src_idx, u8 dst_idx)
+{
+	struct sps_pipe *prod_pipe, *cons_pipe;
+	u32 prod_empty, cons_empty;
+
+	/* If we have any remaints in the pipes we don't go to sleep */
+	prod_pipe = ctx.usb_bam_sps.sps_pipes[src_idx];
+	cons_pipe = ctx.usb_bam_sps.sps_pipes[dst_idx];
+	if (sps_is_pipe_empty(prod_pipe, &prod_empty) ||
+			sps_is_pipe_empty(cons_pipe, &cons_empty)) {
+		pr_err("%s: sps_is_pipe_empty failed with\n", __func__);
+		return 0;
+	}
+	if (!prod_empty || !cons_empty) {
+		pr_err("%s: pipes not empty prod=%d cond=%d", __func__,
+			prod_empty, cons_empty);
+		return 0;
+	}
+
+	return 1;
+}
+
+void usb_bam_suspend(struct usb_bam_connect_ipa_params *ipa_params)
+{
+	struct usb_bam_pipe_connect *pipe_connect;
+	enum usb_bam cur_bam;
+	u8 src_idx, dst_idx;
+
+	if (!ipa_params) {
+		pr_err("%s: Invalid ipa params\n", __func__);
+		return;
+	}
+
+	src_idx = ipa_params->src_idx;
+	dst_idx = ipa_params->dst_idx;
+
+	if (src_idx >= ctx.max_connections || dst_idx >= ctx.max_connections) {
+		pr_err("%s: Invalid connection index src=%d dst=%d\n",
+			__func__, src_idx, dst_idx);
+	}
+
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+	if (cur_bam != HSUSB_BAM)
+		return;
+
+	info.src_idx = src_idx;
+	info.dst_idx = dst_idx;
+
+	pr_err("%s: Starting suspend sequence(BAM=%s)\n", __func__,
+			bam_enable_strings[cur_bam]);
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.bus_suspend = 1;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	/* Stop PROD transfers */
+	if (info.stop) {
+		spin_lock(&usb_bam_ipa_handshake_info_lock);
+		info.stop(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = true;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+
+	/* Don't go to LPM if data in the pipes */
+	if (!check_pipes_empty(src_idx, dst_idx)) {
+		pr_err("%s: pipes not empty, won't start suspend", __func__);
+		return;
+	}
+
+	queue_work(ctx.usb_bam_wq, &info.suspend_work);
+}
+
+static void usb_bam_start_suspend(struct work_struct *w)
+{
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (!info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Resume started, not suspending", __func__);
+		return;
+	}
+
+	/* Stop PROD transfers in case they were started */
+	if (info.stop && !info.prod_stopped) {
+		info.stop(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = true;
+	}
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	/* Don't start LPM seq if data in the pipes */
+	if (!check_pipes_empty(info.src_idx, info.dst_idx)) {
+		mutex_unlock(&info.suspend_resume_mutex);
+		return;
+	}
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.lpm_wait_handshake = true;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	wait_for_prod_release(HSUSB_BAM);
+
+	mutex_unlock(&info.suspend_resume_mutex);
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_RELEASED)
+		usb_bam_finish_suspend();
+	else
+		pr_debug("Consumer not released yet\n");
+}
+
+static void usb_bam_finish_resume(struct work_struct *w)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+
+	BUG_ON(trans == NULL);
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+	/* Suspend happened in the meantime */
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Bus suspended, not resuming", __func__);
+		mutex_unlock(&info.suspend_resume_mutex);
+		return;
+	}
+	info.lpm_wait_handshake = true;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	wait_for_prod_granted(HSUSB_BAM);
+	wait_for_cons_granted(HSUSB_BAM);
+	if (info.cons_stopped) {
+		ipa_resume_pipes();
+		if (info.start) {
+			pr_debug("%s: Enqueue CONS transfer", __func__);
+			info.start(info.start_stop_param,
+				PEER_PERIPHERAL_TO_USB);
+			info.cons_stopped = 0;
+		}
+	}
+
+	if (info.start) {
+		spin_lock(&usb_bam_ipa_handshake_info_lock);
+		info.start(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = false;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_GRANTED) {
+		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
+				 ipa_rm_resource_cons[HSUSB_BAM]);
+	}
+	mutex_unlock(&info.suspend_resume_mutex);
+	pr_debug("%s: done", __func__);
+}
+
+void usb_bam_resume(struct usb_bam_connect_ipa_params *ipa_params)
+{
+	enum usb_bam cur_bam;
+	u8 src_idx, dst_idx;
+	struct usb_bam_pipe_connect *pipe_connect;
+
+	pr_debug("%s: Resuming\n", __func__);
+
+	if (!ipa_params) {
+		pr_err("%s: Invalid ipa params\n", __func__);
+		return;
+	}
+
+	src_idx = ipa_params->src_idx;
+	dst_idx = ipa_params->dst_idx;
+
+	if (src_idx >= ctx.max_connections || dst_idx >= ctx.max_connections) {
+		pr_err("%s: Invalid connection index src=%d dst=%d\n",
+			__func__, src_idx, dst_idx);
+		return;
+	}
+
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+	if (cur_bam != HSUSB_BAM)
+		return;
+
+	info.in_lpm = false;
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.bus_suspend = 0;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	queue_work(ctx.usb_bam_wq, &info.resume_work);
+}
+
 int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	u8 idx;
@@ -800,27 +1248,38 @@
 	pipe_connect = &usb_bam_connections[idx];
 	cur_bam = pipe_connect->bam_type;
 
-	if (cur_bam == HSUSB_BAM) {
-		spin_lock(&usb_bam_lock);
-		sched_lpm = 0;
-		lpm_wait_handshake = 1;
-		spin_unlock(&usb_bam_lock);
-	}
-
 	if (pipe_connect->enabled) {
-		pr_debug("%s: connection %d was already established\n",
+		pr_err("%s: connection %d was already established\n",
 			__func__, idx);
 		return 0;
 	}
 
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+
 	spin_lock(&usb_bam_lock);
+	if (ctx.pipes_enabled_per_bam[cur_bam] == 0) {
+		spin_unlock(&usb_bam_lock);
+		if (cur_bam == HSUSB_BAM) {
+			spin_lock(&usb_bam_ipa_handshake_info_lock);
+			info.lpm_wait_handshake = 1;
+			info.connect_complete = 0;
+			info.lpm_wait_pipes = 1;
+			info.bus_suspend = 0;
+			info.cons_stopped = 0;
+			info.prod_stopped = 0;
+			spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		}
+		usb_bam_resume_core(cur_bam);
+	} else
+		spin_unlock(&usb_bam_lock);
 
 	 /* Check if BAM requires RESET before connect and reset first pipe */
+	 spin_lock(&usb_bam_lock);
 	 if ((pdata->reset_on_connect[cur_bam] == true) &&
 		 (ctx.pipes_enabled_per_bam[cur_bam] == 0))
 			sps_device_reset(ctx.h_bam[cur_bam]);
-
-	spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_lock);
 
 	if (ipa_params->dir == USB_TO_PEER_PERIPHERAL) {
 		pr_debug("%s: Starting connect sequence\n", __func__);
@@ -830,23 +1289,19 @@
 	ret = connect_pipe_ipa(idx, ipa_params);
 	if (ret) {
 		pr_err("%s: pipe connection failure\n", __func__);
+		mutex_unlock(&info.suspend_resume_mutex);
 		return ret;
 	}
 
 	spin_lock(&usb_bam_lock);
-
 	pipe_connect->enabled = 1;
 	ctx.pipes_enabled_per_bam[cur_bam] += 1;
-
-	if (ipa_params->dir == PEER_PERIPHERAL_TO_USB &&
-		cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED) {
-		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
-		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
-					 ipa_rm_resource_cons[cur_bam]);
-		pr_debug("%s: Ended connect sequence\n", __func__);
-	}
-
 	spin_unlock(&usb_bam_lock);
+	if (ipa_params->dir == PEER_PERIPHERAL_TO_USB && cur_bam == HSUSB_BAM)
+		wait_for_cons_granted(cur_bam);
+
+	mutex_unlock(&info.suspend_resume_mutex);
+	pr_debug("%s: done", __func__);
 
 	return 0;
 }
@@ -904,6 +1359,14 @@
 			usb_bam_set_inactivity_timer(pipe_connect->bam_type);
 		spin_unlock(&usb_bam_lock);
 
+		/* A2 wakeup not from LPM (CONS was up) */
+		wait_for_prod_granted(pipe_connect->bam_type);
+		if (info.start) {
+			pr_debug("%s: Enqueue PROD transfer", __func__);
+			info.start(info.start_stop_param,
+					USB_TO_PEER_PERIPHERAL);
+		}
+
 		break;
 
 	case USB_BAM_EVENT_INACTIVITY:
@@ -1111,9 +1574,22 @@
 int usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
 	void *param)
 {
+	info.wake_cb = callback;
+	info.wake_param = param;
 	return __usb_bam_register_wake_cb(idx, callback, param, true);
 }
 
+int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param)
+{
+	info.start = start;
+	info.stop = stop;
+	info.start_stop_param = param;
+	return 0;
+}
+
 int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param)
 {
 	u32 ret = 0;
@@ -1156,78 +1632,29 @@
 		return 0;
 	}
 
-	spin_lock(&usb_bam_lock);
-
 	ret = disconnect_pipe(idx);
 	if (ret) {
 		pr_err("%s: src pipe disconnection failure\n", __func__);
-		spin_unlock(&usb_bam_lock);
 		return ret;
 	}
 
 	pipe_connect->enabled = 0;
-
+	spin_lock(&usb_bam_lock);
 	if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0)
 		pr_err("%s: wrong pipes enabled counter for bam_type=%d\n",
 			__func__, pipe_connect->bam_type);
 	else
 		ctx.pipes_enabled_per_bam[pipe_connect->bam_type] -= 1;
-
 	spin_unlock(&usb_bam_lock);
 
 	return 0;
 }
 
-static void usb_bam_start_lpm(void)
-{
-	struct usb_phy *trans = usb_get_transceiver();
-	BUG_ON(trans == NULL);
-	spin_lock(&usb_bam_lock);
-	lpm_wait_handshake = 0;
-	if (sched_lpm) {
-		pr_debug("%s: Going to LPM\n", __func__);
-		spin_unlock(&usb_bam_lock);
-		pm_runtime_resume(trans->dev);
-		pm_runtime_put_noidle(trans->dev);
-		pm_runtime_suspend(trans->dev);
-		return;
-	}
-	spin_unlock(&usb_bam_lock);
-}
-
-static void wait_for_prod_release(enum usb_bam cur_bam)
-{
-	int ret;
-
-	if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
-		pr_debug("%s consumer already released\n", __func__);
-	 if (cur_prod_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
-		pr_debug("%s producer already released\n", __func__);
-
-	init_completion(&prod_released[cur_bam]);
-	init_completion(&cons_released[cur_bam]);
-	pr_debug("%s: Releasing %s_PROD\n", __func__,
-				bam_enable_strings[cur_bam]);
-	ret = ipa_rm_release_resource(ipa_rm_resource_prod[cur_bam]);
-	if (!ret) {
-		pr_debug("%s: Released without waiting\n", __func__);
-		cur_prod_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
-		complete_all(&prod_released[cur_bam]);
-	} else if (ret == -EINPROGRESS) {
-		pr_debug("%s: Waiting for PROD_RELEASED\n", __func__);
-		if (!wait_for_completion_timeout(&prod_released[cur_bam],
-						USB_BAM_TIMEOUT))
-			pr_err("%s: Timeout waiting for PROD_RELEASED\n",
-			__func__);
-	} else
-		pr_err("%s: ipa_rm_request_resource ret =%d", __func__, ret);
-}
-
 static void wait_for_cons_release(enum usb_bam cur_bam)
 {
 	 pr_debug("%s: Waiting for CONS release\n", __func__);
-	 if (cur_prod_state[cur_bam] != IPA_RM_RESOURCE_RELEASED) {
-		if (!wait_for_completion_timeout(&cons_released[cur_bam],
+	 if (info.cur_cons_state[cur_bam] != IPA_RM_RESOURCE_RELEASED) {
+		if (!wait_for_completion_timeout(&info.cons_released[cur_bam],
 						  USB_BAM_TIMEOUT))
 			pr_err("%s: Timeout wainting for CONS_RELEASE\n",
 				__func__);
@@ -1244,13 +1671,17 @@
 	struct sps_connect *sps_connection;
 	enum usb_bam cur_bam;
 
-
 	if (!ipa_params->prod_clnt_hdl && !ipa_params->cons_clnt_hdl) {
 		pr_err("%s: Both of the handles is missing\n", __func__);
 		return -EINVAL;
 	}
 
 	pr_debug("%s: Starting disconnect sequence\n", __func__);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.connect_complete = 0;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	mutex_lock(&info.suspend_resume_mutex);
 	/* Delay USB core to go into lpm before we finish our handshake */
 	if (ipa_params->prod_clnt_hdl) {
 		idx = ipa_params->dst_idx;
@@ -1258,12 +1689,15 @@
 
 		/* Do the release handshake with the A2 via RM */
 		cur_bam = pipe_connect->bam_type;
+		info.lpm_wait_pipes = 1;
 		wait_for_prod_release(cur_bam);
 		/* close USB -> IPA pipe */
+		usb_bam_resume_core(cur_bam);
 		ret = ipa_disconnect(ipa_params->prod_clnt_hdl);
 		if (ret) {
 			pr_err("%s: dst pipe disconnection failure\n",
 				__func__);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 		sps_connection = &ctx.usb_bam_sps.sps_connections[idx];
@@ -1274,6 +1708,7 @@
 		if (ret) {
 			pr_err("%s: failure to disconnect pipe %d\n",
 				__func__, idx);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 	}
@@ -1288,6 +1723,7 @@
 		if (ret) {
 			pr_err("%s: src pipe disconnection failure\n",
 				__func__);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 
@@ -1299,17 +1735,24 @@
 		if (ret) {
 			pr_err("%s: failure to disconnect pipe %d\n",
 				__func__, idx);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
-		pr_debug("%s: Notify CONS release\n", __func__);
 
-		if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pipe_connect->ipa_clnt_hdl = -1;
+
+		if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED) {
+			pr_debug("%s Notify CONS _RELEASED\n", __func__);
 			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
 				ipa_rm_resource_cons[cur_bam]);
+		}
 		pr_debug("%s Ended disconnect sequence\n", __func__);
-		usb_bam_start_lpm();
+		mutex_unlock(&info.suspend_resume_mutex);
+		usb_bam_start_lpm(1);
+		return 0;
 	}
 
+	mutex_unlock(&info.suspend_resume_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(usb_bam_disconnect_ipa);
@@ -1810,18 +2253,23 @@
 		ctx.pipes_enabled_per_bam[i] = 0;
 		ctx.inactivity_timer_ms[i] = 0;
 		ctx.is_bam_inactivity[i] = false;
-		init_completion(&prod_avail[i]);
-		complete(&prod_avail[i]);
-		init_completion(&cons_avail[i]);
-		complete(&cons_avail[i]);
-		init_completion(&cons_released[i]);
-		complete(&cons_released[i]);
-		init_completion(&prod_released[i]);
-		complete(&prod_released[i]);
-		cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
-		cur_cons_state[i] = IPA_RM_RESOURCE_RELEASED;
+		init_completion(&info.prod_avail[i]);
+		complete(&info.prod_avail[i]);
+		init_completion(&info.cons_avail[i]);
+		complete(&info.cons_avail[i]);
+		init_completion(&info.cons_released[i]);
+		complete(&info.cons_released[i]);
+		init_completion(&info.prod_released[i]);
+		complete(&info.prod_released[i]);
+		info.cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
+		info.cur_cons_state[i] = IPA_RM_RESOURCE_RELEASED;
 	}
 
+	INIT_WORK(&info.resume_work, usb_bam_finish_resume);
+	INIT_WORK(&info.suspend_work, usb_bam_start_suspend);
+	INIT_WORK(&info.finish_suspend_work, usb_bam_finish_suspend_);
+	mutex_init(&info.suspend_resume_mutex);
+
 	spin_lock_init(&usb_bam_peer_handshake_info_lock);
 	INIT_WORK(&peer_handshake_info.reset_event.event_w, usb_bam_sm_work);
 
@@ -1837,8 +2285,8 @@
 		destroy_workqueue(ctx.usb_bam_wq);
 		return ret;
 	}
+	spin_lock_init(&usb_bam_ipa_handshake_info_lock);
 	usb_bam_ipa_create_resources();
-
 	spin_lock_init(&usb_bam_lock);
 
 	return ret;
@@ -1911,14 +2359,14 @@
 
 bool msm_bam_lpm_ok(void)
 {
-	spin_lock(&usb_bam_lock);
-	if (lpm_wait_handshake) {
-		sched_lpm = 1;
-		spin_unlock(&usb_bam_lock);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (info.lpm_wait_handshake || info.lpm_wait_pipes) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Scheduling LPM for later\n", __func__);
 		return 0;
 	} else {
-		spin_unlock(&usb_bam_lock);
+		info.in_lpm = 1;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Going to LPM now\n", __func__);
 		return 1;
 	}
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index eac8953..9a642d6 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -2503,6 +2503,8 @@
 		batt_data = &palladium_1500_data;
 	} else if (chip->batt_type == BATT_OEM) {
 		batt_data = &oem_batt_data;
+	} else if (chip->batt_type == BATT_QRD_4V35_2000MAH) {
+		batt_data = &QRD_4v35_2000mAh_data;
 	} else {
 		battery_id = read_battery_id(chip);
 		if (battery_id < 0) {
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index c05f683..b71f903 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -539,9 +539,12 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
-	if (!port->port_usb)
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
+	}
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
@@ -552,14 +555,69 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
-	if (!port->port_usb)
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
+	}
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
 }
 
+static void gbam_stop_endless_rx(struct gbam_port *port)
+{
+	struct bam_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
+		return;
+	}
+	pr_debug("%s: dequeue\n", __func__);
+
+	status = usb_ep_dequeue(port->port_usb->out, d->rx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+
+}
+static void gbam_stop_endless_tx(struct gbam_port *port)
+{
+	struct bam_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
+		return;
+	}
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->in, d->tx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+}
+
+static void gbam_start(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct gbam_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		gbam_start_endless_rx(port);
+	else
+		gbam_start_endless_tx(port);
+}
+
+static void gbam_stop(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct gbam_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		gbam_stop_endless_rx(port);
+	else
+		gbam_stop_endless_tx(port);
+}
+
 static void gbam_start_io(struct gbam_port *port)
 {
 	unsigned long		flags;
@@ -1409,6 +1467,10 @@
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
 
 	usb_bam_register_wake_cb(d->dst_connection_idx, gbam_wake_cb, port);
+	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		usb_bam_register_start_stop_cbs(gbam_start, gbam_stop, port);
+		usb_bam_suspend(&d->ipa_params);
+	}
 }
 
 void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans)
@@ -1426,4 +1488,6 @@
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
 
 	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
+	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+		usb_bam_resume(&d->ipa_params);
 }
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 2abe2ef..081a09c 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -92,6 +92,7 @@
 	if (!port->port_usb)
 		return;
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("error enqueuing transfer, %d\n", status);
@@ -105,11 +106,40 @@
 	if (!port->port_usb)
 		return;
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("error enqueuing transfer, %d\n", status);
 }
 
+static void bam_data_stop_endless_rx(struct bam_data_port *port)
+{
+	struct bam_data_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb)
+		return;
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->out, d->rx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+
+}
+static void bam_data_stop_endless_tx(struct bam_data_port *port)
+{
+	struct bam_data_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb)
+		return;
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->in, d->tx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+}
+
 static int bam_data_peer_reset_cb(void *param)
 {
 	struct bam_data_port	*port = (struct bam_data_port *)param;
@@ -529,9 +559,28 @@
 	return usb_gadget_wakeup(d_port->cdev->gadget);
 }
 
+static void bam_data_start(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct bam_data_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		bam_data_start_endless_rx(port);
+	else
+		bam_data_start_endless_tx(port);
+}
+
+static void bam_data_stop(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct bam_data_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		bam_data_stop_endless_rx(port);
+	else
+		bam_data_stop_endless_tx(port);
+}
+
 void bam_data_suspend(u8 port_num)
 {
-
 	struct bam_data_port	*port;
 	struct bam_data_ch_info *d;
 
@@ -540,6 +589,11 @@
 
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
 	usb_bam_register_wake_cb(d->dst_connection_idx, bam_data_wake_cb, port);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		usb_bam_register_start_stop_cbs(bam_data_start, bam_data_stop,
+									port);
+		usb_bam_suspend(&d->ipa_params);
+	}
 }
 
 void bam_data_resume(u8 port_num)
@@ -553,5 +607,6 @@
 
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
 	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+		usb_bam_resume(&d->ipa_params);
 }
-
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index ede8bdb..d1d0f91 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -2180,7 +2180,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int msm_hsic_pm_suspend(struct device *dev)
 {
-	int ret;
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
 
@@ -2188,15 +2187,16 @@
 
 	dbg_log_event(NULL, "PM Suspend", 0);
 
+	if (!atomic_read(&mehci->in_lpm)) {
+		dev_info(dev, "abort suspend\n");
+		dbg_log_event(NULL, "PM Suspend abort", 0);
+		return -EBUSY;
+	}
+
 	if (device_may_wakeup(dev) && !mehci->async_irq)
 		enable_irq_wake(hcd->irq);
 
-	ret = msm_hsic_suspend(mehci);
-
-	if (ret && device_may_wakeup(dev) && !mehci->async_irq)
-		disable_irq_wake(hcd->irq);
-
-	return ret;
+	return 0;
 }
 
 static int msm_hsic_pm_suspend_noirq(struct device *dev)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index d4d7ee9..833bab2 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -870,7 +870,7 @@
 		return 0;
 
 	if (motg->pdata->delay_lpm_hndshk_on_disconnect && !msm_bam_lpm_ok())
-		return 0;
+		return -EBUSY;
 
 	disable_irq(motg->irq);
 	host_bus_suspend = !test_bit(MHL, &motg->inputs) && phy->otg->host &&
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index f726e79..1f0efd3 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -287,7 +287,7 @@
 	timeout_count = 100;
 	keys_state = (link0_status >> 28) & 0x7;
 	while ((keys_state != HDCP_KEYS_STATE_VALID) &&
-		timeout_count--) {
+		--timeout_count) {
 		link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
 		keys_state = (link0_status >> 28) & 0x7;
 		DEV_DBG("%s: %s: Keys not ready(%d). s=%d\n, l0=%0x08x",
@@ -320,7 +320,7 @@
 				link0_status);
 			msleep(20);
 		}
-	} while (!an_ready && timeout_count--);
+	} while (!an_ready && --timeout_count);
 
 	if (!timeout_count) {
 		rc = -ETIMEDOUT;
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index aa1eba5..ce9e5b9 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -195,7 +195,7 @@
 	/* write pointer offset in bytes */
 	unsigned int write_offset;
 
-	/* non-zero if data error occured */
+	/* non-zero if data error occurred */
 	int error;
 };
 
@@ -237,7 +237,10 @@
 	 * (dmx_sct_filter_params) and no sections were
 	 * received for the given time.
 	 */
-	DMX_EVENT_SECTION_TIMEOUT = 0x00000400
+	DMX_EVENT_SECTION_TIMEOUT = 0x00000400,
+
+	/* Scrambling bits change between clear and scrambled */
+	DMX_EVENT_SCRAMBLING_STATUS_CHANGE = 0x00000800
 };
 
 enum dmx_oob_cmd {
@@ -256,7 +259,7 @@
 /* Discontinuity indicator was set */
 #define DMX_FILTER_DISCONTINUITY_INDICATOR	0x02
 
-/* PES legnth in PES header is not correct */
+/* PES length in PES header is not correct */
 #define DMX_FILTER_PES_LENGTH_ERROR		0x04
 
 
@@ -412,7 +415,7 @@
 	/*
 	 * The PID the index entry belongs to.
 	 * In case of recording filter, multiple PIDs may exist in the same
-	 * filter through DMX_ADD_PID ioctl and each can be indexed seperatly.
+	 * filter through DMX_ADD_PID ioctl and each can be indexed separately.
 	 */
 	__u16 pid;
 
@@ -423,7 +426,7 @@
 	__u64 match_tsp_num;
 
 	/*
-	 * The TS packet number in the recorded data preceeding
+	 * The TS packet number in the recorded data preceding
 	 * match_tsp_num and has PUSI set.
 	 */
 	__u64 last_pusi_tsp_num;
@@ -432,6 +435,23 @@
 	__u64 stc;
 };
 
+/* Scrambling information associated with DMX_EVENT_SCRAMBLING_STATUS_CHANGE */
+struct dmx_scrambling_status_event_info {
+	/*
+	 * The PID which its scrambling bit status changed.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have
+	 * different scrambling bits status.
+	 */
+	__u16 pid;
+
+	/* old value of scrambling bits */
+	__u8 old_value;
+
+	/* new value of scrambling bits */
+	__u8 new_value;
+};
+
 /*
  * Filter's event returned through DMX_GET_EVENT.
  * poll with POLLPRI would block until events are available.
@@ -447,6 +467,7 @@
 		struct dmx_es_data_event_info es_data;
 		struct dmx_marker_event_info marker;
 		struct dmx_index_event_info index;
+		struct dmx_scrambling_status_event_info scrambling_status;
 	} params;
 };
 
@@ -754,6 +775,19 @@
 	__u32 identifier;
 };
 
+struct dmx_scrambling_bits {
+	/*
+	 * The PID to return its scrambling bit value.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have different
+	 * scrambling bits status.
+	 */
+	__u16 pid;
+
+	/* Current value of scrambling bits: 0, 1, 2 or 3 */
+	__u8 value;
+};
+
 #define DMX_START                _IO('o', 41)
 #define DMX_STOP                 _IO('o', 42)
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
@@ -784,5 +818,6 @@
 #define DMX_SET_INDEXING_PARAMS _IOW('o', 69, struct dmx_indexing_params)
 #define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
 #define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
+#define DMX_GET_SCRAMBLING_BITS _IOWR('o', 72, struct dmx_scrambling_bits)
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/mfd/pm8xxx/batterydata-lib.h
index df9569b..47a2b7b 100644
--- a/include/linux/mfd/pm8xxx/batterydata-lib.h
+++ b/include/linux/mfd/pm8xxx/batterydata-lib.h
@@ -18,10 +18,10 @@
 #define FCC_CC_COLS		5
 #define FCC_TEMP_COLS		8
 
-#define PC_CC_ROWS             29
+#define PC_CC_ROWS             31
 #define PC_CC_COLS             13
 
-#define PC_TEMP_ROWS		29
+#define PC_TEMP_ROWS		31
 #define PC_TEMP_COLS		8
 
 #define MAX_SINGLE_LUT_COLS	20
@@ -74,6 +74,7 @@
 	BATT_PALLADIUM,
 	BATT_DESAY,
 	BATT_OEM,
+	BATT_QRD_4V35_2000MAH,
 };
 
 /**
@@ -114,6 +115,7 @@
 extern struct bms_battery_data  palladium_1500_data;
 extern struct bms_battery_data  desay_5200_data;
 extern struct bms_battery_data  oem_batt_data;
+extern struct bms_battery_data QRD_4v35_2000mAh_data;
 
 int interpolate_fcc(struct single_row_lut *fcc_temp_lut, int batt_temp);
 int interpolate_scalingfactor(struct sf_lut *sf_lut, int row_entry, int pc);
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index da56df6..4711ec8 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -67,6 +67,7 @@
 void wcnss_riva_log_debug_regs(void);
 void wcnss_pronto_log_debug_regs(void);
 int wcnss_device_ready(void);
+void wcnss_riva_dump_pmic_regs(void);
 
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 616f8d5..58ea22d 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -45,6 +45,7 @@
 #define NUM_DECIMATORS 4
 #define NUM_INTERPOLATORS 3
 #define BITS_PER_REG 8
+#define SITAR_RX_PORT_START_NUMBER 10
 
 enum {
 	AIF1_PB = 0,
@@ -53,11 +54,11 @@
 };
 
 struct wcd9xxx_ch sitar_rx_chs[SITAR_RX_MAX] = {
-	WCD9XXX_CH(10, 0),
-	WCD9XXX_CH(11, 1),
-	WCD9XXX_CH(12, 2),
-	WCD9XXX_CH(13, 3),
-	WCD9XXX_CH(14, 4)
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER, 0),
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER + 1, 1),
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER + 2, 2),
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER + 3, 3),
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER + 4, 4)
 };
 
 struct wcd9xxx_ch sitar_tx_chs[SITAR_TX_MAX] = {
@@ -1368,10 +1369,10 @@
 						vport_check_table[dai_id],
 						port_id,
 						sitar_p->dai)) {
-				pr_info("%s: TX%u is used by other virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
 					__func__, port_id + 1);
 				mutex_unlock(&codec->mutex);
-				return -EINVAL;
+				return 0;
 			}
 			widget->value |= 1 << port_id;
 			list_add_tail(&core->tx_chs[port_id].list,
@@ -1381,10 +1382,10 @@
 			list_del_init(&core->tx_chs[port_id].list);
 		} else {
 			if (enable)
-				pr_info("%s: TX%u port is used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is used by this virtual port\n",
 					__func__, port_id + 1);
 			else
-				pr_info("%s: TX%u port is not used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is not used by this virtual port\n",
 					__func__, port_id + 1);
 			/* avoid update power function */
 			mutex_unlock(&codec->mutex);
@@ -1446,9 +1447,13 @@
 		list_del_init(&core->rx_chs[port_id].list);
 		break;
 	case 1:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&sitar_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			SITAR_RX_PORT_START_NUMBER,
+			&sitar_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &sitar_p->dai[AIF1_PB].wcd9xxx_ch_list);
 		break;
@@ -1458,14 +1463,10 @@
 		goto err;
 	}
 
-
+rtn:
 	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
-
 	mutex_unlock(&codec->mutex);
 	return 0;
-pr_err:
-	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
-		__func__, port_id + 1);
 err:
 	mutex_unlock(&codec->mutex);
 	return -EINVAL;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index b71dd65..669f8e3 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -60,6 +60,7 @@
 #define BITS_PER_REG 8
 /* This actual number of TX ports supported in slimbus slave */
 #define TAPAN_TX_PORT_NUMBER	16
+#define TAPAN_RX_PORT_START_NUMBER	16
 
 /* Nummer of TX ports actually connected from Slimbus slave to codec Digital */
 #define TAPAN_SLIM_CODEC_TX_PORTS 5
@@ -155,11 +156,11 @@
 static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
 
 static const struct wcd9xxx_ch tapan_rx_chs[TAPAN_RX_MAX] = {
-	WCD9XXX_CH(16, 0),
-	WCD9XXX_CH(17, 1),
-	WCD9XXX_CH(18, 2),
-	WCD9XXX_CH(19, 3),
-	WCD9XXX_CH(20, 4),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER, 0),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER + 1, 1),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER + 2, 2),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER + 3, 3),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER + 4, 4),
 };
 
 static const struct wcd9xxx_ch tapan_tx_chs[TAPAN_TX_MAX] = {
@@ -1410,7 +1411,7 @@
 				dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
 					__func__, port_id + 1);
 				mutex_unlock(&codec->mutex);
-				return -EINVAL;
+				return 0;
 			}
 			widget->value |= 1 << port_id;
 			list_add_tail(&core->tx_chs[port_id].list,
@@ -1495,23 +1496,35 @@
 		list_del_init(&core->rx_chs[port_id].list);
 	break;
 	case 1:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAPAN_RX_PORT_START_NUMBER,
+			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tapan_p->dai[AIF1_PB].wcd9xxx_ch_list);
 	break;
 	case 2:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tapan_p->dai[AIF2_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAPAN_RX_PORT_START_NUMBER,
+			&tapan_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
+				dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+					__func__, port_id + 1);
+				goto rtn;
+			}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tapan_p->dai[AIF2_PB].wcd9xxx_ch_list);
 	break;
 	case 3:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tapan_p->dai[AIF3_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAPAN_RX_PORT_START_NUMBER,
+			&tapan_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
+				dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+					__func__, port_id + 1);
+				goto rtn;
+			}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tapan_p->dai[AIF3_PB].wcd9xxx_ch_list);
 	break;
@@ -1520,13 +1533,10 @@
 		goto err;
 	}
 
+rtn:
 	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
-
 	mutex_unlock(&codec->mutex);
 	return 0;
-pr_err:
-	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
-		__func__, port_id + 1);
 err:
 	mutex_unlock(&codec->mutex);
 	return -EINVAL;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 29703b9..69e4cca 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -129,6 +129,8 @@
 #define TABLA_GPIO_IRQ_DEBOUNCE_TIME_US 5000
 
 #define TABLA_MBHC_GND_MIC_SWAP_THRESHOLD 2
+#define TABLA_RX_PORT_START_NUMBER	10
+
 
 #define TABLA_ACQUIRE_LOCK(x) do { \
 	mutex_lock_nested(&x, SINGLE_DEPTH_NESTING); \
@@ -302,13 +304,13 @@
 static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
 
 static const struct wcd9xxx_ch tabla_rx_chs[TABLA_RX_MAX] = {
-	WCD9XXX_CH(10, 0),
-	WCD9XXX_CH(11, 1),
-	WCD9XXX_CH(12, 2),
-	WCD9XXX_CH(13, 3),
-	WCD9XXX_CH(14, 4),
-	WCD9XXX_CH(15, 5),
-	WCD9XXX_CH(16, 6)
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER, 0),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 1, 1),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 2, 2),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 3, 3),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 4, 4),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 5, 5),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 6, 6)
 };
 
 static const struct wcd9xxx_ch tabla_tx_chs[TABLA_TX_MAX] = {
@@ -2031,10 +2033,10 @@
 						vtable,
 						port_id,
 						tabla_p->dai)) {
-				pr_info("%s: TX%u is used by other virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
 					__func__, port_id + 1);
 				mutex_unlock(&codec->mutex);
-				return -EINVAL;
+				return 0;
 			}
 			widget->value |= 1 << port_id;
 			list_add_tail(&core->tx_chs[port_id].list,
@@ -2045,10 +2047,10 @@
 			list_del_init(&core->tx_chs[port_id].list);
 		} else {
 			if (enable)
-				pr_info("%s: TX%u port is used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is used by this virtual port\n",
 					__func__, port_id + 1);
 			else
-				pr_info("%s: TX%u port is not used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is not used by this virtual port\n",
 					__func__, port_id + 1);
 			/* avoid update power function */
 			mutex_unlock(&codec->mutex);
@@ -2116,23 +2118,35 @@
 		list_del_init(&core->rx_chs[port_id].list);
 	break;
 	case 1:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TABLA_RX_PORT_START_NUMBER,
+			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tabla_p->dai[AIF1_PB].wcd9xxx_ch_list);
 	break;
 	case 2:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TABLA_RX_PORT_START_NUMBER,
+			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tabla_p->dai[AIF2_PB].wcd9xxx_ch_list);
 	break;
 	case 3:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TABLA_RX_PORT_START_NUMBER,
+			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tabla_p->dai[AIF3_PB].wcd9xxx_ch_list);
 	break;
@@ -2140,15 +2154,8 @@
 		pr_err("Unknown AIF %d\n", widget->value);
 		goto err;
 	}
-
+rtn:
 	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
-
-	mutex_unlock(&codec->mutex);
-	return 0;
-
-pr_err:
-	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
-		__func__, port_id + 1);
 	mutex_unlock(&codec->mutex);
 	return 0;
 err:
@@ -2703,7 +2710,7 @@
 	}
 
 	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x01);
-	msleep(250);
+	msleep(20);
 	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 	pr_debug("%s: leave\n", __func__);
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 5d4f9e6..99e5237 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -294,6 +294,7 @@
 #define NUM_INTERPOLATORS 7
 #define BITS_PER_REG 8
 #define TAIKO_TX_PORT_NUMBER	16
+#define TAIKO_RX_PORT_START_NUMBER	16
 
 #define TAIKO_I2S_MASTER_MODE_MASK 0x08
 
@@ -409,19 +410,19 @@
 static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
 
 static const struct wcd9xxx_ch taiko_rx_chs[TAIKO_RX_MAX] = {
-	WCD9XXX_CH(16, 0),
-	WCD9XXX_CH(17, 1),
-	WCD9XXX_CH(18, 2),
-	WCD9XXX_CH(19, 3),
-	WCD9XXX_CH(20, 4),
-	WCD9XXX_CH(21, 5),
-	WCD9XXX_CH(22, 6),
-	WCD9XXX_CH(23, 7),
-	WCD9XXX_CH(24, 8),
-	WCD9XXX_CH(25, 9),
-	WCD9XXX_CH(26, 10),
-	WCD9XXX_CH(27, 11),
-	WCD9XXX_CH(28, 12),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER, 0),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 1, 1),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 2, 2),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 3, 3),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 4, 4),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 5, 5),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 6, 6),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 7, 7),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 8, 8),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 9, 9),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 10, 10),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 11, 11),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 12, 12),
 };
 
 static const struct wcd9xxx_ch taiko_tx_chs[TAIKO_TX_MAX] = {
@@ -2042,11 +2043,10 @@
 						vtable,
 						port_id,
 						taiko_p->dai)) {
-					pr_debug("%s: TX%u is used by other\n"
-						"virtual port\n",
+					dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
 						__func__, port_id + 1);
 					mutex_unlock(&codec->mutex);
-					return -EINVAL;
+					return 0;
 				}
 				widget->value |= 1 << port_id;
 				list_add_tail(&core->tx_chs[port_id].list,
@@ -2057,11 +2057,11 @@
 				list_del_init(&core->tx_chs[port_id].list);
 			} else {
 				if (enable)
-					pr_debug("%s: TX%u port is used by\n"
+					dev_dbg(codec->dev, "%s: TX%u port is used by\n"
 						"this virtual port\n",
 						__func__, port_id + 1);
 				else
-					pr_debug("%s: TX%u port is not used by\n"
+					dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
 						"this virtual port\n",
 						__func__, port_id + 1);
 				/* avoid update power function */
@@ -2130,23 +2130,35 @@
 		list_del_init(&core->rx_chs[port_id].list);
 	break;
 	case 1:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&taiko_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAIKO_RX_PORT_START_NUMBER,
+			&taiko_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &taiko_p->dai[AIF1_PB].wcd9xxx_ch_list);
 	break;
 	case 2:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&taiko_p->dai[AIF2_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAIKO_RX_PORT_START_NUMBER,
+			&taiko_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list);
 	break;
 	case 3:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&taiko_p->dai[AIF3_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAIKO_RX_PORT_START_NUMBER,
+			&taiko_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list);
 	break;
@@ -2154,14 +2166,11 @@
 		pr_err("Unknown AIF %d\n", widget->value);
 		goto err;
 	}
-
+rtn:
 	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
 
 	mutex_unlock(&codec->mutex);
 	return 0;
-pr_err:
-	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
-		__func__, port_id + 1);
 err:
 	mutex_unlock(&codec->mutex);
 	return -EINVAL;
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 29c06cb..ed4e090 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1003,8 +1003,8 @@
 		} else if (channel_mode == 6) {
 			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
 			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
-			open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
-			open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[3] = PCM_CHANNEL_LFE;
 			open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
 			open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
 		} else if (channel_mode == 8) {
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c2fd2d7..ac26d0c 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -3363,6 +3363,7 @@
 	u32 lbuf_addr_lsw;
 	u32 liomode;
 	u32 io_compressed;
+	int dir = 0;
 
 	if (!ac || ac->apr == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
@@ -3380,15 +3381,21 @@
 	read.seq_id = param->uid;
 	liomode = (NT_MODE | ASYNC_IO_MODE);
 	io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
-	if (ac->io_mode == liomode)
+	if (ac->io_mode == liomode) {
 		lbuf_addr_lsw = (read.buf_addr_lsw - 32);
-	else if (ac->io_mode == io_compressed)
+		/*legacy wma driver case*/
+		dir = IN;
+	} else if (ac->io_mode == io_compressed) {
 		lbuf_addr_lsw = (read.buf_addr_lsw - 64);
-	else
+		dir = OUT;
+	} else {
 		lbuf_addr_lsw = read.buf_addr_lsw;
+		dir = OUT;
+	}
 
-	list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
-		buf_node = list_entry(ptr, struct asm_buffer_node, list);
+	list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
+		buf_node = list_entry(ptr, struct asm_buffer_node,
+			list);
 			if (buf_node->buf_addr_lsw == lbuf_addr_lsw) {
 				read.mem_map_handle = buf_node->mmap_hdl;
 				break;