Merge "msm: camera: Fix crash issue while enabling regular stats" into msm-3.0
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index 4fb653e..084050e 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -24,13 +24,13 @@
 
 Example:
 
-	qcom,sdcc@F9600000 {
+	qcom,sdcc@f9600000 {
 	/* SDC1 used as eMMC slot */
 	cell-index = <1>;
 	compatible = "qcom,msm-sdcc";
-	reg = <0xF9600000 0x800   // SDCC register interface
-		0xF9600800 0x1800  // DML register interface
-		0xF9602000 0x2000> // BAM register interface
+	reg = <0xf9600000 0x800   // SDCC register interface
+		0xf9600800 0x1800  // DML register interface
+		0xf9602000 0x2000> // BAM register interface
 
 	interrupts = <123>;
 	qcom,sdcc-clk-rates = <400000 24000000 48000000>;
diff --git a/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt b/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
new file mode 100644
index 0000000..8cc3c54
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/spmi-pmic-arb.txt
@@ -0,0 +1,32 @@
+Qualcomm SPMI Controller (PMIC Arbiter)
+
+Required properties:
+- cell-index : the bus identifier.
+- compatible : should be "qcom,spmi-pmic-arb".
+- reg : offset and length of the PMIC Arbiter Core register map.
+- reg : offset and length of the PMIC Arbiter Interrupt controller register map.
+- interrupts : the PMIC Arbiter interrupt.
+- qcom,pmic-arb-ee : the execution environment (EE) identifier.
+- qcom,pmic-arb-channel : the assigned channel number for channel registers.
+- qcom,pmic-arb-ppid-map : an array used to map a 12-bit PPID to 8-bit APID.
+
+Peripherals on the SPMI bus are identified with a 12-bit identifier (PPID)
+which is composed of a 4-bit slave address and an 8-bit peripheral identifier.
+The PMIC Arbiter hardware uses an 8-bit APID (Arbiter Peripheral Identifier)
+internally.  Software needs the mapping between the APID and the PPID.
+Up to a maximum of 256 peripherals are supported and the mapping is target
+specific.
+
+Example:
+
+	qcom,spmi@fc4c0000 {
+		cell-index = <0>;
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0xfc4cf000 0x1000>,
+		      <0Xfc4cb000 0x1000>;
+		interrupts = <0>;
+		qcom,pmic-arb-ee = <0>;
+		qcom,pmic-arb-channel = <0>;
+		qcom,pmic-arb-ppid-map = <0x130 0x00>, /* PPID 0x130, APID 0 */
+					 <0x131 0x01>; /* PPID 0x131, APID 1 */
+	};
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index c1399ae..95ddf34 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -35,16 +35,16 @@
 - qcom,hsusb-otg-pmic-id-irq: ID, routed to PMIC IRQ number
 
 Example HSUSB OTG controller device node :
-	usb@F9690000 {
+	usb@f9690000 {
 		compatible = "qcom,hsusb-otg";
-		reg = <0xF9690000 0x400>;
+		reg = <0xf9690000 0x400>;
 		interrupts = <134>;
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <1>;
 		qcom,hsusb-otg-default-mode = <2>;
-		qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xFFFFFFFF>;
+		qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xffffffff>;
 		qcom,hsusb-otg-power-budget = <500>;
 		qcom,hsusb-otg-pclk-src-name = "dfab_usb_clk";
 		qcom,hsusb-otg-pmic-id-irq = <47>
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index 57ad77a..725971d 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -27,15 +27,15 @@
 		interrupts = <1 2 0>;
 	};
 
-	serial@F991F000 {
+	serial@f991f000 {
 		compatible = "qcom,msm-lsuart-v14";
-		reg = <0xF991F000 0x1000>;
+		reg = <0xf991f000 0x1000>;
 		interrupts = <0 109 0>;
 	};
 
-	usb@F9A55000 {
+	usb@f9a55000 {
 		compatible = "qcom,hsusb-otg";
-		reg = <0xF9A55000 0x400>;
+		reg = <0xf9a55000 0x400>;
 		interrupts = <0 134 0>;
 
 		qcom,hsusb-otg-phy-type = <2>;
@@ -43,10 +43,10 @@
 		qcom,hsusb-otg-otg-control = <1>;
 	};
 
-	qcom,sdcc@F980B000 {
+	qcom,sdcc@f980b000 {
 		cell-index = <1>;
 		compatible = "qcom,msm-sdcc";
-		reg = <0xF980B000 0x1000>;
+		reg = <0xf980b000 0x1000>;
 		interrupts = <0 123 0>;
 
 		qcom,sdcc-clk-rates = <400000 24000000 48000000>;
@@ -56,10 +56,10 @@
 		qcom,sdcc-disable_cmd23;
 	};
 
-	qcom,sdcc@F984B000 {
+	qcom,sdcc@f984b000 {
 		cell-index = <3>;
 		compatible = "qcom,msm-sdcc";
-		reg = <0xF984B000 0x1000>;
+		reg = <0xf984b000 0x1000>;
 		interrupts = <0 127 0>;
 
 		qcom,sdcc-clk-rates = <400000 24000000 48000000>;
@@ -68,10 +68,10 @@
 		qcom,sdcc-disable_cmd23;
 	};
 
-	qcom,sps@F9980000 {
+	qcom,sps@f9980000 {
 		compatible = "qcom,msm_sps";
-		reg = <0xF9984000 0x15000>,
-		      <0xF9999000 0xB000>;
+		reg = <0xf9984000 0x15000>,
+		      <0xf9999000 0xb000>;
 		interrupts = <0 94 0>;
 
 		qcom,bam-dma-res-pipes = <6>;
@@ -83,4 +83,104 @@
 		interrupts = <96>;
 		spi-max-frequency = <24000000>;
 	};
+
+	qcom,spmi@fc4c0000 {
+		cell-index = <0>;
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0xfc4cf000 0x1000>,
+		      <0Xfc4cb000 0x1000>;
+		/* 190,ee0_krait_hlos_spmi_periph_irq */
+		/* 187,channel_0_krait_hlos_trans_done_irq */
+		interrupts = <0 190 0 0 187 0>;
+		qcom,pmic-arb-ee = <0>;
+		qcom,pmic-arb-channel = <0>;
+		qcom,pmic-arb-ppid-map = <0x130 0x00>, /* PM8941_LDO1 */
+					 <0x131 0x01>, /* PM8941_LDO2 */
+					 <0x132 0x02>, /* PM8941_LDO3 */
+					 <0x133 0x03>, /* PM8941_LDO4 */
+					 <0x134 0x04>, /* PM8941_LDO5 */
+					 <0x135 0x05>, /* PM8941_LDO6 */
+					 <0x136 0x06>, /* PM8941_LDO7 */
+					 <0x137 0x07>, /* PM8941_LDO8 */
+					 <0x138 0x08>, /* PM8941_LDO9 */
+					 <0x139 0x09>, /* PM8941_LDO10 */
+					 <0x13a 0x0a>, /* PM8941_LDO11 */
+					 <0x13b 0x0b>, /* PM8941_LDO12 */
+					 <0x13c 0x0c>, /* PM8941_LDO13 */
+					 <0x13d 0x0d>, /* PM8941_LDO14 */
+					 <0x13e 0x0e>, /* PM8941_LDO15 */
+					 <0x13f 0x0f>, /* PM8941_LDO16 */
+					 <0x140 0x10>, /* PM8941_LDO17 */
+					 <0x141 0x11>, /* PM8941_LDO18 */
+					 <0x142 0x12>, /* PM8941_LDO19 */
+					 <0x143 0x13>, /* PM8941_LDO20 */
+					 <0x144 0x14>, /* PM8941_LDO21 */
+					 <0x145 0x15>, /* PM8941_LDO22 */
+					 <0x146 0x16>, /* PM8941_LDO23 */
+					 <0x147 0x17>, /* PM8941_LDO24 */
+					 <0x148 0x18>, /* PM8941_LDO25 */
+					 <0x149 0x19>, /* PM8941_LDO26 */
+					 <0x0c0 0x1a>, /* PM8941_GPIO1 */
+					 <0x0c1 0x1b>, /* PM8941_GPIO2 */
+					 <0x0c2 0x1c>, /* PM8941_GPIO3 */
+					 <0x0c3 0x1d>, /* PM8941_GPIO4 */
+					 <0x0c4 0x1e>, /* PM8941_GPIO5 */
+					 <0x0c5 0x1f>, /* PM8941_GPIO6 */
+					 <0x0c6 0x20>, /* PM8941_GPIO7 */
+					 <0x0c7 0x21>, /* PM8941_GPIO8 */
+					 <0x0c8 0x22>, /* PM8941_GPIO9 */
+					 <0x0c9 0x23>, /* PM8941_GPIO10 */
+					 <0x0ca 0x24>, /* PM8941_GPIO11 */
+					 <0x0cb 0x25>, /* PM8941_GPIO12 */
+					 <0x0cc 0x26>, /* PM8941_GPIO13 */
+					 <0x0cd 0x27>, /* PM8941_GPIO14 */
+					 <0x0ce 0x28>, /* PM8941_GPIO15 */
+					 <0x0cf 0x29>, /* PM8941_GPIO16 */
+					 <0x0d0 0x2a>, /* PM8941_GPIO17 */
+					 <0x0d1 0x2b>, /* PM8941_GPIO18 */
+					 <0x0d2 0x2c>, /* PM8941_GPIO19 */
+					 <0x0d3 0x2d>, /* PM8941_GPIO20 */
+					 <0x0d4 0x2e>, /* PM8941_GPIO21 */
+					 <0x0d5 0x2f>, /* PM8941_GPIO22 */
+					 <0x0d6 0x30>, /* PM8941_GPIO23 */
+					 <0x0d7 0x31>, /* PM8941_GPIO24 */
+					 <0x0d8 0x32>, /* PM8941_GPIO25 */
+					 <0x0d9 0x33>, /* PM8941_GPIO26 */
+					 <0x0da 0x34>, /* PM8941_GPIO27 */
+					 <0x0db 0x35>, /* PM8941_GPIO28 */
+					 <0x0dc 0x36>, /* PM8941_GPIO29 */
+					 <0x0dd 0x37>, /* PM8941_GPIO30 */
+					 <0x0de 0x38>, /* PM8941_GPIO31 */
+					 <0x0df 0x39>, /* PM8941_GPIO32 */
+					 <0x0e0 0x3a>, /* PM8941_GPIO33 */
+					 <0x0e1 0x3b>, /* PM8941_GPIO34 */
+					 <0x0e2 0x3c>, /* PM8941_GPIO35 */
+					 <0x0e3 0x3d>, /* PM8941_GPIO36 */
+					 <0x028 0x3e>, /* COINCELL */
+					 <0x005 0x3f>, /* INTERRUPT */
+					 <0x001 0x40>, /* PM8941_0 */
+					 <0x201 0x41>, /* PM8841_0 */
+					 <0x101 0x42>, /* PM8941_1 */
+					 <0x301 0x43>, /* PM8841_1 */
+					 <0x008 0x44>, /* PON0 */
+					 <0x208 0x45>, /* PON1 */
+					 <0x110 0x46>, /* PM8941_SMPS1 */
+					 <0x111 0x47>, /* PM8941_SMPS2 */
+					 <0x112 0x48>, /* PM8941_SMPS3 */
+					 <0x310 0x49>, /* PM8841_SMPS1 */
+					 <0x311 0x4a>, /* PM8841_SMPS2 */
+					 <0x312 0x4b>, /* PM8841_SMPS3 */
+					 <0x313 0x4c>, /* PM8841_SMPS4 */
+					 <0x314 0x4d>, /* PM8841_SMPS5 */
+					 <0x315 0x4e>, /* PM8841_SMPS6 */
+					 <0x316 0x4f>, /* PM8841_SMPS7 */
+					 <0x317 0x50>, /* PM8841_SMPS8 */
+					 <0x050 0x51>, /* SHARED_XO */
+					 <0x051 0x52>, /* BB_CLK1 */
+					 <0x052 0x53>, /* BB_CLK2 */
+					 <0x059 0x54>, /* SLEEP_CLK */
+					 <0x010 0x55>, /* SMBC_OVP */
+					 <0x011 0x56>, /* SMBC_CHG */
+					 <0x012 0x57>; /* SMBC_BIF */
+	};
 };
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index a708fbc..8a505cc 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -37,10 +37,8 @@
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
-# CONFIG_MSM_DALRPC is not set
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
@@ -94,6 +92,8 @@
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_DCC_TTY=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_SUPPLY=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 3c87f8d..dd8cb16 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -26,6 +26,7 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM7X27=y
+CONFIG_ARCH_MSM8625=y
 CONFIG_MSM_SOC_REV_A=y
 # CONFIG_MACH_MSM7X27_SURF is not set
 # CONFIG_MACH_MSM7X27_FFA is not set
@@ -44,7 +45,6 @@
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM7X27A_AUDIO=y
 CONFIG_MSM_DMA_TEST=y
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_MSM_SLEEP_STATS_DEVICE=y
 CONFIG_BT_MSM_PINTEST=y
 CONFIG_MSM_RPC_VIBRATOR=y
@@ -52,6 +52,7 @@
 CONFIG_ARM_THUMBEE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
@@ -231,6 +232,7 @@
 # CONFIG_MT9T013 is not set
 # CONFIG_MT9D112 is not set
 CONFIG_OV5640=y
+CONFIG_OV5647=y
 CONFIG_WEBCAM_OV7692_QRD=y
 CONFIG_WEBCAM_OV9726=y
 # CONFIG_MT9P012 is not set
@@ -254,6 +256,7 @@
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
+CONFIG_SND_MSM_SOC=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
 CONFIG_HID_MICROSOFT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index cc33b8f..199b91f 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -26,6 +26,7 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM7X27=y
+CONFIG_ARCH_MSM8625=y
 CONFIG_MSM_SOC_REV_A=y
 # CONFIG_MACH_MSM7X27_SURF is not set
 # CONFIG_MACH_MSM7X27_FFA is not set
@@ -52,6 +53,7 @@
 CONFIG_ARM_THUMBEE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
@@ -349,3 +351,4 @@
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRC_CCITT=y
+CONFIG_OV5647=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index b71df28..b3a45d2 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -326,6 +326,7 @@
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_WEBCAM_OV9726=y
 CONFIG_MT9E013=y
+CONFIG_IMX074=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 9fd7e71..1f511bb 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -326,6 +326,7 @@
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_WEBCAM_OV9726=y
 CONFIG_MT9E013=y
+CONFIG_IMX074=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 95dd09c..f1b1fa5 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -1,4 +1,5 @@
 CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-perf"
 CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -52,6 +53,8 @@
 CONFIG_MACH_APQ8064_CDP=y
 CONFIG_MACH_APQ8064_MTP=y
 CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_HRD=y
+CONFIG_MACH_MPQ8064_DTV=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_KERNEL_PMEM_EBI_REGION=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -311,6 +314,9 @@
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
+CONFIG_IMX074=y
+CONFIG_IMX074_ACT=y
+CONFIG_OV2720=y
 CONFIG_S5K3L1YX=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_IRIS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 3a70b22..e58b94b 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -52,6 +52,8 @@
 CONFIG_MACH_APQ8064_CDP=y
 CONFIG_MACH_APQ8064_MTP=y
 CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_HRD=y
+CONFIG_MACH_MPQ8064_DTV=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_KERNEL_PMEM_EBI_REGION=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -82,6 +84,8 @@
 CONFIG_MSM_QDSS=y
 CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE=y
 CONFIG_MSM_SLEEP_STATS=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -312,6 +316,9 @@
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
+CONFIG_IMX074=y
+CONFIG_IMX074_ACT=y
+CONFIG_OV2720=y
 CONFIG_S5K3L1YX=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_IRIS=y
@@ -433,13 +440,13 @@
 CONFIG_LOCKUP_DETECTOR=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
-CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DEBUG_LIST=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 543a4f9f..7ba17e6 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -142,7 +142,6 @@
 CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
 CONFIG_IP6_NF_MANGLE=y
 CONFIG_IP6_NF_RAW=y
-CONFIG_CFG80211=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -162,7 +161,7 @@
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_NETDEVICES=y
-CONFIG_HOSTAP=y
+CONFIG_ATH6K_LEGACY=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
 # CONFIG_INPUT_MOUSEDEV is not set
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index c3b841a..d2434e6 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -54,79 +54,46 @@
  * consider why they can't support the logging.
  */
 
+#define __raw_write_logged(v, a, _t)	({ \
+	int _ret; \
+	void *_addr = (void *)(a); \
+	_ret = uncached_logk(LOGK_WRITEL, _addr); \
+	ETB_WAYPOINT; \
+	__raw_write##_t##_no_log((v), _addr); \
+	if (_ret) \
+		LOG_BARRIER; \
+	})
+
+
 #define __raw_writeb_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v))
 #define __raw_writew_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
 #define __raw_writel_no_log(v, a)	(__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))
 
-#define __raw_writeb(v, a)	({ \
-	int _ret; \
-	void *_addr = (void *)(a); \
-	_ret = uncached_logk(LOGK_WRITEL, _addr); \
-	ETB_WAYPOINT; \
-	__raw_writeb_no_log(v, _addr); \
-	if (_ret) \
-		LOG_BARRIER; \
-	})
 
-#define __raw_writew(v, a)	({ \
-	int _ret; \
-	void *_addr = (void *)(a); \
-	_ret = uncached_logk(LOGK_WRITEL, _addr); \
-	ETB_WAYPOINT; \
-	__raw_writew_no_log(v, _addr); \
-	if (_ret) \
-		LOG_BARRIER; \
-	})
-
-#define __raw_writel(v, a)	({ \
-	int _ret; \
-	void *_addr = (void *)(a); \
-	_ret = uncached_logk(LOGK_WRITEL, _addr); \
-	ETB_WAYPOINT; \
-	__raw_writel_no_log(v, _addr); \
-	if (_ret) \
-		LOG_BARRIER; \
-	})
+#define __raw_writeb(v, a)	__raw_write_logged((v), (a), b)
+#define __raw_writew(v, a)	__raw_write_logged((v), (a), w)
+#define __raw_writel(v, a)	__raw_write_logged((v), (a), l)
 
 #define __raw_readb_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
 #define __raw_readw_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
 #define __raw_readl_no_log(a)		(__chk_io_ptr(a), *(volatile unsigned int __force *)(a))
 
-#define __raw_readb(a)		({ \
-	unsigned char __a; \
+#define __raw_read_logged(a, _l, _t)		({ \
+	unsigned _t __a; \
 	void *_addr = (void *)(a); \
 	int _ret; \
 	_ret = uncached_logk(LOGK_READL, _addr); \
 	ETB_WAYPOINT; \
-	__a = __raw_readb_no_log(_addr);\
+	__a = __raw_read##_l##_no_log(_addr);\
 	if (_ret) \
 		LOG_BARRIER; \
 	__a; \
 	})
 
-#define __raw_readw(a)		({ \
-	unsigned short __a; \
-	void *_addr = (void *)(a); \
-	int _ret; \
-	_ret = uncached_logk(LOGK_READL, _addr); \
-	ETB_WAYPOINT; \
-	__a = __raw_readw_no_log(_addr);\
-	if (_ret) \
-		LOG_BARRIER; \
-	__a; \
-	})
 
-#define __raw_readl(a)		({ \
-	unsigned int __a; \
-	void *_addr = (void *)(a); \
-	int _ret; \
-	_ret = uncached_logk(LOGK_READL, _addr); \
-	ETB_WAYPOINT; \
-	__a = __raw_readl_no_log(_addr);\
-	if (_ret) \
-		LOG_BARRIER; \
-	__a; \
-	})
+#define __raw_readb(a)		__raw_read_logged((a), b, char)
+#define __raw_readw(a)		__raw_read_logged((a), w, short)
+#define __raw_readl(a)		__raw_read_logged((a), l, int)
 
 /*
  * Architecture ioremap implementation.
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0b0f733..18fbcf6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -747,6 +747,18 @@
 	help
 	  Support for the Qualcomm APQ8064 LIQUID device.
 
+config MACH_MPQ8064_HRD
+	depends on ARCH_APQ8064
+	bool "MPQ8064 HRD"
+	help
+	  Support for the Qualcomm MPQ8064 HRD device.
+
+config MACH_MPQ8064_DTV
+	depends on ARCH_APQ8064
+	bool "MPQ8064 DTV"
+	help
+	  Support for the Qualcomm MPQ8064 DTV device.
+
 config MACH_FSM9XXX_SURF
 	depends on ARCH_FSM9XXX
 	depends on !MSM_STACKED_MEMORY
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index b2f7c84d..8347a25 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -38,7 +38,12 @@
 	obj-$(CONFIG_MSM_SOC_REV_NONE) += acpuclock-8x50.o
 endif
 
-obj-$(CONFIG_SMP) += headsmp.o platsmp.o
+obj-$(CONFIG_SMP) += headsmp.o
+ifdef CONFIG_ARCH_MSM8625
+	obj-$(CONFIG_SMP) += platsmp-8625.o
+else
+	obj-$(CONFIG_SMP) += platsmp.o
+endif
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 
 obj-$(CONFIG_MSM_CPU_AVS) += avs.o
@@ -88,12 +93,14 @@
 ifndef CONFIG_ARCH_APQ8064
 ifndef CONFIG_ARCH_MSM8960
 ifndef CONFIG_ARCH_MSM8X60
+ifndef CONFIG_ARCH_MSMCOPPER
 	obj-$(CONFIG_MSM_SMD) += pmic.o
 	obj-$(CONFIG_MSM_ONCRPCROUTER) += rpc_hsusb.o rpc_pmapp.o rpc_fsusb.o
 endif
 endif
 endif
 endif
+endif
 ifndef CONFIG_ARCH_MSM8960
 ifndef CONFIG_ARCH_MSM8X60
 ifndef CONFIG_ARCH_APQ8064
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 6140559..7ad3f65 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -757,7 +757,7 @@
 	res = clk_set_rate(drv_state.ebi1_clk, speed->axiclk_khz * 1000);
 	if (res < 0)
 		pr_warning("Setting AXI min rate failed (%d)\n", res);
-	res = clk_enable(drv_state.ebi1_clk);
+	res = clk_prepare_enable(drv_state.ebi1_clk);
 	if (res < 0)
 		pr_warning("Enabling AXI clock failed (%d)\n", res);
 
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 470e836..99c3d78 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -148,10 +148,10 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+			.vreg[VREG_HFPLL_A] = { "hfpll0_s8", 2100000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll0_l23", 1800000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_L23 },
 		},
@@ -160,16 +160,16 @@
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait1",     1300000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+			.vreg[VREG_HFPLL_A] = { "hfpll1_s8", 2100000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll1_l23", 1800000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_L23 },
 		},
@@ -177,10 +177,10 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_A] = { "hfpll", 2100000,
+			.vreg[VREG_HFPLL_A] = { "hfpll_l2_s8", 2100000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll_l2_l23", 1800000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8921_L23 },
 		},
@@ -201,7 +201,7 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -210,13 +210,13 @@
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait1",     1150000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -225,13 +225,13 @@
 			.aux_clk_sel     = MSM_ACC2_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait2",     1150000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait2_mem", 1150000,
 					     RPM_VREG_VOTER4,
 					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait2_dig", 1150000,
 					     RPM_VREG_VOTER4,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll2", 1800000,
 					     RPM_VREG_VOTER4,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -240,13 +240,13 @@
 			.aux_clk_sel     = MSM_ACC3_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait3",     1150000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait3_mem", 1150000,
 					     RPM_VREG_VOTER5,
 					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait3_dig", 1150000,
 					     RPM_VREG_VOTER5,
 					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll3", 1800000,
 					     RPM_VREG_VOTER5,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -254,7 +254,7 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x300,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8921_LVS7 },
 		},
@@ -272,7 +272,7 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8038_S1 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -281,13 +281,13 @@
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait1",     1300000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_S1 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -295,7 +295,7 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -314,7 +314,7 @@
 			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8038_S1 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
 					     RPM_VREG_VOTER1,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -323,13 +323,13 @@
 			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
 			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
 			.vreg[VREG_CORE] = { "krait1",     1300000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
+			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
+			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_S1 },
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
 					     RPM_VREG_VOTER2,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -337,7 +337,7 @@
 			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
 			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
 			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_B] = { "hfpll", 1800000,
+			.vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
 					     RPM_VREG_VOTER6,
 					     RPM_VREG_ID_PM8038_L23 },
 		},
@@ -922,8 +922,8 @@
 				sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
 				sc->vreg[VREG_MEM].max_vdd, 0);
 		if (rc) {
-			pr_err("%s: vdd_mem (cpu%d) increase failed (%d)\n",
-				__func__, cpu, rc);
+			pr_err("%s increase failed (%d)\n",
+				sc->vreg[VREG_MEM].name, rc);
 			return rc;
 		}
 		 sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
@@ -935,8 +935,8 @@
 				sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
 				sc->vreg[VREG_DIG].max_vdd, 0);
 		if (rc) {
-			pr_err("%s: vdd_dig (cpu%d) increase failed (%d)\n",
-				__func__, cpu, rc);
+			pr_err("%s increase failed (%d)\n",
+				sc->vreg[VREG_DIG].name, rc);
 			return rc;
 		}
 		sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
@@ -953,8 +953,8 @@
 		rc = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
 					   sc->vreg[VREG_CORE].max_vdd);
 		if (rc) {
-			pr_err("%s: vdd_core (cpu%d) increase failed (%d)\n",
-				__func__, cpu, rc);
+			pr_err("%s increase failed (%d)\n",
+				sc->vreg[VREG_CORE].name, rc);
 			return rc;
 		}
 		sc->vreg[VREG_CORE].cur_vdd = vdd_core;
@@ -980,8 +980,8 @@
 		ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
 					    sc->vreg[VREG_CORE].max_vdd);
 		if (ret) {
-			pr_err("%s: vdd_core (cpu%d) decrease failed (%d)\n",
-			       __func__, cpu, ret);
+			pr_err("%s decrease failed (%d)\n",
+			       sc->vreg[VREG_CORE].name, ret);
 			return;
 		}
 		sc->vreg[VREG_CORE].cur_vdd = vdd_core;
@@ -993,8 +993,8 @@
 				sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
 				sc->vreg[VREG_DIG].max_vdd, 0);
 		if (ret) {
-			pr_err("%s: vdd_dig (cpu%d) decrease failed (%d)\n",
-				__func__, cpu, ret);
+			pr_err("%s decrease failed (%d)\n",
+				sc->vreg[VREG_DIG].name, ret);
 			return;
 		}
 		sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
@@ -1009,8 +1009,8 @@
 				sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
 				sc->vreg[VREG_MEM].max_vdd, 0);
 		if (ret) {
-			pr_err("%s: vdd_mem (cpu%d) decrease failed (%d)\n",
-				__func__, cpu, ret);
+			pr_err("%s decrease failed (%d)\n",
+				sc->vreg[VREG_MEM].name, ret);
 			return;
 		}
 		 sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
@@ -1147,7 +1147,7 @@
 	pr_debug("Initializing HFPLL%d\n", sc - scalable);
 
 	/* Disable the PLL for re-programming. */
-	hfpll_disable(sc, 0);
+	hfpll_disable(sc, 1);
 
 	/* Configure PLL parameters for integer mode. */
 	writel_relaxed(0x7845C665, sc->hfpll_base + HFPLL_CONFIG_CTL);
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index f1abde4..0a56dd2 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -671,7 +671,7 @@
 	skb = info->skb;
 	kfree(info);
 	hdr = (struct bam_mux_hdr *)skb->data;
-	DBG_INC_WRITE_CNT(skb->data_len);
+	DBG_INC_WRITE_CNT(skb->len);
 	event_data = (unsigned long)(skb);
 	spin_lock_irqsave(&bam_ch[hdr->ch_id].lock, flags);
 	bam_ch[hdr->ch_id].num_tx_pkts--;
@@ -1194,11 +1194,15 @@
 	int i = 0;
 
 	i += scnprintf(buf + i, max - i,
+			"skb read cnt:    %u\n"
+			"skb write cnt:   %u\n"
 			"skb copy cnt:    %u\n"
 			"skb copy bytes:  %u\n"
 			"sps tx failures: %u\n"
 			"sps tx stalls:   %u\n"
 			"rx queue len:    %d\n",
+			bam_dmux_read_cnt,
+			bam_dmux_write_cnt,
 			bam_dmux_write_cpy_cnt,
 			bam_dmux_write_cpy_bytes,
 			bam_dmux_tx_sps_failure_cnt,
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index cd84722..109ed2c 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -41,8 +41,8 @@
 	},
 
 	{
-		.func = GPIOMUX_FUNC_1, /*active 3*/
-		.drv = GPIOMUX_DRV_8MA,
+		.func = GPIOMUX_FUNC_2, /*active 3*/
+		.drv = GPIOMUX_DRV_2MA,
 		.pull = GPIOMUX_PULL_NONE,
 	},
 
@@ -76,6 +76,27 @@
 		.pull = GPIOMUX_PULL_KEEPER,
 	},
 
+	{
+		.func = GPIOMUX_FUNC_9, /*active 9*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+	{
+		.func = GPIOMUX_FUNC_A, /*active 10*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+	{
+		.func = GPIOMUX_FUNC_6, /*active 11*/
+		.drv = GPIOMUX_DRV_8MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+	{
+		.func = GPIOMUX_FUNC_4, /*active 12*/
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+
 };
 
 
@@ -83,7 +104,7 @@
 	{
 		.gpio = 2,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[2],
+			[GPIOMUX_ACTIVE]    = &cam_settings[12],
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
 		},
 	},
@@ -97,7 +118,7 @@
 	{
 		.gpio = 4,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[1],
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
 		},
 	},
@@ -109,7 +130,7 @@
 		},
 	},
 	{
-		.gpio = 76,
+		.gpio = 34,
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &cam_settings[2],
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
@@ -122,39 +143,39 @@
 			[GPIOMUX_SUSPENDED] = &cam_settings[0],
 		},
 	},
-};
-
-static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
 	{
 		.gpio = 10,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_ACTIVE]    = &cam_settings[9],
 			[GPIOMUX_SUSPENDED] = &cam_settings[8],
 		},
 	},
 	{
 		.gpio = 11,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_ACTIVE]    = &cam_settings[10],
 			[GPIOMUX_SUSPENDED] = &cam_settings[8],
 		},
 	},
 	{
 		.gpio = 12,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_ACTIVE]    = &cam_settings[11],
 			[GPIOMUX_SUSPENDED] = &cam_settings[8],
 		},
 	},
 	{
 		.gpio = 13,
 		.settings = {
-			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_ACTIVE]    = &cam_settings[11],
 			[GPIOMUX_SUSPENDED] = &cam_settings[8],
 		},
 	},
 };
 
+static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
+};
+
 #ifdef CONFIG_MSM_CAMERA
 
 static struct msm_bus_vectors cam_init_vectors[] = {
@@ -310,27 +331,36 @@
 	},
 };
 
-static struct camera_vreg_t msm_8064_back_cam_vreg[] = {
+static struct camera_vreg_t apq_8064_back_cam_vreg[] = {
 	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
 	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vio", REG_VS, 0, 0, 0},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
 };
 
+static struct camera_vreg_t apq_8064_front_cam_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
+#define CAML_RSTN PM8921_GPIO_PM_TO_SYS(28)
+#define CAMR_RSTN 34
+
 static struct gpio apq8064_common_cam_gpio[] = {
-	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
-	{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
-	{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
 };
 
 static struct gpio apq8064_back_cam_gpio[] = {
-	{107, GPIOF_DIR_OUT, "CAM_RESET"},
+	{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
+	{CAML_RSTN, GPIOF_DIR_OUT, "CAM_RESET"},
 };
 
 static struct msm_gpio_set_tbl apq8064_back_cam_gpio_set_tbl[] = {
-	{107, GPIOF_OUT_INIT_LOW, 1000},
-	{107, GPIOF_OUT_INIT_HIGH, 4000},
+	{CAML_RSTN, GPIOF_OUT_INIT_LOW, 10000},
+	{CAML_RSTN, GPIOF_OUT_INIT_HIGH, 10000},
 };
 
 static struct msm_camera_gpio_conf apq8064_back_cam_gpio_conf = {
@@ -344,6 +374,41 @@
 	.cam_gpio_set_tbl_size = ARRAY_SIZE(apq8064_back_cam_gpio_set_tbl),
 };
 
+static struct gpio apq8064_front_cam_gpio[] = {
+	{4, GPIOF_DIR_IN, "CAMIF_MCLK"},
+	{12, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
+	{13, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
+	{CAMR_RSTN, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl apq8064_front_cam_gpio_set_tbl[] = {
+	{CAMR_RSTN, GPIOF_OUT_INIT_LOW, 10000},
+	{CAMR_RSTN, GPIOF_OUT_INIT_HIGH, 10000},
+};
+
+static struct msm_camera_gpio_conf apq8064_front_cam_gpio_conf = {
+	.cam_gpiomux_conf_tbl = apq8064_cam_2d_configs,
+	.cam_gpiomux_conf_tbl_size = ARRAY_SIZE(apq8064_cam_2d_configs),
+	.cam_gpio_common_tbl = apq8064_common_cam_gpio,
+	.cam_gpio_common_tbl_size = ARRAY_SIZE(apq8064_common_cam_gpio),
+	.cam_gpio_req_tbl = apq8064_front_cam_gpio,
+	.cam_gpio_req_tbl_size = ARRAY_SIZE(apq8064_front_cam_gpio),
+	.cam_gpio_set_tbl = apq8064_front_cam_gpio_set_tbl,
+	.cam_gpio_set_tbl_size = ARRAY_SIZE(apq8064_front_cam_gpio_set_tbl),
+};
+
+static struct msm_camera_i2c_conf apq8064_back_cam_i2c_conf = {
+	.use_i2c_mux = 1,
+	.mux_dev = &msm8960_device_i2c_mux_gsbi4,
+	.i2c_mux_mode = MODE_L,
+};
+
+static struct msm_camera_i2c_conf apq8064_front_cam_i2c_conf = {
+	.use_i2c_mux = 1,
+	.mux_dev = &msm8960_device_i2c_mux_gsbi4,
+	.i2c_mux_mode = MODE_L,
+};
+
 #ifdef CONFIG_IMX074
 static struct msm_camera_sensor_flash_data flash_imx074 = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
@@ -351,9 +416,10 @@
 
 static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
 	.mount_angle	= 90,
-	.cam_vreg = msm_8064_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8064_back_cam_vreg),
+	.cam_vreg = apq_8064_back_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_back_cam_vreg),
 	.gpio_conf = &apq8064_back_cam_gpio_conf,
+	.i2c_conf = &apq8064_back_cam_i2c_conf,
 };
 
 static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
@@ -366,11 +432,36 @@
 };
 #endif
 
+#ifdef CONFIG_OV2720
+static struct msm_camera_sensor_flash_data flash_ov2720 = {
+	.flash_type	= MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
+	.mount_angle	= 0,
+	.cam_vreg = apq_8064_front_cam_vreg,
+	.num_vreg = ARRAY_SIZE(apq_8064_front_cam_vreg),
+	.gpio_conf = &apq8064_front_cam_gpio_conf,
+	.i2c_conf = &apq8064_front_cam_i2c_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov2720_data = {
+	.sensor_name	= "ov2720",
+	.pdata	= &msm_camera_csi_device_data[1],
+	.flash_data	= &flash_ov2720,
+	.sensor_platform_info = &sensor_board_info_ov2720,
+	.csi_if	= 1,
+	.camera_type = FRONT_CAMERA_2D,
+};
+#endif
+
+
 void __init apq8064_init_cam(void)
 {
 	msm_gpiomux_install(apq8064_cam_common_configs,
 			ARRAY_SIZE(apq8064_cam_common_configs));
 
+	platform_device_register(&msm8960_device_i2c_mux_gsbi4);
 	platform_device_register(&msm8960_device_csiphy0);
 	platform_device_register(&msm8960_device_csiphy1);
 	platform_device_register(&msm8960_device_csid0);
@@ -388,6 +479,12 @@
 	.platform_data = &msm_camera_sensor_imx074_data,
 	},
 #endif
+#ifdef CONFIG_OV2720
+	{
+	I2C_BOARD_INFO("ov2720", 0x6C),
+	.platform_data = &msm_camera_sensor_ov2720_data,
+	},
+#endif
 };
 
 struct msm_camera_board_info apq8064_camera_board_info = {
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index c3cc9eb..9b6c253 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -64,6 +64,18 @@
 };
 #endif
 
+static struct gpiomux_setting gpio_i2c_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gpio_i2c_config_sus = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_KEEPER,
+};
+
 static struct gpiomux_setting cdc_mclk = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
@@ -347,6 +359,20 @@
 			[GPIOMUX_SUSPENDED] = &gsbi7_func1_cfg,
 		},
 	},
+	{
+		.gpio      = 21,		/* GSBI1 QUP I2C_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config_sus,
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
+		},
+	},
+	{
+		.gpio      = 20,		/* GSBI1 QUP I2C_DATA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config_sus,
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config apq8064_slimbus_config[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 02dfc5e..4c386e9 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -117,6 +117,9 @@
 	PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
 	PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
 	PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
+	PM8921_GPIO_OUTPUT_FUNC(44, 0, PM_GPIO_FUNC_2),
+	PM8921_GPIO_OUTPUT(33, 0, HIGH),
+	PM8921_GPIO_OUTPUT(20, 0, HIGH),
 };
 
 /* Initial PM8XXX MPP configurations */
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 4e29feb..caee8ba 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -157,6 +157,7 @@
 	REGULATOR_SUPPLY("riva_vddpx",		"wcnss_wlan.0"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-005b"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-0024"),
+	REGULATOR_SUPPLY("vddp",		"0-0048"),
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 0d187a9..9069039 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -121,8 +121,8 @@
 
 static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
 	{TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
-	{TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
-	{TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+	{TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+	{TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
 };
 
 /* SDC3 pad data */
@@ -146,8 +146,8 @@
 
 static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
 	{TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
-	{TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_DOWN},
-	{TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_DOWN}
+	{TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+	{TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
 };
 
 static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
@@ -220,7 +220,7 @@
 
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 static unsigned int sdc3_sup_clk_rates[] = {
-	400000, 24000000, 48000000, 96000000
+	400000, 24000000, 48000000, 96000000, 192000000
 };
 
 static struct mmc_platform_data sdc3_data = {
@@ -234,6 +234,10 @@
 	.status_irq	= MSM_GPIO_TO_INT(26),
 	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 	.is_status_gpio_active_low = 1,
+	.xpc_cap	= 1,
+	.uhs_caps	= (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+			MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
+			MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_800),
 };
 static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
 #else
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index c07f497b..12cee78 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -18,6 +18,7 @@
 #include <linux/slimbus/slimbus.h>
 #include <linux/mfd/wcd9310/core.h>
 #include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/pm8xxx/misc.h>
 #include <linux/msm_ssbi.h>
 #include <linux/spi/spi.h>
 #include <linux/dma-mapping.h>
@@ -26,6 +27,7 @@
 #include <linux/memory.h>
 #include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/cyttsp.h>
+#include <linux/i2c/isa1200.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -54,6 +56,7 @@
 #include <mach/msm_bus_board.h>
 #include <mach/cpuidle.h>
 #include <mach/mdm2.h>
+#include <linux/msm_tsens.h>
 
 #include "msm_watchdog.h"
 #include "board-8064.h"
@@ -78,7 +81,7 @@
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE	0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE	0x300000 /* (3MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 #define MSM_ION_HEAP_NUM	8
@@ -233,6 +236,18 @@
 	.align = SZ_128K,
 };
 #endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -243,14 +258,6 @@
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -275,6 +282,14 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
@@ -528,6 +543,86 @@
 	},
 };
 
+#define HAP_SHIFT_LVL_OE_GPIO		PM8921_MPP_PM_TO_SYS(8)
+#define ISA1200_HAP_EN_GPIO		PM8921_GPIO_PM_TO_SYS(33)
+#define ISA1200_HAP_LEN_GPIO		PM8921_GPIO_PM_TO_SYS(20)
+#define ISA1200_HAP_CLK			PM8921_GPIO_PM_TO_SYS(44)
+
+static int isa1200_power(int on)
+{
+	gpio_set_value_cansleep(ISA1200_HAP_CLK, !!on);
+
+	return 0;
+}
+
+static int isa1200_dev_setup(bool enable)
+{
+	int rc = 0;
+
+	rc = pm8xxx_aux_clk_control(CLK_MP3_2, XO_DIV_1, enable);
+	if (rc) {
+		pr_err("%s: unable to write aux clock register(%d)\n",
+			__func__, rc);
+		return rc;
+	}
+
+	if (!enable)
+		goto free_gpio;
+
+	rc = gpio_request(ISA1200_HAP_CLK, "haptics_clk");
+	if (rc) {
+		pr_err("%s: unable to request gpio %d config(%d)\n",
+			__func__, ISA1200_HAP_CLK, rc);
+		return rc;
+	}
+
+	rc = gpio_direction_output(ISA1200_HAP_CLK, 0);
+	if (rc) {
+		pr_err("%s: unable to set direction\n", __func__);
+		goto free_gpio;
+	}
+
+	return 0;
+
+free_gpio:
+	gpio_free(ISA1200_HAP_CLK);
+	return rc;
+}
+
+static struct isa1200_regulator isa1200_reg_data[] = {
+	{
+		.name = "vddp",
+		.min_uV = ISA_I2C_VTG_MIN_UV,
+		.max_uV = ISA_I2C_VTG_MAX_UV,
+		.load_uA = ISA_I2C_CURR_UA,
+	},
+};
+
+static struct isa1200_platform_data isa1200_1_pdata = {
+	.name = "vibrator",
+	.dev_setup = isa1200_dev_setup,
+	.power_on = isa1200_power,
+	.hap_en_gpio = ISA1200_HAP_EN_GPIO,
+	.hap_len_gpio = ISA1200_HAP_LEN_GPIO,
+	.max_timeout = 15000,
+	.mode_ctrl = PWM_GEN_MODE,
+	.pwm_fd = {
+		.pwm_div = 256,
+	},
+	.is_erm = false,
+	.smart_en = true,
+	.ext_clk_en = true,
+	.chip_en = 1,
+	.regulator_info = isa1200_reg_data,
+	.num_regulators = ARRAY_SIZE(isa1200_reg_data),
+};
+
+static struct i2c_board_info isa1200_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("isa1200_1", 0x90>>1),
+		.platform_data = &isa1200_1_pdata,
+	},
+};
 /* configuration data for mxt1386e using V2.1 firmware */
 static const u8 mxt1386e_config_data_v2_1[] = {
 	/* T6 Object */
@@ -890,6 +985,14 @@
 	.peripheral_platform_device = &apq8064_device_hsic_host,
 };
 
+static struct tsens_platform_data apq_tsens_pdata  = {
+		.tsens_factor		= 1000,
+		.hw_type		= APQ_8064,
+		.tsens_num_sensor	= 11,
+		.slope = {1176, 1176, 1154, 1176, 1111,
+			1132, 1132, 1199, 1132, 1199, 1132},
+};
+
 #define MSM_SHARED_RAM_PHYS 0x80000000
 static void __init apq8064_map_io(void)
 {
@@ -1225,7 +1328,6 @@
 static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW_L2_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1238,9 +1340,7 @@
 static struct msm_spm_platform_data msm_spm_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW0_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1255,9 +1355,7 @@
 	},
 	[1] = {
 		.reg_base_addr = MSM_SAW1_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1272,9 +1370,7 @@
 	},
 	[2] = {
 		.reg_base_addr = MSM_SAW2_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1289,9 +1385,7 @@
 	},
 	[3] = {
 		.reg_base_addr = MSM_SAW3_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1368,6 +1462,7 @@
 
 static struct platform_device *common_devices[] __initdata = {
 	&apq8064_device_dmov,
+	&apq8064_device_qup_i2c_gsbi1,
 	&apq8064_device_qup_i2c_gsbi3,
 	&apq8064_device_qup_i2c_gsbi4,
 	&apq8064_device_qup_spi_gsbi5,
@@ -1434,6 +1529,7 @@
 	&apq_pcm_afe,
 	&apq_cpudai_auxpcm_rx,
 	&apq_cpudai_auxpcm_tx,
+	&apq_cpudai_stub,
 	&apq8064_rpm_device,
 	&apq8064_rpm_log_device,
 	&apq8064_rpm_stat_device,
@@ -1496,6 +1592,11 @@
 	/* add more slimbus slaves as needed */
 };
 
+static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi1_pdata = {
+	.clk_freq = 100000,
+	.src_clk_rate = 24000000,
+};
+
 static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
 	.clk_freq = 100000,
 	.src_clk_rate = 24000000,
@@ -1506,8 +1607,20 @@
 	.src_clk_rate = 24000000,
 };
 
+#define GSBI_DUAL_MODE_CODE 0x60
+#define MSM_GSBI1_PHYS		0x12440000
 static void __init apq8064_i2c_init(void)
 {
+	void __iomem *gsbi_mem;
+
+	apq8064_device_qup_i2c_gsbi1.dev.platform_data =
+					&apq8064_i2c_qup_gsbi1_pdata;
+	gsbi_mem = ioremap_nocache(MSM_GSBI1_PHYS, 4);
+	writel_relaxed(GSBI_DUAL_MODE_CODE, gsbi_mem);
+	/* Ensure protocol code is written before proceeding */
+	wmb();
+	iounmap(gsbi_mem);
+	apq8064_i2c_qup_gsbi1_pdata.use_gsbi_shared_mode = 1;
 	apq8064_device_qup_i2c_gsbi3.dev.platform_data =
 					&apq8064_i2c_qup_gsbi3_pdata;
 	apq8064_device_qup_i2c_gsbi4.dev.platform_data =
@@ -1569,6 +1682,12 @@
 		cyttsp_info,
 		ARRAY_SIZE(cyttsp_info),
 	},
+	{
+		I2C_FFA | I2C_LIQUID,
+		APQ_8064_GSBI1_QUP_I2C_BUS_ID,
+		isa1200_board_info,
+		ARRAY_SIZE(isa1200_board_info),
+	},
 };
 
 static void __init register_i2c_devices(void)
@@ -1576,6 +1695,14 @@
 	u8 mach_mask = 0;
 	int i;
 
+#ifdef CONFIG_MSM_CAMERA
+	struct i2c_registry apq8064_camera_i2c_devices = {
+		I2C_SURF | I2C_FFA | I2C_LIQUID | I2C_RUMI,
+		APQ_8064_GSBI4_QUP_I2C_BUS_ID,
+		apq8064_camera_board_info.board_info,
+		apq8064_camera_board_info.num_i2c_board_info,
+	};
+#endif
 	/* Build the matching 'supported_machs' bitmask */
 	if (machine_is_apq8064_cdp())
 		mach_mask = I2C_SURF;
@@ -1597,6 +1724,12 @@
 						apq8064_i2c_devices[i].info,
 						apq8064_i2c_devices[i].len);
 	}
+#ifdef CONFIG_MSM_CAMERA
+	if (apq8064_camera_i2c_devices.machs & mach_mask)
+		i2c_register_board_info(apq8064_camera_i2c_devices.bus,
+			apq8064_camera_i2c_devices.info,
+			apq8064_camera_i2c_devices.len);
+#endif
 }
 
 static void __init apq8064_common_init(void)
@@ -1652,12 +1785,14 @@
 		&msm8064_device_watchdog.dev.platform_data;
 
 	wdog_pdata->bark_time = 15000;
+	msm_tsens_early_init(&apq_tsens_pdata);
 	apq8064_common_init();
 	platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
 }
 
 static void __init apq8064_rumi3_init(void)
 {
+	msm_tsens_early_init(&apq_tsens_pdata);
 	apq8064_common_init();
 	ethernet_init();
 	platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
@@ -1668,6 +1803,7 @@
 
 static void __init apq8064_cdp_init(void)
 {
+	msm_tsens_early_init(&apq_tsens_pdata);
 	apq8064_common_init();
 	ethernet_init();
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
@@ -1676,6 +1812,7 @@
 	apq8064_init_gpu();
 	platform_add_devices(msm_footswitch_devices,
 			     msm_num_footswitch_devices);
+	apq8064_init_cam();
 }
 
 MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
@@ -1727,3 +1864,21 @@
 	.init_early = apq8064_allocate_memory_regions,
 MACHINE_END
 
+MACHINE_START(MPQ8064_HRD, "QCT MPQ8064 HRD")
+	.map_io = apq8064_map_io,
+	.reserve = apq8064_reserve,
+	.init_irq = apq8064_init_irq,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_timer,
+	.init_machine = apq8064_cdp_init,
+MACHINE_END
+
+MACHINE_START(MPQ8064_DTV, "QCT MPQ8064 DTV")
+	.map_io = apq8064_map_io,
+	.reserve = apq8064_reserve,
+	.init_irq = apq8064_init_irq,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_timer,
+	.init_machine = apq8064_cdp_init,
+MACHINE_END
+
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index d401f4c..e8c8144 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -64,6 +64,8 @@
 
 extern struct msm_camera_board_info apq8064_camera_board_info;
 void apq8064_init_cam(void);
+
+#define APQ_8064_GSBI1_QUP_I2C_BUS_ID 0
 #define APQ_8064_GSBI3_QUP_I2C_BUS_ID 3
 #define APQ_8064_GSBI4_QUP_I2C_BUS_ID 4
 
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index e0bc723..47a381a 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -350,16 +350,16 @@
 
 static struct camera_vreg_t msm_8930_back_cam_vreg[] = {
 	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
 };
 
 static struct camera_vreg_t msm_8930_front_cam_vreg[] = {
 	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 };
 
@@ -409,7 +409,6 @@
 	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8930_back_cam_gpio_set_tbl),
 };
 
-#ifdef CONFIG_IMX074_ACT
 static struct i2c_board_info imx074_actuator_i2c_info = {
 	I2C_BOARD_INFO("imx074_act", 0x11),
 };
@@ -420,9 +419,7 @@
 	.vcm_pwd        = 0,
 	.vcm_enable     = 1,
 };
-#endif
 
-#ifdef CONFIG_IMX074
 static struct msm_camera_sensor_flash_data flash_imx074 = {
 	.flash_type	= MSM_CAMERA_FLASH_LED,
 #ifdef CONFIG_MSM_CAMERA_FLASH
@@ -445,21 +442,25 @@
 	.sensor_platform_info = &sensor_board_info_imx074,
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
-#ifdef CONFIG_IMX074_ACT
 	.actuator_info = &imx074_actuator_info
-#endif
 };
-#endif
 
-#ifdef CONFIG_MT9M114
+static struct camera_vreg_t msm_8930_mt9m114_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
 static struct msm_camera_sensor_flash_data flash_mt9m114 = {
 	.flash_type = MSM_CAMERA_FLASH_NONE
 };
 
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.cam_vreg = msm_8930_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8930_back_cam_vreg),
+	.cam_vreg = msm_8930_mt9m114_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8930_mt9m114_vreg),
 	.gpio_conf = &msm_8930_back_cam_gpio_conf,
 };
 
@@ -471,9 +472,7 @@
 	.csi_if = 1,
 	.camera_type = BACK_CAMERA_2D,
 };
-#endif
 
-#ifdef CONFIG_OV2720
 static struct msm_camera_sensor_flash_data flash_ov2720 = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
 };
@@ -493,7 +492,6 @@
 	.csi_if	= 1,
 	.camera_type = FRONT_CAMERA_2D,
 };
-#endif
 
 static struct camera_vreg_t msm_8930_s5k3l1yx_vreg[] = {
 	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
@@ -539,18 +537,14 @@
 
 #ifdef CONFIG_I2C
 struct i2c_board_info msm8930_camera_i2c_boardinfo[] = {
-#ifdef CONFIG_IMX074
 	{
 	I2C_BOARD_INFO("imx074", 0x1A),
 	.platform_data = &msm_camera_sensor_imx074_data,
 	},
-#endif
-#ifdef CONFIG_OV2720
 	{
 	I2C_BOARD_INFO("ov2720", 0x6C),
 	.platform_data = &msm_camera_sensor_ov2720_data,
 	},
-#endif
 	{
 	I2C_BOARD_INFO("mt9m114", 0x48),
 	.platform_data = &msm_camera_sensor_mt9m114_data,
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 9175c75..e6b342f 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -29,15 +29,19 @@
 #include "board-8930.h"
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1376 * 768 * 4), 4096) * 3) /* 4 bpp x 3 pages */
 #else
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1376 * 768 * 4), 4096) * 2) /* 4 bpp x 2 pages */
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE	(1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+		(roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
 #elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+		(roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
 #else
 #define MSM_FB_EXT_BUF_SIZE	0
 #endif
@@ -87,7 +91,8 @@
 				PANEL_NAME_MAX_LEN)))
 		return 0;
 
-#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+	!defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
 	if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
 			strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
 				PANEL_NAME_MAX_LEN)))
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 90cc3c5..a094ba5 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -77,6 +77,7 @@
 #include <linux/ion.h>
 #include <mach/ion.h>
 #include <mach/mdm2.h>
+#include <mach/msm_rtb.h>
 
 #include "timer.h"
 #include "devices.h"
@@ -130,7 +131,7 @@
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE	0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE	0x300000 /* (3MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 #define MSM_ION_HEAP_NUM	8
@@ -250,6 +251,38 @@
 	},
 };
 
+#if defined(CONFIG_MSM_RTB)
+static struct msm_rtb_platform_data msm_rtb_pdata = {
+	.size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+	int s;
+
+	s = memparse(p, NULL);
+	msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+	return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+
+static struct platform_device msm_rtb_device = {
+	.name           = "msm_rtb",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &msm_rtb_pdata,
+	},
+};
+#endif
+
+static void __init reserve_rtb_memory(void)
+{
+#if defined(CONFIG_MSM_RTB)
+	msm8930_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+#endif
+}
+
 static void __init size_pmem_devices(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
@@ -303,6 +336,18 @@
 	.align = SZ_128K,
 };
 #endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -313,14 +358,6 @@
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -345,6 +382,14 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
@@ -399,6 +444,7 @@
 	reserve_pmem_memory();
 	reserve_ion_memory();
 	reserve_mdp_memory();
+	reserve_rtb_memory();
 }
 
 static struct reserve_info msm8930_reserve_info __initdata = {
@@ -1047,9 +1093,7 @@
 static struct msm_spm_platform_data msm_spm_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW0_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1064,9 +1108,7 @@
 	},
 	[1] = {
 		.reg_base_addr = MSM_SAW1_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1120,7 +1162,6 @@
 static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW_L2_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1577,7 +1618,7 @@
 };
 
 static struct tsens_platform_data msm_tsens_pdata  = {
-	.slope			= 910,
+	.slope		= {872, 872, 872, 872, 872},
 	.tsens_factor		= 1000,
 	.hw_type		= MSM_8960,
 	.tsens_num_sensor	= 5,
@@ -1719,6 +1760,9 @@
 #ifdef MSM8930_PHASE_2
 	&gpio_keys_8930,
 #endif
+#ifdef CONFIG_MSM_RTB
+	&msm_rtb_device,
+#endif
 };
 
 static struct platform_device *cdp_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 23c4928..87cb105 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -411,20 +411,26 @@
 		.is_vpe    = 1,
 		.cam_bus_scale_table = &cam_bus_client_pdata,
 	},
+	{
+		.ioclk.mclk_clk_rate = 24000000,
+		.ioclk.vfe_clk_rate  = 228570000,
+		.csid_core = 2,
+		.cam_bus_scale_table = &cam_bus_client_pdata,
+	},
 };
 
 static struct camera_vreg_t msm_8960_back_cam_vreg[] = {
 	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
-	{"cam_vio", REG_VS, 0, 0, 0},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
 };
 
 static struct camera_vreg_t msm_8960_front_cam_vreg[] = {
 	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
-	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
 	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
 };
 
@@ -474,7 +480,6 @@
 	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8960_back_cam_gpio_set_tbl),
 };
 
-#ifdef CONFIG_IMX074_ACT
 static struct i2c_board_info imx074_actuator_i2c_info = {
 	I2C_BOARD_INFO("imx074_act", 0x11),
 };
@@ -485,9 +490,7 @@
 	.vcm_pwd        = 0,
 	.vcm_enable     = 1,
 };
-#endif
 
-#ifdef CONFIG_IMX074
 static struct msm_camera_sensor_flash_data flash_imx074 = {
 	.flash_type	= MSM_CAMERA_FLASH_LED,
 #ifdef CONFIG_MSM_CAMERA_FLASH
@@ -510,21 +513,25 @@
 	.sensor_platform_info = &sensor_board_info_imx074,
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
-#ifdef CONFIG_IMX074_ACT
 	.actuator_info = &imx074_actuator_info
-#endif
 };
-#endif
 
-#ifdef CONFIG_MT9M114
+static struct camera_vreg_t msm_8960_mt9m114_vreg[] = {
+	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+	{"cam_vio", REG_VS, 0, 0, 0},
+	{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+	{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+	{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
+};
+
 static struct msm_camera_sensor_flash_data flash_mt9m114 = {
 	.flash_type = MSM_CAMERA_FLASH_NONE
 };
 
 static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
 	.mount_angle = 90,
-	.cam_vreg = msm_8960_back_cam_vreg,
-	.num_vreg = ARRAY_SIZE(msm_8960_back_cam_vreg),
+	.cam_vreg = msm_8960_mt9m114_vreg,
+	.num_vreg = ARRAY_SIZE(msm_8960_mt9m114_vreg),
 	.gpio_conf = &msm_8960_back_cam_gpio_conf,
 };
 
@@ -536,9 +543,7 @@
 	.csi_if = 1,
 	.camera_type = BACK_CAMERA_2D,
 };
-#endif
 
-#ifdef CONFIG_OV2720
 static struct msm_camera_sensor_flash_data flash_ov2720 = {
 	.flash_type	= MSM_CAMERA_FLASH_NONE,
 };
@@ -558,7 +563,6 @@
 	.csi_if	= 1,
 	.camera_type = FRONT_CAMERA_2D,
 };
-#endif
 
 static struct camera_vreg_t msm_8960_s5k3l1yx_vreg[] = {
 	{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
@@ -643,8 +647,10 @@
 
 	platform_device_register(&msm8960_device_csiphy0);
 	platform_device_register(&msm8960_device_csiphy1);
+	platform_device_register(&msm8960_device_csiphy2);
 	platform_device_register(&msm8960_device_csid0);
 	platform_device_register(&msm8960_device_csid1);
+	platform_device_register(&msm8960_device_csid2);
 	platform_device_register(&msm8960_device_ispif);
 	platform_device_register(&msm8960_device_vfe);
 	platform_device_register(&msm8960_device_vpe);
@@ -652,18 +658,14 @@
 
 #ifdef CONFIG_I2C
 static struct i2c_board_info msm8960_camera_i2c_boardinfo[] = {
-#ifdef CONFIG_IMX074
 	{
 	I2C_BOARD_INFO("imx074", 0x1A),
 	.platform_data = &msm_camera_sensor_imx074_data,
 	},
-#endif
-#ifdef CONFIG_OV2720
 	{
 	I2C_BOARD_INFO("ov2720", 0x6C),
 	.platform_data = &msm_camera_sensor_ov2720_data,
 	},
-#endif
 	{
 	I2C_BOARD_INFO("mt9m114", 0x48),
 	.platform_data = &msm_camera_sensor_mt9m114_data,
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index aa8477e..9a98058 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -29,15 +29,19 @@
 #include "board-8960.h"
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1920 * 1200 * 4), 4096) * 3) /* 4 bpp x 3 pages */
 #else
-#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1920 * 1200 * 4), 4096) * 2) /* 4 bpp x 2 pages */
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE	(1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+		(roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
 #elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+		(roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
 #else
 #define MSM_FB_EXT_BUF_SIZE	0
 #endif
@@ -68,6 +72,7 @@
 #define MIPI_CMD_NOVATEK_QHD_PANEL_NAME	"mipi_cmd_novatek_qhd"
 #define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME	"mipi_video_novatek_qhd"
 #define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME	"mipi_video_toshiba_wsvga"
+#define MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME	"mipi_video_toshiba_wuxga"
 #define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME	"mipi_video_chimei_wxga"
 #define MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME	"mipi_video_chimei_wuxga"
 #define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME	"mipi_video_simulator_vga"
@@ -81,7 +86,7 @@
 	}
 };
 
-static void set_mdp_clocks_for_liquid_wuxga(void);
+static void set_mdp_clocks_for_wuxga(void);
 
 static int msm_fb_detect_panel(const char *name)
 {
@@ -91,7 +96,7 @@
 			if (!strncmp(name, MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
 				     strnlen(MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
 						PANEL_NAME_MAX_LEN))) {
-				set_mdp_clocks_for_liquid_wuxga();
+				set_mdp_clocks_for_wuxga();
 				return 0;
 			}
 		} else {
@@ -106,7 +111,8 @@
 					PANEL_NAME_MAX_LEN)))
 			return 0;
 
-#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+	!defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
 		if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
 				strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
 					PANEL_NAME_MAX_LEN)))
@@ -126,6 +132,13 @@
 				strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
 					PANEL_NAME_MAX_LEN)))
 			return 0;
+
+		if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME,
+				strnlen(MIPI_VIDEO_TOSHIBA_WUXGA_PANEL_NAME,
+					PANEL_NAME_MAX_LEN))) {
+			set_mdp_clocks_for_wuxga();
+			return 0;
+		}
 #endif
 	}
 
@@ -649,9 +662,9 @@
 
 /**
  * Set MDP clocks to high frequency to avoid DSI underflow
- * when using high resolution 1200x1920 WUXGA panel.
+ * when using high resolution 1200x1920 WUXGA panels
  */
-static void set_mdp_clocks_for_liquid_wuxga(void)
+static void set_mdp_clocks_for_wuxga(void)
 {
 	int i;
 
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 76a27ff..b99ce8a 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -79,6 +79,7 @@
 #include <mach/ion.h>
 #include <mach/mdm2.h>
 #include <mach/mdm-peripheral.h>
+#include <mach/msm_rtb.h>
 
 #include <linux/fmem.h>
 
@@ -143,7 +144,7 @@
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
 #define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
-#define MSM_ION_QSECOM_SIZE	0x100000 /* (1MB) */
+#define MSM_ION_QSECOM_SIZE	0x300000 /* (3MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
 #define MSM_ION_HEAP_NUM	8
@@ -270,6 +271,38 @@
 	},
 };
 
+#if defined(CONFIG_MSM_RTB)
+static struct msm_rtb_platform_data msm_rtb_pdata = {
+	.size = SZ_1M,
+};
+
+static int __init msm_rtb_set_buffer_size(char *p)
+{
+	int s;
+
+	s = memparse(p, NULL);
+	msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+	return 0;
+}
+early_param("msm_rtb_size", msm_rtb_set_buffer_size);
+
+
+static struct platform_device msm_rtb_device = {
+	.name           = "msm_rtb",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &msm_rtb_pdata,
+	},
+};
+#endif
+
+static void __init reserve_rtb_memory(void)
+{
+#if defined(CONFIG_MSM_RTB)
+	msm8960_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+#endif
+}
+
 static void __init size_pmem_devices(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
@@ -306,30 +339,48 @@
 	return MEMTYPE_EBI1;
 }
 
+#define FMEM_ENABLED 1
+
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
-	.reusable = 1,
+	.reusable = FMEM_ENABLED,
+	.mem_is_fmem = FMEM_ENABLED,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
 	.reusable = 0,
+	.mem_is_fmem = FMEM_ENABLED,
 };
 
 static struct ion_co_heap_pdata co_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
+	.mem_is_fmem = 0,
 };
 
 static struct ion_co_heap_pdata fw_co_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
+	.mem_is_fmem = FMEM_ENABLED,
 };
 #endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -340,14 +391,6 @@
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -372,6 +415,14 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
@@ -432,23 +483,17 @@
 	msm8960_reserve_table[mem_type].size += size;
 }
 
-static __init const struct ion_platform_heap *find_ion_heap(int heap_id)
-{
-	unsigned int i;
-	for (i = 0; i < ion_pdata.nr; ++i) {
-		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
-		if (heap->id == heap_id)
-			return (const struct ion_platform_heap *) heap;
-	}
-	return 0;
-}
-
 /**
  * Reserve memory for ION and calculate amount of reusable memory for fmem.
  * We only reserve memory for heaps that are not reusable. However, we only
  * support one reusable heap at the moment so we ignore the reusable flag for
  * other than the first heap with reusable flag set. Also handle special case
- * for adjacent heap when the adjacent heap is adjacent to a reusable heap.
+ * for video heaps (MM,FW, and MFC). Video requires heaps MM and MFC to be
+ * at a higher address than FW in addition to not more than 256MB away from the
+ * base address of the firmware. This means that if MM is reusable the other
+ * two heaps must be allocated in the same region as FW. This is handled by the
+ * mem_is_fmem flag in the platform data. In addition the MM heap must be
+ * adjacent to the FW heap for content protection purposes.
  */
 static void __init reserve_ion_memory(void)
 {
@@ -458,7 +503,8 @@
 
 	adjust_mem_for_liquid();
 	fmem_pdata.size = 0;
-	fmem_pdata.reserved_size = 0;
+	fmem_pdata.reserved_size_low = 0;
+	fmem_pdata.reserved_size_high = 0;
 
 	/* We only support 1 reusable heap. Check if more than one heap
 	 * is specified as reusable and set as non-reusable if found.
@@ -483,7 +529,7 @@
 	for (i = 0; i < ion_pdata.nr; ++i) {
 		int reusable = 0;
 		int adjacent_heap_id = INVALID_HEAP_ID;
-		int adj_reusable = 0;
+		int mem_is_fmem = 0;
 		const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
 
 		if (heap->extra_data) {
@@ -491,31 +537,30 @@
 			case ION_HEAP_TYPE_CP:
 				reusable = ((struct ion_cp_heap_pdata *)
 						heap->extra_data)->reusable;
+				mem_is_fmem = ((struct ion_cp_heap_pdata *)
+						heap->extra_data)->mem_is_fmem;
 				break;
 			case ION_HEAP_TYPE_CARVEOUT:
 				adjacent_heap_id = ((struct ion_co_heap_pdata *)
 					heap->extra_data)->adjacent_mem_id;
+				mem_is_fmem = ((struct ion_co_heap_pdata *)
+						heap->extra_data)->mem_is_fmem;
 				break;
 			default:
 				break;
 			}
 		}
 
-		if (adjacent_heap_id != INVALID_HEAP_ID) {
-			const struct ion_platform_heap *adj_heap =
-						find_ion_heap(adjacent_heap_id);
-			if (adj_heap) {
-				adj_reusable = ((struct ion_cp_heap_pdata *)
-						adj_heap->extra_data)->reusable;
-				if (adj_reusable)
-					fmem_pdata.reserved_size += heap->size;
-			}
+		if (mem_is_fmem && !reusable) {
+			if (adjacent_heap_id != INVALID_HEAP_ID)
+				fmem_pdata.reserved_size_low += heap->size;
+			else
+				fmem_pdata.reserved_size_high += heap->size;
 		}
-
-		if (!reusable && !adj_reusable)
-			reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
-		else
+		if (mem_is_fmem)
 			fmem_pdata.size += heap->size;
+		else
+			reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
 	}
 #endif
 }
@@ -531,6 +576,7 @@
 	reserve_pmem_memory();
 	reserve_ion_memory();
 	reserve_mdp_memory();
+	reserve_rtb_memory();
 }
 
 static struct reserve_info msm8960_reserve_info __initdata = {
@@ -1186,9 +1232,7 @@
 static struct msm_spm_platform_data msm_spm_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW0_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0xB0,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1203,9 +1247,7 @@
 	},
 	[1] = {
 		.reg_base_addr = MSM_SAW1_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0xB0,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1259,7 +1301,6 @@
 static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
 	[0] = {
 		.reg_base_addr = MSM_SAW_L2_BASE,
-		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
 		.reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
@@ -1824,7 +1865,7 @@
 };
 
 static struct tsens_platform_data msm_tsens_pdata  = {
-		.slope			= 910,
+		.slope			= {910, 910, 910, 910, 910},
 		.tsens_factor		= 1000,
 		.hw_type		= MSM_8960,
 		.tsens_num_sensor	= 5,
@@ -1943,6 +1984,9 @@
 #endif
 	&msm_device_dspcrashd_8960,
 	&msm8960_device_watchdog,
+#ifdef CONFIG_MSM_RTB
+	&msm_rtb_device,
+#endif
 };
 
 static struct platform_device *sim_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index 95a1347..58e40db 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -70,6 +70,7 @@
 	REGULATOR_SUPPLY("8018_s1",		NULL),
 	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_otg"),
 	REGULATOR_SUPPLY("HSIC_VDDCX",		"msm_hsic_peripheral"),
+	REGULATOR_SUPPLY("HSIC_VDDCX",		"msm_hsic_host"),
 };
 VREG_CONSUMERS(S2) = {
 	REGULATOR_SUPPLY("8018_s2",		NULL),
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 1f19bf6..74471dd 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -518,6 +518,7 @@
 	&msm_device_hsic_peripheral,
 	&msm_device_gadget_peripheral,
 	&msm_device_hsusb_host,
+	&msm_device_hsic_host,
 	&msm_device_usb_bam,
 	&android_usb_device,
 	&msm9615_device_uart_gsbi4,
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index b4b0b9a..4b6716e 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -36,6 +36,7 @@
 #include <mach/ion.h>
 #endif
 #include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
 #include "clock.h"
 
 #define MSM_KERNEL_EBI1_MEM_SIZE	0x280000
@@ -98,6 +99,17 @@
 	.align = SZ_128K,
 };
 
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -107,14 +119,6 @@
 			.name	= ION_VMALLOC_HEAP_NAME,
 		},
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *) &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -139,6 +143,14 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *) &co_ion_pdata,
+		},
+		{
 			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
@@ -182,6 +194,126 @@
 }
 #endif
 
+static struct resource smd_resource[] = {
+	{
+		.name	= "modem_smd_in",
+		.start	= 32 + 17,		/* mss_sw_to_kpss_ipc_irq0  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "modem_smsm_in",
+		.start	= 32 + 18,		/* mss_sw_to_kpss_ipc_irq1  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "adsp_smd_in",
+		.start	= 32 + 156,		/* lpass_to_kpss_ipc_irq0  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "adsp_smsm_in",
+		.start	= 32 + 157,		/* lpass_to_kpss_ipc_irq1  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "wcnss_smd_in",
+		.start	= 32 + 142,		/* WcnssAppsSmdMedIrq  */
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "wcnss_smsm_in",
+		.start	= 32 + 144,		/* RicaAppsWlanSmsmIrq  */
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+	{
+		.irq_config_id = SMD_MODEM,
+		.subsys_name = "modem",
+		.edge = SMD_APPS_MODEM,
+
+		.smd_int.irq_name = "modem_smd_in",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos = 1 << 12,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "modem_smsm_in",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smsm_dev",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos = 1 << 13,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+	{
+		.irq_config_id = SMD_Q6,
+		.subsys_name = "q6",
+		.edge = SMD_APPS_QDSP,
+
+		.smd_int.irq_name = "adsp_smd_in",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos = 1 << 8,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "adsp_smsm_in",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smsm_dev",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos = 1 << 9,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+	{
+		.irq_config_id = SMD_WCNSS,
+		.subsys_name = "wcnss",
+		.edge = SMD_APPS_WCNSS,
+
+		.smd_int.irq_name = "wcnss_smd_in",
+		.smd_int.flags = IRQF_TRIGGER_RISING,
+		.smd_int.irq_id = -1,
+		.smd_int.device_name = "smd_dev",
+		.smd_int.dev_id = 0,
+		.smd_int.out_bit_pos = 1 << 17,
+		.smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smd_int.out_offset = 0x8,
+
+		.smsm_int.irq_name = "wcnss_smsm_in",
+		.smsm_int.flags = IRQF_TRIGGER_RISING,
+		.smsm_int.irq_id = -1,
+		.smsm_int.device_name = "smsm_dev",
+		.smsm_int.dev_id = 0,
+		.smsm_int.out_bit_pos = 1 << 19,
+		.smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+		.smsm_int.out_offset = 0x8,
+	},
+};
+
+static struct smd_platform smd_platform_data = {
+	.num_ss_configs = ARRAY_SIZE(smd_config_list),
+	.smd_ss_configs = smd_config_list,
+};
+
+struct platform_device msm_device_smd_copper = {
+	.name	= "msm_smd",
+	.id	= -1,
+	.resource = smd_resource,
+	.num_resources = ARRAY_SIZE(smd_resource),
+	.dev = {
+		.platform_data = &smd_platform_data,
+	}
+};
+
 static void __init msm_copper_calculate_reserve_sizes(void)
 {
 #ifdef CONFIG_ION_MSM
@@ -223,6 +355,7 @@
 #ifdef CONFIG_ION_MSM
 	platform_device_register(&ion_dev);
 #endif
+	platform_device_register(&msm_device_smd_copper);
 }
 
 static struct of_device_id irq_match[] __initdata  = {
@@ -266,6 +399,8 @@
 			"msm_otg", NULL),
 	OF_DEV_AUXDATA("qcom,spi-qup-v2", 0xF9924000, \
 			"spi_qsd.1", NULL),
+	OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
+			"spmi-pmic-arb.0", NULL),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index c0b1d16..77af5e2 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -22,6 +22,7 @@
 #include <mach/irqs-7xxx.h>
 #include "devices-msm7x2xa.h"
 #include "board-msm7627a.h"
+#include <mach/vreg.h>
 
 #ifdef CONFIG_MSM_CAMERA_V4L2
 static uint32_t camera_off_gpio_table[] = {
@@ -177,6 +178,7 @@
 static struct msm_camera_sensor_info msm_camera_sensor_s5k4e1_data = {
 	.sensor_name    = "s5k4e1",
 	.sensor_reset_enable = 1,
+	.pmic_gpio_enable    = 0,
 	.pdata                  = &msm_camera_device_data_csi1,
 	.flash_data             = &flash_s5k4e1,
 	.sensor_platform_info   = &sensor_board_info_s5k4e1,
@@ -205,6 +207,7 @@
 static struct msm_camera_sensor_info msm_camera_sensor_mt9e013_data = {
 	.sensor_name    = "mt9e013",
 	.sensor_reset_enable = 1,
+	.pmic_gpio_enable    = 0,
 	.pdata                  = &msm_camera_device_data_csi1,
 	.flash_data             = &flash_mt9e013,
 	.sensor_platform_info   = &sensor_board_info_mt9e013,
@@ -227,6 +230,7 @@
 	.sensor_name    = "imx072",
 	.sensor_reset_enable = 1,
 	.sensor_reset   = GPIO_CAM_GP_CAMIF_RESET_N, /* TODO 106,*/
+	.pmic_gpio_enable  = 0,
 	.sensor_pwd             = 85,
 	.vcm_pwd                = GPIO_CAM_GP_CAM_PWDN,
 	.vcm_enable             = 1,
@@ -261,6 +265,7 @@
 static struct msm_camera_sensor_info msm_camera_sensor_ov9726_data = {
 	.sensor_name    = "ov9726",
 	.sensor_reset_enable = 0,
+	.pmic_gpio_enable  = 0,
 	.pdata                  = &msm_camera_device_data_csi0,
 	.flash_data             = &flash_ov9726,
 	.sensor_platform_info   = &sensor_board_info_ov9726,
@@ -385,6 +390,85 @@
 	gpio_direction_output(QRD_GPIO_CAM_3MP_PWDN, 1);
 }
 
+#define GPIO_SKU3_CAM_5MP_SHDN_N   5         /* PWDN */
+#define GPIO_SKU3_CAM_5MP_CAMIF_RESET   6    /* (board_is(EVT))?123:121 RESET */
+#define GPIO_SKU3_CAM_5MP_CAM_DRIVER_PWDN 30
+
+#define GPIO_SKU1_CAM_VGA_SHDN    18
+#define GPIO_SKU1_CAM_VGA_RESET_N 29
+
+static void evb_camera_gpio_cfg(void)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_SKU3_CAM_5MP_SHDN_N, "ov5647");
+	if (rc < 0)
+		pr_err("%s: gpio_request GPIO_SKU3_CAM_5MP_SHDN_N failed!",
+			 __func__);
+
+	pr_debug("gpio_tlmm_config %d\r\n", GPIO_SKU3_CAM_5MP_SHDN_N);
+	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU3_CAM_5MP_SHDN_N, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s:unable to enable Powr Dwn gpio for main camera!\n",
+			 __func__);
+		gpio_free(GPIO_SKU3_CAM_5MP_SHDN_N);
+	}
+
+	gpio_direction_output(GPIO_SKU3_CAM_5MP_SHDN_N, 1);
+
+	rc = gpio_request(GPIO_SKU3_CAM_5MP_CAMIF_RESET, "ov5647");
+	if (rc < 0)
+		pr_err("%s: gpio_request GPIO_SKU3_CAM_5MP_CAMIF_RESET failed!",
+			 __func__);
+
+	pr_debug("gpio_tlmm_config %d\r\n", GPIO_SKU3_CAM_5MP_CAMIF_RESET);
+	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU3_CAM_5MP_CAMIF_RESET, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s: unable to enable reset gpio for main camera!\n",
+			 __func__);
+		gpio_free(GPIO_SKU3_CAM_5MP_CAMIF_RESET);
+	}
+
+	gpio_direction_output(GPIO_SKU3_CAM_5MP_CAMIF_RESET, 1);
+
+	rc = gpio_request(GPIO_SKU1_CAM_VGA_SHDN, "ov7692");
+	if (rc < 0)
+		pr_err("%s: gpio_request---GPIO_SKU1_CAM_VGA_SHDN failed!",
+			 __func__);
+
+	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU1_CAM_VGA_SHDN, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s:unable to enable Powr Dwn gpio for frnt camera!\n",
+			 __func__);
+		gpio_free(GPIO_SKU1_CAM_VGA_SHDN);
+	}
+
+	gpio_direction_output(GPIO_SKU1_CAM_VGA_SHDN, 1);
+
+	rc = gpio_request(GPIO_SKU1_CAM_VGA_RESET_N, "ov7692");
+	if (rc < 0)
+		pr_err("%s: gpio_request---GPIO_SKU1_CAM_VGA_RESET_N failed!",
+			 __func__);
+
+	rc = gpio_tlmm_config(GPIO_CFG(GPIO_SKU1_CAM_VGA_RESET_N, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+
+	if (rc < 0) {
+		pr_err("%s: unable to enable reset gpio for front camera!\n",
+			 __func__);
+		gpio_free(GPIO_SKU1_CAM_VGA_RESET_N);
+	}
+	gpio_direction_output(GPIO_SKU1_CAM_VGA_RESET_N, 1);
+
+}
+
 static void msm_camera_vreg_config(int vreg_en)
 {
 	int rc = vreg_en ?
@@ -495,6 +579,45 @@
 	.ioext.appsz		= MSM7XXX_CLK_CTL_SIZE,
 };
 
+#ifdef CONFIG_OV5647
+
+static struct msm_camera_sensor_platform_info ov5647_sensor_7627a_info = {
+	.mount_angle = 90
+};
+
+static struct msm_camera_sensor_flash_src msm_flash_src_ov5647 = {
+	.flash_sr_type = MSM_CAMERA_FLASH_SRC_LED,
+	._fsrc.led_src.led_name = "flashlight",
+	._fsrc.led_src.led_name_len = 10,
+};
+
+static struct msm_camera_sensor_flash_data flash_ov5647 = {
+	.flash_type             = MSM_CAMERA_FLASH_LED,
+	.flash_src              = &msm_flash_src_ov5647,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov5647_data = {
+	.sensor_name    = "ov5647",
+	.sensor_reset_enable = 1,
+	.sensor_reset   = GPIO_SKU3_CAM_5MP_CAMIF_RESET,
+	.pmic_gpio_enable  = 1,
+	.sensor_pwd     = GPIO_SKU3_CAM_5MP_SHDN_N,
+	.vcm_pwd        = GPIO_SKU3_CAM_5MP_CAM_DRIVER_PWDN,
+	.vcm_enable     = 0,
+	.pdata          = &msm_camera_device_data_rear,
+	.flash_data     = &flash_ov5647,
+	.sensor_platform_info   = &ov5647_sensor_7627a_info,
+	.csi_if                 = 1
+};
+
+static struct platform_device msm_camera_sensor_ov5647 = {
+	.name      = "msm_camera_ov5647",
+	.dev       = {
+		.platform_data = &msm_camera_sensor_ov5647_data,
+	},
+};
+#endif
+
 #ifdef CONFIG_S5K4E1
 static struct msm_camera_sensor_platform_info s5k4e1_sensor_7627a_info = {
 	.mount_angle = 90
@@ -509,6 +632,7 @@
 	.sensor_name		= "s5k4e1",
 	.sensor_reset_enable	= 1,
 	.sensor_reset		= GPIO_CAM_GP_CAMIF_RESET_N,
+	.pmic_gpio_enable       = 0,
 	.sensor_pwd	     = 85,
 	.vcm_pwd		= GPIO_CAM_GP_CAM_PWDN,
 	.vcm_enable	     = 1,
@@ -540,6 +664,7 @@
 	.sensor_name		= "imx072",
 	.sensor_reset_enable	= 1,
 	.sensor_reset		= GPIO_CAM_GP_CAMIF_RESET_N, /* TODO 106,*/
+	.pmic_gpio_enable       = 0,
 	.sensor_pwd	     = 85,
 	.vcm_pwd		= GPIO_CAM_GP_CAM_PWDN,
 	.vcm_enable	     = 1,
@@ -572,6 +697,7 @@
 	.sensor_name		= "ov9726",
 	.sensor_reset_enable	= 0,
 	.sensor_reset		= GPIO_CAM_GP_CAM1MP_XCLR,
+	.pmic_gpio_enable       = 0,
 	.sensor_pwd	     = 85,
 	.vcm_pwd		= 1,
 	.vcm_enable	     = 0,
@@ -605,6 +731,7 @@
 	.sensor_name		= "mt9e013",
 	.sensor_reset		= 0,
 	.sensor_reset_enable	= 1,
+	.pmic_gpio_enable       = 0,
 	.sensor_pwd		= 85,
 	.vcm_pwd		= 1,
 	.vcm_enable		= 0,
@@ -641,6 +768,7 @@
 static struct msm_camera_sensor_info msm_camera_sensor_ov5640_data = {
 	.sensor_name	    = "ov5640",
 	.sensor_reset_enable    = 1,
+	.pmic_gpio_enable  = 0,
 	.sensor_reset	   = QRD_GPIO_CAM_5MP_RESET,
 	.sensor_pwd	     = QRD_GPIO_CAM_5MP_SHDN_EN,
 	.vcm_pwd		= 0,
@@ -671,8 +799,9 @@
 static struct msm_camera_sensor_info msm_camera_sensor_ov7692_data = {
 	.sensor_name	    = "ov7692",
 	.sensor_reset_enable    = 0,
-	.sensor_reset	   = 0,
-	.sensor_pwd	     = QRD_GPIO_CAM_3MP_PWDN,
+	.pmic_gpio_enable  = 1,
+	.sensor_reset	   = GPIO_SKU1_CAM_VGA_RESET_N,
+	.sensor_pwd	     = GPIO_SKU1_CAM_VGA_SHDN,
 	.vcm_pwd		= 0,
 	.vcm_enable	     = 0,
 	.pdata			= &msm_camera_device_data_front,
@@ -731,6 +860,22 @@
 	#endif
 };
 
+static struct i2c_board_info i2c_camera_devices_evb[] = {
+	#ifdef CONFIG_OV5647
+	{
+		I2C_BOARD_INFO("ov5647", 0x36 << 1),
+	},
+	{
+		I2C_BOARD_INFO("ov5647_af", 0x18 >> 1),
+	},
+	#endif
+	#ifdef CONFIG_WEBCAM_OV7692_QRD
+	{
+		I2C_BOARD_INFO("ov7692", 0x78),
+	},
+	#endif
+};
+
 static struct platform_device *camera_devices_msm[] __initdata = {
 #ifdef CONFIG_S5K4E1
 	&msm_camera_sensor_s5k4e1,
@@ -754,6 +899,15 @@
 	&msm_camera_sensor_ov7692,
 #endif
 };
+
+static struct platform_device *camera_devices_evb[] __initdata = {
+#ifdef CONFIG_OV5647
+	&msm_camera_sensor_ov5647,
+#endif
+#ifdef CONFIG_WEBCAM_OV7692_QRD
+	&msm_camera_sensor_ov7692,
+#endif
+};
 #endif
 
 enum {
@@ -785,24 +939,127 @@
 				ARRAY_SIZE(cam_exp_i2c_info));
 }
 
+#define LCD_CAMERA_LDO_2V8 35 /* SKU1&SKU3 2.8V LDO */
+#define SKU3_LCD_CAMERA_LDO_1V8 40 /* SKU3 1.8V LDO */
+
+static int lcd_camera_ldo_1v8 = SKU3_LCD_CAMERA_LDO_1V8;
+
+static void lcd_camera_power_init(void)
+{
+	int rc = 0;
+
+	pr_debug("lcd_camera_power_init\n");
+
+	lcd_camera_ldo_1v8 = SKU3_LCD_CAMERA_LDO_1V8; /* SKU3 PVT */
+
+	/* LDO_EXT2V8 */
+	if (gpio_request(LCD_CAMERA_LDO_2V8, "lcd_camera_ldo_2v8")) {
+		pr_err("failed to request gpio lcd_camera_ldo_2v8\n");
+		return;
+	}
+
+	rc = gpio_tlmm_config(GPIO_CFG(LCD_CAMERA_LDO_2V8, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s: unable to enable lcd_camera_ldo_2v8!\n", __func__);
+		goto fail_gpio2;
+	}
+
+	/* LDO_EVT1V8 */
+	if (gpio_request(lcd_camera_ldo_1v8, "lcd_camera_ldo_1v8")) {
+		pr_err("failed to request gpio lcd_camera_ldo_1v8\n");
+		goto fail_gpio2;
+	}
+
+	rc = gpio_tlmm_config(GPIO_CFG(lcd_camera_ldo_1v8, 0,
+		GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN,
+		GPIO_CFG_2MA), GPIO_CFG_ENABLE);
+	if (rc < 0) {
+		pr_err("%s: unable to enable lcd_camera_ldo_1v8!\n", __func__);
+		goto fail_gpio1;
+	}
+
+	return;
+
+fail_gpio1:
+	gpio_free(lcd_camera_ldo_1v8);
+fail_gpio2:
+	gpio_free(LCD_CAMERA_LDO_2V8);
+
+	return;
+}
+
+static int lcd_camera_power_on_sku3(void)
+{
+	int rc = 0;
+
+	pr_debug("turn on sku3 lcd_camera_ldo_1v8\n");
+	gpio_set_value_cansleep(lcd_camera_ldo_1v8, 1);
+
+	pr_debug("turn on sku3 lcd_camera_ldo\n");
+	gpio_set_value_cansleep(LCD_CAMERA_LDO_2V8, 1);
+
+	return rc;
+}
+
+static int lcd_camera_power_off_sku3(void)
+{
+	int rc = 0;
+
+	pr_debug("turn off sku3 lcd_camera_ldo_1v8\n");
+	gpio_set_value_cansleep(lcd_camera_ldo_1v8, 0);
+
+	pr_debug("turn off sku3 lcd_camera_ldo\n");
+	gpio_set_value_cansleep(LCD_CAMERA_LDO_2V8, 0);
+
+	gpio_free(lcd_camera_ldo_1v8);
+	gpio_free(LCD_CAMERA_LDO_2V8);
+
+	return rc;
+}
+
+int lcd_camera_power_onoff(int on)
+{
+	int rc = 0;
+
+	pr_debug("lcd_camera_power_onoff on = %d,\n", on);
+
+	if (on)
+		rc = lcd_camera_power_on_sku3();
+	else
+		rc = lcd_camera_power_off_sku3();
+
+	return rc;
+}
+EXPORT_SYMBOL(lcd_camera_power_onoff);
+
+
 void __init msm7627a_camera_init(void)
 {
 	int rc;
 
+	pr_debug("msm7627a_camera_init Entered\n");
+	/* LCD and camera power (VREG & LDO) init */
+	if (machine_is_msm7627a_evb())
+		lcd_camera_power_init();
+
 #ifndef CONFIG_MSM_CAMERA_V4L2
 	if (machine_is_msm7627a_qrd1()) {
 		qrd1_camera_gpio_cfg();
 		platform_add_devices(camera_devices_qrd,
 				ARRAY_SIZE(camera_devices_qrd));
-	} else if (machine_is_msm7627a_evb())
-		return;
-	else if (machine_is_msm7627a_qrd3())
+	} else if (machine_is_msm7627a_evb()) {
+		evb_camera_gpio_cfg();
+		platform_add_devices(camera_devices_evb,
+				ARRAY_SIZE(camera_devices_evb));
+	} else if (machine_is_msm7627a_qrd3())
 		return;
 	else
 		platform_add_devices(camera_devices_msm,
 				ARRAY_SIZE(camera_devices_msm));
 #endif
-	if (!machine_is_msm7627a_qrd1())
+	if (!machine_is_msm7627a_qrd1() || !machine_is_msm7627a_evb())
 		register_i2c_devices();
 	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
 
@@ -822,11 +1079,16 @@
 	msm7x27a_init_cam();
 #endif
 #ifndef CONFIG_MSM_CAMERA_V4L2
-	if (machine_is_msm7627a_qrd1())
+	if (machine_is_msm7627a_qrd1()) {
 		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
 				i2c_camera_devices_qrd,
 				ARRAY_SIZE(i2c_camera_devices_qrd));
-	else
+	} else if (machine_is_msm7627a_evb()) {
+		pr_debug("machine_is_msm7627a_evb i2c_register_board_info\n");
+		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
+				i2c_camera_devices_evb,
+				ARRAY_SIZE(i2c_camera_devices_evb));
+	} else
 #endif
 		i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
 				i2c_camera_devices,
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 011a4d4..4e856b1 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -28,10 +28,10 @@
 #include "board-msm7627a.h"
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE	     0x260000
+#define MSM_FB_SIZE	     0x261000
 #define MSM7x25A_MSM_FB_SIZE    0xE1000
 #else
-#define MSM_FB_SIZE	     0x195000
+#define MSM_FB_SIZE	     0x196000
 #define MSM7x25A_MSM_FB_SIZE    0x96000
 #endif
 
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 93a6178..a10d81a 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -72,17 +72,17 @@
 };
 
 static struct msm_gpio sdc2_sleep_cfg_data[] = {
-	{GPIO_CFG(62, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(62, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
 								"sdc2_clk"},
-	{GPIO_CFG(63, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(63, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_cmd"},
-	{GPIO_CFG(64, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(64, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_dat_3"},
-	{GPIO_CFG(65, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(65, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_dat_2"},
-	{GPIO_CFG(66, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(66, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_dat_1"},
-	{GPIO_CFG(67, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+	{GPIO_CFG(67, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 								"sdc2_dat_0"},
 };
 static struct msm_gpio sdc3_cfg_data[] = {
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 51da14b..a6b29dc 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -47,6 +47,7 @@
 #include <mach/msm_battery.h>
 #include <linux/smsc911x.h>
 #include <linux/atmel_maxtouch.h>
+#include <linux/fmem.h>
 #include "devices.h"
 #include "timer.h"
 #include "board-msm7x27a-regulator.h"
@@ -370,6 +371,9 @@
 	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
 	.cached = 1,
 	.memory_type = MEMTYPE_EBI1,
+	.request_region = request_fmem_c_region,
+	.release_region = release_fmem_c_region,
+	.reusable = 1,
 };
 
 static struct platform_device android_pmem_adsp_device = {
@@ -672,6 +676,14 @@
 static void msm7x27a_cfg_uart2dm_serial(void) { }
 #endif
 
+struct fmem_platform_data fmem_pdata;
+
+struct platform_device fmem_device = {
+	.name = "fmem",
+	.id = -1,
+	.dev = { .platform_data = &fmem_pdata },
+};
+
 static struct platform_device *rumi_sim_devices[] __initdata = {
 	&msm_device_dmov,
 	&msm_device_smd,
@@ -700,6 +712,7 @@
 	&msm_gsbi1_qup_i2c_device,
 	&msm_device_otg,
 	&msm_device_gadget_peripheral,
+	&fmem_device,
 	&android_usb_device,
 	&android_pmem_device,
 	&android_pmem_adsp_device,
@@ -744,8 +757,19 @@
 	},
 };
 
+#ifdef CONFIG_ANDROID_PMEM
+static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
+		&android_pmem_adsp_pdata,
+		&android_pmem_audio_pdata,
+		&android_pmem_pdata,
+};
+#endif
+
 static void __init size_pmem_devices(void)
 {
+#ifdef CONFIG_ANDROID_PMEM
+	unsigned int i;
+	unsigned int reusable_count = 0;
 
 	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
 		pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
@@ -755,11 +779,30 @@
 		pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
 	}
 
-#ifdef CONFIG_ANDROID_PMEM
 	android_pmem_adsp_pdata.size = pmem_adsp_size;
 	android_pmem_pdata.size = pmem_mdp_size;
 	android_pmem_audio_pdata.size = pmem_audio_size;
+
+	fmem_pdata.size = 0;
+
+	/* Find pmem devices that should use FMEM (reusable) memory.
+	 */
+	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
+
+		if (!reusable_count && pdata->reusable)
+			fmem_pdata.size += pdata->size;
+
+		reusable_count += (pdata->reusable) ? 1 : 0;
+
+		if (pdata->reusable && reusable_count > 1) {
+			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
+				__func__, pdata->name);
+			pdata->reusable = 0;
+		}
+	}
 #endif
+
 }
 
 static void __init reserve_memory_for(struct android_pmem_platform_data *p)
@@ -770,9 +813,12 @@
 static void __init reserve_pmem_memory(void)
 {
 #ifdef CONFIG_ANDROID_PMEM
-	reserve_memory_for(&android_pmem_adsp_pdata);
-	reserve_memory_for(&android_pmem_pdata);
-	reserve_memory_for(&android_pmem_audio_pdata);
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+		if (!pmem_pdata_array[i]->reusable)
+			reserve_memory_for(pmem_pdata_array[i]);
+	}
+
 	msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
 #endif
 }
@@ -798,6 +844,7 @@
 {
 	reserve_info = &msm7x27a_reserve_info;
 	msm_reserve();
+	fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
 }
 
 static void __init msm8625_reserve(void)
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 74ba1b3..c31e6d9 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2643,15 +2643,19 @@
 #endif /* CONFIG_MSM_DSPS */
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1024 * 600 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1024 * 600 * 4), 4096) * 3) /* 4 bpp x 3 pages */
 #else
-#define MSM_FB_PRIM_BUF_SIZE (1024 * 600 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+		(roundup((1024 * 600 * 4), 4096) * 2) /* 4 bpp x 2 pages */
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE  (1920 * 1080 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE  \
+		(roundup((1920 * 1080 * 2), 4096) * 1) /* 2 bpp x 1 page */
 #elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE  (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE  \
+		(roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
 #else
 #define MSM_FB_EXT_BUFT_SIZE	0
 #endif
@@ -5278,6 +5282,18 @@
 	.align = PAGE_SIZE,
 };
 #endif
+
+/**
+ * These heaps are listed in the order they will be allocated. Due to
+ * video hardware restrictions and content protection the FW heap has to
+ * be allocated adjacent (below) the MM heap and the MFC heap has to be
+ * allocated after the MM heap to ensure MFC heap is not more than 256MB
+ * away from the base address of the FW heap.
+ * However, the order of FW heap and MM heap doesn't matter since these
+ * two heaps are taken care of by separate code to ensure they are adjacent
+ * to each other.
+ * Don't swap the order unless you know what you are doing!
+ */
 static struct ion_platform_data ion_pdata = {
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
@@ -5288,14 +5304,6 @@
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_SF_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SF_HEAP_NAME,
-			.size	= MSM_ION_SF_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = (void *)&co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MM_HEAP_NAME,
@@ -5312,14 +5320,6 @@
 			.extra_data = (void *) &fw_co_ion_pdata,
 		},
 		{
-			.id	= ION_CAMERA_HEAP_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_CAMERA_HEAP_NAME,
-			.size	= MSM_ION_CAMERA_SIZE,
-			.memory_type = ION_EBI_TYPE,
-			.extra_data = &co_ion_pdata,
-		},
-		{
 			.id	= ION_CP_MFC_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_MFC_HEAP_NAME,
@@ -5328,6 +5328,22 @@
 			.extra_data = (void *) &cp_mfc_ion_pdata,
 		},
 		{
+			.id	= ION_SF_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = (void *)&co_ion_pdata,
+		},
+		{
+			.id	= ION_CAMERA_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_CAMERA_HEAP_NAME,
+			.size	= MSM_ION_CAMERA_SIZE,
+			.memory_type = ION_EBI_TYPE,
+			.extra_data = &co_ion_pdata,
+		},
+		{
 			.id	= ION_CP_WB_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CP,
 			.name	= ION_WB_HEAP_NAME,
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 8374636..bd7ec87 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -146,7 +146,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = N16(m, n) | SPDIV(SRC_SEL_##s, div), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 
 #define F_MND8(f, nmsb, nlsb, s, div, m, n) \
@@ -155,7 +154,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = N8(nmsb, nlsb, m, n) | SPDIV(SRC_SEL_##s, div), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 
 static struct clk_ops clk_ops_rcg_7x30;
@@ -227,14 +225,13 @@
 static struct clk_ops clk_ops_tcxo = {
 	.enable = tcxo_clk_enable,
 	.disable = tcxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = pcom_is_local,
 };
 
 static struct fixed_clk tcxo_clk = {
-	.rate = 19200000,
 	.c = {
 		.dbg_name = "tcxo_clk",
+		.rate = 19200000,
 		.ops = &clk_ops_tcxo,
 		CLK_INIT(tcxo_clk.c),
 	},
@@ -253,66 +250,65 @@
 static struct clk_ops clk_ops_lpxo = {
 	.enable = lpxo_clk_enable,
 	.disable = lpxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = pcom_is_local,
 };
 
 static struct fixed_clk lpxo_clk = {
-	.rate = 24576000,
 	.c = {
 		.dbg_name = "lpxo_clk",
+		.rate = 24576000,
 		.ops = &clk_ops_lpxo,
 		CLK_INIT(lpxo_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll1_clk = {
-	.rate = 768000000,
 	.en_reg = PLL_ENA_REG,
 	.en_mask = BIT(1),
 	.status_reg = PLL1_STATUS_BASE_REG,
 	.parent = &tcxo_clk.c,
 	.c = {
 		.dbg_name = "pll1_clk",
+		.rate = 768000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll1_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll2_clk = {
-	.rate = 806400000, /* TODO: Support scaling */
 	.en_reg = PLL_ENA_REG,
 	.en_mask = BIT(2),
 	.status_reg = PLL2_STATUS_BASE_REG,
 	.parent = &tcxo_clk.c,
 	.c = {
 		.dbg_name = "pll2_clk",
+		.rate = 806400000, /* TODO: Support scaling */
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll2_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll3_clk = {
-	.rate = 737280000,
 	.en_reg = PLL_ENA_REG,
 	.en_mask = BIT(3),
 	.status_reg = PLL3_STATUS_BASE_REG,
 	.parent = &lpxo_clk.c,
 	.c = {
 		.dbg_name = "pll3_clk",
+		.rate = 737280000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll3_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll4_clk = {
-	.rate = 891000000,
 	.en_reg = PLL_ENA_REG,
 	.en_mask = BIT(4),
 	.status_reg = PLL4_STATUS_BASE_REG,
 	.parent = &lpxo_clk.c,
 	.c = {
 		.dbg_name = "pll4_clk",
+		.rate = 891000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
 	},
@@ -321,7 +317,7 @@
 static struct clk_ops clk_ops_branch;
 
 static struct clk_freq_tbl clk_tbl_axi[] = {
-	F_RAW(1, &lpxo_clk.c, 0, 0, 0, 0, NULL),
+	F_RAW(1, &lpxo_clk.c, 0, 0, 0, NULL),
 	F_END,
 };
 
@@ -998,6 +994,7 @@
 	.ns_reg = CSI_NS_REG,
 	.md_reg = CSI_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(24, 17),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_csi,
 	.current_freq = &rcg_dummy_freq,
@@ -1011,7 +1008,7 @@
 };
 
 static struct clk_freq_tbl clk_tbl_tcxo[] = {
-	F_RAW(19200000, &tcxo_clk.c, 0, 0, 0, 0, NULL),
+	F_RAW(19200000, &tcxo_clk.c, 0, 0, 0, NULL),
 	F_END,
 };
 
@@ -1142,6 +1139,7 @@
 	.ns_reg = UART1DM_NS_REG,
 	.md_reg = UART1DM_NS_REG - 4,
 	.root_en_mask = BIT(11),
+	.mnd_en_mask = BIT(8),
 	.freq_tbl = clk_tbl_uartdm,
 	.ns_mask = F_MASK_MND16,
 	.current_freq = &rcg_dummy_freq,
@@ -1167,6 +1165,7 @@
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_uartdm,
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -1252,7 +1251,7 @@
 	F_BASIC(192000000, pll1,  4),
 	F_BASIC(245760000, pll3,  3),
 	/* Sync to AXI. Hence this "rate" is not fixed. */
-	F_RAW(1, &lpxo_clk.c, 0, BIT(14), 0, 0, NULL),
+	F_RAW(1, &lpxo_clk.c, 0, BIT(14), 0, NULL),
 	F_END,
 };
 
@@ -1354,6 +1353,7 @@
 	.ns_reg = SDCn_NS_REG(1),
 	.md_reg = SDCn_NS_REG(1) - 4,
 	.ns_mask = F_MASK_MND8(19, 12),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_sdc1_3,
 	.current_freq = &rcg_dummy_freq,
@@ -1377,6 +1377,7 @@
 	.ns_reg = SDCn_NS_REG(3),
 	.md_reg = SDCn_NS_REG(3) - 4,
 	.ns_mask = F_MASK_MND8(19, 12),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_sdc1_3,
 	.current_freq = &rcg_dummy_freq,
@@ -1412,6 +1413,7 @@
 	.ns_reg = SDCn_NS_REG(2),
 	.md_reg = SDCn_NS_REG(2) - 4,
 	.ns_mask = F_MASK_MND8(20, 13),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_sdc2_4,
 	.current_freq = &rcg_dummy_freq,
@@ -1435,6 +1437,7 @@
 	.ns_reg = SDCn_NS_REG(4),
 	.md_reg = SDCn_NS_REG(4) - 4,
 	.ns_mask = F_MASK_MND8(20, 13),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_sdc2_4,
 	.current_freq = &rcg_dummy_freq,
@@ -1505,6 +1508,7 @@
 	.md_reg = MDP_LCDC_NS_REG - 4,
 	.root_en_mask = BIT(11),
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_mdp_lcdc,
 	.current_freq = &rcg_dummy_freq,
@@ -1533,8 +1537,8 @@
 };
 
 static struct clk_freq_tbl clk_tbl_mdp_vsync[] = {
-	F_RAW(       0, &gnd_clk.c,  0, (0x3<<2), 0, 0, NULL),
-	F_RAW(24576000, &lpxo_clk.c, 0, (0x1<<2), 0, 0, NULL),
+	F_RAW(       0, &gnd_clk.c,  0, (0x3<<2), 0, NULL),
+	F_RAW(24576000, &lpxo_clk.c, 0, (0x1<<2), 0, NULL),
 	F_END,
 };
 
@@ -1578,6 +1582,7 @@
 	.md_reg = MI2S_RX_NS_REG - 4,
 	.root_en_mask = BIT(11),
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_mi2s_codec,
 	.current_freq = &rcg_dummy_freq,
@@ -1617,6 +1622,7 @@
 	.md_reg = MI2S_TX_NS_REG - 4,
 	.root_en_mask = BIT(11),
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_mi2s_codec,
 	.current_freq = &rcg_dummy_freq,
@@ -1662,6 +1668,7 @@
 	.md_reg = MI2S_NS_REG - 4,
 	.root_en_mask = BIT(11),
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_mi2s,
 	.current_freq = &rcg_dummy_freq,
@@ -1694,7 +1701,6 @@
 		.freq_hz = f, \
 		.md_val = MD16(m, n), \
 		.ns_val = N16(m, n) | SPDIV(SRC_SEL_SDAC_##s, div), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 		.src_clk = &s##_clk.c, \
 	}
 
@@ -1722,6 +1728,7 @@
 	.ns_reg = SDAC_NS_REG,
 	.md_reg = SDAC_NS_REG - 4,
 	.root_en_mask = BIT(11),
+	.mnd_en_mask = BIT(8),
 	.freq_tbl = clk_tbl_sdac,
 	.ns_mask = F_MASK_MND16,
 	.set_rate = set_rate_mnd,
@@ -1765,6 +1772,7 @@
 	},
 	.md_reg = TV_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(23, 16),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_tv,
 	.current_freq = &rcg_dummy_freq,
@@ -1856,6 +1864,7 @@
 	},
 	.md_reg = USBH_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(23, 16),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -1994,6 +2003,7 @@
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_vfe_jpeg,
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -2018,6 +2028,7 @@
 	.root_en_mask = BIT(13),
 	.freq_tbl = clk_tbl_vfe_jpeg,
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -2102,6 +2113,7 @@
 	.root_en_mask = BIT(9),
 	.freq_tbl = clk_tbl_cam,
 	.ns_mask = F_MASK_MND16,
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -2134,6 +2146,7 @@
 	.ns_reg = VPE_NS_REG,
 	.md_reg = VPE_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(22, 15),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_vpe,
 	.current_freq = &rcg_dummy_freq,
@@ -2170,6 +2183,7 @@
 	.ns_reg = MFC_NS_REG,
 	.md_reg = MFC_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(24, 17),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_mfc,
 	.current_freq = &rcg_dummy_freq,
@@ -2218,6 +2232,7 @@
 	.ns_reg = SPI_NS_REG,
 	.md_reg = SPI_NS_REG - 4,
 	.ns_mask = F_MASK_MND8(19, 12),
+	.mnd_en_mask = BIT(8),
 	.root_en_mask = BIT(11),
 	.freq_tbl = clk_tbl_spi,
 	.current_freq = &rcg_dummy_freq,
@@ -2231,10 +2246,10 @@
 };
 
 static struct clk_freq_tbl clk_tbl_lpa_codec[] = {
-	F_RAW(1, NULL, 0, 0, 0, 0, NULL), /* src MI2S_CODEC_RX */
-	F_RAW(2, NULL, 0, 1, 0, 0, NULL), /* src ECODEC_CIF */
-	F_RAW(3, NULL, 0, 2, 0, 0, NULL), /* src MI2S */
-	F_RAW(4, NULL, 0, 3, 0, 0, NULL), /* src SDAC */
+	F_RAW(1, NULL, 0, 0, 0, NULL), /* src MI2S_CODEC_RX */
+	F_RAW(2, NULL, 0, 1, 0, NULL), /* src ECODEC_CIF */
+	F_RAW(3, NULL, 0, 2, 0, NULL), /* src MI2S */
+	F_RAW(4, NULL, 0, 3, 0, NULL), /* src SDAC */
 	F_END,
 };
 
@@ -2260,7 +2275,7 @@
 };
 
 static struct clk_freq_tbl clk_tbl_mdc[] = {
-	F_RAW(1, NULL, 0, 0, 0, 0, NULL),
+	F_RAW(1, NULL, 0, 0, 0, NULL),
 	F_END
 };
 
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 493a210..8188e08 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -423,7 +423,7 @@
 					RPM_VREG_VOTER3, 1800000, 1800000, 1);
 		} else {
 			rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
-					RPM_VREG_VOTER3, 2200000, 2200000, 1);
+					RPM_VREG_VOTER3, 2100000, 2100000, 1);
 			if (rc)
 				return rc;
 			rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
@@ -470,14 +470,13 @@
 static struct clk_ops clk_ops_pxo = {
 	.enable = pxo_clk_enable,
 	.disable = pxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = local_clk_is_local,
 };
 
 static struct fixed_clk pxo_clk = {
-	.rate = 27000000,
 	.c = {
 		.dbg_name = "pxo_clk",
+		.rate = 27000000,
 		.ops = &clk_ops_pxo,
 		CLK_INIT(pxo_clk.c),
 	},
@@ -496,36 +495,35 @@
 static struct clk_ops clk_ops_cxo = {
 	.enable = cxo_clk_enable,
 	.disable = cxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = local_clk_is_local,
 };
 
 static struct fixed_clk cxo_clk = {
-	.rate = 19200000,
 	.c = {
 		.dbg_name = "cxo_clk",
+		.rate = 19200000,
 		.ops = &clk_ops_cxo,
 		CLK_INIT(cxo_clk.c),
 	},
 };
 
 static struct pll_clk pll2_clk = {
-	.rate = 800000000,
 	.mode_reg = MM_PLL1_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll2_clk",
+		.rate = 800000000,
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll2_clk.c),
 	},
 };
 
 static struct pll_clk pll3_clk = {
-	.rate = 1200000000,
 	.mode_reg = BB_MMCC_PLL2_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll3_clk",
+		.rate = 1200000000,
 		.ops = &clk_ops_pll,
 		.vdd_class = &vdd_sr2_pll,
 		.fmax[VDD_SR2_PLL_ON] = ULONG_MAX,
@@ -534,50 +532,50 @@
 };
 
 static struct pll_vote_clk pll4_clk = {
-	.rate = 393216000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(4),
 	.status_reg = LCC_PLL0_STATUS_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll4_clk",
+		.rate = 393216000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll8_clk = {
-	.rate = 384000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(8),
 	.status_reg = BB_PLL8_STATUS_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll8_clk",
+		.rate = 384000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll8_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll14_clk = {
-	.rate = 480000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(14),
 	.status_reg = BB_PLL14_STATUS_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll14_clk",
+		.rate = 480000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll14_clk.c),
 	},
 };
 
 static struct pll_clk pll15_clk = {
-	.rate = 975000000,
 	.mode_reg = MM_PLL3_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll15_clk",
+		.rate = 975000000,
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll15_clk.c),
 	},
@@ -1246,6 +1244,7 @@
 		.md_reg = GPn_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gp, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1262,7 +1261,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gp[] = {
 	F_GP(        0, gnd,  1, 0, 0),
@@ -1297,6 +1295,7 @@
 		.md_reg = GSBIn_UART_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(31, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_uart, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1313,7 +1312,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
 	F_GSBI_UART(       0, gnd,  1,  0,   0),
@@ -1361,6 +1359,7 @@
 		.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_qup, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1377,7 +1376,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
 	F_GSBI_QUP(       0, gnd,  1, 0,  0),
@@ -1500,6 +1498,7 @@
 		.md_reg = SDCn_APPS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_sdc, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1516,7 +1515,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_sdc[] = {
 	F_SDC(        0, gnd,   1, 0,   0),
@@ -1545,7 +1543,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_tsif_ref[] = {
 	F_TSIF_REF(     0, gnd,  1, 0,   0),
@@ -1564,6 +1561,7 @@
 	.md_reg = TSIF_REF_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_tsif_ref,
 	.current_freq = &rcg_dummy_freq,
@@ -1621,6 +1619,7 @@
 	.md_reg = USB_HS##n##_XCVR_FS_CLK_MD_REG, \
 	.root_en_mask = BIT(11), \
 	.ns_mask = (BM(23, 16) | BM(6, 0)), \
+	.mnd_en_mask = BIT(8), \
 	.set_rate = set_rate_mnd, \
 	.freq_tbl = clk_tbl_usb, \
 	.current_freq = &rcg_dummy_freq, \
@@ -1638,7 +1637,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_usb[] = {
 	F_USB(       0, gnd,  1, 0,  0),
@@ -1667,6 +1665,7 @@
 	.md_reg = USB_HSIC_XCVR_FS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb_hsic,
 	.current_freq = &rcg_dummy_freq,
@@ -1787,6 +1786,7 @@
 		.md_reg = USB_FSn_XCVR_FS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_usb, \
 		.current_freq = &rcg_dummy_freq, \
@@ -2522,6 +2522,7 @@
 		.md_reg = CAMCLK##n##_MD_REG, \
 		.root_en_mask = BIT(2), \
 		.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0), \
+		.mnd_en_mask = BIT(5), \
 		.ctl_mask = BM(7, 6), \
 		.set_rate = set_rate_mnd_8, \
 		.freq_tbl = clk_tbl_cam, \
@@ -2540,7 +2541,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_cam[] = {
 	F_CAM(        0, gnd,  1, 0,  0),
@@ -2569,7 +2569,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_csi[] = {
 	F_CSI(        0, gnd,  1, 0, 0),
@@ -2588,6 +2587,7 @@
 	.md_reg	= CSI0_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_csi,
@@ -2643,6 +2643,7 @@
 	.md_reg	= CSI1_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_csi,
@@ -2698,6 +2699,7 @@
 	.md_reg = CSI2_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = BM(31, 24) | BM(15, 14) | BM(2, 0),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_csi,
@@ -3005,7 +3007,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_csi_phytimer[] = {
 	F_CSI_PHYTIMER(        0, gnd,  1, 0, 0),
@@ -3023,6 +3024,7 @@
 	.md_reg = CSIPHYTIMER_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(31, 24) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd_8,
 	.freq_tbl = clk_tbl_csi_phytimer,
@@ -3194,7 +3196,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(20, 16, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gfx2d[] = {
 	F_GFX2D(        0, gnd,  0,  0),
@@ -3308,7 +3309,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 
 static struct clk_freq_tbl clk_tbl_gfx3d_8960[] = {
@@ -3410,7 +3410,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 
 static struct clk_freq_tbl clk_tbl_vcap[] = {
@@ -3487,7 +3486,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 12, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 
 static struct clk_freq_tbl clk_tbl_ijpeg[] = {
@@ -3527,6 +3525,7 @@
 	.md_reg = IJPEG_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(15, 12) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_ijpeg,
@@ -3590,7 +3589,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MND_BANKED8(22, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_mdp[] = {
 	F_MDP(        0, gnd,  0,  0),
@@ -3822,7 +3820,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 #define F_TV(f, s, p_r, d, m, n) \
 	{ \
@@ -3831,7 +3828,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 		.extra_freq_data = (void *)p_r, \
 	}
 /* Switching TV freqs requires PLL reconfiguration. */
@@ -3873,6 +3869,7 @@
 	.md_reg = TV_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_tv,
 	.freq_tbl = clk_tbl_tv,
@@ -3885,6 +3882,21 @@
 	},
 };
 
+static struct cdiv_clk tv_src_div_clk = {
+	.b = {
+		.ctl_reg = TV_NS_REG,
+		.halt_check = NOCHECK,
+	},
+	.ns_reg = TV_NS_REG,
+	.div_offset = 6,
+	.max_div = 2,
+	.c = {
+		.dbg_name = "tv_src_div_clk",
+		.ops = &clk_ops_cdiv,
+		CLK_INIT(tv_src_div_clk.c),
+	},
+};
+
 static struct branch_clk tv_enc_clk = {
 	.b = {
 		.ctl_reg = TV_CC_REG,
@@ -3953,6 +3965,36 @@
 	},
 };
 
+static struct branch_clk rgb_tv_clk = {
+	.b = {
+		.ctl_reg = TV_CC2_REG,
+		.en_mask = BIT(14),
+		.halt_reg = DBG_BUS_VEC_J_REG,
+		.halt_bit = 27,
+	},
+	.parent = &tv_src_clk.c,
+	.c = {
+		.dbg_name = "rgb_tv_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(rgb_tv_clk.c),
+	},
+};
+
+static struct branch_clk npl_tv_clk = {
+	.b = {
+		.ctl_reg = TV_CC2_REG,
+		.en_mask = BIT(16),
+		.halt_reg = DBG_BUS_VEC_J_REG,
+		.halt_bit = 26,
+	},
+	.parent = &tv_src_clk.c,
+	.c = {
+		.dbg_name = "npl_tv_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(npl_tv_clk.c),
+	},
+};
+
 static struct branch_clk hdmi_app_clk = {
 	.b = {
 		.ctl_reg = MISC_CC2_REG,
@@ -3993,7 +4035,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MND_BANKED8(11, 19, n, m, 0, 27, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(6, 11, n), \
-		.mnd_en_mask = (BIT(10) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_vcodec[] = {
 	F_VCODEC(        0, gnd,  0,  0),
@@ -4087,7 +4128,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 11, 10, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 
 static struct clk_freq_tbl clk_tbl_vfe[] = {
@@ -4133,6 +4173,7 @@
 	.md_reg = VFE_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(11, 10) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_vfe,
@@ -4173,7 +4214,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_aif_osr[] = {
 	F_AIF_OSR(       0, gnd,  1, 0,   0),
@@ -4206,6 +4246,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -4231,6 +4272,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -4310,7 +4352,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
 	F_PCM(       0, gnd,  1, 0,   0),
@@ -4342,6 +4383,7 @@
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
@@ -4367,6 +4409,7 @@
 	.md_reg = LCC_SLIMBUS_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 24) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_aif_osr,
 	.current_freq = &rcg_dummy_freq,
@@ -4632,6 +4675,8 @@
 	{ TEST_MM_HS(0x33), &vcap_clk.c },
 	{ TEST_MM_HS(0x34), &vcap_npl_clk.c },
 	{ TEST_MM_HS(0x35), &vcap_axi_clk.c },
+	{ TEST_MM_HS(0x36), &rgb_tv_clk.c },
+	{ TEST_MM_HS(0x37), &npl_tv_clk.c },
 	{ TEST_MM_HS(0x38), &gfx3d_axi_clk.c },
 
 	{ TEST_LPA(0x0F), &mi2s_bit_clk.c },
@@ -4877,10 +4922,10 @@
 	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c, "msm_serial_hsl.0"),
-	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi1_qup_clk.c,	"qup_i2c.0"),
 	CLK_LOOKUP("core_clk",		gsbi2_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi3_qup_clk.c,	"qup_i2c.3"),
-	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	"qup_i2c.4"),
 	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	"spi_qsd.0"),
 	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	""),
@@ -4911,9 +4956,10 @@
 	CLK_LOOKUP("ce3_core_src_clk",	ce3_src_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("dma_bam_pclk",	dma_bam_p_clk.c,	NULL),
 	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,	"msm_serial_hsl.1"),
+	CLK_LOOKUP("iface_clk",		gsbi1_p_clk.c,	"qup_i2c.0"),
 	CLK_LOOKUP("iface_clk",		gsbi2_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi3_p_clk.c,		"qup_i2c.3"),
-	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi4_p_clk.c,		"qup_i2c.4"),
 	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		"spi_qsd.0"),
 	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,	"msm_serial_hsl.0"),
@@ -4934,38 +4980,38 @@
 	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
 	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
 	CLK_LOOKUP("core_clk",		amp_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam1_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
-	CLK_LOOKUP("cam_clk",		cam0_clk.c,		""),
-	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		""),
-	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		""),
-	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		""),
-	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		""),
-	CLK_LOOKUP("csi_clk",		csi0_clk.c,		""),
-	CLK_LOOKUP("csi_clk",		csi1_clk.c,		""),
-	CLK_LOOKUP("csi_clk",		csi1_clk.c,		""),
-	CLK_LOOKUP("csi_clk",		csi2_clk.c,		""),
-	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		""),
-	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		""),
-	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		""),
-	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		""),
-	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		""),
-	CLK_LOOKUP("csi_pix_clk",	csi_pix1_clk.c,		""),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		""),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi1_clk.c,		""),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi2_clk.c,		""),
-	CLK_LOOKUP("csiphy_timer_src_clk", csiphy_timer_src_clk.c, ""),
-	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	""),
-	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	""),
-	CLK_LOOKUP("csiphy_timer_clk",	csi2phy_timer_clk.c,	""),
+	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-001a"),
+	CLK_LOOKUP("cam_clk",		cam1_clk.c,	"4-006c"),
+	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		"msm_csid.2"),
+	CLK_LOOKUP("csi_clk",		csi0_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_clk",		csi1_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_clk",		csi2_clk.c,		"msm_csid.2"),
+	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		"msm_csid.2"),
+	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_pix1_clk",	csi_pix1_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi1_clk",	csi_rdi1_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi2_clk",	csi_rdi2_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.0"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.2"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	"msm_csiphy.0"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	"msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi2phy_timer_clk.c,	"msm_csiphy.2"),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi1_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi2_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_esc_clk",	dsi1_esc_clk.c,		NULL),
 	CLK_LOOKUP("dsi_esc_clk",	dsi2_esc_clk.c,		NULL),
-	CLK_DUMMY("rgb_tv_clk",		RGB_TV_CLK,		"", OFF),
-	CLK_DUMMY("npl_tv_clk",		NPL_TV_CLK,		"", OFF),
+	CLK_LOOKUP("rgb_clk",		rgb_tv_clk.c,		""),
+	CLK_LOOKUP("npl_clk",		npl_tv_clk.c,		""),
+
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"kgsl-3d0.0"),
 	CLK_LOOKUP("core_clk",		gfx3d_clk.c,	"footswitch-8x60.2"),
 	CLK_LOOKUP("bus_clk",		gfx3d_axi_clk.c, "footswitch-8x60.2"),
@@ -4988,18 +5034,19 @@
 	CLK_LOOKUP("lut_clk",		lut_mdp_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("core_clk",		rot_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("core_clk",		rot_clk.c,	"footswitch-8x60.6"),
-	CLK_DUMMY("tv_src_clk",		TV_SRC_CLK,		NULL, OFF),
+	CLK_LOOKUP("tv_src_clk",	tv_src_clk.c,		""),
+	CLK_LOOKUP("tv_src_div_clk",	tv_src_div_clk.c,	""),
 	CLK_LOOKUP("core_clk",		vcodec_clk.c,		"msm_vidc.0"),
 	CLK_LOOKUP("core_clk",		vcodec_clk.c,	"footswitch-8x60.7"),
-	CLK_DUMMY("mdp_tv_clk",		MDP_TV_CLK,		NULL, OFF),
-	CLK_DUMMY("tv_clk",		MDP_TV_CLK, "footswitch-8x60.4", OFF),
-	CLK_DUMMY("hdmi_clk",		HDMI_TV_CLK,		"", OFF),
+	CLK_LOOKUP("mdp_tv_clk",	mdp_tv_clk.c,		""),
+	CLK_LOOKUP("tv_clk",		mdp_tv_clk.c,	"footswitch-8x60.4"),
+	CLK_LOOKUP("hdmi_clk",		hdmi_tv_clk.c,		""),
 	CLK_LOOKUP("core_clk",		hdmi_app_clk.c,		""),
 	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		""),
 	CLK_LOOKUP("core_clk",		vpe_clk.c,	"footswitch-8x60.9"),
-	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		""),
+	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("core_clk",		vfe_clk.c,	"footswitch-8x60.8"),
-	CLK_LOOKUP("csi_vfe_clk",	csi_vfe_clk.c,		""),
+	CLK_LOOKUP("csi_vfe_clk",	csi_vfe_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("bus_clk",		vfe_axi_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("bus_clk",		mdp_axi_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("bus_clk",		rot_axi_clk.c,	"footswitch-8x60.6"),
@@ -5008,7 +5055,9 @@
 	CLK_LOOKUP("bus_b_clk",        vcodec_axi_b_clk.c, "footswitch-8x60.7"),
 	CLK_LOOKUP("bus_clk",		vpe_axi_clk.c,	"footswitch-8x60.9"),
 	CLK_LOOKUP("amp_pclk",		amp_p_clk.c,		NULL),
-	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		""),
+	CLK_LOOKUP("csi_pclk",          csi_p_clk.c,            "msm_csid.0"),
+	CLK_LOOKUP("csi_pclk",          csi_p_clk.c,            "msm_csid.1"),
+	CLK_LOOKUP("csi_pclk",          csi_p_clk.c,            "msm_csid.2"),
 	CLK_LOOKUP("dsi_m_pclk",	dsi1_m_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_s_pclk",	dsi1_s_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_m_pclk",	dsi2_m_p_clk.c,		NULL),
@@ -5028,24 +5077,32 @@
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"footswitch-8x60.6"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,		"msm_vidc.0"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"footswitch-8x60.7"),
-	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		""),
+	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		""),
 	CLK_LOOKUP("iface_pclk",	vpe_p_clk.c,	"footswitch-8x60.9"),
 
-	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		""),
-	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		""),
-	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c, ""),
-	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c, ""),
-	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c, ""),
-	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c, ""),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c, ""),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c, ""),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c, ""),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c, ""),
-	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		""),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		"msm-dai-q6.2"),
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	""),
-	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
 	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	""),
 	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		""),
 	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		""),
@@ -5220,10 +5277,13 @@
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"4-0020"),
 	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		"msm_csid.2"),
 	CLK_LOOKUP("csi_clk",		csi0_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_clk",		csi1_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_clk",		csi2_clk.c,		"msm_csid.2"),
 	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		"msm_csid.2"),
 	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		"msm_ispif.0"),
 	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		"msm_ispif.0"),
 	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		NULL),
@@ -5237,8 +5297,11 @@
 			   csiphy_timer_src_clk.c, "msm_csiphy.0"),
 	CLK_LOOKUP("csiphy_timer_src_clk",
 			   csiphy_timer_src_clk.c, "msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.2"),
 	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	"msm_csiphy.0"),
 	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	"msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi2phy_timer_clk.c,	"msm_csiphy.2"),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi1_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi2_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_esc_clk",	dsi1_esc_clk.c,		NULL),
@@ -5287,6 +5350,7 @@
 	CLK_LOOKUP("amp_pclk",		amp_p_clk.c,		NULL),
 	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		"msm_csid.0"),
 	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		"msm_csid.2"),
 	CLK_LOOKUP("dsi_m_pclk",	dsi1_m_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_s_pclk",	dsi1_s_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_m_pclk",	dsi2_m_p_clk.c,		NULL),
@@ -5315,19 +5379,27 @@
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
-	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		NULL),
-	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
-	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		NULL),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("pcm_clk",		pcm_clk.c,		"msm-dai-q6.2"),
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
-	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
 	CLK_LOOKUP("core_clk",		jpegd_axi_clk.c,	"msm_iommu.0"),
 	CLK_LOOKUP("core_clk",		vpe_axi_clk.c,		"msm_iommu.1"),
 	CLK_LOOKUP("core_clk",		mdp_axi_clk.c,		"msm_iommu.2"),
@@ -5599,10 +5671,6 @@
 /* Local clock driver initialization. */
 static void __init msm8960_clock_init(void)
 {
-	/* Copy gfx2d's frequency table because it's modified by both clocks */
-	gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
-			sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
-			GFP_KERNEL);
 
 	if (cpu_is_msm8960()) {
 		rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
@@ -5672,6 +5740,7 @@
 	clk_set_rate(&usb_hsic_xcvr_fs_clk.c, 60000000);
 	clk_set_rate(&usb_hsic_hsic_src_clk.c, 480000000);
 	clk_set_rate(&usb_hsic_hsio_cal_clk.c, 9000000);
+	clk_set_rate(&usb_hsic_system_clk.c, 60000000);
 	/*
 	 * Set the CSI rates to a safe default to avoid warnings when
 	 * switching csi pix and rdi clocks.
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index e53d441..d3f5396 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -318,14 +318,13 @@
 static struct clk_ops clk_ops_pxo = {
 	.enable = pxo_clk_enable,
 	.disable = pxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = xo_clk_is_local,
 };
 
 static struct fixed_clk pxo_clk = {
-	.rate = 27000000,
 	.c = {
 		.dbg_name = "pxo_clk",
+		.rate = 27000000,
 		.ops = &clk_ops_pxo,
 		CLK_INIT(pxo_clk.c),
 	},
@@ -344,49 +343,48 @@
 static struct clk_ops clk_ops_cxo = {
 	.enable = cxo_clk_enable,
 	.disable = cxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = xo_clk_is_local,
 };
 
 static struct fixed_clk cxo_clk = {
-	.rate = 19200000,
 	.c = {
 		.dbg_name = "cxo_clk",
+		.rate = 19200000,
 		.ops = &clk_ops_cxo,
 		CLK_INIT(cxo_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll8_clk = {
-	.rate = 384000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(8),
 	.status_reg = BB_PLL8_STATUS_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll8_clk",
+		.rate = 384000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll8_clk.c),
 	},
 };
 
 static struct pll_clk pll2_clk = {
-	.rate = 800000000,
 	.mode_reg = MM_PLL1_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll2_clk",
+		.rate = 800000000,
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll2_clk.c),
 	},
 };
 
 static struct pll_clk pll3_clk = {
-	.rate = 0, /* TODO: Detect rate dynamically */
 	.mode_reg = MM_PLL2_MODE_REG,
 	.parent = &pxo_clk.c,
 	.c = {
 		.dbg_name = "pll3_clk",
+		.rate = 0, /* TODO: Detect rate dynamically */
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll3_clk.c),
 	},
@@ -417,15 +415,14 @@
 static struct clk_ops clk_ops_pll4 = {
 	.enable = pll4_clk_enable,
 	.disable = pll4_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.get_parent = pll4_clk_get_parent,
 	.is_local = pll4_clk_is_local,
 };
 
 static struct fixed_clk pll4_clk = {
-	.rate = 540672000,
 	.c = {
 		.dbg_name = "pll4_clk",
+		.rate = 540672000,
 		.ops = &clk_ops_pll4,
 		CLK_INIT(pll4_clk.c),
 	},
@@ -1014,6 +1011,7 @@
 		.md_reg = GPn_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gp, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1030,7 +1028,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gp[] = {
 	F_GP(        0, gnd,  1, 0, 0),
@@ -1059,6 +1056,7 @@
 		.md_reg = GSBIn_UART_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(31, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_uart, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1075,7 +1073,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
 	F_GSBI_UART(       0, gnd,  1,  0,   0),
@@ -1123,6 +1120,7 @@
 		.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_qup, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1139,7 +1137,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
 	F_GSBI_QUP(       0, gnd,  1, 0,  0),
@@ -1260,6 +1257,7 @@
 		.md_reg = SDCn_APPS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_sdc, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1276,7 +1274,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_sdc[] = {
 	F_SDC(       0, gnd,   1, 0,   0),
@@ -1302,7 +1299,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_tsif_ref[] = {
 	F_TSIF_REF(     0, gnd,  1, 0,   0),
@@ -1321,6 +1317,7 @@
 	.md_reg = TSIF_REF_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_tsif_ref,
 	.current_freq = &rcg_dummy_freq,
@@ -1369,7 +1366,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_usb[] = {
 	F_USB(       0, gnd,  1, 0,  0),
@@ -1390,6 +1386,7 @@
 	.md_reg = USB_HS1_XCVR_FS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -1423,6 +1420,7 @@
 		.md_reg = USB_FSn_XCVR_FS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_usb, \
 		.current_freq = &rcg_dummy_freq, \
@@ -2033,7 +2031,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_cam[] = {
 	F_CAM(        0, gnd,  1, 0,  0),
@@ -2061,6 +2058,7 @@
 	.md_reg = CAMCLK_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(31, 24) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd_8,
 	.freq_tbl = clk_tbl_cam,
@@ -2199,7 +2197,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(20, 16, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gfx2d[] = {
 	F_GFX2D(        0, gnd,  0,  0),
@@ -2313,7 +2310,6 @@
 		.md_val = MD4(4, m, 0, n), \
 		.ns_val = NS_MND_BANKED4(18, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gfx3d[] = {
 	F_GFX3D(        0, gnd,  0,  0),
@@ -2386,7 +2382,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 12, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!n, \
 	}
 static struct clk_freq_tbl clk_tbl_ijpeg[] = {
 	F_IJPEG(        0, gnd,  1, 0,  0),
@@ -2417,6 +2412,7 @@
 	.md_reg = IJPEG_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(15, 12) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_ijpeg,
@@ -2479,7 +2475,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MND_BANKED8(22, 14, n, m, 3, 0, s##_to_mm_mux), \
 		.ctl_val = CC_BANKED(9, 6, n), \
-		.mnd_en_mask = (BIT(8) | BIT(5)) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_mdp[] = {
 	F_MDP(        0, gnd,  0,  0),
@@ -2585,7 +2580,6 @@
 		.md_val = MD16(m, n), \
 		.ns_val = NS_MM(31, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_pixel_mdp[] = {
 	F_PIXEL_MDP(        0, gnd,  1,   0,    0),
@@ -2618,6 +2612,7 @@
 	},
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(31, 16) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pixel_mdp,
@@ -2713,7 +2708,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 		.extra_freq_data = p_r, \
 	}
 /* Switching TV freqs requires PLL reconfiguration. */
@@ -2745,6 +2739,7 @@
 	.md_reg = TV_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(15, 14) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_tv,
 	.freq_tbl = clk_tbl_tv,
@@ -2846,7 +2841,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(18, 11, n, m, 0, 0, 1, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_vcodec[] = {
 	F_VCODEC(        0, gnd,  0,  0),
@@ -2876,6 +2870,7 @@
 	.md_reg = VCODEC_MD0_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(18, 11) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_vcodec,
@@ -2944,7 +2939,6 @@
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS_MM(23, 16, n, m, 11, 10, d, 2, 0, s##_to_mm_mux), \
 		.ctl_val = CC(6, n), \
-		.mnd_en_mask = BIT(5) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_vfe[] = {
 	F_VFE(        0, gnd,   1, 0,  0),
@@ -2982,6 +2976,7 @@
 	.md_reg = VFE_MD_REG,
 	.root_en_mask = BIT(2),
 	.ns_mask = (BM(23, 16) | BM(11, 10) | BM(2, 0)),
+	.mnd_en_mask = BIT(5),
 	.ctl_mask = BM(7, 6),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_vfe,
@@ -3039,7 +3034,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_aif_osr[] = {
 	F_AIF_OSR(       0, gnd,  1, 0,   0),
@@ -3071,6 +3065,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -3131,7 +3126,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
 	F_PCM(       0, gnd,  1, 0,   0),
@@ -3163,6 +3157,7 @@
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
@@ -3900,11 +3895,6 @@
 	}
 
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-	/* Copy gfx2d's frequency table because it's modified by both clocks */
-	gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
-			sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
-			GFP_KERNEL);
-
 	/* Initialize clock registers. */
 	reg_init();
 
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 0bdacec..df9c152 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -223,14 +223,13 @@
 static struct clk_ops clk_ops_cxo = {
 	.enable = cxo_clk_enable,
 	.disable = cxo_clk_disable,
-	.get_rate = fixed_clk_get_rate,
 	.is_local = local_clk_is_local,
 };
 
 static struct fixed_clk cxo_clk = {
-	.rate = 19200000,
 	.c = {
 		.dbg_name = "cxo_clk",
+		.rate = 19200000,
 		.ops = &clk_ops_cxo,
 		CLK_INIT(cxo_clk.c),
 	},
@@ -274,7 +273,6 @@
 	.disable = pll_acpu_vote_clk_disable,
 	.auto_off = pll_acpu_vote_clk_disable,
 	.is_enabled = pll_vote_clk_is_enabled,
-	.get_rate = pll_vote_clk_get_rate,
 	.get_parent = pll_vote_clk_get_parent,
 	.is_local = local_clk_is_local,
 };
@@ -285,7 +283,6 @@
 static unsigned int soft_vote_pll0;
 
 static struct pll_vote_clk pll0_clk = {
-	.rate = 276000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(0),
 	.status_reg = BB_PLL0_STATUS_REG,
@@ -294,13 +291,13 @@
 	.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
 	.c = {
 		.dbg_name = "pll0_clk",
+		.rate = 276000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll0_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll0_acpu_clk = {
-	.rate = 276000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(0),
 	.status_reg = BB_PLL0_STATUS_REG,
@@ -308,19 +305,20 @@
 	.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
 	.c = {
 		.dbg_name = "pll0_acpu_clk",
+		.rate = 276000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll0_acpu_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll4_clk = {
-	.rate = 393216000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(4),
 	.status_reg = LCC_PLL0_STATUS_REG,
 	.parent = &cxo_clk.c,
 	.c = {
 		.dbg_name = "pll4_clk",
+		.rate = 393216000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll4_clk.c),
 	},
@@ -329,7 +327,6 @@
 static unsigned int soft_vote_pll8;
 
 static struct pll_vote_clk pll8_clk = {
-	.rate = 384000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(8),
 	.status_reg = BB_PLL8_STATUS_REG,
@@ -338,13 +335,13 @@
 	.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
 	.c = {
 		.dbg_name = "pll8_clk",
+		.rate = 384000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll8_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll8_acpu_clk = {
-	.rate = 384000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(8),
 	.status_reg = BB_PLL8_STATUS_REG,
@@ -352,29 +349,30 @@
 	.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
 	.c = {
 		.dbg_name = "pll8_acpu_clk",
+		.rate = 384000000,
 		.ops = &clk_ops_pll_acpu_vote,
 		CLK_INIT(pll8_acpu_clk.c),
 	},
 };
 
 static struct pll_clk pll9_acpu_clk = {
-	.rate = 440000000,
 	.mode_reg = SC_PLL0_MODE_REG,
 	.c = {
 		.dbg_name = "pll9_acpu_clk",
+		.rate = 440000000,
 		.ops = &clk_ops_pll,
 		CLK_INIT(pll9_acpu_clk.c),
 	},
 };
 
 static struct pll_vote_clk pll14_clk = {
-	.rate = 480000000,
 	.en_reg = BB_PLL_ENA_SC0_REG,
 	.en_mask = BIT(11),
 	.status_reg = BB_PLL14_STATUS_REG,
 	.parent = &cxo_clk.c,
 	.c = {
 		.dbg_name = "pll14_clk",
+		.rate = 480000000,
 		.ops = &clk_ops_pll_vote,
 		CLK_INIT(pll14_clk.c),
 	},
@@ -428,6 +426,7 @@
 		.md_reg = GPn_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gp, \
 		.current_freq = &rcg_dummy_freq, \
@@ -444,7 +443,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gp[] = {
 	F_GP(        0, gnd,  1, 0, 0),
@@ -471,6 +469,7 @@
 		.md_reg = GSBIn_UART_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(31, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_uart, \
 		.current_freq = &rcg_dummy_freq, \
@@ -487,7 +486,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
 	F_GSBI_UART(       0, gnd,  1,  0,   0),
@@ -527,6 +525,7 @@
 		.md_reg = GSBIn_QUP_APPS_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_gsbi_qup, \
 		.current_freq = &rcg_dummy_freq, \
@@ -543,7 +542,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
 	F_GSBI_QUP(       0, gnd,  1, 0,  0),
@@ -658,6 +656,7 @@
 		.md_reg = SDCn_APPS_CLK_MD_REG(n), \
 		.root_en_mask = BIT(11), \
 		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = f_table, \
 		.current_freq = &rcg_dummy_freq, \
@@ -674,7 +673,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_sdc1_2[] = {
 	F_SDC(        0, gnd,   1, 0,   0),
@@ -697,7 +695,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(16, m, 0, n), \
 		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_usb[] = {
 	F_USB(       0, gnd,  1, 0,  0),
@@ -724,6 +721,7 @@
 	.md_reg = USB_HS1_XCVR_FS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -748,6 +746,7 @@
 	.md_reg = USB_HS1_SYS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -772,6 +771,7 @@
 	.md_reg = USB_HSIC_XCVR_FS_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb,
 	.current_freq = &rcg_dummy_freq,
@@ -796,6 +796,7 @@
 	.md_reg = USB_HSIC_SYSTEM_CLK_MD_REG,
 	.root_en_mask = BIT(11),
 	.ns_mask = (BM(23, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_usb_hsic_sys,
 	.current_freq = &rcg_dummy_freq,
@@ -1129,7 +1130,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD8(8, m, 0, n), \
 		.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_aif_osr[] = {
 	F_AIF_OSR(       0, gnd,  1, 0,   0),
@@ -1162,6 +1162,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1186,6 +1187,7 @@
 		.md_reg = md, \
 		.root_en_mask = BIT(9), \
 		.ns_mask = (BM(31, 24) | BM(6, 0)), \
+		.mnd_en_mask = BIT(8), \
 		.set_rate = set_rate_mnd, \
 		.freq_tbl = clk_tbl_aif_osr, \
 		.current_freq = &rcg_dummy_freq, \
@@ -1264,7 +1266,6 @@
 		.src_clk = &s##_clk.c, \
 		.md_val = MD16(m, n), \
 		.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
-		.mnd_en_mask = BIT(8) * !!(n), \
 	}
 static struct clk_freq_tbl clk_tbl_pcm[] = {
 	F_PCM(       0, gnd,  1, 0,   0),
@@ -1296,6 +1297,7 @@
 	.md_reg = LCC_PCM_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 16) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_pcm,
 	.current_freq = &rcg_dummy_freq,
@@ -1321,6 +1323,7 @@
 	.md_reg = LCC_SLIMBUS_MD_REG,
 	.root_en_mask = BIT(9),
 	.ns_mask = (BM(31, 24) | BM(6, 0)),
+	.mnd_en_mask = BIT(8),
 	.set_rate = set_rate_mnd,
 	.freq_tbl = clk_tbl_aif_osr,
 	.current_freq = &rcg_dummy_freq,
@@ -1689,21 +1692,29 @@
 	CLK_LOOKUP("iface_clk",		pmic_arb1_p_clk.c,	""),
 	CLK_LOOKUP("core_clk",		pmic_ssbi2_clk.c,	""),
 	CLK_LOOKUP("mem_clk",		rpm_msg_ram_p_clk.c,	""),
-	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		NULL),
-	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
+	CLK_LOOKUP("bit_clk",		mi2s_bit_clk.c,		"msm-dai-q6.6"),
+	CLK_LOOKUP("osr_clk",		mi2s_osr_clk.c,		"msm-dai-q6.6"),
 
-	CLK_LOOKUP("i2s_mic_bit_clk",	codec_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	codec_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_bit_clk",	spare_i2s_mic_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_mic_osr_clk",	spare_i2s_mic_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	codec_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	codec_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_bit_clk",	spare_i2s_spkr_bit_clk.c,	NULL),
-	CLK_LOOKUP("i2s_spkr_osr_clk",	spare_i2s_spkr_osr_clk.c,	NULL),
-	CLK_LOOKUP("pcm_clk",		pcm_clk.c,			NULL),
+	CLK_LOOKUP("bit_clk",		codec_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.1"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_mic_bit_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_mic_osr_clk.c,
+			   "msm-dai-q6.5"),
+	CLK_LOOKUP("bit_clk",		codec_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("osr_clk",		codec_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.16384"),
+	CLK_LOOKUP("bit_clk",		spare_i2s_spkr_bit_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("osr_clk",		spare_i2s_spkr_osr_clk.c,
+			   "msm-dai-q6.4"),
+	CLK_LOOKUP("pcm_clk",		pcm_clk.c,	"msm-dai-q6.2"),
 
 	CLK_LOOKUP("sps_slimbus_clk",	sps_slimbus_clk.c,	NULL),
-	CLK_LOOKUP("audio_slimbus_clk",	audio_slimbus_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		audio_slimbus_clk.c, "msm_slim_ctrl.1"),
 	CLK_LOOKUP("core_clk",		dfab_usb_hs_clk.c,	"msm_otg"),
 	CLK_LOOKUP("bus_clk",		dfab_sdc1_clk.c,	"msm_sdcc.1"),
 	CLK_LOOKUP("bus_clk",		dfab_sdc2_clk.c,	"msm_sdcc.2"),
@@ -1821,7 +1832,7 @@
 	pll9_lval = readl_relaxed(SC_PLL0_L_VAL_REG);
 
 	if (pll9_lval == 0x1C)
-		pll9_acpu_clk.rate = 550000000;
+		pll9_acpu_clk.c.rate = 550000000;
 
 	/* Enable PLL4 source on the LPASS Primary PLL Mux */
 	regval = readl_relaxed(LCC_PRI_PLL_CLK_CTL_REG);
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index c02c6f3..4f68fb4 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -192,13 +192,8 @@
 		writel_relaxed(ns_reg_val, clk->ns_reg);
 	}
 
-	/*
-	 * If this freq requires the MN counter to be enabled,
-	 * update the enable mask to match the current bank.
-	 */
-	if (nf->mnd_en_mask)
-		nf->mnd_en_mask = new_bank_masks->mnd_en_mask;
-	/* Update the NS mask to match the current bank. */
+	/* Update the MND_EN and NS masks to match the current bank. */
+	clk->mnd_en_mask = new_bank_masks->mnd_en_mask;
 	clk->ns_mask = new_bank_masks->ns_mask;
 }
 
@@ -343,8 +338,8 @@
 
 	/* Enable MN counter, if applicable. */
 	reg_val = readl_relaxed(reg);
-	if (clk->current_freq->mnd_en_mask) {
-		reg_val |= clk->current_freq->mnd_en_mask;
+	if (clk->current_freq->md_val) {
+		reg_val |= clk->mnd_en_mask;
 		writel_relaxed(reg_val, reg);
 	}
 	/* Enable root. */
@@ -408,8 +403,8 @@
 		writel_relaxed(reg_val, reg);
 	}
 	/* Disable MN counter, if applicable. */
-	if (clk->current_freq->mnd_en_mask) {
-		reg_val &= ~(clk->current_freq->mnd_en_mask);
+	if (clk->current_freq->md_val) {
+		reg_val &= ~(clk->mnd_en_mask);
 		writel_relaxed(reg_val, reg);
 	}
 	/*
@@ -641,7 +636,7 @@
 	ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
 	for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
 		if ((freq->ns_val & ns_mask) == ns_val &&
-		    (!freq->mnd_en_mask || freq->md_val == md_val)) {
+		    (!freq->md_val || freq->md_val == md_val)) {
 			pr_info("%s rate=%d\n", clk->c.dbg_name, freq->freq_hz);
 			break;
 		}
@@ -686,12 +681,6 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-unsigned long pll_vote_clk_get_rate(struct clk *clk)
-{
-	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
-	return pll->rate;
-}
-
 struct clk *pll_vote_clk_get_parent(struct clk *clk)
 {
 	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
@@ -709,7 +698,6 @@
 	.disable = pll_vote_clk_disable,
 	.auto_off = pll_vote_clk_disable,
 	.is_enabled = pll_vote_clk_is_enabled,
-	.get_rate = pll_vote_clk_get_rate,
 	.get_parent = pll_vote_clk_get_parent,
 	.is_local = local_clk_is_local,
 };
@@ -766,12 +754,6 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-static unsigned long pll_clk_get_rate(struct clk *clk)
-{
-	struct pll_clk *pll = to_pll_clk(clk);
-	return pll->rate;
-}
-
 static struct clk *pll_clk_get_parent(struct clk *clk)
 {
 	struct pll_clk *pll = to_pll_clk(clk);
@@ -817,13 +799,11 @@
 	.enable = pll_clk_enable,
 	.disable = pll_clk_disable,
 	.auto_off = pll_clk_disable,
-	.get_rate = pll_clk_get_rate,
 	.get_parent = pll_clk_get_parent,
 	.is_local = local_clk_is_local,
 };
 
 struct clk_ops clk_ops_gnd = {
-	.get_rate = fixed_clk_get_rate,
 	.is_local = local_clk_is_local,
 };
 
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index d312f24..c587b43 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -27,10 +27,12 @@
 
 /* MD Registers */
 #define MD4(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
+		((BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n))) \
+		* !!(n))
 #define MD8(m_lsb, m, n_lsb, n) \
-		(BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
-#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
+		((BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n))) \
+		* !!(n))
+#define MD16(m, n) ((BVAL(31, 16, m) | BVAL(15, 0, ~(n))) * !!(n))
 
 /* NS Registers */
 #define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
@@ -101,11 +103,10 @@
  */
 struct clk_freq_tbl {
 	const uint32_t	freq_hz;
-	struct clk	*src_clk;
+	struct clk	*const src_clk;
 	const uint32_t	md_val;
 	const uint32_t	ns_val;
 	const uint32_t	ctl_val;
-	uint32_t	mnd_en_mask;
 	void		*const extra_freq_data;
 };
 
@@ -126,13 +127,12 @@
 	const struct bank_mask_info	bank1_mask;
 };
 
-#define F_RAW(f, sc, m_v, n_v, c_v, m_m, e) { \
+#define F_RAW(f, sc, m_v, n_v, c_v, e) { \
 	.freq_hz = f, \
 	.src_clk = sc, \
 	.md_val = m_v, \
 	.ns_val = n_v, \
 	.ctl_val = c_v, \
-	.mnd_en_mask = m_m, \
 	.extra_freq_data = e, \
 	}
 #define FREQ_END	(UINT_MAX-1)
@@ -185,6 +185,7 @@
 	const uint32_t	root_en_mask;
 	uint32_t	ns_mask;
 	const uint32_t	ctl_mask;
+	uint32_t	mnd_en_mask;
 
 	void		*bank_info;
 	void   (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
@@ -249,29 +250,14 @@
 
 /**
  * struct fixed_clk - fixed rate clock (used for crystal oscillators)
- * @rate: output rate
  * @c: clk
  */
 struct fixed_clk {
-	unsigned long rate;
 	struct clk c;
 };
 
-static inline struct fixed_clk *to_fixed_clk(struct clk *clk)
-{
-	return container_of(clk, struct fixed_clk, c);
-}
-
-static inline unsigned long fixed_clk_get_rate(struct clk *clk)
-{
-	struct fixed_clk *f = to_fixed_clk(clk);
-	return f->rate;
-}
-
-
 /**
  * struct pll_vote_clk - phase locked loop (HW voteable)
- * @rate: output rate
  * @soft_vote: soft voting variable for multiple PLL software instances
  * @soft_vote_mask: soft voting mask for multiple PLL software instances
  * @en_reg: enable register
@@ -281,8 +267,6 @@
  * @c: clk
  */
 struct pll_vote_clk {
-	unsigned long rate;
-
 	u32 *soft_vote;
 	const u32 soft_vote_mask;
 	void __iomem *const en_reg;
@@ -303,14 +287,11 @@
 
 /**
  * struct pll_clk - phase locked loop
- * @rate: output rate
  * @mode_reg: enable register
  * @parent: clock source
  * @c: clk
  */
 struct pll_clk {
-	unsigned long rate;
-
 	void __iomem *const mode_reg;
 
 	struct clk *parent;
@@ -394,7 +375,6 @@
  */
 int pll_vote_clk_enable(struct clk *clk);
 void pll_vote_clk_disable(struct clk *clk);
-unsigned long pll_vote_clk_get_rate(struct clk *clk);
 struct clk *pll_vote_clk_get_parent(struct clk *clk);
 int pll_vote_clk_is_enabled(struct clk *clk);
 
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 4757f7d..fc2e83f 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -23,9 +23,9 @@
 static int rpm_clk_enable(struct clk *clk)
 {
 	unsigned long flags;
-	struct msm_rpm_iv_pair iv;
-	int rc = 0;
 	struct rpm_clk *r = to_rpm_clk(clk);
+	struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
+	int rc = 0;
 	unsigned long this_khz, this_sleep_khz;
 	unsigned long peer_khz = 0, peer_sleep_khz = 0;
 	struct rpm_clk *peer = r->peer;
@@ -39,8 +39,6 @@
 
 	this_sleep_khz = r->last_set_sleep_khz;
 
-	iv.id = r->rpm_clk_id;
-
 	/* Take peer clock's rate into account only if it's enabled. */
 	if (peer->enabled) {
 		peer_khz = peer->last_set_khz;
@@ -48,11 +46,16 @@
 	}
 
 	iv.value = max(this_khz, peer_khz);
+	if (r->branch)
+		iv.value = !!iv.value;
+
 	rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
 	if (rc)
 		goto out;
 
 	iv.value = max(this_sleep_khz, peer_sleep_khz);
+	if (r->branch)
+		iv.value = !!iv.value;
 	rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
 	if (rc) {
 		iv.value = peer_khz;
@@ -76,25 +79,23 @@
 	spin_lock_irqsave(&rpm_clock_lock, flags);
 
 	if (r->last_set_khz) {
-		struct msm_rpm_iv_pair iv;
+		struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
 		struct rpm_clk *peer = r->peer;
 		unsigned long peer_khz = 0, peer_sleep_khz = 0;
 		int rc;
 
-		iv.id = r->rpm_clk_id;
-
 		/* Take peer clock's rate into account only if it's enabled. */
 		if (peer->enabled) {
 			peer_khz = peer->last_set_khz;
 			peer_sleep_khz = peer->last_set_sleep_khz;
 		}
 
-		iv.value = peer_khz;
+		iv.value = r->branch ? !!peer_khz : peer_khz;
 		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
 		if (rc)
 			goto out;
 
-		iv.value = peer_sleep_khz;
+		iv.value = r->branch ? !!peer_sleep_khz : peer_sleep_khz;
 		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
 	}
 	r->enabled = false;
@@ -186,6 +187,12 @@
 	return false;
 }
 
+static unsigned long rpm_branch_clk_get_rate(struct clk *clk)
+{
+	struct rpm_clk *r = to_rpm_clk(clk);
+	return r->last_set_khz * 1000;
+}
+
 struct clk_ops clk_ops_rpm = {
 	.enable = rpm_clk_enable,
 	.disable = rpm_clk_disable,
@@ -195,3 +202,10 @@
 	.round_rate = rpm_clk_round_rate,
 	.is_local = rpm_clk_is_local,
 };
+
+struct clk_ops clk_ops_rpm_branch = {
+	.enable = rpm_clk_enable,
+	.disable = rpm_clk_disable,
+	.is_local = rpm_clk_is_local,
+	.get_rate = rpm_branch_clk_get_rate,
+};
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index 24df9b6..27afd6f 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
 
 struct clk_ops;
 extern struct clk_ops clk_ops_rpm;
+extern struct clk_ops clk_ops_rpm_branch;
 
 struct rpm_clk {
 	const int rpm_clk_id;
@@ -27,6 +28,7 @@
 	/* 0 if active_only. Otherwise, same as last_set_khz. */
 	unsigned last_set_sleep_khz;
 	bool enabled;
+	bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
 
 	struct rpm_clk *peer;
 	struct clk c;
@@ -65,4 +67,35 @@
 		}, \
 	};
 
+#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, rate) \
+	static struct rpm_clk active; \
+	static struct rpm_clk name = { \
+		.rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
+		.rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+		.peer = &active, \
+		.last_set_khz = ((rate) / 1000), \
+		.last_set_sleep_khz = ((rate) / 1000), \
+		.branch = true, \
+		.c = { \
+			.ops = &clk_ops_rpm_branch, \
+			.flags = CLKFLAG_SKIP_AUTO_OFF, \
+			.dbg_name = #name, \
+			CLK_INIT(name.c), \
+		}, \
+	}; \
+	static struct rpm_clk active = { \
+		.rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
+		.rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+		.peer = &name, \
+		.last_set_khz = ((rate) / 1000), \
+		.active_only = true, \
+		.branch = true, \
+		.c = { \
+			.ops = &clk_ops_rpm_branch, \
+			.flags = CLKFLAG_SKIP_AUTO_OFF, \
+			.dbg_name = #active, \
+			CLK_INIT(active.c), \
+		}, \
+	};
+
 #endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 57fd749..5b89fa9 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/clock.c
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -222,7 +222,7 @@
 unsigned long clk_get_rate(struct clk *clk)
 {
 	if (!clk->ops->get_rate)
-		return 0;
+		return clk->rate;
 
 	return clk->ops->get_rate(clk);
 }
diff --git a/arch/arm/mach-msm/cp14.h b/arch/arm/mach-msm/cp14.h
index 9f7241e..d640412 100644
--- a/arch/arm/mach-msm/cp14.h
+++ b/arch/arm/mach-msm/cp14.h
@@ -325,21 +325,21 @@
 #define RCP14_ETMACTR14()		MRC14(1, c0, c14, 2)
 #define RCP14_ETMACTR15()		MRC14(1, c0, c15, 2)
 #define RCP14_ETMDCVR0()		MRC14(1, c0, c0, 3)
-#define RCP14_ETMDCVR1()		MRC14(1, c0, c1, 3)
 #define RCP14_ETMDCVR2()		MRC14(1, c0, c2, 3)
-#define RCP14_ETMDCVR3()		MRC14(1, c0, c3, 3)
 #define RCP14_ETMDCVR4()		MRC14(1, c0, c4, 3)
-#define RCP14_ETMDCVR5()		MRC14(1, c0, c5, 3)
 #define RCP14_ETMDCVR6()		MRC14(1, c0, c6, 3)
-#define RCP14_ETMDCVR7()		MRC14(1, c0, c7, 3)
+#define RCP14_ETMDCVR8()		MRC14(1, c0, c8, 3)
+#define RCP14_ETMDCVR10()		MRC14(1, c0, c10, 3)
+#define RCP14_ETMDCVR12()		MRC14(1, c0, c12, 3)
+#define RCP14_ETMDCVR14()		MRC14(1, c0, c14, 3)
 #define RCP14_ETMDCMR0()		MRC14(1, c0, c0, 4)
-#define RCP14_ETMDCMR1()		MRC14(1, c0, c1, 4)
 #define RCP14_ETMDCMR2()		MRC14(1, c0, c2, 4)
-#define RCP14_ETMDCMR3()		MRC14(1, c0, c3, 4)
 #define RCP14_ETMDCMR4()		MRC14(1, c0, c4, 4)
-#define RCP14_ETMDCMR5()		MRC14(1, c0, c5, 4)
 #define RCP14_ETMDCMR6()		MRC14(1, c0, c6, 4)
-#define RCP14_ETMDCMR7()		MRC14(1, c0, c7, 4)
+#define RCP14_ETMDCMR8()		MRC14(1, c0, c8, 4)
+#define RCP14_ETMDCMR10()		MRC14(1, c0, c10, 4)
+#define RCP14_ETMDCMR12()		MRC14(1, c0, c12, 4)
+#define RCP14_ETMDCMR14()		MRC14(1, c0, c14, 4)
 #define RCP14_ETMCNTRLDVR0()		MRC14(1, c0, c0, 5)
 #define RCP14_ETMCNTRLDVR1()		MRC14(1, c0, c1, 5)
 #define RCP14_ETMCNTRLDVR2()		MRC14(1, c0, c2, 5)
@@ -389,7 +389,7 @@
 #define RCP14_ETMAUXCR()		MRC14(1, c0, c15, 7)
 #define RCP14_ETMTRACEIDR()		MRC14(1, c1, c0, 0)
 #define RCP14_ETMIDR2()			MRC14(1, c1, c2, 0)
-#define RCP14_ETMVMIDCVR()		MRC14(1, c1, c1, 0)
+#define RCP14_ETMVMIDCVR()		MRC14(1, c1, c0, 1)
 #define RCP14_ETMOSLSR()		MRC14(1, c1, c1, 4)
 /* not available in PFTv1.1 */
 #define RCP14_ETMOSSRR()		MRC14(1, c1, c2, 4)
@@ -462,21 +462,21 @@
 #define WCP14_ETMACTR14(val)		MCR14(val, 1, c0, c14, 2)
 #define WCP14_ETMACTR15(val)		MCR14(val, 1, c0, c15, 2)
 #define WCP14_ETMDCVR0(val)		MCR14(val, 1, c0, c0, 3)
-#define WCP14_ETMDCVR1(val)		MCR14(val, 1, c0, c1, 3)
 #define WCP14_ETMDCVR2(val)		MCR14(val, 1, c0, c2, 3)
-#define WCP14_ETMDCVR3(val)		MCR14(val, 1, c0, c3, 3)
 #define WCP14_ETMDCVR4(val)		MCR14(val, 1, c0, c4, 3)
-#define WCP14_ETMDCVR5(val)		MCR14(val, 1, c0, c5, 3)
 #define WCP14_ETMDCVR6(val)		MCR14(val, 1, c0, c6, 3)
-#define WCP14_ETMDCVR7(val)		MCR14(val, 1, c0, c7, 3)
+#define WCP14_ETMDCVR8(val)		MCR14(val, 1, c0, c8, 3)
+#define WCP14_ETMDCVR10(val)		MCR14(val, 1, c0, c10, 3)
+#define WCP14_ETMDCVR12(val)		MCR14(val, 1, c0, c12, 3)
+#define WCP14_ETMDCVR14(val)		MCR14(val, 1, c0, c14, 3)
 #define WCP14_ETMDCMR0(val)		MCR14(val, 1, c0, c0, 4)
-#define WCP14_ETMDCMR1(val)		MCR14(val, 1, c0, c1, 4)
 #define WCP14_ETMDCMR2(val)		MCR14(val, 1, c0, c2, 4)
-#define WCP14_ETMDCMR3(val)		MCR14(val, 1, c0, c3, 4)
 #define WCP14_ETMDCMR4(val)		MCR14(val, 1, c0, c4, 4)
-#define WCP14_ETMDCMR5(val)		MCR14(val, 1, c0, c5, 4)
 #define WCP14_ETMDCMR6(val)		MCR14(val, 1, c0, c6, 4)
-#define WCP14_ETMDCMR7(val)		MCR14(val, 1, c0, c7, 4)
+#define WCP14_ETMDCMR8(val)		MCR14(val, 1, c0, c8, 4)
+#define WCP14_ETMDCMR10(val)		MCR14(val, 1, c0, c10, 4)
+#define WCP14_ETMDCMR12(val)		MCR14(val, 1, c0, c12, 4)
+#define WCP14_ETMDCMR14(val)		MCR14(val, 1, c0, c14, 4)
 #define WCP14_ETMCNTRLDVR0(val)		MCR14(val, 1, c0, c0, 5)
 #define WCP14_ETMCNTRLDVR1(val)		MCR14(val, 1, c0, c1, 5)
 #define WCP14_ETMCNTRLDVR2(val)		MCR14(val, 1, c0, c2, 5)
@@ -525,7 +525,7 @@
 #define WCP14_ETMAUXCR(val)		MCR14(val, 1, c0, c15, 7)
 #define WCP14_ETMTRACEIDR(val)		MCR14(val, 1, c1, c0, 0)
 #define WCP14_ETMIDR2(val)		MCR14(val, 1, c1, c2, 0)
-#define WCP14_ETMVMIDCVR(val)		MCR14(val, 1, c1, c1, 0)
+#define WCP14_ETMVMIDCVR(val)		MCR14(val, 1, c1, c0, 1)
 #define WCP14_ETMOSLAR(val)		MCR14(val, 1, c1, c0, 4)
 /* not available in PFTv1.1 */
 #define WCP14_ETMOSSRR(val)		MCR14(val, 1, c1, c2, 4)
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 9328143..6b79fab 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -50,6 +50,7 @@
 #define MSM_UART7DM_PHYS	(MSM_GSBI7_PHYS + 0x40000)
 
 /* GSBI QUP devices */
+#define MSM_GSBI1_QUP_PHYS	(MSM_GSBI1_PHYS + 0x20000)
 #define MSM_GSBI3_QUP_PHYS	(MSM_GSBI3_PHYS + 0x80000)
 #define MSM_GSBI4_QUP_PHYS	(MSM_GSBI4_PHYS + 0x80000)
 #define MSM_GSBI5_QUP_PHYS	(MSM_GSBI5_PHYS + 0x80000)
@@ -195,6 +196,46 @@
 	},
 };
 
+static struct resource resources_qup_i2c_gsbi1[] = {
+	{
+		.name	= "gsbi_qup_i2c_addr",
+		.start	= MSM_GSBI1_PHYS,
+		.end	= MSM_GSBI1_PHYS + 4 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_phys_addr",
+		.start	= MSM_GSBI1_QUP_PHYS,
+		.end	= MSM_GSBI1_QUP_PHYS + MSM_QUP_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_err_intr",
+		.start	= APQ8064_GSBI1_QUP_IRQ,
+		.end	= APQ8064_GSBI1_QUP_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "i2c_clk",
+		.start	= 21,
+		.end	= 21,
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.name	= "i2c_sda",
+		.start	= 20,
+		.end	= 20,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+struct platform_device apq8064_device_qup_i2c_gsbi1 = {
+	.name		= "qup_i2c",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(resources_qup_i2c_gsbi1),
+	.resource	= resources_qup_i2c_gsbi1,
+};
+
 struct platform_device apq8064_device_qup_i2c_gsbi3 = {
 	.name		= "qup_i2c",
 	.id		= 3,
@@ -221,6 +262,18 @@
 		.end	= GSBI4_QUP_IRQ,
 		.flags	= IORESOURCE_IRQ,
 	},
+	{
+		.name	= "i2c_clk",
+		.start	= 11,
+		.end	= 11,
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.name	= "i2c_sda",
+		.start	= 10,
+		.end	= 10,
+		.flags	= IORESOURCE_IO,
+	},
 };
 
 struct platform_device apq8064_device_qup_i2c_gsbi4 = {
@@ -306,7 +359,7 @@
 };
 
 struct platform_device apq_cpudai_hdmi_rx = {
-	.name	= "msm-dai-q6",
+	.name	= "msm-dai-q6-hdmi",
 	.id	= 8,
 };
 
@@ -413,6 +466,11 @@
 	.id	= -1,
 };
 
+struct platform_device apq_cpudai_stub = {
+	.name = "msm-dai-stub",
+	.id = -1,
+};
+
 static struct resource resources_ssbi_pmic1[] = {
 	{
 		.start  = MSM_PMIC1_SSBI_CMD_PHYS,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 4525bab..4d4b88f 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1134,27 +1134,27 @@
 };
 
 #ifdef CONFIG_MSM_CAMERA
-struct resource msm_camera_resources[] = {
+static struct resource msm_cam_gsbi4_i2c_mux_resources[] = {
 	{
-		.name   = "s3d_rw",
+		.name   = "i2c_mux_rw",
 		.start  = 0x008003E0,
-		.end    = 0x008003E0 + SZ_16 - 1,
+		.end    = 0x008003E0 + SZ_8 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 	{
-		.name   = "s3d_ctl",
+		.name   = "i2c_mux_ctl",
 		.start  = 0x008020B8,
-		.end    = 0x008020B8 + SZ_16 - 1,
+		.end    = 0x008020B8 + SZ_4 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 };
 
-int __init msm_get_cam_resources(struct msm_camera_sensor_info *s_info)
-{
-	s_info->resource = msm_camera_resources;
-	s_info->num_resources = ARRAY_SIZE(msm_camera_resources);
-	return 0;
-}
+struct platform_device msm8960_device_i2c_mux_gsbi4 = {
+	.name           = "msm_cam_i2c_mux",
+	.id             = 0,
+	.resource       = msm_cam_gsbi4_i2c_mux_resources,
+	.num_resources  = ARRAY_SIZE(msm_cam_gsbi4_i2c_mux_resources),
+};
 
 static struct resource msm_csiphy0_resources[] = {
 	{
@@ -1186,6 +1186,21 @@
 	},
 };
 
+static struct resource msm_csiphy2_resources[] = {
+	{
+		.name	= "csiphy",
+		.start	= 0x04801400,
+		.end	= 0x04801400 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "csiphy",
+		.start	= MSM8960_CSIPHY_2_2LN_IRQ,
+		.end	= MSM8960_CSIPHY_2_2LN_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 struct platform_device msm8960_device_csiphy0 = {
 	.name           = "msm_csiphy",
 	.id             = 0,
@@ -1200,6 +1215,13 @@
 	.num_resources  = ARRAY_SIZE(msm_csiphy1_resources),
 };
 
+struct platform_device msm8960_device_csiphy2 = {
+	.name           = "msm_csiphy",
+	.id             = 2,
+	.resource       = msm_csiphy2_resources,
+	.num_resources  = ARRAY_SIZE(msm_csiphy2_resources),
+};
+
 static struct resource msm_csid0_resources[] = {
 	{
 		.name	= "csid",
@@ -1230,6 +1252,21 @@
 	},
 };
 
+static struct resource msm_csid2_resources[] = {
+	{
+		.name	= "csid",
+		.start	= 0x04801800,
+		.end	= 0x04801800 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "csid",
+		.start	= CSI_2_IRQ,
+		.end	= CSI_2_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 struct platform_device msm8960_device_csid0 = {
 	.name           = "msm_csid",
 	.id             = 0,
@@ -1244,6 +1281,13 @@
 	.num_resources  = ARRAY_SIZE(msm_csid1_resources),
 };
 
+struct platform_device msm8960_device_csid2 = {
+	.name           = "msm_csid",
+	.id             = 2,
+	.resource       = msm_csid2_resources,
+	.num_resources  = ARRAY_SIZE(msm_csid2_resources),
+};
+
 struct resource msm_ispif_resources[] = {
 	{
 		.name	= "ispif",
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 3944a93..18acb36 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -234,6 +234,30 @@
 	},
 };
 
+static struct resource resources_hsic_host[] = {
+	{
+		.start	= MSM9615_HSIC_PHYS,
+		.end	= MSM9615_HSIC_PHYS + MSM9615_HSIC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= USB_HSIC_IRQ,
+		.end	= USB_HSIC_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm_device_hsic_host = {
+	.name		= "msm_hsic_host",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_hsic_host),
+	.resource	= resources_hsic_host,
+	.dev		= {
+		.dma_mask               = &dma_mask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+};
+
 static struct resource resources_uart_gsbi4[] = {
 	{
 		.start	= GSBI4_UARTDM_IRQ,
@@ -419,7 +443,7 @@
 };
 
 static struct tsens_platform_data msm_tsens_pdata = {
-	.slope			= 910,
+	.slope			= {872, 872, 872, 872, 872},
 	.tsens_factor		= 1000,
 	.hw_type		= MSM_9615,
 	.tsens_num_sensor	= 5,
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 31eee43..15d4ae6 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -866,6 +866,35 @@
 	.resource	= gsbi0_msm8625_qup_resources,
 };
 
+static struct resource gsbi1_msm8625_qup_i2c_resources[] = {
+	{
+		.name	= "qup_phys_addr",
+		.start	= MSM_GSBI1_QUP_PHYS,
+		.end	= MSM_GSBI1_QUP_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "gsbi_qup_i2c_addr",
+		.start	= MSM_GSBI1_PHYS,
+		.end	= MSM_GSBI1_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "qup_err_intr",
+		.start	= MSM8625_INT_ARM11_DMA,
+		.end	= MSM8625_INT_ARM11_DMA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* Use GSBI1 QUP for /dev/i2c-1 */
+struct platform_device msm8625_device_qup_i2c_gsbi1 = {
+	.name		= "qup_i2c",
+	.id		= MSM_GSBI1_QUP_I2C_BUS_ID,
+	.num_resources	= ARRAY_SIZE(gsbi1_qup_i2c_resources),
+	.resource	= gsbi1_msm8625_qup_i2c_resources,
+};
+
 static struct resource msm8625_gpio_resources[] = {
 	{
 		.start	= MSM8625_INT_GPIO_GROUP1,
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index fc732da..e9b94f6 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -1181,6 +1181,7 @@
 	.set_grp_async = set_grp3d_async,
 	.idle_timeout = HZ/20,
 	.nap_allowed = true,
+	.idle_needed = true,
 	.clk_map = KGSL_CLK_SRC | KGSL_CLK_CORE |
 		KGSL_CLK_IFACE | KGSL_CLK_MEM,
 };
@@ -1223,6 +1224,7 @@
 	.set_grp_async = NULL,
 	.idle_timeout = HZ/10,
 	.nap_allowed = true,
+	.idle_needed = true,
 	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 };
 
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index c4f57ab..c86d051 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -59,10 +59,13 @@
 extern struct platform_device msm8960_device_qup_i2c_gsbi12;
 extern struct platform_device msm8960_device_qup_spi_gsbi1;
 extern struct platform_device msm8960_gemini_device;
+extern struct platform_device msm8960_device_i2c_mux_gsbi4;
 extern struct platform_device msm8960_device_csiphy0;
 extern struct platform_device msm8960_device_csiphy1;
+extern struct platform_device msm8960_device_csiphy2;
 extern struct platform_device msm8960_device_csid0;
 extern struct platform_device msm8960_device_csid1;
+extern struct platform_device msm8960_device_csid2;
 extern struct platform_device msm8960_device_ispif;
 extern struct platform_device msm8960_device_vfe;
 extern struct platform_device msm8960_device_vpe;
@@ -70,6 +73,7 @@
 extern struct platform_device apq8064_device_uart_gsbi1;
 extern struct platform_device apq8064_device_uart_gsbi3;
 extern struct platform_device apq8064_device_uart_gsbi7;
+extern struct platform_device apq8064_device_qup_i2c_gsbi1;
 extern struct platform_device apq8064_device_qup_i2c_gsbi3;
 extern struct platform_device apq8064_device_qup_i2c_gsbi4;
 extern struct platform_device apq8064_device_qup_spi_gsbi5;
@@ -123,6 +127,7 @@
 extern struct platform_device msm_gsbi12_qup_i2c_device;
 
 extern struct platform_device msm8625_device_qup_i2c_gsbi0;
+extern struct platform_device msm8625_device_qup_i2c_gsbi1;
 
 extern struct platform_device msm_slim_ctrl;
 extern struct platform_device msm_device_sps;
@@ -222,6 +227,7 @@
 extern struct platform_device apq_cpudai_afe_02_rx;
 extern struct platform_device apq_cpudai_afe_02_tx;
 extern struct platform_device apq_pcm_afe;
+extern struct platform_device apq_cpudai_stub;
 
 extern struct platform_device *msm_footswitch_devices[];
 extern unsigned msm_num_footswitch_devices;
diff --git a/arch/arm/mach-msm/etm.c b/arch/arm/mach-msm/etm.c
index bee0975..9d04a58 100644
--- a/arch/arm/mach-msm/etm.c
+++ b/arch/arm/mach-msm/etm.c
@@ -377,9 +377,9 @@
 	etm_write(etm_config.etm_addr_access_type[6], ETMACTR6);
 	etm_write(etm_config.etm_addr_access_type[7], ETMACTR7);
 	etm_write(etm_config.etm_data_comp_value[0], ETMDCVR0);
-	etm_write(etm_config.etm_data_comp_value[1], ETMDCVR1);
+	etm_write(etm_config.etm_data_comp_value[1], ETMDCVR2);
 	etm_write(etm_config.etm_data_comp_mask[0], ETMDCMR0);
-	etm_write(etm_config.etm_data_comp_mask[1], ETMDCMR1);
+	etm_write(etm_config.etm_data_comp_mask[1], ETMDCMR2);
 	etm_write(etm_config.etm_counter_reload_value[0], ETMCNTRLDVR0);
 	etm_write(etm_config.etm_counter_reload_value[1], ETMCNTRLDVR1);
 	etm_write(etm_config.etm_counter_enable[0], ETMCNTENR0);
@@ -564,9 +564,9 @@
 	emit_log_word(etm_read(ETMACTR6));
 	emit_log_word(etm_read(ETMACTR7));
 	emit_log_word(etm_read(ETMDCVR0));
-	emit_log_word(etm_read(ETMDCVR1));
+	emit_log_word(etm_read(ETMDCVR2));
 	emit_log_word(etm_read(ETMDCMR0));
-	emit_log_word(etm_read(ETMDCMR1));
+	emit_log_word(etm_read(ETMDCMR2));
 	emit_log_word(etm_read(ETMCNTRLDVR0));
 	emit_log_word(etm_read(ETMCNTRLDVR1));
 	emit_log_word(etm_read(ETMCNTENR0));
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 26adec6..8d40908 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -10,10 +10,13 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/cpu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/vfp.h>
 
+#include <mach/msm_rtb.h>
+
 #include "pm.h"
 #include "qdss.h"
 #include "spm.h"
@@ -49,6 +52,9 @@
 			/*
 			 * OK, proper wakeup, we're done
 			 */
+			pen_release = -1;
+			dmac_flush_range((void *)&pen_release,
+				(void *)(&pen_release + sizeof(pen_release)));
 			break;
 		}
 
@@ -60,6 +66,8 @@
 		 * possible, since we are currently running incoherently, and
 		 * therefore cannot safely call printk() or anything else
 		 */
+		dmac_inv_range((void *)&pen_release,
+			       (void *)(&pen_release + sizeof(pen_release)));
 		pr_debug("CPU%u: spurious wakeup call\n", cpu);
 	}
 }
@@ -109,6 +117,45 @@
 	return cpu == 0 ? -EPERM : 0;
 }
 
+#define CPU_SHIFT	0
+#define CPU_MASK	0xF
+#define CPU_OF(n)	(((n) & CPU_MASK) << CPU_SHIFT)
+#define CPUSET_SHIFT	4
+#define CPUSET_MASK	0xFFFF
+#define CPUSET_OF(n)	(((n) & CPUSET_MASK) << CPUSET_SHIFT)
+
+static int hotplug_rtb_callback(struct notifier_block *nfb,
+				unsigned long action, void *hcpu)
+{
+	/*
+	 * Bits [19:4] of the data are the online mask, lower 4 bits are the
+	 * cpu number that is being changed. Additionally, changes to the
+	 * online_mask that will be done by the current hotplug will be made
+	 * even though they aren't necessarily in the online mask yet.
+	 *
+	 * XXX: This design is limited to supporting at most 16 cpus
+	 */
+	int this_cpumask = CPUSET_OF(1 << (int)hcpu);
+	int cpumask = CPUSET_OF(cpumask_bits(cpu_online_mask)[0]);
+	int cpudata = CPU_OF((int)hcpu) | cpumask;
+
+	switch (action & (~CPU_TASKS_FROZEN)) {
+	case CPU_STARTING:
+		uncached_logk(LOGK_HOTPLUG, (void *)(cpudata | this_cpumask));
+		break;
+	case CPU_DYING:
+		uncached_logk(LOGK_HOTPLUG, (void *)(cpudata & ~this_cpumask));
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+static struct notifier_block hotplug_rtb_notifier = {
+	.notifier_call = hotplug_rtb_callback,
+};
+
 int msm_platform_secondary_init(unsigned int cpu)
 {
 	int ret;
@@ -127,3 +174,9 @@
 
 	return ret;
 }
+
+static int __init init_hotplug_notifier(void)
+{
+	return register_hotcpu_notifier(&hotplug_rtb_notifier);
+}
+early_initcall(init_hotplug_notifier);
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index c274899..32d162d 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -100,12 +100,14 @@
 	cmp	r1, #1
 	bne	skip
 	bl	v7_flush_dcache_all
+	b skip2
 
 skip:	ldr	r0, =saved_state
 	ldr	r1, =saved_state_end
 	sub	r1, r1, r0
 	bl	v7_flush_kern_dcache_area
 
+skip2:
 #ifdef CONFIG_ARCH_MSM_KRAIT
 	ldr	r0, =SCM_SVC_BOOT
 	ldr	r1, =SCM_CMD_TERMINATE_PC
@@ -136,7 +138,9 @@
 #if (NR_CPUS >= 2)
 	mrc	p15, 0, r1, c0, c0, 5	/* MPIDR */
 	ands	r1, r1, #15		/* What CPU am I */
-	addne	r0, r0, #CPU_SAVED_STATE_SIZE
+	mov	r2, #CPU_SAVED_STATE_SIZE
+	mul	r2, r2, r1
+	add	r0, r0, r2
 #endif
 
 	ldmfd   r0, {r4-r14}
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index ba9fc70..96b0083 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -202,6 +202,18 @@
 	uint8_t cam_gpio_set_tbl_size;
 };
 
+enum msm_camera_i2c_mux_mode {
+	MODE_R,
+	MODE_L,
+	MODE_DUAL
+};
+
+struct msm_camera_i2c_conf {
+	uint8_t use_i2c_mux;
+	struct platform_device *mux_dev;
+	enum msm_camera_i2c_mux_mode i2c_mux_mode;
+};
+
 struct msm_camera_sensor_platform_info {
 	int mount_angle;
 	int sensor_reset;
@@ -209,6 +221,7 @@
 	int num_vreg;
 	int32_t (*ext_power_ctrl) (int enable);
 	struct msm_camera_gpio_conf *gpio_conf;
+	struct msm_camera_i2c_conf *i2c_conf;
 };
 
 struct msm_actuator_info {
@@ -238,6 +251,7 @@
 	char *eeprom_data;
 	enum msm_camera_type camera_type;
 	struct msm_actuator_info *actuator_info;
+	int pmic_gpio_enable;
 };
 
 struct msm_camera_board_info {
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 700e28c..ef7be45 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -631,12 +631,6 @@
 	S_EXIT
 };
 
-enum msm_cam_mode {
-	MODE_R,
-	MODE_L,
-	MODE_DUAL
-};
-
 struct msm_cam_clk_info {
 	const char *clk_name;
 	long clk_rate;
@@ -648,7 +642,7 @@
 int msm_camio_vpe_clk_enable(uint32_t);
 int msm_camio_vpe_clk_disable(void);
 
-void msm_camio_mode_config(enum msm_cam_mode mode);
+void msm_camio_mode_config(enum msm_camera_i2c_mux_mode mode);
 int  msm_camio_clk_enable(enum msm_camio_clk_type clk);
 int  msm_camio_clk_disable(enum msm_camio_clk_type clk);
 int  msm_camio_clk_config(uint32_t freq);
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 48eae0c..2d2d2fb 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -20,8 +20,9 @@
 
 enum {
 	VIDEO_FIRMWARE_POOL,
-	LOW_256MB_POOL,
-	HIGH_POOL,
+	VIDEO_MAIN_POOL,
+	VIDEO_MFC_POOL,
+	GEN_POOL,
 };
 
 
diff --git a/arch/arm/mach-msm/include/mach/irqs-8960.h b/arch/arm/mach-msm/include/mach/irqs-8960.h
index dae0f47..012dd74 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8960.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8960.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -268,6 +268,8 @@
 #define PM8921_SEC_IRQ_104			(GIC_SPI_START + 225)
 #define PM8018_SEC_IRQ_107			(GIC_SPI_START + 226)
 #define USB_HSIC_IRQ				(GIC_SPI_START + 229)
+#define MSM8960_CSIPHY_2_2LN_IRQ		(GIC_SPI_START + 228)
+#define CSI_2_IRQ				(GIC_SPI_START + 227)
 
 /* Backwards compatible IRQ macros. */
 #define INT_ADM_AARM				ADM_0_SCSS_0_IRQ
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8625.h b/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
index 8088a4c..3435c2a 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8625.h
@@ -48,11 +48,11 @@
 #define MSM8625_SCU_PHYS		0xC0600000
 #define MSM8625_SCU_SIZE		SZ_256
 
-#define MSM8625_SPM0_PHYS		0xC0200000
-#define MSM8625_SPM0_SIZE		SZ_4K
+#define MSM8625_SAW0_PHYS		0xC0200000
+#define MSM8625_SAW0_SIZE		SZ_4K
 
-#define MSM8625_SPM1_PHYS		0xC0700000
-#define MSM8625_SPM1_SIZE		SZ_4K
+#define MSM8625_SAW1_PHYS		0xC0700000
+#define MSM8625_SAW1_SIZE		SZ_4K
 
 #define MSM8625_CFG_CTL_PHYS		0xA9800000
 #define MSM8625_CFG_CTL_SIZE		SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-copper.h b/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
index a3c9da8..6311dbe 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -23,12 +23,17 @@
  *
  */
 
+#define COPPER_MSM_SHARED_RAM_PHYS	0x18D00000
+
 #define COPPER_QGIC_DIST_PHYS	0xF9000000
 #define COPPER_QGIC_DIST_SIZE	SZ_4K
 
 #define COPPER_QGIC_CPU_PHYS	0xF9002000
 #define COPPER_QGIC_CPU_SIZE	SZ_4K
 
+#define COPPER_APCS_GCC_PHYS	0xF9011000
+#define COPPER_APCS_GCC_SIZE	SZ_4K
+
 #define COPPER_TLMM_PHYS	0xFD400000
 #define COPPER_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index d53910d..27965d3 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,7 +47,9 @@
 
 #if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
 	defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
-	defined(CONFIG_ARCH_MSMCOPPER)
+	defined(CONFIG_ARCH_MSMCOPPER) || defined(CONFIG_ARCH_MSM7X27) || \
+	defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
+	defined(CONFIG_ARCH_MSM8625)
 
 /* Unified iomap */
 
@@ -80,13 +82,28 @@
 #define MSM_APCS_GLB_BASE	IOMEM(0xFA702000)	/*  4K  */
 #define MSM_SAW2_BASE		IOMEM(0xFA703000)	/*  4k  */
 #define MSM_SAW3_BASE		IOMEM(0xFA704000)	/*  4k  */
+#define MSM_VIC_BASE		IOMEM(0xFA100000)	/*  4K */
+#define MSM_CSR_BASE		IOMEM(0xFA101000)	/*  4K */
+#define MSM_GPIO1_BASE		IOMEM(0xFA102000)	/*  4K */
+#define MSM_GPIO2_BASE		IOMEM(0xFA103000)	/*  4K */
+#define MSM_SCU_BASE		IOMEM(0xFA104000)	/*  4K */
+#define MSM_CFG_CTL_BASE	IOMEM(0xFA105000)	/*  4K */
+#define MSM_MDC_BASE		IOMEM(0xFA400000)	/*  1M */
+#define MSM_AD5_BASE		IOMEM(0xFA900000)	/*  13M (D00000)
+							  0xFB600000 */
 
-#if defined(CONFIG_ARCH_MSM9615)
+#define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
+#define MSM8625_SECONDARY_PHYS		0x0FE00000
+
+
+#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 #else
 #define MSM_SHARED_RAM_SIZE	SZ_2M
 #endif
 
+#include "msm_iomap-7xxx.h"
+#include "msm_iomap-8625.h"
 #include "msm_iomap-8960.h"
 #include "msm_iomap-8930.h"
 #include "msm_iomap-8064.h"
@@ -105,29 +122,7 @@
 #elif defined(CONFIG_ARCH_FSM9XXX)
 #include "msm_iomap-fsm9xxx.h"
 #else
-#define MSM_VIC_BASE			IOMEM(0xFA000000)	/* 4K */
-#define MSM_CSR_BASE			IOMEM(0xFA001000)	/* 4K */
-#define MSM_TMR_BASE			MSM_CSR_BASE		/* 4K */
-#define MSM_TMR0_BASE			IOMEM(0xFA002000)	/* 4K */
-#define MSM_GPIO1_BASE			IOMEM(0xFA003000)	/* 4K */
-#define MSM_GPIO2_BASE			IOMEM(0xFA004000)	/* 4K */
-#define MSM_CLK_CTL_BASE		IOMEM(0xFA005000)	/* 4K */
-#define MSM_L2CC_BASE			IOMEM(0xFA006000)	/* 4K */
-#define MSM_QGIC_DIST_BASE		IOMEM(0xFA007000)	/* 4K */
-#define MSM_QGIC_CPU_BASE		IOMEM(0xFA008000)	/* 4K */
-#define MSM_SCU_BASE			IOMEM(0xFA009000)	/* 4K */
-#define MSM_SPM0_BASE			IOMEM(0xFA00A000)	/* 4K */
-#define MSM_SPM1_BASE			IOMEM(0xFA00B000)	/* 4K */
-#define MSM_CFG_CTL_BASE		IOMEM(0xFA00C000)	/* 4K */
-#define MSM_SHARED_RAM_BASE		IOMEM(0xFA100000)	/* 4K */
-#define MSM_MDC_BASE			IOMEM(0xFA200000)	/* 4K */
-#define MSM_AD5_BASE			IOMEM(0xFA300000)	/* 4K */
-#define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
-#define MSM8625_SECONDARY_PHYS		0x0FE00000
-#define MSM_SHARED_RAM_SIZE		SZ_1M
-
-#include "msm_iomap-7xxx.h"
-#include "msm_iomap-8625.h"
+#error "Target compiled without IO map\n"
 #endif
 
 #if defined(CONFIG_DEBUG_MSM_UART1)
diff --git a/arch/arm/mach-msm/include/mach/msm_rtb.h b/arch/arm/mach-msm/include/mach/msm_rtb.h
index ac45cbd..a75ab91 100644
--- a/arch/arm/mach-msm/include/mach/msm_rtb.h
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -18,9 +18,14 @@
 	LOGK_READL,
 	LOGK_WRITEL,
 	LOGK_LOGBUF,
+	LOGK_HOTPLUG,
 	LOGK_OTHER,
 };
 
+struct msm_rtb_platform_data {
+	unsigned int size;
+};
+
 #if defined(CONFIG_MSM_RTB)
 /*
  * returns 1 if data was logged, 0 otherwise
diff --git a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
index d50fe2b..92dfe12 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
@@ -132,6 +132,8 @@
 
 	unsigned int minor_no;
 	struct codec_operations codec_ops;
+	uint32_t buffer_size;
+	uint32_t buffer_count;
 };
 
 #endif /* !CODEC_UTILS_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index 80ec683..bcb1240 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -117,8 +117,8 @@
 	MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_2,
 	MSM_RPM_ID_SYS_FABRIC_CFG_IOCTL,
 	MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
-	MSM_RPM_ID_SYSTEM_FABRIC_ARB_28 =
-		MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 28,
+	MSM_RPM_ID_SYSTEM_FABRIC_ARB_29 =
+		MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 29,
 
 	MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
 	MSM_RPM_ID_MM_FABRIC_HALT_0 =
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 830db1f..dcf9f12 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -292,7 +292,13 @@
 static struct map_desc msm_copper_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, COPPER),
 	MSM_CHIP_DEVICE(QGIC_CPU, COPPER),
+	MSM_CHIP_DEVICE(APCS_GCC, COPPER),
 	MSM_CHIP_DEVICE(TLMM, COPPER),
+	{
+		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
+		.length =   MSM_SHARED_RAM_SIZE,
+		.type =     MT_DEVICE,
+	},
 #ifdef CONFIG_DEBUG_MSMCOPPER_UART
 	MSM_DEVICE(DEBUG_UART),
 #endif
@@ -300,6 +306,7 @@
 
 void __init msm_map_copper_io(void)
 {
+	msm_shared_ram_phys = COPPER_MSM_SHARED_RAM_PHYS;
 	msm_map_io(msm_copper_io_desc, ARRAY_SIZE(msm_copper_io_desc));
 }
 #endif /* CONFIG_ARCH_MSMCOPPER */
@@ -410,8 +417,8 @@
 	MSM_CHIP_DEVICE(SCU, MSM8625),
 	MSM_CHIP_DEVICE(CFG_CTL, MSM8625),
 	MSM_CHIP_DEVICE(CLK_CTL, MSM8625),
-	MSM_CHIP_DEVICE(SPM0, MSM8625),
-	MSM_CHIP_DEVICE(SPM1, MSM8625),
+	MSM_CHIP_DEVICE(SAW0, MSM8625),
+	MSM_CHIP_DEVICE(SAW1, MSM8625),
 #if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
 	defined(CONFIG_DEBUG_MSM_UART3)
 	MSM_CHIP_DEVICE(DEBUG_UART, MSM7XXX),
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index c856455..727b729 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -103,11 +103,11 @@
 	case MSM_SUBSYSTEM_VIDEO_FWARE:
 		return VIDEO_FIRMWARE_POOL;
 	case MSM_SUBSYSTEM_VIDEO:
-		return LOW_256MB_POOL;
+		return VIDEO_MAIN_POOL;
 	case MSM_SUBSYSTEM_CAMERA:
 	case MSM_SUBSYSTEM_DISPLAY:
 	case MSM_SUBSYSTEM_ROTATOR:
-		return HIGH_POOL;
+		return GEN_POOL;
 	default:
 		return 0xFFFFFFFF;
 	}
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index f720fa9..b75fb38 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.c
@@ -22,8 +22,10 @@
 #include "qdss.h"
 #include "cp14.h"
 
+ /* no of dbg regs + 1 (for storing the reg count) */
 #define MAX_DBG_REGS		(90)
 #define MAX_DBG_STATE_SIZE	(MAX_DBG_REGS * num_possible_cpus())
+ /* no of etm regs + 1 (for storing the reg count) */
 #define MAX_ETM_REGS		(78)
 #define MAX_ETM_STATE_SIZE	(MAX_ETM_REGS * num_possible_cpus())
 
@@ -70,7 +72,7 @@
 		break;
 	case 3:
 		state[i++] = dbg_read(DBGBVR3);
-		state[i++] = dbg_read(DBGBVR3);
+		state[i++] = dbg_read(DBGBCR3);
 		break;
 	case 4:
 		state[i++] = dbg_read(DBGBVR4);
@@ -78,7 +80,7 @@
 		break;
 	case 5:
 		state[i++] = dbg_read(DBGBVR5);
-		state[i++] = dbg_read(DBGBVR5);
+		state[i++] = dbg_read(DBGBCR5);
 		break;
 	case 6:
 		state[i++] = dbg_read(DBGBVR6);
@@ -143,7 +145,7 @@
 		break;
 	case 3:
 		dbg_write(state[i++], DBGBVR3);
-		dbg_write(state[i++], DBGBVR3);
+		dbg_write(state[i++], DBGBCR3);
 		break;
 	case 4:
 		dbg_write(state[i++], DBGBVR4);
@@ -151,7 +153,7 @@
 		break;
 	case 5:
 		dbg_write(state[i++], DBGBVR5);
-		dbg_write(state[i++], DBGBVR5);
+		dbg_write(state[i++], DBGBCR5);
 		break;
 	case 6:
 		dbg_write(state[i++], DBGBVR6);
@@ -937,9 +939,9 @@
 		etm_write(etm.state[i++], ETMSQ12EVR);
 		etm_write(etm.state[i++], ETMSQ21EVR);
 		etm_write(etm.state[i++], ETMSQ23EVR);
+		etm_write(etm.state[i++], ETMSQ31EVR);
 		etm_write(etm.state[i++], ETMSQ32EVR);
 		etm_write(etm.state[i++], ETMSQ13EVR);
-		etm_write(etm.state[i++], ETMSQ31EVR);
 		etm_write(etm.state[i++], ETMSQR);
 		for (j = 0; j < etm.nr_ext_out; j++)
 			i = etm_write_extoutevr(etm.state, i, j);
@@ -1046,9 +1048,9 @@
 		pr_info("dbg arch %u not supported\n", dbg.arch);
 		goto dbg_out;
 	}
-	dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23);
-	dbg.nr_bp = BMVAL(dbgdidr, 24, 27);
-	dbg.nr_wp = BMVAL(dbgdidr, 28, 31);
+	dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23) + 1;
+	dbg.nr_bp = BMVAL(dbgdidr, 24, 27) + 1;
+	dbg.nr_wp = BMVAL(dbgdidr, 28, 31) + 1;
 
 	/* Allocate dbg state save space */
 	dbg.state = kzalloc(MAX_DBG_STATE_SIZE * sizeof(uint32_t), GFP_KERNEL);
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 5db8b40..34bc415 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -82,7 +82,7 @@
 	/* Pull RESET gpio low and wait for it to settle. */
 	pr_debug("Pulling RESET gpio low\n");
 	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
-	usleep(1000);
+	usleep_range(5000, 10000);
 
 	/* Deassert RESET first and wait for ir to settle. */
 	pr_debug("%s: Pulling RESET gpio high\n", __func__);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 3b064ff..d26d76b 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/memory.c
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -226,6 +226,25 @@
 	return unstable_limit - mb->start;
 }
 
+/* stable size of all memory banks contiguous to and below this one */
+static unsigned long total_stable_size(unsigned long bank)
+{
+	int i;
+	struct membank *mb = &meminfo.bank[bank];
+	int memtype = reserve_info->paddr_to_memtype(mb->start);
+	unsigned long size;
+
+	size = stable_size(mb, reserve_info->low_unstable_address);
+	for (i = bank - 1, mb = &meminfo.bank[bank - 1]; i >= 0; i--, mb--) {
+		if (mb->start + mb->size != (mb + 1)->start)
+			break;
+		if (reserve_info->paddr_to_memtype(mb->start) != memtype)
+			break;
+		size += stable_size(mb, reserve_info->low_unstable_address);
+	}
+	return size;
+}
+
 static void __init calculate_reserve_limits(void)
 {
 	int i;
@@ -242,7 +261,7 @@
 			continue;
 		}
 		mt = &reserve_info->memtype_reserve_table[memtype];
-		size = stable_size(mb, reserve_info->low_unstable_address);
+		size = total_stable_size(i);
 		mt->limit = max(mt->limit, size);
 	}
 }
@@ -277,10 +296,11 @@
 		if (mt->flags & MEMTYPE_FLAGS_FIXED || !mt->size)
 			continue;
 
-		/* We know we will find a memory bank of the proper size
+		/* We know we will find memory bank(s) of the proper size
 		 * as we have limited the size of the memory pool for
-		 * each memory type to the size of the largest memory
-		 * bank. Choose the memory bank with the highest physical
+		 * each memory type to the largest total size of the memory
+		 * banks which are contiguous and of the correct memory type.
+		 * Choose the memory bank with the highest physical
 		 * address which is large enough, so that we will not
 		 * take memory from the lowest memory bank which the kernel
 		 * is in (and cause boot problems) and so that we might
@@ -293,9 +313,14 @@
 				reserve_info->paddr_to_memtype(mb->start);
 			if (memtype != membank_type)
 				continue;
-			size = stable_size(mb,
-				reserve_info->low_unstable_address);
+			size = total_stable_size(i);
 			if (size >= mt->size) {
+				size = stable_size(mb,
+					reserve_info->low_unstable_address);
+				/* mt->size may be larger than size, all this
+				 * means is that we are carving the memory pool
+				 * out of multiple contiguous memory banks.
+				 */
 				mt->start = mb->start + (size - mt->size);
 				ret = memblock_remove(mt->start, mt->size);
 				BUG_ON(ret);
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index 018e2a6..061998c 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -6,4 +6,5 @@
 obj-$(CONFIG_ARCH_MSM8960) += msm_bus_board_8960.o
 obj-$(CONFIG_ARCH_MSM9615) += msm_bus_board_9615.o
 obj-$(CONFIG_ARCH_APQ8064) += msm_bus_board_8064.o
+obj-$(CONFIG_ARCH_MSM8930) += msm_bus_board_8930.o
 obj-$(CONFIG_DEBUG_FS) += msm_bus_dbg.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
new file mode 100644
index 0000000..36fe156
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
@@ -0,0 +1,878 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/rpm.h>
+#include "msm_bus_core.h"
+
+#define NMASTERS 45
+#define NSLAVES 75
+#define NFAB_8930 5
+
+enum msm_bus_fabric_tiered_slave_type {
+	MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS_0 = 1,
+	MSM_BUS_TIERED_SLAVE_SYSTEM_IMEM,
+
+	MSM_BUS_TIERED_SLAVE_MM_IMEM = 1,
+	MSM_BUS_MMSS_TIERED_SLAVE_FAB_APPS_0,
+
+	MSM_BUS_TIERED_SLAVE_EBI1_CH0 = 1,
+	MSM_BUS_TIERED_SLAVE_KMPSS_L2,
+};
+
+enum msm_bus_8930_master_ports_type {
+	MSM_BUS_SYSTEM_MASTER_PORT_APPSS_FAB = 0,
+	MSM_BUS_MASTER_PORT_SPS,
+	MSM_BUS_MASTER_PORT_ADM_PORT0,
+	MSM_BUS_MASTER_PORT_ADM_PORT1,
+	MSM_BUS_MASTER_PORT_LPASS_PROC,
+	MSM_BUS_MASTER_PORT_MSS,
+	MSM_BUS_MASTER_PORT_RIVA,
+	MSM_BUS_MASTER_PORT_MSS_SW_PROC,
+	MSM_BUS_MASTER_PORT_MSS_FW_PROC,
+	MSM_BUS_MASTER_PORT_LPASS,
+	MSM_BUS_SYSTEM_MASTER_PORT_CPSS_FPB,
+	MSM_BUS_SYSTEM_MASTER_PORT_SYSTEM_FPB,
+	MSM_BUS_SYSTEM_MASTER_PORT_MMSS_FPB,
+	MSM_BUS_SYSTEM_MASTER_PORT_ADM_AHB_CI,
+
+	MSM_BUS_MASTER_PORT_MDP_PORT0 = 0,
+	MSM_BUS_MASTER_PORT_MDP_PORT1,
+	MSM_BUS_MASTER_PORT_GRAPHICS_3D,
+	MSM_BUS_MASTER_PORT_ROTATOR,
+	MSM_BUS_MASTER_PORT_VFE,
+	MSM_BUS_MASTER_PORT_VPE,
+	MSM_BUS_MASTER_PORT_JPEG_ENC,
+	MSM_BUS_MMSS_MASTER_PORT_APPS_FAB,
+	MSM_BUS_MASTER_PORT_HD_CODEC_PORT0,
+	MSM_BUS_MASTER_PORT_HD_CODEC_PORT1,
+
+	MSM_BUS_MASTER_PORT_KMPSS_M0 = 0,
+	MSM_BUS_MASTER_PORT_KMPSS_M1,
+	MSM_BUS_APPSS_MASTER_PORT_FAB_MMSS_0,
+	MSM_BUS_APPSS_MASTER_PORT_FAB_SYSTEM_0,
+};
+
+enum msm_bus_8930_slave_ports_type {
+	MSM_BUS_SLAVE_PORT_MM_IMEM = 0,
+	MSM_BUS_MMSS_SLAVE_PORT_APPS_FAB_0,
+
+	MSM_BUS_SLAVE_PORT_EBI1_CH0 = 0,
+	MSM_BUS_SLAVE_PORT_KMPSS_L2,
+	MSM_BUS_APPSS_SLAVE_PORT_MMSS_FAB,
+	MSM_BUS_SLAVE_PORT_SYSTEM_FAB,
+
+	MSM_BUS_SYSTEM_SLAVE_PORT_APPSS_FAB_0 = 0,
+	MSM_BUS_SLAVE_PORT_SPS,
+	MSM_BUS_SLAVE_PORT_SYSTEM_IMEM,
+	MSM_BUS_SLAVE_PORT_CORESIGHT,
+	MSM_BUS_SLAVE_PORT_KMPSS,
+	MSM_BUS_SLAVE_PORT_MSS,
+	MSM_BUS_SLAVE_PORT_LPASS,
+	MSM_BUS_SYSTEM_SLAVE_PORT_CPSS_FPB,
+	MSM_BUS_SYSTEM_SLAVE_PORT_SYSTEM_FPB,
+	MSM_BUS_SYSTEM_SLAVE_PORT_MMSS_FPB,
+	MSM_BUS_SLAVE_PORT_RIVA,
+};
+
+static int tier2[] = {MSM_BUS_BW_TIER2,};
+static uint32_t master_iids[NMASTERS];
+static uint32_t slave_iids[NSLAVES];
+
+static int mport_kmpss_m0[] = {MSM_BUS_MASTER_PORT_KMPSS_M0,};
+static int mport_kmpss_m1[] = {MSM_BUS_MASTER_PORT_KMPSS_M1,};
+
+static int mmss_mport_apps_fab[] = {MSM_BUS_MMSS_MASTER_PORT_APPS_FAB,};
+static int system_mport_appss_fab[] = {MSM_BUS_SYSTEM_MASTER_PORT_APPSS_FAB,};
+static int sport_ebi1_ch0[] = {
+	MSM_BUS_SLAVE_PORT_EBI1_CH0,
+};
+static int sport_kmpss_l2[] = {MSM_BUS_SLAVE_PORT_KMPSS_L2,};
+static int appss_sport_mmss_fab[] = {MSM_BUS_APPSS_SLAVE_PORT_MMSS_FAB,};
+static int sport_system_fab[] = {MSM_BUS_SLAVE_PORT_SYSTEM_FAB,};
+
+static int tiered_slave_ebi1_ch0[] = {
+	MSM_BUS_TIERED_SLAVE_EBI1_CH0,
+};
+
+static int tiered_slave_kmpss[] = {MSM_BUS_TIERED_SLAVE_KMPSS_L2,};
+
+static struct msm_bus_node_info apps_fabric_info[] = {
+	{
+		.id = MSM_BUS_MASTER_AMPSS_M0,
+		.masterp = mport_kmpss_m0,
+		.num_mports = ARRAY_SIZE(mport_kmpss_m0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_AMPSS_M1,
+		.masterp = mport_kmpss_m1,
+		.num_mports = ARRAY_SIZE(mport_kmpss_m1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI_CH0,
+		.slavep = sport_ebi1_ch0,
+		.num_sports = ARRAY_SIZE(sport_ebi1_ch0),
+		.tier = tiered_slave_ebi1_ch0,
+		.num_tiers = ARRAY_SIZE(tiered_slave_ebi1_ch0),
+		.buswidth = 8,
+		.slaveclk[DUAL_CTX] = "mem_clk",
+		.slaveclk[ACTIVE_CTX] = "mem_a_clk",
+	},
+	{
+		.id = MSM_BUS_SLAVE_AMPSS_L2,
+		.slavep = sport_kmpss_l2,
+		.num_sports = ARRAY_SIZE(sport_kmpss_l2),
+		.tier = tiered_slave_kmpss,
+		.num_tiers = ARRAY_SIZE(tiered_slave_kmpss),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_FAB_MMSS,
+		.gateway = 1,
+		.slavep = appss_sport_mmss_fab,
+		.num_sports = ARRAY_SIZE(appss_sport_mmss_fab),
+		.masterp = mmss_mport_apps_fab,
+		.num_mports = ARRAY_SIZE(mmss_mport_apps_fab),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_FAB_SYSTEM,
+		.gateway = 1,
+		.slavep = sport_system_fab,
+		.num_sports = ARRAY_SIZE(sport_system_fab),
+		.masterp = system_mport_appss_fab,
+		.num_mports = ARRAY_SIZE(system_mport_appss_fab),
+		.buswidth = 8,
+	},
+};
+
+static int mport_sps[] = {MSM_BUS_MASTER_PORT_SPS,};
+static int mport_adm_port0[] = {MSM_BUS_MASTER_PORT_ADM_PORT0,};
+static int mport_adm_port1[] = {MSM_BUS_MASTER_PORT_ADM_PORT1,};
+static int mport_mss[] = {MSM_BUS_MASTER_PORT_MSS,};
+static int mport_lpass_proc[] = {MSM_BUS_MASTER_PORT_LPASS_PROC,};
+static int mport_riva[] = {MSM_BUS_MASTER_PORT_RIVA,};
+static int mport_mss_sw_proc[] = {MSM_BUS_MASTER_PORT_MSS_SW_PROC,};
+static int mport_mss_fw_proc[] = {MSM_BUS_MASTER_PORT_MSS_FW_PROC,};
+static int mport_lpass[] = {MSM_BUS_MASTER_PORT_LPASS,};
+static int system_mport_mmss_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_MMSS_FPB,};
+static int system_mport_adm_ahb_ci[] = {MSM_BUS_SYSTEM_MASTER_PORT_ADM_AHB_CI,};
+static int appss_mport_fab_system[] = {
+	MSM_BUS_APPSS_MASTER_PORT_FAB_SYSTEM_0,
+};
+static int mport_system_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_SYSTEM_FPB,};
+static int system_mport_cpss_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_CPSS_FPB,};
+
+static int system_sport_appss_fab[] = {
+	MSM_BUS_SYSTEM_SLAVE_PORT_APPSS_FAB_0,
+};
+static int system_sport_system_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_SYSTEM_FPB,};
+static int system_sport_cpss_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_CPSS_FPB,};
+static int sport_sps[] = {MSM_BUS_SLAVE_PORT_SPS,};
+static int sport_system_imem[] = {MSM_BUS_SLAVE_PORT_SYSTEM_IMEM,};
+static int sport_coresight[] = {MSM_BUS_SLAVE_PORT_CORESIGHT,};
+static int sport_riva[] = {MSM_BUS_SLAVE_PORT_RIVA,};
+static int sport_kmpss[] = {MSM_BUS_SLAVE_PORT_KMPSS,};
+static int sport_mss[] = {MSM_BUS_SLAVE_PORT_MSS,};
+static int sport_lpass[] = {MSM_BUS_SLAVE_PORT_LPASS,};
+static int sport_mmss_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_MMSS_FPB,};
+
+static int tiered_slave_system_imem[] = {MSM_BUS_TIERED_SLAVE_SYSTEM_IMEM,};
+static int system_tiered_slave_fab_appss[] = {
+	MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS_0,
+};
+
+static struct msm_bus_node_info system_fabric_info[]  = {
+	{
+		.id = MSM_BUS_MASTER_SPS,
+		.masterp = mport_sps,
+		.num_mports = ARRAY_SIZE(mport_sps),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM_PORT0,
+		.masterp = mport_adm_port0,
+		.num_mports = ARRAY_SIZE(mport_adm_port0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM_PORT1,
+		.masterp = mport_adm_port1,
+		.num_mports = ARRAY_SIZE(mport_adm_port1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_LPASS_PROC,
+		.masterp = mport_lpass_proc,
+		.num_mports = ARRAY_SIZE(mport_lpass_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS,
+		.masterp = mport_mss,
+		.num_mports = ARRAY_SIZE(mport_mss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_RIVA,
+		.masterp = mport_riva,
+		.num_mports = ARRAY_SIZE(mport_riva),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS_SW_PROC,
+		.masterp = mport_mss_sw_proc,
+		.num_mports = ARRAY_SIZE(mport_mss_sw_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS_FW_PROC,
+		.masterp = mport_mss_fw_proc,
+		.num_mports = ARRAY_SIZE(mport_mss_fw_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_LPASS,
+		.masterp = mport_lpass,
+		.num_mports = ARRAY_SIZE(mport_lpass),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_SYSTEM_MASTER_MMSS_FPB,
+		.masterp = system_mport_mmss_fpb,
+		.num_mports = ARRAY_SIZE(system_mport_mmss_fpb),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM0_CI,
+		.masterp = system_mport_adm_ahb_ci,
+		.num_mports = ARRAY_SIZE(system_mport_adm_ahb_ci),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_FAB_APPSS,
+		.gateway = 1,
+		.slavep = system_sport_appss_fab,
+		.num_sports = ARRAY_SIZE(system_sport_appss_fab),
+		.masterp = appss_mport_fab_system,
+		.num_mports = ARRAY_SIZE(appss_mport_fab_system),
+		.tier = system_tiered_slave_fab_appss,
+		.num_tiers = ARRAY_SIZE(system_tiered_slave_fab_appss),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_FAB_SYSTEM_FPB,
+		.gateway = 1,
+		.slavep = system_sport_system_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_system_fpb),
+		.masterp = mport_system_fpb,
+		.num_mports = ARRAY_SIZE(mport_system_fpb),
+		.buswidth = 4,
+	},
+	{
+		.id = MSM_BUS_FAB_CPSS_FPB,
+		.gateway = 1,
+		.slavep = system_sport_cpss_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_cpss_fpb),
+		.masterp = system_mport_cpss_fpb,
+		.num_mports = ARRAY_SIZE(system_mport_cpss_fpb),
+		.buswidth = 4,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SPS,
+		.slavep = sport_sps,
+		.num_sports = ARRAY_SIZE(sport_sps),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
+		.slavep = sport_system_imem,
+		.num_sports = ARRAY_SIZE(sport_system_imem),
+		.tier = tiered_slave_system_imem,
+		.num_tiers = ARRAY_SIZE(tiered_slave_system_imem),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_CORESIGHT,
+		.slavep = sport_coresight,
+		.num_sports = ARRAY_SIZE(sport_coresight),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RIVA,
+		.slavep = sport_riva,
+		.num_sports = ARRAY_SIZE(sport_riva),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_AMPSS,
+		.slavep = sport_kmpss,
+		.num_sports = ARRAY_SIZE(sport_kmpss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSS,
+		.slavep = sport_mss,
+		.num_sports = ARRAY_SIZE(sport_mss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_LPASS,
+		.slavep = sport_lpass,
+		.num_sports = ARRAY_SIZE(sport_lpass),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SYSTEM_SLAVE_MMSS_FPB,
+		.slavep = sport_mmss_fpb,
+		.num_sports = ARRAY_SIZE(sport_mmss_fpb),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+};
+
+static int mport_mdp[] = {
+	MSM_BUS_MASTER_PORT_MDP_PORT0,
+	MSM_BUS_MASTER_PORT_MDP_PORT1,
+};
+static int mport_mdp1[] = {MSM_BUS_MASTER_PORT_MDP_PORT1,};
+static int mport_rotator[] = {MSM_BUS_MASTER_PORT_ROTATOR,};
+static int mport_graphics_3d[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D,};
+static int mport_vfe[] = {MSM_BUS_MASTER_PORT_VFE,};
+static int mport_vpe[] = {MSM_BUS_MASTER_PORT_VPE,};
+static int mport_jpeg_enc[] = {MSM_BUS_MASTER_PORT_JPEG_ENC,};
+static int mport_hd_codec_port0[] = {MSM_BUS_MASTER_PORT_HD_CODEC_PORT0,};
+static int mport_hd_codec_port1[] = {MSM_BUS_MASTER_PORT_HD_CODEC_PORT1,};
+static int appss_mport_fab_mmss[] = {
+	MSM_BUS_APPSS_MASTER_PORT_FAB_MMSS_0,
+};
+
+static int mmss_sport_apps_fab[] = {
+	MSM_BUS_MMSS_SLAVE_PORT_APPS_FAB_0,
+};
+static int sport_mm_imem[] = {MSM_BUS_SLAVE_PORT_MM_IMEM,};
+
+static int mmss_tiered_slave_fab_apps[] = {
+	MSM_BUS_MMSS_TIERED_SLAVE_FAB_APPS_0,
+};
+static int tiered_slave_mm_imem[] = {MSM_BUS_TIERED_SLAVE_MM_IMEM,};
+
+
+static struct msm_bus_node_info mmss_fabric_info[]  = {
+	{
+		.id = MSM_BUS_MASTER_MDP_PORT0,
+		.masterp = mport_mdp,
+		.num_mports = ARRAY_SIZE(mport_mdp),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MDP_PORT1,
+		.masterp = mport_mdp1,
+		.num_mports = ARRAY_SIZE(mport_mdp1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ROTATOR,
+		.masterp = mport_rotator,
+		.num_mports = ARRAY_SIZE(mport_rotator),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_GRAPHICS_3D,
+		.masterp = mport_graphics_3d,
+		.num_mports = ARRAY_SIZE(mport_graphics_3d),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_VFE,
+		.masterp = mport_vfe,
+		.num_mports = ARRAY_SIZE(mport_vfe),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_VPE,
+		.masterp = mport_vpe,
+		.num_mports = ARRAY_SIZE(mport_vpe),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_JPEG_ENC,
+		.masterp = mport_jpeg_enc,
+		.num_mports = ARRAY_SIZE(mport_jpeg_enc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_HD_CODEC_PORT0,
+		.masterp = mport_hd_codec_port0,
+		.num_mports = ARRAY_SIZE(mport_hd_codec_port0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_HD_CODEC_PORT1,
+		.masterp = mport_hd_codec_port1,
+		.num_mports = ARRAY_SIZE(mport_hd_codec_port1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_FAB_APPSS,
+		.gateway = 1,
+		.slavep = mmss_sport_apps_fab,
+		.num_sports = ARRAY_SIZE(mmss_sport_apps_fab),
+		.masterp = appss_mport_fab_mmss,
+		.num_mports = ARRAY_SIZE(appss_mport_fab_mmss),
+		.tier = mmss_tiered_slave_fab_apps,
+		.num_tiers = ARRAY_SIZE(mmss_tiered_slave_fab_apps),
+		.buswidth = 16,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MM_IMEM,
+		.slavep = sport_mm_imem,
+		.num_sports = ARRAY_SIZE(sport_mm_imem),
+		.tier = tiered_slave_mm_imem,
+		.num_tiers = ARRAY_SIZE(tiered_slave_mm_imem),
+		.buswidth = 8,
+	},
+};
+
+static struct msm_bus_node_info sys_fpb_fabric_info[]  = {
+	{
+		.id = MSM_BUS_FAB_SYSTEM,
+		.gateway = 1,
+		.slavep = system_sport_system_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_system_fpb),
+		.masterp = mport_system_fpb,
+		.num_mports = ARRAY_SIZE(mport_system_fpb),
+		.buswidth = 4,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_MASTER_SPDM,
+		.ahb = 1,
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_RPM,
+		.ahb = 1,
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_SLAVE_SPDM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RPM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RPM_MSG_RAM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MPM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC1_SSBI1_A,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC1_SSBI1_B,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC1_SSBI1_C,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC2_SSBI2_A,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC2_SSBI2_B,
+		.buswidth = 4,
+		.ahb = 1,
+	},
+};
+
+static struct msm_bus_node_info cpss_fpb_fabric_info[] = {
+	{
+		.id = MSM_BUS_FAB_SYSTEM,
+		.gateway = 1,
+		.slavep = system_sport_cpss_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_cpss_fpb),
+		.masterp = system_mport_cpss_fpb,
+		.num_mports = ARRAY_SIZE(system_mport_cpss_fpb),
+		.buswidth = 4,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI1_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI2_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI3_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI4_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI5_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI6_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI7_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI8_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI9_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI10_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI11_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI12_UART,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI1_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI2_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI3_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI4_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI5_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI6_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI7_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI8_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI9_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI10_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI11_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_GSBI12_QUP,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_NAND,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS0,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS1,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS2,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS3,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS4,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI2_CS5,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_USB_FS1,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_USB_FS2,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_TSIF,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_TSSC,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_PDM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_DIMEM,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_TCSR,
+		.buswidth = 8,
+		.ahb = 1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSM_PRNG,
+		.buswidth = 4,
+		.ahb = 1,
+	},
+};
+
+static void msm_bus_board_assign_iids(struct msm_bus_fabric_registration
+	*fabreg, int fabid)
+{
+	int i;
+	for (i = 0; i < fabreg->len; i++) {
+		if (!fabreg->info[i].gateway) {
+			fabreg->info[i].priv_id = fabid + fabreg->info[i].id;
+			if (fabreg->info[i].id < SLAVE_ID_KEY)
+				master_iids[fabreg->info[i].id] =
+					fabreg->info[i].priv_id;
+			else
+				slave_iids[fabreg->info[i].id - (SLAVE_ID_KEY)]
+					= fabreg->info[i].priv_id;
+		} else
+			fabreg->info[i].priv_id = fabreg->info[i].id;
+	}
+}
+
+static int msm_bus_board_8930_get_iid(int id)
+{
+	if ((id < SLAVE_ID_KEY && id >= NMASTERS) ||
+		id >= (SLAVE_ID_KEY + NSLAVES)) {
+		MSM_BUS_ERR("Cannot get iid. Invalid id %d passed\n", id);
+		return -EINVAL;
+	}
+
+	return CHECK_ID(((id < SLAVE_ID_KEY) ? master_iids[id] :
+		slave_iids[id - SLAVE_ID_KEY]), id);
+}
+
+static struct msm_bus_board_algorithm msm_bus_board_algo = {
+	.board_nfab = NFAB_8930,
+	.get_iid = msm_bus_board_8930_get_iid,
+	.assign_iids = msm_bus_board_assign_iids,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_apps_fabric_pdata = {
+	.id = MSM_BUS_FAB_APPSS,
+	.name = "msm_apps_fab",
+	.info = apps_fabric_info,
+	.len = ARRAY_SIZE(apps_fabric_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.haltid = MSM_RPM_ID_APPS_FABRIC_CFG_HALT_0,
+	.offset = MSM_RPM_ID_APPS_FABRIC_ARB_0,
+	.nmasters = 4,
+	.nslaves = 4,
+	.ntieredslaves = 2,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_sys_fabric_pdata = {
+	.id = MSM_BUS_FAB_SYSTEM,
+	.name = "msm_sys_fab",
+	system_fabric_info,
+	ARRAY_SIZE(system_fabric_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.haltid = MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0,
+	.offset = MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
+	.nmasters = 14,
+	.nslaves = 11,
+	.ntieredslaves = 2,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_mm_fabric_pdata = {
+	.id = MSM_BUS_FAB_MMSS,
+	.name = "msm_mm_fab",
+	mmss_fabric_info,
+	ARRAY_SIZE(mmss_fabric_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.haltid = MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
+	.offset = MSM_RPM_ID_MM_FABRIC_ARB_0,
+	.nmasters = 10,
+	.nslaves = 2,
+	.ntieredslaves = 2,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_sys_fpb_pdata = {
+	.id = MSM_BUS_FAB_SYSTEM_FPB,
+	.name = "msm_sys_fpb",
+	sys_fpb_fabric_info,
+	ARRAY_SIZE(sys_fpb_fabric_info),
+	.ahb = 1,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.nmasters = 0,
+	.nslaves = 0,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_8930_cpss_fpb_pdata = {
+	.id = MSM_BUS_FAB_CPSS_FPB,
+	.name = "msm_cpss_fpb",
+	cpss_fpb_fabric_info,
+	ARRAY_SIZE(cpss_fpb_fabric_info),
+	.ahb = 1,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.nmasters = 0,
+	.nslaves = 0,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+};
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index f93a79b..6e79dfe 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/memory_alloc.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -64,7 +65,6 @@
 #endif
 
 struct msm_rtb_state msm_rtb = {
-	.size = SZ_1M,
 	.filter = 1 << LOGK_LOGBUF,
 };
 
@@ -107,16 +107,6 @@
 	start->data = data;
 }
 
-static int __init msm_rtb_set_buffer_size(char *p)
-{
-	int s;
-
-	s = memparse(p, NULL);
-	msm_rtb.size = ALIGN(s, SZ_4K);
-	return 0;
-}
-early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-
 #if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
 static int msm_rtb_get_idx(void)
 {
@@ -178,12 +168,15 @@
 }
 EXPORT_SYMBOL(uncached_logk);
 
-int msm_rtb_init(void)
+int msm_rtb_probe(struct platform_device *pdev)
 {
+	struct msm_rtb_platform_data *d = pdev->dev.platform_data;
 #if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
 	unsigned int cpu;
 #endif
 
+	msm_rtb.size = d->size;
+
 	if (msm_rtb.size <= 0 || msm_rtb.size > SZ_1M)
 		return -EINVAL;
 
@@ -227,4 +220,22 @@
 	msm_rtb.enabled = 1;
 	return 0;
 }
+
+static struct platform_driver msm_rtb_driver = {
+	.driver         = {
+		.name = "msm_rtb",
+		.owner = THIS_MODULE
+	},
+};
+
+static int __init msm_rtb_init(void)
+{
+	return platform_driver_probe(&msm_rtb_driver, msm_rtb_probe);
+}
+
+static void __exit msm_rtb_exit(void)
+{
+	platform_driver_unregister(&msm_rtb_driver);
+}
 module_init(msm_rtb_init)
+module_exit(msm_rtb_exit)
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 6ec9b5d..2b4dae1 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -25,6 +25,7 @@
 
 #include <mach/msm_iomap.h>
 #include <mach/msm_xo.h>
+#include <mach/socinfo.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -142,13 +143,17 @@
 	writel_relaxed(A5_RESET, base + GSS_CSR_RESET);
 }
 
-static void setup_qgic2_bus_access(void *data)
+static void cfg_qgic2_bus_access(void *data)
 {
 	struct gss_data *drv = data;
-	void __iomem *base = drv->base;
 	int i;
 
-	writel_relaxed(0x2, base + GSS_CSR_CFG_HID);
+	/*
+	 * Apply a 8064 v1.0 workaround to configure QGIC bus access.
+	 * This must be done from Krait 0 to configure the Master ID
+	 * correctly.
+	 */
+	writel_relaxed(0x2, drv->base + GSS_CSR_CFG_HID);
 	for (i = 0; i <= 3; i++)
 		readl_relaxed(drv->qgic2_base);
 }
@@ -233,15 +238,15 @@
 	while (!(readl_relaxed(base + GSS_CSR_POWER_UP_DOWN) & A5_POWER_STATUS))
 		cpu_relax();
 
-	/*
-	 * Apply a 8064 v1.0 workaround to configure QGIC bus access. This must
-	 * be done from Krait 0 to configure the Master ID correctly.
-	 */
-	ret = smp_call_function_single(0, setup_qgic2_bus_access, drv, 1);
-	if (ret) {
-		pr_err("Failed to configure QGIC2 bus access\n");
-		pil_gss_shutdown(pil);
-		return ret;
+	if (cpu_is_apq8064() &&
+	    ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) &&
+	     (SOCINFO_VERSION_MINOR(socinfo_get_version()) == 0))) {
+		ret = smp_call_function_single(0, cfg_qgic2_bus_access, drv, 1);
+		if (ret) {
+			pr_err("Failed to configure QGIC2 bus access\n");
+			pil_gss_shutdown(pil);
+			return ret;
+		}
 	}
 
 	/* Release A5 from reset. */
@@ -263,6 +268,20 @@
 	return pas_init_image(PAS_GSS, metadata, size);
 }
 
+static int pil_gss_shutdown_trusted(struct pil_desc *pil)
+{
+	struct gss_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+
+	ret = pas_shutdown(PAS_GSS);
+	if (ret)
+		return ret;
+
+	remove_gss_proxy_votes_now(drv);
+
+	return ret;
+}
+
 static int pil_gss_reset_trusted(struct pil_desc *pil)
 {
 	struct gss_data *drv = dev_get_drvdata(pil->dev);
@@ -276,23 +295,26 @@
 	if (err)
 		remove_gss_proxy_votes_now(drv);
 
+	if (cpu_is_apq8064() &&
+	    ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) &&
+	     (SOCINFO_VERSION_MINOR(socinfo_get_version()) == 0))) {
+		err = smp_call_function_single(0, cfg_qgic2_bus_access, drv, 1);
+		if (err) {
+			pr_err("Failed to configure QGIC2 bus access\n");
+			pil_gss_shutdown_trusted(pil);
+			return err;
+		}
+		/*
+		 * On 8064v1.0, pas_auth_and_reset() will not release the A5
+		 * from reset. Linux must do this after cfg_qgic2_bus_access()
+		 * is called on CPU0.
+		 */
+		writel_relaxed(0x0, drv->base + GSS_CSR_RESET);
+	}
+
 	return err;
 }
 
-static int pil_gss_shutdown_trusted(struct pil_desc *pil)
-{
-	struct gss_data *drv = dev_get_drvdata(pil->dev);
-	int ret;
-
-	ret = pas_shutdown(PAS_GSS);
-	if (ret)
-		return ret;
-
-	remove_gss_proxy_votes_now(drv);
-
-	return ret;
-}
-
 static struct pil_reset_ops pil_gss_ops_trusted = {
 	.init_image = pil_gss_init_image_trusted,
 	.verify_blob = nop_verify_blob,
diff --git a/arch/arm/mach-msm/pil-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
index 511377d..b0bce02 100644
--- a/arch/arm/mach-msm/pil-q6v4.c
+++ b/arch/arm/mach-msm/pil-q6v4.c
@@ -29,11 +29,10 @@
 #include "pil-q6v4.h"
 #include "scm-pas.h"
 
-#define PROXY_VOTE_TIMEOUT	40000
+#define PROXY_VOTE_TIMEOUT	10000
 
 #define QDSP6SS_RST_EVB		0x0
 #define QDSP6SS_RESET		0x04
-#define QDSP6SS_CGC_OVERRIDE	0x18
 #define QDSP6SS_STRAP_TCM	0x1C
 #define QDSP6SS_STRAP_AHB	0x20
 #define QDSP6SS_GFMUX_CTL	0x30
@@ -62,7 +61,6 @@
 
 #define Q6SS_CLK_ENA		BIT(1)
 #define Q6SS_SRC_SWITCH_CLK_OVR	BIT(8)
-#define Q6SS_AXIS_ACLK_EN	BIT(9)
 
 struct q6v4_data {
 	void __iomem *base;
@@ -220,15 +218,6 @@
 	if (err)
 		dev_err(pil->dev, "Failed to unhalt bus port\n");
 
-	/*
-	 * Assert AXIS_ACLK_EN override to allow for correct updating of the
-	 * QDSP6_CORE_STATE status bit. This is mandatory only for the SW Q6
-	 * in 8960v1 and optional elsewhere.
-	 */
-	reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
-	reg |= Q6SS_AXIS_ACLK_EN;
-	writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);
-
 	/* Deassert Q6SS_SS_ARES */
 	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
 	reg &= ~(Q6SS_SS_ARES);
@@ -278,16 +267,6 @@
 	/* Bring Q6 core out of reset and start execution. */
 	writel_relaxed(0x0, drv->base + QDSP6SS_RESET);
 
-	/*
-	 * Re-enable auto-gating of AXIS_ACLK at lease one AXI clock cycle
-	 * after resets are de-asserted.
-	 */
-	mb();
-	usleep_range(1, 10);
-	reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
-	reg &= ~Q6SS_AXIS_ACLK_EN;
-	writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
new file mode 100644
index 0000000..534fc0e
--- /dev/null
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -0,0 +1,202 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/smp_scu.h>
+#include <asm/unified.h>
+#include <mach/msm_iomap.h>
+#include <mach/smp.h>
+#include "pm.h"
+
+#define MSM_CORE1_RESET		0xA8600590
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+int pen_release = -1;
+
+static bool cold_boot_done;
+
+static uint32_t *msm8625_boot_vector;
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void __cpuinit write_pen_release(int val)
+{
+	pen_release = val;
+	smp_wmb();
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static void __iomem *scu_base_addr(void)
+{
+	return MSM_SCU_BASE;
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_secondary_init(0);
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+	void __iomem *base_ptr;
+
+	if (cold_boot_done == false) {
+		base_ptr = ioremap_nocache(MSM_CORE1_RESET, SZ_4);
+		if (!base_ptr)
+			return -ENODEV;
+		/* Reset core 1 out of reset */
+		__raw_writel(0x0, base_ptr);
+		mb();
+		cold_boot_done = true;
+		iounmap(base_ptr);
+	}
+
+	/*
+	 * Set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * This is really belt and braces; we hold unintended secondary
+	 * CPUs in the holding pen until we're ready for them.  However,
+	 * since we haven't sent them a soft interrupt, they shouldn't
+	 * be there.
+	 */
+	write_pen_release(cpu);
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+	gic_raise_softirq(cpumask_of(cpu), 1);
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	void __iomem *scu_base = scu_base_addr();
+
+	unsigned int i, ncores;
+
+	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+static void __init msm8625_boot_vector_init(uint32_t *boot_vector,
+		unsigned long entry)
+{
+	if (!boot_vector)
+		return;
+	msm8625_boot_vector = boot_vector;
+
+	msm8625_boot_vector[0] = 0xE51FF004; /* ldr pc, 4 */
+	msm8625_boot_vector[1] = entry;
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i, value;
+	void __iomem *second_ptr;
+
+	/*
+	 * Initialise the present map, which describes the set of CPUs
+	 * actually populated at the present time.
+	 */
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+
+	scu_enable(scu_base_addr());
+
+	/*
+	 * Write the address of secondary startup into the
+	 * boot remapper register. The secondary CPU branches to this address.
+	 */
+	__raw_writel(MSM8625_SECONDARY_PHYS, (MSM_CFG_CTL_BASE + 0x34));
+	mb();
+
+	second_ptr = ioremap_nocache(MSM8625_SECONDARY_PHYS, SZ_8);
+	if (!second_ptr) {
+		pr_err("failed to ioremap for secondary core\n");
+		return;
+	}
+
+	msm8625_boot_vector_init(second_ptr,
+			virt_to_phys(msm_secondary_startup));
+	iounmap(second_ptr);
+
+	/* Enable boot remapper address: bit 26 for core1 */
+	value = __raw_readl(MSM_CFG_CTL_BASE + 0x30);
+	__raw_writel(value | (0x4 << 24), MSM_CFG_CTL_BASE + 0x30) ;
+	mb();
+}
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index e1934bb..7977d22 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1668,6 +1668,13 @@
 	.valid = suspend_valid_only_mem,
 };
 
+/* Hotplug the "non boot" CPU's and put
+ * the cores into low power mode
+ */
+void msm_pm_cpu_enter_lowpower(unsigned int cpu)
+{
+	return;
+}
 
 /******************************************************************************
  * Restart Definitions
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c b/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
index c38fefc..d43c961 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -76,6 +76,9 @@
 
 #define MASK_32BITS     0xFFFFFFFF
 
+#define MAX_BUF 4
+#define BUFSZ (524288)
+
 #define __CONTAINS(r, v, l) ({					\
 	typeof(r) __r = r;					\
 	typeof(v) __v = v;					\
@@ -1192,6 +1195,8 @@
 		audio->out_sample_rate = config.sample_rate;
 		audio->out_channel_mode = config.channel_count;
 		audio->out_bits = config.bits;
+		audio->buffer_count = config.buffer_count;
+		audio->buffer_size = config.buffer_size;
 		MM_DBG("AUDIO_SET_CONFIG: config.bits = %d\n", config.bits);
 		rc = 0;
 		break;
@@ -1199,7 +1204,8 @@
 
 	case AUDIO_GET_CONFIG:{
 		struct msm_audio_config config;
-		config.buffer_count = 2;
+		config.buffer_count = audio->buffer_count;
+		config.buffer_size = audio->buffer_size;
 		config.sample_rate = audio->out_sample_rate;
 		if (audio->out_channel_mode == AUDPP_CMD_PCM_INTF_MONO_V)
 			config.channel_count = 1;
@@ -1518,6 +1524,8 @@
 	dec_attrb |= audlpa_decs[audio->minor_no].dec_attrb;
 	audio->codec_ops.ioctl = audlpa_decs[audio->minor_no].ioctl;
 	audio->codec_ops.adec_params = audlpa_decs[audio->minor_no].adec_params;
+	audio->buffer_size = BUFSZ;
+	audio->buffer_count = MAX_BUF;
 
 	dec_attrb |= MSM_AUD_MODE_LP;
 
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 37428da..541f62f 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -505,12 +505,19 @@
 		return;
 	pr_debug("%s: handle[%p]\n", __func__, handle);
 
+	if (apr_reset_workqueue == NULL) {
+		pr_err("%s: apr_reset_workqueue is NULL\n", __func__);
+		return;
+	}
+
 	apr_reset_worker = kzalloc(sizeof(struct apr_reset_work),
-					GFP_ATOMIC);
-	if (apr_reset_worker == NULL || apr_reset_workqueue == NULL) {
+							GFP_ATOMIC);
+
+	if (apr_reset_worker == NULL) {
 		pr_err("%s: mem failure\n", __func__);
 		return;
 	}
+
 	apr_reset_worker->handle = handle;
 	INIT_WORK(&apr_reset_worker->work, apr_reset_deregister);
 	queue_work(apr_reset_workqueue, &apr_reset_worker->work);
diff --git a/arch/arm/mach-msm/qdss-ptm.c b/arch/arm/mach-msm/qdss-ptm.c
index 96a727a..c0dc58e 100644
--- a/arch/arm/mach-msm/qdss-ptm.c
+++ b/arch/arm/mach-msm/qdss-ptm.c
@@ -67,9 +67,9 @@
 #define ETMSQ12EVR		(0x180)
 #define ETMSQ21EVR		(0x184)
 #define ETMSQ23EVR		(0x188)
-#define ETMSQ32EVR		(0x18C)
-#define ETMSQ13EVR		(0x190)
-#define ETMSQ31EVR		(0x194)
+#define ETMSQ31EVR		(0x18C)
+#define ETMSQ32EVR		(0x190)
+#define ETMSQ13EVR		(0x194)
 #define ETMSQR			(0x19C)
 #define ETMEXTOUTEVRn(n)	(0x1A0 + (n * 4))
 #define ETMCIDCVRn(n)		(0x1B0 + (n * 4))
@@ -91,7 +91,7 @@
 #define ETMTSEVR		(0x1F8)
 #define ETMAUXCR		(0x1FC)
 #define ETMTRACEIDR		(0x200)
-#define ETMVMIDCVR		(0x204)
+#define ETMVMIDCVR		(0x240)
 /* Management registers (0x300-0x314) */
 #define ETMOSLAR		(0x300)
 #define ETMOSLSR		(0x304)
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index b95c3aa..bca1e0c 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -273,6 +273,38 @@
 #define MSM_TRIG_A2WCNSS_SMSM_INT
 #endif
 
+/*
+ * stub out legacy macros if they are not being used so that the legacy
+ * code compiles even though it is not used
+ *
+ * these definitions should not be used in active code and will cause
+ * an early failure
+ */
+#ifndef INT_A9_M2A_0
+#define INT_A9_M2A_0 -1
+#endif
+#ifndef INT_A9_M2A_5
+#define INT_A9_M2A_5 -1
+#endif
+#ifndef INT_ADSP_A11
+#define INT_ADSP_A11 -1
+#endif
+#ifndef INT_ADSP_A11_SMSM
+#define INT_ADSP_A11_SMSM -1
+#endif
+#ifndef INT_DSPS_A11
+#define INT_DSPS_A11 -1
+#endif
+#ifndef INT_DSPS_A11_SMSM
+#define INT_DSPS_A11_SMSM -1
+#endif
+#ifndef INT_WCNSS_A11
+#define INT_WCNSS_A11 -1
+#endif
+#ifndef INT_WCNSS_A11_SMSM
+#define INT_WCNSS_A11_SMSM -1
+#endif
+
 #define SMD_LOOPBACK_CID 100
 
 #define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 0ec88d5..a1bf280 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -218,6 +218,7 @@
 
 	/* 8064 IDs */
 	[109] = MSM_CPU_8064,
+	[130] = MSM_CPU_8064,
 
 	/* 8930 IDs */
 	[116] = MSM_CPU_8930,
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index 78fd922..b155781 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -65,12 +65,7 @@
 #elif defined(CONFIG_MSM_SPM_V2)
 
 enum {
-	MSM_SPM_REG_SAW2_SECURE,
-	MSM_SPM_REG_SAW2_ID,
 	MSM_SPM_REG_SAW2_CFG,
-	MSM_SPM_REG_SAW2_STS0,
-	MSM_SPM_REG_SAW2_STS1,
-	MSM_SPM_REG_SAW2_VCTL,
 	MSM_SPM_REG_SAW2_AVS_CTL,
 	MSM_SPM_REG_SAW2_AVS_HYSTERESIS,
 	MSM_SPM_REG_SAW2_SPM_CTL,
@@ -79,8 +74,13 @@
 	MSM_SPM_REG_SAW2_PMIC_DATA_1,
 	MSM_SPM_REG_SAW2_RST,
 
-	MSM_SPM_REG_NR_INITIALIZE,
-	MSM_SPM_REG_SAW2_SEQ_ENTRY = MSM_SPM_REG_NR_INITIALIZE,
+	MSM_SPM_REG_NR_INITIALIZE = MSM_SPM_REG_SAW2_RST,
+	MSM_SPM_REG_SAW2_ID,
+	MSM_SPM_REG_SAW2_SECURE,
+	MSM_SPM_REG_SAW2_STS0,
+	MSM_SPM_REG_SAW2_STS1,
+	MSM_SPM_REG_SAW2_VCTL,
+	MSM_SPM_REG_SAW2_SEQ_ENTRY ,
 
 	MSM_SPM_REG_NR
 };
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 07a9241..9970c90 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -122,9 +122,13 @@
 	if (pdev && pwlanconfig)
 		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
 					WCNSS_WLAN_SWITCH_ON);
-	if (!ret)
+	/* delay PIL operation, this SSR may be happening soon after kernel
+	 * resumes because of a SMSM RESET by Riva when APPS was suspended.
+	 * PIL fails to locate the images without this delay */
+	if (!ret) {
+		msleep(1000);
 		pil_force_boot("wcnss");
-
+	}
 	ss_restart_inprogress = false;
 	enable_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
 
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
old mode 100644
new mode 100755
index 7d2e44f..8dcce03
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1136,4 +1136,6 @@
 apq8064_cdp		MACH_APQ8064_CDP	APQ8064_CDP		3948
 apq8064_mtp		MACH_APQ8064_MTP	APQ8064_MTP		3949
 apq8064_liquid		MACH_APQ8064_LIQUID	APQ8064_LIQUID		3951
+mpq8064_hrd		MACH_MPQ8064_HRD	MPQ8064_HRD		3994
+mpq8064_dtv		MACH_MPQ8064_DTV	MPQ8064_DTV		3995
 msm7627a_qrd3		MACH_MSM7627A_QRD3	MSM7627A_QRD3		4005
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 851189d..58bf45d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@
 
 source "drivers/spi/Kconfig"
 
+source "drivers/spmi/Kconfig"
+
 source "drivers/slimbus/Kconfig"
 
 source "drivers/pps/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index e18822cd..82008ed 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -51,6 +51,7 @@
 obj-$(CONFIG_TARGET_CORE)	+= target/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
+obj-$(CONFIG_SPMI)		+= spmi/
 obj-$(CONFIG_SLIMBUS)		+= slimbus/
 obj-y				+= net/
 obj-$(CONFIG_ATM)		+= atm/
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index a9faff0..7d28604 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -128,6 +128,7 @@
 	struct diag_client_map *client_map;
 	int *data_ready;
 	int num_clients;
+	int polling_reg_flag;
 	struct diag_write_device *buf_tbl;
 
 	/* Memory pool parameters */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index a703148..e24d896 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -60,8 +60,8 @@
 static unsigned int max_clients = 15;
 static unsigned int threshold_client_limit = 30;
 /* This is the maximum number of pkt registrations supported at initialization*/
-unsigned int diag_max_registration = 500;
-unsigned int diag_threshold_registration = 650;
+unsigned int diag_max_registration = 600;
+unsigned int diag_threshold_registration = 750;
 
 /* Timer variables */
 static struct timer_list drain_timer;
@@ -256,15 +256,49 @@
 	return -ENOMEM;
 }
 
+int diag_find_polling_reg(int i)
+{
+	uint16_t subsys_id, cmd_code_lo, cmd_code_hi;
+
+	subsys_id = driver->table[i].subsys_id;
+	cmd_code_lo = driver->table[i].cmd_code_lo;
+	cmd_code_hi = driver->table[i].cmd_code_hi;
+	if (driver->table[i].cmd_code == 0x0C)
+		return 1;
+	else if (driver->table[i].cmd_code == 0xFF) {
+		if (subsys_id == 0x04 && cmd_code_hi == 0x0E &&
+			 cmd_code_lo == 0x0E)
+			return 1;
+		else if (subsys_id == 0x08 && cmd_code_hi == 0x02 &&
+			 cmd_code_lo == 0x02)
+			return 1;
+		else if (subsys_id == 0x32 && cmd_code_hi == 0x03  &&
+			 cmd_code_lo == 0x03)
+			return 1;
+	}
+	return 0;
+}
+
 void diag_clear_reg(int proc_num)
 {
 	int i;
 
+	mutex_lock(&driver->diagchar_mutex);
+	/* reset polling flag */
+	driver->polling_reg_flag = 0;
 	for (i = 0; i < diag_max_registration; i++) {
 		if (driver->table[i].client_id == proc_num) {
 			driver->table[i].process_id = 0;
 		}
 	}
+	/* re-scan the registration table */
+	for (i = 0; i < diag_max_registration; i++) {
+		if (diag_find_polling_reg(i) == 1) {
+			driver->polling_reg_flag = 1;
+			break;
+		}
+	}
+	mutex_unlock(&driver->diagchar_mutex);
 }
 
 void diag_add_reg(int j, struct bindpkt_params *params,
@@ -275,6 +309,11 @@
 	driver->table[j].subsys_id = params->subsys_id;
 	driver->table[j].cmd_code_lo = params->cmd_code_lo;
 	driver->table[j].cmd_code_hi = params->cmd_code_hi;
+
+	/* check if incoming reg is polling & polling is yet not registered */
+	if (driver->polling_reg_flag == 0)
+		if (diag_find_polling_reg(j) == 1)
+			driver->polling_reg_flag = 1;
 	if (params->proc_id == APPS_PROC) {
 		driver->table[j].process_id = current->tgid;
 		driver->table[j].client_id = APPS_PROC;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 07322cd..079e04b 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -891,8 +891,8 @@
 	/* Check for polling for Apps only DIAG */
 	else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
 		(*(buf+2) == 0x03)) {
-		/* If there is NO MODEM present */
-		if (!(driver->ch)) {
+		/* If no one has registered for polling */
+		if (!(driver->polling_reg_flag)) {
 			/* Respond to polling for Apps only DIAG */
 			for (i = 0; i < 3; i++)
 				driver->apps_rsp_buf[i] = *(buf+i);
@@ -901,13 +901,10 @@
 
 			ENCODE_RSP_AND_SEND(15);
 			return 0;
-		} else {
-			/* Since Modem is present, send error response */
-			return 1;
 		}
 	}
 	 /* Check for ID for NO MODEM present */
-	else if (!(driver->ch)) {
+	else if (!(driver->polling_reg_flag)) {
 		/* respond to 0x0 command */
 		if (*buf == 0x00) {
 			for (i = 0; i < 55; i++)
@@ -1041,9 +1038,9 @@
 	queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
 	queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
 	/* Poll SMD CNTL channels to check for data */
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_cntl_work));
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_cntl_work));
+	diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
+	diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
+	diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
 	/* Poll USB channel to check for data*/
 	queue_work(driver->diag_wq, &(driver->diag_read_work));
 #ifdef CONFIG_DIAG_SDIO_PIPE
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index df2cd65..2c3dc54 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -19,6 +19,66 @@
 
 #define HDR_SIZ 8
 
+void diag_smd_cntl_notify(void *ctxt, unsigned event)
+{
+	int r1, r2;
+
+	if (!(driver->ch_cntl))
+		return;
+
+	switch (event) {
+	case SMD_EVENT_DATA:
+		r1 = smd_read_avail(driver->ch_cntl);
+		r2 = smd_cur_packet_size(driver->ch_cntl);
+		if (r1 > 0 && r1 == r2)
+			queue_work(driver->diag_wq,
+				 &(driver->diag_read_smd_cntl_work));
+		else
+			pr_debug("diag: incomplete pkt on Modem CNTL ch\n");
+		break;
+	}
+}
+
+void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event)
+{
+	int r1, r2;
+
+	if (!(driver->chqdsp_cntl))
+		return;
+
+	switch (event) {
+	case SMD_EVENT_DATA:
+		r1 = smd_read_avail(driver->chqdsp_cntl);
+		r2 = smd_cur_packet_size(driver->chqdsp_cntl);
+		if (r1 > 0 && r1 == r2)
+			queue_work(driver->diag_wq,
+				 &(driver->diag_read_smd_qdsp_cntl_work));
+		else
+			pr_debug("diag: incomplete pkt on LPASS CNTL ch\n");
+		break;
+	}
+}
+
+void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event)
+{
+	int r1, r2;
+
+	if (!(driver->ch_wcnss_cntl))
+		return;
+
+	switch (event) {
+	case SMD_EVENT_DATA:
+		r1 = smd_read_avail(driver->ch_wcnss_cntl);
+		r2 = smd_cur_packet_size(driver->ch_wcnss_cntl);
+		if (r1 > 0 && r1 == r2)
+			queue_work(driver->diag_wq,
+				 &(driver->diag_read_smd_wcnss_cntl_work));
+		else
+			pr_debug("diag: incomplete pkt on WCNSS CNTL ch\n");
+		break;
+	}
+}
+
 static void diag_smd_cntl_send_req(int proc_num)
 {
 	int data_len = 0, type = -1, count_bytes = 0, j, r, flag = 0;
@@ -30,6 +90,11 @@
 	void *buf = NULL;
 	smd_channel_t *smd_ch = NULL;
 
+	if (pkt_params == NULL) {
+		pr_alert("diag: Memory allocation failure\n");
+		return;
+	}
+
 	if (proc_num == MODEM_PROC) {
 		buf = driver->buf_in_cntl;
 		smd_ch = driver->ch_cntl;
@@ -62,6 +127,17 @@
 		while (count_bytes + HDR_SIZ <= r) {
 			type = *(uint32_t *)(buf);
 			data_len = *(uint32_t *)(buf + 4);
+			if (type < DIAG_CTRL_MSG_REG ||
+					 type > DIAG_CTRL_MSG_F3_MASK_V2) {
+				pr_alert("diag: Invalid Msg type %d proc %d",
+					 type, proc_num);
+				break;
+			}
+			if (data_len < 0 || data_len > r) {
+				pr_alert("diag: Invalid data len %d proc %d",
+					 data_len, proc_num);
+				break;
+			}
 			count_bytes = count_bytes+HDR_SIZ+data_len;
 			if (type == DIAG_CTRL_MSG_REG && r >= count_bytes) {
 				msg = buf+HDR_SIZ;
@@ -70,6 +146,10 @@
 				pkt_params->count = msg->count_entries;
 				temp = kzalloc(pkt_params->count * sizeof(struct
 						 bindpkt_params), GFP_KERNEL);
+				if (temp == NULL) {
+					pr_alert("diag: Memory alloc fail\n");
+					return;
+				}
 				for (j = 0; j < pkt_params->count; j++) {
 					temp->cmd_code = msg->cmd_code;
 					temp->subsys_id = msg->subsysid;
@@ -93,11 +173,12 @@
 	kfree(pkt_params);
 	if (flag) {
 		/* Poll SMD CNTL channels to check for data */
-		queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
-		queue_work(driver->diag_wq,
-			 &(driver->diag_read_smd_qdsp_cntl_work));
-		queue_work(driver->diag_wq,
-			 &(driver->diag_read_smd_wcnss_cntl_work));
+		if (proc_num == MODEM_PROC)
+			diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
+		else if (proc_num == QDSP_PROC)
+			diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
+		else if (proc_num == WCNSS_PROC)
+			diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
 	}
 }
 
@@ -116,21 +197,6 @@
 	diag_smd_cntl_send_req(WCNSS_PROC);
 }
 
-static void diag_smd_cntl_notify(void *ctxt, unsigned event)
-{
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
-}
-
-static void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event)
-{
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_cntl_work));
-}
-
-static void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event)
-{
-	queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_cntl_work));
-}
-
 static int diag_smd_cntl_probe(struct platform_device *pdev)
 {
 	int r = 0;
@@ -192,6 +258,7 @@
 
 void diagfwd_cntl_init(void)
 {
+	driver->polling_reg_flag = 0;
 	if (driver->buf_in_cntl == NULL) {
 		driver->buf_in_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_cntl == NULL)
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 542138d..a76d36d 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,26 @@
 #ifndef DIAGFWD_CNTL_H
 #define DIAGFWD_CNTL_H
 
-#define DIAG_CTRL_MSG_REG 1	/* Message registration commands */
+/* Message registration commands */
+#define DIAG_CTRL_MSG_REG		1
+/* Message passing for DTR events */
+#define DIAG_CTRL_MSG_DTR		2
+/* Control Diag sleep vote, buffering etc */
+#define DIAG_CTRL_MSG_DIAGMODE		3
+/* Diag data based on "light" diag mask */
+#define DIAG_CTRL_MSG_DIAGDATA		4
+/* Deprecated */
+#define DIAG_CTRL_MSG_LOG_MASK		5
+#define DIAG_CTRL_MSG_EVENT_MASK	6
+#define DIAG_CTRL_MSG_F3_MASK		7
+/* Send diag internal feature mask 'diag_int_feature_mask' */
+#define DIAG_CTRL_MSG_FEATURE		8
+/* Send Diag log mask for a particular equip id */
+#define DIAG_CTRL_MSG_EQUIP_LOG_MASK	9
+/* Send Diag event mask */
+#define DIAG_CTRL_MSG_EVENT_MASK_V2	10
+/* Send Diag F3 mask */
+#define DIAG_CTRL_MSG_F3_MASK_V2	11
 
 struct cmd_code_range {
 	uint16_t cmd_code_lo;
@@ -34,5 +53,8 @@
 void diag_read_smd_cntl_work_fn(struct work_struct *);
 void diag_read_smd_qdsp_cntl_work_fn(struct work_struct *);
 void diag_read_smd_wcnss_cntl_work_fn(struct work_struct *);
+void diag_smd_cntl_notify(void *ctxt, unsigned event);
+void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event);
+void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event);
 
 #endif
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index d725851..5276bcc 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto Engine driver.
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011 - 2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@
 #define DST_INDEX_SG_CMD(index) (index & 0x3fff)
 #define ADM_DESC_LAST  (1 << 31)
 #define QCE_FIFO_SIZE  0x8000
+
 /*
  * CE HW device structure.
  * Each engine has an instance of the structure.
@@ -128,6 +129,7 @@
 {
 	unsigned int val;
 	unsigned int rev;
+	unsigned int ret;
 
 	val = (uint32_t)(*((uint32_t *)pce_dev->ce_dm.buffer.version));
 	if (((val & 0xfffffff) != 0x0000043) &&
@@ -144,6 +146,23 @@
 				"Qualcomm Crypto 4.2 device found at 0x%x\n",
 				pce_dev->phy_iobase);
 		pce_dev->ce_dm.ce_block_size = 64;
+
+		/* Configure the crypto register to support 64byte CRCI if it
+		 * is not XPU protected and the HW version of device is greater
+		 * than 0x42.
+		 * Crypto config register returns a 0 when it is XPU protected.
+		 */
+
+		ret = readl_relaxed(pce_dev->iobase + CRYPTO_CONFIG_REG);
+		if (ret) {
+			val = (CRYPTO_REQ_SIZE_ENUM_64_BYTES <<
+					CRYPTO_REQ_SIZE) |
+				(CRYPTO_FIFO_ENUM_64_BYTES <<
+					CRYPTO_FIFO_THRESHOLD);
+
+			writel_relaxed(val, pce_dev->iobase +
+					CRYPTO_CONFIG_REG);
+		} /* end of if (ret) */
 	} else {
 		if (rev == 0x40) {
 			dev_info(pce_dev->pdev,
@@ -152,12 +171,6 @@
 			pce_dev->ce_dm.ce_block_size = 16;
 		}
 	}
-	/*
-	* This is a temporary change - until Data Mover changes its
-	* configuration from 16 byte crci to 64 byte crci.
-	*/
-	if (cpu_is_msm9615())
-		pce_dev->ce_dm.ce_block_size = 16;
 
 	dev_info(pce_dev->pdev,
 			"IO base 0x%x\n, ce_in channel %d     , "
@@ -2609,4 +2622,4 @@
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Mona Hossain <mhossain@codeaurora.org>");
 MODULE_DESCRIPTION("Crypto Engine driver");
-MODULE_VERSION("2.14");
+MODULE_VERSION("2.15");
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 2a2892e..a81dbd3 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -91,7 +91,7 @@
 				const struct fmem_data *fmem_info =
 					fmem_get_info();
 				heap->base = fmem_info->phys -
-					     fmem_info->reserved_size;
+					     fmem_info->reserved_size_low;
 				cp_data->virt_addr = fmem_info->virt;
 				pr_info("ION heap %s using FMEM\n",
 							shared_heap->name);
@@ -159,6 +159,10 @@
 				heap->base = fmem_info->phys;
 				data->virt_addr = fmem_info->virt;
 				pr_info("ION heap %s using FMEM\n", heap->name);
+			} else if (data->mem_is_fmem) {
+				const struct fmem_data *fmem_info =
+					fmem_get_info();
+				heap->base = fmem_info->phys + fmem_info->size;
 			}
 			align = data->align;
 			break;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 06f4a14..79a0e0b 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -978,15 +978,6 @@
 	}
 	mutex_unlock(&kgsl_driver.process_mutex);
 
-	BUG_ON(!mutex_is_locked(&device->mutex));
-	list_for_each_entry(entry, &device->memqueue, list) {
-		if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, size)) {
-			result = &entry->memdesc;
-			return result;
-		}
-
-	}
-
 	while (1) {
 		struct adreno_context *adreno_context = NULL;
 		context = idr_get_next(&device->context_idr, &next);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index caedf26..0361387 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -64,7 +64,7 @@
 
 #define GSL_RB_WRITE(ring, gpuaddr, data) \
 	do { \
-		writel_relaxed(data, ring); \
+		*ring = data; \
 		wmb(); \
 		kgsl_cffdump_setmem(gpuaddr, data, 4); \
 		ring++; \
@@ -93,7 +93,7 @@
 #define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */
 #define GSL_RB_GET_READPTR(rb, data) \
 	do { \
-		*(data) = readl_relaxed(&(rb)->memptrs->rptr); \
+		*(data) = rb->memptrs->rptr; \
 	} while (0)
 #else
 #define GSL_RB_CNTL_NO_UPDATE 0x1 /* disable */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1a0a17d..120b129 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -49,20 +49,20 @@
 
 static struct ion_client *kgsl_ion_client;
 
-#ifdef CONFIG_GENLOCK
-
 /**
  * kgsl_add_event - Add a new timstamp event for the KGSL device
  * @device - KGSL device for the new event
  * @ts - the timestamp to trigger the event on
  * @cb - callback function to call when the timestamp expires
  * @priv - private data for the specific event type
+ * @owner - driver instance that owns this event
  *
  * @returns - 0 on success or error code on failure
  */
 
 static int kgsl_add_event(struct kgsl_device *device, u32 ts,
-	void (*cb)(struct kgsl_device *, void *, u32), void *priv)
+	void (*cb)(struct kgsl_device *, void *, u32), void *priv,
+	struct kgsl_device_private *owner)
 {
 	struct kgsl_event *event;
 	struct list_head *n;
@@ -86,6 +86,7 @@
 	event->timestamp = ts;
 	event->priv = priv;
 	event->func = cb;
+	event->owner = owner;
 
 	/* Add the event in order to the list */
 
@@ -105,7 +106,36 @@
 	queue_work(device->work_queue, &device->ts_expired_ws);
 	return 0;
 }
-#endif
+
+/**
+ * kgsl_cancel_events - Cancel all events for a process
+ * @device - KGSL device for the events to cancel
+ * @owner - driver instance that owns the events to cancel
+ *
+ */
+static void kgsl_cancel_events(struct kgsl_device *device,
+	struct kgsl_device_private *owner)
+{
+	struct kgsl_event *event, *event_tmp;
+	unsigned int cur = device->ftbl->readtimestamp(device,
+		KGSL_TIMESTAMP_RETIRED);
+
+	list_for_each_entry_safe(event, event_tmp, &device->events, list) {
+		if (event->owner != owner)
+			continue;
+		/*
+		 * "cancel" the events by calling their callback.
+		 * Currently, events are used for lock and memory
+		 * management, so if the process is dying the right
+		 * thing to do is release or free.
+		 */
+		if (event->func)
+			event->func(device, event->priv, cur);
+
+		list_del(&event->list);
+		kfree(event);
+	}
+}
 
 static inline struct kgsl_mem_entry *
 kgsl_mem_entry_create(void)
@@ -227,44 +257,10 @@
 	idr_remove(&dev_priv->device->context_idr, id);
 }
 
-/* to be called when a process is destroyed, this walks the memqueue and
- * frees any entryies that belong to the dying process
- */
-static void kgsl_memqueue_cleanup(struct kgsl_device *device,
-				     struct kgsl_process_private *private)
-{
-	struct kgsl_mem_entry *entry, *entry_tmp;
-
-	if (!private)
-		return;
-
-	BUG_ON(!mutex_is_locked(&device->mutex));
-
-	list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) {
-		if (entry->priv == private) {
-			list_del(&entry->list);
-			kgsl_mem_entry_put(entry);
-		}
-	}
-}
-
-static void kgsl_memqueue_freememontimestamp(struct kgsl_device *device,
-				  struct kgsl_mem_entry *entry,
-				  uint32_t timestamp,
-				  enum kgsl_timestamp_type type)
-{
-	BUG_ON(!mutex_is_locked(&device->mutex));
-
-	entry->free_timestamp = timestamp;
-
-	list_add_tail(&entry->list, &device->memqueue);
-}
-
 static void kgsl_timestamp_expired(struct work_struct *work)
 {
 	struct kgsl_device *device = container_of(work, struct kgsl_device,
 		ts_expired_ws);
-	struct kgsl_mem_entry *entry, *entry_tmp;
 	struct kgsl_event *event, *event_tmp;
 	uint32_t ts_processed;
 
@@ -274,15 +270,6 @@
 	ts_processed = device->ftbl->readtimestamp(device,
 		KGSL_TIMESTAMP_RETIRED);
 
-	/* Flush the freememontimestamp queue */
-	list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) {
-		if (timestamp_cmp(ts_processed, entry->free_timestamp) < 0)
-			break;
-
-		list_del(&entry->list);
-		kgsl_mem_entry_put(entry);
-	}
-
 	/* Process expired events */
 	list_for_each_entry_safe(event, event_tmp, &device->events, list) {
 		if (timestamp_cmp(ts_processed, event->timestamp) < 0)
@@ -652,7 +639,7 @@
 	/* clean up any to-be-freed entries that belong to this
 	 * process and this device
 	 */
-	kgsl_memqueue_cleanup(device, private);
+	kgsl_cancel_events(device, dev_priv);
 
 	mutex_unlock(&device->mutex);
 	kfree(dev_priv);
@@ -997,6 +984,16 @@
 	return 0;
 }
 
+static void kgsl_freemem_event_cb(struct kgsl_device *device,
+	void *priv, u32 timestamp)
+{
+	struct kgsl_mem_entry *entry = priv;
+	spin_lock(&entry->priv->mem_lock);
+	list_del(&entry->list);
+	spin_unlock(&entry->priv->mem_lock);
+	kgsl_mem_entry_put(entry);
+}
+
 static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private
 						    *dev_priv, unsigned int cmd,
 						    void *data)
@@ -1007,13 +1004,11 @@
 
 	spin_lock(&dev_priv->process_priv->mem_lock);
 	entry = kgsl_sharedmem_find(dev_priv->process_priv, param->gpuaddr);
-	if (entry)
-		list_del(&entry->list);
 	spin_unlock(&dev_priv->process_priv->mem_lock);
 
 	if (entry) {
-		kgsl_memqueue_freememontimestamp(dev_priv->device, entry,
-					param->timestamp, param->type);
+		result = kgsl_add_event(dev_priv->device, param->timestamp,
+					kgsl_freemem_event_cb, entry, dev_priv);
 	} else {
 		KGSL_DRV_ERR(dev_priv->device,
 			"invalid gpuaddr %08x\n", param->gpuaddr);
@@ -1763,6 +1758,7 @@
  * @timestamp - Timestamp to trigger the event
  * @data - User space buffer containing struct kgsl_genlock_event_priv
  * @len - length of the userspace buffer
+ * @owner - driver instance that owns this event
  * @returns 0 on success or error code on error
  *
  * Attack to a genlock handle and register an event to release the
@@ -1770,7 +1766,8 @@
  */
 
 static int kgsl_add_genlock_event(struct kgsl_device *device,
-	u32 timestamp, void __user *data, int len)
+	u32 timestamp, void __user *data, int len,
+	struct kgsl_device_private *owner)
 {
 	struct kgsl_genlock_event_priv *event;
 	struct kgsl_timestamp_event_genlock priv;
@@ -1795,7 +1792,8 @@
 		return ret;
 	}
 
-	ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event);
+	ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event,
+			     owner);
 	if (ret)
 		kfree(event);
 
@@ -1803,7 +1801,8 @@
 }
 #else
 static long kgsl_add_genlock_event(struct kgsl_device *device,
-	u32 timestamp, void __user *data, int len)
+	u32 timestamp, void __user *data, int len,
+	struct kgsl_device_private *owner)
 {
 	return -EINVAL;
 }
@@ -1826,7 +1825,8 @@
 	switch (param->type) {
 	case KGSL_TIMESTAMP_EVENT_GENLOCK:
 		ret = kgsl_add_genlock_event(dev_priv->device,
-			param->timestamp, param->priv, param->len);
+			param->timestamp, param->priv, param->len,
+			dev_priv);
 		break;
 	default:
 		ret = -EINVAL;
@@ -2183,7 +2183,6 @@
 	INIT_WORK(&device->idle_check_ws, kgsl_idle_check);
 	INIT_WORK(&device->ts_expired_ws, kgsl_timestamp_expired);
 
-	INIT_LIST_HEAD(&device->memqueue);
 	INIT_LIST_HEAD(&device->events);
 
 	ret = kgsl_mmu_init(device);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 8ea5279..2fb1e43 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -126,6 +126,7 @@
 	void (*func)(struct kgsl_device *, void *, u32);
 	void *priv;
 	struct list_head list;
+	struct kgsl_device_private *owner;
 };
 
 
@@ -154,7 +155,6 @@
 	uint32_t state;
 	uint32_t requested_state;
 
-	struct list_head memqueue;
 	unsigned int active_cnt;
 	struct completion suspend_gate;
 
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index fe5677e..a16b954 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -382,15 +382,16 @@
 kgsl_pt_map_set(struct kgsl_gpummu_pt *pt, uint32_t pte, uint32_t val)
 {
 	uint32_t *baseptr = (uint32_t *)pt->base.hostptr;
-
-	writel_relaxed(val, &baseptr[pte]);
+	BUG_ON(pte*sizeof(uint32_t) >= pt->base.size);
+	baseptr[pte] = val;
 }
 
 static inline uint32_t
 kgsl_pt_map_get(struct kgsl_gpummu_pt *pt, uint32_t pte)
 {
 	uint32_t *baseptr = (uint32_t *)pt->base.hostptr;
-	return readl_relaxed(&baseptr[pte]) & GSL_PT_PAGE_ADDR_MASK;
+	BUG_ON(pte*sizeof(uint32_t) >= pt->base.size);
+	return baseptr[pte] & GSL_PT_PAGE_ADDR_MASK;
 }
 
 static unsigned int kgsl_gpummu_pt_get_flags(struct kgsl_pagetable *pt,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 1ef71a4..ae50183 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -66,8 +66,17 @@
 		struct kgsl_pwrlevel *pwrlevel = &pwr->pwrlevels[new_level];
 		pwr->active_pwrlevel = new_level;
 		if ((test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags)) ||
-			(device->state == KGSL_STATE_NAP))
+			(device->state == KGSL_STATE_NAP)) {
+			/*
+			 * On some platforms, instability is caused on
+			 * changing clock freq when the core is busy.
+			 * Idle the gpu core before changing the clock freq.
+			 */
+			if (pwr->idle_needed == true)
+				device->ftbl->idle(device,
+						KGSL_TIMEOUT_DEFAULT);
 			clk_set_rate(pwr->grp_clks[0], pwrlevel->gpu_freq);
+		}
 		if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) {
 			if (pwr->pcl)
 				msm_bus_scale_client_update_request(pwr->pcl,
@@ -499,6 +508,7 @@
 	pwr->power_flags = 0;
 
 	pwr->nap_allowed = pdata->nap_allowed;
+	pwr->idle_needed = pdata->idle_needed;
 	pwr->interval_timeout = pdata->idle_timeout;
 	pwr->ebi1_clk = clk_get(&pdev->dev, "bus_clk");
 	if (IS_ERR(pwr->ebi1_clk))
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 23e2bd1..99dbae9 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -50,6 +50,7 @@
 	struct regulator *gpu_reg;
 	uint32_t pcl;
 	unsigned int nap_allowed;
+	unsigned int idle_needed;
 	const char *regulator_name;
 	const char *irq_name;
 	s64 time;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 7211879..389ed6d 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -636,13 +636,17 @@
 			uint32_t *dst,
 			unsigned int offsetbytes)
 {
+	uint32_t *src;
 	BUG_ON(memdesc == NULL || memdesc->hostptr == NULL || dst == NULL);
-	WARN_ON(offsetbytes + sizeof(unsigned int) > memdesc->size);
+	WARN_ON(offsetbytes % sizeof(uint32_t) != 0);
+	if (offsetbytes % sizeof(uint32_t) != 0)
+		return -EINVAL;
 
-	if (offsetbytes + sizeof(unsigned int) > memdesc->size)
+	WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
+	if (offsetbytes + sizeof(uint32_t) > memdesc->size)
 		return -ERANGE;
-
-	*dst = readl_relaxed(memdesc->hostptr + offsetbytes);
+	src = (uint32_t *)(memdesc->hostptr + offsetbytes);
+	*dst = *src;
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_sharedmem_readl);
@@ -652,12 +656,19 @@
 			unsigned int offsetbytes,
 			uint32_t src)
 {
+	uint32_t *dst;
 	BUG_ON(memdesc == NULL || memdesc->hostptr == NULL);
-	BUG_ON(offsetbytes + sizeof(unsigned int) > memdesc->size);
+	WARN_ON(offsetbytes % sizeof(uint32_t) != 0);
+	if (offsetbytes % sizeof(uint32_t) != 0)
+		return -EINVAL;
 
+	WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
+	if (offsetbytes + sizeof(uint32_t) > memdesc->size)
+		return -ERANGE;
 	kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes,
-		src, sizeof(uint));
-	writel_relaxed(src, memdesc->hostptr + offsetbytes);
+		src, sizeof(uint32_t));
+	dst = (uint32_t *)(memdesc->hostptr + offsetbytes);
+	*dst = src;
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_sharedmem_writel);
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index c8b4707..4988313 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -324,13 +324,13 @@
 {
 	dev->clk_state = state;
 	if (state != 0) {
-		clk_prepare_enable(dev->clk);
-		clk_prepare_enable(dev->pclk);
+		clk_enable(dev->clk);
+		clk_enable(dev->pclk);
 	} else {
 		qup_update_state(dev, QUP_RESET_STATE);
-		clk_disable_unprepare(dev->clk);
+		clk_disable(dev->clk);
 		qup_config_core_on_en(dev);
-		clk_disable_unprepare(dev->pclk);
+		clk_disable(dev->pclk);
 	}
 }
 
@@ -1285,6 +1285,8 @@
 	dev->suspended = 0;
 	mutex_init(&dev->mlock);
 	dev->clk_state = 0;
+	clk_prepare(dev->clk);
+	clk_prepare(dev->pclk);
 	setup_timer(&dev->pwr_timer, qup_i2c_pwr_timer, (unsigned long) dev);
 
 	pm_runtime_set_active(&pdev->dev);
@@ -1344,6 +1346,8 @@
 	}
 	free_irq(dev->err_irq, dev);
 	i2c_del_adapter(&dev->adapter);
+	clk_unprepare(dev->clk);
+	clk_unprepare(dev->pclk);
 	clk_put(dev->clk);
 	clk_put(dev->pclk);
 	qup_i2c_free_gpios(dev);
@@ -1378,6 +1382,8 @@
 	del_timer_sync(&dev->pwr_timer);
 	if (dev->clk_state != 0)
 		qup_i2c_pwr_mgmt(dev, 0);
+	clk_unprepare(dev->clk);
+	clk_unprepare(dev->pclk);
 	qup_i2c_free_gpios(dev);
 	return 0;
 }
@@ -1387,6 +1393,8 @@
 	struct platform_device *pdev = to_platform_device(device);
 	struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
 	BUG_ON(qup_i2c_request_gpios(dev) != 0);
+	clk_prepare(dev->clk);
+	clk_prepare(dev->pclk);
 	dev->suspended = 0;
 	return 0;
 }
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index d2a8879..40aae69 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -18,7 +18,7 @@
 #include <linux/firmware.h>
 #include <linux/i2c.h>
 #include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
@@ -611,22 +611,23 @@
 		if (!finger[id].status)
 			continue;
 
-		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
-				finger[id].status != MXT_RELEASE ?
-				finger[id].area : 0);
-		input_report_abs(input_dev, ABS_MT_POSITION_X,
-				finger[id].x);
-		input_report_abs(input_dev, ABS_MT_POSITION_Y,
-				finger[id].y);
-		input_report_abs(input_dev, ABS_MT_PRESSURE,
-				finger[id].status != MXT_RELEASE ?
-				finger[id].pressure : 0);
-		input_mt_sync(input_dev);
+		input_mt_slot(input_dev, id);
+		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+				finger[id].status != MXT_RELEASE);
 
-		if (finger[id].status == MXT_RELEASE)
-			finger[id].status = 0;
-		else
+		if (finger[id].status != MXT_RELEASE) {
 			finger_num++;
+			input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+					finger[id].area);
+			input_report_abs(input_dev, ABS_MT_POSITION_X,
+					finger[id].x);
+			input_report_abs(input_dev, ABS_MT_POSITION_Y,
+					finger[id].y);
+			input_report_abs(input_dev, ABS_MT_PRESSURE,
+					finger[id].area);
+		} else {
+			finger[id].status = 0;
+		}
 	}
 
 	input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
@@ -1841,6 +1842,7 @@
 			     0, 255, 0, 0);
 
 	/* For multi touch */
+	input_mt_init_slots(input_dev, MXT_MAX_FINGER);
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			     0, MXT_MAX_AREA, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
diff --git a/drivers/input/touchscreen/cyttsp-i2c.c b/drivers/input/touchscreen/cyttsp-i2c.c
index a60dbf5..267e481 100644
--- a/drivers/input/touchscreen/cyttsp-i2c.c
+++ b/drivers/input/touchscreen/cyttsp-i2c.c
@@ -710,25 +710,26 @@
 	else if (!(g_bl_data.bl_status & BL_CHECKSUM_MASK) &&
 			(appid_lo == ts->platform_data->correct_fw_ver))
 		fw_upgrade = 1;
-	else
-		if ((appid_hi == g_bl_data.appid_hi) &&
-			(appid_lo == g_bl_data.appid_lo)) {
-			if (appver_hi > g_bl_data.appver_hi) {
+	else if ((appid_hi == g_bl_data.appid_hi) &&
+			(appid_lo == g_bl_data.appid_lo))
+			if (appver_hi > g_bl_data.appver_hi)
 				fw_upgrade = 1;
-			} else if ((appver_hi == g_bl_data.appver_hi) &&
-					 (appver_lo > g_bl_data.appver_lo)) {
-					fw_upgrade = 1;
-				} else {
-					fw_upgrade = 0;
-					pr_info("%s: Firmware version "
-					"lesser/equal to existing firmware, "
-					"upgrade not needed\n", __func__);
-				}
-		} else {
-			fw_upgrade = 0;
-			pr_info("%s: Firware versions do not match, "
-						"cannot upgrade\n", __func__);
-		}
+			else if ((appver_hi == g_bl_data.appver_hi) &&
+					 (appver_lo > g_bl_data.appver_lo))
+				fw_upgrade = 1;
+			else {
+				fw_upgrade = 0;
+				pr_info("%s: Firmware version "
+				"lesser/equal to existing firmware, "
+				"upgrade not needed\n", __func__);
+			}
+	else if (appid_lo == ts->platform_data->correct_fw_ver)
+		fw_upgrade = 1;
+	else {
+		fw_upgrade = 0;
+		pr_info("%s: Firmware versions do not match, "
+					"cannot upgrade\n", __func__);
+	}
 
 	if (fw_upgrade) {
 		pr_info("%s: Starting firmware upgrade\n", __func__);
diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c
index 57b11c9..ed6ab4d 100644
--- a/drivers/media/radio/radio-iris-transport.c
+++ b/drivers/media/radio/radio-iris-transport.c
@@ -4,7 +4,7 @@
  *  FM HCI_SMD ( FM HCI Shared Memory Driver) is Qualcomm's Shared memory driver
  *  for the HCI protocol. This file is based on drivers/bluetooth/hci_vhci.c
  *
- *  Copyright (c) 2000-2001, 2011 Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2000-2001, 2011-2012 Code Aurora Forum. All rights reserved.
  *
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
  *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
@@ -25,6 +25,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
+#include <linux/workqueue.h>
 #include <mach/msm_smd.h>
 #include <media/radio-iris.h>
 
@@ -35,6 +36,8 @@
 };
 struct radio_data hs;
 
+static struct work_struct *reset_worker;
+
 static void radio_hci_smd_destruct(struct radio_hci_dev *hdev)
 {
 	radio_hci_unregister_dev(hs.hdev);
@@ -92,6 +95,30 @@
 	return 0;
 }
 
+
+static void send_disable_event(struct work_struct *worker)
+{
+	struct sk_buff *skb;
+	unsigned char buf[6] = { 0x0f, 0x04, 0x01, 0x02, 0x4c, 0x00 };
+	int len = sizeof(buf);
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (!skb) {
+		FMDERR("Memory not allocated for the socket");
+		return;
+	}
+
+	FMDERR("FM INSERT DISABLE Rx Event");
+
+	memcpy(skb_put(skb, len), buf, len);
+
+	skb_orphan(skb);
+	skb->dev = (struct net_device   *)hs.hdev;
+
+	radio_hci_recv_frame(skb);
+	kfree(worker);
+}
+
 static void radio_hci_smd_notify_cmd(void *data, unsigned int event)
 {
 	struct radio_hci_dev *hdev = hs.hdev;
@@ -106,7 +133,15 @@
 		tasklet_schedule(&hs.rx_task);
 		break;
 	case SMD_EVENT_OPEN:
+		break;
 	case SMD_EVENT_CLOSE:
+		reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC);
+		if (!reset_worker) {
+			FMDERR("Out of memory");
+			break;
+		}
+		INIT_WORK(reset_worker, send_disable_event);
+		schedule_work(reset_worker);
 		break;
 	default:
 		break;
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 545c61c..476300c 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -1589,7 +1589,7 @@
 	if (status)
 		return;
 
-	iris_q_event(radio, IRIS_EVT_RADIO_READY);
+	iris_q_event(radio, IRIS_EVT_RADIO_DISABLED);
 
 	radio_hci_req_complete(hdev, status);
 }
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index ca44c34..e70a0a5 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -33,8 +33,7 @@
 	  MICRON 2M YUV Sensor
 config IMX074
 	bool "Sensor IMX074 (BAYER 13.5M)"
-	depends on MSM_CAMERA && (ARCH_MSM8X60 || ARCH_MSM8960)
-	default y
+	depends on MSM_CAMERA
 	---help---
 	SONY 13.5 MP Bayer Sensor
 config OV5640
@@ -43,6 +42,12 @@
 	default n
 	---help---
 	Omni 5M YUV Sensor
+
+config OV5647
+	bool "Sensor ov5647 (BAYER 5M)"
+	depends on MSM_CAMERA
+	---help---
+	  OV 5M Bayer Sensor with AutoFocus
 config WEBCAM_OV7692_QRD
 	bool "Sensor OV7692 QRD(VGA YUV)"
 	depends on MSM_CAMERA && ARCH_MSM7X27A && !MSM_CAMERA_V4L2
@@ -51,7 +56,7 @@
 	  Omni Vision VGA YUV Sensor for QRD Devices
 config MT9M114
         bool "Sensor MT9M114 (YUV 1.26M)"
-        depends on MSM_CAMERA && ARCH_MSM8960
+        depends on MSM_CAMERA
         ---help---
         APTINA 1.26 MP yuv Sensor
 config WEBCAM_OV7692
@@ -120,8 +125,7 @@
 
 config IMX074_ACT
 	bool "Actuator IMX074 (BAYER 13.5M)"
-	depends on MSM_CAMERA && ARCH_MSM8960
-	default y
+	depends on MSM_CAMERA
 	---help---
 	Actuator for SONY 13.5 MP Bayer Sensor
 
@@ -177,8 +181,7 @@
 
 config OV2720
 	bool "Sensor ov2720 (Omnivision 2MP)"
-	depends on MSM_CAMERA && ARCH_MSM8960
-	default y
+	depends on MSM_CAMERA
 
 config VB6801
 	bool "Sensor vb6801"
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index b91449a..8703669 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -44,6 +44,8 @@
 obj-$(CONFIG_QS_S5K4E1) += qs_s5k4e1.o qs_s5k4e1_reg.o
 obj-$(CONFIG_VB6801) += vb6801.o
 obj-$(CONFIG_IMX072) += imx072.o imx072_reg.o
+obj-$(CONFIG_WEBCAM_OV9726) += ov9726.o ov9726_reg.o
+obj-$(CONFIG_OV5647) += ov5647.o ov5647_reg.o
 obj-$(CONFIG_WEBCAM_OV7692) += ov7692.o
 obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd.o
 obj-$(CONFIG_OV5640) += ov5640.o
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
index e4d340d4..fab3a21 100644
--- a/drivers/media/video/msm/actuators/imx074_act.c
+++ b/drivers/media/video/msm/actuators/imx074_act.c
@@ -197,6 +197,11 @@
 		(struct v4l2_subdev *)sdev);
 }
 
+static int imx074_act_power_down(void *act_info)
+{
+	return (int) msm_actuator_af_power_down(&imx074_act_t);
+}
+
 static struct msm_actuator_ctrl_t imx074_act_t = {
 	.i2c_driver = &imx074_act_i2c_driver,
 	.i2c_addr = 0xE4,
@@ -205,6 +210,7 @@
 		.a_init_table = imx074_i2c_add_driver_table,
 		.a_create_subdevice = imx074_act_create_subdevice,
 		.a_config = imx074_act_config,
+		.a_power_down = imx074_act_power_down,
 	},
 
 	.i2c_client = {
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index 109b3dd..315cca7 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -79,21 +79,14 @@
 	msm_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
 
 	for (i = 0; i < csiphy_params->lane_cnt; i++) {
-		msm_io_w(0x00, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
-		msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+		msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
 		msm_io_w(csiphy_params->settle_cnt,
 			csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*i);
-		msm_io_w(0x00000052,
-			csiphybase + MIPI_CSIPHY_LNn_CFG5_ADDR + 0x40*i);
 	}
 
-	msm_io_w(0x00000000, csiphybase + MIPI_CSIPHY_LNCK_CFG1_ADDR);
-	msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+	msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
 	msm_io_w(csiphy_params->settle_cnt,
 			 csiphybase + MIPI_CSIPHY_LNCK_CFG3_ADDR);
-	msm_io_w(0x5, csiphybase + MIPI_CSIPHY_LNCK_CFG4_ADDR);
-	msm_io_w(0x2, csiphybase + MIPI_CSIPHY_LNCK_CFG5_ADDR);
-	msm_io_w(0x0, csiphybase + 0x128);
 
 	msm_io_w(0x24,
 		csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR);
diff --git a/drivers/media/video/msm/io/Makefile b/drivers/media/video/msm/io/Makefile
index 584738d..c567be2 100644
--- a/drivers/media/video/msm/io/Makefile
+++ b/drivers/media/video/msm/io/Makefile
@@ -1,3 +1,4 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_eeprom.o
+EXTRA_CFLAGS += -Idrivers/media/video/msm
+obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_eeprom.o msm_camera_i2c_mux.o
 obj-$(CONFIG_MSM_CAMERA) += msm_io_util.o
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.c b/drivers/media/video/msm/io/msm_camera_i2c_mux.c
new file mode 100644
index 0000000..ad3128b
--- /dev/null
+++ b/drivers/media/video/msm/io/msm_camera_i2c_mux.c
@@ -0,0 +1,186 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include "msm.h"
+#include "msm_camera_i2c_mux.h"
+
+static int msm_i2c_mux_config(struct i2c_mux_device *mux_device, uint8_t *mode)
+{
+	uint32_t val;
+	val = msm_io_r(mux_device->ctl_base);
+	if (*mode == MODE_DUAL) {
+		msm_io_w(val | 0x3, mux_device->ctl_base);
+	} else if (*mode == MODE_L) {
+		msm_io_w(((val | 0x2) & ~(0x1)), mux_device->ctl_base);
+		val = msm_io_r(mux_device->ctl_base);
+		CDBG("the camio mode config left value is %d\n", val);
+	} else {
+		msm_io_w(((val | 0x1) & ~(0x2)), mux_device->ctl_base);
+		val = msm_io_r(mux_device->ctl_base);
+		CDBG("the camio mode config right value is %d\n", val);
+	}
+	return 0;
+}
+
+static int msm_i2c_mux_init(struct i2c_mux_device *mux_device)
+{
+	int rc = 0, val = 0;
+	if (mux_device->use_count == 0) {
+		mux_device->ctl_base = ioremap(mux_device->ctl_mem->start,
+			resource_size(mux_device->ctl_mem));
+		if (!mux_device->ctl_base) {
+			rc = -ENOMEM;
+			return rc;
+		}
+		mux_device->rw_base = ioremap(mux_device->rw_mem->start,
+			resource_size(mux_device->rw_mem));
+		if (!mux_device->rw_base) {
+			rc = -ENOMEM;
+			iounmap(mux_device->ctl_base);
+			return rc;
+		}
+		val = msm_io_r(mux_device->rw_base);
+		msm_io_w((val | 0x200), mux_device->rw_base);
+	}
+	mux_device->use_count++;
+	return 0;
+};
+
+static int msm_i2c_mux_release(struct i2c_mux_device *mux_device)
+{
+	int val = 0;
+	mux_device->use_count--;
+	if (mux_device->use_count == 0) {
+		val = msm_io_r(mux_device->rw_base);
+		msm_io_w((val & ~0x200), mux_device->rw_base);
+		iounmap(mux_device->rw_base);
+		iounmap(mux_device->ctl_base);
+	}
+	return 0;
+}
+
+static long msm_i2c_mux_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct i2c_mux_device *mux_device;
+	int rc = 0;
+	mux_device = v4l2_get_subdevdata(sd);
+	if (mux_device == NULL) {
+		rc = -ENOMEM;
+		return rc;
+	}
+	mutex_lock(&mux_device->mutex);
+	switch (cmd) {
+	case VIDIOC_MSM_I2C_MUX_CFG:
+		rc = msm_i2c_mux_config(mux_device, (uint8_t *) arg);
+		break;
+	case VIDIOC_MSM_I2C_MUX_INIT:
+		rc = msm_i2c_mux_init(mux_device);
+		break;
+	case VIDIOC_MSM_I2C_MUX_RELEASE:
+		rc = msm_i2c_mux_release(mux_device);
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+	}
+	mutex_unlock(&mux_device->mutex);
+	return rc;
+}
+
+static struct v4l2_subdev_core_ops msm_i2c_mux_subdev_core_ops = {
+	.ioctl = &msm_i2c_mux_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_i2c_mux_subdev_ops = {
+	.core = &msm_i2c_mux_subdev_core_ops,
+};
+
+static int __devinit i2c_mux_probe(struct platform_device *pdev)
+{
+	struct i2c_mux_device *mux_device;
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	mux_device = kzalloc(sizeof(struct i2c_mux_device), GFP_KERNEL);
+	if (!mux_device) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&mux_device->subdev, &msm_i2c_mux_subdev_ops);
+	v4l2_set_subdevdata(&mux_device->subdev, mux_device);
+	platform_set_drvdata(pdev, &mux_device->subdev);
+	mutex_init(&mux_device->mutex);
+
+	mux_device->ctl_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "i2c_mux_ctl");
+	if (!mux_device->ctl_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->ctl_io = request_mem_region(mux_device->ctl_mem->start,
+		resource_size(mux_device->ctl_mem), pdev->name);
+	if (!mux_device->ctl_io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->rw_mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "i2c_mux_rw");
+	if (!mux_device->rw_mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->rw_io = request_mem_region(mux_device->rw_mem->start,
+		resource_size(mux_device->rw_mem), pdev->name);
+	if (!mux_device->rw_io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto i2c_mux_no_resource;
+	}
+	mux_device->pdev = pdev;
+	return 0;
+
+i2c_mux_no_resource:
+	mutex_destroy(&mux_device->mutex);
+	kfree(mux_device);
+	return 0;
+}
+
+static struct platform_driver i2c_mux_driver = {
+	.probe = i2c_mux_probe,
+	.driver = {
+		.name = MSM_I2C_MUX_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_camera_i2c_mux_init_module(void)
+{
+	return platform_driver_register(&i2c_mux_driver);
+}
+
+static void __exit msm_camera_i2c_mux_exit_module(void)
+{
+	platform_driver_unregister(&i2c_mux_driver);
+}
+
+module_init(msm_camera_i2c_mux_init_module);
+module_exit(msm_camera_i2c_mux_exit_module);
+MODULE_DESCRIPTION("MSM Camera I2C mux driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/io/msm_camera_i2c_mux.h b/drivers/media/video/msm/io/msm_camera_i2c_mux.h
new file mode 100644
index 0000000..94394fc
--- /dev/null
+++ b/drivers/media/video/msm/io/msm_camera_i2c_mux.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_I2C_MUX_H
+#define MSM_I2C_MUX_H
+
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct i2c_mux_device {
+	struct platform_device *pdev;
+	struct v4l2_subdev subdev;
+	struct resource *ctl_mem;
+	struct resource *ctl_io;
+	void __iomem *ctl_base;
+	struct resource *rw_mem;
+	struct resource *rw_io;
+	void __iomem *rw_base;
+	struct mutex mutex;
+	unsigned use_count;
+};
+
+struct i2c_mux_cfg_params {
+	struct v4l2_subdev *subdev;
+	void *parms;
+};
+
+#define VIDIOC_MSM_I2C_MUX_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct i2c_mux_cfg_params)
+
+#define VIDIOC_MSM_I2C_MUX_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 14, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_I2C_MUX_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct v4l2_subdev*)
+
+#endif
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index ed77185..84d441d 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -157,7 +157,7 @@
 	D("Waiting for config status\n");
 	rc = wait_event_interruptible_timeout(queue->wait,
 		!list_empty_careful(&queue->list),
-		out->timeout_ms);
+		msecs_to_jiffies(out->timeout_ms));
 	D("Waiting is over for config status\n");
 	if (list_empty_careful(&queue->list)) {
 		if (!rc)
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 40bc160..55c0da1 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -48,6 +48,7 @@
 #define MSM_VFE_DRV_NAME "msm_vfe"
 #define MSM_VPE_DRV_NAME "msm_vpe"
 #define MSM_GEMINI_DRV_NAME "msm_gemini"
+#define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
 
 /* msm queue management APIs*/
 
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index d111452..ea969cf 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -32,11 +32,6 @@
 static struct clk *camio_imem_clk;
 static struct regulator *fs_ijpeg;
 
-static struct platform_device *camio_dev;
-static struct resource *s3drw_io, *s3dctl_io;
-static struct resource *s3drw_mem, *s3dctl_mem;
-void __iomem *s3d_rw, *s3d_ctl;
-
 void msm_io_w(u32 data, void __iomem *addr)
 {
 	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
@@ -234,89 +229,6 @@
 	return rc;
 }
 
-int32_t msm_camio_3d_enable(const struct msm_camera_sensor_info *s_info)
-{
-	int32_t val = 0, rc = 0;
-	char s3drw[] = "s3d_rw";
-	char s3dctl[] = "s3d_ctl";
-	struct platform_device *pdev = camio_dev;
-	pdev->resource = s_info->resource;
-	pdev->num_resources = s_info->num_resources;
-
-	s3drw_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, s3drw);
-	if (!s3drw_mem) {
-		pr_err("%s: no mem resource?\n", __func__);
-		return -ENODEV;
-	}
-	s3dctl_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, s3dctl);
-	if (!s3dctl_mem) {
-		pr_err("%s: no mem resource?\n", __func__);
-		return -ENODEV;
-	}
-	s3drw_io = request_mem_region(s3drw_mem->start,
-		resource_size(s3drw_mem), pdev->name);
-	if (!s3drw_io)
-		return -EBUSY;
-
-	s3d_rw = ioremap(s3drw_mem->start,
-		resource_size(s3drw_mem));
-	if (!s3d_rw) {
-		rc = -ENOMEM;
-		goto s3drw_nomem;
-	}
-	s3dctl_io = request_mem_region(s3dctl_mem->start,
-		resource_size(s3dctl_mem), pdev->name);
-	if (!s3dctl_io) {
-		rc = -EBUSY;
-		goto s3dctl_busy;
-	}
-	s3d_ctl = ioremap(s3dctl_mem->start,
-		resource_size(s3dctl_mem));
-	if (!s3d_ctl) {
-		rc = -ENOMEM;
-		goto s3dctl_nomem;
-	}
-
-	val = msm_io_r(s3d_rw);
-	msm_io_w((val | 0x200), s3d_rw);
-	return rc;
-
-s3dctl_nomem:
-	release_mem_region(s3dctl_mem->start, resource_size(s3dctl_mem));
-s3dctl_busy:
-	iounmap(s3d_rw);
-s3drw_nomem:
-	release_mem_region(s3drw_mem->start, resource_size(s3drw_mem));
-return rc;
-}
-
-void msm_camio_3d_disable(void)
-{
-	int32_t val = 0;
-	msm_io_w((val & ~0x200), s3d_rw);
-	iounmap(s3d_ctl);
-	release_mem_region(s3dctl_mem->start, resource_size(s3dctl_mem));
-	iounmap(s3d_rw);
-	release_mem_region(s3drw_mem->start, resource_size(s3drw_mem));
-}
-
-void msm_camio_mode_config(enum msm_cam_mode mode)
-{
-	uint32_t val;
-	val = msm_io_r(s3d_ctl);
-	if (mode == MODE_DUAL) {
-		msm_io_w(val | 0x3, s3d_ctl);
-	} else if (mode == MODE_L) {
-		msm_io_w(((val | 0x2) & ~(0x1)), s3d_ctl);
-		val = msm_io_r(s3d_ctl);
-		CDBG("the camio mode config left value is %d\n", val);
-	} else {
-		msm_io_w(((val | 0x1) & ~(0x2)), s3d_ctl);
-		val = msm_io_r(s3d_ctl);
-		CDBG("the camio mode config right value is %d\n", val);
-	}
-}
-
 void msm_camio_bus_scale_cfg(struct msm_bus_scale_pdata *cam_bus_scale_table,
 		enum msm_bus_perf_setting perf_setting)
 {
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 89bdf0f..b539d19 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -598,6 +598,14 @@
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CFG);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_MODULE_CFG);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_PIXEL_IF_CFG);
+	if (msm_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
+		VFE33_HW_NUMBER) {
+		msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI0_CFG);
+		msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI1_CFG);
+	}  else {
+		++p;
+		++p;
+	}
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_REALIGN_BUF);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CHROMA_UP);
 	msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_STATS_CFG);
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 62c3639..0d8be58 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -223,7 +223,7 @@
 #define V32_OUT_CLAMP_OFF         0x00000524
 #define V32_OUT_CLAMP_LEN         8
 
-#define V32_OPERATION_CFG_LEN     36
+#define V32_OPERATION_CFG_LEN     44
 
 #define V32_AXI_OUT_OFF           0x00000038
 #define V32_AXI_OUT_LEN           216
@@ -875,6 +875,9 @@
 #define VFE_DMI_DATA_LO                 0x000005A4
 #define VFE_BUS_IO_FORMAT_CFG           0x000006F8
 #define VFE_PIXEL_IF_CFG                0x000006FC
+#define VFE_RDI0_CFG                    0x00000734
+#define VFE_RDI1_CFG                    0x000007A4
+
 #define VFE_VIOLATION_STATUS            0x000007B4
 
 #define VFE33_DMI_DATA_HI               0x000005A0
diff --git a/drivers/media/video/msm/ov5647.c b/drivers/media/video/msm/ov5647.c
new file mode 100644
index 0000000..2a6e7be
--- /dev/null
+++ b/drivers/media/video/msm/ov5647.c
@@ -0,0 +1,1201 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/bitops.h>
+#include <linux/leds.h>
+#include <mach/camera.h>
+#include <media/msm_camera.h>
+#include "ov5647.h"
+
+/* 16bit address - 8 bit context register structure */
+#define Q8	0x00000100
+#define Q10	0x00000400
+
+#define REG_OV5647_GAIN_MSB           0x350A
+#define REG_OV5647_GAIN_LSB           0x350B
+#define REG_OV5647_LINE_HSB           0x3500
+#define REG_OV5647_LINE_MSB           0x3501
+#define REG_OV5647_LINE_LSB           0x3502
+
+/* MCLK */
+#define OV5647_MASTER_CLK_RATE 24000000
+
+/* AF Total steps parameters */
+#define OV5647_TOTAL_STEPS_NEAR_TO_FAR	32
+
+#define OV5647_REG_PREV_FRAME_LEN_1	31
+#define OV5647_REG_PREV_FRAME_LEN_2	32
+#define OV5647_REG_PREV_LINE_LEN_1	33
+#define OV5647_REG_PREV_LINE_LEN_2	34
+
+#define OV5647_REG_SNAP_FRAME_LEN_1	15
+#define OV5647_REG_SNAP_FRAME_LEN_2	16
+#define OV5647_REG_SNAP_LINE_LEN_1	17
+#define OV5647_REG_SNAP_LINE_LEN_2	18
+#define MSB                             1
+#define LSB                             0
+
+/* Debug switch */
+#ifdef CDBG
+#undef CDBG
+#endif
+#ifdef CDBG_HIGH
+#undef CDBG_HIGH
+#endif
+
+/*#define OV5647_VERBOSE_DGB*/
+
+#ifdef OV5647_VERBOSE_DGB
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#define CDBG_HIGH(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#define CDBG_HIGH(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+/*for debug*/
+#ifdef CDBG
+#undef CDBG
+#endif
+#define CDBG(fmt, args...) printk(fmt, ##args)
+
+static uint8_t  mode_mask = 0x09;
+struct ov5647_work_t {
+	struct work_struct work;
+};
+
+static struct ov5647_work_t *ov5647_sensorw;
+static struct ov5647_work_t *ov5647_af_sensorw;
+static struct i2c_client *ov5647_af_client;
+static struct i2c_client *ov5647_client;
+
+struct ov5647_ctrl_t {
+	const struct  msm_camera_sensor_info *sensordata;
+
+	uint32_t sensormode;
+	uint32_t fps_divider;/* init to 1 * 0x00000400 */
+	uint32_t pict_fps_divider;/* init to 1 * 0x00000400 */
+	uint16_t fps;
+
+	uint16_t curr_lens_pos;
+	uint16_t curr_step_pos;
+	uint16_t my_reg_gain;
+	uint32_t my_reg_line_count;
+	uint16_t total_lines_per_frame;
+
+	enum ov5647_resolution_t prev_res;
+	enum ov5647_resolution_t pict_res;
+	enum ov5647_resolution_t curr_res;
+	enum ov5647_test_mode_t  set_test;
+};
+
+static bool CSI_CONFIG;
+static struct ov5647_ctrl_t *ov5647_ctrl;
+
+static DECLARE_WAIT_QUEUE_HEAD(ov5647_wait_queue);
+static DECLARE_WAIT_QUEUE_HEAD(ov5647_af_wait_queue);
+DEFINE_MUTEX(ov5647_mut);
+
+static uint16_t prev_line_length_pck;
+static uint16_t prev_frame_length_lines;
+static uint16_t snap_line_length_pck;
+static uint16_t snap_frame_length_lines;
+
+static int ov5647_i2c_rxdata(unsigned short saddr,
+		unsigned char *rxdata, int length)
+{
+	struct i2c_msg msgs[] = {
+		{
+			.addr  = saddr,
+			.flags = 0,
+			.len   = 2,
+			.buf   = rxdata,
+		},
+		{
+			.addr  = saddr,
+			.flags = I2C_M_RD,
+			.len   = 1,
+			.buf   = rxdata,
+		},
+	};
+	if (i2c_transfer(ov5647_client->adapter, msgs, 2) < 0) {
+		CDBG("ov5647_i2c_rxdata faild 0x%x\n", saddr);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int32_t ov5647_i2c_txdata(unsigned short saddr,
+		unsigned char *txdata, int length)
+{
+	struct i2c_msg msg[] = {
+		{
+			.addr = saddr,
+			.flags = 0,
+			.len = length,
+			.buf = txdata,
+		},
+	};
+	if (i2c_transfer(ov5647_client->adapter, msg, 1) < 0) {
+		CDBG("ov5647_i2c_txdata faild 0x%x\n", saddr);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int32_t ov5647_i2c_read(unsigned short raddr,
+		unsigned short *rdata)
+{
+	int32_t rc = 0;
+	unsigned char buf[2];
+
+	if (!rdata)
+		return -EIO;
+	CDBG("%s:saddr:0x%x raddr:0x%x data:0x%x",
+		__func__, ov5647_client->addr, raddr, *rdata);
+	memset(buf, 0, sizeof(buf));
+	buf[0] = (raddr & 0xFF00) >> 8;
+	buf[1] = (raddr & 0x00FF);
+	rc = ov5647_i2c_rxdata(ov5647_client->addr >> 1, buf, 1);
+	if (rc < 0) {
+		CDBG("ov5647_i2c_read 0x%x failed!\n", raddr);
+		return rc;
+	}
+	*rdata = buf[0];
+	CDBG("ov5647_i2c_read 0x%x val = 0x%x!\n", raddr, *rdata);
+
+	return rc;
+}
+
+static int32_t ov5647_i2c_write_b_sensor(unsigned short waddr, uint8_t bdata)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[3];
+
+	memset(buf, 0, sizeof(buf));
+	buf[0] = (waddr & 0xFF00) >> 8;
+	buf[1] = (waddr & 0x00FF);
+	buf[2] = bdata;
+	CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
+	rc = ov5647_i2c_txdata(ov5647_client->addr >> 1, buf, 3);
+	if (rc < 0) {
+		pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+				waddr, bdata);
+	}
+	return rc;
+}
+
+static int32_t ov5647_i2c_write_b_table(struct ov5647_i2c_reg_conf const
+		*reg_conf_tbl, int num)
+{
+	int i;
+	int32_t rc = -EIO;
+
+	for (i = 0; i < num; i++) {
+		rc = ov5647_i2c_write_b_sensor(reg_conf_tbl->waddr,
+				reg_conf_tbl->wdata);
+		if (rc < 0)
+			break;
+		reg_conf_tbl++;
+	}
+	return rc;
+}
+
+static int32_t ov5647_af_i2c_txdata(unsigned short saddr,
+		unsigned char *txdata, int length)
+{
+	struct i2c_msg msg[] = {
+		{
+			.addr = saddr,
+			.flags = 0,
+			.len = length,
+			.buf = txdata,
+		},
+	};
+	if (i2c_transfer(ov5647_af_client->adapter, msg, 1) < 0) {
+		pr_err("ov5647_af_i2c_txdata faild 0x%x\n", saddr);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int32_t ov5647_af_i2c_write_b_sensor(uint8_t waddr, uint8_t bdata)
+{
+	int32_t rc = -EFAULT;
+	unsigned char buf[2];
+
+	memset(buf, 0, sizeof(buf));
+	buf[0] = waddr;
+	buf[1] = bdata;
+	CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
+	rc = ov5647_af_i2c_txdata(ov5647_af_client->addr, buf, 2);
+	if (rc < 0) {
+		pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
+				waddr, bdata);
+	}
+	return rc;
+}
+
+static void ov5647_start_stream(void)
+{
+	CDBG("CAMERA_DBG: 0x4202 0x0, stream on...\r\n");
+	ov5647_i2c_write_b_sensor(0x4202, 0x00);/* streaming on */
+}
+
+static void ov5647_stop_stream(void)
+{
+	CDBG("CAMERA_DBG: 0x4202 0xf, stream off...\r\n");
+	ov5647_i2c_write_b_sensor(0x4202, 0x0f);/* streaming off */
+}
+
+static void ov5647_group_hold_on(void)
+{
+	ov5647_i2c_write_b_sensor(0x0104, 0x01);
+}
+
+static void ov5647_group_hold_off(void)
+{
+	ov5647_i2c_write_b_sensor(0x0104, 0x0);
+}
+
+static void ov5647_get_pict_fps(uint16_t fps, uint16_t *pfps)
+{
+	/* input fps is preview fps in Q8 format */
+	uint32_t divider, d1, d2;
+	uint32_t preview_pclk = 0x37, snapshot_pclk = 0x4f;
+
+	d1 = (prev_frame_length_lines * 0x00000400) / snap_frame_length_lines;
+	d2 = (prev_line_length_pck * 0x00000400) / snap_line_length_pck;
+	divider = (d1 * d2*preview_pclk/snapshot_pclk) / 0x400;
+	CDBG(KERN_ERR "ov5647_get_pict_fps divider = %d", divider);
+	/*Verify PCLK settings and frame sizes.*/
+	*pfps = (uint16_t) (fps * divider / 0x400);
+}
+
+static uint16_t ov5647_get_prev_lines_pf(void)
+{
+	if (ov5647_ctrl->prev_res == QTR_SIZE)
+		return prev_frame_length_lines;
+	else
+		return snap_frame_length_lines;
+}
+
+static uint16_t ov5647_get_prev_pixels_pl(void)
+{
+	if (ov5647_ctrl->prev_res == QTR_SIZE)
+		return prev_line_length_pck;
+	else
+		return snap_line_length_pck;
+}
+
+static uint16_t ov5647_get_pict_lines_pf(void)
+{
+	if (ov5647_ctrl->pict_res == QTR_SIZE)
+		return prev_frame_length_lines;
+	else
+		return snap_frame_length_lines;
+}
+
+static uint16_t ov5647_get_pict_pixels_pl(void)
+{
+	if (ov5647_ctrl->pict_res == QTR_SIZE)
+		return prev_line_length_pck;
+	else
+		return snap_line_length_pck;
+}
+
+static uint32_t ov5647_get_pict_max_exp_lc(void)
+{
+	return snap_frame_length_lines * 24;
+}
+
+static int32_t ov5647_set_fps(struct fps_cfg   *fps)
+{
+	uint16_t total_lines_per_frame;
+	int32_t rc = 0;
+
+	ov5647_ctrl->fps_divider = fps->fps_div;
+	ov5647_ctrl->pict_fps_divider = fps->pict_fps_div;
+
+	if (ov5647_ctrl->sensormode == SENSOR_PREVIEW_MODE) {
+		total_lines_per_frame = (uint16_t)
+		((prev_frame_length_lines * ov5647_ctrl->fps_divider) / 0x400);
+	} else {
+		total_lines_per_frame = (uint16_t)
+		((snap_frame_length_lines * ov5647_ctrl->fps_divider) / 0x400);
+	}
+
+	ov5647_group_hold_on();
+	rc = ov5647_i2c_write_b_sensor(0x0340,
+			((total_lines_per_frame & 0xFF00) >> 8));
+	rc = ov5647_i2c_write_b_sensor(0x0341,
+			(total_lines_per_frame & 0x00FF));
+	ov5647_group_hold_off();
+
+	return rc;
+}
+
+static inline uint8_t ov5647_byte(uint16_t word, uint8_t offset)
+{
+	return word >> (offset * BITS_PER_BYTE);
+}
+
+static int32_t ov5647_write_exp_gain(uint16_t gain, uint32_t line)
+{
+	int rc = 0;
+	uint16_t max_line;
+	u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
+	uint8_t gain_lsb, gain_hsb;
+	ov5647_ctrl->my_reg_gain = gain;
+	ov5647_ctrl->my_reg_line_count = (uint16_t)line;
+
+	CDBG(KERN_ERR "preview exposure setting 0x%x, 0x%x, %d",
+		 gain, line, line);
+
+	gain_lsb = (uint8_t) (ov5647_ctrl->my_reg_gain);
+	gain_hsb = (uint8_t)((ov5647_ctrl->my_reg_gain & 0x300)>>8);
+	/* adjust frame rate */
+	if (line > 980) {
+		rc = ov5647_i2c_write_b_sensor(0x380E,
+			 (uint8_t)((line+4) >> 8)) ;
+		rc = ov5647_i2c_write_b_sensor(0x380F,
+			 (uint8_t)((line+4) & 0x00FF)) ;
+		max_line = line + 4;
+	} else if (max_line > 984) {
+		rc = ov5647_i2c_write_b_sensor(0x380E,
+			 (uint8_t)(984 >> 8)) ;
+		rc = ov5647_i2c_write_b_sensor(0x380F,
+			 (uint8_t)(984 & 0x00FF)) ;
+		max_line = 984;
+	}
+
+	line = line<<4;
+	/* ov5647 need this operation */
+	intg_time_hsb = (u8)(line>>16);
+	intg_time_msb = (u8) ((line & 0xFF00) >> 8);
+	intg_time_lsb = (u8) (line & 0x00FF);
+
+	ov5647_group_hold_on();
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb) ;
+	ov5647_group_hold_off();
+
+	return rc;
+}
+
+
+static int32_t ov5647_set_pict_exp_gain(uint16_t gain, uint32_t line)
+{
+	uint16_t max_line;
+	int rc = 0;
+	uint8_t gain_lsb, gain_hsb;
+	u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
+
+	ov5647_ctrl->my_reg_gain = gain;
+	ov5647_ctrl->my_reg_line_count = (uint16_t)line;
+
+	gain_lsb = (uint8_t) (ov5647_ctrl->my_reg_gain);
+	gain_hsb = (uint8_t)((ov5647_ctrl->my_reg_gain & 0x300)>>8);
+
+	CDBG(KERN_ERR "snapshot exposure seting 0x%x, 0x%x, %d"
+		, gain, line, line);
+
+	if (line > 1964) {
+		rc = ov5647_i2c_write_b_sensor(0x380E,
+			 (uint8_t)((line+4) >> 8)) ;
+		rc = ov5647_i2c_write_b_sensor(0x380F,
+			 (uint8_t)((line+4) & 0x00FF)) ;
+		max_line = line + 4;
+	} else if (max_line > 1968) {
+		rc = ov5647_i2c_write_b_sensor(0x380E,
+			 (uint8_t)(1968 >> 8)) ;
+		rc = ov5647_i2c_write_b_sensor(0x380F,
+			 (uint8_t)(1968 & 0x00FF)) ;
+		max_line = 1968;
+	}
+	line = line<<4;
+	/* ov5647 need this operation */
+	intg_time_hsb = (u8)(line>>16);
+	intg_time_msb = (u8) ((line & 0xFF00) >> 8);
+	intg_time_lsb = (u8) (line & 0x00FF);
+
+	/* FIXME for BLC trigger */
+	ov5647_group_hold_on();
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb - 1) ;
+
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_HSB, intg_time_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_MSB, intg_time_msb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_LINE_LSB, intg_time_lsb) ;
+
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_MSB, gain_hsb) ;
+	rc = ov5647_i2c_write_b_sensor(REG_OV5647_GAIN_LSB, gain_lsb) ;
+	ov5647_group_hold_off();
+
+	msleep(500);
+	return rc;
+
+}
+
+static int32_t ov5647_move_focus(int direction, int32_t num_steps)
+{
+	uint8_t   code_val_msb = 0;
+	uint8_t   code_val_lsb = 0;
+	int16_t   step_direction, actual_step, next_position;
+	int rc;
+
+	if (num_steps == 0)
+		return 0;
+
+	if (direction == MOVE_NEAR)
+		step_direction = 20;
+	else if (direction == MOVE_FAR)
+		step_direction = -20;
+	else
+		return -EINVAL;
+
+	actual_step = (int16_t)(step_direction * num_steps);
+	next_position = (int16_t)ov5647_ctrl->curr_lens_pos + actual_step;
+	if (next_position < 0) {
+		CDBG(KERN_ERR "%s: OV5647 position(=%d) out of range",
+			__func__, next_position);
+		next_position = 0;
+	}
+	if (next_position > 0x3FF) {
+		CDBG(KERN_ERR "%s: OV5647 position(=%d) out of range",
+			__func__, next_position);
+		next_position = 0x3FF;
+	}
+	ov5647_ctrl->curr_lens_pos = next_position;
+
+	code_val_msb = (uint8_t)((ov5647_ctrl->curr_lens_pos & 0x03FF) >> 4);
+	code_val_lsb = (uint8_t)((ov5647_ctrl->curr_lens_pos & 0x000F) << 4);
+	code_val_lsb |= mode_mask;
+
+	rc = ov5647_af_i2c_write_b_sensor(code_val_msb, code_val_lsb);
+	/* DAC Setting */
+	if (rc != 0) {
+		CDBG(KERN_ERR "%s: WRITE ERROR lsb = 0x%x, msb = 0x%x",
+			__func__, code_val_lsb, code_val_msb);
+	} else {
+		CDBG(KERN_ERR "%s: Successful lsb = 0x%x, msb = 0x%x",
+			__func__, code_val_lsb, code_val_msb);
+		/* delay may set based on the steps moved
+		when I2C write successful */
+		msleep(100);
+	}
+	return 0;
+}
+
+static int32_t ov5647_set_default_focus(uint8_t af_step)
+{
+	uint8_t  code_val_msb = 0;
+	uint8_t  code_val_lsb = 0;
+	int rc = 0;
+
+	ov5647_ctrl->curr_lens_pos = 200;
+
+
+	code_val_msb = (ov5647_ctrl->curr_lens_pos & 0x03FF) >> 4;
+	code_val_lsb = (ov5647_ctrl->curr_lens_pos & 0x000F) << 4;
+	code_val_lsb |= mode_mask;
+
+	CDBG(KERN_ERR "ov5647_set_default_focus:lens pos = %d",
+		 ov5647_ctrl->curr_lens_pos);
+	rc = ov5647_af_i2c_write_b_sensor(code_val_msb, code_val_lsb);
+	/* DAC Setting */
+	if (rc != 0)
+		CDBG(KERN_ERR "%s: WRITE ERROR lsb = 0x%x, msb = 0x%x",
+			__func__, code_val_lsb, code_val_msb);
+	else
+		CDBG(KERN_ERR "%s: WRITE successful lsb = 0x%x, msb = 0x%x",
+			__func__, code_val_lsb, code_val_msb);
+
+	usleep_range(10000, 11000);
+	return 0;
+}
+
+static int32_t ov5647_test(enum ov5647_test_mode_t mo)
+{
+	int32_t rc = 0;
+
+	if (mo != TEST_OFF)
+		rc = ov5647_i2c_write_b_sensor(0x0601, (uint8_t) mo);
+
+	return rc;
+}
+
+static void ov5647_reset_sensor(void)
+{
+	ov5647_i2c_write_b_sensor(0x103, 0x1);
+}
+
+
+static int32_t ov5647_sensor_setting(int update_type, int rt)
+{
+
+	int32_t rc = 0;
+	struct msm_camera_csi_params ov5647_csi_params;
+
+	ov5647_stop_stream();
+
+	/* wait for clk/data really stop */
+	if ((rt == RES_CAPTURE) || (CSI_CONFIG == 0))
+		msleep(66);
+	else
+		msleep(266);
+
+	CDBG("CAMERA_DBG1: 0x4800 regVal:0x25\r\n");
+	ov5647_i2c_write_b_sensor(0x4800, 0x25);/* streaming off */
+
+	usleep_range(10000, 11000);
+
+	if (update_type == REG_INIT) {
+		ov5647_reset_sensor();
+		ov5647_i2c_write_b_table(ov5647_regs.rec_settings,
+			ov5647_regs.rec_size);
+		CSI_CONFIG = 0;
+	} else if (update_type == UPDATE_PERIODIC) {
+			/* turn off flash when preview */
+
+			if (rt == RES_PREVIEW) {
+				ov5647_i2c_write_b_table(ov5647_regs.reg_prev,
+					 ov5647_regs.reg_prev_size);
+				CDBG("CAMERA_DBG:preview settings...\r\n");
+			} else {
+				ov5647_i2c_write_b_table(ov5647_regs.reg_snap,
+					 ov5647_regs.reg_snap_size);
+				CDBG("CAMERA_DBG:snapshot settings...\r\n");
+			}
+
+			msleep(20);
+			if (!CSI_CONFIG) {
+				msm_camio_vfe_clk_rate_set(192000000);
+				ov5647_csi_params.data_format = CSI_8BIT;
+				ov5647_csi_params.lane_cnt = 2;
+				ov5647_csi_params.lane_assign = 0xe4;
+				ov5647_csi_params.dpcm_scheme = 0;
+				ov5647_csi_params.settle_cnt = 10;
+				rc = msm_camio_csi_config(&ov5647_csi_params);
+				msleep(20);
+				CSI_CONFIG = 1;
+			/* exit powerdown state */
+				ov5647_i2c_write_b_sensor(0x0100, 0x01);
+			}
+			CDBG("CAMERA_DBG: 0x4800 regVal:0x04\r\n");
+			/* streaming on */
+			ov5647_i2c_write_b_sensor(0x4800, 0x04);
+			msleep(266);
+			ov5647_start_stream();
+			msleep(30);
+	}
+	return rc;
+}
+
+static int32_t ov5647_video_config(int mode)
+{
+	int32_t rc = 0;
+	int rt;
+	CDBG("video config\n");
+	/* change sensor resolution if needed */
+	if (ov5647_ctrl->prev_res == QTR_SIZE)
+		rt = RES_PREVIEW;
+	else
+		rt = RES_CAPTURE;
+	if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+		return rc;
+	if (ov5647_ctrl->set_test) {
+		if (ov5647_test(ov5647_ctrl->set_test) < 0)
+			return  rc;
+	}
+
+	ov5647_ctrl->curr_res = ov5647_ctrl->prev_res;
+	ov5647_ctrl->sensormode = mode;
+	return rc;
+}
+
+static int32_t ov5647_snapshot_config(int mode)
+{
+	int32_t rc = 0;
+	int rt;
+
+	/*change sensor resolution if needed */
+	if (ov5647_ctrl->curr_res != ov5647_ctrl->pict_res) {
+		if (ov5647_ctrl->pict_res == QTR_SIZE)
+			rt = RES_PREVIEW;
+		else
+			rt = RES_CAPTURE;
+		if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+			return rc;
+	}
+
+	ov5647_ctrl->curr_res = ov5647_ctrl->pict_res;
+	ov5647_ctrl->sensormode = mode;
+	return rc;
+}
+
+static int32_t ov5647_raw_snapshot_config(int mode)
+{
+	int32_t rc = 0;
+	int rt;
+
+	/* change sensor resolution if needed */
+	if (ov5647_ctrl->curr_res != ov5647_ctrl->pict_res) {
+		if (ov5647_ctrl->pict_res == QTR_SIZE)
+			rt = RES_PREVIEW;
+		else
+			rt = RES_CAPTURE;
+		if (ov5647_sensor_setting(UPDATE_PERIODIC, rt) < 0)
+			return rc;
+	}
+
+	ov5647_ctrl->curr_res = ov5647_ctrl->pict_res;
+	ov5647_ctrl->sensormode = mode;
+	return rc;
+}
+
+static int32_t ov5647_set_sensor_mode(int mode,
+		int res)
+{
+	int32_t rc = 0;
+
+	switch (mode) {
+	case SENSOR_PREVIEW_MODE:
+		rc = ov5647_video_config(mode);
+		break;
+	case SENSOR_SNAPSHOT_MODE:
+		rc = ov5647_snapshot_config(mode);
+		break;
+	case SENSOR_RAW_SNAPSHOT_MODE:
+		rc = ov5647_raw_snapshot_config(mode);
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+static int32_t ov5647_power_down(void)
+{
+	ov5647_stop_stream();
+	return 0;
+}
+
+static int ov5647_probe_init_done(const struct msm_camera_sensor_info *data)
+{
+	CDBG("probe done\n");
+	gpio_direction_output(data->sensor_pwd, 1);
+	return 0;
+}
+
+static int ov5647_probe_init_sensor(const struct msm_camera_sensor_info *data)
+{
+	int32_t rc = 0;
+	uint16_t regaddress1 = 0x300a;
+	uint16_t regaddress2 = 0x300b;
+	uint16_t chipid1 = 0;
+	uint16_t chipid2 = 0;
+
+	CDBG("%s: %d\n", __func__, __LINE__);
+
+	gpio_direction_output(data->sensor_pwd, 0);
+	usleep_range(4000, 4100);
+	gpio_direction_output(data->sensor_reset, 1);
+	usleep_range(2000, 2100);
+
+	ov5647_i2c_read(regaddress1, &chipid1);
+	if (chipid1 != 0x56) {
+		rc = -ENODEV;
+		pr_err("ov5647_probe_init_sensor fail chip id doesnot match\n");
+		goto init_probe_fail;
+	}
+
+	ov5647_i2c_read(regaddress2, &chipid2);
+	if (chipid2 != 0x47) {
+		rc = -ENODEV;
+		pr_err("ov5647_probe_init_sensor fail chip id doesnot match\n");
+		goto init_probe_fail;
+	}
+
+	pr_err("ID1: 0x%x\n", chipid1);
+	pr_err("ID2: 0x%x\n", chipid2);
+	goto init_probe_done;
+
+init_probe_fail:
+	pr_err(" ov5647_probe_init_sensor fails\n");
+	ov5647_probe_init_done(data);
+	return rc;
+init_probe_done:
+	pr_debug(" ov5647_probe_init_sensor finishes\n");
+	gpio_direction_output(data->sensor_pwd, 1);
+	return rc;
+}
+
+
+static int ov5647_sensor_open_init(const struct msm_camera_sensor_info *data)
+{
+	int32_t rc = 0;
+
+	CDBG("%s: %d\n", __func__, __LINE__);
+	CDBG("Calling ov5647_sensor_open_init\n");
+
+	ov5647_ctrl = kzalloc(sizeof(struct ov5647_ctrl_t), GFP_KERNEL);
+	if (!ov5647_ctrl) {
+		CDBG("ov5647_init failed!\n");
+		rc = -ENOMEM;
+		goto init_done;
+	}
+	ov5647_ctrl->fps_divider = 1 * 0x00000400;
+	ov5647_ctrl->pict_fps_divider = 1 * 0x00000400;
+	ov5647_ctrl->set_test = TEST_OFF;
+	ov5647_ctrl->prev_res = QTR_SIZE;
+	ov5647_ctrl->pict_res = FULL_SIZE;
+
+	if (data)
+		ov5647_ctrl->sensordata = data;
+
+	prev_frame_length_lines = 0x3d8;
+
+	prev_line_length_pck = 0x768*2;
+
+	snap_frame_length_lines = 0x7b0;
+
+	snap_line_length_pck = 0xa8c;
+
+	/* enable mclk first */
+	msm_camio_clk_rate_set(OV5647_MASTER_CLK_RATE);
+
+	gpio_direction_output(data->sensor_pwd, 1);
+	gpio_direction_output(data->sensor_reset, 0);
+	usleep_range(10000, 11000);
+	/* power on camera ldo and vreg */
+	if (ov5647_ctrl->sensordata->pmic_gpio_enable)
+		lcd_camera_power_onoff(1);
+	usleep_range(10000, 11000); /*waiting for ldo stable*/
+	gpio_direction_output(data->sensor_pwd, 0);
+	msleep(20);
+	gpio_direction_output(data->sensor_reset, 1);
+	msleep(25);
+
+	CDBG("init settings\n");
+	if (ov5647_ctrl->prev_res == QTR_SIZE)
+		rc = ov5647_sensor_setting(REG_INIT, RES_PREVIEW);
+	else
+		rc = ov5647_sensor_setting(REG_INIT, RES_CAPTURE);
+	ov5647_ctrl->fps = 30 * Q8;
+
+	/* enable AF actuator */
+	if (ov5647_ctrl->sensordata->vcm_enable) {
+		CDBG("enable AF actuator, gpio = %d\n",
+			 ov5647_ctrl->sensordata->vcm_pwd);
+		rc = gpio_request(ov5647_ctrl->sensordata->vcm_pwd,
+						"ov5647_af");
+		if (!rc)
+			gpio_direction_output(
+				ov5647_ctrl->sensordata->vcm_pwd,
+				 1);
+		else {
+			pr_err("ov5647_ctrl gpio request failed!\n");
+			goto init_fail;
+		}
+		msleep(20);
+		rc = ov5647_set_default_focus(0);
+		if (rc < 0) {
+			gpio_direction_output(ov5647_ctrl->sensordata->vcm_pwd,
+								0);
+			gpio_free(ov5647_ctrl->sensordata->vcm_pwd);
+		}
+	}
+	if (rc < 0)
+		goto init_fail;
+	else
+		goto init_done;
+init_fail:
+	CDBG("init_fail\n");
+	ov5647_probe_init_done(data);
+	/* No need to power OFF camera ldo and vreg
+	affects Display while resume */
+init_done:
+	CDBG("init_done\n");
+	return rc;
+}
+
+static int ov5647_i2c_remove(struct i2c_client *client)
+{
+	return 0;
+}
+
+static int ov5647_init_client(struct i2c_client *client)
+{
+	/* Initialize the MSM_CAMI2C Chip */
+	init_waitqueue_head(&ov5647_wait_queue);
+	return 0;
+}
+
+static int ov5647_af_init_client(struct i2c_client *client)
+{
+	/* Initialize the MSM_CAMI2C Chip */
+	init_waitqueue_head(&ov5647_af_wait_queue);
+	return 0;
+}
+
+static const struct i2c_device_id ov5647_af_i2c_id[] = {
+	{"ov5647_af", 0},
+	{ }
+};
+
+static int ov5647_af_i2c_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	int rc = 0;
+	CDBG("ov5647_af_probe called!\n");
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		CDBG("i2c_check_functionality failed\n");
+		goto probe_failure;
+	}
+
+	ov5647_af_sensorw = kzalloc(sizeof(struct ov5647_work_t), GFP_KERNEL);
+	if (!ov5647_af_sensorw) {
+		CDBG("kzalloc failed.\n");
+		rc = -ENOMEM;
+		goto probe_failure;
+	}
+
+	i2c_set_clientdata(client, ov5647_af_sensorw);
+	ov5647_af_init_client(client);
+	ov5647_af_client = client;
+
+	msleep(50);
+
+	CDBG("ov5647_af_probe successed! rc = %d\n", rc);
+	return 0;
+
+probe_failure:
+	CDBG("ov5647_af_probe failed! rc = %d\n", rc);
+	return rc;
+}
+
+static const struct i2c_device_id ov5647_i2c_id[] = {
+	{"ov5647", 0}, {}
+};
+
+static int ov5647_i2c_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	int rc = 0;
+	CDBG("ov5647_probe called!\n");
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		CDBG("i2c_check_functionality failed\n");
+		goto probe_failure;
+	}
+
+	ov5647_sensorw = kzalloc(sizeof(struct ov5647_work_t), GFP_KERNEL);
+	if (!ov5647_sensorw) {
+		CDBG("kzalloc failed.\n");
+		rc = -ENOMEM;
+		goto probe_failure;
+	}
+
+	i2c_set_clientdata(client, ov5647_sensorw);
+	ov5647_init_client(client);
+	ov5647_client = client;
+
+	msleep(50);
+
+	CDBG("ov5647_probe successed! rc = %d\n", rc);
+	return 0;
+
+probe_failure:
+	CDBG("ov5647_probe failed! rc = %d\n", rc);
+	return rc;
+}
+
+static int __devexit ov5647_remove(struct i2c_client *client)
+{
+	struct ov5647_work_t *sensorw = i2c_get_clientdata(client);
+	free_irq(client->irq, sensorw);
+	ov5647_client = NULL;
+	kfree(sensorw);
+	return 0;
+}
+
+static int __devexit ov5647_af_remove(struct i2c_client *client)
+{
+	struct ov5647_work_t *ov5647_af = i2c_get_clientdata(client);
+	free_irq(client->irq, ov5647_af);
+	ov5647_af_client = NULL;
+	kfree(ov5647_af);
+	return 0;
+}
+
+static struct i2c_driver ov5647_i2c_driver = {
+	.id_table = ov5647_i2c_id,
+	.probe  = ov5647_i2c_probe,
+	.remove = ov5647_i2c_remove,
+	.driver = {
+		.name = "ov5647",
+	},
+};
+
+static struct i2c_driver ov5647_af_i2c_driver = {
+	.id_table = ov5647_af_i2c_id,
+	.probe  = ov5647_af_i2c_probe,
+	.remove = __exit_p(ov5647_af_i2c_remove),
+	.driver = {
+		.name = "ov5647_af",
+	},
+};
+
+int ov5647_sensor_config(void __user *argp)
+{
+	struct sensor_cfg_data cdata;
+	long   rc = 0;
+	if (copy_from_user(&cdata,
+				(void *)argp,
+				sizeof(struct sensor_cfg_data)))
+		return -EFAULT;
+	mutex_lock(&ov5647_mut);
+	CDBG("ov5647_sensor_config: cfgtype = %d\n",
+			cdata.cfgtype);
+	switch (cdata.cfgtype) {
+	case CFG_GET_PICT_FPS:
+		ov5647_get_pict_fps(
+			cdata.cfg.gfps.prevfps,
+			&(cdata.cfg.gfps.pictfps));
+
+		if (copy_to_user((void *)argp,
+			&cdata,
+			sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PREV_L_PF:
+		cdata.cfg.prevl_pf =
+			ov5647_get_prev_lines_pf();
+
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PREV_P_PL:
+		cdata.cfg.prevp_pl =
+			ov5647_get_prev_pixels_pl();
+
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PICT_L_PF:
+		cdata.cfg.pictl_pf =
+			ov5647_get_pict_lines_pf();
+
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PICT_P_PL:
+		cdata.cfg.pictp_pl =
+			ov5647_get_pict_pixels_pl();
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_GET_PICT_MAX_EXP_LC:
+		cdata.cfg.pict_max_exp_lc =
+			ov5647_get_pict_max_exp_lc();
+
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_SET_FPS:
+	case CFG_SET_PICT_FPS:
+		rc = ov5647_set_fps(&(cdata.cfg.fps));
+		break;
+	case CFG_SET_EXP_GAIN:
+		rc = ov5647_write_exp_gain(cdata.cfg.exp_gain.gain,
+				cdata.cfg.exp_gain.line);
+		break;
+	case CFG_SET_PICT_EXP_GAIN:
+		rc = ov5647_set_pict_exp_gain(cdata.cfg.exp_gain.gain,
+				cdata.cfg.exp_gain.line);
+		break;
+	case CFG_SET_MODE:
+		rc = ov5647_set_sensor_mode(cdata.mode, cdata.rs);
+		break;
+	case CFG_PWR_DOWN:
+		rc = ov5647_power_down();
+		break;
+	case CFG_MOVE_FOCUS:
+		rc = ov5647_move_focus(cdata.cfg.focus.dir,
+				cdata.cfg.focus.steps);
+		break;
+	case CFG_SET_DEFAULT_FOCUS:
+		rc = ov5647_set_default_focus(cdata.cfg.focus.steps);
+		break;
+
+	case CFG_GET_AF_MAX_STEPS:
+		cdata.max_steps = OV5647_TOTAL_STEPS_NEAR_TO_FAR;
+		if (copy_to_user((void *)argp,
+					&cdata,
+				sizeof(struct sensor_cfg_data)))
+			rc = -EFAULT;
+		break;
+	case CFG_SET_EFFECT:
+		rc = ov5647_set_default_focus(cdata.cfg.effect);
+		break;
+	default:
+		rc = -EFAULT;
+		break;
+	}
+	mutex_unlock(&ov5647_mut);
+
+	return rc;
+}
+
+static int ov5647_sensor_release(void)
+{
+	int rc = -EBADF;
+	unsigned short rdata;
+
+	mutex_lock(&ov5647_mut);
+	ov5647_power_down();
+	msleep(20);
+	ov5647_i2c_read(0x3018, &rdata);
+	rdata |= 0x18; /*set bit 3 bit 4 to 1*/
+	ov5647_i2c_write_b_sensor(0x3018, rdata);/*write back*/
+	msleep(20);
+
+	gpio_set_value(ov5647_ctrl->sensordata->sensor_pwd, 1);
+	usleep_range(5000, 5100);
+	if (ov5647_ctrl->sensordata->vcm_enable) {
+		gpio_direction_output(ov5647_ctrl->sensordata->vcm_pwd, 0);
+		gpio_free(ov5647_ctrl->sensordata->vcm_pwd);
+	}
+
+	/* No need to power OFF camera ldo and vreg
+	affects Display while resume */
+
+	kfree(ov5647_ctrl);
+	ov5647_ctrl = NULL;
+	CDBG("ov5647_release completed\n");
+	mutex_unlock(&ov5647_mut);
+
+	return rc;
+}
+
+static int ov5647_sensor_probe(const struct msm_camera_sensor_info *info,
+		struct msm_sensor_ctrl *s)
+{
+	int rc = 0;
+
+	CDBG("%s E\n", __func__);
+
+	gpio_direction_output(info->sensor_pwd, 1);
+	gpio_direction_output(info->sensor_reset, 0);
+	usleep_range(1000, 1100);
+	/* turn on ldo and vreg */
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(1);
+
+	rc = i2c_add_driver(&ov5647_i2c_driver);
+	if (rc < 0 || ov5647_client == NULL) {
+		rc = -ENOTSUPP;
+		CDBG("I2C add driver ov5647 failed");
+		goto probe_fail_2;
+	}
+	if (info->vcm_enable) {
+		rc = i2c_add_driver(&ov5647_af_i2c_driver);
+		if (rc < 0 || ov5647_af_client == NULL) {
+			rc = -ENOTSUPP;
+			CDBG("I2C add driver ov5647 af failed");
+			goto probe_fail_3;
+		}
+	}
+	msm_camio_clk_rate_set(OV5647_MASTER_CLK_RATE);
+
+	rc = ov5647_probe_init_sensor(info);
+	if (rc < 0)
+		goto probe_fail_1;
+
+	s->s_init = ov5647_sensor_open_init;
+	s->s_release = ov5647_sensor_release;
+	s->s_config  = ov5647_sensor_config;
+	s->s_mount_angle = info->sensor_platform_info->mount_angle;
+	gpio_set_value(info->sensor_pwd, 1);
+	ov5647_probe_init_done(info);
+	/* turn off ldo and vreg */
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
+
+	CDBG("%s X", __func__);
+	return rc;
+
+probe_fail_3:
+	i2c_del_driver(&ov5647_af_i2c_driver);
+probe_fail_2:
+	i2c_del_driver(&ov5647_i2c_driver);
+probe_fail_1:
+	/* turn off ldo and vreg */
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
+	CDBG("ov5647_sensor_probe: SENSOR PROBE FAILS!\n");
+	CDBG("%s X", __func__);
+	return rc;
+}
+
+static int __devinit ov5647_probe(struct platform_device *pdev)
+{
+	return msm_camera_drv_start(pdev, ov5647_sensor_probe);
+}
+
+static struct platform_driver msm_camera_driver = {
+	.probe = ov5647_probe,
+	.driver = {
+		.name = "msm_camera_ov5647",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init ov5647_init(void)
+{
+	return platform_driver_register(&msm_camera_driver);
+}
+
+module_init(ov5647_init);
+MODULE_DESCRIPTION("Omnivision 5 MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/ov5647.h b/drivers/media/video/msm/ov5647.h
new file mode 100644
index 0000000..b43f15c
--- /dev/null
+++ b/drivers/media/video/msm/ov5647.h
@@ -0,0 +1,92 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef OV5647_H
+#define OV5647_H
+#include <linux/types.h>
+#include <mach/board.h>
+
+extern struct ov5647_reg ov5647_regs;
+extern int lcd_camera_power_onoff(int on);
+extern struct rw_semaphore leds_list_lock;
+extern struct list_head leds_list;
+
+struct ov5647_i2c_reg_conf {
+	unsigned short waddr;
+	unsigned short wdata;
+};
+
+enum ov5647_test_mode_t {
+	TEST_OFF,
+	TEST_1,
+	TEST_2,
+	TEST_3
+};
+
+enum ov5647_resolution_t {
+	QTR_SIZE,
+	FULL_SIZE,
+	INVALID_SIZE
+};
+enum ov5647_setting {
+	RES_PREVIEW,
+	RES_CAPTURE
+};
+enum ov5647_reg_update {
+	/* Sensor egisters that need to be updated during initialization */
+	REG_INIT,
+	/* Sensor egisters that needs periodic I2C writes */
+	UPDATE_PERIODIC,
+	/* All the sensor Registers will be updated */
+	UPDATE_ALL,
+	/* Not valid update */
+	UPDATE_INVALID
+};
+
+enum ov5647_reg_pll {
+	E013_VT_PIX_CLK_DIV,
+	E013_VT_SYS_CLK_DIV,
+	E013_PRE_PLL_CLK_DIV,
+	E013_PLL_MULTIPLIER,
+	E013_OP_PIX_CLK_DIV,
+	E013_OP_SYS_CLK_DIV
+};
+
+enum ov5647_reg_mode {
+	E013_X_ADDR_START,
+	E013_X_ADDR_END,
+	E013_Y_ADDR_START,
+	E013_Y_ADDR_END,
+	E013_X_OUTPUT_SIZE,
+	E013_Y_OUTPUT_SIZE,
+	E013_DATAPATH_SELECT,
+	E013_READ_MODE,
+	E013_ANALOG_CONTROL5,
+	E013_DAC_LD_4_5,
+	E013_SCALING_MODE,
+	E013_SCALE_M,
+	E013_LINE_LENGTH_PCK,
+	E013_FRAME_LENGTH_LINES,
+	E013_COARSE_INTEGRATION_TIME,
+	E013_FINE_INTEGRATION_TIME,
+	E013_FINE_CORRECTION
+};
+
+struct ov5647_reg {
+	const struct ov5647_i2c_reg_conf *rec_settings;
+	const unsigned short rec_size;
+	const struct ov5647_i2c_reg_conf *reg_prev;
+	const unsigned short reg_prev_size;
+	const struct ov5647_i2c_reg_conf *reg_snap;
+	const unsigned short reg_snap_size;
+};
+#endif /* OV5647_H */
diff --git a/drivers/media/video/msm/ov5647_reg.c b/drivers/media/video/msm/ov5647_reg.c
new file mode 100644
index 0000000..4a0fed4
--- /dev/null
+++ b/drivers/media/video/msm/ov5647_reg.c
@@ -0,0 +1,219 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#include "ov5647.h"
+struct ov5647_i2c_reg_conf ov5647_prev_settings[] = {
+	/*1280*960 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps
+	for back to preview*/
+	{0x3035, 0x21},
+	{0x3036, 0x37},
+	{0x3821, 0x07},
+	{0x3820, 0x41},
+	{0x3612, 0x09},
+	{0x3618, 0x00},
+	{0x380c, 0x07},
+	{0x380d, 0x68},
+	{0x380e, 0x03},
+	{0x380f, 0xd8},
+	{0x3814, 0x31},
+	{0x3815, 0x31},
+	{0x3709, 0x52},
+	{0x3808, 0x05},
+	{0x3809, 0x00},
+	{0x380a, 0x03},
+	{0x380b, 0xc0},
+	{0x3800, 0x00},
+	{0x3801, 0x18},
+	{0x3802, 0x00},
+	{0x3803, 0x0e},
+	{0x3804, 0x0a},
+	{0x3805, 0x27},
+	{0x3806, 0x07},
+	{0x3807, 0x95},
+	{0x4004, 0x02},
+};
+
+struct ov5647_i2c_reg_conf ov5647_snap_settings[] = {
+	/*2608*1952 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps*/
+	{0x3035, 0x21},
+	{0x3036, 0x4f},
+	{0x3821, 0x06},
+	{0x3820, 0x00},
+	{0x3612, 0x0b},
+	{0x3618, 0x04},
+	{0x380c, 0x0a},
+	{0x380d, 0x8c},
+	{0x380e, 0x07},
+	{0x380f, 0xb0},
+	{0x3814, 0x11},
+	{0x3815, 0x11},
+	{0x3709, 0x12},
+	{0x3808, 0x0a},
+	{0x3809, 0x30},
+	{0x380a, 0x07},
+	{0x380b, 0xa0},
+	{0x3800, 0x00},
+	{0x3801, 0x04},
+	{0x3802, 0x00},
+	{0x3803, 0x00},
+	{0x3804, 0x0a},
+	{0x3805, 0x3b},
+	{0x3806, 0x07},
+	{0x3807, 0xa3},
+	{0x4004, 0x04},
+};
+
+struct ov5647_i2c_reg_conf ov5647_recommend_settings[] = {
+	{0x3035, 0x11},
+	{0x303c, 0x11},
+	{0x370c, 0x03},
+	{0x5000, 0x06},
+	{0x5003, 0x08},
+	{0x5a00, 0x08},
+	{0x3000, 0xff},
+	{0x3001, 0xff},
+	{0x3002, 0xff},
+	{0x301d, 0xf0},
+	{0x3a18, 0x00},
+	{0x3a19, 0xf8},
+	{0x3c01, 0x80},
+	{0x3b07, 0x0c},
+	{0x3708, 0x64},
+	{0x3630, 0x2e},
+	{0x3632, 0xe2},
+	{0x3633, 0x23},
+	{0x3634, 0x44},
+	{0x3620, 0x64},
+	{0x3621, 0xe0},
+	{0x3600, 0x37},
+	{0x3704, 0xa0},
+	{0x3703, 0x5a},
+	{0x3715, 0x78},
+	{0x3717, 0x01},
+	{0x3731, 0x02},
+	{0x370b, 0x60},
+	{0x3705, 0x1a},
+	{0x3f05, 0x02},
+	{0x3f06, 0x10},
+	{0x3f01, 0x0a},
+	{0x3a08, 0x01},
+	{0x3a0f, 0x58},
+	{0x3a10, 0x50},
+	{0x3a1b, 0x58},
+	{0x3a1e, 0x50},
+	{0x3a11, 0x60},
+	{0x3a1f, 0x28},
+	{0x4001, 0x02},
+	{0x4000, 0x09},
+	{0x3000, 0x00},
+	{0x3001, 0x00},
+	{0x3002, 0x00},
+	{0x3017, 0xe0},
+	{0x301c, 0xfc},
+	{0x3636, 0x06},
+	{0x3016, 0x08},
+	{0x3827, 0xec},
+	{0x3018, 0x44},
+	{0x3035, 0x21},
+	{0x3106, 0xf5},
+	{0x3034, 0x18},
+	{0x301c, 0xf8},
+	/*lens setting*/
+	{0x5000, 0x86},
+	{0x5800, 0x11},
+	{0x5801, 0x0c},
+	{0x5802, 0x0a},
+	{0x5803, 0x0b},
+	{0x5804, 0x0d},
+	{0x5805, 0x13},
+	{0x5806, 0x09},
+	{0x5807, 0x05},
+	{0x5808, 0x03},
+	{0x5809, 0x03},
+	{0x580a, 0x06},
+	{0x580b, 0x08},
+	{0x580c, 0x05},
+	{0x580d, 0x01},
+	{0x580e, 0x00},
+	{0x580f, 0x00},
+	{0x5810, 0x02},
+	{0x5811, 0x06},
+	{0x5812, 0x05},
+	{0x5813, 0x01},
+	{0x5814, 0x00},
+	{0x5815, 0x00},
+	{0x5816, 0x02},
+	{0x5817, 0x06},
+	{0x5818, 0x09},
+	{0x5819, 0x05},
+	{0x581a, 0x04},
+	{0x581b, 0x04},
+	{0x581c, 0x06},
+	{0x581d, 0x09},
+	{0x581e, 0x11},
+	{0x581f, 0x0c},
+	{0x5820, 0x0b},
+	{0x5821, 0x0b},
+	{0x5822, 0x0d},
+	{0x5823, 0x13},
+	{0x5824, 0x22},
+	{0x5825, 0x26},
+	{0x5826, 0x26},
+	{0x5827, 0x24},
+	{0x5828, 0x24},
+	{0x5829, 0x24},
+	{0x582a, 0x22},
+	{0x582b, 0x20},
+	{0x582c, 0x22},
+	{0x582d, 0x26},
+	{0x582e, 0x22},
+	{0x582f, 0x22},
+	{0x5830, 0x42},
+	{0x5831, 0x22},
+	{0x5832, 0x02},
+	{0x5833, 0x24},
+	{0x5834, 0x22},
+	{0x5835, 0x22},
+	{0x5836, 0x22},
+	{0x5837, 0x26},
+	{0x5838, 0x42},
+	{0x5839, 0x26},
+	{0x583a, 0x06},
+	{0x583b, 0x26},
+	{0x583c, 0x24},
+	{0x583d, 0xce},
+	/* manual AWB,manual AE,close Lenc,open WBC*/
+	{0x3503, 0x03}, /*manual AE*/
+	{0x3501, 0x10},
+	{0x3502, 0x80},
+	{0x350a, 0x00},
+	{0x350b, 0x7f},
+	{0x5001, 0x01}, /*manual AWB*/
+	{0x5180, 0x08},
+	{0x5186, 0x04},
+	{0x5187, 0x00},
+	{0x5188, 0x04},
+	{0x5189, 0x00},
+	{0x518a, 0x04},
+	{0x518b, 0x00},
+	{0x5000, 0x06}, /*No lenc,WBC on*/
+};
+
+struct ov5647_reg ov5647_regs = {
+	.rec_settings = &ov5647_recommend_settings[0],
+	.rec_size = ARRAY_SIZE(ov5647_recommend_settings),
+	.reg_prev = &ov5647_prev_settings[0],
+	.reg_prev_size = ARRAY_SIZE(ov5647_prev_settings),
+	.reg_snap = &ov5647_snap_settings[0],
+	.reg_snap_size = ARRAY_SIZE(ov5647_snap_settings),
+};
diff --git a/drivers/media/video/msm/ov7692.h b/drivers/media/video/msm/ov7692.h
index e43a17d..fc9cf1c 100644
--- a/drivers/media/video/msm/ov7692.h
+++ b/drivers/media/video/msm/ov7692.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,11 @@
 #include <linux/types.h>
 #include <mach/board.h>
 
+#define INVMASK(v)  (0xff-v)
+#define OV7692Core_WritePREG(pTbl)  OV7692_WritePRegs \
+			(pTbl, sizeof(pTbl)/sizeof(pTbl[0]))
+
+extern int lcd_camera_power_onoff(int on);
 struct reg_addr_val_pair_struct {
 	uint8_t	reg_addr;
 	uint8_t	reg_val;
@@ -46,5 +51,616 @@
 	/* Not valid update */
 	UPDATE_INVALID
 };
+
+/*OV SENSOR SCCB*/
+struct OV7692_WREG {
+	uint8_t addr;
+	uint8_t data;
+	uint8_t mask;
+} OV7692_WREG;
+
+#ifdef CONFIG_WEBCAM_OV7692_QRD
+/*  96MHz PCLK @ 24MHz MCLK */
+struct reg_addr_val_pair_struct ov7692_init_settings_array[] = {
+	{0x12, 0x80},
+	{0x0e, 0x08},
+	{0x69, 0x52},
+	{0x1e, 0xb3},
+	{0x48, 0x42},
+	{0xff, 0x01},
+	{0xae, 0xa0},
+	{0xa8, 0x26},
+	{0xb4, 0xc0},
+	{0xb5, 0x40},
+	{0xff, 0x00},
+	{0x0c, 0x00},
+	{0x62, 0x10},
+	{0x12, 0x00},
+	{0x17, 0x65},
+	{0x18, 0xa4},
+	{0x19, 0x0a},
+	{0x1a, 0xf6},
+	{0x3e, 0x30},
+	{0x64, 0x0a},
+	{0xff, 0x01},
+	{0xb4, 0xc0},
+	{0xff, 0x00},
+	{0x67, 0x20},
+	{0x81, 0x3f},
+	{0xcc, 0x02},
+	{0xcd, 0x80},
+	{0xce, 0x01},
+	{0xcf, 0xe0},
+	{0xc8, 0x02},
+	{0xc9, 0x80},
+	{0xca, 0x01},
+	{0xcb, 0xe0},
+	{0xd0, 0x48},
+	{0x82, 0x03},
+	/*{0x0e, 0x00},*/
+	{0x70, 0x00},
+	{0x71, 0x34},
+	{0x74, 0x28},
+	{0x75, 0x98},
+	{0x76, 0x00},
+	{0x77, 0x64},
+	{0x78, 0x01},
+	{0x79, 0xc2},
+	{0x7a, 0x4e},
+	{0x7b, 0x1f},
+	{0x7c, 0x00},
+	{0x11, 0x00},
+	{0x20, 0x00},
+	{0x21, 0x23},
+	{0x50, 0x9a},
+	{0x51, 0x80},
+	{0x4c, 0x7d},
+	/*{0x0e, 0x00},*/
+	{0x85, 0x10},
+	{0x86, 0x00},
+	{0x87, 0x00},
+	{0x88, 0x00},
+	{0x89, 0x2a},
+	{0x8a, 0x26},
+	{0x8b, 0x22},
+	{0xbb, 0x7a},
+	{0xbc, 0x69},
+	{0xbd, 0x11},
+	{0xbe, 0x13},
+	{0xbf, 0x81},
+	{0xc0, 0x96},
+	{0xc1, 0x1e},
+	{0xb7, 0x05},
+	{0xb8, 0x09},
+	{0xb9, 0x00},
+	{0xba, 0x18},
+	{0x5a, 0x1f},
+	{0x5b, 0x9f},
+	{0x5c, 0x6a},
+	{0x5d, 0x42},
+	{0x24, 0x78},
+	{0x25, 0x68},
+	{0x26, 0xb3},
+	{0xa3, 0x0b},
+	{0xa4, 0x15},
+	{0xa5, 0x2a},
+	{0xa6, 0x51},
+	{0xa7, 0x63},
+	{0xa8, 0x74},
+	{0xa9, 0x83},
+	{0xaa, 0x91},
+	{0xab, 0x9e},
+	{0xac, 0xaa},
+	{0xad, 0xbe},
+	{0xae, 0xce},
+	{0xaf, 0xe5},
+	{0xb0, 0xf3},
+	{0xb1, 0xfb},
+	{0xb2, 0x06},
+	{0x8c, 0x5c},
+	{0x8d, 0x11},
+	{0x8e, 0x12},
+	{0x8f, 0x19},
+	{0x90, 0x50},
+	{0x91, 0x20},
+	{0x92, 0x96},
+	{0x93, 0x80},
+	{0x94, 0x13},
+	{0x95, 0x1b},
+	{0x96, 0xff},
+	{0x97, 0x00},
+	{0x98, 0x3d},
+	{0x99, 0x36},
+	{0x9a, 0x51},
+	{0x9b, 0x43},
+	{0x9c, 0xf0},
+	{0x9d, 0xf0},
+	{0x9e, 0xf0},
+	{0x9f, 0xff},
+	{0xa0, 0x68},
+	{0xa1, 0x62},
+	{0xa2, 0x0e},
+};
+#endif
+/* Exposure Compensation */
+struct OV7692_WREG ov7692_exposure_compensation_lv0_tbl[] = {
+	/*@@ +1.7EV*/
+	{0x24, 0xc0},
+	{0x25, 0xb8},
+	{0x26, 0xe6},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv1_tbl[] = {
+	/*@@ +1.0EV*/
+	{0x24, 0xa8},
+	{0x25, 0xa0},
+	{0x26, 0xc4},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv2_default_tbl[] = {
+	/*@@ default*/
+	{0x24, 0x86},
+	{0x25, 0x76},
+	{0x26, 0xb3},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv3_tbl[] = {
+	/*@@ -1.0EV*/
+	{0x24, 0x70},
+	{0x25, 0x60},
+	{0x26, 0xa2},
+};
+
+struct OV7692_WREG ov7692_exposure_compensation_lv4_tbl[] = {
+	/*@@ -1.7EV*/
+	{0x24, 0x50},
+	{0x25, 0x40},
+	{0x26, 0xa2},
+};
+
+struct OV7692_WREG ov7692_antibanding_off_tbl[] = {
+	{0x13, 0xE5, INVMASK(0x20)},
+};
+
+struct OV7692_WREG ov7692_antibanding_auto_tbl[] = {
+	{0x13, 0x20, INVMASK(0x20)},
+	{0x14, 0x14, INVMASK(0x17)},
+};
+
+struct OV7692_WREG ov7692_antibanding_50z_tbl[] = {
+	/*Band 50Hz*/
+	{0x13, 0x20, INVMASK(0x20)},
+	{0x14, 0x17, INVMASK(0x17)},
+};
+
+struct OV7692_WREG ov7692_antibanding_60z_tbl[] = {
+	/*Band 60Hz*/
+	{0x13, 0x20, INVMASK(0x20)},
+	{0x14, 0x16, INVMASK(0x17)},
+};
+
+/*Saturation*/
+struct OV7692_WREG ov7692_saturation_lv0_tbl[] = {
+	/*Saturation level 0*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x00, INVMASK(0xff)},
+	{0xd9, 0x00, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv1_tbl[] = {
+	/*Saturation level 1*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x10, INVMASK(0xff)},
+	{0xd9, 0x10, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv2_tbl[] = {
+	/*Saturation level 2*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x20, INVMASK(0xff)},
+	{0xd9, 0x20, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+
+};
+
+struct OV7692_WREG ov7692_saturation_lv3_tbl[] = {
+	/*Saturation level 3*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x30, INVMASK(0xff)},
+	{0xd9, 0x30, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+
+};
+
+struct OV7692_WREG ov7692_saturation_default_lv4_tbl[] = {
+	/*Saturation level 4 (default)*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x40, INVMASK(0xff)},
+	{0xd9, 0x40, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv5_tbl[] = {
+	/*Saturation level 5*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x50, INVMASK(0xff)},
+	{0xd9, 0x50, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv6_tbl[] = {
+	/*Saturation level 6*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x60, INVMASK(0xff)},
+	{0xd9, 0x60, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv7_tbl[] = {
+	/*Saturation level 7*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x70, INVMASK(0xff)},
+	{0xd9, 0x70, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+struct OV7692_WREG ov7692_saturation_lv8_tbl[] = {
+	/*Saturation level 8*/
+	{0x81, 0x33, INVMASK(0x33)},
+	{0xd8, 0x80, INVMASK(0xff)},
+	{0xd9, 0x80, INVMASK(0xff)},
+	{0xd2, 0x02, INVMASK(0xff)},
+};
+
+/*EFFECT*/
+struct OV7692_WREG ov7692_effect_normal_tbl[] = {
+	{0x81, 0x00, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x00, },
+	{0xda, 0x80, },
+	{0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_mono_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x80, },
+	{0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_bw_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x80, },
+	{0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_sepia_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x40, },
+	{0xdb, 0xa0, },
+};
+
+struct OV7692_WREG ov7692_effect_bluish_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0xc0, },
+	{0xdb, 0x80, },
+};
+
+struct OV7692_WREG ov7692_effect_reddish_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x80, },
+	{0xdb, 0xc0, },
+};
+
+struct OV7692_WREG ov7692_effect_greenish_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x00, },
+	{0xd2, 0x18, },
+	{0xda, 0x60, },
+	{0xdb, 0x60, },
+};
+
+struct OV7692_WREG ov7692_effect_negative_tbl[] = {
+	{0x81, 0x20, INVMASK(0x20)},
+	{0x28, 0x80, },
+	{0xd2, 0x40, },
+	{0xda, 0x80, },
+	{0xdb, 0x80, },
+};
+
+/*Contrast*/
+struct OV7692_WREG ov7692_contrast_lv0_tbl[] = {
+	/*Contrast -4*/
+	{0xb2, 0x29},
+	{0xa3, 0x55},
+	{0xa4, 0x5b},
+	{0xa5, 0x67},
+	{0xa6, 0x7e},
+	{0xa7, 0x89},
+	{0xa8, 0x93},
+	{0xa9, 0x9c},
+	{0xaa, 0xa4},
+	{0xab, 0xac},
+	{0xac, 0xb3},
+	{0xad, 0xbe},
+	{0xae, 0xc7},
+	{0xaf, 0xd5},
+	{0xb0, 0xdd},
+	{0xb1, 0xe1},
+};
+
+struct OV7692_WREG ov7692_contrast_lv1_tbl[] = {
+	/*Contrast -3*/
+	{0xb2, 0x20},
+	{0xa3, 0x43},
+	{0xa4, 0x4a},
+	{0xa5, 0x58},
+	{0xa6, 0x73},
+	{0xa7, 0x80},
+	{0xa8, 0x8b},
+	{0xa9, 0x96},
+	{0xaa, 0x9f},
+	{0xab, 0xa8},
+	{0xac, 0xb1},
+	{0xad, 0xbe},
+	{0xae, 0xc9},
+	{0xaf, 0xd8},
+	{0xb0, 0xe2},
+	{0xb1, 0xe8},
+};
+
+struct OV7692_WREG ov7692_contrast_lv2_tbl[] = {
+	/*Contrast -2*/
+	{0xb2, 0x18},
+	{0xa3, 0x31},
+	{0xa4, 0x39},
+	{0xa5, 0x4a},
+	{0xa6, 0x68},
+	{0xa7, 0x77},
+	{0xa8, 0x84},
+	{0xa9, 0x90},
+	{0xaa, 0x9b},
+	{0xab, 0xa5},
+	{0xac, 0xaf},
+	{0xad, 0xbe},
+	{0xae, 0xca},
+	{0xaf, 0xdc},
+	{0xb0, 0xe7},
+	{0xb1, 0xee},
+};
+
+struct OV7692_WREG ov7692_contrast_lv3_tbl[] = {
+	/*Contrast -1*/
+	{0xb2, 0x10},
+	{0xa3, 0x1f},
+	{0xa4, 0x28},
+	{0xa5, 0x3b},
+	{0xa6, 0x5d},
+	{0xa7, 0x6e},
+	{0xa8, 0x7d},
+	{0xa9, 0x8a},
+	{0xaa, 0x96},
+	{0xab, 0xa2},
+	{0xac, 0xad},
+	{0xad, 0xbe},
+	{0xae, 0xcc},
+	{0xaf, 0xe0},
+	{0xb0, 0xed},
+	{0xb1, 0xf4},
+};
+
+struct OV7692_WREG ov7692_contrast_default_lv4_tbl[] = {
+	/*Contrast 0*/
+	{0xb2, 0x6},
+	{0xa3, 0xb},
+	{0xa4, 0x15},
+	{0xa5, 0x2a},
+	{0xa6, 0x51},
+	{0xa7, 0x63},
+	{0xa8, 0x74},
+	{0xa9, 0x83},
+	{0xaa, 0x91},
+	{0xab, 0x9e},
+	{0xac, 0xaa},
+	{0xad, 0xbe},
+	{0xae, 0xce},
+	{0xaf, 0xe5},
+	{0xb0, 0xf3},
+	{0xb1, 0xfb},
+};
+
+struct OV7692_WREG ov7692_contrast_lv5_tbl[] = {
+	/*Contrast 1*/
+	{0xb2, 0xc},
+	{0xa3, 0x4},
+	{0xa4, 0xc},
+	{0xa5, 0x1f},
+	{0xa6, 0x45},
+	{0xa7, 0x58},
+	{0xa8, 0x6b},
+	{0xa9, 0x7c},
+	{0xaa, 0x8d},
+	{0xab, 0x9d},
+	{0xac, 0xac},
+	{0xad, 0xc3},
+	{0xae, 0xd2},
+	{0xaf, 0xe8},
+	{0xb0, 0xf2},
+	{0xb1, 0xf7},
+};
+
+struct OV7692_WREG ov7692_contrast_lv6_tbl[] = {
+	/*Contrast 2*/
+	{0xb2, 0x1},
+	{0xa3, 0x2},
+	{0xa4, 0x9},
+	{0xa5, 0x1a},
+	{0xa6, 0x3e},
+	{0xa7, 0x4a},
+	{0xa8, 0x59},
+	{0xa9, 0x6a},
+	{0xaa, 0x79},
+	{0xab, 0x8e},
+	{0xac, 0xa4},
+	{0xad, 0xc1},
+	{0xae, 0xdb},
+	{0xaf, 0xf4},
+	{0xb0, 0xff},
+	{0xb1, 0xff},
+};
+
+struct OV7692_WREG ov7692_contrast_lv7_tbl[] = {
+	/*Contrast 3*/
+	{0xb2, 0xc},
+	{0xa3, 0x4},
+	{0xa4, 0x8},
+	{0xa5, 0x17},
+	{0xa6, 0x27},
+	{0xa7, 0x3d},
+	{0xa8, 0x54},
+	{0xa9, 0x60},
+	{0xaa, 0x77},
+	{0xab, 0x85},
+	{0xac, 0xa4},
+	{0xad, 0xc6},
+	{0xae, 0xd2},
+	{0xaf, 0xe9},
+	{0xb0, 0xf0},
+	{0xb1, 0xf7},
+};
+
+struct OV7692_WREG ov7692_contrast_lv8_tbl[] = {
+	/*Contrast 4*/
+	{0xb2, 0x1},
+	{0xa3, 0x4},
+	{0xa4, 0x4},
+	{0xa5, 0x7},
+	{0xa6, 0xb},
+	{0xa7, 0x17},
+	{0xa8, 0x2a},
+	{0xa9, 0x41},
+	{0xaa, 0x59},
+	{0xab, 0x6b},
+	{0xac, 0x8b},
+	{0xad, 0xb1},
+	{0xae, 0xd2},
+	{0xaf, 0xea},
+	{0xb0, 0xf4},
+	{0xb1, 0xff},
+};
+
+	/*Sharpness*/
+struct OV7692_WREG ov7692_sharpness_lv0_tbl[] = {
+	/*Sharpness 0*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0x00, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv1_tbl[] = {
+	/*Sharpness 1*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0x01, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_default_lv2_tbl[] = {
+	/*Sharpness Auto (Default)*/
+	{0xb4, 0x00, INVMASK(0x20)},
+	{0xb6, 0x00, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv3_tbl[] = {
+	/*Sharpness 3*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0x66, INVMASK(0x04)},
+};
+struct OV7692_WREG ov7692_sharpness_lv4_tbl[] = {
+	/*Sharpness 4*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0x99, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv5_tbl[] = {
+	/*Sharpness 5*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0xcc, INVMASK(0x1f)},
+};
+struct OV7692_WREG ov7692_sharpness_lv6_tbl[] = {
+	/*Sharpness 6*/
+	{0xb4, 0x20, INVMASK(0x20)},
+	{0xb6, 0xff, INVMASK(0x1f)},
+};
+
+	/* ISO TYPE*/
+struct OV7692_WREG ov7692_iso_type_auto[] = {
+	/*@@ISO Auto*/
+	{0x14, 0x20, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_100[] = {
+	/*@@ISO 100*/
+	{0x14, 0x00, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_200[] = {
+	/*@@ISO 200*/
+	{0x14, 0x10, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_400[] = {
+	/*@@ISO 400*/
+	{0x14, 0x20, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_800[] = {
+	/*@@ISO 800*/
+	{0x14, 0x30, INVMASK(0x70)},
+};
+
+struct OV7692_WREG ov7692_iso_type_1600[] = {
+	/*@@ISO 1600*/
+	{0x14, 0x40, INVMASK(0x70)},
+};
+
+	/*Light Mode*/
+struct OV7692_WREG ov7692_wb_def[] = {
+	{0x13, 0xf7},
+	{0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_custom[] = {
+	{0x13, 0xf5},
+	{0x01, 0x56},
+	{0x02, 0x50},
+	{0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_inc[] = {
+	{0x13, 0xf5},
+	{0x01, 0x66},
+	{0x02, 0x40},
+	{0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_daylight[] = {
+	{0x13, 0xf5},
+	{0x01, 0x43},
+	{0x02, 0x5d},
+	{0x15, 0x00},
+};
+
+struct OV7692_WREG ov7692_wb_cloudy[] = {
+	{0x13, 0xf5},
+	{0x01, 0x48},
+	{0x02, 0x63},
+	{0x15, 0x00},
+};
+
 #endif
 
diff --git a/drivers/media/video/msm/ov7692_qrd.c b/drivers/media/video/msm/ov7692_qrd.c
index e558e57..d83f28e 100644
--- a/drivers/media/video/msm/ov7692_qrd.c
+++ b/drivers/media/video/msm/ov7692_qrd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/* #define DEBUG */
-
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/i2c.h>
@@ -52,129 +50,9 @@
 
 
 /*============================================================================
-  DATA DECLARATIONS
-  ============================================================================*/
-/*  96MHz PCLK @ 24MHz MCLK */
-struct reg_addr_val_pair_struct ov7692_init_settings_array[] = {
-	{0x12, 0x80},
-	{0x0e, 0x08},
-	{0x69, 0x52},
-	{0x1e, 0xb3},
-	{0x48, 0x42},
-	{0xff, 0x01},
-	{0xae, 0xa0},
-	{0xa8, 0x26},
-	{0xb4, 0xc0},
-	{0xb5, 0x40},
-	{0xff, 0x00},
-	{0x0c, 0x00},
-	{0x62, 0x10},
-	{0x12, 0x00},
-	{0x17, 0x65},
-	{0x18, 0xa4},
-	{0x19, 0x0a},
-	{0x1a, 0xf6},
-	{0x3e, 0x30},
-	{0x64, 0x0a},
-	{0xff, 0x01},
-	{0xb4, 0xc0},
-	{0xff, 0x00},
-	{0x67, 0x20},
-	{0x81, 0x3f},
-	{0xcc, 0x02},
-	{0xcd, 0x80},
-	{0xce, 0x01},
-	{0xcf, 0xe0},
-	{0xc8, 0x02},
-	{0xc9, 0x80},
-	{0xca, 0x01},
-	{0xcb, 0xe0},
-	{0xd0, 0x48},
-	{0x82, 0x03},
-	{0x0e, 0x00},
-	{0x70, 0x00},
-	{0x71, 0x34},
-	{0x74, 0x28},
-	{0x75, 0x98},
-	{0x76, 0x00},
-	{0x77, 0x64},
-	{0x78, 0x01},
-	{0x79, 0xc2},
-	{0x7a, 0x4e},
-	{0x7b, 0x1f},
-	{0x7c, 0x00},
-	{0x11, 0x00},
-	{0x20, 0x00},
-	{0x21, 0x23},
-	{0x50, 0x9a},
-	{0x51, 0x80},
-	{0x4c, 0x7d},
-	{0x0e, 0x00},
-	{0x85, 0x10},
-	{0x86, 0x00},
-	{0x87, 0x00},
-	{0x88, 0x00},
-	{0x89, 0x2a},
-	{0x8a, 0x26},
-	{0x8b, 0x22},
-	{0xbb, 0x7a},
-	{0xbc, 0x69},
-	{0xbd, 0x11},
-	{0xbe, 0x13},
-	{0xbf, 0x81},
-	{0xc0, 0x96},
-	{0xc1, 0x1e},
-	{0xb7, 0x05},
-	{0xb8, 0x09},
-	{0xb9, 0x00},
-	{0xba, 0x18},
-	{0x5a, 0x1f},
-	{0x5b, 0x9f},
-	{0x5c, 0x6a},
-	{0x5d, 0x42},
-	{0x24, 0x78},
-	{0x25, 0x68},
-	{0x26, 0xb3},
-	{0xa3, 0x0b},
-	{0xa4, 0x15},
-	{0xa5, 0x2a},
-	{0xa6, 0x51},
-	{0xa7, 0x63},
-	{0xa8, 0x74},
-	{0xa9, 0x83},
-	{0xaa, 0x91},
-	{0xab, 0x9e},
-	{0xac, 0xaa},
-	{0xad, 0xbe},
-	{0xae, 0xce},
-	{0xaf, 0xe5},
-	{0xb0, 0xf3},
-	{0xb1, 0xfb},
-	{0xb2, 0x06},
-	{0x8c, 0x5c},
-	{0x8d, 0x11},
-	{0x8e, 0x12},
-	{0x8f, 0x19},
-	{0x90, 0x50},
-	{0x91, 0x20},
-	{0x92, 0x96},
-	{0x93, 0x80},
-	{0x94, 0x13},
-	{0x95, 0x1b},
-	{0x96, 0xff},
-	{0x97, 0x00},
-	{0x98, 0x3d},
-	{0x99, 0x36},
-	{0x9a, 0x51},
-	{0x9b, 0x43},
-	{0x9c, 0xf0},
-	{0x9d, 0xf0},
-	{0x9e, 0xf0},
-	{0x9f, 0xff},
-	{0xa0, 0x68},
-	{0xa1, 0x62},
-	{0xa2, 0x0e},
-};
+			DATA DECLARATIONS
+============================================================================*/
+
 
 static bool OV7692_CSI_CONFIG;
 /* 816x612, 24MHz MCLK 96MHz PCLK */
@@ -214,6 +92,10 @@
 static struct ov7692_ctrl_t *ov7692_ctrl;
 static DECLARE_WAIT_QUEUE_HEAD(ov7692_wait_queue);
 DEFINE_MUTEX(ov7692_mut);
+static int effect_value;
+static int16_t ov7692_effect = CAMERA_EFFECT_OFF;
+static unsigned int SAT_U = 0x80;
+static unsigned int SAT_V = 0x80;
 
 /*=============================================================*/
 
@@ -284,14 +166,33 @@
 	memset(buf, 0, sizeof(buf));
 	buf[0] = waddr;
 	buf[1] = bdata;
-
+	CDBG("i2c_write_b addr = 0x%x, val = 0x%x\n", waddr, bdata);
 	rc = ov7692_i2c_txdata(ov7692_client->addr >> 1, buf, 2);
 	if (rc < 0)
 		CDBG("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
-				waddr, bdata);
+		waddr, bdata);
+
 	return rc;
 }
 
+static int32_t OV7692_WritePRegs(struct OV7692_WREG *pTb, int32_t len)
+{
+	int32_t i, ret = 0;
+	uint8_t regv;
+
+	for (i = 0; i < len; i++) {
+		if (pTb[i].mask == 0) {
+			ov7692_i2c_write_b_sensor(pTb[i].addr, pTb[i].data);
+		} else {
+			ov7692_i2c_read(pTb[i].addr, &regv, 1);
+			regv &= pTb[i].mask;
+			regv |= (pTb[i].data & (~pTb[i].mask));
+			ov7692_i2c_write_b_sensor(pTb[i].addr, regv);
+		}
+	}
+	return ret;
+}
+
 static int32_t ov7692_sensor_setting(int update_type, int rt)
 {
 	int32_t i, array_length;
@@ -314,8 +215,6 @@
 			ov7692_csi_params.dpcm_scheme = 0;
 			ov7692_csi_params.settle_cnt = 0x14;
 
-			rc = msm_camio_csi_config(&ov7692_csi_params);
-			msleep(20);
 			array_length = sizeof(ov7692_init_settings_array) /
 				sizeof(ov7692_init_settings_array[0]);
 			for (i = 0; i < array_length; i++) {
@@ -325,6 +224,10 @@
 				if (rc < 0)
 					return rc;
 			}
+			usleep_range(10000, 11000);
+			rc = msm_camio_csi_config(&ov7692_csi_params);
+			usleep_range(10000, 11000);
+			ov7692_i2c_write_b_sensor(0x0e, 0x00);
 			OV7692_CSI_CONFIG = 1;
 			msleep(20);
 			return rc;
@@ -371,6 +274,442 @@
 	return rc;
 }
 
+static int ov7692_set_exposure_compensation(int compensation)
+{
+	long rc = 0;
+
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...exposure_compensation = %d\n",
+		 __func__ , compensation);
+	switch (compensation) {
+	case CAMERA_EXPOSURE_COMPENSATION_LV0:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV0\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv0_tbl);
+		break;
+	case CAMERA_EXPOSURE_COMPENSATION_LV1:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV1\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv1_tbl);
+		break;
+	case CAMERA_EXPOSURE_COMPENSATION_LV2:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV2\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv2_default_tbl);
+		break;
+	case CAMERA_EXPOSURE_COMPENSATION_LV3:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV3\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv3_tbl);
+		break;
+	case CAMERA_EXPOSURE_COMPENSATION_LV4:
+		CDBG("--CAMERA--CAMERA_EXPOSURE_COMPENSATION_LV3\n");
+		rc = OV7692Core_WritePREG(
+			ov7692_exposure_compensation_lv4_tbl);
+		break;
+	default:
+		CDBG("--CAMERA--ERROR CAMERA_EXPOSURE_COMPENSATION\n");
+		break;
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static long ov7692_set_antibanding(int antibanding)
+{
+	long rc = 0;
+
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...antibanding = %d\n", __func__, antibanding);
+	switch (antibanding) {
+	case CAMERA_ANTIBANDING_OFF:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_OFF\n");
+		break;
+	case CAMERA_ANTIBANDING_60HZ:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_60HZ\n");
+		rc = OV7692Core_WritePREG(ov7692_antibanding_60z_tbl);
+		break;
+	case CAMERA_ANTIBANDING_50HZ:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_50HZ\n");
+		rc = OV7692Core_WritePREG(ov7692_antibanding_50z_tbl);
+		break;
+	case CAMERA_ANTIBANDING_AUTO:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_AUTO\n");
+		rc = OV7692Core_WritePREG(ov7692_antibanding_auto_tbl);
+		break;
+	default:
+		CDBG("--CAMERA--CAMERA_ANTIBANDING_ERROR COMMAND\n");
+		break;
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_saturation(int saturation)
+{
+	long rc = 0;
+
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...saturation = %d\n", __func__ , saturation);
+
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		switch (saturation) {
+		case CAMERA_SATURATION_LV0:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV0\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv0_tbl);
+			break;
+		case CAMERA_SATURATION_LV1:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV1\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv1_tbl);
+			break;
+		case CAMERA_SATURATION_LV2:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV2\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv2_tbl);
+			break;
+		case CAMERA_SATURATION_LV3:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV3\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv3_tbl);
+			break;
+		case CAMERA_SATURATION_LV4:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV4\n");
+			rc = OV7692Core_WritePREG(
+				ov7692_saturation_default_lv4_tbl);
+			break;
+		case CAMERA_SATURATION_LV5:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV5\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv5_tbl);
+			break;
+		case CAMERA_SATURATION_LV6:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV6\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv6_tbl);
+			break;
+		case CAMERA_SATURATION_LV7:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV7\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv7_tbl);
+			break;
+		case CAMERA_SATURATION_LV8:
+			CDBG("--CAMERA--CAMERA_SATURATION_LV8\n");
+			rc = OV7692Core_WritePREG(ov7692_saturation_lv8_tbl);
+			break;
+		default:
+			CDBG("--CAMERA--CAMERA_SATURATION_ERROR COMMAND\n");
+			break;
+		}
+	}
+
+	/*for recover saturation level when change special effect*/
+	switch (saturation) {
+	case CAMERA_SATURATION_LV0:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV0\n");
+		SAT_U = 0x00;
+		SAT_V = 0x00;
+		break;
+	case CAMERA_SATURATION_LV1:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV1\n");
+		SAT_U = 0x10;
+		SAT_V = 0x10;
+		break;
+	case CAMERA_SATURATION_LV2:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV2\n");
+		SAT_U = 0x20;
+		SAT_V = 0x20;
+		break;
+	case CAMERA_SATURATION_LV3:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV3\n");
+		SAT_U = 0x30;
+		SAT_V = 0x30;
+		break;
+	case CAMERA_SATURATION_LV4:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV4\n");
+		SAT_U = 0x40;
+		SAT_V = 0x40;
+		break;
+	case CAMERA_SATURATION_LV5:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV5\n");
+		SAT_U = 0x50;
+		SAT_V = 0x50;
+		break;
+	case CAMERA_SATURATION_LV6:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV6\n");
+		SAT_U = 0x60;
+		SAT_V = 0x60;
+		break;
+	case CAMERA_SATURATION_LV7:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV7\n");
+		SAT_U = 0x70;
+		SAT_V = 0x70;
+		break;
+	case CAMERA_SATURATION_LV8:
+		CDBG("--CAMERA--CAMERA_SATURATION_LV8\n");
+		SAT_U = 0x80;
+		SAT_V = 0x80;
+		break;
+	default:
+		CDBG("--CAMERA--CAMERA_SATURATION_ERROR COMMAND\n");
+		break;
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static long ov7692_set_effect(int mode, int effect)
+{
+	int rc = 0;
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+
+	switch (mode) {
+	case SENSOR_PREVIEW_MODE:
+		break;
+	case SENSOR_HFR_60FPS_MODE:
+		break;
+	case SENSOR_HFR_90FPS_MODE:
+		/* Context A Special Effects */
+		CDBG("-CAMERA- %s ...SENSOR_PREVIEW_MODE\n", __func__);
+		break;
+	case SENSOR_SNAPSHOT_MODE:
+		/* Context B Special Effects */
+		CDBG("-CAMERA- %s ...SENSOR_SNAPSHOT_MODE\n", __func__);
+		break;
+	default:
+		break;
+	}
+	effect_value = effect;
+	switch (effect) {
+	case CAMERA_EFFECT_OFF: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_OFF\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_normal_tbl);
+		/* for recover saturation level
+		 when change special effect*/
+		ov7692_i2c_write_b_sensor(0xda, SAT_U);
+		/* for recover saturation level
+		when change special effect*/
+		ov7692_i2c_write_b_sensor(0xdb, SAT_V);
+		break;
+	}
+	case CAMERA_EFFECT_MONO: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_MONO\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_mono_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_BW: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_BW\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_bw_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_BLUISH: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_BLUISH\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_bluish_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_SOLARIZE: {
+		CDBG("%s ...CAMERA_EFFECT_NEGATIVE(No Support)!\n", __func__);
+		break;
+	}
+	case CAMERA_EFFECT_SEPIA: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_SEPIA\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_sepia_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_REDDISH: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_REDDISH\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_reddish_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_GREENISH: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_GREENISH\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_greenish_tbl);
+		break;
+	}
+	case CAMERA_EFFECT_NEGATIVE: {
+		CDBG("--CAMERA-- %s ...CAMERA_EFFECT_NEGATIVE\n", __func__);
+		rc = OV7692Core_WritePREG(ov7692_effect_negative_tbl);
+		break;
+	}
+	default: {
+		CDBG("--CAMERA-- %s ...Default(Not Support)\n", __func__);
+	}
+	}
+	ov7692_effect = effect;
+	/*Refresh Sequencer */
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_contrast(int contrast)
+{
+	int rc = 0;
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...contrast = %d\n", __func__ , contrast);
+
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		switch (contrast) {
+		case CAMERA_CONTRAST_LV0:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV0\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv0_tbl);
+			break;
+		case CAMERA_CONTRAST_LV1:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV1\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv1_tbl);
+			break;
+		case CAMERA_CONTRAST_LV2:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV2\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv2_tbl);
+			break;
+		case CAMERA_CONTRAST_LV3:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV3\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv3_tbl);
+			break;
+		case CAMERA_CONTRAST_LV4:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV4\n");
+			rc = OV7692Core_WritePREG(
+				ov7692_contrast_default_lv4_tbl);
+			break;
+		case CAMERA_CONTRAST_LV5:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV5\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv5_tbl);
+			break;
+		case CAMERA_CONTRAST_LV6:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV6\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv6_tbl);
+			break;
+		case CAMERA_CONTRAST_LV7:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV7\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv7_tbl);
+			break;
+		case CAMERA_CONTRAST_LV8:
+			CDBG("--CAMERA--CAMERA_CONTRAST_LV8\n");
+			rc = OV7692Core_WritePREG(ov7692_contrast_lv8_tbl);
+			break;
+		default:
+			CDBG("--CAMERA--CAMERA_CONTRAST_ERROR COMMAND\n");
+			break;
+		}
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_sharpness(int sharpness)
+{
+	int rc = 0;
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...sharpness = %d\n", __func__ , sharpness);
+
+	if (effect_value == CAMERA_EFFECT_OFF) {
+		switch (sharpness) {
+		case CAMERA_SHARPNESS_LV0:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV0\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv0_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV1:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV1\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv1_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV2:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV2\n");
+			rc = OV7692Core_WritePREG(
+				ov7692_sharpness_default_lv2_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV3:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV3\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv3_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV4:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV4\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv4_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV5:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV5\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv5_tbl);
+			break;
+		case CAMERA_SHARPNESS_LV6:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_LV6\n");
+			rc = OV7692Core_WritePREG(ov7692_sharpness_lv6_tbl);
+			break;
+		default:
+			CDBG("--CAMERA--CAMERA_SHARPNESS_ERROR COMMAND\n");
+			break;
+		}
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_iso(int8_t iso_type)
+{
+	long rc = 0;
+
+	CDBG("--CAMERA-- %s ...(Start)\n", __func__);
+	CDBG("--CAMERA-- %s ...iso_type = %d\n", __func__ , iso_type);
+	switch (iso_type) {
+	case CAMERA_ISO_TYPE_AUTO:
+		CDBG("--CAMERA--CAMERA_ISO_TYPE_AUTO\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_auto);
+		break;
+	case CAMEAR_ISO_TYPE_HJR:
+		CDBG("--CAMERA--CAMEAR_ISO_TYPE_HJR\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_auto);
+		break;
+	case CAMEAR_ISO_TYPE_100:
+		CDBG("--CAMERA--CAMEAR_ISO_TYPE_100\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_100);
+		break;
+	case CAMERA_ISO_TYPE_200:
+		CDBG("--CAMERA--CAMERA_ISO_TYPE_200\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_200);
+		break;
+	case CAMERA_ISO_TYPE_400:
+		CDBG("--CAMERA--CAMERA_ISO_TYPE_400\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_400);
+		break;
+	case CAMEAR_ISO_TYPE_800:
+		CDBG("--CAMERA--CAMEAR_ISO_TYPE_800\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_800);
+		break;
+	case CAMERA_ISO_TYPE_1600:
+		CDBG("--CAMERA--CAMERA_ISO_TYPE_1600\n");
+		rc = OV7692Core_WritePREG(ov7692_iso_type_1600);
+		break;
+	default:
+		CDBG("--CAMERA--ERROR ISO TYPE\n");
+		break;
+	}
+	CDBG("--CAMERA-- %s ...(End)\n", __func__);
+	return rc;
+}
+
+static int ov7692_set_wb_oem(uint8_t param)
+{
+	int rc = 0;
+	CDBG("--CAMERA--%s runs\r\n", __func__);
+
+	switch (param) {
+	case CAMERA_WB_AUTO:
+		CDBG("--CAMERA--CAMERA_WB_AUTO\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_def);
+		break;
+	case CAMERA_WB_CUSTOM:
+		CDBG("--CAMERA--CAMERA_WB_CUSTOM\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_custom);
+		break;
+	case CAMERA_WB_INCANDESCENT:
+		CDBG("--CAMERA--CAMERA_WB_INCANDESCENT\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_inc);
+		break;
+	case CAMERA_WB_DAYLIGHT:
+		CDBG("--CAMERA--CAMERA_WB_DAYLIGHT\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_daylight);
+		break;
+	case CAMERA_WB_CLOUDY_DAYLIGHT:
+		CDBG("--CAMERA--CAMERA_WB_CLOUDY_DAYLIGHT\n");
+		rc = OV7692Core_WritePREG(ov7692_wb_cloudy);
+		break;
+	default:
+		break;
+	}
+	return rc;
+}
+
 static void ov7692_power_on(void)
 {
 	CDBG("%s\n", __func__);
@@ -392,13 +731,12 @@
 static void ov7692_hw_reset(void)
 {
 	CDBG("--CAMERA-- %s ... (Start...)\n", __func__);
-	gpio_set_value(ov7692_reset_gpio, 1);   /* reset camera reset pin */
-	msleep(20);
+	gpio_set_value(ov7692_reset_gpio, 1);   /*reset camera reset pin*/
+	usleep_range(5000, 5100);
 	gpio_set_value(ov7692_reset_gpio, 0);
-	msleep(20);
+	usleep_range(5000, 5100);
 	gpio_set_value(ov7692_reset_gpio, 1);
-	msleep(20);
-
+	usleep_range(1000, 1100);
 	CDBG("--CAMERA-- %s ... (End...)\n", __func__);
 }
 
@@ -458,6 +796,9 @@
 
 	if (data)
 		ov7692_ctrl->sensordata = data;
+	/* turn on LDO for PVT */
+	if (data->pmic_gpio_enable)
+		lcd_camera_power_onoff(1);
 
 	/* enable mclk first */
 
@@ -465,7 +806,7 @@
 	msleep(20);
 
 	ov7692_power_on();
-	msleep(20);
+	usleep_range(5000, 5100);
 
 	rc = ov7692_probe_init_sensor(data);
 	if (rc < 0) {
@@ -481,6 +822,8 @@
 
 init_fail:
 	CDBG(" ov7692_sensor_open_init fail\n");
+	if (data->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
 	kfree(ov7692_ctrl);
 init_done:
 	CDBG("ov7692_sensor_open_init done\n");
@@ -559,14 +902,160 @@
 	CDBG("ov7692_sensor_config: cfgtype = %d\n", cdata.cfgtype);
 	switch (cdata.cfgtype) {
 	case CFG_SET_MODE:
-		rc = ov7692_set_sensor_mode(cdata.mode,
-				cdata.rs);
+		rc = ov7692_set_sensor_mode(cdata.mode, cdata.rs);
+		break;
+	case CFG_SET_EFFECT:
+		CDBG("--CAMERA-- CFG_SET_EFFECT mode=%d, effect = %d !!\n",
+			 cdata.mode, cdata.cfg.effect);
+		rc = ov7692_set_effect(cdata.mode, cdata.cfg.effect);
+		break;
+	case CFG_START:
+		CDBG("--CAMERA-- CFG_START (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_PWR_UP:
+		CDBG("--CAMERA-- CFG_PWR_UP (Not Support) !!\n");
+		/* Not Support */
 		break;
 	case CFG_PWR_DOWN:
+		CDBG("--CAMERA-- CFG_PWR_DOWN !!\n");
 		ov7692_power_down();
 		break;
+	case CFG_WRITE_EXPOSURE_GAIN:
+		CDBG("--CAMERA-- CFG_WRITE_EXPOSURE_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_DEFAULT_FOCUS:
+		CDBG("--CAMERA-- CFG_SET_DEFAULT_FOCUS (Not Implement) !!\n");
+		break;
+	case CFG_MOVE_FOCUS:
+		CDBG("--CAMERA-- CFG_MOVE_FOCUS (Not Implement) !!\n");
+		break;
+	case CFG_REGISTER_TO_REAL_GAIN:
+		CDBG("--CAMERA-- CFG_REGISTER_TO_REAL_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_REAL_TO_REGISTER_GAIN:
+		CDBG("--CAMERA-- CFG_REAL_TO_REGISTER_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_FPS:
+		CDBG("--CAMERA-- CFG_SET_FPS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_PICT_FPS:
+		CDBG("--CAMERA-- CFG_SET_PICT_FPS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_BRIGHTNESS:
+		CDBG("--CAMERA-- CFG_SET_BRIGHTNESS  !!\n");
+		/* rc = ov7692_set_brightness(cdata.cfg.brightness); */
+		break;
+	case CFG_SET_CONTRAST:
+		CDBG("--CAMERA-- CFG_SET_CONTRAST  !!\n");
+		rc = ov7692_set_contrast(cdata.cfg.contrast);
+		break;
+	case CFG_SET_ZOOM:
+		CDBG("--CAMERA-- CFG_SET_ZOOM (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_EXPOSURE_MODE:
+		CDBG("--CAMERA-- CFG_SET_EXPOSURE_MODE !!\n");
+		/* rc = ov7692_set_exposure_mode(cdata.cfg.ae_mode); */
+		break;
+	case CFG_SET_WB:
+		CDBG("--CAMERA-- CFG_SET_WB!!\n");
+		ov7692_set_wb_oem(cdata.cfg.wb_val);
+		rc = 0 ;
+		break;
+	case CFG_SET_ANTIBANDING:
+		CDBG("--CAMERA-- CFG_SET_ANTIBANDING antibanding = %d !!\n",
+			 cdata.cfg.antibanding);
+		rc = ov7692_set_antibanding(cdata.cfg.antibanding);
+		break;
+	case CFG_SET_EXP_GAIN:
+		CDBG("--CAMERA-- CFG_SET_EXP_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_PICT_EXP_GAIN:
+		CDBG("--CAMERA-- CFG_SET_PICT_EXP_GAIN (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_LENS_SHADING:
+		CDBG("--CAMERA-- CFG_SET_LENS_SHADING !!\n");
+		/* rc = ov7692_lens_shading_enable(cdata.cfg.lens_shading); */
+		break;
+	case CFG_GET_PICT_FPS:
+		CDBG("--CAMERA-- CFG_GET_PICT_FPS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PREV_L_PF:
+		CDBG("--CAMERA-- CFG_GET_PREV_L_PF (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PREV_P_PL:
+		CDBG("--CAMERA-- CFG_GET_PREV_P_PL (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PICT_L_PF:
+		CDBG("--CAMERA-- CFG_GET_PICT_L_PF (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PICT_P_PL:
+		CDBG("--CAMERA-- CFG_GET_PICT_P_PL (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_AF_MAX_STEPS:
+		CDBG("--CAMERA-- CFG_GET_AF_MAX_STEPS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_GET_PICT_MAX_EXP_LC:
+		CDBG("--CAMERA-- CFG_GET_PICT_MAX_EXP_LC (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SEND_WB_INFO:
+		CDBG("--CAMERA-- CFG_SEND_WB_INFO (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SENSOR_INIT:
+		CDBG("--CAMERA-- CFG_SENSOR_INIT (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_SATURATION:
+		CDBG("--CAMERA-- CFG_SET_SATURATION !!\n");
+		rc = ov7692_set_saturation(cdata.cfg.saturation);
+		break;
+	case CFG_SET_SHARPNESS:
+		CDBG("--CAMERA-- CFG_SET_SHARPNESS !!\n");
+		rc = ov7692_set_sharpness(cdata.cfg.sharpness);
+		break;
+	case CFG_SET_TOUCHAEC:
+		CDBG("--CAMERA-- CFG_SET_TOUCHAEC!!\n");
+		/* ov7692_set_touchaec(cdata.cfg.aec_cord.x,
+			 cdata.cfg.aec_cord.y); */
+		rc = 0 ;
+		break;
+	case CFG_SET_AUTO_FOCUS:
+		CDBG("--CAMERA-- CFG_SET_AUTO_FOCUS (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_AUTOFLASH:
+		CDBG("--CAMERA-- CFG_SET_AUTOFLASH (Not Support) !!\n");
+		/* Not Support */
+		break;
+	case CFG_SET_EXPOSURE_COMPENSATION:
+		CDBG("--CAMERA-- CFG_SET_EXPOSURE_COMPENSATION !\n");
+		rc = ov7692_set_exposure_compensation(
+			cdata.cfg.exp_compensation);
+		break;
+	case CFG_SET_ISO:
+		CDBG("--CAMERA-- CFG_SET_ISO !\n");
+		rc = ov7692_set_iso(cdata.cfg.iso_type);
+		break;
 	default:
-		rc = -EFAULT;
+		CDBG("--CAMERA-- %s: Command=%d (Not Implement) !!\n",
+			 __func__, cdata.cfgtype);
+		rc = -EINVAL;
 		break;
 	}
 
@@ -577,6 +1066,7 @@
 static int ov7692_sensor_release(void)
 {
 	int rc = -EBADF;
+
 	mutex_lock(&ov7692_mut);
 	ov7692_sw_reset();
 	ov7692_power_down();
@@ -614,20 +1104,23 @@
 		rc = -ENOTSUPP;
 		goto probe_fail;
 	}
-
+	pr_debug("%s: %d Entered\n", __func__, __LINE__);
 	rc = ov7692_probe_init_gpio(info);
 	if (rc < 0) {
 		CDBG("%s: gpio init failed\n", __func__);
 		goto probe_fail;
 	}
+	/* turn on LDO for PVT */
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(1);
 
 	ov7692_power_down();
 
 	msm_camio_clk_rate_set(24000000);
-	msleep(20);
+	usleep_range(5000, 5100);
 
 	ov7692_power_on();
-	msleep(20);
+	usleep_range(5000, 5100);
 
 	if (info->sensor_reset_enable)
 		ov7692_hw_reset();
@@ -645,12 +1138,18 @@
 	s->s_camera_type = FRONT_CAMERA_2D;
 	s->s_mount_angle = info->sensor_platform_info->mount_angle;
 
+	/* ov7692_sw_reset(); */
 	ov7692_power_down();
 
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
+
 	return rc;
 
 probe_fail:
 	CDBG("ov7692_sensor_probe: SENSOR PROBE FAILS!\n");
+	if (info->pmic_gpio_enable)
+		lcd_camera_power_onoff(0);
 	i2c_del_driver(&ov7692_i2c_driver);
 	return rc;
 }
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index f31aece..92700f6 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -38,7 +38,7 @@
 static struct msm_camera_i2c_reg_conf imx074_prev_settings[] = {
 	{0x0307, 0x2D}, /*pll_multiplier*/
 	{0x0340, 0x06}, /*frame_length_lines_hi*/
-	{0x0341, 0x2D}, /*frame_length_lines_lo*/
+	{0x0341, 0x34}, /*frame_length_lines_lo*/
 	{0x0342, 0x11}, /*line_length_pclk_hi*/
 	{0x0343, 0x78}, /*line_length_pclk_lo*/
 	{0x0347, 0x00}, /*y_addr_start*/
@@ -161,9 +161,9 @@
 		.x_output = 0x838,
 		.y_output = 0x618,
 		.line_length_pclk = 0x1178,
-		.frame_length_lines = 0x62D,
+		.frame_length_lines = 0x634,
 		.vt_pixel_clk = 216000000,
-		.op_pixel_clk = 216000000,
+		.op_pixel_clk = 108000000,
 		.binning_factor = 2,
 	},
 };
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d0b4f1f..cade3d6 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -13,6 +13,7 @@
 #include "msm_sensor.h"
 #include "msm.h"
 #include "msm_ispif.h"
+#include "msm_camera_i2c_mux.h"
 
 /*=============================================================*/
 
@@ -449,6 +450,26 @@
 	{"cam_clk", MSM_SENSOR_MCLK_24HZ},
 };
 
+int32_t msm_sensor_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_INIT, NULL);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_CFG, (void *)&i2c_conf->i2c_mux_mode);
+	return 0;
+}
+
+int32_t msm_sensor_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+				VIDIOC_MSM_I2C_MUX_RELEASE, NULL);
+	return 0;
+}
+
 int32_t msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
 {
 	int32_t rc = 0;
@@ -506,6 +527,10 @@
 	if (data->sensor_platform_info->ext_power_ctrl != NULL)
 		data->sensor_platform_info->ext_power_ctrl(1);
 
+	if (data->sensor_platform_info->i2c_conf &&
+		data->sensor_platform_info->i2c_conf->use_i2c_mux)
+		msm_sensor_enable_i2c_mux(data->sensor_platform_info->i2c_conf);
+
 	return rc;
 enable_clk_failed:
 		msm_camera_config_gpio_table(data, 0);
@@ -531,6 +556,11 @@
 {
 	struct msm_camera_sensor_info *data = s_ctrl->sensordata;
 	CDBG("%s\n", __func__);
+	if (data->sensor_platform_info->i2c_conf &&
+		data->sensor_platform_info->i2c_conf->use_i2c_mux)
+		msm_sensor_disable_i2c_mux(
+			data->sensor_platform_info->i2c_conf);
+
 	if (data->sensor_platform_info->ext_power_ctrl != NULL)
 		data->sensor_platform_info->ext_power_ctrl(0);
 	msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index 2177991..954dd2f 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -114,8 +114,8 @@
 	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
 	{0x0306, 0x00}, /* pll_multiplier */
 	{0x0307, 0xA5}, /* pll_multiplier */
-	{0x0202, 0x02}, /* coarse_integration_time */
-	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0202, 0x03}, /* coarse_integration_time */
+	{0x0203, 0xD8}, /* coarse_integration_time */
 	{0x0340, 0x03}, /* frame_length_lines */
 	{0x0341, 0xE0}, /* frame_length_lines */
 	{0x0342, 0x14}, /* line_length_pck */
@@ -152,7 +152,7 @@
 	{0x0306, 0x00}, /* pll_multiplier */
 	{0x0307, 0xA5}, /* pll_multiplier */
 	{0x0202, 0x02}, /* coarse_integration_time */
-	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0203, 0x90}, /* coarse_integration_time */
 	{0x0340, 0x02}, /* frame_length_lines */
 	{0x0341, 0x98}, /* frame_length_lines */
 	{0x0342, 0x14}, /* line_length_pck */
@@ -188,10 +188,10 @@
 	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
 	{0x0306, 0x00}, /* pll_multiplier */
 	{0x0307, 0xA5}, /* pll_multiplier */
-	{0x0202, 0x02}, /* coarse_integration_time */
-	{0x0203, 0x1C}, /* coarse_integration_time */
+	{0x0202, 0x01}, /* coarse_integration_time */
+	{0x0203, 0xFA}, /* coarse_integration_time */
 	{0x0340, 0x02}, /* frame_length_lines */
-	{0x0341, 0x0D}, /* frame_length_lines */
+	{0x0341, 0x02}, /* frame_length_lines */
 	{0x0342, 0x14}, /* line_length_pck */
 	{0x0343, 0xD8}, /* line_length_pck */
 	{0x0344, 0x01}, /* x_addr_start */
@@ -519,7 +519,7 @@
 		.x_output = 864,
 		.y_output = 480,
 		.line_length_pclk = 5336,
-		.frame_length_lines = 525,
+		.frame_length_lines = 514,
 		.vt_pixel_clk = 330000000,
 		.op_pixel_clk = 320000000,
 		.binning_factor = 1,
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index e4d8bd5..6be3f2d 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -42,7 +42,7 @@
 #define PM8921_VERSION_MASK	0xFFF0
 #define PM8921_VERSION_VALUE	0x06F0
 #define PM8922_VERSION_VALUE	0x0AF0
-#define PM8917_VERSION_VALUE	0x12F0
+#define PM8917_VERSION_VALUE	0x0CF0
 #define PM8921_REVISION_MASK	0x000F
 
 #define REG_PM8921_PON_CNTRL_3	0x01D
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index eb0048a..b655848 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -139,6 +139,12 @@
 #define PM8901_DELAY_AFTER_REG_DISABLE_MS	4
 #define PM8901_DELAY_BEFORE_SHUTDOWN_MS		8
 
+#define REG_PM8XXX_XO_CNTRL_2	0x114
+#define MP3_1_MASK	0xE0
+#define MP3_2_MASK	0x1C
+#define MP3_1_SHIFT	5
+#define MP3_2_SHIFT	2
+
 struct pm8xxx_misc_chip {
 	struct list_head			link;
 	struct pm8xxx_misc_platform_data	pdata;
@@ -540,7 +546,7 @@
 		case PM8XXX_VERSION_8018:
 			rc = pm8xxx_misc_masked_write(chip,
 				REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
-				(enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+				(enable ? SLEEP_CTRL_SMPL_EN_RESET
 					   : SLEEP_CTRL_SMPL_EN_PWR_OFF));
 			break;
 		case PM8XXX_VERSION_8058:
@@ -552,7 +558,7 @@
 		case PM8XXX_VERSION_8921:
 			rc = pm8xxx_misc_masked_write(chip,
 				REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
-				(enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+				(enable ? SLEEP_CTRL_SMPL_EN_RESET
 					   : SLEEP_CTRL_SMPL_EN_PWR_OFF));
 			break;
 		default:
@@ -1046,6 +1052,48 @@
 }
 EXPORT_SYMBOL_GPL(pm8xxx_preload_dVdd);
 
+int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+				enum pm8xxx_aux_clk_div divider, bool enable)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	u8 clk_mask = 0, value = 0;
+
+	if (clk_id == CLK_MP3_1) {
+		clk_mask = MP3_1_MASK;
+		value = divider << MP3_1_SHIFT;
+	} else if (clk_id == CLK_MP3_2) {
+		clk_mask = MP3_2_MASK;
+		value = divider << MP3_2_SHIFT;
+	} else {
+		pr_err("Invalid clock id of %d\n", clk_id);
+		return -EINVAL;
+	}
+	if (!enable)
+		value = 0;
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8038:
+		case PM8XXX_VERSION_8921:
+			pm8xxx_misc_masked_write(chip,
+					REG_PM8XXX_XO_CNTRL_2, clk_mask, value);
+			break;
+		default:
+			/* Functionality not supported */
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_aux_clk_control);
+
 static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
 {
 	const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index 87abcda..56774e9 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.c
@@ -241,6 +241,12 @@
 	},
 };
 
+static struct mfd_cell tabla1x_devs[] = {
+	{
+		.name = "tabla1x_codec",
+	},
+};
+
 static void tabla_bring_up(struct tabla *tabla)
 {
 	tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x4);
@@ -367,6 +373,8 @@
 static int tabla_device_init(struct tabla *tabla, int irq)
 {
 	int ret;
+	struct mfd_cell *tabla_dev;
+	int tabla_dev_size;
 
 	mutex_init(&tabla->io_lock);
 	mutex_init(&tabla->xfer_lock);
@@ -386,9 +394,19 @@
 		pr_err("IRQ initialization failed\n");
 		goto err;
 	}
+	tabla->version = tabla_reg_read(tabla, TABLA_A_CHIP_VERSION) & 0x1F;
+	pr_info("%s : Tabla version %u initialized\n",
+		__func__, tabla->version);
 
+	if (TABLA_IS_1_X(tabla->version)) {
+		tabla_dev = tabla1x_devs;
+		tabla_dev_size = ARRAY_SIZE(tabla1x_devs);
+	} else {
+		tabla_dev = tabla_devs;
+		tabla_dev_size = ARRAY_SIZE(tabla_devs);
+	}
 	ret = mfd_add_devices(tabla->dev, -1,
-			      tabla_devs, ARRAY_SIZE(tabla_devs),
+			      tabla_dev, tabla_dev_size,
 			      NULL, 0);
 	if (ret != 0) {
 		dev_err(tabla->dev, "Failed to add children: %d\n", ret);
diff --git a/drivers/misc/pmem.c b/drivers/misc/pmem.c
index f0d523e..2f48d71 100644
--- a/drivers/misc/pmem.c
+++ b/drivers/misc/pmem.c
@@ -2785,7 +2785,8 @@
 	pmem[id].dev.name = pdata->name;
 	pmem[id].dev.minor = id;
 	pmem[id].dev.fops = &pmem_fops;
-	pr_info("pmem: Initializing %s (user-space) as %s\n",
+	pmem[id].reusable = pdata->reusable;
+	pr_info("pmem: Initializing %s as %s\n",
 		pdata->name, pdata->cached ? "cached" : "non-cached");
 
 	if (misc_register(&pmem[id].dev)) {
@@ -2793,24 +2794,23 @@
 		goto err_cant_register_device;
 	}
 
-	pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
-		pmem[id].memory_type, PAGE_SIZE);
-	if (!pmem[id].base) {
-		pr_err("pmem: Cannot allocate from reserved memory for %s\n",
-		 pdata->name);
-		goto err_misc_deregister;
+	if (!pmem[id].reusable) {
+		pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
+			pmem[id].memory_type, PAGE_SIZE);
+		if (!pmem[id].base) {
+			pr_err("pmem: Cannot allocate from reserved memory for %s\n",
+				pdata->name);
+			goto err_misc_deregister;
+		}
 	}
 
-	pr_info("allocating %lu bytes at %p (%lx physical) for %s\n",
-		pmem[id].size, pmem[id].vbase, pmem[id].base, pmem[id].name);
-
-	pmem[id].reusable = pdata->reusable;
 	/* reusable pmem requires map on demand */
 	pmem[id].map_on_demand = pdata->map_on_demand || pdata->reusable;
 	if (pmem[id].map_on_demand) {
 		if (pmem[id].reusable) {
 			const struct fmem_data *fmem_info = fmem_get_info();
 			pmem[id].area = fmem_info->area;
+			pmem[id].base = fmem_info->phys;
 		} else {
 			pmem_vma = get_vm_area(pmem[id].size, VM_IOREMAP);
 			if (!pmem_vma) {
@@ -2844,12 +2844,17 @@
 	if (pdata->release_region)
 		pmem[id].mem_release = pdata->release_region;
 
+	pr_info("allocating %lu bytes at %lx physical for %s\n",
+		pmem[id].size, pmem[id].base, pmem[id].name);
+
 	return 0;
 
 cleanup_vm:
-	remove_vm_area(pmem_vma);
+	if (!pmem[id].reusable)
+		remove_vm_area(pmem_vma);
 err_free:
-	free_contiguous_memory_by_paddr(pmem[id].base);
+	if (!pmem[id].reusable)
+		free_contiguous_memory_by_paddr(pmem[id].base);
 err_misc_deregister:
 	misc_deregister(&pmem[id].dev);
 err_cant_register_device:
diff --git a/drivers/misc/tzcom.c b/drivers/misc/tzcom.c
index e662f43..2b1484c 100644
--- a/drivers/misc/tzcom.c
+++ b/drivers/misc/tzcom.c
@@ -1002,7 +1002,10 @@
 	}
 	spin_unlock_irqrestore(&tzcom_data->registered_svc_list_lock, flags);
 	PDEBUG("After removing svc list");
-
+	if (pil != NULL) {
+		pil_put(pil);
+		pil = NULL;
+	}
 	PDEBUG("Freeing tzcom data");
 	kfree(tzcom_data);
 	return 0;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 3ae639e..e364eac 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1042,8 +1042,6 @@
 	host->curr.got_dataend = 0;
 	host->curr.got_auto_prog_done = 0;
 
-	memset(&host->pio, 0, sizeof(host->pio));
-
 	datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
 
 	if (host->curr.wait_for_auto_prog_done)
@@ -1078,17 +1076,21 @@
 
 	/* Is data transfer in PIO mode required? */
 	if (!(datactrl & MCI_DPSM_DMAENABLE)) {
-		host->pio.sg = data->sg;
-		host->pio.sg_len = data->sg_len;
-		host->pio.sg_off = 0;
+		unsigned int sg_miter_flags = SG_MITER_ATOMIC;
 
 		if (data->flags & MMC_DATA_READ) {
+			sg_miter_flags |= SG_MITER_TO_SG;
 			pio_irqmask = MCI_RXFIFOHALFFULLMASK;
 			if (host->curr.xfer_remain < MCI_FIFOSIZE)
 				pio_irqmask |= MCI_RXDATAAVLBLMASK;
-		} else
+		} else {
+			sg_miter_flags |= SG_MITER_FROM_SG;
 			pio_irqmask = MCI_TXFIFOHALFEMPTYMASK |
 					MCI_TXFIFOEMPTYMASK;
+		}
+
+		sg_miter_start(&host->sg_miter, data->sg, data->sg_len,
+				sg_miter_flags);
 	}
 
 	if (data->flags & MMC_DATA_READ)
@@ -1254,6 +1256,7 @@
 	struct msmsdcc_host	*host = dev_id;
 	void __iomem		*base = host->base;
 	uint32_t		status;
+	unsigned long flags;
 
 	spin_lock(&host->lock);
 
@@ -1268,9 +1271,10 @@
 #if IRQ_DEBUG
 	msmsdcc_print_status(host, "irq1-r", status);
 #endif
+	local_irq_save(flags);
 
-	do {
-		unsigned long flags;
+	while (sg_miter_next(&host->sg_miter)) {
+
 		unsigned int remain, len;
 		char *buffer;
 
@@ -1278,12 +1282,8 @@
 				| MCI_RXDATAAVLBL)))
 			break;
 
-		/* Map the current scatter buffer */
-		local_irq_save(flags);
-		buffer = kmap_atomic(sg_page(host->pio.sg),
-				     KM_BIO_SRC_IRQ) + host->pio.sg->offset;
-		buffer += host->pio.sg_off;
-		remain = host->pio.sg->length - host->pio.sg_off;
+		buffer = host->sg_miter.addr;
+		remain = host->sg_miter.length;
 
 		len = 0;
 		if (status & MCI_RXACTIVE)
@@ -1294,11 +1294,7 @@
 		if (len > remain)
 			len = remain;
 
-		/* Unmap the buffer */
-		kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
-		local_irq_restore(flags);
-
-		host->pio.sg_off += len;
+		host->sg_miter.consumed = len;
 		host->curr.xfer_remain -= len;
 		host->curr.data_xfered += len;
 		remain -= len;
@@ -1306,20 +1302,11 @@
 		if (remain) /* Done with this page? */
 			break; /* Nope */
 
-		if (status & MCI_RXACTIVE && host->curr.user_pages)
-			flush_dcache_page(sg_page(host->pio.sg));
-
-		if (!--host->pio.sg_len) {
-			memset(&host->pio, 0, sizeof(host->pio));
-			break;
-		}
-
-		/* Advance to next sg */
-		host->pio.sg++;
-		host->pio.sg_off = 0;
-
 		status = readl_relaxed(base + MMCISTATUS);
-	} while (1);
+	}
+
+	sg_miter_stop(&host->sg_miter);
+	local_irq_restore(flags);
 
 	if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) {
 		writel_relaxed((readl_relaxed(host->base + MMCIMASK0) &
@@ -2300,6 +2287,10 @@
 	/* Select free running MCLK as input clock of cm_dll_sdc4 */
 	clk |= (2 << 23);
 
+	/* Clear IO_PAD_PWR_SWITCH while powering off the card */
+	if (!ios->vdd)
+		host->io_pad_pwr_switch = 0;
+
 	if (host->io_pad_pwr_switch)
 		clk |= IO_PAD_PWR_SWITCH;
 
@@ -2575,6 +2566,10 @@
 	unsigned long flags;
 	int rc = 0;
 
+	spin_lock_irqsave(&host->lock, flags);
+	host->io_pad_pwr_switch = 0;
+	spin_unlock_irqrestore(&host->lock, flags);
+
 	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
 		/* Change voltage level of VDDPX to high voltage */
 		rc = msmsdcc_set_vddp_high_vol(host);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index ee7a3e5..319d721 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -361,7 +361,7 @@
 	struct msmsdcc_sps_data sps;
 	bool			is_dma_mode;
 	bool			is_sps_mode;
-	struct msmsdcc_pio_data	pio;
+	struct sg_mapping_iter sg_miter;
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	struct early_suspend early_suspend;
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 4be8373..167efd9 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -318,6 +318,17 @@
 	  The driver provides wear leveling by storing erase counter into the
 	  OOB.
 
+config MTD_LAZYECCSTATS
+	bool "MTD Lazy ECC Stats collection support"
+	default y
+	help
+	  Normally bad block counts for ECC stats are collected at boot time.
+	  This option delays the badblock stats collection until ECCGETSTATS
+	  ioctl is invoked on the partition.
+
+	  This can significantly decrease boot times depending on the size of
+	  the partition.  If unsure, say 'N'.
+
 source "drivers/mtd/chips/Kconfig"
 
 source "drivers/mtd/maps/Kconfig"
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f1af222..ed9468c 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -34,6 +34,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
 
 #include <asm/uaccess.h>
 
@@ -904,6 +905,9 @@
 
 	case ECCGETSTATS:
 	{
+#ifdef CONFIG_MTD_LAZYECCSTATS
+		part_fill_badblockstats(mtd);
+#endif
 		if (copy_to_user(argp, &mtd->ecc_stats,
 				 sizeof(struct mtd_ecc_stats)))
 			return -EFAULT;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 630be3e..4c75f32 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -353,6 +353,21 @@
 	kfree(p);
 }
 
+void part_fill_badblockstats(struct mtd_info *mtd)
+{
+	struct mtd_part *part = PART(mtd);
+	if (part->master->block_isbad) {
+		uint64_t offs = 0;
+		mtd->ecc_stats.badblocks = 0;
+		while (offs < mtd->size) {
+			if (part->master->block_isbad(part->master,
+						offs + part->offset))
+				mtd->ecc_stats.badblocks++;
+			offs += mtd->erasesize;
+		}
+	}
+}
+
 /*
  * This function unregisters and destroy all slave MTD objects which are
  * attached to the given master MTD object.
@@ -542,16 +557,10 @@
 	}
 
 	slave->mtd.ecclayout = master->ecclayout;
-	if (master->block_isbad) {
-		uint64_t offs = 0;
 
-		while (offs < slave->mtd.size) {
-			if (master->block_isbad(master,
-						offs + slave->offset))
-				slave->mtd.ecc_stats.badblocks++;
-			offs += slave->mtd.erasesize;
-		}
-	}
+#ifndef CONFIG_MTD_LAZYECCSTATS
+	part_fill_badblockstats(&(slave->mtd));
+#endif
 
 out_register:
 	return slave;
diff --git a/drivers/net/qfec.c b/drivers/net/qfec.c
index fc27837..e1f4be2 100644
--- a/drivers/net/qfec.c
+++ b/drivers/net/qfec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1899,6 +1899,11 @@
 	setup_timer(&priv->phy_tmr, qfec_phy_monitor, (unsigned long)dev);
 	mod_timer(&priv->phy_tmr, jiffies + HZ);
 
+	/* driver supports AN capable PHY only */
+	qfec_mdio_write(dev, priv->phy_id, MII_BMCR, BMCR_RESET);
+	res = (BMCR_ANENABLE|BMCR_ANRESTART);
+	qfec_mdio_write(dev, priv->phy_id, MII_BMCR, res);
+
 	/* initialize interrupts */
 	QFEC_LOG(QFEC_LOG_DBG, " %s: request irq %d\n", __func__, dev->irq);
 	res = request_irq(dev->irq, qfec_int, 0, dev->name, dev);
diff --git a/drivers/net/wireless/libra/qcomwlan_pwrif.c b/drivers/net/wireless/libra/qcomwlan_pwrif.c
index 8268f24..6a0c78f 100644
--- a/drivers/net/wireless/libra/qcomwlan_pwrif.c
+++ b/drivers/net/wireless/libra/qcomwlan_pwrif.c
@@ -72,7 +72,7 @@
 	static const int vregs_qwlan_peek_current[] = {
 		4000,
 		150000,
-		200000,
+		60000,
 		0,
 		32000,
 		130000,
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index fa8f866..aca724a 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -415,14 +415,6 @@
 				disable ? CHG_CHARGE_DIS_BIT : 0);
 }
 
-static bool pm_is_chg_charge_dis_bit_set(struct pm8921_chg_chip *chip)
-{
-	u8 temp = 0;
-
-	pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
-	return !!(temp & CHG_CHARGE_DIS_BIT);
-}
-
 #define PM8921_CHG_V_MIN_MV	3240
 #define PM8921_CHG_V_STEP_MV	20
 #define PM8921_CHG_V_STEP_10_MV_BIT	BIT(7)
@@ -1024,24 +1016,34 @@
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 	case POWER_SUPPLY_PROP_ONLINE:
-		if (pm_is_chg_charge_dis_bit_set(the_chip) ||
-				!is_usb_chg_plugged_in(the_chip))
-			val->intval = 0;
-		else if (psy->type == POWER_SUPPLY_TYPE_USB ||
+		val->intval = 0;
+		if (charging_disabled)
+			return 0;
+
+		/* USB charging */
+		if (psy->type == POWER_SUPPLY_TYPE_USB ||
 				psy->type == POWER_SUPPLY_TYPE_USB_DCP ||
 				psy->type == POWER_SUPPLY_TYPE_USB_CDP ||
 				psy->type == POWER_SUPPLY_TYPE_USB_ACA) {
-			val->intval = 1;
-		} else if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
+			val->intval = is_usb_chg_plugged_in(the_chip);
+			return 0;
+		}
+
+		/* DC charging */
+		if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
+			/* external charger is connected */
+			if (the_chip->dc_present || is_ext_charging(the_chip)) {
+				val->intval = 1;
+				return 0;
+			}
+			/* USB with max current greater than 500 mA connected */
 			pm_chg_iusbmax_get(the_chip, &current_max);
 			if (current_max > USB_WALL_THRESHOLD_MA)
-				val->intval = 1;
-			else
-				val->intval = 0;
-		} else {
-			val->intval = 0;
-			pr_err("Unkown POWER_SUPPLY_TYPE %d\n", psy->type);
+				val->intval = is_usb_chg_plugged_in(the_chip);
+			return 0;
 		}
+
+		pr_err("Unkown POWER_SUPPLY_TYPE %d\n", psy->type);
 		break;
 	default:
 		return -EINVAL;
@@ -1592,6 +1594,7 @@
 
 	the_chip->usb_psy.type = type;
 	power_supply_changed(&the_chip->usb_psy);
+	power_supply_changed(&the_chip->dc_psy);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pm8921_set_usb_power_supply_type);
@@ -1639,6 +1642,7 @@
 	power_supply_set_charge_type(chip->ext_psy,
 					POWER_SUPPLY_CHARGE_TYPE_NONE);
 	pm8921_disable_source_current(false); /* release BATFET */
+	power_supply_changed(&chip->dc_psy);
 	chip->ext_charging = false;
 	chip->ext_charge_done = false;
 	bms_notify_check(chip);
@@ -1686,8 +1690,10 @@
 		return;
 	}
 
+	power_supply_set_online(chip->ext_psy, dc_present);
 	power_supply_set_charge_type(chip->ext_psy,
 					POWER_SUPPLY_CHARGE_TYPE_FAST);
+	power_supply_changed(&chip->dc_psy);
 	chip->ext_charging = true;
 	chip->ext_charge_done = false;
 	bms_notify_check(chip);
@@ -1768,6 +1774,7 @@
 
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
+	power_supply_changed(&chip->dc_psy);
 
 	return IRQ_HANDLED;
 }
@@ -1819,6 +1826,7 @@
 
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
+	power_supply_changed(&chip->dc_psy);
 
 	bms_notify_check(chip);
 
@@ -1841,6 +1849,7 @@
 
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
+	power_supply_changed(&chip->dc_psy);
 	return IRQ_HANDLED;
 }
 
@@ -1851,6 +1860,7 @@
 	pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
+	power_supply_changed(&chip->dc_psy);
 
 	bms_notify_check(chip);
 
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 02d1c39..d053cd6 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1886,7 +1886,7 @@
 	}
 
 
-	dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
+	dev->rclk = clk_get(dev->dev, "core_clk");
 	if (!dev->rclk) {
 		dev_err(dev->dev, "slimbus clock not found");
 		goto err_clk_get_failed;
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
new file mode 100644
index 0000000..648d2e9
--- /dev/null
+++ b/drivers/spmi/Kconfig
@@ -0,0 +1,22 @@
+#
+# SPMI driver configuration
+#
+menuconfig SPMI
+	bool "SPMI support"
+	help
+	  SPMI (System Power Management Interface) is a two-wire
+	  serial interface between baseband and application processors
+	  and Power Management Integrated Circuits (PMIC).
+
+if SPMI
+config SPMI_MSM_PMIC_ARB
+	tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in SPMI PMIC Arbiter interface on Qualcomm MSM family
+	  processors.
+
+	  This is required for communicating with Qualcomm PMICs and
+	  other devices that have the SPMI interface.
+
+endif
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
new file mode 100644
index 0000000..8406134
--- /dev/null
+++ b/drivers/spmi/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for kernel SPMI framework.
+#
+obj-$(CONFIG_SPMI)			+= spmi.o
+obj-$(CONFIG_SPMI_MSM_PMIC_ARB)		+= spmi-pmic-arb.o
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
new file mode 100644
index 0000000..e5a9d40
--- /dev/null
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -0,0 +1,733 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/of_spmi.h>
+#include <mach/qpnp-int.h>
+
+#define SPMI_PMIC_ARB_NAME		"spmi_pmic_arb"
+
+/* PMIC Arbiter configuration registers */
+#define PMIC_ARB_VERSION		0x0000
+#define PMIC_ARB_INT_EN			0x0004
+
+/* PMIC Arbiter channel registers */
+#define PMIC_ARB_CMD(N)			(0x0800 + (0x80 * (N)))
+#define PMIC_ARB_CONFIG(N)		(0x0804 + (0x80 * (N)))
+#define PMIC_ARB_STATUS(N)		(0x0808 + (0x80 * (N)))
+#define PMIC_ARB_WDATA0(N)		(0x0810 + (0x80 * (N)))
+#define PMIC_ARB_WDATA1(N)		(0x0814 + (0x80 * (N)))
+#define PMIC_ARB_RDATA0(N)		(0x0818 + (0x80 * (N)))
+#define PMIC_ARB_RDATA1(N)		(0x081C + (0x80 * (N)))
+
+/* Interrupt Controller */
+#define SPMI_PIC_OWNER_ACC_STATUS(M, N)	(0x0000 + ((32 * (M)) + (4 * (N))))
+#define SPMI_PIC_ACC_ENABLE(N)		(0x0200 + (4 * (N)))
+#define SPMI_PIC_IRQ_STATUS(N)		(0x0600 + (4 * (N)))
+#define SPMI_PIC_IRQ_CLEAR(N)		(0x0A00 + (4 * (N)))
+
+/* Channel Status fields */
+enum pmic_arb_chnl_status {
+	PMIC_ARB_STATUS_DONE	= (1 << 0),
+	PMIC_ARB_STATUS_FAILURE	= (1 << 1),
+	PMIC_ARB_STATUS_DENIED	= (1 << 2),
+	PMIC_ARB_STATUS_DROPPED	= (1 << 3),
+};
+
+/* Command register fields */
+#define PMIC_ARB_CMD_MAX_BYTE_COUNT	8
+
+/* Command Opcodes */
+enum pmic_arb_cmd_op_code {
+	PMIC_ARB_OP_EXT_WRITEL = 0,
+	PMIC_ARB_OP_EXT_READL = 1,
+	PMIC_ARB_OP_EXT_WRITE = 2,
+	PMIC_ARB_OP_RESET = 3,
+	PMIC_ARB_OP_SLEEP = 4,
+	PMIC_ARB_OP_SHUTDOWN = 5,
+	PMIC_ARB_OP_WAKEUP = 6,
+	PMIC_ARB_OP_AUTHENTICATE = 7,
+	PMIC_ARB_OP_MSTR_READ = 8,
+	PMIC_ARB_OP_MSTR_WRITE = 9,
+	PMIC_ARB_OP_EXT_READ = 13,
+	PMIC_ARB_OP_WRITE = 14,
+	PMIC_ARB_OP_READ = 15,
+	PMIC_ARB_OP_ZERO_WRITE = 16,
+};
+
+/* Maximum number of support PMIC peripherals */
+#define PMIC_ARB_MAX_PERIPHS		256
+#define PMIC_ARB_PERIPH_ID_VALID	(1 << 15)
+#define PMIC_ARB_TIMEOUT_US		100
+#define PMIC_ARB_APID_MASK		0xFF
+#define PMIC_ARB_PPID_MASK		0xFFF
+
+/**
+ * base - base address of the PMIC Arbiter core registers.
+ * intr - base address of the SPMI interrupt control registers
+ */
+struct spmi_pmic_arb_dev {
+	struct spmi_controller	controller;
+	struct device		*dev;
+	struct device		*slave;
+	void __iomem		*base;
+	void __iomem		*intr;
+	int			pic_irq;
+	int			pic_enable_cnt;
+	spinlock_t		lock;
+	u8			owner;
+	u8			channel;
+	u8			min_apid;
+	u8			max_apid;
+	u16			periph_id_map[PMIC_ARB_MAX_PERIPHS];
+};
+
+static u32 pmic_arb_read(struct spmi_pmic_arb_dev *dev, u32 offset)
+{
+	u32 val = readl_relaxed(dev->base + offset);
+	pr_debug("address 0x%p, val 0x%x\n", dev->base + offset, val);
+	return val;
+}
+
+static void pmic_arb_write(struct spmi_pmic_arb_dev *dev, u32 offset, u32 val)
+{
+	pr_debug("address 0x%p, val 0x%x\n", dev->base + offset, val);
+	writel_relaxed(val, dev->base + offset);
+}
+
+static int pmic_arb_wait_for_done(struct spmi_pmic_arb_dev *dev)
+{
+	u32 status = 0;
+	u32 timeout = PMIC_ARB_TIMEOUT_US;
+	u32 offset = PMIC_ARB_STATUS(dev->channel);
+
+	while (timeout--) {
+		status = pmic_arb_read(dev, offset);
+
+		if (status & PMIC_ARB_STATUS_DONE) {
+			if (status & PMIC_ARB_STATUS_DENIED) {
+				dev_err(dev->dev,
+					"%s: transaction denied (0x%x)\n",
+					__func__, status);
+				return -EPERM;
+			}
+
+			if (status & PMIC_ARB_STATUS_FAILURE) {
+				dev_err(dev->dev,
+					"%s: transaction failed (0x%x)\n",
+					__func__, status);
+				return -EIO;
+			}
+
+			if (status & PMIC_ARB_STATUS_DROPPED) {
+				dev_err(dev->dev,
+					"%s: transaction dropped (0x%x)\n",
+					__func__, status);
+				return -EIO;
+			}
+
+			return 0;
+		}
+		udelay(1);
+	}
+
+	dev_err(dev->dev, "%s: timeout, status 0x%x\n", __func__, status);
+	return -ETIMEDOUT;
+}
+
+static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+{
+	u32 data = pmic_arb_read(dev, reg);
+
+	switch (bc & 0x3) {
+	case 3:
+		*buf++ = data & 0xff;
+		data >>= 8;
+	case 2:
+		*buf++ = data & 0xff;
+		data >>= 8;
+	case 1:
+		*buf++ = data & 0xff;
+		data >>= 8;
+	case 0:
+		*buf++ = data & 0xff;
+	default:
+		break;
+	}
+}
+
+static void
+pa_write_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc)
+{
+	u32 data = 0;
+
+	switch (bc & 0x3) {
+	case 3:
+		data = (buf[0]|buf[1]<<8|buf[2]<<16|buf[3]<<24);
+		break;
+	case 2:
+		data = (buf[0]|buf[1]<<8|buf[2]<<16);
+		break;
+	case 1:
+		data = (buf[0]|buf[1]<<8);
+		break;
+	case 0:
+		data = (buf[0]);
+		break;
+	default:
+		break;
+	}
+
+	pmic_arb_write(dev, reg, data);
+}
+
+/* Non-data command */
+static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	unsigned long flags;
+	u32 cmd;
+	int rc;
+
+	pr_debug("op:0x%x sid:%d\n", opc, sid);
+
+	/* Check for valid non-data command */
+	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
+		return -EINVAL;
+
+	cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
+
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(pmic_arb);
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+	return rc;
+}
+
+static int pmic_arb_read_cmd(struct spmi_controller *ctrl,
+				u8 opc, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	unsigned long flags;
+	u32 cmd;
+	int rc;
+
+	pr_debug("op:0x%x sid:%d bc:%d addr:0x%x\n", opc, sid, bc, addr);
+
+	/* Check the opcode */
+	if (opc >= 0x60 && opc <= 0x7F)
+		opc = PMIC_ARB_OP_READ;
+	else if (opc >= 0x20 && opc <= 0x2F)
+		opc = PMIC_ARB_OP_EXT_READ;
+	else if (opc >= 0x38 && opc <= 0x3F)
+		opc = PMIC_ARB_OP_EXT_READL;
+	else
+		return -EINVAL;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(pmic_arb);
+	if (rc)
+		goto done;
+
+	/* Read from FIFO, note 'bc' is actually number of bytes minus 1 */
+	pa_read_data(pmic_arb, buf, PMIC_ARB_RDATA0(pmic_arb->channel), bc);
+
+	if (bc > 3)
+		pa_read_data(pmic_arb, buf + 4,
+				PMIC_ARB_RDATA1(pmic_arb->channel), bc);
+
+done:
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	return rc;
+}
+
+static int pmic_arb_write_cmd(struct spmi_controller *ctrl,
+				u8 opc, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	unsigned long flags;
+	u32 cmd;
+	int rc;
+
+	pr_debug("op:0x%x sid:%d bc:%d addr:0x%x\n", opc, sid, bc, addr);
+
+	/* Check the opcode */
+	if (opc >= 0x40 && opc <= 0x5F)
+		opc = PMIC_ARB_OP_WRITE;
+	else if (opc >= 0x00 && opc <= 0x0F)
+		opc = PMIC_ARB_OP_EXT_WRITE;
+	else if (opc >= 0x30 && opc <= 0x37)
+		opc = PMIC_ARB_OP_EXT_WRITEL;
+	else if (opc >= 0x80 && opc <= 0xFF)
+		opc = PMIC_ARB_OP_ZERO_WRITE;
+	else
+		return -EINVAL;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+
+	/* Write data to FIFOs */
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	pa_write_data(pmic_arb, buf, PMIC_ARB_WDATA0(pmic_arb->channel), bc);
+
+	if (bc > 3)
+		pa_write_data(pmic_arb, buf + 4,
+				PMIC_ARB_WDATA1(pmic_arb->channel), bc);
+
+	/* Start the transaction */
+	pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
+	rc = pmic_arb_wait_for_done(pmic_arb);
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+
+	return rc;
+}
+
+/* APID to PPID */
+static u16 get_peripheral_id(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+	return pmic_arb->periph_id_map[apid] & PMIC_ARB_PPID_MASK;
+}
+
+/* APID to PPID, returns valid flag */
+static int is_apid_valid(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+	return pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID;
+}
+
+/* PPID to APID */
+static uint32_t map_peripheral_id(struct spmi_pmic_arb_dev *pmic_arb, u16 ppid)
+{
+	int first = pmic_arb->min_apid;
+	int last = pmic_arb->max_apid;
+	int i;
+
+	/* Search table for a matching PPID */
+	for (i = first; i <= last; ++i) {
+		if ((pmic_arb->periph_id_map[i] & PMIC_ARB_PPID_MASK) == ppid)
+			return i;
+	}
+
+	dev_err(pmic_arb->dev, "Unknown ppid 0x%x\n", ppid);
+	return PMIC_ARB_MAX_PERIPHS;
+}
+
+/* Enable interrupt at the PMIC Arbiter PIC */
+static int pmic_arb_pic_enable(struct spmi_controller *ctrl,
+				struct qpnp_irq_spec *spec, uint32_t data)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	u8 apid = data & PMIC_ARB_APID_MASK;
+	unsigned long flags;
+	u32 status;
+
+	dev_dbg(pmic_arb->dev, "PIC enable, apid:0x%x, sid:0x%x, pid:0x%x\n",
+				apid, spec->slave, spec->per);
+
+	if (data < pmic_arb->min_apid || data > pmic_arb->max_apid) {
+		dev_err(pmic_arb->dev, "int enable: invalid APID %d\n", data);
+		return -EINVAL;
+	}
+
+	if (!is_apid_valid(pmic_arb, apid)) {
+		dev_err(pmic_arb->dev, "int enable: int not supported\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	status = readl_relaxed(pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+	if (!status) {
+		if (pmic_arb->pic_enable_cnt++ == 0)
+			enable_irq(pmic_arb->pic_irq);
+		writel_relaxed(0x1, pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+		/* Interrupt needs to be enabled before returning to caller */
+		wmb();
+	}
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	return 0;
+}
+
+/* Disable interrupt at the PMIC Arbiter PIC */
+static int pmic_arb_pic_disable(struct spmi_controller *ctrl,
+				struct qpnp_irq_spec *spec, uint32_t data)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	u8 apid = data & PMIC_ARB_APID_MASK;
+	unsigned long flags;
+	u32 status;
+
+	dev_dbg(pmic_arb->dev, "PIC disable, apid:0x%x, sid:0x%x, pid:0x%x\n",
+				apid, spec->slave, spec->per);
+
+	if (data < pmic_arb->min_apid || data > pmic_arb->max_apid) {
+		dev_err(pmic_arb->dev, "int disable: invalid APID %d\n", data);
+		return -EINVAL;
+	}
+
+	if (!is_apid_valid(pmic_arb, apid)) {
+		dev_err(pmic_arb->dev, "int disable: int not supported\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pmic_arb->lock, flags);
+	status = readl_relaxed(pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+	if (status) {
+		if (pmic_arb->pic_enable_cnt-- == 1)
+			disable_irq(pmic_arb->pic_irq);
+		writel_relaxed(0x0, pmic_arb->intr + SPMI_PIC_ACC_ENABLE(apid));
+		/* Interrupt needs to be disabled before returning to caller */
+		wmb();
+	}
+	spin_unlock_irqrestore(&pmic_arb->lock, flags);
+	return 0;
+}
+
+static irqreturn_t
+periph_interrupt(struct spmi_pmic_arb_dev *pmic_arb, u8 apid)
+{
+	u16 ppid = get_peripheral_id(pmic_arb, apid);
+	void __iomem *base = pmic_arb->intr;
+	u8 sid = (ppid >> 8) & 0x0F;
+	u8 pid = ppid & 0xFF;
+	u32 status;
+	int i;
+
+	if (!is_apid_valid(pmic_arb, apid)) {
+		dev_err(pmic_arb->dev, "unknown peripheral id 0x%x\n", ppid);
+		/* return IRQ_NONE; */
+	}
+
+	/* Read the peripheral specific interrupt bits */
+	status = readl_relaxed(base + SPMI_PIC_IRQ_STATUS(apid));
+
+	/* Clear the peripheral interrupts */
+	writel_relaxed(status, base + SPMI_PIC_IRQ_CLEAR(apid));
+	/* Interrupt needs to be cleared/acknowledged before exiting ISR */
+	mb();
+
+	dev_dbg(pmic_arb->dev,
+		"interrupt, apid:0x%x, sid:0x%x, pid:0x%x, intr:0x%x\n",
+						apid, sid, pid, status);
+
+	/* Send interrupt notification */
+	for (i = 0; status && i < 8; ++i, status >>= 1) {
+		if (status & 0x1) {
+			struct qpnp_irq_spec irq_spec = {
+				.slave = sid,
+				.per = pid,
+				.irq = i,
+			};
+			qpnpint_handle_irq(&pmic_arb->controller, &irq_spec);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+/* Peripheral interrupt handler */
+static irqreturn_t pmic_arb_periph_irq(int irq, void *dev_id)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = dev_id;
+	void __iomem *intr = pmic_arb->intr;
+	u8 ee = pmic_arb->owner;
+	u32 ret = IRQ_NONE;
+	u32 status;
+
+	int first = pmic_arb->min_apid >> 5;
+	int last = pmic_arb->max_apid >> 5;
+	int i, j;
+
+	dev_dbg(pmic_arb->dev, "Peripheral interrupt detected\n");
+
+	/* Check the accumulated interrupt status */
+	for (i = first; i <= last; ++i) {
+		status = readl_relaxed(intr + SPMI_PIC_OWNER_ACC_STATUS(ee, i));
+
+		for (j = 0; status && j < 32; ++j, status >>= 1) {
+			if (status & 0x1) {
+				u8 id = (i * 32) + j;
+				ret |= periph_interrupt(pmic_arb, id);
+			}
+		}
+	}
+
+	return ret;
+}
+
+/* Callback to register an APID for specific slave/peripheral */
+static int pmic_arb_intr_priv_data(struct spmi_controller *ctrl,
+				struct qpnp_irq_spec *spec, uint32_t *data)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = spmi_get_ctrldata(ctrl);
+	u16 ppid = ((spec->slave & 0x0F) << 8) | (spec->per & 0xFF);
+	*data = map_peripheral_id(pmic_arb, ppid);
+	return 0;
+}
+
+static int __devinit
+spmi_pmic_arb_get_property(struct platform_device *pdev, char *pname, u32 *prop)
+{
+	int ret = of_property_read_u32(pdev->dev.of_node, pname, prop);
+
+	if (ret)
+		dev_err(&pdev->dev, "missing property: %s\n", pname);
+	else
+		pr_debug("%s = 0x%x\n", pname, *prop);
+
+	return ret;
+}
+
+static int __devinit spmi_pmic_arb_get_map_data(struct platform_device *pdev,
+					struct spmi_pmic_arb_dev *pmic_arb)
+{
+	int i;
+	int ret;
+	int map_size;
+	u32 *map_data;
+	const int map_width = 2 * sizeof(*map_data);
+	const struct device_node *of_node = pdev->dev.of_node;
+
+	/* Get size of the mapping table (in bytes) */
+	if (!of_get_property(of_node, "qcom,pmic-arb-ppid-map", &map_size)) {
+		dev_err(&pdev->dev, "missing ppid mapping table\n");
+		return -ENODEV;
+	}
+
+	/* Map size can't exceed the maximum number of peripherals */
+	if (map_size == 0 || map_size % map_width ||
+				map_size > map_width * PMIC_ARB_MAX_PERIPHS) {
+		dev_err(&pdev->dev, "map size of %d is not valid\n", map_size);
+		return -ENODEV;
+	}
+
+	map_data = kzalloc(map_size, GFP_KERNEL);
+	if (!map_data) {
+		dev_err(&pdev->dev, "can not allocate map data\n");
+		return -ENOMEM;
+	}
+
+	ret = of_property_read_u32_array(of_node,
+		"qcom,pmic-arb-ppid-map", map_data, map_size/sizeof(u32));
+	if (ret) {
+		dev_err(&pdev->dev, "invalid or missing property: ppid-map\n");
+		goto err;
+	};
+
+	pmic_arb->max_apid = 0;
+	pmic_arb->min_apid = PMIC_ARB_MAX_PERIPHS - 1;
+
+	/* Build the mapping table from the data */
+	for (i = 0; i < map_size/sizeof(u32);) {
+		u32 ppid = map_data[i++];
+		u32 apid = map_data[i++];
+
+		if (apid > PMIC_ARB_APID_MASK) {
+			ret = -ENODEV;
+			dev_err(&pdev->dev, "invalid APID: 0x%x\n", apid);
+			goto err;
+		}
+
+		if (ppid > PMIC_ARB_PPID_MASK) {
+			ret = -ENODEV;
+			dev_err(&pdev->dev, "invalid PPID: 0x%x\n", ppid);
+			goto err;
+		}
+
+		if (pmic_arb->periph_id_map[apid] & PMIC_ARB_PERIPH_ID_VALID)
+			dev_warn(&pdev->dev, "duplicate APID 0x%x\n", apid);
+
+		pmic_arb->periph_id_map[apid] = ppid | PMIC_ARB_PERIPH_ID_VALID;
+
+		if (apid > pmic_arb->max_apid)
+			pmic_arb->max_apid = apid;
+
+		if (apid < pmic_arb->min_apid)
+			pmic_arb->min_apid = apid;
+	}
+
+	pr_debug("%d value(s) mapped, min:%d, max:%d\n",
+		map_size/map_width, pmic_arb->min_apid, pmic_arb->max_apid);
+
+err:
+	kfree(map_data);
+	return ret;
+}
+
+static struct qpnp_local_int spmi_pmic_arb_intr_cb = {
+	.mask = pmic_arb_pic_disable,
+	.unmask = pmic_arb_pic_enable,
+	.register_priv_data = pmic_arb_intr_priv_data,
+};
+
+static int __devinit spmi_pmic_arb_probe(struct platform_device *pdev)
+{
+	struct spmi_pmic_arb_dev *pmic_arb;
+	struct resource *mem_res;
+	u32 cell_index;
+	u32 prop;
+	int ret = 0;
+
+	pr_debug("SPMI PMIC Arbiter\n");
+
+	pmic_arb = devm_kzalloc(&pdev->dev,
+				sizeof(struct spmi_pmic_arb_dev), GFP_KERNEL);
+	if (!pmic_arb) {
+		dev_err(&pdev->dev, "can not allocate pmic_arb data\n");
+		return -ENOMEM;
+	}
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res) {
+		dev_err(&pdev->dev, "missing base memory resource\n");
+		return -ENODEV;
+	}
+
+	pmic_arb->base = devm_ioremap(&pdev->dev,
+					mem_res->start, resource_size(mem_res));
+	if (!pmic_arb->base) {
+		dev_err(&pdev->dev, "ioremap of 'base' failed\n");
+		return -ENOMEM;
+	}
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mem_res) {
+		dev_err(&pdev->dev, "missing mem resource (interrupts)\n");
+		return -ENODEV;
+	}
+
+	pmic_arb->intr = devm_ioremap(&pdev->dev,
+					mem_res->start, resource_size(mem_res));
+	if (!pmic_arb->intr) {
+		dev_err(&pdev->dev, "ioremap of 'intr' failed\n");
+		return -ENOMEM;
+	}
+
+	pmic_arb->pic_irq = platform_get_irq(pdev, 0);
+	if (!pmic_arb->pic_irq) {
+		dev_err(&pdev->dev, "missing IRQ resource\n");
+		return -ENODEV;
+	}
+
+	ret = devm_request_irq(&pdev->dev, pmic_arb->pic_irq,
+		pmic_arb_periph_irq, IRQF_TRIGGER_HIGH, pdev->name, pmic_arb);
+	if (ret) {
+		dev_err(&pdev->dev, "request IRQ failed\n");
+		return ret;
+	}
+	disable_irq(pmic_arb->pic_irq);
+
+	/* Get properties from the device tree */
+	ret = spmi_pmic_arb_get_property(pdev, "cell-index", &cell_index);
+	if (ret)
+		return -ENODEV;
+
+	ret = spmi_pmic_arb_get_map_data(pdev, pmic_arb);
+	if (ret)
+		return ret;
+
+	ret = spmi_pmic_arb_get_property(pdev, "qcom,pmic-arb-ee", &prop);
+	if (ret)
+		return -ENODEV;
+	pmic_arb->owner = (u8)prop;
+
+	ret = spmi_pmic_arb_get_property(pdev, "qcom,pmic-arb-channel", &prop);
+	if (ret)
+		return -ENODEV;
+	pmic_arb->channel = (u8)prop;
+
+	pmic_arb->dev = &pdev->dev;
+	platform_set_drvdata(pdev, pmic_arb);
+	spmi_set_ctrldata(&pmic_arb->controller, pmic_arb);
+
+	spin_lock_init(&pmic_arb->lock);
+
+	pmic_arb->controller.nr = cell_index;
+	pmic_arb->controller.dev.parent = pdev->dev.parent;
+	pmic_arb->controller.dev.of_node = of_node_get(pdev->dev.of_node);
+
+	/* Callbacks */
+	pmic_arb->controller.cmd = pmic_arb_cmd;
+	pmic_arb->controller.read_cmd = pmic_arb_read_cmd;
+	pmic_arb->controller.write_cmd =  pmic_arb_write_cmd;
+
+	ret = spmi_add_controller(&pmic_arb->controller);
+	if (ret)
+		goto err_add_controller;
+
+	/* Register the interrupt enable/disable functions */
+	qpnpint_register_controller(cell_index, &spmi_pmic_arb_intr_cb);
+
+	/* Register device(s) from the device tree */
+	of_spmi_register_devices(&pmic_arb->controller);
+
+	pr_debug("PMIC Arb Version 0x%x\n",
+			pmic_arb_read(pmic_arb, PMIC_ARB_VERSION));
+
+	return 0;
+
+err_add_controller:
+	platform_set_drvdata(pdev, NULL);
+	return ret;
+}
+
+static int __devexit spmi_pmic_arb_remove(struct platform_device *pdev)
+{
+	struct spmi_pmic_arb_dev *pmic_arb = platform_get_drvdata(pdev);
+
+	free_irq(pmic_arb->pic_irq, pmic_arb);
+	platform_set_drvdata(pdev, NULL);
+	spmi_del_controller(&pmic_arb->controller);
+	return 0;
+}
+
+static struct of_device_id spmi_pmic_arb_match_table[] = {
+	{	.compatible = "qcom,spmi-pmic-arb",
+	},
+	{}
+};
+
+static struct platform_driver spmi_pmic_arb_driver = {
+	.probe		= spmi_pmic_arb_probe,
+	.remove		= __exit_p(spmi_pmic_arb_remove),
+	.driver		= {
+		.name	= SPMI_PMIC_ARB_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = spmi_pmic_arb_match_table,
+	},
+};
+
+static int __init spmi_pmic_arb_init(void)
+{
+	return platform_driver_register(&spmi_pmic_arb_driver);
+}
+postcore_initcall(spmi_pmic_arb_init);
+
+static void __exit spmi_pmic_arb_exit(void)
+{
+	platform_driver_unregister(&spmi_pmic_arb_driver);
+}
+module_exit(spmi_pmic_arb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:spmi_pmic_arb");
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
new file mode 100644
index 0000000..2842cd8
--- /dev/null
+++ b/drivers/spmi/spmi.c
@@ -0,0 +1,789 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spmi.h>
+
+struct spmii_boardinfo {
+	struct list_head	list;
+	struct spmi_boardinfo	board_info;
+};
+
+static DEFINE_MUTEX(board_lock);
+static LIST_HEAD(board_list);
+static LIST_HEAD(spmi_ctrl_list);
+static DEFINE_IDR(ctrl_idr);
+static struct device_type spmi_ctrl_type = { 0 };
+
+#define to_spmi(dev)	platform_get_drvdata(to_platform_device(dev))
+
+/* Forward declarations */
+struct bus_type spmi_bus_type;
+static int spmi_register_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_busnum_to_ctrl: Map bus number to controller
+ * @busnum: bus number
+ * Returns controller representing this bus number
+ */
+struct spmi_controller *spmi_busnum_to_ctrl(u32 bus_num)
+{
+	struct spmi_controller *ctrl;
+
+	mutex_lock(&board_lock);
+	list_for_each_entry(ctrl, &spmi_ctrl_list, list) {
+		if (bus_num == ctrl->nr) {
+			mutex_unlock(&board_lock);
+			return ctrl;
+		}
+	}
+	mutex_unlock(&board_lock);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(spmi_busnum_to_ctrl);
+
+/**
+ * spmi_add_controller: Controller bring-up.
+ * @ctrl: controller to be registered.
+ * A controller is registered with the framework using this API. ctrl->nr is the
+ * desired number with which SPMI framework registers the controller.
+ * Function will return -EBUSY if the number is in use.
+ */
+int spmi_add_controller(struct spmi_controller *ctrl)
+{
+	int	id;
+	int	status;
+
+	pr_debug("adding controller for bus %d (0x%p)\n", ctrl->nr, ctrl);
+
+	if (ctrl->nr & ~MAX_ID_MASK) {
+		pr_err("invalid bus identifier %d\n", ctrl->nr);
+		return -EINVAL;
+	}
+
+retry:
+	if (idr_pre_get(&ctrl_idr, GFP_KERNEL) == 0) {
+		pr_err("no free memory for idr\n");
+		return -ENOMEM;
+	}
+
+	mutex_lock(&board_lock);
+	status = idr_get_new_above(&ctrl_idr, ctrl, ctrl->nr, &id);
+	if (status == 0 && id != ctrl->nr) {
+		status = -EAGAIN;
+		idr_remove(&ctrl_idr, id);
+	}
+	mutex_unlock(&board_lock);
+	if (status == -EAGAIN)
+		goto retry;
+
+	if (status == 0)
+		status = spmi_register_controller(ctrl);
+	return status;
+}
+EXPORT_SYMBOL_GPL(spmi_add_controller);
+
+/**
+ * spmi_del_controller: Controller tear-down.
+ * @ctrl: controller to which this device is to be added to.
+ *
+ * Controller added with the above API is torn down using this API.
+ */
+int spmi_del_controller(struct spmi_controller *ctrl)
+{
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(spmi_del_controller);
+
+#define spmi_device_attr_gr NULL
+#define spmi_device_uevent NULL
+static void spmi_dev_release(struct device *dev)
+{
+	struct spmi_device *spmidev = to_spmi_device(dev);
+	kfree(spmidev);
+}
+
+static struct device_type spmi_dev_type = {
+	.groups		= spmi_device_attr_gr,
+	.uevent		= spmi_device_uevent,
+	.release	= spmi_dev_release,
+};
+
+/**
+ * spmi_alloc_device: Allocate a new SPMI devices.
+ * @ctrl: controller to which this device is to be added to.
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize a SPMI device without
+ * registering it immediately.  This allows a driver to directly fill
+ * the spmi_device structure before calling spmi_add_device().
+ *
+ * Caller is responsible to call spmi_add_device() on the returned
+ * spmi_device.  If the caller needs to discard the spmi_device without
+ * adding it, then spmi_dev_put() should be called.
+ */
+struct spmi_device *spmi_alloc_device(struct spmi_controller *ctrl)
+{
+	struct spmi_device *spmidev;
+
+	if (!ctrl) {
+		pr_err("Missing SPMI controller\n");
+		return NULL;
+	}
+
+	spmidev = kzalloc(sizeof(*spmidev), GFP_KERNEL);
+	if (!spmidev) {
+		dev_err(&ctrl->dev, "unable to allocate spmi_device\n");
+		return NULL;
+	}
+
+	spmidev->ctrl = ctrl;
+	spmidev->dev.parent = ctrl->dev.parent;
+	spmidev->dev.bus = &spmi_bus_type;
+	spmidev->dev.type = &spmi_dev_type;
+	device_initialize(&spmidev->dev);
+
+	return spmidev;
+}
+EXPORT_SYMBOL_GPL(spmi_alloc_device);
+
+/* Validate the SPMI device structure */
+static struct device *get_valid_device(struct spmi_device *spmidev)
+{
+	struct device *dev;
+
+	if (!spmidev)
+		return NULL;
+
+	dev = &spmidev->dev;
+	if (dev->bus != &spmi_bus_type || dev->type != &spmi_dev_type)
+		return NULL;
+
+	return dev;
+}
+
+/**
+ * spmi_add_device: Add a new device without register board info.
+ * @ctrl: controller to which this device is to be added to.
+ *
+ * Called when device doesn't have an explicit client-driver to be probed, or
+ * the client-driver is a module installed dynamically.
+ */
+int spmi_add_device(struct spmi_device *spmidev)
+{
+	int rc;
+	struct device *dev = get_valid_device(spmidev);
+
+	if (!dev) {
+		pr_err("%s: invalid SPMI device\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Set the device name */
+	dev_set_name(dev, "%s-%p", spmidev->name, spmidev);
+
+	/* Device may be bound to an active driver when this returns */
+	rc = device_add(dev);
+
+	if (rc < 0)
+		dev_err(dev, "Can't add %s, status %d\n", dev_name(dev), rc);
+	else
+		dev_dbg(dev, "device %s registered\n", dev_name(dev));
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(spmi_add_device);
+
+/**
+ * spmi_new_device: Instantiates a new SPMI device
+ * @ctrl: controller to which this device is to be added to.
+ * @info: board information for this device.
+ *
+ * Returns the new device or NULL.
+ */
+struct spmi_device *spmi_new_device(struct spmi_controller *ctrl,
+					struct spmi_boardinfo const *info)
+{
+	struct spmi_device *spmidev;
+	int rc;
+
+	if (!ctrl || !info)
+		return NULL;
+
+	spmidev = spmi_alloc_device(ctrl);
+	if (!spmidev)
+		return NULL;
+
+	spmidev->name = info->name;
+	spmidev->sid  = info->slave_id;
+	spmidev->dev.of_node = info->of_node;
+	spmidev->resource = info->resource;
+	spmidev->num_resources = info->num_resources;
+	spmidev->dev.platform_data = (void *)info->platform_data;
+
+	rc = spmi_add_device(spmidev);
+	if (rc < 0) {
+		spmi_dev_put(spmidev);
+		return NULL;
+	}
+
+	return spmidev;
+}
+EXPORT_SYMBOL_GPL(spmi_new_device);
+
+/* spmi_remove_device: Remove the effect of spmi_add_device() */
+void spmi_remove_device(struct spmi_device *spmi_dev)
+{
+	device_unregister(&spmi_dev->dev);
+}
+EXPORT_SYMBOL_GPL(spmi_remove_device);
+
+/* If controller is not present, only add to boards list */
+static void spmi_match_ctrl_to_boardinfo(struct spmi_controller *ctrl,
+				struct spmi_boardinfo *bi)
+{
+	struct spmi_device *spmidev;
+
+	spmidev = spmi_new_device(ctrl, bi);
+	if (!spmidev)
+		dev_err(ctrl->dev.parent, "can't create new device for %s\n",
+			bi->name);
+}
+
+/**
+ * spmi_register_board_info: Board-initialization routine.
+ * @bus_num: controller number (bus) on which this device will sit.
+ * @info: list of all devices on all controllers present on the board.
+ * @n: number of entries.
+ * API enumerates respective devices on corresponding controller.
+ * Called from board-init function.
+ */
+int spmi_register_board_info(int busnum,
+			struct spmi_boardinfo const *info, unsigned n)
+{
+	int i;
+	struct spmii_boardinfo *bi;
+
+	bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
+	if (!bi)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++, bi++, info++) {
+		struct spmi_controller *ctrl;
+
+		memcpy(&bi->board_info, info, sizeof(*info));
+		mutex_lock(&board_lock);
+		list_add_tail(&bi->list, &board_list);
+		list_for_each_entry(ctrl, &spmi_ctrl_list, list)
+			if (ctrl->nr == busnum)
+				spmi_match_ctrl_to_boardinfo(ctrl,
+							&bi->board_info);
+		mutex_unlock(&board_lock);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spmi_register_board_info);
+
+/* ------------------------------------------------------------------------- */
+
+static inline int
+spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid)
+{
+	BUG_ON(!ctrl || !ctrl->cmd);
+	return ctrl->cmd(ctrl, opcode, sid);
+}
+
+static inline int spmi_read_cmd(struct spmi_controller *ctrl,
+				u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+	BUG_ON(!ctrl || !ctrl->read_cmd);
+	return ctrl->read_cmd(ctrl, opcode, sid, addr, bc, buf);
+}
+
+static inline int spmi_write_cmd(struct spmi_controller *ctrl,
+				u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf)
+{
+	BUG_ON(!ctrl || !ctrl->write_cmd);
+	return ctrl->write_cmd(ctrl, opcode, sid, addr, bc, buf);
+}
+
+/*
+ * register read/write: 5-bit address, 1 byte of data
+ * extended register read/write: 8-bit address, up to 16 bytes of data
+ * extended register read/write long: 16-bit address, up to 8 bytes of data
+ */
+
+/**
+ * spmi_register_read() - register read
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads 1 byte of data from a Slave device register.
+ */
+int spmi_register_read(struct spmi_controller *ctrl, u8 sid, u8 addr, u8 *buf)
+{
+	/* 4-bit Slave Identifier, 5-bit register address */
+	if (sid > SPMI_MAX_SLAVE_ID || addr > 0x1F)
+		return -EINVAL;
+
+	return spmi_read_cmd(ctrl, SPMI_CMD_READ, sid, addr, 0, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_register_read);
+
+/**
+ * spmi_ext_register_read() - extended register read
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @len: the request number of bytes to read (up to 16 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 16 bytes of data from the extended register space on a
+ * Slave device.
+ */
+int spmi_ext_register_read(struct spmi_controller *ctrl,
+				u8 sid, u8 addr, u8 *buf, int len)
+{
+	/* 4-bit Slave Identifier, 8-bit register address, up to 16 bytes */
+	if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 16)
+		return -EINVAL;
+
+	return spmi_read_cmd(ctrl, SPMI_CMD_EXT_READ, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_read);
+
+/**
+ * spmi_ext_register_readl() - extended register read long
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @len: the request number of bytes to read (up to 8 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 8 bytes of data from the extended register space on a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_readl(struct spmi_controller *ctrl,
+				u8 sid, u16 addr, u8 *buf, int len)
+{
+	/* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */
+	if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 8)
+		return -EINVAL;
+
+	return spmi_read_cmd(ctrl, SPMI_CMD_EXT_READL, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_readl);
+
+/**
+ * spmi_register_write() - register write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ *
+ * Writes 1 byte of data to a Slave device register.
+ */
+int spmi_register_write(struct spmi_controller *ctrl, u8 sid, u8 addr, u8 *buf)
+{
+	u8 op = SPMI_CMD_WRITE;
+
+	/* 4-bit Slave Identifier, 5-bit register address */
+	if (sid > SPMI_MAX_SLAVE_ID || addr > 0x1F)
+		return -EINVAL;
+
+	return spmi_write_cmd(ctrl, op, sid, addr, 0, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_register_write);
+
+/**
+ * spmi_register_zero_write() - register zero write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @data: the data to be written to register 0 (7-bits).
+ *
+ * Writes data to register 0 of the Slave device.
+ */
+int spmi_register_zero_write(struct spmi_controller *ctrl, u8 sid, u8 data)
+{
+	u8 op = SPMI_CMD_ZERO_WRITE;
+
+	/* 4-bit Slave Identifier, 5-bit register address */
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+
+	return spmi_write_cmd(ctrl, op, sid, 0, 0, &data);
+}
+EXPORT_SYMBOL_GPL(spmi_register_zero_write);
+
+/**
+ * spmi_ext_register_write() - extended register write
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 16 bytes).
+ *
+ * Writes up to 16 bytes of data to the extended register space of a
+ * Slave device.
+ */
+int spmi_ext_register_write(struct spmi_controller *ctrl,
+				u8 sid, u8 addr, u8 *buf, int len)
+{
+	u8 op = SPMI_CMD_EXT_WRITE;
+
+	/* 4-bit Slave Identifier, 8-bit register address, up to 16 bytes */
+	if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 16)
+		return -EINVAL;
+
+	return spmi_write_cmd(ctrl, op, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_write);
+
+/**
+ * spmi_ext_register_writel() - extended register write long
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 8 bytes).
+ *
+ * Writes up to 8 bytes of data to the extended register space of a
+ * Slave device using 16-bit address.
+ */
+int spmi_ext_register_writel(struct spmi_controller *ctrl,
+				u8 sid, u16 addr, u8 *buf, int len)
+{
+	u8 op = SPMI_CMD_EXT_WRITEL;
+
+	/* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */
+	if (sid > SPMI_MAX_SLAVE_ID || len <= 0 || len > 8)
+		return -EINVAL;
+
+	return spmi_write_cmd(ctrl, op, sid, addr, len - 1, buf);
+}
+EXPORT_SYMBOL_GPL(spmi_ext_register_writel);
+
+/**
+ * spmi_command_reset() - sends RESET command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Reset command initializes the Slave and forces all registers to
+ * their reset values. The Slave shall enter the STARTUP state after
+ * receiving a Reset command.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_reset(struct spmi_controller *ctrl, u8 sid)
+{
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+	return spmi_cmd(ctrl, SPMI_CMD_RESET, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_reset);
+
+/**
+ * spmi_command_sleep() - sends SLEEP command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Sleep command causes the Slave to enter the user defined SLEEP state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_sleep(struct spmi_controller *ctrl, u8 sid)
+{
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+	return spmi_cmd(ctrl, SPMI_CMD_SLEEP, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_sleep);
+
+/**
+ * spmi_command_wakeup() - sends WAKEUP command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Wakeup command causes the Slave to move from the SLEEP state to
+ * the ACTIVE state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_wakeup(struct spmi_controller *ctrl, u8 sid)
+{
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+	return spmi_cmd(ctrl, SPMI_CMD_WAKEUP, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_wakeup);
+
+/**
+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified slave
+ * @dev: SPMI device.
+ * @sid: slave identifier.
+ *
+ * The Shutdown command causes the Slave to enter the SHUTDOWN state.
+ *
+ * Returns
+ * -EINVAL for invalid Slave Identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+int spmi_command_shutdown(struct spmi_controller *ctrl, u8 sid)
+{
+	if (sid > SPMI_MAX_SLAVE_ID)
+		return -EINVAL;
+	return spmi_cmd(ctrl, SPMI_CMD_SHUTDOWN, sid);
+}
+EXPORT_SYMBOL_GPL(spmi_command_shutdown);
+
+/* ------------------------------------------------------------------------- */
+
+static const struct spmi_device_id *spmi_match(const struct spmi_device_id *id,
+		const struct spmi_device *spmi_dev)
+{
+	while (id->name[0]) {
+		if (strncmp(spmi_dev->name, id->name, SPMI_NAME_SIZE) == 0)
+			return id;
+		id++;
+	}
+	return NULL;
+}
+
+static int spmi_device_match(struct device *dev, struct device_driver *drv)
+{
+	struct spmi_device *spmi_dev;
+	struct spmi_driver *sdrv = to_spmi_driver(drv);
+
+	if (dev->type == &spmi_dev_type)
+		spmi_dev = to_spmi_device(dev);
+	else
+		return 0;
+
+	/* Attempt an OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
+	if (sdrv->id_table)
+		return spmi_match(sdrv->id_table, spmi_dev) != NULL;
+
+	if (drv->name)
+		return strncmp(spmi_dev->name, drv->name, SPMI_NAME_SIZE) == 0;
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int spmi_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct spmi_device *spmi_dev = NULL;
+	struct spmi_driver *driver;
+	if (dev->type == &spmi_dev_type)
+		spmi_dev = to_spmi_device(dev);
+
+	if (!spmi_dev || !dev->driver)
+		return 0;
+
+	driver = to_spmi_driver(dev->driver);
+	if (!driver->suspend)
+		return 0;
+
+	return driver->suspend(spmi_dev, mesg);
+}
+
+static int spmi_legacy_resume(struct device *dev)
+{
+	struct spmi_device *spmi_dev = NULL;
+	struct spmi_driver *driver;
+	if (dev->type == &spmi_dev_type)
+		spmi_dev = to_spmi_device(dev);
+
+	if (!spmi_dev || !dev->driver)
+		return 0;
+
+	driver = to_spmi_driver(dev->driver);
+	if (!driver->resume)
+		return 0;
+
+	return driver->resume(spmi_dev);
+}
+
+static int spmi_pm_suspend(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_suspend(dev);
+	else
+		return spmi_legacy_suspend(dev, PMSG_SUSPEND);
+}
+
+static int spmi_pm_resume(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm)
+		return pm_generic_resume(dev);
+	else
+		return spmi_legacy_resume(dev);
+}
+
+#else
+#define spmi_pm_suspend		NULL
+#define spmi_pm_resume		NULL
+#endif
+
+static const struct dev_pm_ops spmi_pm_ops = {
+	.suspend = spmi_pm_suspend,
+	.resume = spmi_pm_resume,
+	SET_RUNTIME_PM_OPS(
+		pm_generic_suspend,
+		pm_generic_resume,
+		pm_generic_runtime_idle
+		)
+};
+struct bus_type spmi_bus_type = {
+	.name		= "spmi",
+	.match		= spmi_device_match,
+	.pm		= &spmi_pm_ops,
+};
+EXPORT_SYMBOL_GPL(spmi_bus_type);
+
+struct device spmi_dev = {
+	.init_name = "spmi",
+};
+
+static int spmi_drv_probe(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+	return sdrv->probe(to_spmi_device(dev));
+}
+
+static int spmi_drv_remove(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+	return sdrv->remove(to_spmi_device(dev));
+}
+
+static void spmi_drv_shutdown(struct device *dev)
+{
+	const struct spmi_driver *sdrv = to_spmi_driver(dev->driver);
+
+	sdrv->shutdown(to_spmi_device(dev));
+}
+
+/**
+ * spmi_driver_register: Client driver registration with SPMI framework.
+ * @drv: client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the SPMI framework.
+ * It is called from the driver's module-init function.
+ */
+int spmi_driver_register(struct spmi_driver *drv)
+{
+	drv->driver.bus = &spmi_bus_type;
+
+	if (drv->probe)
+		drv->driver.probe = spmi_drv_probe;
+
+	if (drv->remove)
+		drv->driver.remove = spmi_drv_remove;
+
+	if (drv->shutdown)
+		drv->driver.shutdown = spmi_drv_shutdown;
+
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(spmi_driver_register);
+
+static int spmi_register_controller(struct spmi_controller *ctrl)
+{
+	int ret = 0;
+
+	/* Can't register until after driver model init */
+	if (WARN_ON(!spmi_bus_type.p)) {
+		ret = -EAGAIN;
+		goto exit;
+	}
+
+	dev_set_name(&ctrl->dev, "spmi-%d", ctrl->nr);
+	ctrl->dev.bus = &spmi_bus_type;
+	ctrl->dev.type = &spmi_ctrl_type;
+	ret = device_register(&ctrl->dev);
+	if (ret)
+		goto exit;
+
+	dev_dbg(&ctrl->dev, "Bus spmi-%d registered: dev:%x\n",
+					ctrl->nr, (u32)&ctrl->dev);
+
+	mutex_lock(&board_lock);
+	list_add_tail(&ctrl->list, &spmi_ctrl_list);
+	mutex_unlock(&board_lock);
+
+	return 0;
+
+exit:
+	mutex_lock(&board_lock);
+	idr_remove(&ctrl_idr, ctrl->nr);
+	mutex_unlock(&board_lock);
+	return ret;
+}
+
+static void __exit spmi_exit(void)
+{
+	device_unregister(&spmi_dev);
+	bus_unregister(&spmi_bus_type);
+}
+
+static int __init spmi_init(void)
+{
+	int retval;
+
+	retval = bus_register(&spmi_bus_type);
+	if (!retval)
+		retval = device_register(&spmi_dev);
+
+	if (retval)
+		bus_unregister(&spmi_bus_type);
+
+	return retval;
+}
+postcore_initcall(spmi_init);
+module_exit(spmi_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("SPMI module");
+MODULE_ALIAS("platform:spmi");
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
index d12c8e8..c900647 100644
--- a/drivers/staging/qcache/fmem.c
+++ b/drivers/staging/qcache/fmem.c
@@ -51,9 +51,11 @@
 {
 	struct fmem_platform_data *pdata = pdev->dev.platform_data;
 
-	fmem_data.phys = pdata->phys + pdata->reserved_size;
-	fmem_data.size = pdata->size - pdata->reserved_size;
-	fmem_data.reserved_size = pdata->reserved_size;
+	fmem_data.phys = pdata->phys + pdata->reserved_size_low;
+	fmem_data.size = pdata->size - pdata->reserved_size_low -
+					pdata->reserved_size_high;
+	fmem_data.reserved_size_low = pdata->reserved_size_low;
+	fmem_data.reserved_size_high = pdata->reserved_size_high;
 
 	if (!fmem_data.size)
 		return -ENODEV;
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index 2a2166a..0e279b8 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/msm_tsens.h>
 #include <linux/io.h>
+#include <linux/err.h>
 
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
@@ -56,10 +57,12 @@
 #define SENSOR4_EN					BIT(7)
 #define SENSORS_EN			(SENSOR0_EN | SENSOR1_EN |	\
 					SENSOR2_EN | SENSOR3_EN | SENSOR4_EN)
-#define TSENS_MIN_STATUS_MASK				BIT(8)
-#define TSENS_LOWER_STATUS_CLR				BIT(9)
-#define TSENS_UPPER_STATUS_CLR				BIT(10)
-#define TSENS_MAX_STATUS_MASK				BIT(11)
+#define TSENS_STATUS_CNTL_OFFSET	8
+#define TSENS_MIN_STATUS_MASK		BIT((tsens_status_cntl_start))
+#define TSENS_LOWER_STATUS_CLR		BIT((tsens_status_cntl_start + 1))
+#define TSENS_UPPER_STATUS_CLR		BIT((tsens_status_cntl_start + 2))
+#define TSENS_MAX_STATUS_MASK		BIT((tsens_status_cntl_start + 3))
+
 #define TSENS_MEASURE_PERIOD				4 /* 1 sec. default */
 #define TSENS_8960_SLP_CLK_ENA				BIT(26)
 
@@ -86,6 +89,7 @@
 
 #define TSENS_S0_STATUS_ADDR			(MSM_CLK_CTL_BASE + 0x00003628)
 #define TSENS_STATUS_ADDR_OFFSET			2
+#define TSENS_SENSOR_STATUS_SIZE			4
 #define TSENS_INT_STATUS_ADDR			(MSM_CLK_CTL_BASE + 0x0000363c)
 
 #define TSENS_LOWER_INT_MASK				BIT(1)
@@ -113,6 +117,26 @@
 #define TSENS_8660_CONFIG_MASK			(3 << TSENS_8660_CONFIG_SHIFT)
 #define TSENS_8660_SLP_CLK_ENA				BIT(24)
 
+#define TSENS_8064_SENSOR5_EN				BIT(8)
+#define TSENS_8064_SENSOR6_EN				BIT(9)
+#define TSENS_8064_SENSOR7_EN				BIT(10)
+#define TSENS_8064_SENSOR8_EN				BIT(11)
+#define TSENS_8064_SENSOR9_EN				BIT(12)
+#define TSENS_8064_SENSOR10_EN				BIT(13)
+#define TSENS_8064_SENSORS_EN			(SENSORS_EN | \
+						TSENS_8064_SENSOR5_EN | \
+						TSENS_8064_SENSOR6_EN | \
+						TSENS_8064_SENSOR7_EN | \
+						TSENS_8064_SENSOR8_EN | \
+						TSENS_8064_SENSOR9_EN | \
+						TSENS_8064_SENSOR10_EN)
+#define TSENS_8064_STATUS_CNTL			(MSM_CLK_CTL_BASE + 0x00003660)
+#define TSENS_8064_S5_STATUS_ADDR		(MSM_CLK_CTL_BASE + 0x00003664)
+#define TSENS_8064_SEQ_SENSORS				5
+#define TSENS_8064_S4_S5_OFFSET				40
+
+static int tsens_status_cntl_start;
+
 struct tsens_tm_device_sensor {
 	struct thermal_zone_device	*tz_dev;
 	enum thermal_device_mode	mode;
@@ -121,11 +145,11 @@
 	int				offset;
 	int				calib_data;
 	int				calib_data_backup;
+	uint32_t			slope_mul_tsens_factor;
 };
 
 struct tsens_tm_device {
 	bool				prev_reading_avail;
-	int				slope_mul_tsens_factor;
 	int				tsens_factor;
 	uint32_t			tsens_num_sensor;
 	enum platform_type		hw_type;
@@ -137,26 +161,28 @@
 /* Temperature on y axis and ADC-code on x-axis */
 static int tsens_tz_code_to_degC(int adc_code, int sensor_num)
 {
-	int degC, degcbeforefactor;
-	degcbeforefactor = adc_code * tmdev->slope_mul_tsens_factor
-				+ tmdev->sensor[sensor_num].offset;
+	int degcbeforefactor, degc;
+	degcbeforefactor = (adc_code *
+			tmdev->sensor[sensor_num].slope_mul_tsens_factor
+			+ tmdev->sensor[sensor_num].offset);
+
 	if (degcbeforefactor == 0)
-		degC = degcbeforefactor;
+		degc = degcbeforefactor;
 	else if (degcbeforefactor > 0)
-		degC = (degcbeforefactor + tmdev->tsens_factor/2)
-						/ tmdev->tsens_factor;
-	else  /* rounding for negative degrees */
-		degC = (degcbeforefactor - tmdev->tsens_factor/2)
-						/ tmdev->tsens_factor;
-	return degC;
+		degc = (degcbeforefactor + tmdev->tsens_factor/2)
+				/ tmdev->tsens_factor;
+	else
+		degc = (degcbeforefactor - tmdev->tsens_factor/2)
+				/ tmdev->tsens_factor;
+	return degc;
 }
 
 static int tsens_tz_degC_to_code(int degC, int sensor_num)
 {
 	int code = (degC * tmdev->tsens_factor -
-			tmdev->sensor[sensor_num].offset
-			+ tmdev->slope_mul_tsens_factor/2)
-			/ tmdev->slope_mul_tsens_factor;
+		tmdev->sensor[sensor_num].offset
+		+ tmdev->sensor[sensor_num].slope_mul_tsens_factor/2)
+		/ tmdev->sensor[sensor_num].slope_mul_tsens_factor;
 
 	if (code > TSENS_THRESHOLD_MAX_CODE)
 		code = TSENS_THRESHOLD_MAX_CODE;
@@ -167,7 +193,7 @@
 
 static void tsens8960_get_temp(int sensor_num, unsigned long *temp)
 {
-	unsigned int code;
+	unsigned int code, offset = 0, sensor_addr;
 
 	if (!tmdev->prev_reading_avail) {
 		while (!(readl_relaxed(TSENS_INT_STATUS_ADDR)
@@ -176,7 +202,12 @@
 				TSENS_TRDY_RDY_MAX_TIME);
 		tmdev->prev_reading_avail = true;
 	}
-	code = readl_relaxed(TSENS_S0_STATUS_ADDR +
+
+	sensor_addr = (unsigned int)TSENS_S0_STATUS_ADDR;
+	if (tmdev->hw_type == APQ_8064 &&
+			sensor_num >= TSENS_8064_SEQ_SENSORS)
+		offset = TSENS_8064_S4_S5_OFFSET;
+	code = readl_relaxed(sensor_addr + offset +
 			(sensor_num << TSENS_STATUS_ADDR_OFFSET));
 	*temp = tsens_tz_code_to_degC(code, sensor_num);
 }
@@ -247,7 +278,8 @@
 			}
 			writel_relaxed(reg | TSENS_SW_RST, TSENS_CNTL_ADDR);
 			if (tmdev->hw_type == MSM_8960 ||
-						tmdev->hw_type == MSM_9615)
+				tmdev->hw_type == MSM_9615 ||
+				tmdev->hw_type == APQ_8064)
 				reg |= mask | TSENS_8960_SLP_CLK_ENA
 							| TSENS_EN;
 			else
@@ -257,7 +289,11 @@
 		} else {
 			reg &= ~mask;
 			if (!(reg & SENSOR0_EN)) {
-				if (tmdev->hw_type == MSM_8960 ||
+				if (tmdev->hw_type == APQ_8064)
+					reg &= ~(TSENS_8064_SENSORS_EN |
+						TSENS_8960_SLP_CLK_ENA |
+						TSENS_EN);
+				else if (tmdev->hw_type == MSM_8960 ||
 						tmdev->hw_type == MSM_9615)
 					reg &= ~(SENSORS_EN |
 						TSENS_8960_SLP_CLK_ENA |
@@ -319,7 +355,11 @@
 	lo_code = TSENS_THRESHOLD_MIN_CODE;
 	hi_code = TSENS_THRESHOLD_MAX_CODE;
 
-	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == APQ_8064)
+		reg_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+	else
+		reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+
 	reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR);
 	switch (trip) {
 	case TSENS_TRIP_STAGE3:
@@ -386,14 +426,21 @@
 		return -EINVAL;
 	}
 
-	if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
-		writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR);
-	else {
+	if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) {
+		if (tmdev->hw_type == APQ_8064)
+			writel_relaxed(reg_cntl | mask, TSENS_8064_STATUS_CNTL);
+		else
+			writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR);
+	} else {
 		if (code < lo_code || code > hi_code) {
 			pr_info("%s with invalid code %x\n", __func__, code);
 			return -EINVAL;
 		}
-		writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR);
+		if (tmdev->hw_type == APQ_8064)
+			writel_relaxed(reg_cntl & ~mask,
+					TSENS_8064_STATUS_CNTL);
+		else
+			writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR);
 	}
 	mb();
 	return 0;
@@ -465,7 +512,10 @@
 	lo_code = TSENS_THRESHOLD_MIN_CODE;
 	hi_code = TSENS_THRESHOLD_MAX_CODE;
 
-	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == APQ_8064)
+		reg_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+	else
+		reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
 	reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR);
 	switch (trip) {
 	case TSENS_TRIP_STAGE3:
@@ -561,25 +611,40 @@
 {
 	struct tsens_tm_device *tm = data;
 	unsigned int threshold, threshold_low, i, code, reg, sensor, mask;
+	unsigned int sensor_addr;
 	bool upper_th_x, lower_th_x;
 	int adc_code;
 
-	reg = readl_relaxed(TSENS_CNTL_ADDR);
-	writel_relaxed(reg | TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR,
-			TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == APQ_8064) {
+		reg = readl_relaxed(TSENS_8064_STATUS_CNTL);
+		writel_relaxed(reg | TSENS_LOWER_STATUS_CLR |
+			TSENS_UPPER_STATUS_CLR, TSENS_8064_STATUS_CNTL);
+	} else {
+		reg = readl_relaxed(TSENS_CNTL_ADDR);
+		writel_relaxed(reg | TSENS_LOWER_STATUS_CLR |
+			TSENS_UPPER_STATUS_CLR, TSENS_CNTL_ADDR);
+	}
 	mask = ~(TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR);
 	threshold = readl_relaxed(TSENS_THRESHOLD_ADDR);
 	threshold_low = (threshold & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
 					>> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT;
 	threshold = (threshold & TSENS_THRESHOLD_UPPER_LIMIT_MASK)
 					>> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT;
-	reg = sensor = readl_relaxed(TSENS_CNTL_ADDR);
-	sensor &= (uint32_t) SENSORS_EN;
+	sensor = readl_relaxed(TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == APQ_8064) {
+		reg = readl_relaxed(TSENS_8064_STATUS_CNTL);
+		sensor &= (uint32_t) TSENS_8064_SENSORS_EN;
+	} else {
+		reg = sensor;
+		sensor &= (uint32_t) SENSORS_EN;
+	}
 	sensor >>= TSENS_SENSOR0_SHIFT;
+	sensor_addr = (unsigned int)TSENS_S0_STATUS_ADDR;
 	for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+		if (i == TSENS_8064_SEQ_SENSORS)
+			sensor_addr += TSENS_8064_S4_S5_OFFSET;
 		if (sensor & TSENS_MASK1) {
-			code = readl_relaxed(TSENS_S0_STATUS_ADDR +
-					(i << TSENS_STATUS_ADDR_OFFSET));
+			code = readl_relaxed(sensor_addr);
 			upper_th_x = code >= threshold;
 			lower_th_x = code <= threshold_low;
 			if (upper_th_x)
@@ -589,8 +654,7 @@
 			if (upper_th_x || lower_th_x) {
 				/* Notify user space */
 				schedule_work(&tm->sensor[i].work);
-				adc_code = readl_relaxed(TSENS_S0_STATUS_ADDR
-					+ (i << TSENS_STATUS_ADDR_OFFSET));
+				adc_code = readl_relaxed(sensor_addr);
 				pr_info("\nTrip point triggered by "
 					"current temperature (%d degrees) "
 					"measured by Temperature-Sensor %d\n",
@@ -598,18 +662,37 @@
 			}
 		}
 		sensor >>= 1;
+		sensor_addr += TSENS_SENSOR_STATUS_SIZE;
 	}
+	if (tmdev->hw_type == APQ_8064)
+		writel_relaxed(reg & mask, TSENS_8064_STATUS_CNTL);
+	else
 	writel_relaxed(reg & mask, TSENS_CNTL_ADDR);
 	mb();
 	return IRQ_HANDLED;
 }
 
+static void tsens8960_sensor_mode_init(void)
+{
+	unsigned int reg_cntl = 0;
+
+	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
+	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+			tmdev->hw_type == APQ_8064) {
+		writel_relaxed(reg_cntl &
+				~((((1 << tmdev->tsens_num_sensor) - 1) >> 1)
+				<< (TSENS_SENSOR0_SHIFT + 1)), TSENS_CNTL_ADDR);
+		tmdev->sensor[TSENS_MAIN_SENSOR].mode = THERMAL_DEVICE_ENABLED;
+	}
+}
+
 static void tsens_disable_mode(void)
 {
 	unsigned int reg_cntl = 0;
 
 	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
-	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615)
+	if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+			tmdev->hw_type == APQ_8064)
 		writel_relaxed(reg_cntl &
 				~((((1 << tmdev->tsens_num_sensor) - 1) <<
 				TSENS_SENSOR0_SHIFT) | TSENS_8960_SLP_CLK_ENA
@@ -624,6 +707,7 @@
 static void tsens_hw_init(void)
 {
 	unsigned int reg_cntl = 0, reg_cfg = 0, reg_thr = 0;
+	unsigned int reg_status_cntl = 0;
 
 	reg_cntl = readl_relaxed(TSENS_CNTL_ADDR);
 	writel_relaxed(reg_cntl | TSENS_SW_RST, TSENS_CNTL_ADDR);
@@ -657,6 +741,25 @@
 				(TSENS_8660_CONFIG << TSENS_8660_CONFIG_SHIFT);
 
 		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+	} else if (tmdev->hw_type == APQ_8064) {
+		reg_cntl |= TSENS_8960_SLP_CLK_ENA |
+			(TSENS_MEASURE_PERIOD << 18) |
+			(((1 << tmdev->tsens_num_sensor) - 1) <<
+			 TSENS_SENSOR0_SHIFT);
+		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+		reg_status_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL);
+		reg_status_cntl |= TSENS_LOWER_STATUS_CLR |
+			TSENS_UPPER_STATUS_CLR |
+			TSENS_MIN_STATUS_MASK |
+			TSENS_MAX_STATUS_MASK;
+		writel_relaxed(reg_status_cntl, TSENS_8064_STATUS_CNTL);
+		reg_cntl |= TSENS_EN;
+		writel_relaxed(reg_cntl, TSENS_CNTL_ADDR);
+
+		reg_cfg = readl_relaxed(TSENS_8960_CONFIG_ADDR);
+		reg_cfg = (reg_cfg & ~TSENS_8960_CONFIG_MASK) |
+			(TSENS_8960_CONFIG << TSENS_8960_CONFIG_SHIFT);
+		writel_relaxed(reg_cfg, TSENS_8960_CONFIG_ADDR);
 	}
 
 	reg_thr |= (TSENS_LOWER_LIMIT_TH << TSENS_THRESHOLD_LOWER_LIMIT_SHIFT) |
@@ -692,8 +795,10 @@
 	}
 
 	tmdev->sensor[TSENS_MAIN_SENSOR].offset = tmdev->tsens_factor *
-		TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor *
+		TSENS_CAL_DEGC -
+		tmdev->sensor[TSENS_MAIN_SENSOR].slope_mul_tsens_factor *
 		tmdev->sensor[TSENS_MAIN_SENSOR].calib_data;
+
 	tmdev->prev_reading_avail = false;
 	INIT_WORK(&tmdev->sensor[TSENS_MAIN_SENSOR].work,
 						notify_uspace_tsens_fn);
@@ -703,35 +808,27 @@
 
 static int tsens_calib_sensors8960(void)
 {
-	uint32_t *main_sensor_addr, sensor_shift, *backup_sensor_addr;
-	uint32_t sensor_mask, i;
+	uint32_t i;
+	uint8_t *main_sensor_addr, *backup_sensor_addr;
 	for (i = 0; i < tmdev->tsens_num_sensor; i++) {
-		main_sensor_addr = TSENS_8960_QFPROM_ADDR0 +
-			(TSENS_8960_QFPROM_SHIFT *
-		((i & TSENS_8960_QFPROM_SHIFT) >> TSENS_SENSOR_QFPROM_SHIFT));
-		sensor_shift = (i % TSENS_8960_QFPROM_SHIFT) * TSENS_RED_SHIFT;
-		sensor_mask = TSENS_THRESHOLD_MAX_CODE << sensor_shift;
-		backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 +
-			(TSENS_8960_QFPROM_SHIFT *
-		((i & TSENS_8960_QFPROM_SHIFT) >> TSENS_SENSOR_QFPROM_SHIFT));
+		main_sensor_addr = TSENS_8960_QFPROM_ADDR0 + i;
+		backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 + i;
 
-		tmdev->sensor[i].calib_data = (readl_relaxed(main_sensor_addr)
-			& sensor_mask) >> sensor_shift;
+		tmdev->sensor[i].calib_data = readb_relaxed(main_sensor_addr);
 		tmdev->sensor[i].calib_data_backup =
-			(readl_relaxed(backup_sensor_addr) &
-				sensor_mask) >> sensor_shift;
+			readb_relaxed(backup_sensor_addr);
 		if (tmdev->sensor[i].calib_data_backup)
 			tmdev->sensor[i].calib_data =
 				tmdev->sensor[i].calib_data_backup;
-
 		if (!tmdev->sensor[i].calib_data) {
 			WARN(1, "%s: No temperature sensor:%d data for"
 			" calibration in QFPROM!\n", __func__, i);
 			return -ENODEV;
 		}
-		tmdev->sensor[i].offset = tmdev->tsens_factor *
-			TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor *
-			tmdev->sensor[i].calib_data;
+		tmdev->sensor[i].offset = (TSENS_CAL_DEGC *
+			tmdev->tsens_factor)
+			- (tmdev->sensor[i].calib_data *
+			tmdev->sensor[i].slope_mul_tsens_factor);
 		tmdev->prev_reading_avail = false;
 		INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
 	}
@@ -756,7 +853,8 @@
 
 	if (tmdev->hw_type == MSM_8660)
 		rc = tsens_calib_sensors8660();
-	else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615)
+	else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 ||
+		tmdev->hw_type == APQ_8064)
 		rc = tsens_calib_sensors8960();
 
 	return rc;
@@ -764,7 +862,7 @@
 
 int msm_tsens_early_init(struct tsens_platform_data *pdata)
 {
-	int rc = 0;
+	int rc = 0, i;
 
 	if (!pdata) {
 		pr_err("No TSENS Platform data\n");
@@ -780,7 +878,8 @@
 		return -ENOMEM;
 	}
 
-	tmdev->slope_mul_tsens_factor = pdata->slope;
+	for (i = 0; i < pdata->tsens_num_sensor; i++)
+		tmdev->sensor[i].slope_mul_tsens_factor = pdata->slope[i];
 	tmdev->tsens_factor = pdata->tsens_factor;
 	tmdev->tsens_num_sensor = pdata->tsens_num_sensor;
 	tmdev->hw_type = pdata->hw_type;
@@ -799,9 +898,14 @@
 		return rc;
 	}
 
+	if (tmdev->hw_type == APQ_8064)
+		tsens_status_cntl_start = 0;
+	else
+		tsens_status_cntl_start = TSENS_STATUS_CNTL_OFFSET;
+
 	tsens_hw_init();
 
-	pr_info("msm_tsens_early_init: done\n");
+	pr_debug("msm_tsens_early_init: done\n");
 
 	return rc;
 }
@@ -823,7 +927,7 @@
 		tmdev->sensor[i].tz_dev = thermal_zone_device_register(name,
 				TSENS_TRIP_NUM, &tmdev->sensor[i],
 				&tsens_thermal_zone_ops, 0, 0, 0, 0);
-		if (tmdev->sensor[i].tz_dev == NULL) {
+		if (IS_ERR(tmdev->sensor[i].tz_dev)) {
 			pr_err("%s: thermal_zone_device_register() failed.\n",
 			__func__);
 			rc = -ENODEV;
@@ -832,6 +936,8 @@
 		tmdev->sensor[i].mode = THERMAL_DEVICE_DISABLED;
 	}
 
+	tsens8960_sensor_mode_init();
+
 	rc = request_irq(TSENS_UPPER_LOWER_INT, tsens_isr,
 		IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
 	if (rc < 0) {
@@ -841,7 +947,7 @@
 		goto fail;
 	}
 
-	pr_notice("%s: OK\n", __func__);
+	pr_debug("%s: OK\n", __func__);
 	mb();
 	return 0;
 fail:
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index ed80b1b..ef28844 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -51,10 +51,7 @@
 	cpu_policy->user_policy.max = max_freq;
 
 	ret = cpufreq_update_policy(cpu);
-	if (ret)
-		pr_err("msm_thermal: cpufreq update to core%d %d err:%d\n",
-				cpu, max_freq, ret);
-	else
+	if (!ret)
 		pr_info("msm_thermal: Limiting core%d max frequency to %d\n",
 			cpu, max_freq);
 
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 9e85eb5..32e9dc0 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -2,7 +2,7 @@
  * drivers/serial/msm_serial.c - driver for msm7k serial device and console
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  * Author: Robert Love <rlove@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -102,48 +102,32 @@
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr &= ~UART_IMR_TXLEV;
 	msm_write(port, msm_port->imr, UART_IMR);
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_start_tx(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr |= UART_IMR_TXLEV;
 	msm_write(port, msm_port->imr, UART_IMR);
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_stop_rx(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE);
 	msm_write(port, msm_port->imr, UART_IMR);
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_enable_ms(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr |= UART_IMR_DELTA_CTS;
 	msm_write(port, msm_port->imr, UART_IMR);
-
-	clk_disable(msm_port->clk);
 }
 
 #ifdef CONFIG_SERIAL_MSM_CLOCK_CONTROL
@@ -365,7 +349,6 @@
 	unsigned int misr;
 
 	spin_lock_irqsave(&port->lock, flags);
-	clk_enable(msm_port->clk);
 	misr = msm_read(port, UART_MISR);
 	msm_write(port, 0, UART_IMR); /* disable interrupt */
 
@@ -377,7 +360,6 @@
 		handle_delta_cts(port);
 
 	msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */
-	clk_disable(msm_port->clk);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	return IRQ_HANDLED;
@@ -386,12 +368,8 @@
 static unsigned int msm_tx_empty(struct uart_port *port)
 {
 	unsigned int ret;
-	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
 	ret = (msm_read(port, UART_SR) & UART_SR_TX_EMPTY) ? TIOCSER_TEMT : 0;
-	clk_disable(msm_port->clk);
-
 	return ret;
 }
 
@@ -403,9 +381,6 @@
 static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	unsigned int mr;
-	struct msm_port *msm_port = UART_TO_MSM(port);
-
-	clk_enable(msm_port->clk);
 
 	mr = msm_read(port, UART_MR1);
 
@@ -417,22 +392,14 @@
 		mr |= UART_MR1_RX_RDY_CTL;
 		msm_write(port, mr, UART_MR1);
 	}
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_break_ctl(struct uart_port *port, int break_ctl)
 {
-	struct msm_port *msm_port = UART_TO_MSM(port);
-
-	clk_enable(msm_port->clk);
-
 	if (break_ctl)
 		msm_write(port, UART_CR_CMD_START_BREAK, UART_CR);
 	else
 		msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR);
-
-	clk_disable(msm_port->clk);
 }
 
 static void msm_set_baud_rate(struct uart_port *port, unsigned int baud)
@@ -520,9 +487,14 @@
 
 static void msm_init_clock(struct uart_port *port)
 {
+	int ret;
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
+	ret = clk_prepare_enable(msm_port->clk);
+	if (ret) {
+		pr_err("%s(): Can't enable uartclk. ret:%d\n", __func__, ret);
+		return;
+	}
 
 #ifdef CONFIG_SERIAL_MSM_CLOCK_CONTROL
 	msm_port->clk_state = MSM_CLK_ON;
@@ -552,7 +524,7 @@
 		clk_disable(msm_port->clk);
 	msm_port->clk_state = MSM_CLK_PORT_OFF;
 #else
-	clk_disable(msm_port->clk);
+	clk_disable_unprepare(msm_port->clk);
 #endif
 
 }
@@ -631,13 +603,9 @@
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
-	clk_enable(msm_port->clk);
-
 	msm_port->imr = 0;
 	msm_write(port, 0, UART_IMR); /* disable interrupts */
 
-	clk_disable(msm_port->clk);
-
 	free_irq(port->irq, port);
 
 #ifdef CONFIG_SERIAL_MSM_RX_WAKEUP
@@ -657,10 +625,8 @@
 {
 	unsigned long flags;
 	unsigned int baud, mr;
-	struct msm_port *msm_port = UART_TO_MSM(port);
 
 	spin_lock_irqsave(&port->lock, flags);
-	clk_enable(msm_port->clk);
 
 	/* calculate and set baud rate */
 	baud = uart_get_baud_rate(port, termios, old, 300, 115200);
@@ -723,8 +689,6 @@
 		port->read_status_mask |= UART_SR_RX_BREAK;
 
 	uart_update_timeout(port, termios->c_cflag, baud);
-
-	clk_disable(msm_port->clk);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -792,20 +756,23 @@
 static void msm_power(struct uart_port *port, unsigned int state,
 		      unsigned int oldstate)
 {
-#ifndef CONFIG_SERIAL_MSM_CLOCK_CONTROL
+	int ret;
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
 	switch (state) {
 	case 0:
-		clk_enable(msm_port->clk);
+		ret = clk_prepare_enable(msm_port->clk);
+		if (ret)
+			pr_err("msm_serial: %s(): Can't enable uartclk.\n",
+						__func__);
 		break;
 	case 3:
-		clk_disable(msm_port->clk);
+		clk_disable_unprepare(msm_port->clk);
 		break;
 	default:
-		printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state);
+		pr_err("msm_serial: %s(): Unknown PM state %d\n",
+						__func__, state);
 	}
-#endif
 }
 
 static struct uart_ops msm_uart_pops = {
diff --git a/drivers/usb/gadget/u_data_hsic.c b/drivers/usb/gadget/u_data_hsic.c
index 7b77a1d..818e2a6 100644
--- a/drivers/usb/gadget/u_data_hsic.c
+++ b/drivers/usb/gadget/u_data_hsic.c
@@ -85,8 +85,7 @@
 	unsigned		port_num;
 
 	/* gadget */
-	spinlock_t		port_lock;
-	void			*port_usb;
+	atomic_t		connected;
 	struct usb_ep		*in;
 	struct usb_ep		*out;
 
@@ -96,10 +95,12 @@
 	unsigned int		tx_q_size;
 	struct list_head	tx_idle;
 	struct sk_buff_head	tx_skb_q;
+	spinlock_t		tx_lock;
 
 	unsigned int		rx_q_size;
 	struct list_head	rx_idle;
 	struct sk_buff_head	rx_skb_q;
+	spinlock_t		rx_lock;
 
 	/* work */
 	struct workqueue_struct	*wq;
@@ -175,17 +176,16 @@
 	struct gdata_port	*port = ctx;
 	unsigned long		flags;
 
-	if (!port)
+	if (!port || !atomic_read(&port->connected))
 		return;
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb) {
-		port->tx_unthrottled_cnt++;
-		queue_work(port->wq, &port->write_tomdm_w);
-		pr_debug("%s: port num =%d unthrottled\n", __func__,
-			port->port_num);
-	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_lock_irqsave(&port->rx_lock, flags);
+	port->tx_unthrottled_cnt++;
+	spin_unlock_irqrestore(&port->rx_lock, flags);
+
+	queue_work(port->wq, &port->write_tomdm_w);
+	pr_debug("%s: port num =%d unthrottled\n", __func__,
+		port->port_num);
 }
 
 static void ghsic_data_write_tohost(struct work_struct *w)
@@ -200,14 +200,16 @@
 
 	port = container_of(w, struct gdata_port, write_tohost_w);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+	if (!port)
+		return;
+
+	spin_lock_irqsave(&port->tx_lock, flags);
+	ep = port->in;
+	if (!ep) {
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		return;
 	}
 
-	ep = port->in;
-
 	while (!list_empty(&port->tx_idle)) {
 		skb = __skb_dequeue(&port->tx_skb_q);
 		if (!skb)
@@ -231,9 +233,9 @@
 
 		info = (struct timestamp_info *)skb->cb;
 		info->tx_queued = get_timestamp();
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		ret = usb_ep_queue(ep, req, GFP_KERNEL);
-		spin_lock_irqsave(&port->port_lock, flags);
+		spin_lock_irqsave(&port->tx_lock, flags);
 		if (ret) {
 			pr_err("%s: usb epIn failed\n", __func__);
 			list_add(&req->list, &port->tx_idle);
@@ -252,7 +254,7 @@
 			data_bridge_unthrottle_rx(port->brdg.ch_id);
 		}
 	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
 }
 
 static int ghsic_data_receive(void *p, void *data, size_t len)
@@ -261,21 +263,15 @@
 	unsigned long		flags;
 	struct sk_buff		*skb = data;
 
-	if (!port) {
+	if (!port || !atomic_read(&port->connected)) {
 		dev_kfree_skb_any(skb);
-		return -EINVAL;
+		return -ENOTCONN;
 	}
 
 	pr_debug("%s: p:%p#%d skb_len:%d\n", __func__,
 			port, port->port_num, skb->len);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		dev_kfree_skb_any(skb);
-		return -ENOTCONN;
-	}
-
+	spin_lock_irqsave(&port->tx_lock, flags);
 	__skb_queue_tail(&port->tx_skb_q, skb);
 
 	if (ghsic_data_fctrl_support &&
@@ -284,12 +280,12 @@
 		port->rx_throttled_cnt++;
 		pr_debug_ratelimited("%s: flow ctrl enabled: tx skbq len: %u\n",
 					__func__, port->tx_skb_q.qlen);
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		queue_work(port->wq, &port->write_tohost_w);
 		return -EBUSY;
 	}
 
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
 
 	queue_work(port->wq, &port->write_tohost_w);
 
@@ -306,14 +302,12 @@
 
 	port = container_of(w, struct gdata_port, write_tomdm_w);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+	if (!port || !atomic_read(&port->connected))
 		return;
-	}
 
+	spin_lock_irqsave(&port->rx_lock, flags);
 	if (test_bit(TX_THROTTLED, &port->brdg.flags)) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		goto start_rx;
 	}
 
@@ -323,9 +317,9 @@
 
 		info = (struct timestamp_info *)skb->cb;
 		info->rx_done_sent = get_timestamp();
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		ret = data_bridge_write(port->brdg.ch_id, skb);
-		spin_lock_irqsave(&port->port_lock, flags);
+		spin_lock_irqsave(&port->rx_lock, flags);
 		if (ret < 0) {
 			if (ret == -EBUSY) {
 				/*flow control*/
@@ -340,7 +334,7 @@
 		}
 		port->to_modem++;
 	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 start_rx:
 	ghsic_data_start_rx(port);
 }
@@ -370,9 +364,9 @@
 
 	dev_kfree_skb_any(skb);
 
-	spin_lock(&port->port_lock);
+	spin_lock(&port->tx_lock);
 	list_add_tail(&req->list, &port->tx_idle);
-	spin_unlock(&port->port_lock);
+	spin_unlock(&port->tx_lock);
 
 	queue_work(port->wq, &port->write_tohost_w);
 }
@@ -406,14 +400,14 @@
 		break;
 	}
 
-	spin_lock(&port->port_lock);
+	spin_lock(&port->rx_lock);
 	if (queue) {
 		info->rx_done = get_timestamp();
 		__skb_queue_tail(&port->rx_skb_q, skb);
 		list_add_tail(&req->list, &port->rx_idle);
 		queue_work(port->wq, &port->write_tomdm_w);
 	}
-	spin_unlock(&port->port_lock);
+	spin_unlock(&port->rx_lock);
 }
 
 static void ghsic_data_start_rx(struct gdata_port *port)
@@ -427,15 +421,17 @@
 	unsigned int		created;
 
 	pr_debug("%s: port:%p\n", __func__, port);
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+	if (!port)
+		return;
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	ep = port->out;
+	if (!ep) {
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		return;
 	}
 
-	ep = port->out;
-
-	while (port->port_usb && !list_empty(&port->rx_idle)) {
+	while (atomic_read(&port->connected) && !list_empty(&port->rx_idle)) {
 		if (port->rx_skb_q.qlen > ghsic_data_pend_limit_with_bridge)
 			break;
 
@@ -454,22 +450,22 @@
 		req->context = skb;
 
 		info->rx_queued = get_timestamp();
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		ret = usb_ep_queue(ep, req, GFP_KERNEL);
-		spin_lock_irqsave(&port->port_lock, flags);
+		spin_lock_irqsave(&port->rx_lock, flags);
 		if (ret) {
 			dev_kfree_skb_any(skb);
 
 			pr_err_ratelimited("%s: rx queue failed\n", __func__);
 
-			if (port->port_usb)
+			if (atomic_read(&port->connected))
 				list_add(&req->list, &port->rx_idle);
 			else
 				usb_ep_free_request(ep, req);
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 }
 
 static void ghsic_data_start_io(struct gdata_port *port)
@@ -480,32 +476,41 @@
 
 	pr_debug("%s: port:%p\n", __func__, port);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
+	if (!port)
+		return;
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	ep = port->out;
+	if (!ep) {
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 		return;
 	}
 
-	ep = port->out;
 	ret = ghsic_data_alloc_requests(ep, &port->rx_idle,
 		port->rx_q_size, ghsic_data_epout_complete, GFP_ATOMIC);
 	if (ret) {
 		pr_err("%s: rx req allocation failed\n", __func__);
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&port->rx_lock, flags);
+
+	spin_lock_irqsave(&port->tx_lock, flags);
+	ep = port->in;
+	if (!ep) {
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		return;
 	}
 
-	ep = port->in;
 	ret = ghsic_data_alloc_requests(ep, &port->tx_idle,
 		port->tx_q_size, ghsic_data_epin_complete, GFP_ATOMIC);
 	if (ret) {
 		pr_err("%s: tx req allocation failed\n", __func__);
 		ghsic_data_free_requests(ep, &port->rx_idle);
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 		return;
 	}
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
 
 	/* queue out requests */
 	ghsic_data_start_rx(port);
@@ -517,7 +522,8 @@
 		container_of(w, struct gdata_port, connect_w);
 	int			ret;
 
-	if (!port || !test_bit(CH_READY, &port->bridge_sts))
+	if (!port || !atomic_read(&port->connected) ||
+		!test_bit(CH_READY, &port->bridge_sts))
 		return;
 
 	pr_debug("%s: port:%p\n", __func__, port);
@@ -551,28 +557,37 @@
 	struct sk_buff	*skb;
 	unsigned long	flags;
 
-	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port)
+		return;
 
-	if (!port || !port->port_usb)
-		goto free_buf_out;
+	spin_lock_irqsave(&port->tx_lock, flags);
+	if (!port->in) {
+		spin_unlock_irqrestore(&port->tx_lock, flags);
+		return;
+	}
 
 	ghsic_data_free_requests(port->in, &port->tx_idle);
-	ghsic_data_free_requests(port->out, &port->rx_idle);
 
 	while ((skb = __skb_dequeue(&port->tx_skb_q)))
 		dev_kfree_skb_any(skb);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	if (!port->out) {
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+		return;
+	}
+
+	ghsic_data_free_requests(port->out, &port->rx_idle);
 
 	while ((skb = __skb_dequeue(&port->rx_skb_q)))
 		dev_kfree_skb_any(skb);
-
-free_buf_out:
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 }
 
 static int ghsic_data_probe(struct platform_device *pdev)
 {
 	struct gdata_port *port;
-	unsigned long flags;
 
 	pr_debug("%s: name:%s no_data_ports= %d\n",
 		__func__, pdev->name, no_data_ports);
@@ -585,11 +600,9 @@
 	port = gdata_ports[pdev->id].port;
 	set_bit(CH_READY, &port->bridge_sts);
 
-	spin_lock_irqsave(&port->port_lock, flags);
 	/* if usb is online, try opening bridge */
-	if (port->port_usb)
+	if (atomic_read(&port->connected))
 		queue_work(port->wq, &port->connect_w);
-	spin_unlock_irqrestore(&port->port_lock, flags);
 
 	return 0;
 }
@@ -598,9 +611,8 @@
 static int ghsic_data_remove(struct platform_device *pdev)
 {
 	struct gdata_port *port;
-	struct usb_ep *ep_in = NULL;
-	struct usb_ep *ep_out = NULL;
-	unsigned long flags;
+	struct usb_ep	*ep_in;
+	struct usb_ep	*ep_out;
 
 	pr_debug("%s: name:%s\n", __func__, pdev->name);
 
@@ -611,15 +623,11 @@
 
 	port = gdata_ports[pdev->id].port;
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb) {
-		ep_in = port->in;
-		ep_out = port->out;
-	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
+	ep_in = port->in;
 	if (ep_in)
 		usb_ep_fifo_flush(ep_in);
+
+	ep_out = port->out;
 	if (ep_out)
 		usb_ep_fifo_flush(ep_out);
 
@@ -663,7 +671,8 @@
 	port->port_num = port_num;
 
 	/* port initialization */
-	spin_lock_init(&port->port_lock);
+	spin_lock_init(&port->rx_lock);
+	spin_lock_init(&port->tx_lock);
 
 	INIT_WORK(&port->connect_w, ghsic_data_connect_w);
 	INIT_WORK(&port->disconnect_w, ghsic_data_disconnect_w);
@@ -724,14 +733,18 @@
 	if (port->out)
 		usb_ep_disable(port->in);
 
-	spin_lock_irqsave(&port->port_lock, flags);
-	port->port_usb = 0;
+	atomic_set(&port->connected, 0);
+
+	spin_lock_irqsave(&port->tx_lock, flags);
 	port->in = NULL;
-	port->out = NULL;
 	port->n_tx_req_queued = 0;
-	clear_bit(TX_THROTTLED, &port->brdg.flags);
 	clear_bit(RX_THROTTLED, &port->brdg.flags);
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->tx_lock, flags);
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	port->out = NULL;
+	clear_bit(TX_THROTTLED, &port->brdg.flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 
 	queue_work(port->wq, &port->disconnect_w);
 }
@@ -762,8 +775,15 @@
 
 	if (port->gtype == USB_GADGET_SERIAL) {
 		gser = gptr;
+
+		spin_lock_irqsave(&port->tx_lock, flags);
 		port->in = gser->in;
+		spin_unlock_irqrestore(&port->tx_lock, flags);
+
+		spin_lock_irqsave(&port->rx_lock, flags);
 		port->out = gser->out;
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+
 		port->tx_q_size = ghsic_data_serial_tx_q_size;
 		port->rx_q_size = ghsic_data_serial_rx_q_size;
 		gser->in->driver_data = port;
@@ -772,8 +792,15 @@
 		out_desc = gser->out_desc;
 	} else {
 		gr = gptr;
+
+		spin_lock_irqsave(&port->tx_lock, flags);
 		port->in = gr->in;
+		spin_unlock_irqrestore(&port->tx_lock, flags);
+
+		spin_lock_irqsave(&port->rx_lock, flags);
 		port->out = gr->out;
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+
 		port->tx_q_size = ghsic_data_rmnet_tx_q_size;
 		port->rx_q_size = ghsic_data_rmnet_rx_q_size;
 		gr->in->driver_data = port;
@@ -796,17 +823,22 @@
 		usb_ep_disable(port->in);
 		goto fail;
 	}
-	spin_lock_irqsave(&port->port_lock, flags);
-	port->port_usb = gptr;
+
+	atomic_set(&port->connected, 1);
+
+	spin_lock_irqsave(&port->tx_lock, flags);
 	port->to_host = 0;
-	port->to_modem = 0;
-	port->tomodem_drp_cnt = 0;
 	port->rx_throttled_cnt = 0;
 	port->rx_unthrottled_cnt = 0;
+	port->unthrottled_pnd_skbs = 0;
+	spin_unlock_irqrestore(&port->tx_lock, flags);
+
+	spin_lock_irqsave(&port->rx_lock, flags);
+	port->to_modem = 0;
+	port->tomodem_drp_cnt = 0;
 	port->tx_throttled_cnt = 0;
 	port->tx_unthrottled_cnt = 0;
-	port->unthrottled_pnd_skbs = 0;
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irqrestore(&port->rx_lock, flags);
 
 	queue_work(port->wq, &port->connect_w);
 fail:
@@ -932,42 +964,49 @@
 		if (!port)
 			continue;
 		pdrv = &gdata_ports[i].pdrv;
-		spin_lock_irqsave(&port->port_lock, flags);
 
+		spin_lock_irqsave(&port->rx_lock, flags);
 		temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
 				"\nName:           %s\n"
 				"#PORT:%d port#:   %p\n"
-				"dpkts_to_usbhost: %lu\n"
+				"data_ch_open:	   %d\n"
+				"data_ch_ready:    %d\n"
+				"\n******UL INFO*****\n\n"
 				"dpkts_to_modem:   %lu\n"
 				"tomodem_drp_cnt:  %u\n"
-				"tx_buf_len:       %u\n"
 				"rx_buf_len:       %u\n"
-				"rx thld cnt       %u\n"
-				"rx unthld cnt     %u\n"
 				"tx thld cnt       %u\n"
 				"tx unthld cnt     %u\n"
-				"uthld pnd skbs    %u\n"
-				"RX_THROTTLED      %d\n"
-				"TX_THROTTLED      %d\n"
-				"data_ch_open:     %d\n"
-				"data_ch_ready:    %d\n",
+				"TX_THROTTLED      %d\n",
 				pdrv->driver.name,
 				i, port,
-				port->to_host, port->to_modem,
+				test_bit(CH_OPENED, &port->bridge_sts),
+				test_bit(CH_READY, &port->bridge_sts),
+				port->to_modem,
 				port->tomodem_drp_cnt,
-				port->tx_skb_q.qlen,
 				port->rx_skb_q.qlen,
-				port->rx_throttled_cnt,
-				port->rx_unthrottled_cnt,
 				port->tx_throttled_cnt,
 				port->tx_unthrottled_cnt,
-				port->unthrottled_pnd_skbs,
-				test_bit(RX_THROTTLED, &port->brdg.flags),
-				test_bit(TX_THROTTLED, &port->brdg.flags),
-				test_bit(CH_OPENED, &port->bridge_sts),
-				test_bit(CH_READY, &port->bridge_sts));
+				test_bit(TX_THROTTLED, &port->brdg.flags));
+		spin_unlock_irqrestore(&port->rx_lock, flags);
 
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_lock_irqsave(&port->tx_lock, flags);
+		temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+				"\n******DL INFO******\n\n"
+				"dpkts_to_usbhost: %lu\n"
+				"tx_buf_len:	   %u\n"
+				"rx thld cnt	   %u\n"
+				"rx unthld cnt	   %u\n"
+				"uthld pnd skbs    %u\n"
+				"RX_THROTTLED	   %d\n",
+				port->to_host,
+				port->tx_skb_q.qlen,
+				port->rx_throttled_cnt,
+				port->rx_unthrottled_cnt,
+				port->unthrottled_pnd_skbs,
+				test_bit(RX_THROTTLED, &port->brdg.flags));
+		spin_unlock_irqrestore(&port->tx_lock, flags);
+
 	}
 
 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
@@ -989,16 +1028,19 @@
 		if (!port)
 			continue;
 
-		spin_lock_irqsave(&port->port_lock, flags);
-		port->to_host = 0;
+		spin_lock_irqsave(&port->rx_lock, flags);
 		port->to_modem = 0;
 		port->tomodem_drp_cnt = 0;
-		port->rx_throttled_cnt = 0;
-		port->rx_unthrottled_cnt = 0;
 		port->tx_throttled_cnt = 0;
 		port->tx_unthrottled_cnt = 0;
+		spin_unlock_irqrestore(&port->rx_lock, flags);
+
+		spin_lock_irqsave(&port->tx_lock, flags);
+		port->to_host = 0;
+		port->rx_throttled_cnt = 0;
+		port->rx_unthrottled_cnt = 0;
 		port->unthrottled_pnd_skbs = 0;
-		spin_unlock_irqrestore(&port->port_lock, flags);
+		spin_unlock_irqrestore(&port->tx_lock, flags);
 	}
 	return count;
 }
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index af7f2cf..d64f223 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -72,6 +72,8 @@
 #define USB_PHY_VDD_DIG_VOL_MAX		1320000 /* uV */
 #define USB_PHY_VDD_DIG_LOAD		49360	/* uA */
 
+#define HSIC_DBG1_REG		0x38
+
 static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
 {
 	int ret = 0;
@@ -160,7 +162,7 @@
 	static struct regulator *hsic_hub_reg;
 
 	pdata = mehci->dev->platform_data;
-	if (!pdata->hub_reset)
+	if (!pdata || !pdata->hub_reset)
 		return ret;
 
 	if (!init)
@@ -233,7 +235,7 @@
 
 	pdata = mehci->dev->platform_data;
 
-	if (!pdata->strobe || !pdata->data)
+	if (!pdata || !pdata->strobe || !pdata->data)
 		return rc;
 
 	if (gpio_status == gpio_en)
@@ -270,16 +272,16 @@
 {
 	int ret;
 
-	clk_enable(mehci->alt_core_clk);
+	clk_prepare_enable(mehci->alt_core_clk);
 
 	ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
 	if (ret) {
-		clk_disable(mehci->alt_core_clk);
+		clk_disable_unprepare(mehci->alt_core_clk);
 		dev_err(mehci->dev, "usb phy clk assert failed\n");
 		return ret;
 	}
 	usleep_range(10000, 12000);
-	clk_disable(mehci->alt_core_clk);
+	clk_disable_unprepare(mehci->alt_core_clk);
 
 	ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
 	if (ret)
@@ -320,6 +322,7 @@
 	struct usb_hcd *hcd = hsic_to_hcd(mehci);
 	int cnt = 0;
 	int ret;
+	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
 
 	ret = msm_hsic_phy_reset(mehci);
 	if (ret) {
@@ -337,36 +340,59 @@
 	if (cnt >= LINK_RESET_TIMEOUT_USEC)
 		return -ETIMEDOUT;
 
-	/* select ULPI phy */
+	/* Reset PORTSC and select ULPI phy */
 	writel_relaxed(0x80000000, USB_PORTSC);
 
 	/* TODO: Need to confirm if HSIC PHY also requires delay after RESET */
 	msleep(100);
 
 	/* HSIC PHY Initialization */
-	/* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
-	writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
 
-	/*set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
-	ulpi_write(mehci, 0xFF, 0x33);
+	/* HSIC init sequence when HSIC signals (Strobe/Data) are
+	routed via GPIOs */
+	if (pdata && pdata->strobe && pdata->data) {
 
-	/* Enable periodic IO calibration in HSIC_CFG register */
-	ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
+		/* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
+		writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);
 
-	/* Configure GPIO 150/151 pins for HSIC functionality mode */
-	ret = msm_hsic_config_gpios(mehci, 1);
-	if (ret) {
-		dev_err(mehci->dev, " gpio configuarion failed\n");
-		return ret;
+		/*set periodic calibration interval to ~2.048sec in
+		  HSIC_IO_CAL_REG */
+		ulpi_write(mehci, 0xFF, 0x33);
+
+		/* Enable periodic IO calibration in HSIC_CFG register */
+		ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);
+
+		/* Configure GPIO 150/151 pins for HSIC functionality mode */
+		ret = msm_hsic_config_gpios(mehci, 1);
+		if (ret) {
+			dev_err(mehci->dev, " gpio configuarion failed\n");
+			return ret;
+		}
+		/* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL
+		   register */
+		writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
+		writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
+		/* Enable HSIC mode in HSIC_CFG register */
+		ulpi_write(mehci, 0x01, 0x31);
+	} else {
+		/* HSIC init sequence when HSIC signals (Strobe/Data) are routed
+		via dedicated I/O */
+
+		/* programmable length of connect signaling (33.2ns) */
+		ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
+		if (ret) {
+			pr_err("%s: Unable to program length of connect "
+			      "signaling\n", __func__);
+		}
+
+		/*set periodic calibration interval to ~2.048sec in
+		  HSIC_IO_CAL_REG */
+		ulpi_write(mehci, 0xFF, 0x33);
+
+		/* Enable HSIC mode in HSIC_CFG register */
+		ulpi_write(mehci, 0xA9, 0x30);
 	}
 
-	/* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO150/151_PAD_CTL register */
-	writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO150_PAD_CTL);
-	writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_GPIO151_PAD_CTL);
-
-	/* Enable HSIC mode in HSIC_CFG register */
-	ulpi_write(mehci, 0x01, 0x31);
-
 	return 0;
 }
 
@@ -423,12 +449,12 @@
 	 */
 	mb();
 
-	clk_disable(mehci->core_clk);
-	clk_disable(mehci->phy_clk);
-	clk_disable(mehci->cal_clk);
-	clk_disable(mehci->ahb_clk);
+	clk_disable_unprepare(mehci->core_clk);
+	clk_disable_unprepare(mehci->phy_clk);
+	clk_disable_unprepare(mehci->cal_clk);
+	clk_disable_unprepare(mehci->ahb_clk);
 	pdata = mehci->dev->platform_data;
-	if (pdata->hub_reset) {
+	if (pdata && pdata->hub_reset) {
 		ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_OFF);
 		if (ret)
 			pr_err("%s failed to devote for"
@@ -471,16 +497,16 @@
 		dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
 
 	pdata = mehci->dev->platform_data;
-	if (pdata->hub_reset) {
+	if (pdata && pdata->hub_reset) {
 		ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
 		if (ret)
 			pr_err("%s failed to vote for"
 				"TCXO D1 buffer%d\n", __func__, ret);
 	}
-	clk_enable(mehci->core_clk);
-	clk_enable(mehci->phy_clk);
-	clk_enable(mehci->cal_clk);
-	clk_enable(mehci->ahb_clk);
+	clk_prepare_enable(mehci->core_clk);
+	clk_prepare_enable(mehci->phy_clk);
+	clk_prepare_enable(mehci->cal_clk);
+	clk_prepare_enable(mehci->ahb_clk);
 
 	temp = readl_relaxed(USB_USBCMD);
 	temp &= ~ASYNC_INTR_CTRL;
@@ -634,32 +660,32 @@
 	if (!init)
 		goto put_clocks;
 
-	/*core_clk is required for LINK protocol engine,it should be at 60MHz */
+	/*core_clk is required for LINK protocol engine
+	 *clock rate appropriately set by target specific clock driver */
 	mehci->core_clk = clk_get(mehci->dev, "core_clk");
 	if (IS_ERR(mehci->core_clk)) {
 		dev_err(mehci->dev, "failed to get core_clk\n");
 		ret = PTR_ERR(mehci->core_clk);
 		return ret;
 	}
-	clk_set_rate(mehci->core_clk, 60000000);
 
-	/* 60MHz alt_core_clk is for LINK to be used during PHY RESET  */
+	/* alt_core_clk is for LINK to be used during PHY RESET
+	 * clock rate appropriately set by target specific clock driver */
 	mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
 	if (IS_ERR(mehci->alt_core_clk)) {
 		dev_err(mehci->dev, "failed to core_clk\n");
 		ret = PTR_ERR(mehci->alt_core_clk);
 		goto put_core_clk;
 	}
-	clk_set_rate(mehci->alt_core_clk, 60000000);
 
-	/* 480MHz phy_clk is required for HSIC PHY operation */
+	/* phy_clk is required for HSIC PHY operation
+	 * clock rate appropriately set by target specific clock driver */
 	mehci->phy_clk = clk_get(mehci->dev, "phy_clk");
 	if (IS_ERR(mehci->phy_clk)) {
 		dev_err(mehci->dev, "failed to get phy_clk\n");
 		ret = PTR_ERR(mehci->phy_clk);
 		goto put_alt_core_clk;
 	}
-	clk_set_rate(mehci->phy_clk, 480000000);
 
 	/* 10MHz cal_clk is required for calibration of I/O pads */
 	mehci->cal_clk = clk_get(mehci->dev, "cal_clk");
@@ -678,18 +704,18 @@
 		goto put_cal_clk;
 	}
 
-	clk_enable(mehci->core_clk);
-	clk_enable(mehci->phy_clk);
-	clk_enable(mehci->cal_clk);
-	clk_enable(mehci->ahb_clk);
+	clk_prepare_enable(mehci->core_clk);
+	clk_prepare_enable(mehci->phy_clk);
+	clk_prepare_enable(mehci->cal_clk);
+	clk_prepare_enable(mehci->ahb_clk);
 
 	return 0;
 
 put_clocks:
-	clk_disable(mehci->core_clk);
-	clk_disable(mehci->phy_clk);
-	clk_disable(mehci->cal_clk);
-	clk_disable(mehci->ahb_clk);
+	clk_disable_unprepare(mehci->core_clk);
+	clk_disable_unprepare(mehci->phy_clk);
+	clk_disable_unprepare(mehci->cal_clk);
+	clk_disable_unprepare(mehci->ahb_clk);
 	clk_put(mehci->ahb_clk);
 put_cal_clk:
 	clk_put(mehci->cal_clk);
@@ -778,7 +804,7 @@
 	}
 
 	pdata = mehci->dev->platform_data;
-	if (pdata->hub_reset) {
+	if (pdata && pdata->hub_reset) {
 		mehci->xo_handle = msm_xo_get(MSM_XO_TCXO_D1, "hsic");
 		if (IS_ERR(mehci->xo_handle)) {
 			pr_err(" %s not able to get the handle"
@@ -843,7 +869,7 @@
 deinit_hub:
 	msm_hsic_config_hub(mehci, 0);
 free_xo_handle:
-	if (pdata->hub_reset)
+	if (pdata && pdata->hub_reset)
 		msm_xo_put(mehci->xo_handle);
 deinit_vddcx:
 	msm_hsic_init_vddcx(mehci, 0);
@@ -874,7 +900,7 @@
 	msm_hsic_config_gpios(mehci, 0);
 	msm_hsic_config_hub(mehci, 0);
 	pdata = mehci->dev->platform_data;
-	if (pdata->hub_reset)
+	if (pdata && pdata->hub_reset)
 		msm_xo_put(mehci->xo_handle);
 	msm_hsic_init_vddcx(mehci, 0);
 
diff --git a/drivers/usb/host/ehci-msm72k.c b/drivers/usb/host/ehci-msm72k.c
index 87c75e7..b3939ef 100644
--- a/drivers/usb/host/ehci-msm72k.c
+++ b/drivers/usb/host/ehci-msm72k.c
@@ -79,9 +79,9 @@
 		return;
 
 	if (vote)
-		clk_enable(pdata->ebi1_clk);
+		clk_prepare_enable(pdata->ebi1_clk);
 	else
-		clk_disable(pdata->ebi1_clk);
+		clk_disable_unprepare(pdata->ebi1_clk);
 }
 
 static void msm_xusb_enable_clks(struct msmusb_hcd *mhcd)
@@ -96,8 +96,8 @@
 		/* OTG driver takes care of clock management */
 		break;
 	case USB_PHY_SERIAL_PMIC:
-		clk_enable(mhcd->alt_core_clk);
-		clk_enable(mhcd->iface_clk);
+		clk_prepare_enable(mhcd->alt_core_clk);
+		clk_prepare_enable(mhcd->iface_clk);
 		break;
 	default:
 		pr_err("%s: undefined phy type ( %X )\n", __func__,
@@ -119,8 +119,8 @@
 		/* OTG driver takes care of clock management */
 		break;
 	case USB_PHY_SERIAL_PMIC:
-		clk_disable(mhcd->alt_core_clk);
-		clk_disable(mhcd->iface_clk);
+		clk_disable_unprepare(mhcd->alt_core_clk);
+		clk_disable_unprepare(mhcd->iface_clk);
 		break;
 	default:
 		pr_err("%s: undefined phy type ( %X )\n", __func__,
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
index 59d9769..0ee1827 100644
--- a/drivers/usb/otg/msm72k_otg.c
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -562,9 +562,9 @@
 
 	if (on)
 		/* enable clocks */
-		clk_enable(dev->alt_core_clk);
+		clk_prepare_enable(dev->alt_core_clk);
 	else
-		clk_disable(dev->alt_core_clk);
+		clk_disable_unprepare(dev->alt_core_clk);
 
 	return 0;
 }
@@ -589,7 +589,7 @@
 		 * low power mode routine
 		 */
 		if (dev->pdata->pclk_required_during_lpm)
-			clk_enable(dev->iface_clk);
+			clk_prepare_enable(dev->iface_clk);
 
 		usb_gadget_vbus_connect(xceiv->gadget);
 	} else {
@@ -601,7 +601,7 @@
 		 * low power mode routine
 		 */
 		if (dev->pdata->pclk_required_during_lpm)
-			clk_disable(dev->iface_clk);
+			clk_disable_unprepare(dev->iface_clk);
 
 		otg_pm_qos_update_latency(dev, 0);
 		if (pdata->setup_gpio)
@@ -628,9 +628,9 @@
 		 */
 		if (dev->pdata->pclk_required_during_lpm) {
 			if (on)
-				clk_enable(dev->iface_clk);
+				clk_prepare_enable(dev->iface_clk);
 			else
-				clk_disable(dev->iface_clk);
+				clk_disable_unprepare(dev->iface_clk);
 		}
 
 		dev->start_host(xceiv->host, on);
@@ -759,9 +759,9 @@
 	mb();
 
 	if (dev->iface_clk)
-		clk_disable(dev->iface_clk);
+		clk_disable_unprepare(dev->iface_clk);
 
-	clk_disable(dev->core_clk);
+	clk_disable_unprepare(dev->core_clk);
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable*/
 	ret = msm_xo_mode_vote(dev->xo_handle, MSM_XO_MODE_OFF);
 	if (ret)
@@ -835,10 +835,10 @@
 		pr_err("%s failed to vote for"
 			"TCXO D1 buffer%d\n", __func__, ret);
 
-	clk_enable(dev->core_clk);
+	clk_prepare_enable(dev->core_clk);
 
 	if (dev->iface_clk)
-		clk_enable(dev->iface_clk);
+		clk_prepare_enable(dev->iface_clk);
 
 	temp = readl(USB_USBCMD);
 	temp &= ~ASYNC_INTR_CTRL;
@@ -1550,7 +1550,7 @@
 	unsigned long timeout;
 	u32 mode, work = 0;
 
-	clk_enable(dev->alt_core_clk);
+	clk_prepare_enable(dev->alt_core_clk);
 
 	if (!phy_reset)
 		goto reset_link;
@@ -1596,7 +1596,7 @@
 	/* Ensure that RESET operation is completed before turning off clock */
 	mb();
 
-	clk_disable(dev->alt_core_clk);
+	clk_disable_unprepare(dev->alt_core_clk);
 
 	if ((xceiv->gadget && xceiv->gadget->is_a_peripheral) ||
 			test_bit(ID, &dev->inputs))
@@ -2646,7 +2646,7 @@
 	 */
 	clk_set_rate(dev->core_clk, INT_MAX);
 
-	clk_enable(dev->core_clk);
+	clk_prepare_enable(dev->core_clk);
 
 	if (!dev->pdata->pclk_is_hw_gated) {
 		dev->iface_clk = clk_get(&pdev->dev, "iface_clk");
@@ -2655,7 +2655,7 @@
 			ret = PTR_ERR(dev->iface_clk);
 			goto put_core_clk;
 		}
-		clk_enable(dev->iface_clk);
+		clk_prepare_enable(dev->iface_clk);
 	}
 
 	if (!dev->pdata->phy_reset) {
@@ -2888,11 +2888,11 @@
 		clk_put(dev->phy_reset_clk);
 put_iface_clk:
 	if (dev->iface_clk) {
-		clk_disable(dev->iface_clk);
+		clk_disable_unprepare(dev->iface_clk);
 		clk_put(dev->iface_clk);
 	}
 put_core_clk:
-	clk_disable(dev->core_clk);
+	clk_disable_unprepare(dev->core_clk);
 	clk_put(dev->core_clk);
 put_alt_core_clk:
 	clk_put(dev->alt_core_clk);
@@ -2942,10 +2942,10 @@
 		dev->pdata->chg_init(0);
 	free_irq(dev->irq, pdev);
 	iounmap(dev->regs);
-	clk_disable(dev->core_clk);
+	clk_disable_unprepare(dev->core_clk);
 	clk_put(dev->core_clk);
 	if (dev->iface_clk) {
-		clk_disable(dev->iface_clk);
+		clk_disable_unprepare(dev->iface_clk);
 		clk_put(dev->iface_clk);
 	}
 	if (dev->alt_core_clk)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 4e1895f..6964835 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -538,7 +538,7 @@
 			motg->reset_counter++;
 	}
 
-	clk_enable(motg->clk);
+	clk_prepare_enable(motg->clk);
 	ret = msm_otg_phy_reset(motg);
 	if (ret) {
 		dev_err(otg->dev, "phy_reset failed\n");
@@ -558,7 +558,7 @@
 	/* Ensure that RESET operation is completed before turning off clock */
 	mb();
 
-	clk_disable(motg->clk);
+	clk_disable_unprepare(motg->clk);
 
 	if (pdata->otg_control == OTG_PHY_CONTROL) {
 		val = readl_relaxed(USB_OTGSC);
@@ -711,8 +711,8 @@
 
 	/* Ensure that above operation is completed before turning off clocks */
 	mb();
-	clk_disable(motg->pclk);
-	clk_disable(motg->core_clk);
+	clk_disable_unprepare(motg->pclk);
+	clk_disable_unprepare(motg->core_clk);
 
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
 	clk_disable_unprepare(motg->xo_handle);
@@ -765,9 +765,9 @@
 		dev_err(otg->dev, "%s failed to vote for "
 			"TCXO D0 buffer%d\n", __func__, ret);
 
-	clk_enable(motg->core_clk);
+	clk_prepare_enable(motg->core_clk);
 
-	clk_enable(motg->pclk);
+	clk_prepare_enable(motg->pclk);
 
 	if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
 		msm_hsusb_ldo_enable(motg, 1);
@@ -2529,7 +2529,7 @@
 		goto free_xo_handle;
 	}
 
-	clk_enable(motg->pclk);
+	clk_prepare_enable(motg->pclk);
 
 	ret = msm_hsusb_init_vddcx(motg, 1);
 	if (ret) {
@@ -2554,7 +2554,7 @@
 		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
 		goto free_ldo_init;
 	}
-	clk_enable(motg->core_clk);
+	clk_prepare_enable(motg->core_clk);
 
 	writel(0, USB_USBINTR);
 	writel(0, USB_OTGSC);
@@ -2652,14 +2652,14 @@
 	free_irq(motg->irq, motg);
 destroy_wlock:
 	wake_lock_destroy(&motg->wlock);
-	clk_disable(motg->core_clk);
+	clk_disable_unprepare(motg->core_clk);
 	msm_hsusb_ldo_enable(motg, 0);
 free_ldo_init:
 	msm_hsusb_ldo_init(motg, 0);
 free_init_vddcx:
 	msm_hsusb_init_vddcx(motg, 0);
 devote_xo_handle:
-	clk_disable(motg->pclk);
+	clk_disable_unprepare(motg->pclk);
 	clk_disable_unprepare(motg->xo_handle);
 free_xo_handle:
 	clk_put(motg->xo_handle);
@@ -2726,8 +2726,8 @@
 	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
 		dev_err(otg->dev, "Unable to suspend PHY\n");
 
-	clk_disable(motg->pclk);
-	clk_disable(motg->core_clk);
+	clk_disable_unprepare(motg->pclk);
+	clk_disable_unprepare(motg->core_clk);
 	clk_put(motg->xo_handle);
 	msm_hsusb_ldo_enable(motg, 0);
 	msm_hsusb_ldo_init(motg, 0);
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index d3f8b2b..0110df9 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -270,6 +270,11 @@
 	select FB_MSM_MIPI_DSI_TOSHIBA
 	default n
 
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+	bool
+	select FB_MSM_MIPI_DSI_TOSHIBA
+	default n
+
 config FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
 	bool
 	select FB_MSM_MIPI_DSI_NOVATEK
@@ -446,6 +451,7 @@
 	bool "MIPI Panel Detect"
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
 	select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
 	select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
 	select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
@@ -497,9 +503,20 @@
 
 config FB_MSM_LVDS_MIPI_PANEL_DETECT
 	bool "LVDS + MIPI Panel Auto Detect"
-	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
 	select FB_MSM_LVDS_CHIMEI_WXGA
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+	select FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT
+	select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
+	select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
+	select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+	select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+	select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+	select FB_MSM_MIPI_SIMULATOR_VIDEO
 	select FB_MSM_MIPI_CHIMEI_WXGA
+	select FB_MSM_MIPI_CHIMEI_WUXGA
 	---help---
 	  Support for LVDS + MIPI panel auto detect
 
@@ -541,6 +558,10 @@
 	bool "MIPI Toshiba WSVGA PT Panel"
 	select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
 
+config FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA_PANEL
+	bool "MIPI Toshiba WUXGA (1920x1200) Panel"
+	select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
+
 config FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT_PANEL
 	bool "MIPI NOVATEK VIDEO QHD PT Panel"
 	select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index bd7628d..2bdab74 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -114,7 +114,7 @@
 endif
 
 ifeq ($(CONFIG_FB_MSM_MIPI_PANEL_DETECT),y)
-obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o
+obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o mipi_toshiba_video_wuxga.o
 obj-y += mipi_novatek_video_qhd_pt.o mipi_novatek_cmd_qhd_pt.o
 obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
 obj-y += mipi_NT35510_video_wvga_pt.o mipi_NT35510_cmd_wvga_pt.o
@@ -124,6 +124,7 @@
 else
 obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT) += mipi_toshiba_video_wvga_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT) += mipi_toshiba_video_wsvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA) += mipi_toshiba_video_wuxga.o
 obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT) += mipi_novatek_video_qhd_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT) += mipi_novatek_cmd_qhd_pt.o
 obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 07a075c..0a86a50 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -480,16 +480,19 @@
 static ssize_t hdmi_msm_wta_cec_frame(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
+	int i;
 	int retry = ((struct hdmi_msm_cec_msg *) buf)->retransmit;
 
-	if (retry > 15)
-		retry = 15;
-	while (1) {
+	for (i = 0; i < RETRANSMIT_MAX_NUM; i++) {
 		hdmi_msm_cec_msg_send((struct hdmi_msm_cec_msg *) buf);
 		if (hdmi_msm_state->cec_frame_wr_status
-		    & CEC_STATUS_WR_ERROR && retry--)
+		    & CEC_STATUS_WR_ERROR && retry--) {
+			mutex_lock(&hdmi_msm_state_mutex);
+			if (hdmi_msm_state->fsm_reset_done)
+				retry++;
+			mutex_unlock(&hdmi_msm_state_mutex);
 			msleep(360);
-		else
+		} else
 			break;
 	}
 
@@ -911,8 +914,13 @@
 	uint32 offset = 4;
 
 	*len = 0;
-	if ((in_buf[2] == 4) && (type != 2)) { /* no non-DTD data present */
-		DEV_WARN("EDID: no non-DTD data present\n");
+
+	/*edid buffer 1, byte 2 being 4 means no non-DTD/Data block collection
+	  present.
+	  edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block collection
+	  present and no DTD data present.*/
+	if ((in_buf[2] == 0) || (in_buf[2] == 4)) {
+		DEV_WARN("EDID: no DTD or non-DTD data present\n");
 		return NULL;
 	}
 	while (offset < 0x80) {
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 93e6d40..a0665ac 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -79,6 +79,8 @@
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 
+static void hdmi_msm_cec_line_latch_detect(void);
+
 #ifdef TOGGLE_CEC_HARDWARE_FSM
 static boolean msg_send_complete = TRUE;
 static boolean msg_recv_complete = TRUE;
@@ -111,7 +113,7 @@
 #define HDMI_MSM_CEC_INT_FRAME_WR_DONE_ACK		BIT(0)
 #define HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT		BIT(0)
 
-#define HDMI_MSM_CEC_FRAME_WR_SUCCESS(___st)         (((___st)&0xF) ==\
+#define HDMI_MSM_CEC_FRAME_WR_SUCCESS(___st)         (((___st)&0xB) ==\
 		(HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT |\
 			HDMI_MSM_CEC_INT_FRAME_WR_DONE_MASK |\
 			HDMI_MSM_CEC_INT_FRAME_ERROR_MASK))
@@ -142,8 +144,8 @@
 	 */
 	HDMI_OUTP(0x02A0, HDMI_MSM_CEC_ADDR_LOGICAL_ADDR(4));
 
-	/* 0x028C CEC_CTRL */
-	HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+	hdmi_msm_state->first_monitor = 0;
+	hdmi_msm_state->fsm_reset_done = false;
 
 	/* 0x029C CEC_INT */
 	/* Enable CEC interrupts */
@@ -161,7 +163,11 @@
 	 * BIT_1_ERR_RANGE_HI = 8 => 750us, the test used 775us,
 	 * so increased this to 9 which => 800us.
 	 */
-	HDMI_OUTP(0x02E0, 0x889788);
+	/*
+	 * CEC latch up issue - To fire monitor interrupt
+	 * for every start of message
+	 */
+	HDMI_OUTP(0x02E0, 0x880000);
 
 	/*
 	 * Slight adjustment to logic 0 low period on write
@@ -173,6 +179,8 @@
 	 */
 	HDMI_OUTP(0x02A4, 0x1 | (7 * 0x30) << 7);
 
+	/* 0x028C CEC_CTRL */
+	HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
 }
 
 void hdmi_msm_cec_write_logical_addr(int addr)
@@ -207,6 +215,9 @@
 
 	boolean frameType = (msg->recvr_id == 15 ? BIT(0) : 0);
 
+	mutex_lock(&hdmi_msm_state_mutex);
+	hdmi_msm_state->fsm_reset_done = false;
+	mutex_unlock(&hdmi_msm_state_mutex);
 #ifdef TOGGLE_CEC_HARDWARE_FSM
 	msg_send_complete = FALSE;
 #endif
@@ -278,9 +289,34 @@
 		msg_recv_complete = TRUE;
 	}
 	msg_send_complete = TRUE;
+#else
+	HDMI_OUTP(0x028C, 0x0);
+	HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
 #endif
 }
 
+void hdmi_msm_cec_line_latch_detect(void)
+{
+	/*
+	 * CECT 9-5-1
+	 * The timer period needs to be changed to appropriate value
+	 */
+	/*
+	 * Timedout without RD_DONE, WR_DONE or ERR_INT
+	 * Toggle CEC hardware FSM
+	 */
+	mutex_lock(&hdmi_msm_state_mutex);
+	if (hdmi_msm_state->first_monitor == 1) {
+		DEV_WARN("CEC line is probably latched up - CECT 9-5-1");
+		if (!msg_recv_complete)
+			hdmi_msm_state->fsm_reset_done = true;
+		HDMI_OUTP(0x028C, 0x0);
+		HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+		hdmi_msm_state->first_monitor = 0;
+	}
+	mutex_unlock(&hdmi_msm_state_mutex);
+}
+
 void hdmi_msm_cec_msg_recv(void)
 {
 	uint32 data;
@@ -476,6 +512,14 @@
 		temp_msg.frame_size = i + 2;
 		hdmi_msm_cec_msg_send(&temp_msg);
 		break;
+	case 0x44:
+		/* User Control Pressed */
+		DEV_INFO("User Control Pressed\n");
+		break;
+	case 0x45:
+		/* User Control Released */
+		DEV_INFO("User Control Released\n");
+		break;
 	default:
 		DEV_INFO("Recvd an unknown cmd = [%u]\n",
 			hdmi_msm_state->cec_queue_wr->opcode);
@@ -837,6 +881,13 @@
 	HDMI_OUTP(0x0254, 4 | (hpd_state ? 0 : 2));
 }
 
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_latch_work(struct work_struct *work)
+{
+	hdmi_msm_cec_line_latch_detect();
+}
+#endif
+
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 static void hdcp_deauthenticate(void);
 static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
@@ -1099,6 +1150,8 @@
 			HDMI_MSM_CEC_INT_FRAME_WR_DONE_ACK);
 		mutex_lock(&hdmi_msm_state_mutex);
 		hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_DONE;
+		hdmi_msm_state->first_monitor = 0;
+		del_timer(&hdmi_msm_state->cec_read_timer);
 		mutex_unlock(&hdmi_msm_state_mutex);
 		complete(&hdmi_msm_state->cec_frame_wr_done);
 		return IRQ_HANDLED;
@@ -1112,17 +1165,50 @@
 #endif
 		HDMI_OUTP(0x029C, cec_intr_status);
 		mutex_lock(&hdmi_msm_state_mutex);
+		hdmi_msm_state->first_monitor = 0;
+		del_timer(&hdmi_msm_state->cec_read_timer);
 		hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_ERROR;
 		mutex_unlock(&hdmi_msm_state_mutex);
 		complete(&hdmi_msm_state->cec_frame_wr_done);
 		return IRQ_HANDLED;
 	}
 
-	if ((cec_intr_status & (1 << 4)) && (cec_intr_status & (1 << 5)))
+	if ((cec_intr_status & (1 << 4)) && (cec_intr_status & (1 << 5))) {
 		DEV_DBG("CEC_IRQ_MONITOR\n");
+		HDMI_OUTP(0x029C, cec_intr_status |
+			  HDMI_MSM_CEC_INT_MONITOR_ACK);
+
+		/*
+		 * CECT 9-5-1
+		 * On the first occassion start a timer
+		 * for few hundred ms, if it expires then
+		 * reset the CEC block else go on with
+		 * frame transactions as usual.
+		 * Below adds hdmi_msm_cec_msg_recv() as an
+		 * item into the work queue instead of running in
+		 * interrupt context
+		 */
+		mutex_lock(&hdmi_msm_state_mutex);
+		if (hdmi_msm_state->first_monitor == 0) {
+			/* This timer might have to be changed
+			 * worst case theoritical =
+			 * 16 bytes * 8 * 2.7msec = 346 msec
+			 */
+			mod_timer(&hdmi_msm_state->cec_read_timer,
+					jiffies + HZ/2);
+			hdmi_msm_state->first_monitor = 1;
+		}
+		mutex_unlock(&hdmi_msm_state_mutex);
+		return IRQ_HANDLED;
+	}
 
 	if ((cec_intr_status & (1 << 6)) && (cec_intr_status & (1 << 7))) {
 		DEV_DBG("CEC_IRQ_FRAME_RD_DONE\n");
+
+		mutex_lock(&hdmi_msm_state_mutex);
+		hdmi_msm_state->first_monitor = 0;
+		del_timer(&hdmi_msm_state->cec_read_timer);
+		mutex_unlock(&hdmi_msm_state_mutex);
 		HDMI_OUTP(0x029C, cec_intr_status |
 			HDMI_MSM_CEC_INT_FRAME_RD_DONE_ACK);
 		hdmi_msm_cec_msg_recv();
@@ -1135,6 +1221,9 @@
 			HDMI_OUTP(0x028C, 0x0);
 			HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
 		}
+#else
+		HDMI_OUTP(0x028C, 0x0);
+		HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
 #endif
 
 		return IRQ_HANDLED;
@@ -2371,6 +2460,8 @@
 		[8] AN_0_READY
 		[9] AN_1_READY */
 		/* wait for an0 and an1 ready bits to be set in LINK0_STATUS */
+
+		mutex_lock(&hdcp_auth_state_mutex);
 		timeout_count = 100;
 		while (((HDMI_INP_ND(0x011C) & (0x3 << 8)) != (0x3 << 8))
 			&& timeout_count--)
@@ -2404,6 +2495,7 @@
 		   [31:0] LINK0_AN_1 */
 		/* read an1 calculation */
 		link0_an_1 = HDMI_INP(0x0150);
+		mutex_unlock(&hdcp_auth_state_mutex);
 
 		/* three bits 28..30 */
 		hdcp_key_state((HDMI_INP(0x011C) >> 28) & 0x7);
@@ -3867,7 +3959,11 @@
 			"AUDIO CFG is %08x", i, audio_pkt_ctrl, audio_cfg);
 		msleep(20);
 	}
+
+	mutex_lock(&hdcp_auth_state_mutex);
 	hdmi_msm_reset_core();
+	mutex_unlock(&hdcp_auth_state_mutex);
+
 	hdmi_msm_init_phy(external_common_state->video_resolution);
 	/* HDMI_USEC_REFTIMER[0x0208] */
 	HDMI_OUTP(0x0208, 0x0001001B);
@@ -3924,6 +4020,13 @@
 }
 #endif
 
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+static void hdmi_msm_cec_read_timer_func(unsigned long data)
+{
+	queue_work(hdmi_work_queue, &hdmi_msm_state->cec_latch_detect_work);
+}
+#endif
+
 static void hdmi_msm_hpd_read_work(struct work_struct *work)
 {
 	uint32 hpd_ctrl;
@@ -3965,6 +4068,7 @@
 
 	hdmi_msm_set_mode(FALSE);
 	hdmi_msm_state->hpd_initialized = FALSE;
+	hdmi_msm_powerdown_phy();
 	hdmi_msm_state->pd->cec_power(0);
 	hdmi_msm_state->pd->enable_5v(0);
 	hdmi_msm_state->pd->core_power(0, 1);
@@ -4248,6 +4352,15 @@
 	add_timer(&hdmi_msm_state->hdcp_timer);
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+	init_timer(&hdmi_msm_state->cec_read_timer);
+	hdmi_msm_state->cec_read_timer.function =
+		hdmi_msm_cec_read_timer_func;
+	hdmi_msm_state->cec_read_timer.data = (uint32)NULL;
+
+	hdmi_msm_state->cec_read_timer.expires = 0xffffffffL;
+ #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
+
 	fb_dev = msm_fb_add_device(pdev);
 	if (fb_dev) {
 		rc = external_common_state_create(fb_dev);
@@ -4452,7 +4565,10 @@
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
+	INIT_WORK(&hdmi_msm_state->cec_latch_detect_work,
+		  hdmi_msm_cec_latch_work);
 	init_completion(&hdmi_msm_state->cec_frame_wr_done);
+	init_completion(&hdmi_msm_state->cec_line_latch_wait);
 #endif
 
 	rc = platform_device_register(&this_device);
diff --git a/drivers/video/msm/hdmi_msm.h b/drivers/video/msm/hdmi_msm.h
index 6d19d157..9675fd5 100644
--- a/drivers/video/msm/hdmi_msm.h
+++ b/drivers/video/msm/hdmi_msm.h
@@ -75,8 +75,10 @@
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 	boolean cec_enabled;
+	unsigned int first_monitor;
 	int cec_logical_addr;
 	struct completion cec_frame_wr_done;
+	struct timer_list cec_read_timer;
 #define CEC_STATUS_WR_ERROR	0x0001
 #define CEC_STATUS_WR_DONE	0x0002
 #define CEC_STATUS_WR_TMOUT	0x0004
@@ -86,8 +88,17 @@
 	struct hdmi_msm_cec_msg *cec_queue_wr;
 	struct hdmi_msm_cec_msg *cec_queue_rd;
 	boolean cec_queue_full;
+	boolean fsm_reset_done;
+
+	/*
+	 * CECT 9-5-1
+	 */
+	struct completion cec_line_latch_wait;
+	struct work_struct cec_latch_detect_work;
+
 #define CEC_QUEUE_SIZE		16
 #define CEC_QUEUE_END	 (hdmi_msm_state->cec_queue_start + CEC_QUEUE_SIZE)
+#define RETRANSMIT_MAX_NUM	7
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT */
 
 	int irq;
diff --git a/drivers/video/msm/lcdc_gordon.c b/drivers/video/msm/lcdc_gordon.c
index f9532b4..8327c6c 100644
--- a/drivers/video/msm/lcdc_gordon.c
+++ b/drivers/video/msm/lcdc_gordon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2010, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -84,6 +84,7 @@
 static int spi_sdo;
 static int spi_sdi;
 static int spi_dac;
+static int bl_level;
 static unsigned char bit_shift[8] = { (1 << 7),	/* MSB */
 	(1 << 6),
 	(1 << 5),
@@ -313,6 +314,17 @@
 		spi_init();	/* LCD needs SPI */
 		gordon_disp_powerup();
 		gordon_disp_on();
+		if (bl_level <= 1) {
+			/* keep back light OFF */
+			serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+			udelay(15);
+			serigo(GORDON_REG_VALTRAN, 0x01);
+		} else {
+			/* keep back light ON */
+			serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+			udelay(15);
+			serigo(GORDON_REG_VALTRAN, 0x01);
+		}
 		gordon_state.disp_initialized = TRUE;
 	}
 	return 0;
@@ -351,18 +363,20 @@
 
 static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
 {
-		int bl_level = mfd->bl_level;
+		bl_level = mfd->bl_level;
 
-		if (bl_level <= 1) {
-			/* keep back light OFF */
-			serigo(GORDON_REG_LCDIFCTL2, 0x0B);
-			udelay(15);
-			serigo(GORDON_REG_VALTRAN, 0x01);
-		} else {
-			/* keep back light ON */
-			serigo(GORDON_REG_LCDIFCTL2, 0x7B);
-			udelay(15);
-			serigo(GORDON_REG_VALTRAN, 0x01);
+		if (gordon_state.disp_initialized) {
+			if (bl_level <= 1) {
+				/* keep back light OFF */
+				serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+				udelay(15);
+				serigo(GORDON_REG_VALTRAN, 0x01);
+			} else {
+				/* keep back light ON */
+				serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+				udelay(15);
+				serigo(GORDON_REG_VALTRAN, 0x01);
+			}
 		}
 }
 
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 43520e0..e43f729 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -875,15 +875,16 @@
 
 	/* LCDC Frame Start */
 	if (mdp_interrupt & LCDC_FRAME_START) {
+		dma = &dma2_data;
+		spin_lock_irqsave(&mdp_spin_lock, flag);
 		/* let's disable LCDC interrupt */
 		mdp_intr_mask &= ~LCDC_FRAME_START;
 		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-
-		dma = &dma2_data;
 		if (dma->waiting) {
 			dma->waiting = FALSE;
 			complete(&dma->comp);
 		}
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	}
 
 	/* DMA2 LCD-Out Complete */
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index bf53c73..4f8be7e 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -370,17 +370,18 @@
 
 static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
 {
-	uint32 val;
+	uint32 val, s;
 	int	n;
 
 	n = mdp4_leading_0(src);
 	if (n > f_num)
 		n = f_num;
-	val = src << n;	/* maximum to reduce lose of resolution */
-	val /= dst;
+	s = src << n;	/* maximum to reduce lose of resolution */
+	val = s / dst;
 	if (n < f_num) {
 		n = f_num - n;
 		val <<= n;
+		val |= ((s % dst) << n) / dst;
 	}
 
 	return val;
@@ -2342,6 +2343,9 @@
 	mdp4_stat.overlay_unset[pipe->mixer_num]++;
 
 	mdp4_overlay_pipe_free(pipe);
+
+	mdp4_set_perf_level();
+
 	mutex_unlock(&mfd->dma->ov_mutex);
 
 	return 0;
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index 5cdafe1..0b707d7 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -38,13 +38,16 @@
 {
 	uint8 *buf;
 	int bpp, ptype;
+	int yres, remainder;
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info;
 	int ret;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -55,10 +58,28 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	if (atv_pipe == NULL) {
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -150,16 +171,36 @@
 	uint8 *buf;
 	int bpp;
 	unsigned long flag;
+	int yres, remainder;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* no need to power on cmd block since it's lcdc mode */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	mutex_lock(&mfd->dma->ov_mutex);
 
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 3f12827..a3be2af 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -96,13 +96,16 @@
 	int hsync_end_x;
 	uint8 *buf;
 	int bpp, ptype;
+	int yres, remainder;
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info;
 	int ret;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -115,10 +118,28 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	if (dsi_pipe == NULL) {
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -295,7 +316,9 @@
 {
 	struct fb_info *fbi;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 	int bpp;
+	int yres, remainder;
 	uint8 *buf = NULL;
 
 	if (dsi_pipe == NULL)
@@ -314,10 +337,28 @@
 
 	fbi = mfd->fbi;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	if (pipe->is_3d) {
 		pipe->src_height = pipe->src_height_3d;
@@ -648,16 +689,36 @@
 	struct fb_info *fbi = mfd->fbi;
 	uint8 *buf;
 	int bpp;
+	int yres, remainder;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* no need to power on cmd block since it's dsi video mode */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	mutex_lock(&mfd->dma->ov_mutex);
 
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 3a1a9aa..590ad65 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -231,8 +231,15 @@
 		return -EINVAL;
 
 	mdp4_overlay_panel_mode(MDP4_MIXER1, MDP4_PANEL_DTV);
-	if (dtv_pipe != NULL)
-		ret = mdp4_dtv_start(mfd);
+
+	/* Allocate dtv_pipe at dtv_on*/
+	if (dtv_pipe == NULL) {
+		if (mdp4_overlay_dtv_set(mfd, NULL)) {
+			pr_warn("%s: dtv_pipe is NULL, dtv_set failed\n",
+				__func__);
+			return -EINVAL;
+		}
+	}
 
 	ret = panel_next_on(pdev);
 	if (ret != 0)
@@ -527,7 +534,7 @@
 	*/
 	temp_src_format = inpdw(rgb_base + 0x0050);
 	MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
-	mdp4_mixer_stage_up(pipe);
+	mdp4_mixer_stage_up(dtv_pipe);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 #endif
@@ -604,14 +611,6 @@
 		return;
 
 	mutex_lock(&mfd->dma->ov_mutex);
-	if (dtv_pipe == NULL) {
-		if (mdp4_overlay_dtv_set(mfd, NULL)) {
-			pr_warn("%s: dtv_pipe == NULL\n", __func__);
-			mutex_unlock(&mfd->dma->ov_mutex);
-			return;
-		}
-	}
-
 	pipe = dtv_pipe;
 	if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
 		pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 3dece1f..ae498fc 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -84,8 +84,11 @@
 	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *pipe;
 	int ret;
+	int yres, remainder;
+	struct msm_panel_info *panel_info;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -98,6 +101,17 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	if (is_mdp4_hw_reset()) {
@@ -107,8 +121,15 @@
 
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	if (lcdc_pipe == NULL) {
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -552,16 +573,36 @@
 	struct fb_info *fbi = mfd->fbi;
 	uint8 *buf;
 	int bpp;
+	int yres, remainder;
 	struct mdp4_overlay_pipe *pipe;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* no need to power on cmd block since it's lcdc mode */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	mutex_lock(&mfd->dma->ov_mutex);
 
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index cd4afd0..7739837 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -394,20 +394,49 @@
 		temp = kzalloc(sizeof(struct msmfb_writeback_data_list),
 				GFP_KERNEL);
 		if (temp == NULL) {
-			pr_err("Out of memory\n");
-			goto err;
+			pr_err("%s: out of memory\n", __func__);
+			goto register_alloc_fail;
 		}
 
-		temp->addr = (void *)(data->iova + data->offset);
+		if (data->iova)
+			temp->addr = (void *)(data->iova + data->offset);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		else {
+			struct ion_handle *srcp_ihdl;
+			ulong len;
+			srcp_ihdl = ion_import_fd(mfd->iclient,
+						  data->memory_id);
+			if (IS_ERR_OR_NULL(srcp_ihdl)) {
+				pr_err("%s: ion import fd failed\n", __func__);
+				goto register_ion_fail;
+			}
+			if (ion_phys(mfd->iclient,
+				     srcp_ihdl,
+				     (ulong *)&temp->addr,
+				     (size_t *)&len)) {
+				pr_err("%s: unable to get ion phys\n",
+				       __func__);
+				goto register_ion_fail;
+			}
+			temp->addr += data->offset;
+		}
+#else
+		else {
+			pr_err("%s: only support ion memory\n", __func__);
+			goto register_ion_fail;
+		}
+#endif
 		memcpy(&temp->buf_info, data, sizeof(struct msmfb_data));
 		if (mdp4_overlay_writeback_register_buffer(mfd, temp)) {
-			pr_err("Error registering node\n");
-			kfree(temp);
-			temp = NULL;
+			pr_err("%s: error registering node\n", __func__);
+			goto register_ion_fail;
 		}
 	}
-err:
 	return temp;
+ register_ion_fail:
+	kfree(temp);
+ register_alloc_fail:
+	return NULL;
 }
 int mdp4_writeback_start(
 		struct fb_info *info)
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index 3997814..e8b288f 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -522,14 +522,37 @@
 			  boolean sync)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct fb_info *fbi = mfd->fbi;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 	MDPIBUF *iBuf;
 	int bpp = info->var.bits_per_pixel / 8;
+	int yres, remainder;
+
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
 
 	down(&mfd->sem);
+
 	iBuf = &mfd->ibuf;
 	iBuf->buf = (uint8 *) info->fix.smem_start;
-	iBuf->buf += info->var.xoffset * bpp +
-			info->var.yoffset * info->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		iBuf->buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		iBuf->buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		iBuf->buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	iBuf->ibuf_width = info->var.xres_virtual;
 	iBuf->bpp = bpp;
diff --git a/drivers/video/msm/mdp_dma_dsi_video.c b/drivers/video/msm/mdp_dma_dsi_video.c
index 505eb74..0e76a07 100644
--- a/drivers/video/msm/mdp_dma_dsi_video.c
+++ b/drivers/video/msm/mdp_dma_dsi_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -67,14 +67,17 @@
 	int hsync_end_x;
 	uint8 *buf;
 	uint32 dma2_cfg_reg;
+	int yres, remainder;
 
 	int bpp;
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
+	struct msm_panel_info *panel_info;
 	int ret;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -85,10 +88,29 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_DSI_VIDEO;
 
@@ -239,17 +261,38 @@
 	uint8 *buf;
 	int bpp;
 	unsigned long flag;
+	int yres, remainder;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 	int irq_block = MDP_DMA2_TERM;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	down(&mfd->dma->mutex);
 
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 	/* no need to power on cmd block since it's dsi mode */
 	/* starting address */
 	MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x8, (uint32) buf);
diff --git a/drivers/video/msm/mdp_dma_lcdc.c b/drivers/video/msm/mdp_dma_lcdc.c
index 9ce7e13..5dada35 100644
--- a/drivers/video/msm/mdp_dma_lcdc.c
+++ b/drivers/video/msm/mdp_dma_lcdc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -89,12 +89,15 @@
 	struct fb_info *fbi;
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
+	struct msm_panel_info *panel_info;
 	uint32 dma_base;
 	uint32 timer_base = LCDC_BASE;
 	uint32 block = MDP_DMA2_BLOCK;
 	int ret;
+	int yres, remainder;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -105,12 +108,32 @@
 	fbi = mfd->fbi;
 	var = &fbi->var;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_LCDC;
 
@@ -299,6 +322,7 @@
 	}
 #endif
 
+	down(&mfd->dma->mutex);
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	MDP_OUTP(MDP_BASE + timer_base, 0);
@@ -307,6 +331,7 @@
 	mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
 
 	ret = panel_next_off(pdev);
+	up(&mfd->dma->mutex);
 
 	/* delay to make sure the last frame finishes */
 	msleep(16);
@@ -317,23 +342,45 @@
 void mdp_lcdc_update(struct msm_fb_data_type *mfd)
 {
 	struct fb_info *fbi = mfd->fbi;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 	uint8 *buf;
 	int bpp;
 	unsigned long flag;
 	uint32 dma_base;
+	int yres, remainder;
 	int irq_block = MDP_DMA2_TERM;
 #ifdef CONFIG_FB_MSM_MDP40
 	int intr = INTR_DMA_P_DONE;
 #endif
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	if (!mfd->panel_power_on)
 		return;
 
+	down(&mfd->dma->mutex);
 	/* no need to power on cmd block since it's lcdc mode */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	dma_base = DMA_P_BASE;
 
@@ -365,4 +412,5 @@
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	wait_for_completion_killable(&mfd->dma->comp);
 	mdp_disable_irq(irq_block);
+	up(&mfd->dma->mutex);
 }
diff --git a/drivers/video/msm/mdp_dma_tv.c b/drivers/video/msm/mdp_dma_tv.c
index 66d9422..1305e03 100644
--- a/drivers/video/msm/mdp_dma_tv.c
+++ b/drivers/video/msm/mdp_dma_tv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,12 +39,15 @@
 int mdp_dma3_on(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd;
+	struct msm_panel_info *panel_info;
 	struct fb_info *fbi;
 	uint8 *buf;
 	int bpp;
 	int ret = 0;
+	int yres, remainder;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	panel_info = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -53,13 +56,33 @@
 		return -EINVAL;
 
 	fbi = mfd->fbi;
+
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* MDP cmd block enable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
 
 	/* starting address[31..8] of Video frame buffer is CS0 */
 	MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
@@ -112,15 +135,37 @@
 	uint8 *buf;
 	int bpp;
 	unsigned long flag;
+	int yres, remainder;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
 
 	if (!mfd->panel_power_on)
 		return;
 
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
 	/* no need to power on cmd block since dma3 is running */
 	bpp = fbi->var.bits_per_pixel / 8;
 	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (fbi->var.yoffset < yres) {
+		buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
+
 	MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 9907109..4fbb044 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -50,7 +50,8 @@
 #define MIPI_DSI_PANEL_WSVGA_PT	4
 #define MIPI_DSI_PANEL_QHD_PT 5
 #define MIPI_DSI_PANEL_WXGA	6
-#define DSI_PANEL_MAX	6
+#define MIPI_DSI_PANEL_WUXGA	7
+#define DSI_PANEL_MAX	7
 
 enum {		/* mipi dsi panel */
 	DSI_VIDEO_MODE,
diff --git a/drivers/video/msm/mipi_toshiba.c b/drivers/video/msm/mipi_toshiba.c
index 5788f27..2db8bcf 100644
--- a/drivers/video/msm/mipi_toshiba.c
+++ b/drivers/video/msm/mipi_toshiba.c
@@ -196,7 +196,8 @@
 		mipi_dsi_cmds_tx(mfd, &toshiba_tx_buf,
 			toshiba_wvga_display_on_cmds,
 			ARRAY_SIZE(toshiba_wvga_display_on_cmds));
-	else if (TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WSVGA_PT)
+	else if (TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WSVGA_PT ||
+		TM_GET_PID(mfd->panel.id) == MIPI_DSI_PANEL_WUXGA)
 		mipi_dsi_cmds_tx(mfd, &toshiba_tx_buf,
 			toshiba_wsvga_display_on_cmds,
 			ARRAY_SIZE(toshiba_wsvga_display_on_cmds));
diff --git a/drivers/video/msm/mipi_toshiba_video_wuxga.c b/drivers/video/msm/mipi_toshiba_video_wuxga.c
new file mode 100644
index 0000000..297248f
--- /dev/null
+++ b/drivers/video/msm/mipi_toshiba_video_wuxga.c
@@ -0,0 +1,97 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_toshiba.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+	/* 1920*1200, RGB888, 4 Lane 60 fps video mode */
+	/* regulator */
+	{0x03, 0x0a, 0x04, 0x00, 0x20},
+	/* timing */
+	{0x66, 0x26, 0x1F, 0x00, 0x55, 0x9C, 0x16, 0x90,
+	0x23, 0x03, 0x04, 0xa0},
+	/* phy ctrl */
+	{0x5f, 0x00, 0x00, 0x10},
+	/* strength */
+	{0xff, 0x00, 0x06, 0x00},
+	/* pll control */
+	{0x0, 0xD7, 0x1, 0x19, 0x00, 0x50, 0x48, 0x63,
+	0x41, 0x0f, 0x01,
+	0x00, 0x14, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01 },
+};
+
+static int __init mipi_video_toshiba_wuxga_init(void)
+{
+	int ret;
+
+	if (msm_fb_detect_client("mipi_video_toshiba_wuxga"))
+		return 0;
+
+	pinfo.xres = 1920;
+	pinfo.yres = 1200;
+
+	pinfo.type = MIPI_VIDEO_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.lcdc.h_back_porch = 50;
+	pinfo.lcdc.h_front_porch = 50;
+	pinfo.lcdc.h_pulse_width = 170;
+	pinfo.lcdc.v_back_porch = 7;
+	pinfo.lcdc.v_front_porch = 8;
+	pinfo.lcdc.v_pulse_width = 30;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+	pinfo.bl_max = MIPI_TOSHIBA_PWM_LEVEL;
+	pinfo.bl_min = 1;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 981560000;
+
+	pinfo.mipi.mode = DSI_VIDEO_MODE;
+	pinfo.mipi.pulse_mode_hsa_he = TRUE;
+	pinfo.mipi.hfp_power_stop = FALSE;
+	pinfo.mipi.hbp_power_stop = FALSE;
+	pinfo.mipi.hsa_power_stop = FALSE;
+	pinfo.mipi.eof_bllp_power_stop = TRUE;
+	pinfo.mipi.bllp_power_stop = TRUE;
+	pinfo.mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+	pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+	pinfo.mipi.vc = 0;
+	pinfo.mipi.rgb_swap = DSI_RGB_SWAP_BGR;
+	pinfo.mipi.data_lane0 = TRUE;
+	pinfo.mipi.data_lane1 = TRUE;
+	pinfo.mipi.data_lane2 = TRUE;
+	pinfo.mipi.data_lane3 = TRUE;
+	pinfo.mipi.tx_eot_append = TRUE;
+	pinfo.mipi.t_clk_post = 0x04;
+	pinfo.mipi.t_clk_pre = 0x1c;
+	pinfo.mipi.stream = 0; /* dma_p */
+	pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo.mipi.frame_rate = 60;
+	pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+	ret = mipi_toshiba_device_register(&pinfo, MIPI_DSI_PRIM,
+						MIPI_DSI_PANEL_WUXGA);
+	if (ret)
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mipi_video_toshiba_wuxga_init);
diff --git a/drivers/video/msm/mipi_truly_video_wvga_pt.c b/drivers/video/msm/mipi_truly_video_wvga_pt.c
index 931c564..03ef32b 100644
--- a/drivers/video/msm/mipi_truly_video_wvga_pt.c
+++ b/drivers/video/msm/mipi_truly_video_wvga_pt.c
@@ -38,10 +38,8 @@
 {
 	int ret;
 
-#ifdef CONFIG_FB_MSM_MIPI_PANEL_DETECT
 	if (msm_fb_detect_client("mipi_video_truly_wvga"))
 		return 0;
-#endif
 
 	pinfo.xres = 480;
 	pinfo.yres = 800;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 489e6d2..019acce 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -606,6 +606,7 @@
 	return 0;
 }
 
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
 static int msm_fb_ext_suspend(struct device *dev)
 {
 	struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
@@ -635,13 +636,16 @@
 
 	return ret;
 }
+#endif
 
 static struct dev_pm_ops msm_fb_dev_pm_ops = {
 	.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))
 	.suspend = msm_fb_ext_suspend,
 	.resume = msm_fb_ext_resume,
+#endif
 };
 
 static struct platform_driver msm_fb_driver = {
@@ -969,6 +973,7 @@
 	struct fb_var_screeninfo *var;
 	int *id;
 	int fbram_offset;
+	int remainder, remainder_mode2;
 
 	/*
 	 * fb info initialization
@@ -1105,15 +1110,28 @@
 
 	fix->line_length = msm_fb_line_length(mfd->index, panel_info->xres,
 					      bpp);
+
+	/* Make sure all buffers can be addressed on a page boundary by an x
+	 * and y offset */
+
+	remainder = (fix->line_length * panel_info->yres) % PAGE_SIZE;
+	if (!remainder)
+		remainder = PAGE_SIZE;
+	remainder_mode2 = (fix->line_length *
+				panel_info->mode2_yres) % PAGE_SIZE;
+	if (!remainder_mode2)
+		remainder_mode2 = PAGE_SIZE;
+
 	/* calculate smem_len based on max size of two supplied modes */
-	fix->smem_len = roundup(MAX(msm_fb_line_length(mfd->index,
-					       panel_info->xres,
-					       bpp) *
-			    panel_info->yres * mfd->fb_page,
-			    msm_fb_line_length(mfd->index,
+	fix->smem_len = MAX((msm_fb_line_length(mfd->index, panel_info->xres,
+					      bpp) *
+			    panel_info->yres + PAGE_SIZE -
+				remainder) * mfd->fb_page,
+			    (msm_fb_line_length(mfd->index,
 					       panel_info->mode2_xres,
 					       bpp) *
-			    panel_info->mode2_yres * mfd->fb_page), PAGE_SIZE);
+			    panel_info->mode2_yres + PAGE_SIZE -
+				remainder_mode2) * mfd->fb_page);
 
 
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
index f63ebcd..a5a8e57 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h
@@ -24,8 +24,8 @@
 #define VIDC_REG_IN(x...)
 #endif
 
-#define __inpdw(port) (*((u32 *) (port)))
-#define __outpdw(port, val) (*((u32 *) (port)) = ((u32) (val)))
+#define __inpdw(port) __raw_readl(port)
+#define __outpdw(port, val) __raw_writel(val, port)
 
 #define in_dword(addr) (__inpdw(addr))
 #define in_dword_masked(addr, mask) (__inpdw(addr) & (mask))
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index b300fbc..dee4da7 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -2111,8 +2111,10 @@
 	struct video_client_ctx *client_ctx = file->private_data;
 
 	INFO("msm_vidc_dec: Inside %s()", __func__);
-	res_trk_close_secure_session();
+	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
+	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
 	vid_dec_close_client(client_ctx);
+	res_trk_close_secure_session();
 	vidc_release_firmware();
 #ifndef USE_RES_TRACKER
 	vidc_disable_clk();
@@ -2125,13 +2127,15 @@
 {
 	struct video_client_ctx *client_ctx = file->private_data;
 
-	DBG("msm_vidc_dec: Inside %s()", __func__);
+	INFO("msm_vidc_dec: Inside %s()", __func__);
+	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT);
+	vidc_cleanup_addr_table(client_ctx, BUFFER_TYPE_INPUT);
 	vid_dec_close_client(client_ctx);
 	vidc_release_firmware();
 #ifndef USE_RES_TRACKER
 	vidc_disable_clk();
 #endif
-	DBG("msm_vidc_dec: Return from %s()", __func__);
+	INFO("msm_vidc_dec: Return from %s()", __func__);
 	return 0;
 }
 
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index cd3f954..f799a6c 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -384,6 +384,59 @@
 }
 EXPORT_SYMBOL(vidc_get_fd_info);
 
+void vidc_cleanup_addr_table(struct video_client_ctx *client_ctx,
+				enum buffer_dir buffer)
+{
+	u32 *num_of_buffers = NULL;
+	u32 i = 0;
+	struct buf_addr_table *buf_addr_table;
+	if (buffer == BUFFER_TYPE_INPUT) {
+		buf_addr_table = client_ctx->input_buf_addr_table;
+		num_of_buffers = &client_ctx->num_of_input_buffers;
+		DBG("%s(): buffer = INPUT\n", __func__);
+
+	} else {
+		buf_addr_table = client_ctx->output_buf_addr_table;
+		num_of_buffers = &client_ctx->num_of_output_buffers;
+		DBG("%s(): buffer = OUTPUT\n", __func__);
+	}
+
+	if (!*num_of_buffers)
+		goto bail_out_cleanup;
+	if (!client_ctx->user_ion_client)
+		goto bail_out_cleanup;
+	for (i = 0; i < *num_of_buffers; ++i) {
+		if (buf_addr_table[i].client_data) {
+			msm_subsystem_unmap_buffer(
+			(struct msm_mapped_buffer *)
+			buf_addr_table[i].client_data);
+			buf_addr_table[i].client_data = NULL;
+		}
+		if (buf_addr_table[i].buff_ion_handle) {
+			ion_unmap_kernel(client_ctx->user_ion_client,
+					buf_addr_table[i].buff_ion_handle);
+			ion_free(client_ctx->user_ion_client,
+					buf_addr_table[i].buff_ion_handle);
+			buf_addr_table[i].buff_ion_handle = NULL;
+		}
+	}
+	if (client_ctx->vcd_h264_mv_buffer.client_data) {
+		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+		client_ctx->vcd_h264_mv_buffer.client_data);
+		client_ctx->vcd_h264_mv_buffer.client_data = NULL;
+	}
+	if (client_ctx->h264_mv_ion_handle) {
+		ion_unmap_kernel(client_ctx->user_ion_client,
+				client_ctx->h264_mv_ion_handle);
+		ion_free(client_ctx->user_ion_client,
+				client_ctx->h264_mv_ion_handle);
+		client_ctx->h264_mv_ion_handle = NULL;
+	}
+bail_out_cleanup:
+	return;
+}
+EXPORT_SYMBOL(vidc_cleanup_addr_table);
+
 u32 vidc_lookup_addr_table(struct video_client_ctx *client_ctx,
 	enum buffer_dir buffer,
 	u32 search_with_user_vaddr,
@@ -540,9 +593,10 @@
 				client_ctx->user_ion_client,
 				buff_ion_handle,
 				ionflag);
-			if (!(*kernel_vaddr)) {
+			if (IS_ERR_OR_NULL((void *)*kernel_vaddr)) {
 				ERR("%s():ION virtual addr fail\n",
 				 __func__);
+				*kernel_vaddr = (unsigned long)NULL;
 				goto ion_error;
 			}
 			if (ion_phys(client_ctx->user_ion_client,
@@ -587,7 +641,7 @@
 	mutex_unlock(&client_ctx->enrty_queue_lock);
 	return true;
 ion_error:
-	if (*kernel_vaddr)
+	if (*kernel_vaddr && buff_ion_handle)
 		ion_unmap_kernel(client_ctx->user_ion_client, buff_ion_handle);
 	if (!IS_ERR_OR_NULL(buff_ion_handle))
 		ion_free(client_ctx->user_ion_client, buff_ion_handle);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.h b/drivers/video/msm/vidc/common/init/vidc_init.h
index ced99ff..a67329c 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.h
+++ b/drivers/video/msm/vidc/common/init/vidc_init.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -80,6 +80,8 @@
 u32 vidc_delete_addr_table(struct video_client_ctx *client_ctx,
 	enum buffer_dir buffer, unsigned long user_vaddr,
 	unsigned long *kernel_vaddr);
+void vidc_cleanup_addr_table(struct video_client_ctx *client_ctx,
+				enum buffer_dir buffer);
 
 u32 vidc_timer_create(void (*timer_handler)(void *),
 	void *user_data, void **timer_handle);
diff --git a/include/linux/fmem.h b/include/linux/fmem.h
index aebeec4..44b7005 100644
--- a/include/linux/fmem.h
+++ b/include/linux/fmem.h
@@ -20,7 +20,8 @@
 struct fmem_platform_data {
 	unsigned long phys;
 	unsigned long size;
-	unsigned long reserved_size;
+	unsigned long reserved_size_low;
+	unsigned long reserved_size_high;
 };
 
 struct fmem_data {
@@ -28,7 +29,8 @@
 	void *virt;
 	struct vm_struct *area;
 	unsigned long size;
-	unsigned long reserved_size;
+	unsigned long reserved_size_low;
+	unsigned long reserved_size_high;
 };
 
 enum fmem_state {
diff --git a/include/linux/ion.h b/include/linux/ion.h
index ade87e6..3256fba 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -64,12 +64,12 @@
 
 enum ion_heap_ids {
 	INVALID_HEAP_ID = -1,
-	ION_IOMMU_HEAP_ID = 4,
 	ION_CP_MM_HEAP_ID = 8,
 	ION_CP_MFC_HEAP_ID = 12,
 	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
 	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
 	ION_SF_HEAP_ID = 24,
+	ION_IOMMU_HEAP_ID = 25,
 	ION_QSECOM_HEAP_ID = 27,
 	ION_AUDIO_HEAP_ID = 28,
 
@@ -160,6 +160,8 @@
  *			of this heap in the case of a shared heap.
  * @reusable		Flag indicating whether this heap is reusable of not.
  *			(see FMEM)
+ * @mem_is_fmem		Flag indicating whether this memory is coming from fmem
+ *			or not.
  * @virt_addr:		Virtual address used when using fmem.
  * @request_region:	function to be called when the number of allocations
  *			goes from 0 -> 1
@@ -174,6 +176,7 @@
 	ion_phys_addr_t secure_base; /* Base addr used when heap is shared */
 	size_t secure_size; /* Size used for securing heap when heap is shared*/
 	int reusable;
+	int mem_is_fmem;
 	ion_virt_addr_t *virt_addr;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
@@ -184,6 +187,8 @@
  * struct ion_co_heap_pdata - defines a carveout heap in the given platform
  * @adjacent_mem_id:	Id of heap that this heap must be adjacent to.
  * @align:		Alignment requirement for the memory
+ * @mem_is_fmem		Flag indicating whether this memory is coming from fmem
+ *			or not.
  * @request_region:	function to be called when the number of allocations
  *			goes from 0 -> 1
  * @release_region:	function to be called when the number of allocations
@@ -194,6 +199,7 @@
 struct ion_co_heap_pdata {
 	int adjacent_mem_id;
 	unsigned int align;
+	int mem_is_fmem;
 	int (*request_region)(void *);
 	int (*release_region)(void *);
 	void *(*setup_region)(void);
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index c4f601b..c90d8d1 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -73,6 +73,22 @@
 	PM8XXX_RESTART_ON_HARD_RESET,
 };
 
+enum pm8xxx_aux_clk_id {
+	CLK_MP3_1,
+	CLK_MP3_2,
+};
+
+enum pm8xxx_aux_clk_div {
+	X0_DIV_NONE,
+	XO_DIV_1,
+	XO_DIV_2,
+	XO_DIV_4,
+	XO_DIV_8,
+	XO_DIV_16,
+	XO_DIV_32,
+	XO_DIV_64,
+};
+
 #if defined(CONFIG_MFD_PM8XXX_MISC) || defined(CONFIG_MFD_PM8XXX_MISC_MODULE)
 
 /**
@@ -181,6 +197,19 @@
  */
 int pm8xxx_usb_id_pullup(int enable);
 
+/**
+ * pm8xxx_aux_clk_control - Control an auxiliary clock
+ * @clk_id: ID of clock to be programmed, registers of XO_CNTRL2
+ * @divider: divisor to use when configuring desired clock
+ * @enable: enable (1) the designated clock with the supplied division,
+ *		or disable (0) the designated clock
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+				enum pm8xxx_aux_clk_div divider,
+				bool enable);
+
 #else
 
 static inline int pm8xxx_reset_pwr_off(int reset)
@@ -225,6 +254,12 @@
 {
 	return -ENODEV;
 }
+static inline int pm8xxx_aux_clk_control(enum pm8xxx_aux_clk_id clk_id,
+			enum pm8xxx_aux_clk_div divider, bool enable)
+{
+	return -ENODEV;
+}
+
 #endif
 
 #endif
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 18997d7..cb394e8 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -436,6 +436,15 @@
 			__attribute__((aligned(sizeof(kernel_ulong_t))));
 };
 
+#define SPMI_NAME_SIZE	32
+#define SPMI_MODULE_PREFIX "spmi:"
+
+struct spmi_device_id {
+	char name[SPMI_NAME_SIZE];
+	kernel_ulong_t driver_data	/* Data private to the driver */
+			__attribute__((aligned(sizeof(kernel_ulong_t))));
+};
+
 /* dmi */
 enum dmi_field {
 	DMI_NONE,
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 9eb6dda..37b9d35 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -148,6 +148,7 @@
 	unsigned int idle_timeout;
 	unsigned int nap_allowed;
 	unsigned int clk_map;
+	unsigned int idle_needed;
 	struct msm_bus_scale_pdata *bus_scale_table;
 	const char *iommu_user_ctx_name;
 	const char *iommu_priv_ctx_name;
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 189548c..99b5acd 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -22,14 +22,15 @@
 	MSM_8660 = 0,
 	MSM_8960,
 	MSM_9615,
+	APQ_8064,
 	MSM_TYPE
 };
 
 struct tsens_platform_data {
-	int				slope;
 	int				tsens_factor;
 	uint32_t			tsens_num_sensor;
 	enum platform_type		hw_type;
+	int				slope[11];
 };
 
 struct tsens_device {
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 3a6f037..cf58d27 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -49,6 +49,8 @@
 
 struct mtd_info;
 
+void part_fill_badblockstats(struct mtd_info *mtd);
+
 /*
  * Functions dealing with the various ways of partitioning the space
  */
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
new file mode 100644
index 0000000..ffcb24e
--- /dev/null
+++ b/include/linux/spmi.h
@@ -0,0 +1,408 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_SPMI_H
+#define _LINUX_SPMI_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+/* Maximum slave identifier */
+#define SPMI_MAX_SLAVE_ID		16
+
+/* SPMI Commands */
+enum spmi_commands {
+	SPMI_CMD_EXT_WRITE = 0x00,
+	SPMI_CMD_RESET = 0x10,
+	SPMI_CMD_SLEEP = 0x11,
+	SPMI_CMD_SHUTDOWN = 0x12,
+	SPMI_CMD_WAKEUP = 0x13,
+	SPMI_CMD_AUTHENTICATE = 0x14,
+	SPMI_CMD_MSTR_READ = 0x15,
+	SPMI_CMD_MSTR_WRITE = 0x16,
+	SPMI_CMD_TRANSFER_BUS_OWNERSHIP = 0x1A,
+	SPMI_CMD_DDB_MASTER_READ = 0x1B,
+	SPMI_CMD_DDB_SLAVE_READ = 0x1C,
+	SPMI_CMD_EXT_READ = 0x20,
+	SPMI_CMD_EXT_WRITEL = 0x30,
+	SPMI_CMD_EXT_READL = 0x38,
+	SPMI_CMD_WRITE = 0x40,
+	SPMI_CMD_READ = 0x60,
+	SPMI_CMD_ZERO_WRITE = 0x80,
+};
+
+struct spmi_device;
+
+/**
+ * struct spmi_controller: interface to the SPMI master controller
+ * @nr: board-specific number identifier for this controller/bus
+ * @name: name for this controller
+ * @cmd: sends a non-data command sequence on the SPMI bus.
+ * @read_cmd: sends a register read command sequence on the SPMI bus.
+ * @write_cmd: sends a register write command sequence on the SPMI bus.
+ */
+struct spmi_controller {
+	struct device		dev;
+	unsigned int		nr;
+	struct list_head	list;
+	int		(*cmd)(struct spmi_controller *, u8 opcode, u8 sid);
+	int		(*read_cmd)(struct spmi_controller *,
+				u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);
+	int		(*write_cmd)(struct spmi_controller *,
+				u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);
+};
+#define to_spmi_controller(d) container_of(d, struct spmi_controller, dev)
+
+/**
+ * struct spmi_driver: Manage SPMI generic/slave device driver
+ * @probe: binds this driver to a SPMI device.
+ * @remove: unbinds this driver from the SPMI device.
+ * @shutdown: standard shutdown callback used during powerdown/halt.
+ * @suspend: standard suspend callback used during system suspend
+ * @resume: standard resume callback used during system resume
+ * @driver: SPMI device drivers should initialize name and owner field of
+ *	    this structure
+ * @id_table: list of SPMI devices supported by this driver
+ */
+struct spmi_driver {
+	int				(*probe)(struct spmi_device *dev);
+	int				(*remove)(struct spmi_device *dev);
+	void				(*shutdown)(struct spmi_device *dev);
+	int				(*suspend)(struct spmi_device *dev,
+					pm_message_t pmesg);
+	int				(*resume)(struct spmi_device *dev);
+
+	struct device_driver		driver;
+	const struct spmi_device_id	*id_table;
+};
+#define to_spmi_driver(d) container_of(d, struct spmi_driver, driver)
+
+/**
+ * Client/device handle (struct spmi_device):
+ * ------------------------------------------
+ * This is the client/device handle returned when a SPMI device
+ * is registered with a controller.
+ * Pointer to this structure is used by client-driver as a handle.
+ * @dev: driver model representation of the device.
+ * @name: name of driver to use with this device.
+ * @ctrl: SPMI controller managing the bus hosting this device.
+ * @resource: array of resources for this device_node
+ * @num_resources: number of resources for this device node
+ * @sid: slave identifier.
+ */
+struct spmi_device {
+	struct device		dev;
+	const char		*name;
+	struct spmi_controller	*ctrl;
+	struct resource		*resource;
+	u32			num_resources;
+	u8			sid;
+};
+#define to_spmi_device(d) container_of(d, struct spmi_device, dev)
+
+/**
+ * struct spmi_boardinfo: Declare board info for SPMI device bringup.
+ * @slave_id: slave identifier.
+ * @spmi_device: device to be registered with the SPMI framework.
+ * @of_node: pointer to the OpenFirmware device node.
+ * @num_resources: number of resources for this device node
+ * @resource: array of resources for this device_node
+ * @platform_data: goes to spmi_device.dev.platform_data
+ */
+struct spmi_boardinfo {
+	char			name[SPMI_NAME_SIZE];
+	uint8_t			slave_id;
+	struct device_node	*of_node;
+	u32			num_resources;
+	struct resource		*resource;
+	const void		*platform_data;
+};
+
+/**
+ * spmi_driver_register: Client driver registration with SPMI framework.
+ * @drv: client driver to be associated with client-device.
+ *
+ * This API will register the client driver with the SPMI framework.
+ * It is called from the driver's module-init function.
+ */
+extern int spmi_driver_register(struct spmi_driver *drv);
+
+/**
+ * spmi_driver_unregister - reverse effect of spmi_driver_register
+ * @sdrv: the driver to unregister
+ * Context: can sleep
+ */
+static inline void spmi_driver_unregister(struct spmi_driver *sdrv)
+{
+	if (sdrv)
+		driver_unregister(&sdrv->driver);
+}
+
+/**
+ * spmi_add_controller: Controller bring-up.
+ * @ctrl: controller to be registered.
+ *
+ * A controller is registered with the framework using this API. ctrl->nr is the
+ * desired number with which SPMI framework registers the controller.
+ * Function will return -EBUSY if the number is in use.
+ */
+extern int spmi_add_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_del_controller: Controller tear-down.
+ * Controller added with the above API is teared down using this API.
+ */
+extern int spmi_del_controller(struct spmi_controller *ctrl);
+
+/**
+ * spmi_busnum_to_ctrl: Map bus number to controller
+ * @busnum: bus number
+ *
+ * Returns controller device representing this bus number
+ */
+extern struct spmi_controller *spmi_busnum_to_ctrl(u32 bus_num);
+
+/**
+ * spmi_alloc_device: Allocate a new SPMI devices.
+ * @ctrl: controller to which this device is to be added to.
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize a SPMI device without
+ * registering it immediately.  This allows a driver to directly fill
+ * the spmi_device structure before calling spmi_add_device().
+ *
+ * Caller is responsible to call spmi_add_device() on the returned
+ * spmi_device.  If the caller needs to discard the spmi_device without
+ * adding it, then spmi_dev_put() should be called.
+ */
+extern struct spmi_device *spmi_alloc_device(struct spmi_controller *ctrl);
+
+/**
+ * spmi_add_device: Add spmi_device allocated with spmi_alloc_device().
+ * @spmi_dev: spmi_device to be added (registered).
+ */
+extern int spmi_add_device(struct spmi_device *spmi_dev);
+
+/**
+ * spmi_new_device: Instantiates a new SPMI device
+ * @ctrl: controller to which this device is to be added to.
+ * @info: board information for this device.
+ *
+ * Returns the new device or NULL.
+ */
+extern struct spmi_device *spmi_new_device(struct spmi_controller *ctrl,
+					struct spmi_boardinfo const *info);
+
+/* spmi_remove_device: Remove the effect of spmi_add_device() */
+extern void spmi_remove_device(struct spmi_device *spmi_dev);
+
+#ifdef CONFIG_SPMI
+/**
+ * spmi_register_board_info: Board-initialization routine.
+ * @bus_num: controller number (bus) on which this device will sit.
+ * @info: list of all devices on all controllers present on the board.
+ * @n: number of entries.
+ *
+ * API enumerates respective devices on corresponding controller.
+ * Called from board-init function.
+ */
+extern int spmi_register_board_info(int busnum,
+			struct spmi_boardinfo const *info, unsigned n);
+#else
+static inline int spmi_register_board_info(int busnum,
+			struct spmi_boardinfo const *info, unsigned n)
+{
+	return 0;
+}
+#endif
+
+static inline void *spmi_get_ctrldata(const struct spmi_controller *ctrl)
+{
+	return dev_get_drvdata(&ctrl->dev);
+}
+
+static inline void spmi_set_ctrldata(struct spmi_controller *ctrl, void *data)
+{
+	dev_set_drvdata(&ctrl->dev, data);
+}
+
+static inline void *spmi_get_devicedata(const struct spmi_device *dev)
+{
+	return dev_get_drvdata(&dev->dev);
+}
+
+static inline void spmi_set_devicedata(struct spmi_device *dev, void *data)
+{
+	dev_set_drvdata(&dev->dev, data);
+}
+
+static inline void spmi_dev_put(struct spmi_device *spmidev)
+{
+	if (spmidev)
+		put_device(&spmidev->dev);
+}
+
+/**
+ * spmi_register_read() - register read
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads 1 byte of data from a Slave device register.
+ */
+extern int spmi_register_read(struct spmi_controller *ctrl,
+					u8 sid, u8 ad, u8 *buf);
+
+/**
+ * spmi_ext_register_read() - extended register read
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @len: the request number of bytes to read (up to 16 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 16 bytes of data from the extended register space on a
+ * Slave device.
+ */
+extern int spmi_ext_register_read(struct spmi_controller *ctrl,
+					u8 sid, u8 ad, u8 *buf, int len);
+
+/**
+ * spmi_ext_register_readl() - extended register read long
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @len: the request number of bytes to read (up to 8 bytes).
+ * @buf: buffer to be populated with data from the Slave.
+ *
+ * Reads up to 8 bytes of data from the extended register space on a
+ * Slave device using 16-bit address.
+ */
+extern int spmi_ext_register_readl(struct spmi_controller *ctrl,
+					u8 sid, u16 ad, u8 *buf, int len);
+
+/**
+ * spmi_register_write() - register write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (5-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ *
+ * Writes 1 byte of data to a Slave device register.
+ */
+extern int spmi_register_write(struct spmi_controller *ctrl,
+					u8 sid, u8 ad, u8 *buf);
+
+/**
+ * spmi_register_zero_write() - register zero write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @data: the data to be written to register 0 (7-bits).
+ *
+ * Writes data to register 0 of the Slave device.
+ */
+extern int spmi_register_zero_write(struct spmi_controller *ctrl,
+					u8 sid, u8 data);
+
+/**
+ * spmi_ext_register_write() - extended register write
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (8-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 16 bytes).
+ *
+ * Writes up to 16 bytes of data to the extended register space of a
+ * Slave device.
+ */
+extern int spmi_ext_register_write(struct spmi_controller *ctrl,
+					u8 sid, u8 ad, u8 *buf, int len);
+
+/**
+ * spmi_ext_register_writel() - extended register write long
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ * @ad: slave register address (16-bit address).
+ * @buf: buffer containing the data to be transferred to the Slave.
+ * @len: the request number of bytes to read (up to 8 bytes).
+ *
+ * Writes up to 8 bytes of data to the extended register space of a
+ * Slave device using 16-bit address.
+ */
+extern int spmi_ext_register_writel(struct spmi_controller *ctrl,
+					u8 sid, u16 ad, u8 *buf, int len);
+
+/**
+ * spmi_command_reset() - sends RESET command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Reset command initializes the Slave and forces all registers to
+ * their reset values. The Slave shall enter the STARTUP state after
+ * receiving a Reset command.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_reset(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_sleep() - sends SLEEP command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Sleep command causes the Slave to enter the user defined SLEEP state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_sleep(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_wakeup() - sends WAKEUP command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Wakeup command causes the Slave to move from the SLEEP state to
+ * the ACTIVE state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_wakeup(struct spmi_controller *ctrl, u8 sid);
+
+/**
+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified slave
+ * @ctrl: SPMI controller.
+ * @sid: slave identifier.
+ *
+ * The Shutdown command causes the Slave to enter the SHUTDOWN state.
+ *
+ * Returns
+ * -EINVAL for invalid slave identifier.
+ * -EPERM if the SPMI transaction is denied due to permission issues.
+ * -EIO if the SPMI transaction fails (parity errors, etc).
+ * -ETIMEDOUT if the SPMI transaction times out.
+ */
+extern int spmi_command_shutdown(struct spmi_controller *ctrl, u8 sid);
+#endif
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 1a6f68f..e0a04dc 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -184,10 +184,10 @@
 	_IOW(MSM_CAM_IOCTL_MAGIC, 51, uint32_t *)
 
 #define MSM_CAM_IOCTL_GET_MCTL_INFO \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 51, struct msm_mctl_node_info *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_mctl_node_info *)
 
 #define MSM_CAM_IOCTL_MCTL_DIVERT_DONE \
-	_IOR(MSM_CAM_IOCTL_MAGIC, 52, struct msm_cam_evt_divert_frame *)
+	_IOR(MSM_CAM_IOCTL_MAGIC, 53, struct msm_cam_evt_divert_frame *)
 
 struct msm_mctl_pp_cmd {
 	int32_t  id;
@@ -765,8 +765,16 @@
 #define CFG_GET_OUTPUT_INFO		32
 #define CFG_GET_EEPROM_DATA		33
 #define CFG_SET_ACTUATOR_INFO		34
-#define CFG_GET_ACTUATOR_INFO		35
-#define CFG_MAX			36
+#define CFG_GET_ACTUATOR_INFO           35
+/* TBD: QRD */
+#define CFG_SET_SATURATION            36
+#define CFG_SET_SHARPNESS             37
+#define CFG_SET_TOUCHAEC              38
+#define CFG_SET_AUTO_FOCUS            39
+#define CFG_SET_AUTOFLASH             40
+#define CFG_SET_EXPOSURE_COMPENSATION 41
+#define CFG_SET_ISO                   42
+#define CFG_MAX			43
 
 
 #define MOVE_NEAR	0
@@ -857,14 +865,6 @@
 #define CAMERA_SETAE_AVERAGE		0
 #define CAMERA_SETAE_CENWEIGHT	1
 
-#define CFG_SET_SATURATION		30
-#define CFG_SET_SHARPNESS			31
-#define CFG_SET_TOUCHAEC            32
-#define CFG_SET_AUTO_FOCUS          33
-#define CFG_SET_AUTOFLASH 34
-/* QRD */
-#define CFG_SET_EXPOSURE_COMPENSATION 35
-
 #define  CAMERA_WB_AUTO               1 /* This list must match aeecamera.h */
 #define  CAMERA_WB_CUSTOM             2
 #define  CAMERA_WB_INCANDESCENT       3
@@ -948,6 +948,14 @@
 	MSM_V4L2_POWER_LINE_AUTO,
 };
 
+#define CAMERA_ISO_TYPE_AUTO           0
+#define CAMEAR_ISO_TYPE_HJR            1
+#define CAMEAR_ISO_TYPE_100            2
+#define CAMERA_ISO_TYPE_200            3
+#define CAMERA_ISO_TYPE_400            4
+#define CAMEAR_ISO_TYPE_800            5
+#define CAMERA_ISO_TYPE_1600           6
+
 struct sensor_pict_fps {
 	uint16_t prevfps;
 	uint16_t pictfps;
@@ -1083,6 +1091,7 @@
 		uint16_t pictp_pl;
 		uint32_t pict_max_exp_lc;
 		uint16_t p_fps;
+		uint8_t iso_type;
 		struct sensor_init_cfg init_info;
 		struct sensor_pict_fps gfps;
 		struct exp_gain_cfg exp_gain;
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 36139ba..34a21bd 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -590,7 +590,8 @@
 	IRIS_EVT_NEW_SRCH_LIST,
 	IRIS_EVT_NEW_AF_LIST,
 	IRIS_EVT_TXRDSDAT,
-	IRIS_EVT_TXRDSDONE
+	IRIS_EVT_TXRDSDONE,
+	IRIS_EVT_RADIO_DISABLED
 };
 enum emphasis_type {
 	FM_RX_EMP75 = 0x0,
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8e66a25..164d3b4 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -931,7 +931,7 @@
 	if (conn->sec_level == BT_SECURITY_SDP)
 		conn->sec_level = BT_SECURITY_LOW;
 
-	if (conn->pending_sec_level > conn->sec_level)
+	if (!status && encrypt && conn->pending_sec_level > conn->sec_level)
 		conn->sec_level = conn->pending_sec_level;
 
 	hci_proto_encrypt_cfm(conn, status, encrypt);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 312de3f..d5c4189 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -489,6 +489,7 @@
 	__u8		fixed_channel;
 	__u8		num_conf_req;
 	__u8		num_conf_rsp;
+	__u8		incoming;
 
 	__u8		fcs;
 	__u8		sec_level;
@@ -648,6 +649,8 @@
 #define L2CAP_AMP_STATE_RESEGMENT		12
 
 #define L2CAP_ATT_ERROR				0x01
+#define L2CAP_ATT_MTU_REQ			0x02
+#define L2CAP_ATT_MTU_RSP			0x03
 #define L2CAP_ATT_RESPONSE_BIT			0x01
 #define L2CAP_ATT_INDICATE			0x1D
 #define L2CAP_ATT_NOT_SUPPORTED			0x06
@@ -689,6 +692,8 @@
 void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
+struct sock *l2cap_find_sock_by_fixed_cid_and_dir(__le16 cid, bdaddr_t *src,
+						bdaddr_t *dst, int server);
 void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err);
 void l2cap_chan_del(struct sock *sk, int err);
 int l2cap_do_connect(struct sock *sk);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 47bfde5..4c2bd37 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -561,6 +561,19 @@
 		goto done;
 	}
 
+	if (!skb_queue_empty(&hdev->cmd_q)) {
+		BT_ERR("command queue is not empty, purging");
+		skb_queue_purge(&hdev->cmd_q);
+	}
+	if (!skb_queue_empty(&hdev->rx_q)) {
+		BT_ERR("rx queue is not empty, purging");
+		skb_queue_purge(&hdev->rx_q);
+	}
+	if (!skb_queue_empty(&hdev->raw_q)) {
+		BT_ERR("raw queue is not empty, purging");
+		skb_queue_purge(&hdev->raw_q);
+	}
+
 	if (!test_bit(HCI_RAW, &hdev->flags)) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		set_bit(HCI_INIT, &hdev->flags);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b4dde4c..9662795 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -930,18 +930,24 @@
 }
 
 /* Find socket with fixed cid with given source and destination bdaddrs.
- * Returns closest match, locked.
+ * Direction of the req/rsp must match.
  */
-static struct sock *l2cap_get_sock_by_fixed_scid(int state,
-				__le16 cid, bdaddr_t *src, bdaddr_t *dst)
+struct sock *l2cap_find_sock_by_fixed_cid_and_dir(__le16 cid, bdaddr_t *src,
+						bdaddr_t *dst, int incoming)
 {
 	struct sock *sk = NULL, *sk1 = NULL;
 	struct hlist_node *node;
 
+	BT_DBG(" %d", incoming);
+
 	read_lock(&l2cap_sk_list.lock);
 
 	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		if (state && sk->sk_state != state)
+
+		if (incoming && !l2cap_pi(sk)->incoming)
+			continue;
+
+		if (!incoming && l2cap_pi(sk)->incoming)
 			continue;
 
 		if (l2cap_pi(sk)->scid == cid && !bacmp(&bt_sk(sk)->dst, dst)) {
@@ -1022,13 +1028,12 @@
 	l2cap_sock_init(sk, parent);
 	bacpy(&bt_sk(sk)->src, conn->src);
 	bacpy(&bt_sk(sk)->dst, conn->dst);
+	l2cap_pi(sk)->incoming = 1;
 
 	bt_accept_enqueue(parent, sk);
 
 	__l2cap_chan_add(conn, sk);
 
-	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-
 	sk->sk_state = BT_CONNECTED;
 	parent->sk_data_ready(parent, 0);
 
@@ -1061,10 +1066,10 @@
 				if (pending_sec > sec_level)
 					sec_level = pending_sec;
 
-				if (smp_conn_security(conn, sec_level)) {
+				if (smp_conn_security(conn, sec_level))
 					l2cap_chan_ready(sk);
-					hci_conn_put(conn->hcon);
-				}
+
+				hci_conn_put(conn->hcon);
 
 			} else if (sk->sk_type != SOCK_SEQPACKET &&
 					sk->sk_type != SOCK_STREAM) {
@@ -1081,6 +1086,9 @@
 	}
 
 	read_unlock(&l->lock);
+
+	if (conn->hcon->out && conn->hcon->type == LE_LINK)
+		l2cap_le_conn_ready(conn);
 }
 
 /* Notify sockets that we cannot guaranty reliability anymore */
@@ -3035,7 +3043,8 @@
 {
 	lock_sock(sk);
 
-	if (l2cap_pi(sk)->mode != L2CAP_MODE_ERTM) {
+	if (l2cap_pi(sk)->mode != L2CAP_MODE_ERTM ||
+			sk->sk_state != BT_CONNECTED) {
 		release_sock(sk);
 		return;
 	}
@@ -7209,15 +7218,24 @@
 	return 0;
 }
 
-static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
+static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid,
+							struct sk_buff *skb)
 {
 	struct sock *sk;
 	struct sk_buff *skb_rsp;
 	struct l2cap_hdr *lh;
+	int dir;
+	u8 mtu_rsp[] = {L2CAP_ATT_MTU_RSP, 23, 0};
 	u8 err_rsp[] = {L2CAP_ATT_ERROR, 0x00, 0x00, 0x00,
 						L2CAP_ATT_NOT_SUPPORTED};
 
-	sk = l2cap_get_sock_by_fixed_scid(0, cid, conn->src, conn->dst);
+	dir = (skb->data[0] & L2CAP_ATT_RESPONSE_BIT) ? 0 : 1;
+
+	sk = l2cap_find_sock_by_fixed_cid_and_dir(cid, conn->src,
+							conn->dst, dir);
+
+	BT_DBG("sk %p, dir:%d", sk, dir);
+
 	if (!sk)
 		goto drop;
 
@@ -7231,6 +7249,22 @@
 	if (l2cap_pi(sk)->imtu < skb->len)
 		goto drop;
 
+	if (skb->data[0] == L2CAP_ATT_MTU_REQ) {
+		skb_rsp = bt_skb_alloc(sizeof(mtu_rsp) + L2CAP_HDR_SIZE,
+								GFP_ATOMIC);
+		if (!skb_rsp)
+			goto drop;
+
+		lh = (struct l2cap_hdr *) skb_put(skb_rsp, L2CAP_HDR_SIZE);
+		lh->len = cpu_to_le16(sizeof(mtu_rsp));
+		lh->cid = cpu_to_le16(L2CAP_CID_LE_DATA);
+		memcpy(skb_put(skb_rsp, sizeof(mtu_rsp)), mtu_rsp,
+							sizeof(mtu_rsp));
+		hci_send_acl(conn->hcon, NULL, skb_rsp, 0);
+
+		goto free_skb;
+	}
+
 	if (!sock_queue_rcv_skb(sk, skb))
 		goto done;
 
@@ -7333,7 +7367,7 @@
 	struct hlist_node *node;
 
 	if (type != ACL_LINK)
-		return -EINVAL;
+		return 0;
 
 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
@@ -7424,6 +7458,7 @@
 	struct l2cap_chan_list *l;
 	struct l2cap_conn *conn = hcon->l2cap_data;
 	struct sock *sk;
+	int smp = 0;
 
 	if (!conn)
 		return 0;
@@ -7445,9 +7480,7 @@
 				l2cap_chan_ready(sk);
 			}
 
-			del_timer(&hcon->smp_timer);
-			smp_link_encrypt_cmplt(conn, status, encrypt);
-
+			smp = 1;
 			bh_unlock_sock(sk);
 			continue;
 		}
@@ -7511,6 +7544,11 @@
 
 	read_unlock(&l->lock);
 
+	if (smp) {
+		del_timer(&hcon->smp_timer);
+		smp_link_encrypt_cmplt(conn, status, encrypt);
+	}
+
 	return 0;
 }
 
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 94cacde..6a4a2f0 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -611,8 +611,16 @@
 		case L2CAP_MODE_BASIC:
 			l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
 			break;
-		case L2CAP_MODE_ERTM:
 		case L2CAP_MODE_STREAMING:
+			if (!disable_ertm) {
+				/* No fallback to ERTM or Basic mode */
+				l2cap_pi(sk)->conf_state |=
+						L2CAP_CONF_STATE2_DEVICE;
+				break;
+			}
+			err = -EINVAL;
+			break;
+		case L2CAP_MODE_ERTM:
 			if (!disable_ertm)
 				break;
 			/* fall through */
@@ -957,7 +965,8 @@
 	else
 		err = bt_sock_recvmsg(iocb, sock, msg, len, flags);
 
-	l2cap_ertm_recv_done(sk);
+	if (err >= 0)
+		l2cap_ertm_recv_done(sk);
 
 	return err;
 }
@@ -1096,6 +1105,7 @@
 static int l2cap_sock_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
+	struct sock *srv_sk = NULL;
 	int err;
 
 	BT_DBG("sock %p, sk %p", sock, sk);
@@ -1103,6 +1113,16 @@
 	if (!sk)
 		return 0;
 
+	/* If this is an ATT Client socket, find the matching Server */
+	if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA && !l2cap_pi(sk)->incoming)
+		srv_sk = l2cap_find_sock_by_fixed_cid_and_dir(L2CAP_CID_LE_DATA,
+					&bt_sk(sk)->src, &bt_sk(sk)->dst, 1);
+
+	/* If server socket found, request tear down */
+	BT_DBG("client:%p server:%p", sk, srv_sk);
+	if (srv_sk)
+		l2cap_sock_set_timer(srv_sk, 1);
+
 	err = l2cap_sock_shutdown(sock, 2);
 
 	sock_orphan(sk);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 2e4c47a..910ef77 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -762,7 +762,7 @@
 	struct list_head *p;
 	size_t name_len;
 
-	name_len = strlen(hdev->dev_name);
+	name_len = strnlen(hdev->dev_name, HCI_MAX_EIR_LENGTH);
 
 	if (name_len > 0) {
 		/* EIR Data type */
@@ -890,13 +890,17 @@
 
 	list_add(&uuid->list, &hdev->uuids);
 
-	err = update_class(hdev);
-	if (err < 0)
-		goto failed;
+	if (test_bit(HCI_UP, &hdev->flags)) {
 
-	err = update_eir(hdev);
-	if (err < 0)
-		goto failed;
+		err = update_class(hdev);
+		if (err < 0)
+			goto failed;
+
+		err = update_eir(hdev);
+		if (err < 0)
+			goto failed;
+	} else
+		err = 0;
 
 	err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
 
@@ -950,13 +954,16 @@
 		goto unlock;
 	}
 
-	err = update_class(hdev);
-	if (err < 0)
-		goto unlock;
+	if (test_bit(HCI_UP, &hdev->flags)) {
+		err = update_class(hdev);
+		if (err < 0)
+			goto unlock;
 
-	err = update_eir(hdev);
-	if (err < 0)
-		goto unlock;
+		err = update_eir(hdev);
+		if (err < 0)
+			goto unlock;
+	} else
+		err = 0;
 
 	err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
 
@@ -991,7 +998,10 @@
 	hdev->major_class |= cp->major & MGMT_MAJOR_CLASS_MASK;
 	hdev->minor_class = cp->minor;
 
-	err = update_class(hdev);
+	if (test_bit(HCI_UP, &hdev->flags))
+		err = update_class(hdev);
+	else
+		err = 0;
 
 	if (err == 0)
 		err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
@@ -1027,9 +1037,12 @@
 		err = 0;
 	} else {
 		clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
-		err = update_class(hdev);
-		if (err == 0)
-			err = update_eir(hdev);
+		if (test_bit(HCI_UP, &hdev->flags)) {
+			err = update_class(hdev);
+			if (err == 0)
+				err = update_eir(hdev);
+		} else
+			err = 0;
 	}
 
 	if (err == 0)
@@ -1514,6 +1527,7 @@
 	}
 
 	pairing_complete(cmd, status);
+	hci_conn_put(conn);
 }
 
 static void pairing_security_complete_cb(struct hci_conn *conn, u8 status)
@@ -1936,12 +1950,14 @@
 	if (hdev->disco_state != SCAN_IDLE) {
 		struct hci_cp_le_set_scan_enable le_cp = {0, 0};
 
-		if (hdev->disco_state == SCAN_LE)
-			hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
+		if (test_bit(HCI_UP, &hdev->flags)) {
+			if (hdev->disco_state == SCAN_LE)
+				hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
 							sizeof(le_cp), &le_cp);
-		else
-			hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
-
+			else
+				hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0,
+									 NULL);
+		}
 		hdev->disco_state = SCAN_IDLE;
 	}
 
@@ -1969,18 +1985,20 @@
 
 	hci_dev_lock_bh(hdev);
 
-	if (hdev->disco_state == SCAN_LE)
-		hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
-				sizeof(le_cp), &le_cp);
+	if (test_bit(HCI_UP, &hdev->flags)) {
+		if (hdev->disco_state == SCAN_LE)
+			hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
+					sizeof(le_cp), &le_cp);
 
 	/* re-start BR scan */
-	if (hdev->disco_state != SCAN_IDLE) {
-		struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
-		hdev->disco_int_phase *= 2;
-		hdev->disco_int_count = 0;
-		cp.num_rsp = (u8) hdev->disco_int_phase;
-		hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
-		hdev->disco_state = SCAN_BR;
+		if (hdev->disco_state != SCAN_IDLE) {
+			struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
+			hdev->disco_int_phase *= 2;
+			hdev->disco_int_count = 0;
+			cp.num_rsp = (u8) hdev->disco_int_phase;
+			hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
+			hdev->disco_state = SCAN_BR;
+		}
 	}
 
 	hci_dev_unlock_bh(hdev);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 3b1e54c..99c4559 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -917,7 +917,7 @@
 	int lm = 0;
 
 	if (type != SCO_LINK && type != ESCO_LINK)
-		return -EINVAL;
+		return 0;
 
 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index e301edf..2484a9a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -652,6 +652,7 @@
 static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
 {
 	struct key_master_id *master;
+	u8 sec_level;
 	u8 zerobuf[8];
 
 	if (!hcon || !key || !key->data)
@@ -666,6 +667,17 @@
 
 	hcon->enc_key_size = key->pin_len;
 	hcon->sec_req = TRUE;
+	sec_level = authreq_to_seclevel(key->auth);
+
+	BT_DBG("cur %d, req: %d", hcon->sec_level, sec_level);
+
+	if (sec_level > hcon->sec_level)
+		hcon->pending_sec_level = sec_level;
+
+
+	if (!(hcon->link_mode & HCI_LM_ENCRYPT))
+		hci_conn_hold(hcon);
+
 	hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
 
 	return 0;
@@ -690,11 +702,6 @@
 		if (smp_encrypt_link(hcon, key) < 0)
 			goto invalid_key;
 
-		hcon->sec_level = authreq_to_seclevel(key->auth);
-
-		if (!(hcon->link_mode & HCI_LM_ENCRYPT))
-			hci_conn_hold(hcon);
-
 		return 0;
 	}
 
@@ -729,33 +736,26 @@
 	struct hci_conn *hcon = conn->hcon;
 	__u8 authreq;
 
-	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
+	BT_DBG("conn %p hcon %p %d req: %d",
+			conn, hcon, hcon->sec_level, sec_level);
 
-	if (IS_ERR(hcon->hdev->tfm)) {
-		BT_DBG("IS_ERR");
+	if (IS_ERR(hcon->hdev->tfm))
 		return 1;
-	}
 
-	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
-		BT_DBG("HCI_CONN_ENCRYPT_PEND");
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
 		return -EINPROGRESS;
-	}
 
-	if (sec_level == BT_SECURITY_LOW) {
-		BT_DBG("BT_SECURITY_LOW");
+	if (sec_level == BT_SECURITY_LOW)
 		return 1;
-	}
 
-	if (hcon->sec_level > sec_level) {
-		BT_DBG("hcon->sec_level > sec_level");
+
+	if (hcon->sec_level >= sec_level)
 		return 1;
-	}
 
 	authreq = seclevel_to_authreq(sec_level);
 
-	BT_ERR("conn = %p, sec: %d", conn, sec_level);
 	hcon->smp_conn = conn;
-	hcon->sec_level = sec_level;
+	hcon->pending_sec_level = sec_level;
 
 	if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
 		struct link_key *key;
@@ -785,6 +785,7 @@
 					msecs_to_jiffies(SMP_TIMEOUT));
 
 		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+		hci_conn_hold(hcon);
 	} else {
 		struct smp_cmd_security_req cp;
 		cp.auth_req = authreq;
@@ -792,7 +793,6 @@
 	}
 
 done:
-	hcon->pending_sec_level = sec_level;
 	set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 
 	return 0;
@@ -1045,15 +1045,17 @@
 
 	clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 
+	if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
+		hcon->sec_level = hcon->pending_sec_level;
+
 	if (!status && encrypt && !hcon->sec_req)
-		smp_distribute_keys(conn, 0);
+		return smp_distribute_keys(conn, 0);
 
 	/* Fall back to Pairing request if failed a Link Security request */
 	else if (hcon->sec_req  && (status || !encrypt))
-		smp_conn_security(conn, hcon->sec_level);
+		smp_conn_security(conn, hcon->pending_sec_level);
 
-	else
-		hci_conn_put(hcon);
+	hci_conn_put(hcon);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index ac7f050..46f6461 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -49,7 +49,8 @@
 
 #define AIF1_PB 1
 #define AIF1_CAP 2
-#define NUM_CODEC_DAIS 2
+#define AIF2_PB 3
+#define NUM_CODEC_DAIS 3
 
 struct tabla_codec_dai_data {
 	u32 rate;
@@ -570,6 +571,8 @@
 		-84, 40, digital_gain),
 	SOC_SINGLE_S8_TLV("RX6 Digital Volume", TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
 		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX7 Digital Volume", TABLA_A_CDC_RX7_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
 
 	SOC_SINGLE_S8_TLV("DEC1 Volume", TABLA_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
 		digital_gain),
@@ -2086,71 +2089,99 @@
 	{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX1 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX1 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX3 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX3 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX4 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX4 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX5 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX5 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX6 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX6 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX7 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX7 MIX1 INP2", "IIR1", "IIR1"},
 
 	/* Decimator Inputs */
@@ -2633,7 +2664,7 @@
 	}
 	pr_debug("%s: DAI-ID %x %d %d\n", __func__, dai->id, tx_num, rx_num);
 
-	if (dai->id == AIF1_PB) {
+	if (dai->id == AIF1_PB || dai->id == AIF2_PB) {
 		for (i = 0; i < rx_num; i++) {
 			tabla->dai[dai->id - 1].ch_num[i]  = rx_slot[i];
 			tabla->dai[dai->id - 1].ch_act = 0;
@@ -2681,6 +2712,12 @@
 			tx_slot[cnt] = tx_ch[6 + cnt];
 			cnt++;
 		}
+	} else if (dai->id == AIF2_PB) {
+		*rx_num = tabla_dai[dai->id - 1].playback.channels_max;
+		while (cnt < *rx_num) {
+			rx_slot[cnt] = rx_ch[5 + cnt];
+			cnt++;
+		}
 	}
 	return 0;
 }
@@ -2778,7 +2815,7 @@
 	 * If current dai is a rx dai, set sample rate to
 	 * all the rx paths that are currently not active
 	 */
-	if (dai->id == AIF1_PB) {
+	if (dai->id == AIF1_PB || dai->id == AIF2_PB) {
 
 		rx_state = snd_soc_read(codec,
 			TABLA_A_CDC_CLK_RX_B1_CTL);
@@ -2858,6 +2895,20 @@
 		},
 		.ops = &tabla_dai_ops,
 	},
+	{
+		.name = "tabla_rx2",
+		.id = AIF2_PB,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.rates = WCD9310_RATES,
+			.formats = TABLA_FORMATS,
+			.rate_min = 8000,
+			.rate_max = 48000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &tabla_dai_ops,
+	},
 };
 
 static struct snd_soc_dai_driver tabla_i2s_dai[] = {
@@ -2963,7 +3014,8 @@
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
-			if (tabla_dai[j].id == AIF1_PB)
+			if (tabla_dai[j].id == AIF1_PB ||
+				tabla_dai[j].id == AIF2_PB)
 				continue;
 			if (!strncmp(w->sname,
 				tabla_dai[j].capture.stream_name, 13)) {
@@ -2979,7 +3031,8 @@
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
-			if (tabla_dai[j].id == AIF1_PB)
+			if (tabla_dai[j].id == AIF1_PB ||
+				tabla_dai[j].id == AIF2_PB)
 				continue;
 			if (!strncmp(w->sname,
 				tabla_dai[j].capture.stream_name, 13)) {
@@ -3022,6 +3075,13 @@
 	SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
 
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX6", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+				0, tabla_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("SLIM RX7", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+				0, tabla_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
 	/* Headphone */
 	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
 	SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
@@ -3789,19 +3849,15 @@
 	struct tabla_mbhc_general_cfg *generic;
 	struct tabla_mbhc_btn_detect_cfg *btn_det;
 	int n;
-	u8 tabla_ver;
 	u8 *n_cic, *gain;
+	struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
 
 	tabla = snd_soc_codec_get_drvdata(codec);
 	generic = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
 	btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
 
-	tabla_ver = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
-	tabla_ver &= 0x1F;
-
 	for (n = 0; n < 8; n++) {
-		if ((tabla_ver != TABLA_VERSION_1_0 &&
-		     tabla_ver != TABLA_VERSION_1_1) || n != 7) {
+		if ((!TABLA_IS_1_X(tabla_core->version)) || n != 7) {
 			snd_soc_update_bits(codec,
 					    TABLA_A_CDC_MBHC_FEATURE_B1_CFG,
 					    0x07, n);
@@ -5043,6 +5099,9 @@
 		case AIF1_CAP:
 			ch_cnt = tabla_dai[i].capture.channels_max;
 			break;
+		case AIF2_PB:
+			ch_cnt = tabla_dai[i].playback.channels_max;
+			break;
 		default:
 			continue;
 		}
@@ -5197,13 +5256,32 @@
 	},
 };
 
+static struct platform_driver tabla1x_codec_driver = {
+	.probe = tabla_probe,
+	.remove = tabla_remove,
+	.driver = {
+		.name = "tabla1x_codec",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &tabla_pm_ops,
+#endif
+	},
+};
+
 static int __init tabla_codec_init(void)
 {
-	return platform_driver_register(&tabla_codec_driver);
+	int rtn = platform_driver_register(&tabla_codec_driver);
+	if (rtn == 0) {
+		rtn = platform_driver_register(&tabla1x_codec_driver);
+		if (rtn != 0)
+			platform_driver_unregister(&tabla_codec_driver);
+	}
+	return rtn;
 }
 
 static void __exit tabla_codec_exit(void)
 {
+	platform_driver_unregister(&tabla1x_codec_driver);
 	platform_driver_unregister(&tabla_codec_driver);
 }
 
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 1b3014e..6f2d651 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -56,7 +56,7 @@
 
 obj-$(CONFIG_SND_SOC_MSM_QDSP6_INTF) += qdsp6/
 
-snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o msm-dai-stub.o
 obj-$(CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO) += msm-dai-q6-hdmi.o
 obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o
 snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index b515090..bcf6784 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -310,7 +310,6 @@
 		if (clk_users != 1)
 			return 0;
 
-		codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
 		if (codec_clk) {
 			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
 			clk_enable(codec_clk);
@@ -329,7 +328,6 @@
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
 			clk_disable(codec_clk);
-			clk_put(codec_clk);
 			tabla_mclk_enable(codec, 0);
 		}
 	}
@@ -350,7 +348,6 @@
 		if (clk_users != 1)
 			return 0;
 
-		codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
 		if (codec_clk) {
 			clk_set_rate(codec_clk, 12288000);
 			clk_enable(codec_clk);
@@ -376,7 +373,6 @@
 					__func__, clk_users);
 
 			clk_disable(codec_clk);
-			clk_put(codec_clk);
 			tabla_mclk_enable(w->codec, 0);
 		}
 		break;
@@ -736,8 +732,9 @@
 	int err;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
-	pr_debug("%s()\n", __func__);
+	pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
 
 	/*if (machine_is_msm_liquid()) {
 		top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
@@ -779,6 +776,8 @@
 		return err;
 	}
 
+	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+
 	tabla_hs_detect(codec, &hs_jack, &button_jack, tabla_mbhc_cal,
 			TABLA_MICBIAS2, msm_enable_codec_ext_clk, 0,
 			TABLA_EXT_CLK_RATE);
@@ -865,6 +864,23 @@
 	return 0;
 }
 
+static int msm_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+			channels->min, channels->max);
+
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
 static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -1084,6 +1100,17 @@
 		.platform_name  = "msm-pcm-afe",
 		.ignore_suspend = 1,
 	},
+	{
+		.name = "Voice Stub",
+		.stream_name = "Voice Stub",
+		.cpu_dai_name = "VOICE_STUB",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* .be_id = do not care */
+	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
@@ -1160,14 +1187,14 @@
 	{
 		.name = LPASS_BE_HDMI,
 		.stream_name = "HDMI Playback",
-		.cpu_dai_name = "msm-dai-q6.8",
+		.cpu_dai_name = "msm-dai-q6-hdmi.8",
 		.platform_name = "msm-pcm-routing",
 		.codec_name     = "msm-stub-codec.1",
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.no_codec = 1,
 		.be_id = MSM_BACKEND_DAI_HDMI_RX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_hdmi_be_hw_params_fixup,
 	},
 	/* Backend AFE DAI Links */
 	{
@@ -1216,6 +1243,30 @@
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
 	},
+	{
+		.name = LPASS_BE_STUB_RX,
+		.stream_name = "Stub Playback",
+		.cpu_dai_name = "msm-dai-stub",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tabla_codec",
+		.codec_dai_name = "tabla_rx2",
+		.no_pcm = 1,
+		/* .be_id = do not care */
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm_be_ops,
+	},
+	{
+		.name = LPASS_BE_STUB_TX,
+		.stream_name = "Stub Capture",
+		.cpu_dai_name = "msm-dai-stub",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tabla_codec",
+		.codec_dai_name = "tabla_tx1",
+		.no_pcm = 1,
+		/* .be_id = do not care */
+		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm_be_ops,
+	},
 };
 
 struct snd_soc_card snd_soc_card_msm = {
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 8f71e83..14d9adf 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -271,6 +271,28 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "AUXPCM_HOSTLESS",
 	},
+	{
+		.playback = {
+			.stream_name = "Voice Stub Playback",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 48000,
+		},
+		.capture = {
+			.stream_name = "Voice Stub Capture",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "VOICE_STUB",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index aff87ae..f23a6a0 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -618,7 +618,7 @@
 	 * data to the cpu driver, since cpu drive is unaware of any
 	 * boarc specific configuration.
 	 */
-	pcm_clk = clk_get(NULL, auxpcm_pdata->clk);
+	pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
 	if (IS_ERR(pcm_clk)) {
 		pr_err("%s: could not get pcm_clk\n", __func__);
 		return PTR_ERR(pcm_clk);
diff --git a/sound/soc/msm/msm-dai-stub.c b/sound/soc/msm/msm-dai-stub.c
new file mode 100644
index 0000000..b2bfa2c
--- /dev/null
+++ b/sound/soc/msm/msm-dai-stub.c
@@ -0,0 +1,102 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+static int msm_dai_stub_set_channel_map(struct snd_soc_dai *dai,
+		unsigned int tx_num, unsigned int *tx_slot,
+		unsigned int rx_num, unsigned int *rx_slot)
+{
+	pr_debug("%s:\n", __func__);
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops msm_dai_stub_ops = {
+	.set_channel_map = msm_dai_stub_set_channel_map,
+};
+
+static struct snd_soc_dai_driver msm_dai_stub_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+			SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.capture = {
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+			SNDRV_PCM_RATE_16000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &msm_dai_stub_ops,
+};
+
+static __devinit int msm_dai_stub_dev_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
+
+	rc = snd_soc_register_dai(&pdev->dev, &msm_dai_stub_dai);
+
+	return rc;
+}
+
+static __devexit int msm_dai_stub_dev_remove(struct platform_device *pdev)
+{
+	pr_debug("%s:\n", __func__);
+
+	snd_soc_unregister_dai(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver msm_dai_stub_driver = {
+	.probe  = msm_dai_stub_dev_probe,
+	.remove = msm_dai_stub_dev_remove,
+	.driver = {
+		.name = "msm-dai-stub",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_dai_stub_init(void)
+{
+	pr_debug("%s:\n", __func__);
+
+	return platform_driver_register(&msm_dai_stub_driver);
+}
+module_init(msm_dai_stub_init);
+
+static void __exit msm_dai_stub_exit(void)
+{
+	pr_debug("%s:\n", __func__);
+
+	platform_driver_unregister(&msm_dai_stub_driver);
+}
+module_exit(msm_dai_stub_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MSM Stub DSP DAI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 0a29016..83fd691 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -99,6 +99,8 @@
 			break;
 		} else
 			atomic_set(&prtd->pending_buffer, 0);
+		if (runtime->status->hw_ptr >= runtime->control->appl_ptr)
+			break;
 		pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
 				__func__, prtd->pcm_count);
 
@@ -134,6 +136,9 @@
 		case ASM_SESSION_CMD_RUN: {
 			if (!atomic_read(&prtd->pending_buffer))
 				break;
+			if (runtime->status->hw_ptr >=
+				runtime->control->appl_ptr)
+				break;
 			pr_debug("%s:writing %d bytes"
 				" of buffer to dsp\n",
 				__func__, prtd->pcm_count);
@@ -340,8 +345,26 @@
 	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct msm_audio *prtd = runtime->private_data;
 	int dir = 0;
+	int rc = 0;
 
-	pr_debug("%s\n", __func__);
+	/*
+	If routing is still enabled, we need to issue EOS to
+	the DSP
+	To issue EOS to dsp, we need to be run state otherwise
+	EOS is not honored.
+	*/
+	if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id)) {
+		rc = q6asm_run(prtd->audio_client, 0, 0, 0);
+		atomic_set(&prtd->pending_buffer, 0);
+		prtd->cmd_ack = 0;
+		q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+		pr_debug("%s\n", __func__);
+		rc = wait_event_timeout(the_locks.eos_wait,
+			prtd->cmd_ack, 5 * HZ);
+		if (rc < 0)
+			pr_err("EOS cmd timeout\n");
+		prtd->pcm_irq_pos = 0;
+	}
 
 	dir = IN;
 	atomic_set(&prtd->pending_buffer, 0);
@@ -462,6 +485,7 @@
 
 	switch (cmd) {
 	case SNDRV_PCM_IOCTL1_RESET:
+		prtd->cmd_ack = 0;
 		rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
 		if (rc < 0)
 			pr_err("%s: flush cmd failed rc=%d\n", __func__, rc);
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 8b6b5f1..b01c22c 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -46,6 +46,7 @@
 static struct mutex routing_lock;
 
 static int fm_switch_enable;
+
 #define INT_FM_RX_VOL_MAX_STEPS 100
 #define INT_FM_RX_VOL_GAIN 2000
 
@@ -1229,6 +1230,11 @@
 				0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("VOICE_STUB_UL", "VOICE_STUB Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("STUB_RX", "Stub Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("STUB_TX", "Stub Capture", 0, 0, 0, 0),
+
 	/* Switch Definitions */
 	SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
 				&fm_switch_mixer_controls),
@@ -1432,6 +1438,8 @@
 	{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
+	{"STUB_RX", NULL, "VOICE_STUB_DL"},
+	{"VOICE_STUB_UL", NULL, "STUB_TX"},
 };
 
 static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
@@ -1636,6 +1644,23 @@
 	.remove = __devexit_p(msm_routing_pcm_remove),
 };
 
+int msm_routing_check_backend_enabled(int fedai_id)
+{
+	int i;
+	if (fedai_id >= MSM_FRONTEND_DAI_MM_MAX_ID) {
+		/* bad ID assigned in machine driver */
+		pr_err("%s: bad MM ID\n", __func__);
+		return 0;
+	}
+	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+		if ((test_bit(fedai_id,
+			&msm_bedais[i].fe_sessions))) {
+			return msm_bedais[i].active;
+		}
+	}
+	return 0;
+}
+
 static int __init msm_soc_routing_platform_init(void)
 {
 	mutex_init(&routing_lock);
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 25efb58..9515ab3 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -32,6 +32,8 @@
 #define LPASS_BE_SEC_I2S_RX "(Backend) SECONDARY_I2S_RX"
 
 #define LPASS_BE_MI2S_RX "(Backend) MI2S_RX"
+#define LPASS_BE_STUB_RX "(Backend) STUB_RX"
+#define LPASS_BE_STUB_TX "(Backend) STUB_TX"
 
 /* For multimedia front-ends, asm session is allocated dynamically.
  * Hence, asm session/multimedia front-end mapping has to be maintained.
@@ -85,4 +87,6 @@
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
 
 int lpa_set_volume(unsigned volume);
+
+int msm_routing_check_backend_enabled(int fedai_id);
 #endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index bedfd68..eb363e7 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -309,7 +309,6 @@
 		if (clk_users != 1)
 			return 0;
 
-		codec_clk = clk_get(NULL, "i2s_spkr_osr_clk");
 		if (codec_clk) {
 			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
 			clk_enable(codec_clk);
@@ -328,7 +327,6 @@
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
 			clk_disable(codec_clk);
-			clk_put(codec_clk);
 			tabla_mclk_enable(codec, 0);
 		}
 	}
@@ -708,8 +706,9 @@
 	int err;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
-	pr_debug("%s()\n", __func__);
+	pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
 
 	if (machine_is_msm8960_liquid()) {
 		top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
@@ -752,6 +751,8 @@
 		return err;
 	}
 
+	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+
 	tabla_hs_detect(codec, &hs_jack, &button_jack, tabla_mbhc_cal,
 			TABLA_MICBIAS2, msm8960_enable_codec_ext_clk, 0,
 			TABLA_EXT_CLK_RATE);
@@ -984,7 +985,7 @@
 };
 
 /* Digital audio interface glue - connects codec <---> CPU */
-static struct snd_soc_dai_link msm8960_dai[] = {
+static struct snd_soc_dai_link msm8960_dai_common[] = {
 	/* FrontEnd DAI Links */
 	{
 		.name = "MSM8960 Media1",
@@ -1105,32 +1106,6 @@
 		.no_codec = 1,
 		.ignore_suspend = 1,
 	},
-	/* Backend DAI Links */
-	{
-		.name = LPASS_BE_SLIMBUS_0_RX,
-		.stream_name = "Slimbus Playback",
-		.cpu_dai_name = "msm-dai-q6.16384",
-		.platform_name = "msm-pcm-routing",
-		.codec_name     = "tabla_codec",
-		.codec_dai_name	= "tabla_rx1",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
-		.init = &msm8960_audrx_init,
-		.be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
-		.ops = &msm8960_be_ops,
-	},
-	{
-		.name = LPASS_BE_SLIMBUS_0_TX,
-		.stream_name = "Slimbus Capture",
-		.cpu_dai_name = "msm-dai-q6.16385",
-		.platform_name = "msm-pcm-routing",
-		.codec_name     = "tabla_codec",
-		.codec_dai_name	= "tabla_tx1",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
-		.be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
-		.ops = &msm8960_be_ops,
-	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
@@ -1278,13 +1253,88 @@
 	},
 };
 
-struct snd_soc_card snd_soc_card_msm8960 = {
-	.name		= "msm8960-snd-card",
-	.dai_link	= msm8960_dai,
-	.num_links	= ARRAY_SIZE(msm8960_dai),
+static struct snd_soc_dai_link msm8960_dai_delta_tabla1x[] = {
+	/* Backend DAI Links */
+	{
+		.name = LPASS_BE_SLIMBUS_0_RX,
+		.stream_name = "Slimbus Playback",
+		.cpu_dai_name = "msm-dai-q6.16384",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "tabla1x_codec",
+		.codec_dai_name	= "tabla_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+		.init = &msm8960_audrx_init,
+		.be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8960_be_ops,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_0_TX,
+		.stream_name = "Slimbus Capture",
+		.cpu_dai_name = "msm-dai-q6.16385",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "tabla1x_codec",
+		.codec_dai_name	= "tabla_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+		.be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8960_be_ops,
+	},
+};
+
+
+static struct snd_soc_dai_link msm8960_dai_delta_tabla2x[] = {
+	/* Backend DAI Links */
+	{
+		.name = LPASS_BE_SLIMBUS_0_RX,
+		.stream_name = "Slimbus Playback",
+		.cpu_dai_name = "msm-dai-q6.16384",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "tabla_codec",
+		.codec_dai_name	= "tabla_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+		.init = &msm8960_audrx_init,
+		.be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8960_be_ops,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_0_TX,
+		.stream_name = "Slimbus Capture",
+		.cpu_dai_name = "msm-dai-q6.16385",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "tabla_codec",
+		.codec_dai_name	= "tabla_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+		.be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8960_be_ops,
+	},
+};
+
+static struct snd_soc_dai_link msm8960_tabla1x_dai[
+					 ARRAY_SIZE(msm8960_dai_common) +
+					 ARRAY_SIZE(msm8960_dai_delta_tabla1x)];
+
+
+static struct snd_soc_dai_link msm8960_dai[
+					 ARRAY_SIZE(msm8960_dai_common) +
+					 ARRAY_SIZE(msm8960_dai_delta_tabla2x)];
+
+static struct snd_soc_card snd_soc_tabla1x_card_msm8960 = {
+		.name		= "msm8960-tabla1x-snd-card",
+		.dai_link	= msm8960_tabla1x_dai,
+		.num_links	= ARRAY_SIZE(msm8960_tabla1x_dai),
+};
+
+static struct snd_soc_card snd_soc_card_msm8960 = {
+		.name		= "msm8960-snd-card",
+		.dai_link	= msm8960_dai,
+		.num_links	= ARRAY_SIZE(msm8960_dai),
 };
 
 static struct platform_device *msm8960_snd_device;
+static struct platform_device *msm8960_snd_tabla1x_device;
 
 static int msm8960_configure_headset_mic_gpios(void)
 {
@@ -1359,6 +1409,10 @@
 		return -ENOMEM;
 	}
 
+	memcpy(msm8960_dai, msm8960_dai_common, sizeof(msm8960_dai_common));
+	memcpy(msm8960_dai + ARRAY_SIZE(msm8960_dai_common),
+		msm8960_dai_delta_tabla2x, sizeof(msm8960_dai_delta_tabla2x));
+
 	platform_set_drvdata(msm8960_snd_device, &snd_soc_card_msm8960);
 	ret = platform_device_add(msm8960_snd_device);
 	if (ret) {
@@ -1367,6 +1421,27 @@
 		return ret;
 	}
 
+	msm8960_snd_tabla1x_device = platform_device_alloc("soc-audio", 1);
+	if (!msm8960_snd_tabla1x_device) {
+		pr_err("Platform device allocation failed\n");
+		kfree(tabla_mbhc_cal);
+		return -ENOMEM;
+	}
+
+	memcpy(msm8960_tabla1x_dai, msm8960_dai_common,
+		sizeof(msm8960_dai_common));
+	memcpy(msm8960_tabla1x_dai + ARRAY_SIZE(msm8960_dai_common),
+		msm8960_dai_delta_tabla1x, sizeof(msm8960_dai_delta_tabla1x));
+
+	platform_set_drvdata(msm8960_snd_tabla1x_device,
+		&snd_soc_tabla1x_card_msm8960);
+	ret = platform_device_add(msm8960_snd_tabla1x_device);
+	if (ret) {
+		platform_device_put(msm8960_snd_tabla1x_device);
+		kfree(tabla_mbhc_cal);
+		return ret;
+	}
+
 	if (msm8960_configure_headset_mic_gpios()) {
 		pr_err("%s Fail to configure headset mic gpios\n", __func__);
 		msm8960_headset_gpios_configured = 0;
@@ -1386,6 +1461,7 @@
 	}
 	msm8960_free_headset_mic_gpios();
 	platform_device_unregister(msm8960_snd_device);
+	platform_device_unregister(msm8960_snd_tabla1x_device);
 	kfree(tabla_mbhc_cal);
 }
 module_exit(msm8960_audio_exit);