Merge "usb: ehci-msm-hsic: Remove usage of MSM_GPIO_TO_INT"
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index 5c72eed..d62d0c6 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -49,3 +49,30 @@
 consistent or non-consistent memory as it sees fit.  By using this API,
 you are guaranteeing to the platform that you have all the correct and
 necessary sync points for this memory in the driver.
+
+DMA_ATTR_NO_KERNEL_MAPPING
+--------------------------
+
+DMA_ATTR_NO_KERNEL_MAPPING lets the platform to avoid creating a kernel
+virtual mapping for the allocated buffer. On some architectures creating
+such mapping is non-trivial task and consumes very limited resources
+(like kernel virtual address space or dma consistent address space).
+Buffers allocated with this attribute can be only passed to user space
+by calling dma_mmap_attrs(). By using this API, you are guaranteeing
+that you won't dereference the pointer returned by dma_alloc_attr(). You
+can threat it as a cookie that must be passed to dma_mmap_attrs() and
+dma_free_attrs(). Make sure that both of these also get this attribute
+set on each call.
+
+Since it is optional for platforms to implement
+DMA_ATTR_NO_KERNEL_MAPPING, those that do not will simply ignore the
+attribute and exhibit default behavior.
+
+DMA_ATTR_STRONGLY_ORDERED
+-------------------------
+
+DMA_ATTR_STRONGLY_ORDERED allocates memory with a very restrictive type
+of mapping (no unaligned accesses, no re-ordering, no write merging, no
+buffering, no pre-fetching). This has severe performance penalties and
+should not be used for general purpose DMA allocations. It should only
+be used if one of the restrictions on strongly ordered memory is required.
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index ef77e1e..d7290e0 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -4,9 +4,7 @@
 controlling LEDs that are part of PMIC on Qualcomm reference
 platforms. The PMIC is connected to Host processor via
 SPMI bus. This driver supports various LED modules such as
-WLED (white LED), RGB LED and flash LED. The first version of
-the driver supports WLED and other features are added in the
-next versions.
+WLED (white LED), RGB LED and flash LED.
 
 Required Properties:
 - compatible	: should be "qcom,leds-qpnp"
@@ -48,27 +46,60 @@
 - linux,default-trigger: trigger the led from external modules such as display
 - qcom,default-state:  default state of the led, should be "on" or "off"
 
+RGB Led is a tri-colored led, Red, Blue & Green.
+
+Required properties for RGB led:
+- qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
+- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,pwm-us: time the pwm device will modulate at (us)
+
+Required properties for LPG mode only:
+- qcom,duty-ms: duty cycle time the led will operate at (ms)
+- qcom,duty-pcts: array of values for duty cycle to go through
+- qcom,start-idx: starting point duty-pcts array
+
+Optional properties for RGB led:
+- linux,default-trigger: trigger the led from external modules such as display
+- qcom,default-state:  default state of the led, should be "on" or "off"
+
 Example:
 
-	qcom,leds@d800 {
-			compatible = "qcom,leds-qpnp";
-			status = "okay";
-			qcom,wled_0 {
-				linux,default-trigger = "bkl-trigger"
-				label = "wled";
-				qcom,cs-out-en;
-				qcom,op-fdbck;
-				qcom,default-state "off";
-				qcom,max-current = <25>;
-				qcom,ctrl-delay-us = <0>;
-				qcom,boost-curr-lim = <3>;
-				qcom,cp-sel = <0>;
-				qcom,switch-freq = <2>;
-				qcom,ovp-val = <2>;
-				qcom,num-strings = <1>;
-				qcom,id = <0>;
-				linux,name = "led:wled_backlight";
-			};
+	qcom,leds@d000 {
+		status = "okay";
+		qcom,rgb_pwm {
+			label = "rgb";
+			linux,name = "led:rgb_red";
+			qcom,mode = <0>;
+			qcom,pwm-channel = <6>;
+			qcom,pwm-us = <1000>;
+			qcom,duty-ms = <20>;
+			qcom,start-idx = <1>;
+			qcom,idx-len = <10>;
+			qcom,duty-pcts = [00 19 32 4B 64
+					 64 4B 32 19 00];
+			qcom,max-current = <12>;
+			qcom,default-state = "off";
+			qcom,id = <3>;
+			linux,default-trigger =
+				"battery-charging";
+		};
+
+		qcom,rgb_lpg {
+			label = "rgb";
+			linux,name = "led:rgb_blue";
+			qcom,mode = <1>;
+			qcom,pwm-channel = <4>;
+			qcom,pwm-us = <1000>;
+			qcom,duty-ms = <20>;
+			qcom,start-idx = <1>;
+			qcom,idx-len = <10>;
+			qcom,duty-pcts = [00 19 32 4B 64
+					 64 4B 32 19 00];
+			qcom,max-current = <12>;
+			qcom,default-state = "off";
+			qcom,id = <5>;
+			linux,default-trigger = "none";
+		};
 	};
 
 	qcom,leds@d300 {
@@ -90,3 +121,24 @@
 				qcom,id = <1>;
 			};
 	};
+
+	qcom,leds@d800 {
+			compatible = "qcom,leds-qpnp";
+			status = "okay";
+			qcom,wled_0 {
+				linux,default-trigger = "bkl-trigger"
+				label = "wled";
+				qcom,cs-out-en;
+				qcom,op-fdbck;
+				qcom,default-state "off";
+				qcom,max-current = <25>;
+				qcom,ctrl-delay-us = <0>;
+				qcom,boost-curr-lim = <3>;
+				qcom,cp-sel = <0>;
+				qcom,switch-freq = <2>;
+				qcom,ovp-val = <2>;
+				qcom,num-strings = <1>;
+				qcom,id = <0>;
+				linux,name = "led:wled_backlight";
+			};
+	};
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 99274d5..57d776f 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -28,8 +28,10 @@
 - interrupt-names : Optional interrupt resource entries are:
     "hs_phy_irq" : Interrupt from HSPHY for asynchronous events in LPM.
 	This is not used if wakeup events are received externally (e.g. PMIC)
-- qcom,dwc-usb3-msm-otg-capability: If present then depends on PMIC
-  for VBUS notifications, otherwise depends on PHY.
+- qcom,otg-capability: If present then depend on PMIC for VBUS notifications,
+  otherwise depend on PHY.
+- qcom,charging-disabled: If present then battery charging using USB
+  is disabled.
 
 Example MSM USB3.0 controller device node :
 	usb@f9200000 {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 341b49b..21d8c8c 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -993,6 +993,24 @@
 			status = "disabled";
 		};
 
+		qcom,leds@d000 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd000 0x100>;
+			label = "rgb";
+		};
+
+		qcom,leds@d100 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd100 0x100>;
+			label = "rgb";
+		};
+
+		qcom,leds@d200 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd200 0x100>;
+			label = "rgb";
+		};
+
 		qcom,leds@d300 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xd300 0x100>;
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8910.dtsi
index a2e1338..459a403 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8910.dtsi
@@ -51,6 +51,9 @@
 		reg = <0xf9a55000 0x400>;
 		interrupts = <0 134 0>;
 		interrupt-names = "core_irq";
+		HSUSB_VDDCX-supply = <&pm8110_s1>;
+		HSUSB_1p8-supply = <&pm8110_l10>;
+		HSUSB_3p3-supply = <&pm8110_l20>;
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 002332b..68207af 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -180,6 +180,10 @@
 	};
 };
 
+&usb3 {
+	qcom,charging-disabled;
+};
+
 &pm8941_mvs1 {
 	parent-supply = <&ext_5v>;
 };
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index f4be0dc..6553fc0 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -172,7 +172,7 @@
 };
 
 &usb3 {
-	qcom,dwc-usb3-msm-otg-capability;
+	qcom,otg-capability;
 };
 
 &pm8941_chg {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 79d92a3..83e1141 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -169,6 +169,7 @@
 				<78 512 106496 212992>, /* 208 MB/s */
 				<78 512 2147483647 4294967295>; /* Max. bandwidth */
 		qcom,bus-bw-vectors-bps = <0 13631488 27262976 54525952 109051904 218103808 4294967295>;
+		qcom,dat1-mpm-int = <42>;
 	};
 
 	sdcc2: qcom,sdcc@f98a4000 {
@@ -215,6 +216,7 @@
 				<81 512 106496 212992>, /* 208 MB/s */
 				<81 512 2147483647 4294967295>; /* Max. bandwidth */
 		qcom,bus-bw-vectors-bps = <0 13631488 27262976 54525952 109051904 218103808 4294967295>;
+		qcom,dat1-mpm-int = <44>;
 	};
 
 	sdcc3: qcom,sdcc@f9864000 {
@@ -224,8 +226,15 @@
 			<0xf9864800 0x100>,
 			<0xf9844000 0x7000>;
 		reg-names = "core_mem", "dml_mem", "bam_mem";
-		interrupts = <0 127 0>, <0 223 0>;
-		interrupt-names = "core_irq", "bam_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&sdcc3>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 127 0
+				1 &intc 0 223 0
+				2 &msmgpio 37 0x8>;
+		interrupt-names = "core_irq", "bam_irq", "sdiowakeup_irq";
 
 		gpios = <&msmgpio 40 0>, /* CLK */
 			<&msmgpio 39 0>, /* CMD */
@@ -262,8 +271,15 @@
 			<0xf98e4800 0x100>,
 			<0xf98c4000 0x7000>;
 		reg-names = "core_mem", "dml_mem", "bam_mem";
-		interrupts = <0 129 0>, <0 226 0>;
-		interrupt-names = "core_irq", "bam_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&sdcc4>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 129 0
+				1 &intc 0 226 0
+				2 &msmgpio 95 0x8>;
+		interrupt-names = "core_irq", "bam_irq", "sdiowakeup_irq";
 
 		gpios = <&msmgpio 93 0>, /* CLK */
 			<&msmgpio 91 0>, /* CMD */
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 5f28327..abb222f 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -261,6 +261,58 @@
 	return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
 }
 
+static inline void *dma_alloc_stronglyordered(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	DEFINE_DMA_ATTRS(attrs);
+	dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs);
+	return dma_alloc_attrs(dev, size, dma_handle, flag, &attrs);
+}
+
+static inline void dma_free_stronglyordered(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_handle)
+{
+	DEFINE_DMA_ATTRS(attrs);
+	dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs);
+	return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
+}
+
+static inline int dma_mmap_stronglyordered(struct device *dev,
+		struct vm_area_struct *vma, void *cpu_addr,
+		dma_addr_t dma_addr, size_t size)
+{
+	DEFINE_DMA_ATTRS(attrs);
+	dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs);
+	return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
+}
+
+static inline void *dma_alloc_nonconsistent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	DEFINE_DMA_ATTRS(attrs);
+	dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
+	return dma_alloc_attrs(dev, size, dma_handle, flag, &attrs);
+}
+
+static inline void dma_free_nonconsistent(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_handle)
+{
+	DEFINE_DMA_ATTRS(attrs);
+	dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
+	return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
+}
+
+static inline int dma_mmap_nonconsistent(struct device *dev,
+		struct vm_area_struct *vma, void *cpu_addr,
+		dma_addr_t dma_addr, size_t size)
+{
+	DEFINE_DMA_ATTRS(attrs);
+	dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
+	return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
+}
+
+
+
 /*
  * This can be called during boot to increase the size of the consistent
  * DMA region above it's default value of 2MB. It must be called before the
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 176696c..2b8be54 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1516,6 +1516,17 @@
 	help
 	  SMD Transport Layer for IPC Router
 
+config MSM_QMI_INTERFACE
+	depends on MSM_IPC_ROUTER
+	depends on QMI_ENCDEC
+	default n
+	bool "MSM QMI Interface Library"
+	help
+	  Library to send and receive QMI messages over IPC Router.
+	  This library provides interface functions to the kernel drivers
+	  to perform QMI message marshaling and transport them over IPC
+	  Router.
+
 config MSM_ONCRPCROUTER_DEBUG
 	depends on MSM_ONCRPCROUTER
 	default y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 403c32c..88ed433 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -138,6 +138,7 @@
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_device.o
 obj-$(CONFIG_MSM_IPC_ROUTER) += ipc_router.o
 obj-$(CONFIG_MSM_IPC_ROUTER)+= ipc_socket.o
+obj-$(CONFIG_MSM_QMI_INTERFACE) += msm_qmi_interface.o
 obj-$(CONFIG_DEBUG_FS) += smd_rpc_sym.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_servers.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_clients.o
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index c973bd5..a358bba 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -395,7 +395,6 @@
 #define CHG_TERM_MA		100
 static struct pm8921_charger_platform_data
 apq8064_pm8921_chg_pdata __devinitdata = {
-	.safety_time		= 180,
 	.update_time		= 60000,
 	.max_voltage		= MAX_VOLTAGE_MV,
 	.min_voltage		= 3200,
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index c6bcb6b..4ea9d8e 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1257,29 +1257,20 @@
  * clock is running at 100KHz and voltage levels are at 3.3
  * and 5 volts
  */
-static int enable_100KHz_ls(int enable)
+static int enable_100KHz_ls(int enable, int gpio)
 {
-	int ret = 0;
-	if (enable) {
-		ret = gpio_request(SX150X_GPIO(1, 10),
-					"cs8427_100KHZ_ENABLE");
-		if (ret) {
-			pr_err("%s: Failed to request gpio %d\n", __func__,
-				SX150X_GPIO(1, 10));
-			return ret;
-		}
-		gpio_direction_output(SX150X_GPIO(1, 10), 1);
-	} else {
-		gpio_direction_output(SX150X_GPIO(1, 10), 0);
-		gpio_free(SX150X_GPIO(1, 10));
-	}
-	return ret;
+	if (enable)
+		gpio_direction_output(gpio, 1);
+	else
+		gpio_direction_output(gpio, 0);
+	return 0;
 }
 
 static struct cs8427_platform_data cs8427_i2c_platform_data = {
 	.irq = SX150X_GPIO(1, 4),
 	.reset_gpio = SX150X_GPIO(1, 6),
 	.enable = enable_100KHz_ls,
+	.ls_gpio = SX150X_GPIO(1, 10),
 };
 
 static struct i2c_board_info cs8427_device_info[] __initdata = {
@@ -2703,7 +2694,7 @@
 };
 
 static struct msm_spi_platform_data mpq8064_qup_spi_gsbi6_pdata = {
-	.max_clock_speed = 1100000,
+	.max_clock_speed = 10800000,
 };
 
 static struct ci_bridge_platform_data mpq8064_ci_bridge_pdata = {
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index 0c7666b..d35a907 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -315,7 +315,6 @@
 #define MAX_VOLTAGE_MV		4200
 #define CHG_TERM_MA		100
 static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
-	.safety_time		= 180,
 	.update_time		= 60000,
 	.max_voltage		= MAX_VOLTAGE_MV,
 	.min_voltage		= 3200,
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 9efedb1..1a3d90d 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -396,7 +396,6 @@
 #define MAX_VOLTAGE_MV		4200
 #define CHG_TERM_MA		100
 static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
-	.safety_time		= 180,
 	.update_time		= 60000,
 	.max_voltage		= MAX_VOLTAGE_MV,
 	.min_voltage		= 3200,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 3c417c3..a73246d 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -3510,24 +3510,26 @@
 		.ctl_val = CC_BANKED(9, 6, n), \
 	}
 
-static struct clk_freq_tbl clk_tbl_gfx3d_8960ab[] = {
-	F_GFX3D(        0, gnd,  0,  0),
-	F_GFX3D( 27000000, pxo,  0,  0),
-	F_GFX3D( 48000000, pll8, 1,  8),
-	F_GFX3D( 54857000, pll8, 1,  7),
-	F_GFX3D( 64000000, pll8, 1,  6),
-	F_GFX3D( 76800000, pll8, 1,  5),
-	F_GFX3D( 96000000, pll8, 1,  4),
-	F_GFX3D(128000000, pll8, 1,  3),
-	F_GFX3D(145455000, pll2, 2, 11),
-	F_GFX3D(160000000, pll2, 1,  5),
-	F_GFX3D(177778000, pll2, 2,  9),
-	F_GFX3D(200000000, pll2, 1,  4),
-	F_GFX3D(228571000, pll2, 2,  7),
-	F_GFX3D(266667000, pll2, 1,  3),
-	F_GFX3D(320000000, pll2, 2,  5),
-	F_GFX3D(325000000, pll3, 1,  2),
-	F_GFX3D(400000000, pll2, 1,  2),
+/*Shared by 8064, 8930, and 8960ab*/
+static struct clk_freq_tbl clk_tbl_gfx3d[] = {
+	F_GFX3D(        0, gnd,   0,  0),
+	F_GFX3D( 27000000, pxo,   0,  0),
+	F_GFX3D( 48000000, pll8,  1,  8),
+	F_GFX3D( 54857000, pll8,  1,  7),
+	F_GFX3D( 64000000, pll8,  1,  6),
+	F_GFX3D( 76800000, pll8,  1,  5),
+	F_GFX3D( 96000000, pll8,  1,  4),
+	F_GFX3D(128000000, pll8,  1,  3),
+	F_GFX3D(145455000, pll2,  2, 11),
+	F_GFX3D(160000000, pll2,  1,  5),
+	F_GFX3D(177778000, pll2,  2,  9),
+	F_GFX3D(192000000, pll8,  1,  2),
+	F_GFX3D(200000000, pll2,  1,  4),
+	F_GFX3D(228571000, pll2,  2,  7),
+	F_GFX3D(266667000, pll2,  1,  3),
+	F_GFX3D(320000000, pll2,  2,  5),
+	F_GFX3D(400000000, pll2,  1,  2),
+	F_GFX3D(450000000, pll15, 1,  2),
 	F_END
 };
 
@@ -3552,49 +3554,6 @@
 	F_END
 };
 
-static struct clk_freq_tbl clk_tbl_gfx3d_8064[] = {
-	F_GFX3D(        0, gnd,   0,  0),
-	F_GFX3D( 27000000, pxo,   0,  0),
-	F_GFX3D( 48000000, pll8,  1,  8),
-	F_GFX3D( 54857000, pll8,  1,  7),
-	F_GFX3D( 64000000, pll8,  1,  6),
-	F_GFX3D( 76800000, pll8,  1,  5),
-	F_GFX3D( 96000000, pll8,  1,  4),
-	F_GFX3D(128000000, pll8,  1,  3),
-	F_GFX3D(145455000, pll2,  2, 11),
-	F_GFX3D(160000000, pll2,  1,  5),
-	F_GFX3D(177778000, pll2,  2,  9),
-	F_GFX3D(192000000, pll8,  1,  2),
-	F_GFX3D(200000000, pll2,  1,  4),
-	F_GFX3D(228571000, pll2,  2,  7),
-	F_GFX3D(266667000, pll2,  1,  3),
-	F_GFX3D(400000000, pll2,  1,  2),
-	F_GFX3D(450000000, pll15, 1,  2),
-	F_END
-};
-
-static struct clk_freq_tbl clk_tbl_gfx3d_8930[] = {
-	F_GFX3D(        0, gnd,   0,  0),
-	F_GFX3D( 27000000, pxo,   0,  0),
-	F_GFX3D( 48000000, pll8,  1,  8),
-	F_GFX3D( 54857000, pll8,  1,  7),
-	F_GFX3D( 64000000, pll8,  1,  6),
-	F_GFX3D( 76800000, pll8,  1,  5),
-	F_GFX3D( 96000000, pll8,  1,  4),
-	F_GFX3D(128000000, pll8,  1,  3),
-	F_GFX3D(145455000, pll2,  2, 11),
-	F_GFX3D(160000000, pll2,  1,  5),
-	F_GFX3D(177778000, pll2,  2,  9),
-	F_GFX3D(192000000, pll8,  1,  2),
-	F_GFX3D(200000000, pll2,  1,  4),
-	F_GFX3D(228571000, pll2,  2,  7),
-	F_GFX3D(266667000, pll2,  1,  3),
-	F_GFX3D(320000000, pll2,  2,  5),
-	F_GFX3D(400000000, pll2,  1,  2),
-	F_GFX3D(450000000, pll15, 1,  2),
-	F_END
-};
-
 static unsigned long fmax_gfx3d_8064ab[VDD_DIG_NUM] = {
 	[VDD_DIG_LOW]     = 128000000,
 	[VDD_DIG_NOMINAL] = 325000000,
@@ -3651,7 +3610,7 @@
 	.ns_reg = GFX3D_NS_REG,
 	.root_en_mask = BIT(2),
 	.set_rate = set_rate_mnd_banked,
-	.freq_tbl = clk_tbl_gfx3d_8960,
+	.freq_tbl = clk_tbl_gfx3d,
 	.bank_info = &bmnd_info_gfx3d,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -6558,7 +6517,6 @@
 			sizeof(msm_clocks_8960_common));
 	if (cpu_is_msm8960ab()) {
 		pll3_clk.c.rate = 650000000;
-		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8960ab;
 		gfx3d_clk.c.fmax[VDD_DIG_LOW] = 192000000;
 		gfx3d_clk.c.fmax[VDD_DIG_NOMINAL] = 325000000;
 		gfx3d_clk.c.fmax[VDD_DIG_HIGH] = 400000000;
@@ -6573,6 +6531,7 @@
 
 		gmem_axi_clk.c.depends = &gfx3d_axi_clk.c;
 	} else if (cpu_is_msm8960()) {
+		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8960;
 		memcpy(msm_clocks_8960 + ARRAY_SIZE(msm_clocks_8960_common),
 			 msm_clocks_8960_only, sizeof(msm_clocks_8960_only));
 		msm8960_clock_init_data.size -=
@@ -6583,11 +6542,9 @@
 	 * clocks which differ between chips.
 	 */
 	if (cpu_is_apq8064()) {
-		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8064;
 		gfx3d_clk.c.fmax = fmax_gfx3d_8064;
 	}
 	if (cpu_is_apq8064ab()) {
-		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8064;
 		gfx3d_clk.c.fmax = fmax_gfx3d_8064ab;
 	}
 	if ((cpu_is_apq8064() &&
@@ -6616,7 +6573,6 @@
 		gfx3d_clk.c.fmax = fmax_gfx3d_8930aa;
 	}
 	if (cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627()) {
-		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8930;
 		pll15_clk.c.rate = 900000000;
 		gmem_axi_clk.c.depends = &gfx3d_axi_clk_8930.c;
 	}
diff --git a/arch/arm/mach-msm/include/mach/msm_qmi_interface.h b/arch/arm/mach-msm/include/mach/msm_qmi_interface.h
new file mode 100644
index 0000000..c1b489d
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_qmi_interface.h
@@ -0,0 +1,247 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_QMI_INTERFACE_H_
+#define _MSM_QMI_INTERFACE_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+#include <linux/qmi_encdec.h>
+
+enum qmi_event_type {
+	QMI_RECV_MSG = 1,
+	QMI_SERVER_ARRIVE,
+	QMI_SERVER_EXIT,
+};
+
+struct qmi_handle {
+	void *src_port;
+	void *dest_info;
+	uint16_t next_txn_id;
+	struct list_head txn_list;
+	struct mutex handle_lock;
+	spinlock_t notify_lock;
+	void (*notify)(struct qmi_handle *handle, enum qmi_event_type event,
+			void *notify_priv);
+	void *notify_priv;
+	void (*ind_cb)(struct qmi_handle *handle,
+			unsigned int msg_id, void *msg,
+			unsigned int msg_len, void *ind_cb_priv);
+	void *ind_cb_priv;
+	int handle_reset;
+	wait_queue_head_t reset_waitq;
+};
+
+#ifdef CONFIG_MSM_QMI_INTERFACE
+
+/**
+ * qmi_handle_create() - Create a QMI handle
+ * @notify: Callback to notify events on the handle created.
+ * @notify_priv: Private information to be passed along with the notification.
+ *
+ * @return: Valid QMI handle on success, NULL on error.
+ */
+struct qmi_handle *qmi_handle_create(
+	void (*notify)(struct qmi_handle *handle,
+		       enum qmi_event_type event, void *notify_priv),
+	void *notify_priv);
+
+/**
+ * qmi_handle_destroy() - Destroy the QMI handle
+ * @handle: QMI handle to be destroyed.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_handle_destroy(struct qmi_handle *handle);
+
+/**
+ * qmi_register_ind_cb() - Register the indication callback function
+ * @handle: QMI handle with which the function is registered.
+ * @ind_cb: Callback function to be registered.
+ * @ind_cb_priv: Private data to be passed with the indication callback.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_register_ind_cb(struct qmi_handle *handle,
+	void (*ind_cb)(struct qmi_handle *handle,
+		       unsigned int msg_id, void *msg,
+		       unsigned int msg_len, void *ind_cb_priv),
+	void *ind_cb_priv);
+
+/**
+ * qmi_send_req_wait() - Send a synchronous QMI request
+ * @handle: QMI handle through which the QMI request is sent.
+ * @request_desc: Structure describing the request data structure.
+ * @req: Buffer containing the request data structure.
+ * @req_len: Length of the request data structure.
+ * @resp_desc: Structure describing the response data structure.
+ * @resp: Buffer to hold the response data structure.
+ * @resp_len: Length of the response data structure.
+ * @timeout_ms: Timeout before a response is received.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_send_req_wait(struct qmi_handle *handle,
+		      struct msg_desc *req_desc,
+		      void *req, unsigned int req_len,
+		      struct msg_desc *resp_desc,
+		      void *resp, unsigned int resp_len,
+		      unsigned long timeout_ms);
+
+/**
+ * qmi_send_req_nowait() - Send an asynchronous QMI request
+ * @handle: QMI handle through which the QMI request is sent.
+ * @request_desc: Structure describing the request data structure.
+ * @req: Buffer containing the request data structure.
+ * @req_len: Length of the request data structure.
+ * @resp_desc: Structure describing the response data structure.
+ * @resp: Buffer to hold the response data structure.
+ * @resp_len: Length of the response data structure.
+ * @resp_cb: Callback function to be invoked when the response arrives.
+ * @resp_cb_data: Private information to be passed along with the callback.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_send_req_nowait(struct qmi_handle *handle,
+			struct msg_desc *req_desc,
+			void *req, unsigned int req_len,
+			struct msg_desc *resp_desc,
+			void *resp, unsigned int resp_len,
+			void (*resp_cb)(struct qmi_handle *handle,
+					unsigned int msg_id, void *msg,
+					void *resp_cb_data),
+			void *resp_cb_data);
+
+/**
+ * qmi_recv_msg() - Receive the QMI message
+ * @handle: Handle for which the QMI message has to be received.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_recv_msg(struct qmi_handle *handle);
+
+/**
+ * qmi_connect_to_service() - Connect the QMI handle with a QMI service
+ * @handle: QMI handle to be connected with the QMI service.
+ * @service_id: Service id to identify the QMI service.
+ * @instance_id: Instance id to identify the instance of the QMI service.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_connect_to_service(struct qmi_handle *handle,
+			   uint32_t service_id, uint32_t instance_id);
+
+/**
+ * qmi_svc_event_notifier_register() - Register a notifier block to receive
+ *                                     events regarding a QMI service
+ * @service_id: Service ID to identify the QMI service.
+ * @instance_id: Instance ID to identify the instance of the QMI service.
+ * @nb: Notifier block used to receive the event.
+ *
+ * @return: 0 if successfully registered, < 0 on error.
+ */
+int qmi_svc_event_notifier_register(uint32_t service_id,
+				    uint32_t instance_id,
+				    struct notifier_block *nb);
+
+/**
+ * qmi_svc_event_notifier_unregister() - Unregister service event
+ *                                       notifier block
+ * @service_id: Service ID to identify the QMI service.
+ * @instance_id: Instance ID to identify the instance of the QMI service.
+ * @nb: Notifier block registered to receive the events.
+ *
+ * @return: 0 if successfully registered, < 0 on error.
+ */
+int qmi_svc_event_notifier_unregister(uint32_t service_id,
+				      uint32_t instance_id,
+				      struct notifier_block *nb);
+#else
+
+static inline struct qmi_handle *qmi_handle_create(
+	void (*notify)(struct qmi_handle *handle,
+		       enum qmi_event_type event, void *notify_priv),
+	void *notify_priv)
+{
+	return NULL;
+}
+
+static inline int qmi_handle_destroy(struct qmi_handle *handle)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_register_ind_cb(struct qmi_handle *handle,
+	void (*ind_cb)(struct qmi_handle *handle,
+		       unsigned int msg_id, void *msg,
+		       unsigned int msg_len, void *ind_cb_priv),
+	void *ind_cb_priv)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_send_req_wait(struct qmi_handle *handle,
+				    struct msg_desc *req_desc,
+				    void *req, unsigned int req_len,
+				    struct msg_desc *resp_desc,
+				    void *resp, unsigned int resp_len,
+				    unsigned long timeout_ms)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_send_req_nowait(struct qmi_handle *handle,
+				struct msg_desc *req_desc,
+				void *req, unsigned int req_len,
+				struct msg_desc *resp_desc,
+				void *resp, unsigned int resp_len,
+				void (*resp_cb)(struct qmi_handle *handle,
+						unsigned int msg_id, void *msg,
+						void *resp_cb_data),
+				void *resp_cb_data)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_recv_msg(struct qmi_handle *handle)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_connect_to_service(struct qmi_handle *handle,
+					 uint32_t service_id,
+					 uint32_t instance_id)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_svc_event_notifier_register(uint32_t service_id,
+						  uint32_t instance_id,
+						  struct notifier_block *nb)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_svc_event_notifier_unregister(uint32_t service_id,
+						    uint32_t instance_id,
+						    struct notifier_block *nb)
+{
+	return -ENODEV;
+}
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index 44b52b6..c77c181 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -83,7 +83,7 @@
 #define SMSM_WKUP_REASON_TIMER	0x00000008
 #define SMSM_WKUP_REASON_ALARM	0x00000010
 #define SMSM_WKUP_REASON_RESET	0x00000020
-#define SMSM_A2_FORCE_SHUTDOWN 0x00002000
+#define SMSM_USB_PLUG_UNPLUG    0x00002000
 #define SMSM_A2_RESET_BAM      0x00004000
 
 #define SMSM_VENDOR             0x00020000
diff --git a/arch/arm/mach-msm/msm_qmi_interface.c b/arch/arm/mach-msm/msm_qmi_interface.c
new file mode 100644
index 0000000..1ea1fe6
--- /dev/null
+++ b/arch/arm/mach-msm/msm_qmi_interface.c
@@ -0,0 +1,662 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+#include <linux/qmi_encdec.h>
+
+#include <mach/msm_qmi_interface.h>
+#include <mach/msm_ipc_router.h>
+
+#include "msm_qmi_interface_priv.h"
+
+static LIST_HEAD(svc_event_nb_list);
+static DEFINE_MUTEX(svc_event_nb_list_lock);
+
+static void qmi_event_notify(unsigned event, void *priv)
+{
+	struct qmi_handle *handle = (struct qmi_handle *)priv;
+	unsigned long flags;
+
+	if (!handle)
+		return;
+
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return;
+	}
+
+	switch (event) {
+	case MSM_IPC_ROUTER_READ_CB:
+		spin_lock_irqsave(&handle->notify_lock, flags);
+		handle->notify(handle, QMI_RECV_MSG, handle->notify_priv);
+		spin_unlock_irqrestore(&handle->notify_lock, flags);
+		break;
+
+	default:
+		break;
+	}
+	mutex_unlock(&handle->handle_lock);
+}
+
+struct qmi_handle *qmi_handle_create(
+	void (*notify)(struct qmi_handle *handle,
+		       enum qmi_event_type event, void *notify_priv),
+	void *notify_priv)
+{
+	struct qmi_handle *temp_handle;
+	struct msm_ipc_port *port_ptr;
+
+	temp_handle = kzalloc(sizeof(struct qmi_handle), GFP_KERNEL);
+	if (!temp_handle) {
+		pr_err("%s: Failure allocating client handle\n", __func__);
+		return NULL;
+	}
+
+	port_ptr = msm_ipc_router_create_port(qmi_event_notify,
+					      (void *)temp_handle);
+	if (!port_ptr) {
+		pr_err("%s: IPC router port creation failed\n", __func__);
+		kfree(temp_handle);
+		return NULL;
+	}
+
+	temp_handle->src_port = port_ptr;
+	temp_handle->next_txn_id = 1;
+	INIT_LIST_HEAD(&temp_handle->txn_list);
+	mutex_init(&temp_handle->handle_lock);
+	spin_lock_init(&temp_handle->notify_lock);
+	temp_handle->notify = notify;
+	temp_handle->notify_priv = notify_priv;
+	temp_handle->handle_reset = 0;
+	init_waitqueue_head(&temp_handle->reset_waitq);
+	return temp_handle;
+}
+EXPORT_SYMBOL(qmi_handle_create);
+
+static void clean_txn_info(struct qmi_handle *handle)
+{
+	struct qmi_txn *txn_handle, *temp_txn_handle;
+
+	list_for_each_entry_safe(txn_handle, temp_txn_handle,
+				 &handle->txn_list, list) {
+		if (txn_handle->type == QMI_ASYNC_TXN) {
+			list_del(&txn_handle->list);
+			kfree(txn_handle);
+		} else if (txn_handle->type == QMI_SYNC_TXN) {
+			wake_up(&txn_handle->wait_q);
+		}
+	}
+}
+
+int qmi_handle_destroy(struct qmi_handle *handle)
+{
+	int rc;
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_lock);
+	handle->handle_reset = 1;
+	clean_txn_info(handle);
+	mutex_unlock(&handle->handle_lock);
+
+	rc = wait_event_interruptible(handle->reset_waitq,
+				      list_empty(&handle->txn_list));
+
+	/* TODO: Destroy client owned transaction */
+	msm_ipc_router_close_port((struct msm_ipc_port *)(handle->src_port));
+	kfree(handle->dest_info);
+	kfree(handle);
+	return 0;
+}
+EXPORT_SYMBOL(qmi_handle_destroy);
+
+int qmi_register_ind_cb(struct qmi_handle *handle,
+	void (*ind_cb)(struct qmi_handle *handle,
+		       unsigned int msg_id, void *msg,
+		       unsigned int msg_len, void *ind_cb_priv),
+	void *ind_cb_priv)
+{
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return -ENETRESET;
+	}
+
+	handle->ind_cb = ind_cb;
+	handle->ind_cb_priv = ind_cb_priv;
+	mutex_unlock(&handle->handle_lock);
+	return 0;
+}
+EXPORT_SYMBOL(qmi_register_ind_cb);
+
+static int qmi_encode_and_send_req(struct qmi_txn **ret_txn_handle,
+	struct qmi_handle *handle, enum txn_type type,
+	struct msg_desc *req_desc, void *req, unsigned int req_len,
+	struct msg_desc *resp_desc, void *resp, unsigned int resp_len,
+	void (*resp_cb)(struct qmi_handle *handle,
+			unsigned int msg_id, void *msg,
+			void *resp_cb_data),
+	void *resp_cb_data)
+{
+	struct qmi_txn *txn_handle;
+	int rc, encoded_req_len;
+	void *encoded_req;
+
+	if (!handle || !handle->dest_info ||
+	    !req_desc || !req || !resp_desc || !resp)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return -ENETRESET;
+	}
+
+	/* Allocate Transaction Info */
+	txn_handle = kzalloc(sizeof(struct qmi_txn), GFP_KERNEL);
+	if (!txn_handle) {
+		pr_err("%s: Failed to allocate txn handle\n", __func__);
+		mutex_unlock(&handle->handle_lock);
+		return -ENOMEM;
+	}
+	txn_handle->type = type;
+	INIT_LIST_HEAD(&txn_handle->list);
+	init_waitqueue_head(&txn_handle->wait_q);
+
+	/* Cache the parameters passed & mark it as sync*/
+	txn_handle->handle = handle;
+	txn_handle->resp_desc = resp_desc;
+	txn_handle->resp = resp;
+	txn_handle->resp_len = resp_len;
+	txn_handle->resp_received = 0;
+	txn_handle->resp_cb = resp_cb;
+	txn_handle->resp_cb_data = resp_cb_data;
+
+	/* Encode the request msg */
+	encoded_req_len = req_desc->max_msg_len + QMI_HEADER_SIZE;
+	encoded_req = kmalloc(encoded_req_len, GFP_KERNEL);
+	if (!encoded_req) {
+		pr_err("%s: Failed to allocate req_msg_buf\n", __func__);
+		rc = -ENOMEM;
+		goto encode_and_send_req_err1;
+	}
+	rc = qmi_kernel_encode(req_desc,
+		(void *)(encoded_req + QMI_HEADER_SIZE),
+		req_desc->max_msg_len, req);
+	if (rc < 0) {
+		pr_err("%s: Encode Failure %d\n", __func__, rc);
+		goto encode_and_send_req_err2;
+	}
+	encoded_req_len = rc;
+
+	/* Encode the header & Add to the txn_list */
+	if (!handle->next_txn_id)
+		handle->next_txn_id++;
+	txn_handle->txn_id = handle->next_txn_id++;
+	encode_qmi_header(encoded_req, QMI_REQUEST_CONTROL_FLAG,
+			  txn_handle->txn_id, req_desc->msg_id,
+			  encoded_req_len);
+	encoded_req_len += QMI_HEADER_SIZE;
+	list_add_tail(&txn_handle->list, &handle->txn_list);
+
+	/* Send the request */
+	rc = msm_ipc_router_send_msg((struct msm_ipc_port *)(handle->src_port),
+		(struct msm_ipc_addr *)handle->dest_info,
+		encoded_req, encoded_req_len);
+	if (rc < 0) {
+		pr_err("%s: send_msg failed %d\n", __func__, rc);
+		goto encode_and_send_req_err3;
+	}
+	mutex_unlock(&handle->handle_lock);
+
+	kfree(encoded_req);
+	if (ret_txn_handle)
+		*ret_txn_handle = txn_handle;
+	return 0;
+
+encode_and_send_req_err3:
+	list_del(&txn_handle->list);
+encode_and_send_req_err2:
+	kfree(encoded_req);
+encode_and_send_req_err1:
+	kfree(txn_handle);
+	mutex_unlock(&handle->handle_lock);
+	return rc;
+}
+
+int qmi_send_req_wait(struct qmi_handle *handle,
+		      struct msg_desc *req_desc,
+		      void *req, unsigned int req_len,
+		      struct msg_desc *resp_desc,
+		      void *resp, unsigned int resp_len,
+		      unsigned long timeout_ms)
+{
+	struct qmi_txn *txn_handle = NULL;
+	int rc;
+
+	/* Encode and send the request */
+	rc = qmi_encode_and_send_req(&txn_handle, handle, QMI_SYNC_TXN,
+				     req_desc, req, req_len,
+				     resp_desc, resp, resp_len,
+				     NULL, NULL);
+	if (rc < 0) {
+		pr_err("%s: Error encode & send req: %d\n", __func__, rc);
+		return rc;
+	}
+
+	/* Wait for the response */
+	if (!timeout_ms) {
+		rc = wait_event_interruptible(txn_handle->wait_q,
+					(txn_handle->resp_received ||
+					 handle->handle_reset));
+	} else {
+		rc = wait_event_interruptible_timeout(txn_handle->wait_q,
+					(txn_handle->resp_received ||
+					 handle->handle_reset),
+					msecs_to_jiffies(timeout_ms));
+		if (rc == 0)
+			rc = -ETIMEDOUT;
+	}
+
+	mutex_lock(&handle->handle_lock);
+	if (!txn_handle->resp_received) {
+		pr_err("%s: Response Wait Error %d\n", __func__, rc);
+		if (handle->handle_reset)
+			rc = -ENETRESET;
+		if (rc >= 0)
+			rc = -EFAULT;
+		goto send_req_wait_err;
+	}
+	rc = 0;
+
+send_req_wait_err:
+	list_del(&txn_handle->list);
+	kfree(txn_handle);
+	mutex_unlock(&handle->handle_lock);
+	wake_up(&handle->reset_waitq);
+	return rc;
+}
+EXPORT_SYMBOL(qmi_send_req_wait);
+
+int qmi_send_req_nowait(struct qmi_handle *handle,
+			struct msg_desc *req_desc,
+			void *req, unsigned int req_len,
+			struct msg_desc *resp_desc,
+			void *resp, unsigned int resp_len,
+			void (*resp_cb)(struct qmi_handle *handle,
+					unsigned int msg_id, void *msg,
+					void *resp_cb_data),
+			void *resp_cb_data)
+{
+	return qmi_encode_and_send_req(NULL, handle, QMI_ASYNC_TXN,
+				       req_desc, req, req_len,
+				       resp_desc, resp, resp_len,
+				       resp_cb, resp_cb_data);
+}
+EXPORT_SYMBOL(qmi_send_req_nowait);
+
+static struct qmi_txn *find_txn_handle(struct qmi_handle *handle,
+				       uint16_t txn_id)
+{
+	struct qmi_txn *txn_handle;
+
+	list_for_each_entry(txn_handle, &handle->txn_list, list) {
+		if (txn_handle->txn_id == txn_id)
+			return txn_handle;
+	}
+	return NULL;
+}
+
+static int handle_qmi_response(struct qmi_handle *handle,
+			       unsigned char *resp_msg, uint16_t txn_id,
+			       uint16_t msg_id, uint16_t msg_len)
+{
+	struct qmi_txn *txn_handle;
+	int rc;
+
+	/* Find the transaction handle */
+	txn_handle = find_txn_handle(handle, txn_id);
+	if (!txn_handle) {
+		pr_err("%s Response received for non-existent txn_id %d\n",
+			__func__, txn_id);
+		return -EINVAL;
+	}
+
+	/* Decode the message */
+	rc = qmi_kernel_decode(txn_handle->resp_desc, txn_handle->resp,
+			       (void *)(resp_msg + QMI_HEADER_SIZE), msg_len);
+	if (rc < 0) {
+		pr_err("%s: Response Decode Failure <%d: %d: %d> rc: %d\n",
+			__func__, txn_id, msg_id, msg_len, rc);
+		wake_up(&txn_handle->wait_q);
+		if (txn_handle->type == QMI_ASYNC_TXN) {
+			list_del(&txn_handle->list);
+			kfree(txn_handle);
+		}
+		return rc;
+	}
+
+	/* Handle async or sync resp */
+	switch (txn_handle->type) {
+	case QMI_SYNC_TXN:
+		txn_handle->resp_received = 1;
+		wake_up(&txn_handle->wait_q);
+		rc = 0;
+		break;
+
+	case QMI_ASYNC_TXN:
+		if (txn_handle->resp_cb)
+			txn_handle->resp_cb(txn_handle->handle, msg_id,
+					    txn_handle->resp,
+					    txn_handle->resp_cb_data);
+		list_del(&txn_handle->list);
+		kfree(txn_handle);
+		rc = 0;
+		break;
+
+	default:
+		pr_err("%s: Unrecognized transaction type\n", __func__);
+		return -EFAULT;
+	}
+	return rc;
+}
+
+static int handle_qmi_indication(struct qmi_handle *handle, void *msg,
+				 unsigned int msg_id, unsigned int msg_len)
+{
+	if (handle->ind_cb)
+		handle->ind_cb(handle, msg_id, msg,
+				msg_len, handle->ind_cb_priv);
+	return 0;
+}
+
+int qmi_recv_msg(struct qmi_handle *handle)
+{
+	unsigned int recv_msg_len;
+	unsigned char *recv_msg = NULL;
+	struct msm_ipc_addr src_addr;
+	unsigned char cntl_flag;
+	uint16_t txn_id, msg_id, msg_len;
+	int rc;
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return -ENETRESET;
+	}
+
+	/* Read the messages */
+	rc = msm_ipc_router_read_msg((struct msm_ipc_port *)(handle->src_port),
+				     &src_addr, &recv_msg, &recv_msg_len);
+	if (rc < 0) {
+		pr_err("%s: Read failed %d\n", __func__, rc);
+		mutex_unlock(&handle->handle_lock);
+		return rc;
+	}
+
+	/* Decode the header & Handle the req, resp, indication message */
+	decode_qmi_header(recv_msg, &cntl_flag, &txn_id, &msg_id, &msg_len);
+
+	switch (cntl_flag) {
+	case QMI_RESPONSE_CONTROL_FLAG:
+		rc = handle_qmi_response(handle, recv_msg,
+					 txn_id, msg_id, msg_len);
+		break;
+
+	case QMI_INDICATION_CONTROL_FLAG:
+		rc = handle_qmi_indication(handle, recv_msg, msg_id, msg_len);
+		break;
+
+	default:
+		rc = -EFAULT;
+		pr_err("%s: Unsupported message type %d\n",
+			__func__, cntl_flag);
+		break;
+	}
+	kfree(recv_msg);
+	mutex_unlock(&handle->handle_lock);
+	return rc;
+}
+EXPORT_SYMBOL(qmi_recv_msg);
+
+int qmi_connect_to_service(struct qmi_handle *handle,
+			   uint32_t service_id, uint32_t instance_id)
+{
+	struct msm_ipc_port_name svc_name;
+	struct msm_ipc_server_info svc_info;
+	struct msm_ipc_addr *svc_dest_addr;
+	int rc;
+
+	if (!handle)
+		return -EINVAL;
+
+	svc_dest_addr = kzalloc(sizeof(struct msm_ipc_addr),
+				GFP_KERNEL);
+	if (!svc_dest_addr) {
+		pr_err("%s: Failure allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	svc_name.service = service_id;
+	svc_name.instance = instance_id;
+
+	rc = msm_ipc_router_lookup_server_name(&svc_name, &svc_info, 1, 0xFF);
+	if (rc <= 0) {
+		pr_err("%s: Server not found\n", __func__);
+		return -ENODEV;
+	}
+	svc_dest_addr->addrtype = MSM_IPC_ADDR_ID;
+	svc_dest_addr->addr.port_addr.node_id = svc_info.node_id;
+	svc_dest_addr->addr.port_addr.port_id = svc_info.port_id;
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return -ENETRESET;
+	}
+	handle->dest_info = svc_dest_addr;
+	mutex_unlock(&handle->handle_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(qmi_connect_to_service);
+
+static struct svc_event_nb *find_svc_event_nb_by_name(const char *name)
+{
+	struct svc_event_nb *temp;
+
+	list_for_each_entry(temp, &svc_event_nb_list, list) {
+		if (!strncmp(name, temp->pdriver_name,
+			     sizeof(temp->pdriver_name)))
+			return temp;
+	}
+	return NULL;
+}
+
+static int qmi_svc_event_probe(struct platform_device *pdev)
+{
+	struct svc_event_nb *temp;
+	unsigned long flags;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb_by_name(pdev->name);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&temp->nb_lock, flags);
+	temp->svc_avail = 1;
+	raw_notifier_call_chain(&temp->svc_event_rcvr_list,
+				QMI_SERVER_ARRIVE, NULL);
+	spin_unlock_irqrestore(&temp->nb_lock, flags);
+	mutex_unlock(&svc_event_nb_list_lock);
+	return 0;
+}
+
+static int qmi_svc_event_remove(struct platform_device *pdev)
+{
+	struct svc_event_nb *temp;
+	unsigned long flags;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb_by_name(pdev->name);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&temp->nb_lock, flags);
+	temp->svc_avail = 0;
+	raw_notifier_call_chain(&temp->svc_event_rcvr_list,
+				QMI_SERVER_EXIT, NULL);
+	spin_unlock_irqrestore(&temp->nb_lock, flags);
+	mutex_unlock(&svc_event_nb_list_lock);
+	return 0;
+}
+
+static struct svc_event_nb *find_svc_event_nb(uint32_t service_id,
+					      uint32_t instance_id)
+{
+	struct svc_event_nb *temp;
+
+	list_for_each_entry(temp, &svc_event_nb_list, list) {
+		if (temp->service_id == service_id &&
+		    temp->instance_id == instance_id)
+			return temp;
+	}
+	return NULL;
+}
+
+static struct svc_event_nb *find_and_add_svc_event_nb(uint32_t service_id,
+						      uint32_t instance_id)
+{
+	struct svc_event_nb *temp;
+	int ret;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb(service_id, instance_id);
+	if (temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return temp;
+	}
+
+	temp = kzalloc(sizeof(struct svc_event_nb), GFP_KERNEL);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		pr_err("%s: Failed to alloc notifier block\n", __func__);
+		return temp;
+	}
+
+	spin_lock_init(&temp->nb_lock);
+	temp->service_id = service_id;
+	temp->instance_id = instance_id;
+	INIT_LIST_HEAD(&temp->list);
+	temp->svc_driver.probe = qmi_svc_event_probe;
+	temp->svc_driver.remove = qmi_svc_event_remove;
+	scnprintf(temp->pdriver_name, sizeof(temp->pdriver_name),
+		  "QMI%08x:%08x", service_id, instance_id);
+	temp->svc_driver.driver.name = temp->pdriver_name;
+	RAW_INIT_NOTIFIER_HEAD(&temp->svc_event_rcvr_list);
+
+	list_add_tail(&temp->list, &svc_event_nb_list);
+	mutex_unlock(&svc_event_nb_list_lock);
+
+	ret = platform_driver_register(&temp->svc_driver);
+	if (ret < 0) {
+		pr_err("%s: Failed pdriver register\n", __func__);
+		mutex_lock(&svc_event_nb_list_lock);
+		list_del(&temp->list);
+		mutex_unlock(&svc_event_nb_list_lock);
+		kfree(temp);
+		temp = NULL;
+	}
+
+	return temp;
+}
+
+int qmi_svc_event_notifier_register(uint32_t service_id,
+				    uint32_t instance_id,
+				    struct notifier_block *nb)
+{
+	struct svc_event_nb *temp;
+	unsigned long flags;
+	int ret;
+
+	temp = find_and_add_svc_event_nb(service_id, instance_id);
+	if (!temp)
+		return -EFAULT;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb(service_id, instance_id);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return -EFAULT;
+	}
+	spin_lock_irqsave(&temp->nb_lock, flags);
+	if (temp->svc_avail)
+		nb->notifier_call(nb, QMI_SERVER_ARRIVE, NULL);
+
+	ret = raw_notifier_chain_register(&temp->svc_event_rcvr_list, nb);
+	spin_unlock_irqrestore(&temp->nb_lock, flags);
+	mutex_unlock(&svc_event_nb_list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(qmi_svc_event_notifier_register);
+
+int qmi_svc_event_notifier_unregister(uint32_t service_id,
+				      uint32_t instance_id,
+				      struct notifier_block *nb)
+{
+	int ret;
+	struct svc_event_nb *temp;
+	unsigned long flags;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb(service_id, instance_id);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&temp->nb_lock, flags);
+	ret = raw_notifier_chain_unregister(&temp->svc_event_rcvr_list, nb);
+	spin_unlock_irqrestore(&temp->nb_lock, flags);
+	mutex_unlock(&svc_event_nb_list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(qmi_svc_event_notifier_unregister);
+
+MODULE_DESCRIPTION("MSM QMI Interface");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/msm_qmi_interface_priv.h b/arch/arm/mach-msm/msm_qmi_interface_priv.h
new file mode 100644
index 0000000..58f1ce3
--- /dev/null
+++ b/arch/arm/mach-msm/msm_qmi_interface_priv.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_QMI_INTERFACE_PRIV_H_
+#define _MSM_QMI_INTERFACE_PRIV_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+#include <linux/platform_device.h>
+#include <linux/qmi_encdec.h>
+
+#include <mach/msm_qmi_interface.h>
+
+enum txn_type {
+	QMI_SYNC_TXN = 1,
+	QMI_ASYNC_TXN,
+};
+
+struct qmi_txn {
+	struct list_head list;
+	uint16_t txn_id;
+	enum txn_type type;
+	struct qmi_handle *handle;
+	struct msg_desc *resp_desc;
+	void *resp;
+	unsigned int resp_len;
+	int resp_received;
+	void (*resp_cb)(struct qmi_handle *handle, unsigned int msg_id,
+			void *msg, void *resp_cb_data);
+	void *resp_cb_data;
+	wait_queue_head_t wait_q;
+};
+
+struct svc_event_nb {
+	spinlock_t nb_lock;
+	uint32_t service_id;
+	uint32_t instance_id;
+	char pdriver_name[32];
+	int svc_avail;
+	struct platform_driver svc_driver;
+	struct raw_notifier_head svc_event_rcvr_list;
+	struct list_head list;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/wdog_debug.c b/arch/arm/mach-msm/wdog_debug.c
index 08dd9ce..8b39d26 100644
--- a/arch/arm/mach-msm/wdog_debug.c
+++ b/arch/arm/mach-msm/wdog_debug.c
@@ -43,6 +43,11 @@
 	value = readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
 	value &= ~BIT(WDOG_DEBUG_EN);
 	writel_relaxed(value, wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
+
+	/* Ensure the WDOG_DEBUG_EN status has changed */
+	while (readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET) &
+		BIT(WDOG_DEBUG_EN))
+			;
 }
 EXPORT_SYMBOL(msm_disable_wdog_debug);
 
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 8404601..ab1bd68 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -630,9 +630,14 @@
 
 static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
 {
-	prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
-			    pgprot_writecombine(prot) :
-			    pgprot_dmacoherent(prot);
+	if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
+		prot = pgprot_writecombine(prot);
+	else if (dma_get_attr(DMA_ATTR_STRONGLY_ORDERED, attrs))
+		prot = pgprot_stronglyordered(prot);
+	/* if non-consistent just pass back what was given */
+	else if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
+		prot = pgprot_dmacoherent(prot);
+
 	return prot;
 }
 
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index 7a229a5..de060cc 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -1844,6 +1844,8 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_auth_byte_count);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_auth_result_20);
 	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_status_ocu);
@@ -1860,6 +1862,8 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_auth_byte_count);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_auth_result_32);
 	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_status_ocu);
@@ -1877,6 +1881,8 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_auth_byte_count);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_auth_result_20);
 	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_status_ocu);
@@ -1894,6 +1900,8 @@
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->ce_data_in);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
+	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_status_wait);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_auth_byte_count);
 	*cmd_ptr_vaddr++ = QCE_SET_CMD_PTR(cmdlist->get_auth_result_32);
 	*cmd_ptr_vaddr++ = QCE_SET_LAST_CMD_PTR(cmdlist->get_status_ocu);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index ba122bb..d658217 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -21,6 +21,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 #include <linux/spmi.h>
+#include <linux/qpnp/pwm.h>
 
 #define WLED_MOD_EN_REG(base, n)	(base + 0x60 + n*0x10)
 #define WLED_IDAC_DLY_REG(base, n)	(WLED_MOD_EN_REG(base, n) + 0x01)
@@ -127,6 +128,21 @@
 
 #define LED_TRIGGER_DEFAULT		"none"
 
+#define RGB_LED_SRC_SEL(base)		(base + 0x45)
+#define RGB_LED_EN_CTL(base)		(base + 0x46)
+#define RGB_LED_ATC_CTL(base)		(base + 0x47)
+
+#define RGB_MAX_LEVEL			LED_FULL
+#define RGB_LED_ENABLE_RED		0x80
+#define RGB_LED_ENABLE_GREEN		0x40
+#define RGB_LED_ENABLE_BLUE		0x20
+#define RGB_LED_SOURCE_VPH_PWR		0x01
+#define RGB_LED_ENABLE_MASK		0xE0
+#define RGB_LED_SRC_MASK		0x03
+#define QPNP_LED_PWM_FLAGS	(PM_PWM_LUT_LOOP | PM_PWM_LUT_RAMP_UP)
+#define	PWM_LUT_MAX_SIZE		63
+#define RGB_LED_DISABLE			0x00
+
 /**
  * enum qpnp_leds - QPNP supported led ids
  * @QPNP_ID_WLED - White led backlight
@@ -135,6 +151,9 @@
 	QPNP_ID_WLED = 0,
 	QPNP_ID_FLASH1_LED0,
 	QPNP_ID_FLASH1_LED1,
+	QPNP_ID_RGB_RED,
+	QPNP_ID_RGB_GREEN,
+	QPNP_ID_RGB_BLUE,
 	QPNP_ID_MAX,
 };
 
@@ -180,6 +199,11 @@
 	DELAY_128us,
 };
 
+enum rgb_mode {
+	RGB_MODE_PWM = 0,
+	RGB_MODE_LPG,
+};
+
 static u8 wled_debug_regs[] = {
 	/* common registers */
 	0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4f,
@@ -197,7 +221,9 @@
 	0x4f, 0x46, 0x47,
 };
 
-
+static u8 rgb_pwm_debug_regs[] = {
+	0x45, 0x46, 0x47,
+};
 /**
  *  wled_config_data - wled configuration data
  *  @num_strings - number of wled strings supported
@@ -248,6 +274,24 @@
 };
 
 /**
+ *  rgb_config_data - rgb configuration data
+ *  @lut_params - lut parameters to be used by pwm driver
+ *  @pwm_device - pwm device
+ *  @pwm_channel - pwm channel to be configured for led
+ *  @pwm_period_us - period for pwm, in us
+ *  @mode - mode the led operates in
+ */
+struct rgb_config_data {
+	struct lut_params	lut_params;
+	struct pwm_device	*pwm_dev;
+	int			pwm_channel;
+	u32			pwm_period_us;
+	struct pwm_duty_cycles	*duty_cycles;
+	u8	mode;
+	u8	enable;
+};
+
+/**
  * struct qpnp_led_data - internal led data structure
  * @led_classdev - led class device
  * @id - led index
@@ -268,6 +312,7 @@
 	spinlock_t		lock;
 	struct wled_config_data *wled_cfg;
 	struct flash_config_data	*flash_cfg;
+	struct rgb_config_data	*rgb_cfg;
 	int			max_current;
 	bool			default_on;
 };
@@ -458,6 +503,51 @@
 		}
 	}
 
+	qpnp_dump_regs(led, flash_debug_regs, ARRAY_SIZE(flash_debug_regs));
+
+	return 0;
+}
+
+static int qpnp_rgb_set(struct qpnp_led_data *led)
+{
+	int duty_us;
+	int rc;
+
+	if (led->cdev.brightness) {
+		if (led->rgb_cfg->mode == RGB_MODE_PWM) {
+			duty_us = (led->rgb_cfg->pwm_period_us *
+				led->cdev.brightness) / LED_FULL;
+			rc = pwm_config(led->rgb_cfg->pwm_dev, duty_us,
+					led->rgb_cfg->pwm_period_us);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev, "Failed to " \
+					"configure pwm for new values\n");
+				return rc;
+			}
+		}
+		rc = qpnp_led_masked_write(led,
+			RGB_LED_EN_CTL(led->base),
+			led->rgb_cfg->enable, led->rgb_cfg->enable);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Failed to write led enable reg\n");
+			return rc;
+		}
+		rc = pwm_enable(led->rgb_cfg->pwm_dev);
+	} else {
+		pwm_disable(led->rgb_cfg->pwm_dev);
+		rc = qpnp_led_masked_write(led,
+			RGB_LED_EN_CTL(led->base),
+			led->rgb_cfg->enable, RGB_LED_DISABLE);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Failed to write led enable reg\n");
+			return rc;
+		}
+	}
+
+	qpnp_dump_regs(led, rgb_pwm_debug_regs, ARRAY_SIZE(rgb_pwm_debug_regs));
+
 	return 0;
 }
 
@@ -490,6 +580,14 @@
 			dev_err(&led->spmi_dev->dev,
 				"FLASH set brightness failed (%d)\n", rc);
 		break;
+	case QPNP_ID_RGB_RED:
+	case QPNP_ID_RGB_GREEN:
+	case QPNP_ID_RGB_BLUE:
+		rc = qpnp_rgb_set(led);
+		if (rc < 0)
+			dev_err(&led->spmi_dev->dev,
+				"RGB set brightness failed (%d)\n", rc);
+		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		break;
@@ -507,6 +605,11 @@
 	case QPNP_ID_FLASH1_LED1:
 		led->cdev.max_brightness = led->max_current;
 		break;
+	case QPNP_ID_RGB_RED:
+	case QPNP_ID_RGB_GREEN:
+	case QPNP_ID_RGB_BLUE:
+		led->cdev.max_brightness = RGB_MAX_LEVEL;
+		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		return -EINVAL;
@@ -769,6 +872,74 @@
 	return 0;
 }
 
+static int __devinit qpnp_rgb_init(struct qpnp_led_data *led)
+{
+	int rc, start_idx, idx_len;
+
+	rc = qpnp_led_masked_write(led, RGB_LED_SRC_SEL(led->base),
+		RGB_LED_SRC_MASK, RGB_LED_SOURCE_VPH_PWR);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Failed to write led source select register\n");
+		return rc;
+	}
+
+	if (led->rgb_cfg->pwm_channel != -1) {
+		led->rgb_cfg->pwm_dev =
+			pwm_request(led->rgb_cfg->pwm_channel,
+						led->cdev.name);
+
+		if (IS_ERR_OR_NULL(led->rgb_cfg->pwm_dev)) {
+			dev_err(&led->spmi_dev->dev,
+				"could not acquire PWM Channel %d, " \
+				"error %ld\n",
+				led->rgb_cfg->pwm_channel,
+				PTR_ERR(led->rgb_cfg->pwm_dev));
+			led->rgb_cfg->pwm_dev = NULL;
+			return -ENODEV;
+		}
+
+		if (led->rgb_cfg->mode == RGB_MODE_LPG) {
+			start_idx =
+			led->rgb_cfg->duty_cycles->start_idx;
+			idx_len =
+			led->rgb_cfg->duty_cycles->num_duty_pcts;
+
+			if (idx_len >= PWM_LUT_MAX_SIZE &&
+					start_idx) {
+				dev_err(&led->spmi_dev->dev,
+					"Wrong LUT size or index\n");
+				return -EINVAL;
+			}
+			if ((start_idx + idx_len) >
+					PWM_LUT_MAX_SIZE) {
+				dev_err(&led->spmi_dev->dev,
+					"Exceed LUT limit\n");
+				return -EINVAL;
+			}
+			rc = pwm_lut_config(led->rgb_cfg->pwm_dev,
+				led->rgb_cfg->pwm_period_us,
+				led->rgb_cfg->duty_cycles->duty_pcts,
+				led->rgb_cfg->lut_params);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev, "Failed to " \
+					"configure pwm LUT\n");
+				return rc;
+			}
+		}
+	} else {
+		dev_err(&led->spmi_dev->dev,
+			"Invalid PWM channel\n");
+		return -EINVAL;
+	}
+
+	/* Initialize led for use in auto trickle charging mode */
+	rc = qpnp_led_masked_write(led, RGB_LED_ATC_CTL(led->base),
+		led->rgb_cfg->enable, led->rgb_cfg->enable);
+
+	return 0;
+}
+
 static int __devinit qpnp_led_initialize(struct qpnp_led_data *led)
 {
 	int rc;
@@ -787,12 +958,20 @@
 			dev_err(&led->spmi_dev->dev,
 				"FLASH initialize failed(%d)\n", rc);
 		break;
+	case QPNP_ID_RGB_RED:
+	case QPNP_ID_RGB_GREEN:
+	case QPNP_ID_RGB_BLUE:
+		rc = qpnp_rgb_init(led);
+		if (rc)
+			dev_err(&led->spmi_dev->dev,
+				"RGB initialize failed(%d)\n", rc);
+		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
-		rc = -EINVAL;
+		return -EINVAL;
 	}
 
-	return rc;
+	return 0;
 }
 
 static int __devinit qpnp_get_common_configs(struct qpnp_led_data *led,
@@ -965,6 +1144,120 @@
 	return 0;
 }
 
+static int __devinit qpnp_get_config_rgb(struct qpnp_led_data *led,
+				struct device_node *node)
+{
+	struct property *prop;
+	int rc, i;
+	u32 val;
+	u8 *temp_cfg;
+
+	led->rgb_cfg = devm_kzalloc(&led->spmi_dev->dev,
+				sizeof(struct rgb_config_data), GFP_KERNEL);
+	if (!led->rgb_cfg) {
+		dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	if (led->id == QPNP_ID_RGB_RED)
+		led->rgb_cfg->enable = RGB_LED_ENABLE_RED;
+	else if (led->id == QPNP_ID_RGB_GREEN)
+		led->rgb_cfg->enable = RGB_LED_ENABLE_GREEN;
+	else if (led->id == QPNP_ID_RGB_BLUE)
+		led->rgb_cfg->enable = RGB_LED_ENABLE_BLUE;
+	else
+		return -EINVAL;
+
+	rc = of_property_read_u32(node, "qcom,mode", &val);
+	if (!rc)
+		led->rgb_cfg->mode = (u8) val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
+	if (!rc)
+		led->rgb_cfg->pwm_channel = (u8) val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,pwm-us", &val);
+	if (!rc)
+		led->rgb_cfg->pwm_period_us = val;
+	else
+		return rc;
+
+	if (led->rgb_cfg->mode == RGB_MODE_LPG) {
+		led->rgb_cfg->duty_cycles =
+			devm_kzalloc(&led->spmi_dev->dev,
+			sizeof(struct pwm_duty_cycles), GFP_KERNEL);
+		if (!led->rgb_cfg->duty_cycles) {
+			dev_err(&led->spmi_dev->dev,
+				"Unable to allocate memory\n");
+			return -ENOMEM;
+		}
+
+		rc = of_property_read_u32(node, "qcom,duty-ms", &val);
+		if (!rc)
+			led->rgb_cfg->duty_cycles->duty_ms = (u8) val;
+		else
+			return rc;
+
+		prop = of_find_property(node, "qcom,duty-pcts",
+			&led->rgb_cfg->duty_cycles->num_duty_pcts);
+		if (!prop) {
+			dev_err(&led->spmi_dev->dev, "Looking up property " \
+				"node qcom,duty-pcts failed\n");
+			return -ENODEV;
+		} else if (!led->rgb_cfg->duty_cycles->num_duty_pcts) {
+			dev_err(&led->spmi_dev->dev, "Invalid length of " \
+				"duty pcts\n");
+			return -EINVAL;
+		}
+
+		led->rgb_cfg->duty_cycles->duty_pcts =
+			devm_kzalloc(&led->spmi_dev->dev,
+			sizeof(int) * led->rgb_cfg->duty_cycles->num_duty_pcts,
+			GFP_KERNEL);
+		if (!led->rgb_cfg->duty_cycles->duty_pcts) {
+			dev_err(&led->spmi_dev->dev,
+				"Unable to allocate memory\n");
+			return -ENOMEM;
+		}
+
+		temp_cfg = devm_kzalloc(&led->spmi_dev->dev,
+				led->rgb_cfg->duty_cycles->num_duty_pcts *
+				sizeof(u8), GFP_KERNEL);
+		if (!temp_cfg) {
+			dev_err(&led->spmi_dev->dev, "Failed to allocate " \
+				"memory for duty pcts\n");
+			return -ENOMEM;
+		}
+
+		memcpy(temp_cfg, prop->value,
+			led->rgb_cfg->duty_cycles->num_duty_pcts);
+
+		for (i = 0; i < led->rgb_cfg->duty_cycles->num_duty_pcts; i++)
+			led->rgb_cfg->duty_cycles->duty_pcts[i] =
+				(int) temp_cfg[i];
+
+		rc = of_property_read_u32(node, "qcom,start-idx", &val);
+		if (!rc) {
+			led->rgb_cfg->lut_params.start_idx = (u8) val;
+			led->rgb_cfg->duty_cycles->start_idx = (u8) val;
+		} else
+			return rc;
+
+		led->rgb_cfg->lut_params.idx_len =
+			led->rgb_cfg->duty_cycles->num_duty_pcts;
+		led->rgb_cfg->lut_params.lut_pause_hi = 0;
+		led->rgb_cfg->lut_params.lut_pause_lo = 0;
+		led->rgb_cfg->lut_params.ramp_step_ms = 255;
+		led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
+	}
+
+	return 0;
+}
+
 static int __devinit qpnp_leds_probe(struct spmi_device *spmi)
 {
 	struct qpnp_led_data *led;
@@ -1060,6 +1353,13 @@
 					"Unable to read flash config data\n");
 				return rc;
 			}
+		} else if (strncmp(led_label, "rgb", sizeof("rgb")) == 0) {
+			rc = qpnp_get_config_rgb(led, temp);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev,
+					"Unable to read rgb config data\n");
+				return rc;
+			}
 		} else {
 			dev_err(&led->spmi_dev->dev, "No LED matching label\n");
 			return -EINVAL;
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 80fdac5..912fad4 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -29,7 +29,6 @@
 #include "msm_vidc_debug.h"
 #include "vidc_hal_api.h"
 #include "msm_smem.h"
-#include "msm_vidc_ssr.h"
 
 #define BASE_DEVICE_NUMBER 32
 #define SHARED_QSIZE 0x1000000
@@ -1383,9 +1382,6 @@
 	core->debugfs_root = msm_vidc_debugfs_init_core(
 		core, vidc_driver->debugfs_root);
 	pdev->dev.platform_data = core;
-	rc = msm_vidc_ssr_init(core);
-	if (rc < 0)
-		dprintk(VIDC_ERR, "msm_vidc : Sub Systrem Restart failed\n");
 	return rc;
 
 err_cores_exceeded:
@@ -1414,7 +1410,6 @@
 	vidc_hal_delete_device(core->device);
 	video_unregister_device(&core->vdev[MSM_VIDC_ENCODER].vdev);
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
-	rc = msm_vidc_ssr_uninit(core);
 	v4l2_device_unregister(&core->v4l2_dev);
 	if (core->resources.ocmem.handle)
 		ocmem_notifier_unregister(core->resources.ocmem.handle,
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index fdadb36..a9f6a5d 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -136,11 +136,11 @@
 	{
 		.id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME,
 		.name = "Request I Frame",
-		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.type = V4L2_CTRL_TYPE_BUTTON,
 		.minimum = 0,
-		.maximum = 1,
+		.maximum = 0,
 		.default_value = 0,
-		.step = 1,
+		.step = 0,
 		.menu_skip_mask = 0,
 		.qmenu = NULL,
 	},
@@ -808,7 +808,7 @@
 	case V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME:
 		property_id =
 			HAL_CONFIG_VENC_REQUEST_IFRAME;
-		request_iframe.enable = control.value;
+		request_iframe.enable = true;
 		pdata = &request_iframe;
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL:
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 772f0de..02773ff 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -587,7 +587,6 @@
 
 static void handle_sys_watchdog_timeout(enum command_response cmd, void *data)
 {
-	subsystem_restart("msm_vidc");
 	dprintk(VIDC_ERR,
 		"msm_vidc: Sub System Restart initiated\n");
 }
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 9afc3df..f009e06 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -922,10 +922,15 @@
 	case VC_TYPE:
 		vc_format = (struct v4l2_format_vc_ext *) &priv_fmt->u.timing;
 		c_data->vc_format = *vc_format;
+		c_data->stride = priv_fmt->stride;
 
 		size = (c_data->vc_format.hactive_end -
 			c_data->vc_format.hactive_start);
-		size = VCAP_STRIDE_CALC(size);
+		if (c_data->stride == VC_STRIDE_32)
+			size = VCAP_STRIDE_CALC(size, VCAP_STRIDE_ALIGN_32);
+		else
+			size = VCAP_STRIDE_CALC(size, VCAP_STRIDE_ALIGN_16);
+
 
 		if (c_data->vc_format.color_space)
 			size *= 3;
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 08dcdf3..642074f 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -37,7 +37,10 @@
 	} else {
 		int size = (c_data->vc_format.hactive_end -
 				c_data->vc_format.hactive_start);
-		size = VCAP_STRIDE_CALC(size);
+		if (c_data->stride == VC_STRIDE_32)
+			size = VCAP_STRIDE_CALC(size, VCAP_STRIDE_ALIGN_32);
+		else
+			size = VCAP_STRIDE_CALC(size, VCAP_STRIDE_ALIGN_16);
 		size *= (c_data->vc_format.vactive_end -
 				c_data->vc_format.vactive_start);
 		writel_relaxed(buf->paddr, y_addr);
@@ -527,7 +530,10 @@
 	writel_iowmb(0x000033FF, VCAP_VC_BUF_CTRL);
 
 	rc = vc_format->hactive_end - vc_format->hactive_start;
-	rc = VCAP_STRIDE_CALC(rc);
+	if (c_data->stride == VC_STRIDE_32)
+		rc = VCAP_STRIDE_CALC(rc, VCAP_STRIDE_ALIGN_32);
+	else
+		rc = VCAP_STRIDE_CALC(rc, VCAP_STRIDE_ALIGN_16);
 	if (vc_format->color_space)
 		rc *= 3;
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index a752357..0c77157 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -6241,7 +6241,7 @@
  vreg_deinit:
 	msmsdcc_vreg_init(host, false);
  clk_disable:
-	clk_disable(host->clk);
+	clk_disable_unprepare(host->clk);
 	msmsdcc_msm_bus_unregister(host);
  pm_qos_remove:
 	if (host->cpu_dma_latency)
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 97703aa..cb6b23e 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -210,7 +210,6 @@
  * @dc_present:			present status of dc
  * @usb_charger_current:	usb current to charge the battery with used when
  *				the usb path is enabled or charging is resumed
- * @safety_time:		max time for which charging will happen
  * @update_time:		how frequently the userland needs to be updated
  * @max_voltage_mv:		the max volts the batt should be charged up to
  * @min_voltage_mv:		the min battery voltage before turning the FETon
@@ -231,7 +230,6 @@
 	unsigned int			usb_charger_current;
 	unsigned int			max_bat_chg_current;
 	unsigned int			pmic_chg_irq[PM_CHG_MAX_INTS];
-	unsigned int			safety_time;
 	unsigned int			ttrkl_time;
 	unsigned int			update_time;
 	unsigned int			max_voltage_mv;
@@ -2815,8 +2813,8 @@
 			goto check_again_later;
 		}
 	}
-
-	if (active_path & USB_ACTIVE_BIT) {
+	/* AICL only for usb wall charger */
+	if ((active_path & USB_ACTIVE_BIT) && usb_target_ma > 0) {
 		reg_loop = pm_chg_get_regulation_loop(chip);
 		pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
 		if ((reg_loop & VIN_ACTIVE_BIT) &&
@@ -2861,7 +2859,9 @@
 		unplug_ovp_fet_open(chip);
 	}
 
+	/* AICL only for usb wall charger */
 	if (!(reg_loop & VIN_ACTIVE_BIT) && (active_path & USB_ACTIVE_BIT)
+		&& usb_target_ma > 0
 		&& !charging_disabled) {
 		/* only increase iusb_max if vin loop not active */
 		if (usb_ma < usb_target_ma) {
@@ -3887,11 +3887,15 @@
 #define CHG_BAT_TEMP_DIS_BIT	BIT(2)
 #define SAFE_CURRENT_MA		1500
 #define PM_SUB_REV		0x001
+#define MIN_CHARGE_CURRENT_MA	350
+#define DEFAULT_SAFETY_MINUTES	500
 static int __devinit pm8921_chg_hw_init(struct pm8921_chg_chip *chip)
 {
 	int rc;
 	int vdd_safe;
 	u8 subrev;
+	int fcc_uah;
+	int safety_time = DEFAULT_SAFETY_MINUTES;
 
 	/* forcing 19p2mhz before accessing any charger registers */
 	pm8921_chg_force_19p2mhz_clk(chip);
@@ -3964,20 +3968,26 @@
 		return rc;
 	}
 
-	if (chip->safety_time != 0) {
-		rc = pm_chg_tchg_max_set(chip, chip->safety_time);
-		if (rc) {
-			pr_err("Failed to set max time to %d minutes rc=%d\n",
-							chip->safety_time, rc);
-			return rc;
-		}
+	fcc_uah = pm8921_bms_get_fcc();
+	if (fcc_uah > 0) {
+		safety_time = div_s64((s64)fcc_uah * 60,
+						1000 * MIN_CHARGE_CURRENT_MA);
+		/* add 20 minutes of buffer time */
+		safety_time += 20;
+	}
+
+	rc = pm_chg_tchg_max_set(chip, safety_time);
+	if (rc) {
+		pr_err("Failed to set max time to %d minutes rc=%d\n",
+						safety_time, rc);
+		return rc;
 	}
 
 	if (chip->ttrkl_time != 0) {
 		rc = pm_chg_ttrkl_max_set(chip, chip->ttrkl_time);
 		if (rc) {
 			pr_err("Failed to set trkl time to %d minutes rc=%d\n",
-							chip->safety_time, rc);
+							chip->ttrkl_time, rc);
 			return rc;
 		}
 	}
@@ -4383,7 +4393,6 @@
 	}
 
 	chip->dev = &pdev->dev;
-	chip->safety_time = pdata->safety_time;
 	chip->ttrkl_time = pdata->ttrkl_time;
 	chip->update_time = pdata->update_time;
 	chip->max_voltage_mv = pdata->max_voltage;
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 1f2a95e..28471ca 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -405,8 +405,9 @@
 			return -ENXIO;
 		}
 		if (txn.len == 0) {
+			/* Per protocol, only last 5 bits for client no. */
 			wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
-					sb->laddr;
+					(sb->laddr & 0x1f);
 			wbuf[txn.len] = slc->seglen;
 			if (slc->coeff == SLIM_COEFF_3)
 				wbuf[txn.len] |= 1 << 5;
@@ -420,6 +421,7 @@
 			}
 		}
 		wbuf[txn.len++] = slc->chan;
+		pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
 	}
 	if (txn.len) {
 		txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
@@ -448,8 +450,9 @@
 			return -ENXIO;
 		}
 		if (txn.len == 0) {
+			/* Per protocol, only last 5 bits for client no. */
 			wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
-					sb->laddr;
+					(sb->laddr & 0x1f);
 			ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
 			if (ret) {
 				pr_err("no tid for channel define?");
@@ -457,6 +460,7 @@
 			}
 		}
 		wbuf[txn.len++] = slc->chan;
+		pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
 	}
 	if (txn.len) {
 		txn.mc = SLIM_USR_MC_CHAN_CTRL;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 0396040..4073fc8 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1768,7 +1768,9 @@
 	}
 
 	msm->ext_xceiv.otg_capability = of_property_read_bool(node,
-				"qcom,dwc-usb3-msm-otg-capability");
+				"qcom,otg-capability");
+	msm->charger.charging_disabled = of_property_read_bool(node,
+				"qcom,charging-disabled");
 
 	if (!msm->ext_xceiv.otg_capability) {
 		/* DWC3 has separate IRQ line for OTG events (ID/BSV etc.) */
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 41dd144..7b672c4 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -393,11 +393,14 @@
 	struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg);
 
 
-	if (!dotg->psy) {
-		dev_err(phy->dev, "no usb power supply registered\n");
+	if (!dotg->psy || !dotg->charger) {
+		dev_err(phy->dev, "no usb power supply/charger registered\n");
 		return 0;
 	}
 
+	if (dotg->charger->charging_disabled)
+		return 0;
+
 	if (dotg->charger->chg_type == DWC3_SDP_CHARGER)
 		power_supply_type = POWER_SUPPLY_TYPE_USB;
 	else if (dotg->charger->chg_type == DWC3_CDP_CHARGER)
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 4384888..c93ce5f 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -70,6 +70,7 @@
 struct dwc3_charger {
 	enum dwc3_chg_type	chg_type;
 	unsigned		max_power;
+	bool			charging_disabled;
 
 	/* start/stop charger detection, provided by external charger module */
 	void	(*start_detection)(struct dwc3_charger *charger, bool start);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 92cbe6f..d10c692 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -3068,10 +3068,9 @@
 {
 	static bool init;
 	struct msm_otg *motg = the_msm_otg;
-	struct usb_otg *otg = motg->phy.otg;
 
-	/* In A Host Mode, ignore received BSV interrupts */
-	if (otg->phy->state >= OTG_STATE_A_IDLE)
+	/* Ignore received BSV interrupts, if ID pin is GND */
+	if (!test_bit(ID, &motg->inputs))
 		return;
 
 	if (online) {
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 9f30041..7a92645 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -3022,8 +3022,6 @@
 	hdmi_msm_state->hdcp_activating = TRUE;
 	mutex_unlock(&hdmi_msm_state_mutex);
 
-	fill_black_screen();
-
 	mutex_lock(&hdcp_auth_state_mutex);
 	/*
 	 * Initialize this to zero here to make
@@ -3065,8 +3063,6 @@
 	if (ret)
 		goto error;
 
-	unfill_black_screen();
-
 	mutex_lock(&hdmi_msm_state_mutex);
 	hdmi_msm_state->hdcp_activating = FALSE;
 	mutex_unlock(&hdmi_msm_state_mutex);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 985d0b0..af6ed06 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -3114,7 +3114,7 @@
 {
 	mdp_suspend_sub();
 #ifdef CONFIG_FB_MSM_DTV
-	mdp4_dtv_set_black_screen();
+	mdp4_dtv_set_black_screen(FALSE);
 #endif
 	mdp_footswitch_ctrl(FALSE);
 }
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 3ea196a..d9da6f9 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -531,7 +531,7 @@
 }
 #endif /* CONFIG_FB_MSM_DTV */
 
-void mdp4_dtv_set_black_screen(void);
+void mdp4_dtv_set_black_screen(bool commit);
 
 int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index c76e32f..11952f3 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -416,53 +416,34 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
-#ifdef CONFIG_FB_MSM_HDMI_3D
-void unfill_black_screen(void) { return; }
-#else
-void unfill_black_screen(void)
+void fill_black_screen(bool on, uint8 pipe_num, uint8 mixer_num)
 {
-	uint32 temp_src_format;
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	/*
-	* VG2 Constant Color
-	*/
-	temp_src_format = inpdw(MDP_BASE + 0x30050);
-	MDP_OUTP(MDP_BASE + 0x30050, temp_src_format&(~BIT(22)));
-	/*
-	* MDP_OVERLAY_REG_FLUSH
-	*/
-	MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	return;
-}
-#endif
+	uint32 reg_base        = 0x010000;
+	uint32 const_color_reg = reg_base * (pipe_num + 2) + 0x1008;
+	uint32 src_fmt_reg     = reg_base * (pipe_num + 2) + 0x50;
+	uint32 color           = 0x00000000;
+	uint32 temp_src_format = 0x00000000;
+	uint8  bit             = pipe_num + 2;
 
-#ifdef CONFIG_FB_MSM_HDMI_3D
-void fill_black_screen(void) { return; }
-#else
-void fill_black_screen(void)
-{
-	/*Black color*/
-	uint32 color = 0x00000000;
-	uint32 temp_src_format;
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	/*
-	* VG2 Constant Color
-	*/
-	MDP_OUTP(MDP_BASE + 0x31008, color);
-	/*
-	* MDP_VG2_SRC_FORMAT
-	*/
-	temp_src_format = inpdw(MDP_BASE + 0x30050);
-	MDP_OUTP(MDP_BASE + 0x30050, temp_src_format | BIT(22));
-	/*
-	* MDP_OVERLAY_REG_FLUSH
-	*/
-	MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
+
+	/* Fill constant color */
+	MDP_OUTP(MDP_BASE + const_color_reg, color);
+
+	/* Update source format for pipe */
+	temp_src_format = inpdw(MDP_BASE + src_fmt_reg);
+
+	if (on)
+		MDP_OUTP(MDP_BASE + src_fmt_reg, temp_src_format | BIT(22));
+	else
+		MDP_OUTP(MDP_BASE + src_fmt_reg, temp_src_format | (~BIT(22)));
+
+	/* MDP_OVERLAY_REG_FLUSH for pipe*/
+	MDP_OUTP(MDP_BASE + 0x18000, BIT(bit) | BIT(mixer_num));
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
 	return;
 }
-#endif
 
 void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe)
 {
@@ -3132,6 +3113,9 @@
 								__func__);
 	}
 
+	if (hdmi_prim_display)
+		fill_black_screen(FALSE, pipe->pipe_num, pipe->mixer_num);
+
 	mdp4_overlay_mdp_pipe_req(pipe, mfd);
 
 	mutex_unlock(&mfd->dma->ov_mutex);
@@ -3204,8 +3188,12 @@
 	if (pipe->mixer_num == MDP4_MIXER0) {
 
 	} else {	/* mixer1, DTV, ATV */
-		if (ctrl->panel_mode & MDP4_PANEL_DTV)
+		if (ctrl->panel_mode & MDP4_PANEL_DTV) {
+			if (hdmi_prim_display)
+				fill_black_screen(TRUE, pipe->pipe_num,
+					pipe->mixer_num);
 			mdp4_overlay_dtv_unset(mfd, pipe);
+		}
 	}
 
 	mdp4_stat.overlay_unset[pipe->mixer_num]++;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 5551c9d..501c4e6 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -56,6 +56,7 @@
 	int wait_vsync_cnt;
 	int blt_change;
 	int blt_free;
+	int blt_ctrl;
 	int sysfs_created;
 	struct mutex update_lock;
 	struct completion ov_comp;
@@ -498,9 +499,11 @@
 	int ret = 0;
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
+	struct msm_panel_info *pinfo;
 
 	vctrl = &vsync_ctrl_db[cndx];
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	pinfo = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -510,6 +513,7 @@
 
 	vctrl->mfd = mfd;
 	vctrl->dev = mfd->fbi->dev;
+	vctrl->blt_ctrl = pinfo->lcd.blt_ctrl;
 
 	/* mdp clock on */
 	mdp_clk_ctrl(1);
@@ -1011,6 +1015,7 @@
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	long long vtime;
 
 	vctrl = &vsync_ctrl_db[cndx];
 	pipe = vctrl->base_pipe;
@@ -1047,8 +1052,32 @@
 		spin_unlock_irqrestore(&vctrl->spin_lock, flag);
 		return;
 	}
-
 	spin_unlock_irqrestore(&vctrl->spin_lock, flag);
+
+	if (vctrl->blt_ctrl == BLT_SWITCH_TG_OFF) {
+		int tg_enabled;
+
+		vctrl->blt_change = 0;
+		tg_enabled = inpdw(MDP_BASE + DSI_VIDEO_BASE) & 0x01;
+		if (tg_enabled) {
+			mdp4_dsi_video_wait4vsync(0, &vtime);
+			MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
+			mdp4_dsi_video_wait4dmap_done(0);
+		}
+		mdp4_overlayproc_cfg(pipe);
+		mdp4_overlay_dmap_xy(pipe);
+		if (tg_enabled) {
+			/*
+			* need wait for more than 1 ms to
+			* make sure dsi lanes' fifo is empty and
+			* lanes in stop state befroe reset
+			* controller
+			*/
+			usleep(2000);
+			mipi_dsi_sw_reset();
+			MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
+		}
+	}
 }
 
 void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index e71f49f..2d48781 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -1004,7 +1004,7 @@
 	spin_unlock(&vctrl->spin_lock);
 }
 
-void mdp4_dtv_set_black_screen(void)
+void mdp4_dtv_set_black_screen(bool commit)
 {
 	char *rgb_base;
 	/*Black color*/
@@ -1015,26 +1015,34 @@
 
 	vctrl = &vsync_ctrl_db[cndx];
 	if (vctrl->base_pipe == NULL || !hdmi_prim_display) {
-		pr_err("dtv_pipe is not configured yet\n");
+		pr_debug("dtv_pipe is not configured yet\n");
 		return;
 	}
-	rgb_base = MDP_BASE + MDP4_RGB_BASE;
-	rgb_base += (MDP4_RGB_OFF * vctrl->base_pipe->pipe_num);
+	rgb_base = MDP_BASE;
+	rgb_base += (MDP4_RGB_OFF * (vctrl->base_pipe->pipe_num + 2));
 
-	/*
-	* RGB Constant Color
-	*/
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	/* RGB Constant Color */
 	MDP_OUTP(rgb_base + 0x1008, color);
-	/*
-	* MDP_RGB_SRC_FORMAT
-	*/
+
+	/* MDP_RGB_SRC_FORMAT */
 	temp_src_format = inpdw(rgb_base + 0x0050);
 	MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
-	mdp4_overlay_reg_flush(vctrl->base_pipe, 1);
 
-	mdp4_mixer_stage_up(vctrl->base_pipe, 0);
-	mdp4_mixer_stage_commit(vctrl->base_pipe->mixer_num);
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	if (commit) {
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+		mdp4_overlay_reg_flush(vctrl->base_pipe, 1);
+
+		mdp4_mixer_stage_up(vctrl->base_pipe, 0);
+		mdp4_mixer_stage_commit(vctrl->base_pipe->mixer_num);
+	} else {
+		/* MDP_OVERLAY_REG_FLUSH for pipe*/
+		MDP_OUTP(MDP_BASE + 0x18000,
+			BIT(vctrl->base_pipe->pipe_num + 2) | BIT(MDP4_MIXER1));
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
 }
 
 static void mdp4_dtv_do_blt(struct msm_fb_data_type *mfd, int enable)
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index a8f853d..d932bc9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -58,6 +58,7 @@
 
 static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
 static irqreturn_t hdmi_tx_isr(int irq, void *data);
+static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
 
 struct mdss_hw hdmi_tx_hw = {
 	.hw_ndx = MDSS_HW_HDMI,
@@ -1082,6 +1083,8 @@
 	} else {
 		msm_dss_enable_clk(power_data->clk_config,
 			power_data->num_clk, 0);
+		msm_dss_clk_set_rate(power_data->clk_config,
+			power_data->num_clk);
 		msm_dss_enable_gpio(power_data->gpio_config,
 			power_data->num_gpio, 0);
 		msm_dss_enable_vreg(power_data->vreg_config,
@@ -1616,6 +1619,7 @@
 	bool polarity)
 {
 	struct dss_io_data *io = NULL;
+	u32 cable_sense;
 
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -1632,7 +1636,12 @@
 	else
 		DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(2));
 
-	if ((DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1)) == polarity) {
+	cable_sense = (DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
+	DEV_DBG("%s: listen = %s, sense = %s\n", __func__,
+		polarity ? "connect" : "disconnect",
+		cable_sense ? "connect" : "disconnect");
+
+	if (cable_sense == polarity) {
 		u32 reg_val = DSS_REG_R(io, HDMI_HPD_CTRL);
 
 		/* Toggle HPD circuit to trigger HPD sense */
@@ -1667,13 +1676,25 @@
 	}
 
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
+
+	/*
+	 * this is needed to avoid pll lock failure due to
+	 * clk framework's rate caching.
+	 */
+	hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate = 0;
+
 	hdmi_tx_core_off(hdmi_ctrl);
 
 	mutex_lock(&hdmi_ctrl->mutex);
 	hdmi_ctrl->panel_power_on = false;
 	mutex_unlock(&hdmi_ctrl->mutex);
 
-	hdmi_tx_hpd_polarity_setup(hdmi_ctrl, HPD_CONNECT_POLARITY);
+	if (hdmi_ctrl->hpd_off_pending) {
+		hdmi_tx_hpd_off(hdmi_ctrl);
+		hdmi_ctrl->hpd_off_pending = false;
+	} else {
+		hdmi_tx_hpd_polarity_setup(hdmi_ctrl, HPD_CONNECT_POLARITY);
+	}
 
 	DEV_INFO("%s: HDMI Core: OFF\n", __func__);
 } /* hdmi_tx_power_off_work */
@@ -1860,10 +1881,20 @@
 	if (on) {
 		rc = hdmi_tx_hpd_on(hdmi_ctrl);
 	} else {
-		hdmi_tx_hpd_off(hdmi_ctrl);
-		switch_set_state(&hdmi_ctrl->sdev, 0);
-		DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
-			hdmi_ctrl->sdev.state);
+		/* If power down is already underway, wait for it to finish */
+		flush_work_sync(&hdmi_ctrl->power_off_work);
+
+		if (!hdmi_ctrl->panel_power_on) {
+			hdmi_tx_hpd_off(hdmi_ctrl);
+		} else {
+			hdmi_ctrl->hpd_off_pending = true;
+
+			switch_set_state(&hdmi_ctrl->sdev, 0);
+			DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
+				hdmi_ctrl->sdev.state);
+			DEV_DBG("HDMI HPD: sent fake OFFLINE event\n");
+			kobject_uevent(hdmi_ctrl->kobj, KOBJ_OFFLINE);
+		}
 	}
 
 	return rc;
@@ -1954,6 +1985,8 @@
 	init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done);
 
 	hdmi_ctrl->hpd_state = false;
+	hdmi_ctrl->hpd_initialized = false;
+	hdmi_ctrl->hpd_off_pending = false;
 	INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
 
 	INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 3e9fd3c..ce19355 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -54,6 +54,7 @@
 
 	u32 hpd_initialized;
 	u32 hpd_state;
+	u32 hpd_off_pending;
 	u32 hpd_feature_on;
 	struct work_struct hpd_int_work;
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index e5b5cdb..3db13f5 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -569,6 +569,17 @@
 		goto start_fail;
 	}
 
+	/* request bus bandwidth for panel commands */
+	ctl->clk_rate = MDP_CLK_DEFAULT_RATE;
+	ctl->bus_ib_quota = SZ_1M;
+	mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
+
+	ret = pdata->on(pdata);
+	if (ret) {
+		pr_err("panel power on failed ctl=%d\n", ctl->num);
+		goto panel_fail;
+	}
+
 	pr_debug("ctl_num=%d\n", ctl->num);
 
 	mixer = ctl->mixer_left;
@@ -596,17 +607,16 @@
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, outsize);
 		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
 	}
-
-	/* request bus bandwidth for panel commands */
-	ctl->clk_rate = MDP_CLK_DEFAULT_RATE;
-	ctl->bus_ib_quota = SZ_1M;
-	mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
-
-	ret = pdata->on(pdata);
-
+panel_fail:
+	if (ret && ctl->stop_fnc)
+		ctl->stop_fnc(ctl);
 start_fail:
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 	mutex_unlock(&ctl->lock);
+	if (ret) {
+		mdss_mdp_ctl_destroy(mfd);
+		mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
+	}
 
 	return ret;
 }
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 527b02f..5189b6d 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -653,12 +653,6 @@
 	struct msm_fb_panel_data *pdata = NULL;
 	int ret = 0;
 
-	if (hdmi_prim_display) {
-		MSM_FB_INFO("%s: hdmi primary handles early suspend only\n",
-			__func__);
-		return 0;
-	}
-
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
@@ -684,12 +678,6 @@
 	struct msm_fb_panel_data *pdata = NULL;
 	int ret = 0;
 
-	if (hdmi_prim_display) {
-		MSM_FB_INFO("%s: hdmi primary handles early resume only\n",
-			__func__);
-		return 0;
-	}
-
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
@@ -714,8 +702,7 @@
 	.runtime_suspend = msm_fb_runtime_suspend,
 	.runtime_resume = msm_fb_runtime_resume,
 	.runtime_idle = msm_fb_runtime_idle,
-#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL) && \
-	!defined(CONFIG_FB_MSM_HDMI_AS_PRIMARY))
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
 	.suspend = msm_fb_ext_suspend,
 	.resume = msm_fb_ext_resume,
 #endif
@@ -749,9 +736,7 @@
 static void msmfb_early_suspend(struct early_suspend *h)
 {
 	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-						early_suspend);
-	struct msm_fb_panel_data *pdata = NULL;
-
+						    early_suspend);
 #if defined(CONFIG_FB_MSM_MDP303)
 	/*
 	* For MDP with overlay, set framebuffer with black pixels
@@ -769,37 +754,12 @@
 	}
 #endif
 	msm_fb_suspend_sub(mfd);
-
-	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-	if (hdmi_prim_display &&
-		(mfd->panel_info.type == HDMI_PANEL ||
-		 mfd->panel_info.type == DTV_PANEL)) {
-		/* Turn off the HPD circuitry */
-		if (pdata->power_ctrl) {
-			MSM_FB_INFO("%s: Turning off HPD circuitry\n",
-				__func__);
-			pdata->power_ctrl(FALSE);
-		}
-	}
 }
 
 static void msmfb_early_resume(struct early_suspend *h)
 {
 	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-						early_suspend);
-	struct msm_fb_panel_data *pdata = NULL;
-
-	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-	if (hdmi_prim_display &&
-		(mfd->panel_info.type == HDMI_PANEL ||
-		 mfd->panel_info.type == DTV_PANEL)) {
-		/* Turn on the HPD circuitry */
-		if (pdata->power_ctrl) {
-			MSM_FB_INFO("%s: Turning on HPD circuitry\n", __func__);
-			pdata->power_ctrl(TRUE);
-		}
-	}
-
+						    early_suspend);
 	msm_fb_resume_sub(mfd);
 }
 #endif
@@ -1510,10 +1470,7 @@
 	ret = 0;
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
-
-	if (hdmi_prim_display ||
-	    (mfd->panel_info.type != DTV_PANEL &&
-	     mfd->panel_info.type != WRITEBACK_PANEL)) {
+	if (mfd->panel_info.type != DTV_PANEL) {
 		mfd->early_suspend.suspend = msmfb_early_suspend;
 		mfd->early_suspend.resume = msmfb_early_resume;
 		mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 1594825..7d8ad73 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -214,8 +214,7 @@
 void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
 #endif
 
-void fill_black_screen(void);
-void unfill_black_screen(void);
+void fill_black_screen(bool on, uint8 pipe_num, uint8 mixer_num);
 int msm_fb_check_frame_rate(struct msm_fb_data_type *mfd,
 				struct fb_info *info);
 
diff --git a/drivers/video/msm/msm_fb_panel.h b/drivers/video/msm/msm_fb_panel.h
index 7fc7a2f..bdd4f3bb 100644
--- a/drivers/video/msm/msm_fb_panel.h
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -56,6 +56,11 @@
 	MAX_PHYS_TARGET_NUM,
 } DISP_TARGET_PHYS;
 
+enum {
+	BLT_SWITCH_TG_OFF,
+	BLT_SWITCH_TG_ON
+};
+
 /* panel info type */
 struct lcd_panel_info {
 	__u32 vsync_enable;
@@ -65,6 +70,7 @@
 	__u32 v_pulse_width;
 	__u32 hw_vsync_mode;
 	__u32 vsync_notifier_period;
+	__u32 blt_ctrl;
 	__u32 rev;
 };
 
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
index 547ab56..18513e3 100644
--- a/include/linux/dma-attrs.h
+++ b/include/linux/dma-attrs.h
@@ -15,6 +15,8 @@
 	DMA_ATTR_WEAK_ORDERING,
 	DMA_ATTR_WRITE_COMBINE,
 	DMA_ATTR_NON_CONSISTENT,
+	DMA_ATTR_NO_KERNEL_MAPPING,
+	DMA_ATTR_STRONGLY_ORDERED,
 	DMA_ATTR_MAX,
 };
 
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index d9e20ff..4ad55f4 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -58,7 +58,6 @@
 
 /**
  * struct pm8921_charger_platform_data -
- * @safety_time:	max charging time in minutes incl. fast and trkl
  *			valid range 4 to 512 min. PON default 120 min
  * @ttrkl_time:		max trckl charging time in minutes
  *			valid range 1 to 64 mins. PON default 15 min
@@ -130,7 +129,6 @@
  */
 struct pm8921_charger_platform_data {
 	struct pm8xxx_charger_core_data	charger_cdata;
-	unsigned int			safety_time;
 	unsigned int			ttrkl_time;
 	unsigned int			update_time;
 	unsigned int			max_voltage;
diff --git a/include/linux/qmi_encdec.h b/include/linux/qmi_encdec.h
new file mode 100644
index 0000000..4c5f6d3
--- /dev/null
+++ b/include/linux/qmi_encdec.h
@@ -0,0 +1,169 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _QMI_ENCDEC_H_
+#define _QMI_ENCDEC_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+
+#define QMI_REQUEST_CONTROL_FLAG 0x00
+#define QMI_RESPONSE_CONTROL_FLAG 0x02
+#define QMI_INDICATION_CONTROL_FLAG 0x04
+#define QMI_HEADER_SIZE 7
+
+/**
+ * elem_type - Enum to identify the data type of elements in a data
+ *             structure.
+ */
+enum elem_type {
+	QMI_OPT_FLAG = 1,
+	QMI_DATA_LEN,
+	QMI_UNSIGNED_1_BYTE,
+	QMI_UNSIGNED_2_BYTE,
+	QMI_UNSIGNED_4_BYTE,
+	QMI_UNSIGNED_8_BYTE,
+	QMI_SIGNED_2_BYTE_ENUM,
+	QMI_SIGNED_4_BYTE_ENUM,
+	QMI_STRUCT,
+	QMI_EOTI,
+};
+
+/**
+ * array_type - Enum to identify if an element in a data structure is
+ *              an array. If so, then is it a static length array or a
+ *              variable length array.
+ */
+enum array_type {
+	NO_ARRAY = 0,
+	STATIC_ARRAY = 1,
+	VAR_LEN_ARRAY = 2,
+};
+
+/**
+ * elem_info - Data structure to specify information about an element
+ *               in a data structure. An array of this data structure
+ *               can be used to specify info about a complex data
+ *               structure to be encoded/decoded.
+ *
+ * @data_type: Data type of this element.
+ * @elem_len: Array length of this element, if an array.
+ * @elem_size: Size of a single instance of this data type.
+ * @is_array: Array type of this element.
+ * @tlv_type: QMI message specific type to identify which element
+ *            is present in an incoming message.
+ * @offset: To identify the address of the first instance of this
+ *          element in the data structure.
+ * @ei_array: Array to provide information about the nested structure
+ *            within a data structure to be encoded/decoded.
+ */
+struct elem_info {
+	enum elem_type data_type;
+	uint32_t elem_len;
+	uint32_t elem_size;
+	enum array_type is_array;
+	uint8_t tlv_type;
+	uint32_t offset;
+	struct elem_info *ei_array;
+};
+
+/**
+ * @msg_desc - Describe about the main/outer structure to be
+ *		  encoded/decoded.
+ *
+ * @max_msg_len: Maximum possible length of the QMI message.
+ * @ei_array: Array to provide information about a data structure.
+ */
+struct msg_desc {
+	uint16_t msg_id;
+	int max_msg_len;
+	struct elem_info *ei_array;
+};
+
+struct qmi_header {
+	unsigned char cntl_flag;
+	uint16_t txn_id;
+	uint16_t msg_id;
+	uint16_t msg_len;
+} __attribute__((__packed__));
+
+static inline void encode_qmi_header(unsigned char *buf,
+			unsigned char cntl_flag, uint16_t txn_id,
+			uint16_t msg_id, uint16_t msg_len)
+{
+	struct qmi_header *hdr = (struct qmi_header *)buf;
+
+	hdr->cntl_flag = cntl_flag;
+	hdr->txn_id = txn_id;
+	hdr->msg_id = msg_id;
+	hdr->msg_len = msg_len;
+}
+
+static inline void decode_qmi_header(unsigned char *buf,
+			unsigned char *cntl_flag, uint16_t *txn_id,
+			uint16_t *msg_id, uint16_t *msg_len)
+{
+	struct qmi_header *hdr = (struct qmi_header *)buf;
+
+	*cntl_flag = hdr->cntl_flag;
+	*txn_id = hdr->txn_id;
+	*msg_id = hdr->msg_id;
+	*msg_len = hdr->msg_len;
+}
+
+#ifdef CONFIG_QMI_ENCDEC
+/**
+ * qmi_kernel_encode() - Encode to QMI message wire format
+ * @desc: Pointer to structure descriptor.
+ * @out_buf: Buffer to hold the encoded QMI message.
+ * @out_buf_len: Length of the out buffer.
+ * @in_c_struct: C Structure to be encoded.
+ *
+ * @return: size of encoded message on success, < 0 on error.
+ */
+int qmi_kernel_encode(struct msg_desc *desc,
+		      void *out_buf, uint32_t out_buf_len,
+		      void *in_c_struct);
+
+/**
+ * qmi_kernel_decode() - Decode to C Structure format
+ * @desc: Pointer to structure descriptor.
+ * @out_c_struct: Buffer to hold the decoded C structure.
+ * @in_buf: Buffer containg the QMI message to be decoded.
+ * @in_buf_len: Length of the incoming QMI message.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_kernel_decode(struct msg_desc *desc, void *out_c_struct,
+		      void *in_buf, uint32_t in_buf_len);
+
+#else
+static inline int qmi_kernel_encode(struct msg_desc *desc,
+				    void *out_buf, uint32_t out_buf_len,
+				    void *in_c_struct)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int qmi_kernel_decode(struct msg_desc *desc,
+				    void *out_c_struct,
+				    void *in_buf, uint32_t in_buf_len)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
+#endif
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 13b3f05..84d9b42 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -120,8 +120,14 @@
 	VP_OUT_TYPE,
 };
 
+enum vcap_stride {
+	VC_STRIDE_16,
+	VC_STRIDE_32,
+};
+
 struct vcap_priv_fmt {
 	enum vcap_type type;
+	enum vcap_stride stride;
 	union {
 		struct v4l2_format_vc_ext timing;
 		struct v4l2_pix_format pix;
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 2d3b5c5..39aa1b9 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -39,10 +39,10 @@
 
 #define VCAP_USEC (1000000)
 
-#define VCAP_STRIDE_ALIGN 0x10
-#define VCAP_STRIDE_CALC(x) (((x / VCAP_STRIDE_ALIGN) + \
-			(!(!(x % VCAP_STRIDE_ALIGN)))) * \
-			VCAP_STRIDE_ALIGN)
+#define VCAP_STRIDE_ALIGN_16 0x10
+#define VCAP_STRIDE_ALIGN_32 0x20
+#define VCAP_STRIDE_CALC(x, align) (((x / align) + \
+			(!(!(x % align)))) * align)
 
 #define VCAP_BASE (dev->vcapbase)
 #define VCAP_OFFSET(off) (VCAP_BASE + off)
@@ -241,6 +241,7 @@
 	enum vcap_op_mode		op_mode;
 
 	struct v4l2_format_vc_ext vc_format;
+	enum vcap_stride		stride;
 
 	enum v4l2_buf_type		vp_buf_type_field;
 	struct vp_format_data	vp_in_fmt;
diff --git a/include/sound/cs8427.h b/include/sound/cs8427.h
index 2004ec3..a1e988d 100644
--- a/include/sound/cs8427.h
+++ b/include/sound/cs8427.h
@@ -209,7 +209,8 @@
 	int irq_base;
 	int num_irqs;
 	int reset_gpio;
-	int (*enable) (int enable);
+	int (*enable) (int enable, int gpio);
+	int ls_gpio;
 };
 
 struct snd_pcm_substream;
diff --git a/lib/Kconfig b/lib/Kconfig
index 4a8aba2..f1621d5 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -378,4 +378,13 @@
 	  Digital signature verification. Currently only RSA is supported.
 	  Implementation is done using GnuPG MPI library
 
+config QMI_ENCDEC
+	bool
+	help
+	  Library to encode & decode QMI messages from within
+	  the kernel. The kernel drivers encode the C structure into
+	  QMI message wire format and then send it over a transport.
+	  The kernel drivers receive the QMI message over a transport
+	  and then decode it into a C structure.
+
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index acd6869..0fbcb04 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -123,6 +123,8 @@
 
 obj-$(CONFIG_CLZ_TAB) += clz_tab.o
 
+obj-$(CONFIG_QMI_ENCDEC) += qmi_encdec.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
diff --git a/lib/qmi_encdec.c b/lib/qmi_encdec.c
new file mode 100644
index 0000000..d759885
--- /dev/null
+++ b/lib/qmi_encdec.c
@@ -0,0 +1,492 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/qmi_encdec.h>
+
+#include "qmi_encdec_priv.h"
+
+#define TLV_LEN_SIZE sizeof(uint16_t)
+#define TLV_TYPE_SIZE sizeof(uint8_t)
+
+static int _qmi_kernel_encode(struct elem_info *ei_array,
+			      void *out_buf, void *in_c_struct,
+			      int enc_level);
+
+static int _qmi_kernel_decode(struct elem_info *ei_array,
+			      void *out_c_struct,
+			      void *in_buf, uint32_t in_buf_len,
+			      int dec_level);
+
+/**
+ * qmi_kernel_encode() - Encode to QMI message wire format
+ * @desc: Pointer to structure descriptor.
+ * @out_buf: Buffer to hold the encoded QMI message.
+ * @out_buf_len: Length of the out buffer.
+ * @in_c_struct: C Structure to be encoded.
+ *
+ * @return: size of encoded message on success, < 0 for error.
+ */
+int qmi_kernel_encode(struct msg_desc *desc,
+		      void *out_buf, uint32_t out_buf_len,
+		      void *in_c_struct)
+{
+	int enc_level = 1;
+
+	if (!desc || !desc->ei_array)
+		return -EINVAL;
+
+	if (!out_buf || !in_c_struct)
+		return -EINVAL;
+
+	if (desc->max_msg_len < out_buf_len)
+		return -ETOOSMALL;
+
+	return _qmi_kernel_encode(desc->ei_array, out_buf,
+				  in_c_struct, enc_level);
+}
+EXPORT_SYMBOL(qmi_kernel_encode);
+
+/**
+ * qmi_encode_basic_elem() - Encodes elements of basic/primary data type
+ * @buf_dst: Buffer to store the encoded information.
+ * @buf_src: Buffer containing the elements to be encoded.
+ * @elem_len: Number of elements, in the buf_src, to be encoded.
+ * @elem_size: Size of a single instance of the element to be encoded.
+ *
+ * @return: number of bytes of encoded information.
+ *
+ * This function encodes the "elem_len" number of data elements, each of
+ * size "elem_size" bytes from the source buffer "buf_src" and stores the
+ * encoded information in the destination buffer "buf_dst". The elements are
+ * of primary data type which include uint8_t - uint64_t or similar. This
+ * function returns the number of bytes of encoded information.
+ */
+static int qmi_encode_basic_elem(void *buf_dst, void *buf_src,
+				 uint32_t elem_len, uint32_t elem_size)
+{
+	uint32_t i, rc = 0;
+
+	for (i = 0; i < elem_len; i++) {
+		QMI_ENCDEC_ENCODE_N_BYTES(buf_dst, buf_src, elem_size);
+		rc += elem_size;
+	}
+
+	return rc;
+}
+
+/**
+ * qmi_encode_struct_elem() - Encodes elements of struct data type
+ * @ei_array: Struct info array descibing the struct element.
+ * @buf_dst: Buffer to store the encoded information.
+ * @buf_src: Buffer containing the elements to be encoded.
+ * @elem_len: Number of elements, in the buf_src, to be encoded.
+ * @enc_level: Depth of the nested structure from the main structure.
+ *
+ * @return: Mumber of bytes of encoded information, on success.
+ *          < 0 on error.
+ *
+ * This function encodes the "elem_len" number of struct elements, each of
+ * size "ei_array->elem_size" bytes from the source buffer "buf_src" and
+ * stores the encoded information in the destination buffer "buf_dst". The
+ * elements are of struct data type which includes any C structure. This
+ * function returns the number of bytes of encoded information.
+ */
+static int qmi_encode_struct_elem(struct elem_info *ei_array,
+				  void *buf_dst, void *buf_src,
+				  uint32_t elem_len, int enc_level)
+{
+	int i, rc, encoded_bytes = 0;
+	struct elem_info *temp_ei = ei_array;
+
+	for (i = 0; i < elem_len; i++) {
+		rc = _qmi_kernel_encode(temp_ei->ei_array,
+					buf_dst, buf_src, enc_level);
+		if (rc < 0) {
+			pr_err("%s: STRUCT Encode failure\n", __func__);
+			return rc;
+		}
+		buf_dst = buf_dst + rc;
+		buf_src = buf_src + temp_ei->elem_size;
+		encoded_bytes += rc;
+	}
+
+	return encoded_bytes;
+}
+
+/**
+ * skip_to_next_elem() - Skip to next element in the structure to be encoded
+ * @ei_array: Struct info describing the element to be skipped.
+ *
+ * @return: Struct info of the next element that can be encoded.
+ *
+ * This function is used while encoding optional elements. If the flag
+ * corresponding to an optional element is not set, then encoding the
+ * optional element can be skipped. This function can be used to perform
+ * that operation.
+ */
+static struct elem_info *skip_to_next_elem(struct elem_info *ei_array)
+{
+	struct elem_info *temp_ei = ei_array;
+	uint8_t tlv_type;
+
+	do {
+		tlv_type = temp_ei->tlv_type;
+		temp_ei = temp_ei + 1;
+	} while (tlv_type == temp_ei->tlv_type);
+
+	return temp_ei;
+}
+
+/**
+ * _qmi_kernel_encode() - Core Encode Function
+ * @ei_array: Struct info array describing the structure to be encoded.
+ * @out_buf: Buffer to hold the encoded QMI message.
+ * @in_c_struct: Pointer to the C structure to be encoded.
+ * @enc_level: Encode level to indicate the depth of the nested structure,
+ *             within the main structure, being encoded.
+ *
+ * @return: Number of bytes of encoded information, on success.
+ *          < 0 on error.
+ */
+static int _qmi_kernel_encode(struct elem_info *ei_array,
+			      void *out_buf, void *in_c_struct,
+			      int enc_level)
+{
+	struct elem_info *temp_ei = ei_array;
+	uint8_t opt_flag_value = 0;
+	uint32_t data_len_value = 0, data_len_sz;
+	uint8_t *buf_dst = (uint8_t *)out_buf;
+	uint8_t *tlv_pointer;
+	uint32_t tlv_len;
+	uint8_t tlv_type;
+	uint32_t encoded_bytes = 0;
+	void *buf_src;
+	int encode_tlv = 0;
+	int rc;
+
+	tlv_pointer = buf_dst;
+	tlv_len = 0;
+	buf_dst = buf_dst + (TLV_LEN_SIZE + TLV_TYPE_SIZE);
+
+	while (temp_ei->data_type != QMI_EOTI) {
+		buf_src = in_c_struct + temp_ei->offset;
+		tlv_type = temp_ei->tlv_type;
+
+		if (temp_ei->is_array == NO_ARRAY) {
+			data_len_value = 1;
+		} else if (temp_ei->is_array == STATIC_ARRAY) {
+			data_len_value = temp_ei->elem_len;
+		} else if (data_len_value <= 0 ||
+			    temp_ei->elem_len < data_len_value) {
+			pr_err("%s: Invalid data length\n", __func__);
+			return -EINVAL;
+		}
+
+		switch (temp_ei->data_type) {
+		case QMI_OPT_FLAG:
+			rc = qmi_encode_basic_elem(&opt_flag_value, buf_src,
+						   1, sizeof(uint8_t));
+			if (opt_flag_value)
+				temp_ei = temp_ei + 1;
+			else
+				temp_ei = skip_to_next_elem(temp_ei);
+			break;
+
+		case QMI_DATA_LEN:
+			memcpy(&data_len_value, buf_src, temp_ei->elem_size);
+			data_len_sz = temp_ei->elem_size == sizeof(uint8_t) ?
+					sizeof(uint8_t) : sizeof(uint16_t);
+			rc = qmi_encode_basic_elem(buf_dst, &data_len_value,
+						   1, data_len_sz);
+			if (data_len_value) {
+				UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
+					encoded_bytes, tlv_len, encode_tlv, rc);
+				encode_tlv = 0;
+			} else {
+				temp_ei = skip_to_next_elem(temp_ei);
+			}
+			break;
+
+		case QMI_UNSIGNED_1_BYTE:
+		case QMI_UNSIGNED_2_BYTE:
+		case QMI_UNSIGNED_4_BYTE:
+		case QMI_UNSIGNED_8_BYTE:
+		case QMI_SIGNED_2_BYTE_ENUM:
+		case QMI_SIGNED_4_BYTE_ENUM:
+			rc = qmi_encode_basic_elem(buf_dst, buf_src,
+				data_len_value, temp_ei->elem_size);
+			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
+				encoded_bytes, tlv_len, encode_tlv, rc);
+			break;
+
+		case QMI_STRUCT:
+			rc = qmi_encode_struct_elem(temp_ei, buf_dst, buf_src,
+				data_len_value, (enc_level + 1));
+			if (rc < 0)
+				return rc;
+			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
+				encoded_bytes, tlv_len, encode_tlv, rc);
+			break;
+
+		default:
+			pr_err("%s: Unrecognized data type\n", __func__);
+			return -EINVAL;
+
+		}
+
+		if (encode_tlv && enc_level == 1) {
+			QMI_ENCDEC_ENCODE_TLV(tlv_type, tlv_len, tlv_pointer);
+			encoded_bytes += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
+			tlv_pointer = buf_dst;
+			tlv_len = 0;
+			buf_dst = buf_dst + TLV_LEN_SIZE + TLV_TYPE_SIZE;
+			encode_tlv = 0;
+		}
+	}
+	return encoded_bytes;
+}
+
+/**
+ * qmi_kernel_decode() - Decode to C Structure format
+ * @desc: Pointer to structure descriptor.
+ * @out_c_struct: Buffer to hold the decoded C structure.
+ * @in_buf: Buffer containg the QMI message to be decoded.
+ * @in_buf_len: Length of the incoming QMI message.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_kernel_decode(struct msg_desc *desc, void *out_c_struct,
+		      void *in_buf, uint32_t in_buf_len)
+{
+	int dec_level = 1;
+	int rc = 0;
+
+	if (!desc || !desc->ei_array)
+		return -EINVAL;
+
+	if (!out_c_struct || !in_buf || !in_buf_len)
+		return -EINVAL;
+
+	if (desc->max_msg_len < in_buf_len)
+		return -EINVAL;
+
+	rc = _qmi_kernel_decode(desc->ei_array, out_c_struct,
+				in_buf, in_buf_len, dec_level);
+	if (rc < 0)
+		return rc;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(qmi_kernel_decode);
+
+/**
+ * qmi_decode_basic_elem() - Decodes elements of basic/primary data type
+ * @buf_dst: Buffer to store the decoded element.
+ * @buf_src: Buffer containing the elements in QMI wire format.
+ * @elem_len: Number of elements to be decoded.
+ * @elem_size: Size of a single instance of the element to be decoded.
+ *
+ * @return: Total size of the decoded data elements, in bytes.
+ *
+ * This function decodes the "elem_len" number of elements in QMI wire format,
+ * each of size "elem_size" bytes from the source buffer "buf_src" and stores
+ * the decoded elements in the destination buffer "buf_dst". The elements are
+ * of primary data type which include uint8_t - uint64_t or similar. This
+ * function returns the number of bytes of decoded information.
+ */
+static int qmi_decode_basic_elem(void *buf_dst, void *buf_src,
+				 uint32_t elem_len, uint32_t elem_size)
+{
+	uint32_t i, rc = 0;
+
+	for (i = 0; i < elem_len; i++) {
+		QMI_ENCDEC_DECODE_N_BYTES(buf_dst, buf_src, elem_size);
+		rc += elem_size;
+	}
+
+	return rc;
+}
+
+/**
+ * qmi_decode_struct_elem() - Decodes elements of struct data type
+ * @ei_array: Struct info array descibing the struct element.
+ * @buf_dst: Buffer to store the decoded element.
+ * @buf_src: Buffer containing the elements in QMI wire format.
+ * @elem_len: Number of elements to be decoded.
+ * @tlv_len: Total size of the encoded inforation corresponding to
+ *           this struct element.
+ * @dec_level: Depth of the nested structure from the main structure.
+ *
+ * @return: Total size of the decoded data elements, on success.
+ *          < 0 on error.
+ *
+ * This function decodes the "elem_len" number of elements in QMI wire format,
+ * each of size "(tlv_len/elem_len)" bytes from the source buffer "buf_src"
+ * and stores the decoded elements in the destination buffer "buf_dst". The
+ * elements are of struct data type which includes any C structure. This
+ * function returns the number of bytes of decoded information.
+ */
+static int qmi_decode_struct_elem(struct elem_info *ei_array, void *buf_dst,
+				  void *buf_src, uint32_t elem_len,
+				  uint32_t tlv_len, int dec_level)
+{
+	int i, rc, decoded_bytes = 0;
+	struct elem_info *temp_ei = ei_array;
+
+	for (i = 0; i < elem_len; i++) {
+		rc = _qmi_kernel_decode(temp_ei->ei_array, buf_dst, buf_src,
+					(tlv_len/elem_len), dec_level);
+		if (rc < 0)
+			return rc;
+		if (rc != (tlv_len/elem_len)) {
+			pr_err("%s: Fault in decoding\n", __func__);
+			return -EFAULT;
+		}
+		buf_src = buf_src + rc;
+		buf_dst = buf_dst + temp_ei->elem_size;
+		decoded_bytes += rc;
+	}
+
+	return decoded_bytes;
+}
+
+/**
+ * find_ei() - Find element info corresponding to TLV Type
+ * @ei_array: Struct info array of the message being decoded.
+ * @type: TLV Type of the element being searched.
+ *
+ * @return: Pointer to struct info, if found
+ *
+ * Every element that got encoded in the QMI message will have a type
+ * information associated with it. While decoding the QMI message,
+ * this function is used to find the struct info regarding the element
+ * that corresponds to the type being decoded.
+ */
+static struct elem_info *find_ei(struct elem_info *ei_array,
+				   uint32_t type)
+{
+	struct elem_info *temp_ei = ei_array;
+	while (temp_ei->data_type != QMI_EOTI) {
+		if (temp_ei->tlv_type == (uint8_t)type)
+			return temp_ei;
+		temp_ei = temp_ei + 1;
+	}
+	return NULL;
+}
+
+/**
+ * _qmi_kernel_decode() - Core Decode Function
+ * @ei_array: Struct info array describing the structure to be decoded.
+ * @out_c_struct: Buffer to hold the decoded C struct
+ * @in_buf: Buffer containing the QMI message to be decoded
+ * @in_buf_len: Length of the QMI message to be decoded
+ * @dec_level: Decode level to indicate the depth of the nested structure,
+ *             within the main structure, being decoded
+ *
+ * @return: Number of bytes of decoded information, on success
+ *          < 0 on error.
+ */
+static int _qmi_kernel_decode(struct elem_info *ei_array,
+			      void *out_c_struct,
+			      void *in_buf, uint32_t in_buf_len,
+			      int dec_level)
+{
+	struct elem_info *temp_ei = ei_array;
+	uint8_t opt_flag_value = 1;
+	uint32_t data_len_value = 0, data_len_sz = 0;
+	uint8_t *buf_dst = out_c_struct;
+	uint8_t *tlv_pointer;
+	uint32_t tlv_len = 0;
+	uint32_t tlv_type;
+	uint32_t decoded_bytes = 0;
+	void *buf_src = in_buf;
+	int rc;
+
+	while (decoded_bytes < in_buf_len) {
+		if (dec_level == 1) {
+			tlv_pointer = buf_src;
+			QMI_ENCDEC_DECODE_TLV(&tlv_type,
+					      &tlv_len, tlv_pointer);
+			buf_src += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
+			decoded_bytes += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
+			temp_ei = find_ei(ei_array, tlv_type);
+			if (!temp_ei) {
+				pr_err("%s: Inval element info\n", __func__);
+				return -EINVAL;
+			}
+		}
+
+		buf_dst = out_c_struct + temp_ei->offset;
+		if (temp_ei->data_type == QMI_OPT_FLAG) {
+			memcpy(buf_dst, &opt_flag_value, sizeof(uint8_t));
+			temp_ei = temp_ei + 1;
+			buf_dst = out_c_struct + temp_ei->offset;
+		}
+
+		if (temp_ei->data_type == QMI_DATA_LEN) {
+			data_len_sz = temp_ei->elem_size == sizeof(uint8_t) ?
+					sizeof(uint8_t) : sizeof(uint16_t);
+			rc = qmi_decode_basic_elem(&data_len_value, buf_src,
+						   1, data_len_sz);
+			memcpy(buf_dst, &data_len_value, sizeof(uint32_t));
+			temp_ei = temp_ei + 1;
+			buf_dst = out_c_struct + temp_ei->offset;
+			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
+		}
+
+		if (temp_ei->is_array == NO_ARRAY) {
+			data_len_value = 1;
+		} else if (temp_ei->is_array == STATIC_ARRAY) {
+			data_len_value = temp_ei->elem_len;
+		} else if (data_len_value > temp_ei->elem_len) {
+			pr_err("%s: Data len %d > max spec %d\n",
+				__func__, data_len_value, temp_ei->elem_len);
+			return -ETOOSMALL;
+		}
+
+		switch (temp_ei->data_type) {
+		case QMI_UNSIGNED_1_BYTE:
+		case QMI_UNSIGNED_2_BYTE:
+		case QMI_UNSIGNED_4_BYTE:
+		case QMI_UNSIGNED_8_BYTE:
+		case QMI_SIGNED_2_BYTE_ENUM:
+		case QMI_SIGNED_4_BYTE_ENUM:
+			rc = qmi_decode_basic_elem(buf_dst, buf_src,
+				data_len_value, temp_ei->elem_size);
+			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
+			break;
+
+		case QMI_STRUCT:
+			rc = qmi_decode_struct_elem(temp_ei, buf_dst, buf_src,
+				data_len_value, tlv_len, (dec_level + 1));
+			if (rc < 0)
+				return rc;
+			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
+			break;
+		default:
+			pr_err("%s: Unrecognized data type\n", __func__);
+			return -EINVAL;
+		}
+		temp_ei = temp_ei + 1;
+	}
+	return decoded_bytes;
+}
+MODULE_DESCRIPTION("QMI kernel enc/dec");
+MODULE_LICENSE("GPL v2");
diff --git a/lib/qmi_encdec_priv.h b/lib/qmi_encdec_priv.h
new file mode 100644
index 0000000..97fe45b
--- /dev/null
+++ b/lib/qmi_encdec_priv.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _QMI_ENCDEC_PRIV_H_
+#define _QMI_ENCDEC_PRIV_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+#include <linux/qmi_encdec.h>
+
+#define QMI_ENCDEC_ENCODE_TLV(type, length, p_dst) do { \
+	*p_dst++ = type; \
+	*p_dst++ = ((uint8_t)((length) & 0xFF)); \
+	*p_dst++ = ((uint8_t)(((length) >> 8) & 0xFF)); \
+} while (0)
+
+#define QMI_ENCDEC_DECODE_TLV(p_type, p_length, p_src) do { \
+	*p_type = (uint8_t)*p_src++; \
+	*p_length = (uint8_t)*p_src++; \
+	*p_length |= ((uint8_t)*p_src) << 8; \
+} while (0)
+
+#define QMI_ENCDEC_ENCODE_N_BYTES(p_dst, p_src, size) \
+do { \
+	memcpy(p_dst, p_src, size); \
+	p_dst = (uint8_t *)p_dst + size; \
+	p_src = (uint8_t *)p_src + size; \
+} while (0)
+
+#define QMI_ENCDEC_DECODE_N_BYTES(p_dst, p_src, size) \
+do { \
+	memcpy(p_dst, p_src, size); \
+	p_dst = (uint8_t *)p_dst + size; \
+	p_src = (uint8_t *)p_src + size; \
+} while (0)
+
+#define UPDATE_ENCODE_VARIABLES(temp_si, buf_dst, \
+				encoded_bytes, tlv_len, encode_tlv, rc) \
+do { \
+	buf_dst = (uint8_t *)buf_dst + rc; \
+	encoded_bytes += rc; \
+	tlv_len += rc; \
+	temp_si = temp_si + 1; \
+	encode_tlv = 1; \
+} while (0)
+
+#define UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc) \
+do { \
+	buf_src = (uint8_t *)buf_src + rc; \
+	decoded_bytes += rc; \
+} while (0)
+
+#endif
diff --git a/sound/soc/codecs/cs8427.c b/sound/soc/codecs/cs8427.c
index 23870a4..6e08742 100644
--- a/sound/soc/codecs/cs8427.c
+++ b/sound/soc/codecs/cs8427.c
@@ -110,7 +110,7 @@
 	 * with CS8427 chip
 	 */
 	if (pdata->enable) {
-		err = pdata->enable(1);
+		err = pdata->enable(1, pdata->ls_gpio);
 		if (err < 0) {
 			dev_err(&chip->client->dev,
 				"failed to enable the level shifter\n");
@@ -124,7 +124,7 @@
 	 * with CS8427 chip
 	 */
 	if (pdata->enable) {
-		err = pdata->enable(0);
+		err = pdata->enable(0, pdata->ls_gpio);
 		if (err < 0) {
 			dev_err(&chip->client->dev,
 				"failed to disable the level shifter\n");
@@ -192,7 +192,7 @@
 	 * with CS8427 chip
 	 */
 	if (pdata->enable) {
-		err = pdata->enable(1);
+		err = pdata->enable(1, pdata->ls_gpio);
 		if (err < 0) {
 			dev_err(&chip->client->dev,
 				"failed to enable the level shifter\n");
@@ -207,7 +207,7 @@
 	 * with CS8427 chip
 	 */
 	if (pdata->enable) {
-		err = pdata->enable(0);
+		err = pdata->enable(0, pdata->ls_gpio);
 		if (err < 0) {
 			dev_err(&chip->client->dev,
 				"failed to disable the level shifter\n");
@@ -239,7 +239,7 @@
 	 * with CS8427 chip
 	 */
 	if (pdata->enable) {
-		err = pdata->enable(1);
+		err = pdata->enable(1, pdata->ls_gpio);
 		if (err < 0) {
 			dev_err(&chip->client->dev,
 				"failed to enable the level shifter\n");
@@ -262,7 +262,7 @@
 	 * with CS8427 chip
 	 */
 	if (pdata->enable) {
-		err = pdata->enable(0);
+		err = pdata->enable(0, pdata->ls_gpio);
 		if (err < 0) {
 			dev_err(&chip->client->dev,
 				"failed to disable the level shifter\n");
@@ -734,6 +734,16 @@
 	struct cs8427_platform_data *pdata = chip->client->dev.platform_data;
 	int ret = 0;
 
+	if (pdata->enable) {
+		ret = gpio_request(pdata->ls_gpio, "cs8427 ls");
+		if (ret < 0) {
+			dev_err(&chip->client->dev,
+				 "failed to request the gpio %d\n",
+					pdata->reset_gpio);
+			return ret;
+		}
+	}
+
 	ret = gpio_request(pdata->reset_gpio, "cs8427 reset");
 	if (ret < 0) {
 		dev_err(&chip->client->dev,
@@ -928,8 +938,10 @@
 	}
 	pdata = chip->client->dev.platform_data;
 	gpio_free(pdata->reset_gpio);
-	if (pdata->enable)
-		pdata->enable(0);
+	if (pdata->enable) {
+		pdata->enable(0, pdata->ls_gpio);
+		gpio_free(pdata->ls_gpio);
+	}
 	kfree(chip);
 	return 0;
 }
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 127a2c3..6ac4562 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -875,6 +875,7 @@
 	pr_debug("%s\n", __func__);
 	atomic_set(&prtd->pending_buffer, 0);
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+	compressed_audio.prtd = NULL;
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
 	if (compr->info.codec_param.codec.id ==