Merge "arm/dt: msm8610: Disable MPP 2 and MPP 3 to avoid duplicate ownership"
diff --git a/Documentation/ata/ahci_msm.txt b/Documentation/ata/ahci_msm.txt
new file mode 100644
index 0000000..2f84834
--- /dev/null
+++ b/Documentation/ata/ahci_msm.txt
@@ -0,0 +1,322 @@
+Introduction
+============
+The SATA Host Controller developed for Qualcomm SoC is used
+to facilitate SATA storage devices that connect to SoC through a
+standard SATA cable interface. The MSM Advanced Host Controller
+Interface (AHCI) driver interfaces with the generic Linux AHCI driver
+and communicates with the AHCI controller for data movement between
+system memory and SATA devices (persistent storage).
+
+Hardware description
+====================
+Serial Advanced Technology Attachment (SATA) is a communication
+protocol designed to transfer data between a computer and storage
+devices (Hard Disk Drive(HDD), Solid State Drives(SSD) etc.).
+First generation (Gen1) SATA interfaces communicate at a serial
+rate of 1.5Gb/s and use low-voltage differential signaling on
+serial links. With 8b-10b encoding, the effective data throughput
+for Gen1 interface is 150MB/s.
+
+The SATA host controller in Qualcomm chipsets adheres to the AHCI 1.3
+specification which describes the interface between system software
+and the host controller, as well as the functional behavior needed
+for software to communicate with the SATA host controller.
+
+The SATA PHY hardware macro in Qualcomm chipsets adheres to the
+SATA 3.0 specification with Gen1 serial interface. This is used to
+serialize and de-serialize data and communicates with SATA HDD. Also,
+the PHY can detect SATA HDD during hot swap and raise an interrupt to
+the CPU through AHCI controller to notify about the detection/removal.
+
+The following figure shows the SATA architecture block diagram as
+implemented in MSM chipsets.
+
+                        +---------+
+                        |SATA Disk|
+                        |  Drive  |
+                        +---------+
+                           ^   ^
+                        Tx |   | Rx
+                           v   v
++--------------+     +--------------+     +-----------+
+| System Memory|     |   SATA PHY   |     |    CPU    |
++--------------+     +--------------+     +-----------+
+      ^                 ^       ^           ^     ^
+      |                 |       |           |     |
+      |                 v       v           |     |
+      |            +------------------+(Interrupt)|
+      |            | SATA CONTROLLER  |-----+     |
+      |            +------------------+           |
+      |                 ^       ^                 |
+      |                 |       |                 |
+      v                 v       v                 v
+ <--------------------------------------------------------->
+<             System Fabric (Control and Data)              >
+ <--------------------------------------------------------->
+
+Some controller capabilities:
+- Supports 64-bit addressing
+- Supports native command queueing (upto 32 commands)
+- Supports First-party DMA to move data to and from system memory
+- ATA-7 command set compliant
+- Port multiplier support for some chipsets
+- Supports aggressive power management (partial, slumber modes)
+- Supports asynchronous notification
+
+Software description
+====================
+The SATA driver uses the generic interface to read/write data to
+the Hard Disk Drive (HDD). It uses following components in Linux
+to interface with the generic block layer which then interfaces
+with file system or user processes.
+
+1) AHCI platform Driver (includes MSM-specific glue driver)
+2) LIBAHCI
+3) LIBATA
+4) SCSI
+
+AHCI platform driver registers as a device driver for platform
+device registered during SoC board initialization. It is responsible
+for platform specific tasks like PHY configuration, clock initial-
+ization, claiming memory resources etc. Also, implements certain
+functionality that deviates from the standard specification.
+
+Library "LIBAHCI" implements software layer functionality described
+in the standard AHCI specification. It interfaces with the LIBATA
+framework to execute SATA the command set. It converts ATA task files
+into AHCI command descriptors and pass them to the controller for
+execution. It handles controller interrupts and sends command
+completion events to the upper layers. It implements a controller-
+specific reset and recover mechanism in case of errors. It implements
+link power management policies - partial, slumber modes, runtime power
+management and platform power management. It abstracts the low-level
+controller details from the LIBATA framework.
+
+"LIBATA" is a helper library for implementing ATA and SATA command
+protocol as described in standard ATA and SATA specifications. It
+builds read/write requests from SCSI commands and pass them to the
+low-level controller driver (LLD). It handshakes with the SATA
+device using standard commands to understand capabilities and carry
+out device configurations. It interfaces with the SCSI layer to manage
+underlying disks. It manages different devices connected to each host
+port using a port multiplier. Also, it manages the link PHY component,
+the interconnect interface and any external interface (cables, etc.)
+that follow the SATA electrical specification.
+
+The SCSI layer is a helper library for translating generic block layer
+commands to SCSI commands and pass them on to the LIBATA framework.
+Certain generic stuff like device scan, media change, and hot plug
+detection are handled. This layer handles all types of SCSI devices,
+and SATA storage devices are one class of SCSI devices. It also provides
+the IOCTL interface to manage disks from userspace.
+
+Following is the logical code flow:
+
+                        +------------------------+
+                        | File System (ext4 etc.)|
+                        +------------------------+
+                                   ^
+                                   |
+                                   v
+                        +------------------------+
+                        |  Generic Block Layer   |
+                        +------------------------+
+                                   ^
+                                   |
+                                   v
+                        +------------------------+
+                        |       SCSI Layer       |
+                        +------------------------+
+                                   ^
+                                   |
+                                   v
+                        +------------------------+
+                        |     LIBATA library     |
+                        +------------------------+
+                                   ^
+                                   |
+                                   v
+                        +------------------------+
+                        |     LIBAHCI library    |
+                        +------------------------+
+                                   ^
+                                   |
+                                   v
+                        +------------------------+
+                        | AHCI platform driver + |
+                        | MSM AHCI glue driver   |
+                        +------------------------+
+
+Design
+======
+The MSM AHCI driver acts as a glue driver for the Linux
+AHCI controller driver. It provides the following functionality:
+- Registers as a driver for msm_sata device which has an AHCI-compliant
+  controller and PHY as resources.
+- Registers an AHCI platform device in the probe function providing
+  ahci platform data
+- AHCI platform data consists of the following callbacks:
+	- init
+		o PHY resource acquisition
+		o Clock and voltage regulator initialization
+		o PHY calibration
+	- exit
+		o PHY power down
+		o Clock and voltage regulator turn off
+	- suspend
+	- resume
+		o Sequence described in the next section.
+- The Linux AHCI platform driver then probes the AHCI device and
+  initializes it according to the standard AHCI specification.
+- The SATA drive is detected as part of scsi_scan_host() called by
+  LIBAHCI after controller initialization.
+
+Power Management
+================
+Various power modes are supported by this driver.
+
+Platform suspend/resume:
+During suspend:
+- PHY analog blocks are powered down
+- Controller and PHY is kept in Power-on-Reset (POR) mode
+- Clocks and voltage regulators are gated
+
+During resume:
+- Clocks and voltage regulators are ungated
+- PHY is powered up and calibrated to functional mode
+- Controller is re-initialized to process commands.
+
+Runtime suspend/resume:
+- Execute the same steps as in platform suspend/resume.
+- Runtime suspend/resume is disabled by default due to regressions
+  in hot-plug detection (specification limitation). The users can
+  enable runtime power management with following shell commands.
+
+  # cd /sys/devices/platform/msm_sata.0/ahci.0/
+  # echo auto > ./power/control
+  # echo auto > ./ata1/power/control
+  # echo auto > ./ata1/host0/target0:0:0/0:0:0:0/power/control
+
+  Note: The device will be runtime-suspended only when user unmounts
+  all the partitions.
+
+Link power management (defined by AHCI 1.3 specification):
+- Automatic low power mode transition are supported.
+- AHCI supports two power modes: partial and slumber.
+- Software uses Inteface Communication Control (ICC) bits in AHCI
+  register space to enable automatic partial/slumber state.
+- Partial mode:
+	- Software asserts automatic partial mode when the use
+	  case demands low latency resume.
+	- Upon receiving partial mode signal, PHY disables byte clocks
+	  and re-enables them during resume and thus has low latency.
+- Slumber mode:
+	- Software asserts automatic slumber mode when the use
+	  case demands low power consumption and can withstand
+	  high resume latencies.
+	- Upon receiving slumber mode signal, PHY disables byte
+	  clocks and some internal circuitry. Upon resume PHY
+	  enables byte clocks and reacquires the PLL lock.
+- Once the software enables partial/slumber modes, the transitioning
+  into these modes are automatic and is handled by hardware without
+  software intervention while the controller is idle with no outstanding
+  commands to process.
+
+- The Linux AHCI link power management defines three modes:
+	- max_performance (default mode)
+	  Doesn't allow partial/slumber transition when host is idle.
+	- medium_power (Partial mode)
+	  Following shell commands are used to enable this mode:
+
+	  # cd /sys/devices/platform/msm_sata.0/ahci.0/
+	  # echo medium_power > ./ata1/host0/scsi_host/host0/link_power_management_policy
+
+	- min_power (Slumber mode)
+	  Following shell commands are used to enable this mode:
+
+	  # cd /sys/devices/platform/msm_sata.0/ahci.0/
+	  # echo min_power > ./ata1/host0/scsi_host/host0/link_power_management_policy
+
+SMP/multi-core
+==============
+The MSM AHCI driver hooks only init, exit, suspend, resume callbacks to
+the AHCI driver which are serialized by design and hence the driver, which
+is inherently SMP safe.
+
+Security
+========
+None.
+
+Performance
+===========
+The theoretical performance with Gen1 SATA PHY is 150MB/s (8b/10b encoding).
+The performance is dependent on various factors, mainly:
+- Capabilities of the external SATA hard disk connected to the MSM SATA port
+- Various system bus frequencies and system loads
+- System memory capabilities
+- Benchmark test applications that collect performance numbers
+
+One example of the maximum performance achieved in a specific system
+configuration follows:
+
+Benchmark: Iozone sequential performance
+Block size: 128K
+File size: 1GB
+Platform: APQ8064 V2 CDP
+CPU Governor: Performance
+
+SanDisk SSD (i100 64GB):
+Read - 135MB/s
+Write - 125MB/s
+
+Western Digital HDD (WD20EURS 2TB):
+Read - 121MB/s
+Write - 98MB/s
+
+Interface
+=========
+The MSM AHCI controller driver provides function pointers as the
+required interface to the Linux AHCI controller driver. The main
+routines implemented are init, exit, suspend, and resume for handling
+MSM-specific initialization, freeing of resources on exit, and
+MSM-specific power management tweaks during suspend power collapse.
+
+Driver parameters
+=================
+None.
+
+Config options
+==============
+Config option SATA_AHCI_MSM in drivers/ata/Kconfig enables this driver.
+
+Dependencies
+============
+The MSM AHCI controller driver is dependent on Linux AHCI driver,
+Linux ATA framework, Linux SCSI framework and Linux generic block layer.
+
+While configuring the kernel, the following options should be set:
+
+- CONFIG_BLOCK
+- CONFIG_SCSI
+- CONFIG_ATA
+- CONFIG_SATA_AHCI_PLATFORM
+
+User space utilities
+====================
+Any user space component that can mount a block device can be used to
+read/write data into persistent storage. However, at the time of this
+writing there are no utilities that author is aware of that can manage
+h/w from userspace.
+
+Other
+=====
+None.
+
+Known issues
+============
+None.
+
+To do
+=====
+- Device tree support.
+- MSM bus frequency voting support.
diff --git a/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt b/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt
index 7a15f6a..a77d435 100644
--- a/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt
+++ b/Documentation/devicetree/bindings/arm/msm/acpuclock/acpuclock-a7.txt
@@ -10,7 +10,6 @@
 - reg-names: name of the bases for the above registers. "rcg_base"
 	     is expected.
 - a7_cpu-supply: regulator to supply a7 cpu
-- a7_mem-supply: regulator to supply a7 l2 cache
 
 Example:
 	qcom,acpuclk@f9011050 {
@@ -18,5 +17,4 @@
 		reg = <0xf9011050 0x8>;
 		reg-names = "rcg_base";
 		a7_cpu-supply = <&pm8026_s2>;
-		a7_mem-supply = <&pm8026_l3>;
 	};
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index a3f3a06..9bc949e 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -112,6 +112,18 @@
 		      compression feature in the rotator.
 - qcom,mdss-has-decimation: Boolean property to indicate the presence of
 			    decimation feature in fetch.
+- qcom,mdss-ad-off:		Array of offset addresses for the available
+				Assertive Display (AD) blocks. These offsets
+				are calculated from the register "mdp_phys"
+				defined in reg property. The number of AD
+				offsets should be less than or equal to the
+				number of mixers driving interfaces defined in
+				property: qcom,mdss-mixer-intf-off. Assumes
+				that AD blocks are aligned with the mixer
+				offsets as well (i.e. the first mixer offset
+				corresponds to the same pathway as the first
+				AD offset).
+
 Optional subnodes:
 Child nodes representing the frame buffer virtual devices.
 
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index a221433..96d95da 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -4,7 +4,7 @@
 controlling LEDs that are part of PMIC on Qualcomm reference
 platforms. The PMIC is connected to Host processor via
 SPMI bus. This driver supports various LED modules such as
-WLED (white LED), RGB LED and flash LED.
+Keypad backlight, WLED (white LED), RGB LED and flash LED.
 
 Each LED module is represented as a node of "leds-qpnp". This
 node will further contain the type of LED supported and its
@@ -76,6 +76,18 @@
 - qcom,source-sel: select power source, default 1 (enabled)
 - qcom,mode-ctrl: select operation mode, default 0x60 = Mode Sink
 
+Keypad backlight is a backlight source for buttons. It supports four rows
+and the required rows are enabled by specifying values in the properties.
+
+Required properties for keypad backlight:
+- qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
+- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,pwm-us: time the pwm device will modulate at (us)
+- qcom,row-src-sel-val: select source for rows. One bit is used for each row.
+			Specify 0 for vph_pwr and 1 for vbst for each row.
+- qcom,row-scan-val: select rows for scanning
+- qcom,row-scan-en: row scan enable
+
 Example:
 
 	qcom,leds@a200 {
@@ -174,3 +186,18 @@
 			};
 	};
 
+	qcom,leds@e200 {
+		status = "okay";
+		qcom,kpdbl {
+			label = "kpdbl";
+			linux,name = "button-backlight";
+			qcom,mode = <0>;
+			qcom,pwm-channel = <8>;
+			qcom,pwm-us = <1000>;
+			qcom,id = <7>;
+			qcom,max-current = <20>;
+			qcom,row-src-sel-val = <0x00>;
+			qcom,row-scan-en = <0x01>;
+			qcom,row-scan-val = <0x01>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 2d20794..c3d929c 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -17,6 +17,7 @@
 - vdd_mx-supply:      Reference to the regulator that supplies the memory rail.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
 - qcom,gpio-err-fatal: GPIO used by the modem to indicate error fatal to the apps.
+- qcom,gpio-err-ready: GPIO used by the modem to indicate error ready to the apps.
 - qcom,gpio-proxy-unvote: GPIO used by the modem to trigger proxy unvoting in
   the apps.
 - qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
@@ -49,6 +50,7 @@
 
 		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
 		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
diff --git a/Documentation/devicetree/bindings/regulator/krait-regulator.txt b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
index aaa731e..6a02e86 100644
--- a/Documentation/devicetree/bindings/regulator/krait-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
@@ -13,6 +13,8 @@
 				register base
 - reg-names:			"apcs_gcc" -string to identify the area where
 				the APCS GCC registers reside.
+- qcom,pfm-threshold		The power coeff threshold in abstract power units below which
+				pmic will be made to operate in PFM mode.
 
 Optional properties:
 - qcom,use-phase-switching	indicates whether the driver should add/shed phases on the PMIC
@@ -51,6 +53,7 @@
 		reg-names = "apcs_gcc";
 		compatible = "qcom,krait-pdn";
 		qcom,use-phase-switching;
+		qcom,pfm-threshold = <376975>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 383e50d..9f6cb16 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -458,9 +458,12 @@
 - qcom,sec-auxpcm-gpio-din  : GPIO on which Secondary AUXPCM DIN signal is coming.
 - qcom,sec-auxpcm-gpio-dout : GPIO on which Secondary AUXPCM DOUT signal is coming.
 - qcom,us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
-
 Optional properties:
 - qcom,hdmi-audio-rx: specifies if HDMI audio support is enabled or not.
+- qcom,ext-ult-spk-amp-gpio : GPIO for enabling of speaker path amplifier.
+
+- qcom,ext-ult-lo-amp-gpio: GPIO to enable external ultrasound lineout
+			    amplifier.
 
 Example:
 
@@ -502,6 +505,7 @@
 	qcom,us-euro-gpios = <&pm8941_gpios 20 0>;
 
 	qcom,hdmi-audio-rx;
+	qcom,ext-ult-lo-amp-gpio = <&pm8941_gpios 6 0>;
 
 	qcom,prim-auxpcm-gpio-clk  = <&msmgpio 65 0>;
 	qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 6d06e99..de1577d 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -61,6 +61,9 @@
 	    Used for allowing USB to respond for remote wakup.
 - qcom,hsusb-otg-delay-lpm: If present then USB core will wait one second
 	after disconnect before entering low power mode.
+- qcom,hsusb-otg-delay-lpm-hndshk-on-disconnect: If present then USB core will
+	wait for the handshake with the IPA to complete before entering low
+	power mode.
 - <supply-name>-supply: handle to the regulator device tree node.
          Optional "supply-name" is "vbus_otg" to supply vbus in host mode.
 - qcom,vdd-voltage-level: This property must be a list of three integer
@@ -121,6 +124,8 @@
 - qcom,pool-64-bit-align: If present then the pool's memory will be aligned
   to 64 bits
 - qcom,enable_hbm: if present host bus manager is enabled.
+- qcom,disable-park-mode: if present park mode is enabled. Park mode enables executing
+  up to 3 usb packets from each QH.
 
 Example MSM HSUSB EHCI controller device node :
 	ehci: qcom,ehci-host@f9a55000 {
@@ -145,6 +150,8 @@
   update USB PID and serial numbers used by bootloader in DLOAD mode.
 - qcom,android-usb-swfi-latency : value to be used by device to vote
   for DMA latency in microsecs.
+- qcom,android-usb-cdrom : if this property is present then device creates
+  a new LUN as CD-ROM
 
 Example Android USB device node :
 	android_usb@fc42b0c8 {
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 5391734..282257c 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -45,6 +45,8 @@
 		bits 6-12  PARAMETER_OVERRIDE_B
 		bits 13-19 PARAMETER_OVERRIDE_C
 		bits 20-25 PARAMETER_OVERRIDE_D
+- qcom,skip-charger-detection: If present then charger detection using BC1.2
+  is not supported and attached host should always be assumed as SDP.
 
 Sub nodes:
 - Sub node for "DWC3- USB3 controller".
diff --git a/arch/arm/boot/dts/apq8084-regulator.dtsi b/arch/arm/boot/dts/apq8084-regulator.dtsi
new file mode 100644
index 0000000..00991b3
--- /dev/null
+++ b/arch/arm/boot/dts/apq8084-regulator.dtsi
@@ -0,0 +1,327 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/* QPNP controlled regulators: */
+
+&spmi_bus {
+	qcom,pma8084@1 {
+		pma8084_s1: regulator@1400 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		/* PMA8084 S2 + S12 = 2 phase VDD_CX supply */
+		pma8084_s2: regulator@1700 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		pma8084_s3: regulator@1a00 {
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		pma8084_s4: regulator@1d00 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		pma8084_s5: regulator@2000 {
+			regulator-min-microvolt = <2150000>;
+			regulator-max-microvolt = <2150000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		/* PMA8084 S6 + S7 = 2 phase VDD_GFX supply */
+		pma8084_s6: regulator@2300 {
+			regulator-min-microvolt = <815000>;
+			regulator-max-microvolt = <900000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		/* PMA8084 S8 + S9 + S10 + S11 = 4 phase VDD_APC supply */
+		pma8084_s8: regulator@2900 {
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1100000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		/* Output of PMA8084 L1 and L11 is tied together. */
+		pma8084_l1: regulator@4000 {
+			parent-supply = <&pma8084_s3>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <10000>;
+			status = "okay";
+		};
+
+		pma8084_l2: regulator@4100 {
+			parent-supply = <&pma8084_s3>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l3: regulator@4200 {
+			parent-supply = <&pma8084_s3>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l4: regulator@4300 {
+			parent-supply = <&pma8084_s3>;
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l6: regulator@4500 {
+			parent-supply = <&pma8084_s5>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l8: regulator@4700 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l9: regulator@4800 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l10: regulator@4900 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l12: regulator@4b00 {
+			parent-supply = <&pma8084_s5>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l13: regulator@4c00 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l14: regulator@4d00 {
+			parent-supply = <&pma8084_s5>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l15: regulator@4e00 {
+			parent-supply = <&pma8084_s5>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l16: regulator@4f00 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l17: regulator@5000 {
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l18: regulator@5100 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l19: regulator@5200 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l20: regulator@5300 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l21: regulator@5400 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l22: regulator@5500 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l23: regulator@5600 {
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l24: regulator@5700 {
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3075000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l25: regulator@5800 {
+			regulator-min-microvolt = <2100000>;
+			regulator-max-microvolt = <2100000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l26: regulator@5900 {
+			parent-supply = <&pma8084_s5>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l27: regulator@5a00 {
+			parent-supply = <&pma8084_s3>;
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_lvs1: regulator@8000 {
+			parent-supply = <&pma8084_s4>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_lvs2: regulator@8100 {
+			parent-supply = <&pma8084_s4>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_lvs3: regulator@8200 {
+			parent-supply = <&pma8084_s4>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_lvs4: regulator@8300 {
+			parent-supply = <&pma8084_s4>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_mvs1: regulator@8400 {
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+	};
+};
+
diff --git a/arch/arm/boot/dts/apq8084-sim.dts b/arch/arm/boot/dts/apq8084-sim.dts
index cb16c07..ebcca1b 100644
--- a/arch/arm/boot/dts/apq8084-sim.dts
+++ b/arch/arm/boot/dts/apq8084-sim.dts
@@ -27,3 +27,145 @@
 		status = "ok";
 	};
 };
+
+&sdcc1 {
+	qcom,vdd-always-on;
+	qcom,vdd-lpm-sup;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <800 500000>;
+
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <250 154000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
+	qcom,sup-voltages = <2950 2950>;
+	qcom,nonremovable;
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+
+	status = "ok";
+};
+
+&sdcc2 {
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <9000 800000>;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <6 22000>;
+	qcom,vdd-io-lpm-sup;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
+	qcom,sup-voltages = <2950 2950>;
+	qcom,xpc;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+	qcom,current-limit = <800>;
+
+	status = "ok";
+};
+
+&pma8084_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+
+	gpio@c400 { /* GPIO 5 */
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+};
+
+&pma8084_mpps {
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+	};
+
+	mpp@a500 { /* MPP 6 */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&usb3 {
+	qcom,skip-charger-detection;
+};
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index c2e5ef4..95b1c8f 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -83,4 +83,81 @@
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
 	};
 
+	sdcc1: qcom,sdcc@f9824000 {
+		cell-index = <1>; /* SDC1 eMMC slot */
+		compatible = "qcom,msm-sdcc";
+		reg = <0xf9824000 0x800>;
+		reg-names = "core_mem";
+		interrupts = <0 123 0>;
+		interrupt-names = "core_irq";
+
+		qcom,bus-width = <8>;
+		status = "disabled";
+	};
+
+	sdcc2: qcom,sdcc@f98a4000 {
+		cell-index = <2>; /* SDC2 SD card slot */
+		compatible = "qcom,msm-sdcc";
+		reg = <0xf98a4000 0x800>;
+		reg-names = "core_mem";
+		interrupts = <0 125 0>;
+		interrupt-names = "core_irq";
+
+
+		qcom,bus-width = <4>;
+		status = "disabled";
+	};
+
+	spmi_bus: qcom,spmi@fc4c0000 {
+		cell-index = <0>;
+		compatible = "qcom,spmi-pmic-arb";
+		reg-names = "core", "intr", "cnfg";
+		reg = <0xfc4cf000 0x1000>,
+		      <0Xfc4cb000 0x1000>,
+		      <0Xfc4ca000 0x1000>;
+		/* 190,ee0_krait_hlos_spmi_periph_irq */
+		/* 187,channel_0_krait_hlos_trans_done_irq */
+		interrupts = <0 190 0>, <0 187 0>;
+		qcom,not-wakeup;
+		qcom,pmic-arb-ee = <0>;
+		qcom,pmic-arb-channel = <0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+	};
+
+	usb3: qcom,ssusb@f9200000 {
+		compatible = "qcom,dwc-usb3-msm";
+		reg = <0xf9200000 0xfc000>,
+			 <0xfd4ab000 0x4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		interrupts = <0 133 0>;
+		interrupt-names = "hs_phy_irq";
+		ssusb_vdd_dig-supply = <&pma8084_s1>;
+		SSUSB_1p8-supply = <&pma8084_l6>;
+		hsusb_vdd_dig-supply = <&pma8084_s1>;
+		HSUSB_1p8-supply = <&pma8084_l6>;
+		HSUSB_3p3-supply = <&pma8084_l24>;
+		qcom,dwc-usb3-msm-dbm-eps = <4>;
+		qcom,vdd-voltage-level = <0 900000 1050000>;
+
+		dwc3@f9200000 {
+			compatible = "synopsys,dwc3";
+			reg = <0xf9200000 0xfc000>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 131 0>, <0 179 0>;
+			interrupt-names = "irq", "otg_irq";
+			tx-fifo-resize;
+		};
+	};
+
+	android_usb {
+		compatible = "qcom,android-usb";
+	};
 };
+
+/include/ "msm-pma8084.dtsi"
+/include/ "apq8084-regulator.dtsi"
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
new file mode 100644
index 0000000..7942567
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
@@ -0,0 +1,530 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	qcom,mdss_dsi_nt35590_720p_cmd {
+		compatible = "qcom,mdss-dsi-panel";
+		label = "nt35590 720p command mode dsi panel";
+		status = "disable";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 25 0>;
+		qcom,te-gpio = <&msmgpio 24 0>;
+		qcom,mdss-pan-res = <720 1280>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-bl-levels = <1 4095>;
+		qcom,mdss-pan-dsi-mode = <1>;
+		qcom,mdss-vsync-enable = <1>;
+		qcom,mdss-hw-vsync-mode = <1>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <2>;
+		qcom,mdss-pan-dsi-dst-format = <8>;
+		qcom,mdss-pan-insert-dcs-cmd = <1>;
+		qcom,mdss-pan-wr-mem-continue = <0x3c>;
+		qcom,mdss-pan-wr-mem-start = <0x2c>;
+		qcom,mdss-pan-te-sel = <1>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x2c 0x20>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
+						    20 00 01];
+		qcom,panel-phy-timingSettings = [7d 25 1d 00 37 33
+						    22 27 1e 03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
+					   00 00];
+		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
+					     00 00 00 00 05 00 00 01 97 /* lane1 config */
+					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
+					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
+					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
+		qcom,panel-on-cmds = [29 01 00 00 00 02 FF EE
+					29 01 00 00 00 02 26 08
+					29 01 00 00 00 02 26 00
+					29 01 00 00 10 02 FF 00
+					29 01 00 00 00 02 BA 03
+					29 01 00 00 00 02 C2 08
+					29 01 00 00 00 02 FF 01
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 00 4A
+					29 01 00 00 00 02 01 33
+					29 01 00 00 00 02 02 53
+					29 01 00 00 00 02 03 55
+					29 01 00 00 00 02 04 55
+					29 01 00 00 00 02 05 33
+					29 01 00 00 00 02 06 22
+					29 01 00 00 00 02 08 56
+					29 01 00 00 00 02 09 8F
+					29 01 00 00 00 02 36 73
+					29 01 00 00 00 02 0B 9F
+					29 01 00 00 00 02 0C 9F
+					29 01 00 00 00 02 0D 2F
+					29 01 00 00 00 02 0E 24
+					29 01 00 00 00 02 11 83
+					29 01 00 00 00 02 12 03
+					29 01 00 00 00 02 71 2C
+					29 01 00 00 00 02 6F 03
+					29 01 00 00 00 02 0F 0A
+					29 01 00 00 00 02 FF 05
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 01 00
+					29 01 00 00 00 02 02 8B
+					29 01 00 00 00 02 03 82
+					29 01 00 00 00 02 04 82
+					29 01 00 00 00 02 05 30
+					29 01 00 00 00 02 06 33
+					29 01 00 00 00 02 07 01
+					29 01 00 00 00 02 08 00
+					29 01 00 00 00 02 09 46
+					29 01 00 00 00 02 0A 46
+					29 01 00 00 00 02 0D 0B
+					29 01 00 00 00 02 0E 1D
+					29 01 00 00 00 02 0F 08
+					29 01 00 00 00 02 10 53
+					29 01 00 00 00 02 11 00
+					29 01 00 00 00 02 12 00
+					29 01 00 00 00 02 14 01
+					29 01 00 00 00 02 15 00
+					29 01 00 00 00 02 16 05
+					29 01 00 00 00 02 17 00
+					29 01 00 00 00 02 19 7F
+					29 01 00 00 00 02 1A FF
+					29 01 00 00 00 02 1B 0F
+					29 01 00 00 00 02 1C 00
+					29 01 00 00 00 02 1D 00
+					29 01 00 00 00 02 1E 00
+					29 01 00 00 00 02 1F 07
+					29 01 00 00 00 02 20 00
+					29 01 00 00 00 02 21 06
+					29 01 00 00 00 02 22 55
+					29 01 00 00 00 02 23 4D
+					29 01 00 00 00 02 2D 02
+					29 01 00 00 00 02 28 01
+					29 01 00 00 00 02 2F 02
+					29 01 00 00 00 02 83 01
+					29 01 00 00 00 02 9E 58
+					29 01 00 00 00 02 9F 6A
+					29 01 00 00 00 02 A0 01
+					29 01 00 00 00 02 A2 10
+					29 01 00 00 00 02 BB 0A
+					29 01 00 00 00 02 BC 0A
+					29 01 00 00 00 02 32 08
+					29 01 00 00 00 02 33 B8
+					29 01 00 00 00 02 36 01
+					29 01 00 00 00 02 37 00
+					29 01 00 00 00 02 43 00
+					29 01 00 00 00 02 4B 21
+					29 01 00 00 00 02 4C 03
+					29 01 00 00 00 02 50 21
+					29 01 00 00 00 02 51 03
+					29 01 00 00 00 02 58 21
+					29 01 00 00 00 02 59 03
+					29 01 00 00 00 02 5D 21
+					29 01 00 00 00 02 5E 03
+					29 01 00 00 00 02 6C 00
+					29 01 00 00 00 02 6D 00
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 FF 01
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 75 00
+					29 01 00 00 00 02 76 7D
+					29 01 00 00 00 02 77 00
+					29 01 00 00 00 02 78 8A
+					29 01 00 00 00 02 79 00
+					29 01 00 00 00 02 7A 9C
+					29 01 00 00 00 02 7B 00
+					29 01 00 00 00 02 7C B1
+					29 01 00 00 00 02 7D 00
+					29 01 00 00 00 02 7E BF
+					29 01 00 00 00 02 7F 00
+					29 01 00 00 00 02 80 CF
+					29 01 00 00 00 02 81 00
+					29 01 00 00 00 02 82 DD
+					29 01 00 00 00 02 83 00
+					29 01 00 00 00 02 84 E8
+					29 01 00 00 00 02 85 00
+					29 01 00 00 00 02 86 F2
+					29 01 00 00 00 02 87 01
+					29 01 00 00 00 02 88 1F
+					29 01 00 00 00 02 89 01
+					29 01 00 00 00 02 8A 41
+					29 01 00 00 00 02 8B 01
+					29 01 00 00 00 02 8C 78
+					29 01 00 00 00 02 8D 01
+					29 01 00 00 00 02 8E A5
+					29 01 00 00 00 02 8F 01
+					29 01 00 00 00 02 90 EE
+					29 01 00 00 00 02 91 02
+					29 01 00 00 00 02 92 29
+					29 01 00 00 00 02 93 02
+					29 01 00 00 00 02 94 2A
+					29 01 00 00 00 02 95 02
+					29 01 00 00 00 02 96 5D
+					29 01 00 00 00 02 97 02
+					29 01 00 00 00 02 98 93
+					29 01 00 00 00 02 99 02
+					29 01 00 00 00 02 9A B8
+					29 01 00 00 00 02 9B 02
+					29 01 00 00 00 02 9C E7
+					29 01 00 00 00 02 9D 03
+					29 01 00 00 00 02 9E 07
+					29 01 00 00 00 02 9F 03
+					29 01 00 00 00 02 A0 37
+					29 01 00 00 00 02 A2 03
+					29 01 00 00 00 02 A3 46
+					29 01 00 00 00 02 A4 03
+					29 01 00 00 00 02 A5 56
+					29 01 00 00 00 02 A6 03
+					29 01 00 00 00 02 A7 66
+					29 01 00 00 00 02 A9 03
+					29 01 00 00 00 02 AA 7A
+					29 01 00 00 00 02 AB 03
+					29 01 00 00 00 02 AC 93
+					29 01 00 00 00 02 AD 03
+					29 01 00 00 00 02 AE A3
+					29 01 00 00 00 02 AF 03
+					29 01 00 00 00 02 B0 B4
+					29 01 00 00 00 02 B1 03
+					29 01 00 00 00 02 B2 CB
+					29 01 00 00 00 02 B3 00
+					29 01 00 00 00 02 B4 7D
+					29 01 00 00 00 02 B5 00
+					29 01 00 00 00 02 B6 8A
+					29 01 00 00 00 02 B7 00
+					29 01 00 00 00 02 B8 9C
+					29 01 00 00 00 02 B9 00
+					29 01 00 00 00 02 BA B1
+					29 01 00 00 00 02 BB 00
+					29 01 00 00 00 02 BC BF
+					29 01 00 00 00 02 BD 00
+					29 01 00 00 00 02 BE CF
+					29 01 00 00 00 02 BF 00
+					29 01 00 00 00 02 C0 DD
+					29 01 00 00 00 02 C1 00
+					29 01 00 00 00 02 C2 E8
+					29 01 00 00 00 02 C3 00
+					29 01 00 00 00 02 C4 F2
+					29 01 00 00 00 02 C5 01
+					29 01 00 00 00 02 C6 1F
+					29 01 00 00 00 02 C7 01
+					29 01 00 00 00 02 C8 41
+					29 01 00 00 00 02 C9 01
+					29 01 00 00 00 02 CA 78
+					29 01 00 00 00 02 CB 01
+					29 01 00 00 00 02 CC A5
+					29 01 00 00 00 02 CD 01
+					29 01 00 00 00 02 CE EE
+					29 01 00 00 00 02 CF 02
+					29 01 00 00 00 02 D0 29
+					29 01 00 00 00 02 D1 02
+					29 01 00 00 00 02 D2 2A
+					29 01 00 00 00 02 D3 02
+					29 01 00 00 00 02 D4 5D
+					29 01 00 00 00 02 D5 02
+					29 01 00 00 00 02 D6 93
+					29 01 00 00 00 02 D7 02
+					29 01 00 00 00 02 D8 B8
+					29 01 00 00 00 02 D9 02
+					29 01 00 00 00 02 DA E7
+					29 01 00 00 00 02 DB 03
+					29 01 00 00 00 02 DC 07
+					29 01 00 00 00 02 DD 03
+					29 01 00 00 00 02 DE 37
+					29 01 00 00 00 02 DF 03
+					29 01 00 00 00 02 E0 46
+					29 01 00 00 00 02 E1 03
+					29 01 00 00 00 02 E2 56
+					29 01 00 00 00 02 E3 03
+					29 01 00 00 00 02 E4 66
+					29 01 00 00 00 02 E5 03
+					29 01 00 00 00 02 E6 7A
+					29 01 00 00 00 02 E7 03
+					29 01 00 00 00 02 E8 93
+					29 01 00 00 00 02 E9 03
+					29 01 00 00 00 02 EA A3
+					29 01 00 00 00 02 EB 03
+					29 01 00 00 00 02 EC B4
+					29 01 00 00 00 02 ED 03
+					29 01 00 00 00 02 EE CB
+					29 01 00 00 00 02 EF 00
+					29 01 00 00 00 02 F0 ED
+					29 01 00 00 00 02 F1 00
+					29 01 00 00 00 02 F2 F3
+					29 01 00 00 00 02 F3 00
+					29 01 00 00 00 02 F4 FE
+					29 01 00 00 00 02 F5 01
+					29 01 00 00 00 02 F6 09
+					29 01 00 00 00 02 F7 01
+					29 01 00 00 00 02 F8 13
+					29 01 00 00 00 02 F9 01
+					29 01 00 00 00 02 FA 1D
+					29 01 00 00 00 02 FF 02
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 00 01
+					29 01 00 00 00 02 01 26
+					29 01 00 00 00 02 02 01
+					29 01 00 00 00 02 03 2F
+					29 01 00 00 00 02 04 01
+					29 01 00 00 00 02 05 37
+					29 01 00 00 00 02 06 01
+					29 01 00 00 00 02 07 56
+					29 01 00 00 00 02 08 01
+					29 01 00 00 00 02 09 70
+					29 01 00 00 00 02 0A 01
+					29 01 00 00 00 02 0B 9D
+					29 01 00 00 00 02 0C 01
+					29 01 00 00 00 02 0D C2
+					29 01 00 00 00 02 0E 01
+					29 01 00 00 00 02 0F FF
+					29 01 00 00 00 02 10 02
+					29 01 00 00 00 02 11 31
+					29 01 00 00 00 02 12 02
+					29 01 00 00 00 02 13 32
+					29 01 00 00 00 02 14 02
+					29 01 00 00 00 02 15 60
+					29 01 00 00 00 02 16 02
+					29 01 00 00 00 02 17 94
+					29 01 00 00 00 02 18 02
+					29 01 00 00 00 02 19 B5
+					29 01 00 00 00 02 1A 02
+					29 01 00 00 00 02 1B E3
+					29 01 00 00 00 02 1C 03
+					29 01 00 00 00 02 1D 03
+					29 01 00 00 00 02 1E 03
+					29 01 00 00 00 02 1F 2D
+					29 01 00 00 00 02 20 03
+					29 01 00 00 00 02 21 3A
+					29 01 00 00 00 02 22 03
+					29 01 00 00 00 02 23 48
+					29 01 00 00 00 02 24 03
+					29 01 00 00 00 02 25 57
+					29 01 00 00 00 02 26 03
+					29 01 00 00 00 02 27 68
+					29 01 00 00 00 02 28 03
+					29 01 00 00 00 02 29 7B
+					29 01 00 00 00 02 2A 03
+					29 01 00 00 00 02 2B 90
+					29 01 00 00 00 02 2D 03
+					29 01 00 00 00 02 2F A0
+					29 01 00 00 00 02 30 03
+					29 01 00 00 00 02 31 CB
+					29 01 00 00 00 02 32 00
+					29 01 00 00 00 02 33 ED
+					29 01 00 00 00 02 34 00
+					29 01 00 00 00 02 35 F3
+					29 01 00 00 00 02 36 00
+					29 01 00 00 00 02 37 FE
+					29 01 00 00 00 02 38 01
+					29 01 00 00 00 02 39 09
+					29 01 00 00 00 02 3A 01
+					29 01 00 00 00 02 3B 13
+					29 01 00 00 00 02 3D 01
+					29 01 00 00 00 02 3F 1D
+					29 01 00 00 00 02 40 01
+					29 01 00 00 00 02 41 26
+					29 01 00 00 00 02 42 01
+					29 01 00 00 00 02 43 2F
+					29 01 00 00 00 02 44 01
+					29 01 00 00 00 02 45 37
+					29 01 00 00 00 02 46 01
+					29 01 00 00 00 02 47 56
+					29 01 00 00 00 02 48 01
+					29 01 00 00 00 02 49 70
+					29 01 00 00 00 02 4A 01
+					29 01 00 00 00 02 4B 9D
+					29 01 00 00 00 02 4C 01
+					29 01 00 00 00 02 4D C2
+					29 01 00 00 00 02 4E 01
+					29 01 00 00 00 02 4F FF
+					29 01 00 00 00 02 50 02
+					29 01 00 00 00 02 51 31
+					29 01 00 00 00 02 52 02
+					29 01 00 00 00 02 53 32
+					29 01 00 00 00 02 54 02
+					29 01 00 00 00 02 55 60
+					29 01 00 00 00 02 56 02
+					29 01 00 00 00 02 58 94
+					29 01 00 00 00 02 59 02
+					29 01 00 00 00 02 5A B5
+					29 01 00 00 00 02 5B 02
+					29 01 00 00 00 02 5C E3
+					29 01 00 00 00 02 5D 03
+					29 01 00 00 00 02 5E 03
+					29 01 00 00 00 02 5F 03
+					29 01 00 00 00 02 60 2D
+					29 01 00 00 00 02 61 03
+					29 01 00 00 00 02 62 3A
+					29 01 00 00 00 02 63 03
+					29 01 00 00 00 02 64 48
+					29 01 00 00 00 02 65 03
+					29 01 00 00 00 02 66 57
+					29 01 00 00 00 02 67 03
+					29 01 00 00 00 02 68 68
+					29 01 00 00 00 02 69 03
+					29 01 00 00 00 02 6A 7B
+					29 01 00 00 00 02 6B 03
+					29 01 00 00 00 02 6C 90
+					29 01 00 00 00 02 6D 03
+					29 01 00 00 00 02 6E A0
+					29 01 00 00 00 02 6F 03
+					29 01 00 00 00 02 70 CB
+					29 01 00 00 00 02 71 00
+					29 01 00 00 00 02 72 19
+					29 01 00 00 00 02 73 00
+					29 01 00 00 00 02 74 36
+					29 01 00 00 00 02 75 00
+					29 01 00 00 00 02 76 55
+					29 01 00 00 00 02 77 00
+					29 01 00 00 00 02 78 70
+					29 01 00 00 00 02 79 00
+					29 01 00 00 00 02 7A 83
+					29 01 00 00 00 02 7B 00
+					29 01 00 00 00 02 7C 99
+					29 01 00 00 00 02 7D 00
+					29 01 00 00 00 02 7E A8
+					29 01 00 00 00 02 7F 00
+					29 01 00 00 00 02 80 B7
+					29 01 00 00 00 02 81 00
+					29 01 00 00 00 02 82 C5
+					29 01 00 00 00 02 83 00
+					29 01 00 00 00 02 84 F7
+					29 01 00 00 00 02 85 01
+					29 01 00 00 00 02 86 1E
+					29 01 00 00 00 02 87 01
+					29 01 00 00 00 02 88 60
+					29 01 00 00 00 02 89 01
+					29 01 00 00 00 02 8A 95
+					29 01 00 00 00 02 8B 01
+					29 01 00 00 00 02 8C E1
+					29 01 00 00 00 02 8D 02
+					29 01 00 00 00 02 8E 20
+					29 01 00 00 00 02 8F 02
+					29 01 00 00 00 02 90 23
+					29 01 00 00 00 02 91 02
+					29 01 00 00 00 02 92 59
+					29 01 00 00 00 02 93 02
+					29 01 00 00 00 02 94 94
+					29 01 00 00 00 02 95 02
+					29 01 00 00 00 02 96 B4
+					29 01 00 00 00 02 97 02
+					29 01 00 00 00 02 98 E1
+					29 01 00 00 00 02 99 03
+					29 01 00 00 00 02 9A 01
+					29 01 00 00 00 02 9B 03
+					29 01 00 00 00 02 9C 28
+					29 01 00 00 00 02 9D 03
+					29 01 00 00 00 02 9E 30
+					29 01 00 00 00 02 9F 03
+					29 01 00 00 00 02 A0 37
+					29 01 00 00 00 02 A2 03
+					29 01 00 00 00 02 A3 3B
+					29 01 00 00 00 02 A4 03
+					29 01 00 00 00 02 A5 40
+					29 01 00 00 00 02 A6 03
+					29 01 00 00 00 02 A7 50
+					29 01 00 00 00 02 A9 03
+					29 01 00 00 00 02 AA 6D
+					29 01 00 00 00 02 AB 03
+					29 01 00 00 00 02 AC 80
+					29 01 00 00 00 02 AD 03
+					29 01 00 00 00 02 AE CB
+					29 01 00 00 00 02 AF 00
+					29 01 00 00 00 02 B0 19
+					29 01 00 00 00 02 B1 00
+					29 01 00 00 00 02 B2 36
+					29 01 00 00 00 02 B3 00
+					29 01 00 00 00 02 B4 55
+					29 01 00 00 00 02 B5 00
+					29 01 00 00 00 02 B6 70
+					29 01 00 00 00 02 B7 00
+					29 01 00 00 00 02 B8 83
+					29 01 00 00 00 02 B9 00
+					29 01 00 00 00 02 BA 99
+					29 01 00 00 00 02 BB 00
+					29 01 00 00 00 02 BC A8
+					29 01 00 00 00 02 BD 00
+					29 01 00 00 00 02 BE B7
+					29 01 00 00 00 02 BF 00
+					29 01 00 00 00 02 C0 C5
+					29 01 00 00 00 02 C1 00
+					29 01 00 00 00 02 C2 F7
+					29 01 00 00 00 02 C3 01
+					29 01 00 00 00 02 C4 1E
+					29 01 00 00 00 02 C5 01
+					29 01 00 00 00 02 C6 60
+					29 01 00 00 00 02 C7 01
+					29 01 00 00 00 02 C8 95
+					29 01 00 00 00 02 C9 01
+					29 01 00 00 00 02 CA E1
+					29 01 00 00 00 02 CB 02
+					29 01 00 00 00 02 CC 20
+					29 01 00 00 00 02 CD 02
+					29 01 00 00 00 02 CE 23
+					29 01 00 00 00 02 CF 02
+					29 01 00 00 00 02 D0 59
+					29 01 00 00 00 02 D1 02
+					29 01 00 00 00 02 D2 94
+					29 01 00 00 00 02 D3 02
+					29 01 00 00 00 02 D4 B4
+					29 01 00 00 00 02 D5 02
+					29 01 00 00 00 02 D6 E1
+					29 01 00 00 00 02 D7 03
+					29 01 00 00 00 02 D8 01
+					29 01 00 00 00 02 D9 03
+					29 01 00 00 00 02 DA 28
+					29 01 00 00 00 02 DB 03
+					29 01 00 00 00 02 DC 30
+					29 01 00 00 00 02 DD 03
+					29 01 00 00 00 02 DE 37
+					29 01 00 00 00 02 DF 03
+					29 01 00 00 00 02 E0 3B
+					29 01 00 00 00 02 E1 03
+					29 01 00 00 00 02 E2 40
+					29 01 00 00 00 02 E3 03
+					29 01 00 00 00 02 E4 50
+					29 01 00 00 00 02 E5 03
+					29 01 00 00 00 02 E6 6D
+					29 01 00 00 00 02 E7 03
+					29 01 00 00 00 02 E8 80
+					29 01 00 00 00 02 E9 03
+					29 01 00 00 00 02 EA CB
+					29 01 00 00 00 02 FF 01
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 FF 02
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 FF 04
+					29 01 00 00 00 02 FB 01
+					29 01 00 00 00 02 FF 00
+					29 01 00 00 64 02 11 00
+					29 01 00 00 00 02 FF EE
+					29 01 00 00 00 02 12 50
+					29 01 00 00 00 02 13 02
+					29 01 00 00 00 02 6A 60
+					29 01 00 00 00 02 FF 00
+					29 01 00 00 78 02 29 00];
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+					05 01 00 00 78 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
new file mode 100644
index 0000000..a3718aa
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
@@ -0,0 +1,120 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	qcom,dsi_v2_truly_wvga_video {
+		compatible = "qcom,dsi-panel-v2";
+		label = "Truly WVGA video mode dsi panel";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 41 0>;
+		qcom,mode-selection-gpio = <&msmgpio 7 0>;
+		vdda-supply = <&pm8110_l19>;
+		vddio-supply=<&pm8110_l14>;
+		qcom,mdss-pan-res = <480 800>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <40 8 160 10 2 12>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-levels = <1 255>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-dsi-mode = <0>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <1>;
+		qcom,mdss-pan-dsi-dst-format = <3>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x0>;/*todo*/
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings =[09 08 05 00 20 03];
+		qcom,panel-phy-timingSettings = [5D 12 0C  00 33 38
+						 10 16 1E 03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [03 03 00 00 0f 00];
+		qcom,panel-phy-laneConfig =
+					[80 45 00 00 01 66 /*lane0**/
+					80 45 00 00 01 66 /*lane1*/
+					80 45 00 00 01 66 /*lane2*/
+					80 45 00 00 01 66 /*lane3*/
+					40 67 00 00 01 88]; /*Clk*/
+
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-on-cmds = [
+					05 01 00 00 01 02
+						01 00
+					23 01 00 00 01 02
+						b0 04
+					29 01 00 00 01 03
+						b3 02 00
+					23 01 00 00 01 02
+						bd 00
+					29 01 00 00 01 03
+						c0 18 66
+					29 01 00 00 01 10
+						c1 23 31 99 21 20 00 30 28 0c 0c
+						00 00 00 21 01
+					29 01 00 00 01 07
+						c2 10 06 06 01 03 00
+					29 01 00 00 01 19
+						c8 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 01 19
+						c9 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 01 19
+						ca 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 01 11
+						d0 29 03 ce a6 00 43 20 10 01 00
+						01 01 00 03 01 00
+					29 01 00 00 01 08
+						d1 18 0C 23 03 75 02 50
+					23 01 00 00 01 02
+						d3 11
+					29 01 00 00 01 03
+						d5 2a 2a
+					29 01 00 00 01 03
+						de 01 41
+					23 01 00 00 01 02
+						e6 51
+					23 01 00 00 01 02
+						fa 03
+					23 01 00 00 64 02
+						d6 28
+					39 01 00 00 01 05
+						2a 00 00 01 df
+					39 01 00 00 01 05
+						2b 00 00 03 1f
+					15 01 00 00 01 02
+						35 00
+					39 01 00 00 01 03
+						44 00 50
+					15 01 00 00 01 02
+						36 c1
+					15 01 00 00 01 02
+						3a 77
+					05 01 00 00 96 02
+						11 00
+					05 01 00 00 64 02
+						29 00
+					];
+		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+					05 01 00 00 78 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/mpq8092-regulator.dtsi b/arch/arm/boot/dts/mpq8092-regulator.dtsi
index b724a3d..e6866e5 100644
--- a/arch/arm/boot/dts/mpq8092-regulator.dtsi
+++ b/arch/arm/boot/dts/mpq8092-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,9 +15,9 @@
 
 &spmi_bus {
 
-	qcom,pm8644@1 {
+	qcom,pma8084@1 {
 
-		pm8644_s3: regulator@1a00 {
+		pma8084_s3: regulator@1a00 {
 			regulator-min-microvolt = <1350000>;
 			regulator-max-microvolt = <1350000>;
 			qcom,enable-time = <500>;
@@ -27,7 +27,7 @@
 			status = "okay";
 		};
 
-		pm8644_s4: regulator@1d00 {
+		pma8084_s4: regulator@1d00 {
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <500>;
@@ -37,7 +37,7 @@
 			status = "okay";
 		};
 
-		pm8644_s5: regulator@2000 {
+		pma8084_s5: regulator@2000 {
 			regulator-min-microvolt = <2150000>;
 			regulator-max-microvolt = <2150000>;
 			qcom,enable-time = <500>;
@@ -45,7 +45,7 @@
 			status = "okay";
 		};
 
-		pm8644_s6: regulator@2300 {
+		pma8084_s6: regulator@2300 {
 			regulator-min-microvolt = <900000>;
 			regulator-max-microvolt = <900000>;
 			qcom,enable-time = <500>;
@@ -53,7 +53,7 @@
 			status = "okay";
 		};
 
-		pm8644_s7: regulator@2600 {
+		pma8084_s7: regulator@2600 {
 			regulator-min-microvolt = <900000>;
 			regulator-max-microvolt = <900000>;
 			qcom,enable-time = <500>;
@@ -61,7 +61,7 @@
 			status = "okay";
 		};
 
-		pm8644_s8: regulator@2900 {
+		pma8084_s8: regulator@2900 {
 			regulator-min-microvolt = <900000>;
 			regulator-max-microvolt = <900000>;
 			qcom,enable-time = <500>;
@@ -69,8 +69,8 @@
 			status = "okay";
 		};
 
-		pm8644_l1: regulator@4000 {
-			parent-supply = <&pm8644_s3>;
+		pma8084_l1: regulator@4000 {
+			parent-supply = <&pma8084_s3>;
 			regulator-min-microvolt = <1225000>;
 			regulator-max-microvolt = <1225000>;
 			qcom,enable-time = <200>;
@@ -80,8 +80,8 @@
 			status = "okay";
 		};
 
-		pm8644_l2: regulator@4100 {
-			parent-supply = <&pm8644_s3>;
+		pma8084_l2: regulator@4100 {
+			parent-supply = <&pma8084_s3>;
 			regulator-min-microvolt = <900000>;
 			regulator-max-microvolt = <900000>;
 			qcom,enable-time = <200>;
@@ -89,8 +89,8 @@
 			status = "okay";
 		};
 
-		pm8644_l3: regulator@4200 {
-			parent-supply = <&pm8644_s3>;
+		pma8084_l3: regulator@4200 {
+			parent-supply = <&pma8084_s3>;
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
 			qcom,enable-time = <200>;
@@ -98,8 +98,8 @@
 			status = "okay";
 		};
 
-		pm8644_l4: regulator@4300 {
-			parent-supply = <&pm8644_s3>;
+		pma8084_l4: regulator@4300 {
+			parent-supply = <&pma8084_s3>;
 			regulator-min-microvolt = <1000000>;
 			regulator-max-microvolt = <1000000>;
 			qcom,enable-time = <200>;
@@ -107,8 +107,8 @@
 			status = "okay";
 		};
 
-		pm8644_l6: regulator@4500 {
-			parent-supply = <&pm8644_s5>;
+		pma8084_l6: regulator@4500 {
+			parent-supply = <&pma8084_s5>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <200>;
@@ -116,7 +116,7 @@
 			status = "okay";
 		};
 
-		pm8644_l8: regulator@4700 {
+		pma8084_l8: regulator@4700 {
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <200>;
@@ -124,7 +124,7 @@
 			status = "okay";
 		};
 
-		pm8644_l9: regulator@4800 {
+		pma8084_l9: regulator@4800 {
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
 			qcom,enable-time = <200>;
@@ -132,7 +132,7 @@
 			status = "okay";
 		};
 
-		pm8644_l10: regulator@4900 {
+		pma8084_l10: regulator@4900 {
 			regulator-min-microvolt = <2000000>;
 			regulator-max-microvolt = <2000000>;
 			qcom,enable-time = <200>;
@@ -140,8 +140,8 @@
 			status = "okay";
 		};
 
-		pm8644_l11: regulator@4a00 {
-			parent-supply = <&pm8644_s3>;
+		pma8084_l11: regulator@4a00 {
+			parent-supply = <&pma8084_s3>;
 			regulator-min-microvolt = <1300000>;
 			regulator-max-microvolt = <1300000>;
 			qcom,enable-time = <200>;
@@ -149,8 +149,8 @@
 			status = "okay";
 		};
 
-		pm8644_l12: regulator@4b00 {
-			parent-supply = <&pm8644_s5>;
+		pma8084_l12: regulator@4b00 {
+			parent-supply = <&pma8084_s5>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <200>;
@@ -158,7 +158,7 @@
 			status = "okay";
 		};
 
-		pm8644_l13: regulator@4c00 {
+		pma8084_l13: regulator@4c00 {
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
 			qcom,enable-time = <200>;
@@ -166,8 +166,8 @@
 			status = "okay";
 		};
 
-		pm8644_l14: regulator@4d00 {
-			parent-supply = <&pm8644_s5>;
+		pma8084_l14: regulator@4d00 {
+			parent-supply = <&pma8084_s5>;
 			regulator-min-microvolt = <1000000>;
 			regulator-max-microvolt = <1000000>;
 			qcom,enable-time = <200>;
@@ -175,8 +175,8 @@
 			status = "okay";
 		};
 
-		pm8644_l15: regulator@4e00 {
-			parent-supply = <&pm8644_s5>;
+		pma8084_l15: regulator@4e00 {
+			parent-supply = <&pma8084_s5>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <200>;
@@ -184,8 +184,8 @@
 			status = "okay";
 		};
 
-		pm8644_l16: regulator@4f00 {
-			parent-supply = <&pm8644_s4>;
+		pma8084_l16: regulator@4f00 {
+			parent-supply = <&pma8084_s4>;
 			regulator-min-microvolt = <750000>;
 			regulator-max-microvolt = <750000>;
 			qcom,enable-time = <200>;
@@ -193,7 +193,7 @@
 			status = "okay";
 		};
 
-		pm8644_l17: regulator@5000 {
+		pma8084_l17: regulator@5000 {
 			regulator-min-microvolt = <3150000>;
 			regulator-max-microvolt = <3150000>;
 			qcom,enable-time = <200>;
@@ -203,7 +203,7 @@
 			status = "okay";
 		};
 
-		pm8644_l18: regulator@5100 {
+		pma8084_l18: regulator@5100 {
 			regulator-min-microvolt = <2850000>;
 			regulator-max-microvolt = <2850000>;
 			qcom,enable-time = <200>;
@@ -211,8 +211,8 @@
 			status = "okay";
 		};
 
-		pm8644_l19: regulator@5200 {
-			parent-supply = <&pm8644_s4>;
+		pma8084_l19: regulator@5200 {
+			parent-supply = <&pma8084_s4>;
 			regulator-min-microvolt = <1500000>;
 			regulator-max-microvolt = <1500000>;
 			qcom,enable-time = <200>;
@@ -220,7 +220,7 @@
 			status = "okay";
 		};
 
-		pm8644_l20: regulator@5300 {
+		pma8084_l20: regulator@5300 {
 			regulator-min-microvolt = <2950000>;
 			regulator-max-microvolt = <2950000>;
 			qcom,enable-time = <200>;
@@ -228,7 +228,7 @@
 			status = "okay";
 		};
 
-		pm8644_l21: regulator@5400 {
+		pma8084_l21: regulator@5400 {
 			regulator-min-microvolt = <2950000>;
 			regulator-max-microvolt = <2950000>;
 			qcom,enable-time = <200>;
@@ -236,7 +236,7 @@
 			status = "okay";
 		};
 
-		pm8644_l22: regulator@5500 {
+		pma8084_l22: regulator@5500 {
 			regulator-min-microvolt = <2500000>;
 			regulator-max-microvolt = <2500000>;
 			qcom,enable-time = <200>;
@@ -244,7 +244,7 @@
 			status = "okay";
 		};
 
-		pm8644_l23: regulator@5600 {
+		pma8084_l23: regulator@5600 {
 			regulator-min-microvolt = <3000000>;
 			regulator-max-microvolt = <3000000>;
 			qcom,enable-time = <200>;
@@ -252,7 +252,7 @@
 			status = "okay";
 		};
 
-		pm8644_l24: regulator@5700 {
+		pma8084_l24: regulator@5700 {
 			regulator-min-microvolt = <3075000>;
 			regulator-max-microvolt = <3075000>;
 			qcom,enable-time = <200>;
@@ -260,27 +260,21 @@
 			status = "okay";
 		};
 
-		pm8644_lvs1: regulator@8000 {
-			parent-supply = <&pm8644_s4>;
+		pma8084_lvs1: regulator@8000 {
+			parent-supply = <&pma8084_s4>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
 		};
 
-		pm8644_lvs2: regulator@8100 {
-			parent-supply = <&pm8644_s4>;
+		pma8084_lvs2: regulator@8100 {
+			parent-supply = <&pma8084_s4>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
 		};
 
-		pm8644_mvs1: regulator@8200 {
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8644_mvs2: regulator@8300 {
+		pma8084_mvs1: regulator@8400 {
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
diff --git a/arch/arm/boot/dts/mpq8092-sim.dts b/arch/arm/boot/dts/mpq8092-sim.dts
index 0cbfa33..fc07c59 100644
--- a/arch/arm/boot/dts/mpq8092-sim.dts
+++ b/arch/arm/boot/dts/mpq8092-sim.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,7 +28,7 @@
 	};
 };
 
-&pm8644_gpios {
+&pma8084_gpios {
 	gpio@c000 { /* GPIO 1 */
 	};
 
@@ -94,72 +94,9 @@
 
 	gpio@d500 { /* GPIO 22 */
 	};
-
-	gpio@d600 { /* GPIO 23 */
-	};
-
-	gpio@d700 { /* GPIO 24 */
-	};
-
-	gpio@d800 { /* GPIO 25 */
-	};
-
-	gpio@d900 { /* GPIO 26 */
-	};
-
-	gpio@da00 { /* GPIO 27 */
-	};
-
-	gpio@db00 { /* GPIO 28 */
-	};
-
-	gpio@dc00 { /* GPIO 29 */
-	};
-
-	gpio@dd00 { /* GPIO 30 */
-	};
-
-	gpio@de00 { /* GPIO 31 */
-	};
-
-	gpio@df00 { /* GPIO 32 */
-	};
-
-	gpio@e000 { /* GPIO 33 */
-	};
-
-	gpio@e100 { /* GPIO 34 */
-	};
-
-	gpio@e200 { /* GPIO 35 */
-	};
-
-	gpio@e300 { /* GPIO 36 */
-	};
-
-	gpio@e400 { /* GPIO 37 */
-	};
-
-	gpio@e500 { /* GPIO 38 */
-	};
-
-	gpio@e600 { /* GPIO 39 */
-	};
-
-	gpio@e700 { /* GPIO 40 */
-	};
-
-	gpio@e800 { /* GPIO 41 */
-	};
-
-	gpio@e900 { /* GPIO 42 */
-	};
-
-	gpio@ea00 { /* GPIO 43 */
-	};
 };
 
-&pm8644_mpps {
+&pma8084_mpps {
 	mpp@a000 { /* MPP 1 */
 	};
 
@@ -177,4 +114,10 @@
 
 	mpp@a500 { /* MPP 6 */
 	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
 };
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 5c904b4..c92dad9 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -151,5 +151,5 @@
 	status = "ok";
 };
 
-/include/ "msm-pm8644.dtsi"
+/include/ "msm-pma8084.dtsi"
 /include/ "mpq8092-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 79760c1..391c564 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -260,6 +260,12 @@
 			};
 		};
 
+		qcom,leds@a100 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xa100 0x100>;
+			label = "mpp";
+		};
+
 		qcom,leds@a200 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xa200 0x100>;
@@ -492,5 +498,12 @@
 			reg = <0x5500 0x100>;
 			status = "disabled";
 		};
+
+		qcom,vibrator@c000 {
+			compatible = "qcom,qpnp-vibrator";
+			reg = <0xc000 0x100>;
+			label = "vibrator";
+			status = "disabled";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 99410b3..41920d5 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -686,6 +686,54 @@
 			label = "wled";
 		};
 
+		pwm@b100 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb100 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <0>;
+		};
+
+		pwm@b200 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb200 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <1>;
+		};
+
+		pwm@b300 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb300 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <2>;
+		};
+
+		pwm@b400 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb400 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <3>;
+		};
+
+		pwm@b500 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb500 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <4>;
+		};
+
+		pwm@b600 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb600 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <5>;
+		};
+
 		regulator@8000 {
 			regulator-name = "8226_lvs1";
 			reg = <0x8000 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 43b7d03..eadd5d3 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -849,7 +849,7 @@
 				qcom,decimation = <0>;
 				qcom,pre-div-channel-scaling = <0>;
 				qcom,calibration-type = "absolute";
-				qcom,scale-function = <1>;
+				qcom,scale-function = <3>;
 				qcom,hw-settle-time = <0>;
 				qcom,fast-avg-setup = <3>;
 				qcom,btm-channel-number = <0x70>;
diff --git a/arch/arm/boot/dts/msm-pm8644.dtsi b/arch/arm/boot/dts/msm-pma8084.dtsi
similarity index 76%
rename from arch/arm/boot/dts/msm-pm8644.dtsi
rename to arch/arm/boot/dts/msm-pma8084.dtsi
index 17a6b0b..30525aa 100644
--- a/arch/arm/boot/dts/msm-pm8644.dtsi
+++ b/arch/arm/boot/dts/msm-pma8084.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,20 +16,20 @@
 	interrupt-controller;
 	#interrupt-cells = <3>;
 
-	qcom,pm8644@0 {
+	qcom,pma8084@0 {
 		spmi-slave-container;
 		reg = <0x0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
-		pm8644_gpios: gpios {
+		pma8084_gpios: gpios {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
 			gpio-controller;
 			#gpio-cells = <2>;
 			#address-cells = <1>;
 			#size-cells = <1>;
-			label = "pm8644-gpio";
+			label = "pma8084-gpio";
 
 			gpio@c000 {
 				reg = <0xc000 0x100>;
@@ -140,121 +140,16 @@
 				reg = <0xd500 0x100>;
 				qcom,pin-num = <22>;
 			};
-
-			gpio@d600 {
-				reg = <0xd600 0x100>;
-				qcom,pin-num = <23>;
-			};
-
-			gpio@d700 {
-				reg = <0xd700 0x100>;
-				qcom,pin-num = <24>;
-			};
-
-			gpio@d800 {
-				reg = <0xd800 0x100>;
-				qcom,pin-num = <25>;
-			};
-
-			gpio@d900 {
-				reg = <0xd900 0x100>;
-				qcom,pin-num = <26>;
-			};
-
-			gpio@da00 {
-				reg = <0xda00 0x100>;
-				qcom,pin-num = <27>;
-			};
-
-			gpio@db00 {
-				reg = <0xdb00 0x100>;
-				qcom,pin-num = <28>;
-			};
-
-			gpio@dc00 {
-				reg = <0xdc00 0x100>;
-				qcom,pin-num = <29>;
-			};
-
-			gpio@dd00 {
-				reg = <0xdd00 0x100>;
-				qcom,pin-num = <30>;
-			};
-
-			gpio@de00 {
-				reg = <0xde00 0x100>;
-				qcom,pin-num = <31>;
-			};
-
-			gpio@df00 {
-				reg = <0xdf00 0x100>;
-				qcom,pin-num = <32>;
-			};
-
-			gpio@e000 {
-				reg = <0xe000 0x100>;
-				qcom,pin-num = <33>;
-			};
-
-			gpio@e100 {
-				reg = <0xe100 0x100>;
-				qcom,pin-num = <34>;
-			};
-
-			gpio@e200 {
-				reg = <0xe200 0x100>;
-				qcom,pin-num = <35>;
-			};
-
-			gpio@e300 {
-				reg = <0xe300 0x100>;
-				qcom,pin-num = <36>;
-			};
-
-			gpio@e400 {
-				reg = <0xe400 0x100>;
-				qcom,pin-num = <37>;
-			};
-
-			gpio@e500 {
-				reg = <0xe500 0x100>;
-				qcom,pin-num = <38>;
-			};
-
-			gpio@e600 {
-				reg = <0xe600 0x100>;
-				qcom,pin-num = <39>;
-			};
-
-			gpio@e700 {
-				reg = <0xe700 0x100>;
-				qcom,pin-num = <40>;
-			};
-
-			gpio@e800 {
-				reg = <0xe800 0x100>;
-				qcom,pin-num = <41>;
-			};
-
-			gpio@e900 {
-				reg = <0xe900 0x100>;
-				qcom,pin-num = <42>;
-			};
-
-			gpio@ea00 {
-				reg = <0xea00 0x100>;
-				qcom,pin-num = <43>;
-			};
 		};
 
-		pm8644_mpps: mpps {
+		pma8084_mpps: mpps {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
 			gpio-controller;
 			#gpio-cells = <2>;
 			#address-cells = <1>;
 			#size-cells = <1>;
-			label = "pm8644-mpp";
+			label = "pma8084-mpp";
 
 			mpp@a000 {
 				reg = <0xa000 0x100>;
@@ -285,17 +180,27 @@
 				reg = <0xa500 0x100>;
 				qcom,pin-num = <6>;
 			};
+
+			mpp@a600 {
+				reg = <0xa600 0x100>;
+				qcom,pin-num = <7>;
+			};
+
+			mpp@a700 {
+				reg = <0xa700 0x100>;
+				qcom,pin-num = <8>;
+			};
 		};
 	};
 
-	qcom,pm8644@1 {
+	qcom,pma8084@1 {
 		spmi-slave-container;
 		reg = <0x1>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
 		regulator@1400 {
-			regulator-name = "8644_s1";
+			regulator-name = "8084_s1";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -315,7 +220,7 @@
 		};
 
 		regulator@1700 {
-			regulator-name = "8644_s2";
+			regulator-name = "8084_s2";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -335,7 +240,7 @@
 		};
 
 		regulator@1a00 {
-			regulator-name = "8644_s3";
+			regulator-name = "8084_s3";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -355,7 +260,7 @@
 		};
 
 		regulator@1d00 {
-			regulator-name = "8644_s4";
+			regulator-name = "8084_s4";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -375,7 +280,7 @@
 		};
 
 		regulator@2000 {
-			regulator-name = "8644_s5";
+			regulator-name = "8084_s5";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -395,7 +300,7 @@
 		};
 
 		regulator@2300 {
-			regulator-name = "8644_s6";
+			regulator-name = "8084_s6";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -415,7 +320,7 @@
 		};
 
 		regulator@2600 {
-			regulator-name = "8644_s7";
+			regulator-name = "8084_s7";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -435,7 +340,7 @@
 		};
 
 		regulator@2900 {
-			regulator-name = "8644_s8";
+			regulator-name = "8084_s8";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -455,7 +360,7 @@
 		};
 
 		regulator@2c00 {
-			regulator-name = "8644_s9";
+			regulator-name = "8084_s9";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -475,7 +380,7 @@
 		};
 
 		regulator@2f00 {
-			regulator-name = "8644_s10";
+			regulator-name = "8084_s10";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -495,7 +400,7 @@
 		};
 
 		regulator@3200 {
-			regulator-name = "8644_s11";
+			regulator-name = "8084_s11";
 			spmi-dev-container;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -514,209 +419,248 @@
 			};
 		};
 
+		regulator@3500 {
+			regulator-name = "8084_s12";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x3500 0x300>;
+			status = "disabled";
+
+			qcom,ctl@3500 {
+				reg = <0x3500 0x100>;
+			};
+			qcom,ps@3600 {
+				reg = <0x3600 0x100>;
+			};
+			qcom,freq@3700 {
+				reg = <0x3700 0x100>;
+			};
+		};
+
 		regulator@4000 {
-			regulator-name = "8644_l1";
+			regulator-name = "8084_l1";
 			reg = <0x4000 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4100 {
-			regulator-name = "8644_l2";
+			regulator-name = "8084_l2";
 			reg = <0x4100 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4200 {
-			regulator-name = "8644_l3";
+			regulator-name = "8084_l3";
 			reg = <0x4200 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4300 {
-			regulator-name = "8644_l4";
+			regulator-name = "8084_l4";
 			reg = <0x4300 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4400 {
-			regulator-name = "8644_l5";
+			regulator-name = "8084_l5";
 			reg = <0x4400 0x100>;
 			compatible = "qcom,qpnp-regulator";
-			qcom,force-type = <0x04 0x10>;
 			status = "disabled";
 		};
 
 		regulator@4500 {
-			regulator-name = "8644_l6";
+			regulator-name = "8084_l6";
 			reg = <0x4500 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4600 {
-			regulator-name = "8644_l7";
+			regulator-name = "8084_l7";
 			reg = <0x4600 0x100>;
 			compatible = "qcom,qpnp-regulator";
-			qcom,force-type = <0x04 0x10>;
 			status = "disabled";
 		};
 
 		regulator@4700 {
-			regulator-name = "8644_l8";
+			regulator-name = "8084_l8";
 			reg = <0x4700 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4800 {
-			regulator-name = "8644_l9";
+			regulator-name = "8084_l9";
 			reg = <0x4800 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4900 {
-			regulator-name = "8644_l10";
+			regulator-name = "8084_l10";
 			reg = <0x4900 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4a00 {
-			regulator-name = "8644_l11";
+			regulator-name = "8084_l11";
 			reg = <0x4a00 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4b00 {
-			regulator-name = "8644_l12";
+			regulator-name = "8084_l12";
 			reg = <0x4b00 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4c00 {
-			regulator-name = "8644_l13";
+			regulator-name = "8084_l13";
 			reg = <0x4c00 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4d00 {
-			regulator-name = "8644_l14";
+			regulator-name = "8084_l14";
 			reg = <0x4d00 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4e00 {
-			regulator-name = "8644_l15";
+			regulator-name = "8084_l15";
 			reg = <0x4e00 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@4f00 {
-			regulator-name = "8644_l16";
+			regulator-name = "8084_l16";
 			reg = <0x4f00 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5000 {
-			regulator-name = "8644_l17";
+			regulator-name = "8084_l17";
 			reg = <0x5000 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5100 {
-			regulator-name = "8644_l18";
+			regulator-name = "8084_l18";
 			reg = <0x5100 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5200 {
-			regulator-name = "8644_l19";
+			regulator-name = "8084_l19";
 			reg = <0x5200 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5300 {
-			regulator-name = "8644_l20";
+			regulator-name = "8084_l20";
 			reg = <0x5300 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5400 {
-			regulator-name = "8644_l21";
+			regulator-name = "8084_l21";
 			reg = <0x5400 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5500 {
-			regulator-name = "8644_l22";
+			regulator-name = "8084_l22";
 			reg = <0x5500 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5600 {
-			regulator-name = "8644_l23";
+			regulator-name = "8084_l23";
 			reg = <0x5600 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5700 {
-			regulator-name = "8644_l24";
+			regulator-name = "8084_l24";
 			reg = <0x5700 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@5800 {
-			regulator-name = "8644_l25";
+			regulator-name = "8084_l25";
 			reg = <0x5800 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
+		regulator@5900 {
+			regulator-name = "8084_l26";
+			reg = <0x5900 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5a00 {
+			regulator-name = "8084_l27";
+			reg = <0x5a00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
 		regulator@8000 {
-			regulator-name = "8644_lvs1";
+			regulator-name = "8084_lvs1";
 			reg = <0x8000 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@8100 {
-			regulator-name = "8644_lvs2";
+			regulator-name = "8084_lvs2";
 			reg = <0x8100 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@8200 {
-			regulator-name = "8644_mvs1";
+			regulator-name = "8084_lvs3";
 			reg = <0x8200 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
 
 		regulator@8300 {
-			regulator-name = "8644_mvs2";
+			regulator-name = "8084_lvs4";
 			reg = <0x8300 0x100>;
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
+
+		regulator@8400 {
+			regulator-name = "8084_mvs1";
+			reg = <0x8400 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index e8e58c4..b203540 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -37,7 +37,7 @@
 			vdd-supply = <&pm8226_l19>;
 			vcc_i2c-supply = <&pm8226_lvs1>;
 			synaptics,reset-gpio = <&msmgpio 16 0x00>;
-			synaptics,irq-gpio = <&msmgpio 17 0x00>;
+			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
 			synaptics,i2c-pull-up;
 			synaptics,reg-en;
diff --git a/arch/arm/boot/dts/msm8226-ion.dtsi b/arch/arm/boot/dts/msm8226-ion.dtsi
index f433a49..9ada271 100644
--- a/arch/arm/boot/dts/msm8226-ion.dtsi
+++ b/arch/arm/boot/dts/msm8226-ion.dtsi
@@ -38,9 +38,7 @@
 		qcom,ion-heap@27 { /* QSECOM HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <27>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x780000>;
+			linux,contiguous-region = <&qsecom_mem>;
 		};
 
 		qcom,ion-heap@28 { /* AUDIO HEAP */
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index a732722..1f8a773 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -37,7 +37,7 @@
 			vdd-supply = <&pm8226_l19>;
 			vcc_i2c-supply = <&pm8226_lvs1>;
 			synaptics,reset-gpio = <&msmgpio 16 0x00>;
-			synaptics,irq-gpio = <&msmgpio 17 0x00>;
+			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
 			synaptics,i2c-pull-up;
 			synaptics,reg-en;
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 97b22aa..b6fbd5b 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -114,7 +114,7 @@
 			qcom,type = <0x61706d73>;	/* "smpa" */
 			qcom,id = <0x01>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <5>;		/* Super Turbo */
+			qcom,init-value = <3>;		/* SVS SOC */
 		};
 
 		qcom,lpm-resources@1 {
@@ -123,7 +123,7 @@
 			qcom,type = <0x616F646C>;	/* "ldoa" */
 			qcom,id = <0x03>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
-			qcom,init-value = <3>;		/* Active */
+			qcom,init-value = <3>;		/* SVS SOC */
 		};
 
 		qcom,lpm-resources@2 {
@@ -380,9 +380,9 @@
 		qcom,offset-page-indices = <56>;
 	};
 
-	qcom,rpm-stats@0xfc19dbd0{
+	qcom,rpm-stats@fc19dba0 {
 		compatible = "qcom,rpm-stats";
-		reg = <0xfc19dbd0 0x1000>;
+		reg = <0xfc19dba0 0x1000>;
 		reg-names = "phys_addr_base";
 		qcom,sleep-stats-version = <2>;
 	};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index e694cef..660fb3e 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -37,7 +37,7 @@
 			vdd-supply = <&pm8226_l19>;
 			vcc_i2c-supply = <&pm8226_lvs1>;
 			synaptics,reset-gpio = <&msmgpio 16 0x00>;
-			synaptics,irq-gpio = <&msmgpio 17 0x00>;
+			synaptics,irq-gpio = <&msmgpio 17 0x2008>;
 			synaptics,button-map = <139 102 158>;
 			synaptics,i2c-pull-up;
 			synaptics,reg-en;
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 70731d2..4551f03 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -67,7 +67,7 @@
 			regulator-min-microvolt = <1>;
 			regulator-max-microvolt = <7>;
 			qcom,use-voltage-corner;
-			qcom,consumer-supplies = "vdd_dig", "", "vdd_sr2_dig", "";
+			qcom,consumer-supplies = "vdd_dig", "";
 		};
 		pm8226_s1_corner_ao: regulator-s1-corner-ao {
 			compatible = "qcom,rpm-regulator-smd";
@@ -76,6 +76,7 @@
 			regulator-min-microvolt = <1>;
 			regulator-max-microvolt = <7>;
 			qcom,use-voltage-corner;
+			qcom,consumer-supplies = "vdd_sr2_dig", "";
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 9ee78a4..f71e916 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -59,6 +59,19 @@
 			reg = <0 0x3800000>;
 			label = "secure_mem";
 		};
+
+		qsecom_mem: qsecom_region {
+			linux,contiguous-region;
+			reg = <0 0x780000>;
+			label = "qsecom_mem";
+		};
+
+	};
+
+	qcom,mpm2-sleep-counter@fc4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0xfc4a3000 0x1000>;
+		clock-frequency = <32768>;
 	};
 
 	timer {
@@ -229,6 +242,8 @@
 		HSUSB_3p3-supply = <&pm8226_l20>;
 		qcom,vdd-voltage-level = <1 5 7>;
 
+		qcom,hsusb-otg-phy-init-seq =
+			<0x44 0x80 0x68 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <2>;
@@ -246,6 +261,7 @@
 	android_usb@fe8050c8 {
 		compatible = "qcom,android-usb";
 		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-cdrom;
 	};
 
 	wcd9xxx_intc: wcd9xxx-irq {
@@ -516,7 +532,7 @@
 
 	qcom,smem@fa00000 {
 		compatible = "qcom,smem";
-		reg = <0xfa00000 0x200000>,
+		reg = <0xfa00000 0x100000>,
 			<0xf9011000 0x1000>,
 			<0xfc428000 0x4000>;
 		reg-names = "smem", "irq-reg-base", "aux-mem1";
@@ -677,7 +693,7 @@
 		reg = <0xf9927000 0x1000>;
 		interrupt-names = "qup_err_intr";
 		interrupts = <0 99 0>;
-		qcom,i2c-bus-freq = <100000>;
+		qcom,i2c-bus-freq = <384000>;
 		qcom,i2c-src-freq = <19200000>;
 	};
 
@@ -686,7 +702,6 @@
 		reg = <0xf9011050 0x8>;
 		reg-names = "rcg_base";
 		a7_cpu-supply = <&apc_vreg_corner>;
-		a7_mem-supply = <&pm8226_l3>;
 	};
 
 	qcom,ocmem@fdd00000 {
@@ -787,6 +802,7 @@
 
 		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
 		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
@@ -915,6 +931,42 @@
 				<55 512 3936000 393600>,
 				<55 512 3936000 393600>;
 	};
+
+	qcom,qcrypto@fd404000 {
+		compatible = "qcom,qcrypto";
+                reg  =  <0xfd400000 0x20000>,
+                        <0xfd404000 0x8000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <2>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-hw-shared;
+		qcom,msm-bus,name = "qcrypto-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<56 512 0 0>,
+				<56 512 3936000 393600>;
+	};
+
+        qcom,qcedev@fd400000 {
+		compatible = "qcom,qcedev";
+		reg  =  <0xfd400000 0x20000>,
+			<0xfd404000 0x8000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <1>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-hw-shared;
+		qcom,msm-bus,name = "qcedev-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<56 512 0 0>,
+				<56 512 3936000 393600>;
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 10afcc5..33dd7ff 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 
 /include/ "msm8610.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610 CDP";
@@ -27,6 +28,20 @@
 
 &spmi_bus {
 	qcom,pm8110@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux-default-trigger = "hr-trigger";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,id = <6>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+
 		qcom,leds@a200 {
 			status = "okay";
 			qcom,led_mpp_3 {
@@ -41,6 +56,48 @@
 			};
 		};
 	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&msmgpio 73 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&msmgpio 74 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&msmgpio 72 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+};
+
+&spmi_bus {
+	qcom,pm8110@1 {
+		qcom,vibrator@c000 {
+			status = "okay";
+			qcom,vib-timeout-ms = <15000>;
+			qcom,vib-vtg-level-mV = <3100>;
+		};
+	};
 };
 
 &sdhc_1 {
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 41b58da..7d7d8fd 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -31,9 +31,7 @@
 		qcom,ion-heap@27 { /* QSECOM HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <27>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x100000>;
+			linux,contiguous-region = <&qsecom_mem>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
new file mode 100644
index 0000000..42fa149
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -0,0 +1,37 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	qcom,mdss_mdp@fd900000 {
+		compatible = "qcom,mdss_mdp3";
+		reg = <0xfd900000 0x100000>;
+		reg-names = "mdp_phys";
+		interrupts = <0 72 0>;
+
+		mdss_fb0: qcom,mdss_fb_primary {
+			cell-index = <0>;
+			compatible = "qcom,mdss-fb";
+			qcom,memory-reservation-type = "EBI1";
+			qcom,memory-reservation-size = <0x800000>;
+		};
+	};
+
+	mdss_dsi0: qcom,mdss_dsi@fdd00000 {
+		compatible = "qcom,msm-dsi-v2";
+		label = "MDSS DSI CTRL->0";
+		cell-index = <0>;
+		reg = <0xfdd00000 0x100000>;
+		interrupts = <0 30 0>;
+		vdda-supply = <&pm8110_l4>;
+		qcom,mdss-fb-map = <&mdss_fb0>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index e410185..aeac915 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 
 /include/ "msm8610.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610 MTP";
@@ -27,6 +28,20 @@
 
 &spmi_bus {
 	qcom,pm8110@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux-default-trigger = "hr-trigger";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,id = <6>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+
 		qcom,leds@a200 {
 			status = "okay";
 			qcom,led_mpp_3 {
@@ -41,6 +56,48 @@
 			};
 		};
 	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&msmgpio 73 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&msmgpio 74 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&msmgpio 72 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+};
+
+&spmi_bus {
+	qcom,pm8110@1 {
+		qcom,vibrator@c000 {
+			status = "okay";
+			qcom,vib-timeout-ms = <15000>;
+			qcom,vib-vtg-level-mV = <3100>;
+		};
+	};
 };
 
 &sdhc_1 {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index e8849f6..baae269 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -382,9 +382,9 @@
 		qcom,offset-page-indices = <56>;
 	};
 
-	qcom,rpm-stats@0xfc19dbd0{
+	qcom,rpm-stats@fc19dba0 {
 		compatible = "qcom,rpm-stats";
-		reg = <0xfc19dbd0 0x1000>;
+		reg = <0xfc19dba0 0x1000>;
 		reg-names = "phys_addr_base";
 		qcom,sleep-stats-version = <2>;
 	};
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 67eee5c..f5d01e0 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -66,7 +66,7 @@
 			regulator-min-microvolt = <1>;
 			regulator-max-microvolt = <7>;
 			qcom,use-voltage-corner;
-			qcom,consumer-supplies = "vdd_dig", "", "vdd_sr2_dig", "";
+			qcom,consumer-supplies = "vdd_dig", "";
 		};
 
 		pm8110_s1_corner_ao: regulator-s1-corner-ao {
@@ -76,6 +76,7 @@
 			regulator-min-microvolt = <1>;
 			regulator-max-microvolt = <7>;
 			qcom,use-voltage-corner;
+			qcom,consumer-supplies = "vdd_sr2_dig", "";
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index e406ba8..c7281ea 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -19,6 +19,7 @@
 /include/ "msm8610-pm.dtsi"
 /include/ "msm8610-smp2p.dtsi"
 /include/ "msm8610-bus.dtsi"
+/include/ "msm8610-mdss.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610";
@@ -45,12 +46,28 @@
 		qcom,direct-connect-irqs = <8>;
 	};
 
+	memory {
+
+		qsecom_mem: qsecom_region {
+			linux,contiguous-region;
+			reg = <0 0x100000>;
+			label = "qsecom_mem";
+		};
+
+	};
+
 	aliases {
 		spi0 = &spi_0;
 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
 		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
 	};
 
+	qcom,mpm2-sleep-counter@fc4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0xfc4a3000 0x1000>;
+		clock-frequency = <32768>;
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <1 2 0 1 3 0>;
@@ -148,7 +165,7 @@
 		qcom,buffer-type-tz-usage-map = <0x1 0x1>,
 						<0x1fe 0x2>;
 		qcom,hfi = "q6";
-		qcom,max-hw-load = <97200>; /* FWVGA @ 30 * 2 */
+		qcom,max-hw-load = <108000>; /* 720p @ 30 * 1 */
 	};
 
 	qcom,usbbam@f9a44000 {
@@ -309,7 +326,7 @@
 
 	qcom,smem@d900000 {
 		compatible = "qcom,smem";
-		reg = <0xd900000 0x200000>,
+		reg = <0xd900000 0x100000>,
 			<0xf9011000 0x1000>,
 			<0xfc428000 0x4000>;
 		reg-names = "smem", "irq-reg-base", "aux-mem1";
@@ -401,7 +418,6 @@
 		reg = <0xf9011050 0x8>;
 		reg-names = "rcg_base";
 		a7_cpu-supply = <&apc_vreg_corner>;
-		a7_mem-supply = <&pm8110_l3_ao>;
 	};
 
 	spmi_bus: qcom,spmi@fc4c0000 {
@@ -430,6 +446,20 @@
 		qcom,i2c-bus-freq = <100000>;
 	};
 
+	i2c@f9928000 { /* BLSP1 QUP6 */
+		cell-index = <6>;
+		compatible = "qcom,i2c-qup";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0xf9928000 0x1000>;
+		interrupt-names = "qup_err_intr";
+		interrupts = <0 100 0>;
+		qcom,i2c-bus-freq = <100000>;
+		qcom,i2c-src-freq = <19200000>;
+		qcom,sda-gpio = <&msmgpio 16 0>;
+		qcom,scl-gpio = <&msmgpio 17 0>;
+	};
 
 	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
 		compatible = "qcom,spi-qup-v2";
@@ -484,6 +514,13 @@
 
 	qcom,msm-pcm {
 		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <0>;
+	};
+
+	qcom,msm-pcm-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <1>;
+		qcom,msm-pcm-low-latency;
 	};
 
 	qcom,msm-pcm-routing {
@@ -523,15 +560,15 @@
 		qcom,msm-dai-q6-mi2s-prim {
 			compatible = "qcom,msm-dai-q6-mi2s";
 			qcom,msm-dai-q6-mi2s-dev-id = <0>;
-			qcom,msm-mi2s-rx-lines = <1>;
-			qcom,msm-mi2s-tx-lines = <0>;
+			qcom,msm-mi2s-rx-lines = <0>;
+			qcom,msm-mi2s-tx-lines = <3>;
 		};
 
 		qcom,msm-dai-q6-mi2s-sec {
 			compatible = "qcom,msm-dai-q6-mi2s";
 			qcom,msm-dai-q6-mi2s-dev-id = <1>;
-			qcom,msm-mi2s-rx-lines = <0>;
-			qcom,msm-mi2s-tx-lines = <3>;
+			qcom,msm-mi2s-rx-lines = <3>;
+			qcom,msm-mi2s-tx-lines = <0>;
 		};
 	};
 
@@ -584,8 +621,9 @@
 
 	qcom,wcnss-wlan@fb000000 {
 		compatible = "qcom,wcnss_wlan";
-		reg = <0xfb000000 0x280000>;
-		reg-names = "wcnss_mmio";
+		reg = <0xfb000000 0x280000>,
+			<0xf9011008 0x04>;
+		reg-names = "wcnss_mmio", "wcnss_fiq";
 		interrupts = <0 145 0>, <0 146 0>;
 		interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
 
@@ -623,6 +661,7 @@
 
 		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
 		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 3c1711c..9cfc5fd 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -710,5 +710,12 @@
 		qcom,cdc-micbias1-ext-cap;
 		qcom,cdc-micbias3-ext-cap;
 		qcom,cdc-micbias4-ext-cap;
+
+		/* If boot isn't available, vph_pwr_vreg can be used instead */
+		cdc-vdd-spkdrv-supply = <&pm8941_boost>;
+		qcom,cdc-vdd-spkdrv-voltage = <5000000 5000000>;
+		qcom,cdc-vdd-spkdrv-current = <1250000>;
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index eaf326e..7f46a54 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -202,7 +202,34 @@
 
 	sound {
 		qcom,model = "msm8974-taiko-fluid-snd-card";
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"AMIC1", "MIC BIAS1 Internal1",
+			"MIC BIAS1 Internal1", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic",
+			"DMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic1",
+			"DMIC2", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic2",
+			"DMIC3", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic3",
+			"DMIC4", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic4",
+			"DMIC5", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic5",
+			"DMIC6", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic6",
+			"Lineout_1 amp", "LINEOUT1",
+			"Lineout_3 amp", "LINEOUT3";
+
 		qcom,hdmi-audio-rx;
+		qcom,ext-ult-lo-amp-gpio = <&pm8941_gpios 6 0>;
 	};
 };
 
@@ -212,6 +239,13 @@
 		qcom,cdc-micbias2-ext-cap;
 		qcom,cdc-micbias3-ext-cap;
 		qcom,cdc-micbias4-ext-cap;
+
+		/* If boot isn't available, vph_pwr_vreg can be used instead */
+		cdc-vdd-spkdrv-supply = <&pm8941_boost>;
+		qcom,cdc-vdd-spkdrv-voltage = <5000000 5000000>;
+		qcom,cdc-vdd-spkdrv-current = <1250000>;
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index 31afd9c..cfe39fc 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -45,9 +45,7 @@
 		qcom,ion-heap@27 { /* QSECOM HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <27>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x1100000>;
+			linux,contiguous-region = <&qsecom_mem>;
 		};
 
 		qcom,ion-heap@28 { /* AUDIO HEAP */
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index d9acb81..d8a090b 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -318,6 +318,7 @@
 			"Lineout_3 amp", "LINEOUT3",
 			"Lineout_2 amp", "LINEOUT2",
 			"Lineout_4 amp", "LINEOUT4",
+			"SPK_ultrasound amp", "SPK_OUT",
 			"AMIC1", "MIC BIAS4 External",
 			"MIC BIAS4 External", "Analog Mic4",
 			"AMIC2", "MIC BIAS2 External",
@@ -346,6 +347,7 @@
 		qcom,ext-spk-amp-supply = <&ext_5v>;
 		qcom,ext-spk-amp-gpio = <&pm8841_mpps 1 0>;
 		qcom,dock-plug-det-irq = <&pm8841_mpps 2 0>;
+		qcom,ext-ult-spk-amp-gpio = <&pm8941_gpios 6 0>;
 		qcom,hdmi-audio-rx;
 
 		qcom,prim-auxpcm-gpio-clk  = <&msmgpio 74 0>;
@@ -449,6 +451,14 @@
 	};
 
 	gpio@c500 { /* GPIO 6 */
+		/* ULTRASOUND_EN_1 PA AB enable */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,pull = <4>; /* PULL_DOWN */
+		qcom,vin-sel = <0>; /* VPH */
+		qcom,out-strength = <2>; /* STRENGTH_MED */
+		qcom,src-sel = <0>; /* CONSTANT */
+		qcom,master-en = <1>;
 	};
 
 	gpio@c600 { /* GPIO 7 */
@@ -701,10 +711,24 @@
 	};
 };
 
+&vph_pwr_vreg {
+	status = "ok";
+};
+
 &slim_msm {
 	taiko_codec {
 		qcom,cdc-micbias2-ext-cap;
 		qcom,cdc-micbias3-ext-cap;
+
+		/*
+		 * Liquid has external spkrdrv supply. Give a dummy supply to
+		 * make codec driver's happy.
+		 */
+		cdc-vdd-spkdrv-supply = <&vph_pwr_vreg>;
+		qcom,cdc-vdd-spkdrv-voltage = <0 0>;
+		qcom,cdc-vdd-spkdrv-current = <0>;
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 0be3756..d1b3334 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -466,6 +466,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
+		qcom,pfm-threshold = <73>;
 
 		krait0_vreg: regulator@f9088000 {
 			compatible = "qcom,krait-regulator";
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 494b12c..def7b8c 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -65,6 +65,7 @@
 	qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
 	qcom,mdss-has-bwc;
 	qcom,mdss-has-decimation;
+	qcom,mdss-ad-off = <0x0013100 0x00013300>;
 };
 
 &mdss_hdmi_tx {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 9b8353b..9421345 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -38,7 +38,7 @@
 
 		secure_mem: secure_region {
 			linux,contiguous-region;
-			reg = <0 0x7800000>;
+			reg = <0 0xFC00000>;
 			label = "secure_mem";
 		};
 
@@ -47,6 +47,13 @@
 			reg = <0 0x2000000>;
 			label = "adsp_mem";
 		};
+
+		qsecom_mem: qsecom_region {
+			linux,contiguous-region;
+			reg = <0 0x1100000>;
+			label = "qseecom_mem";
+		};
+
 	};
 
 	intc: interrupt-controller@F9000000 {
@@ -725,6 +732,22 @@
 		qcom,i2c-src-freq = <50000000>;
 	};
 
+	i2c_1: i2c@f9923000 {
+		cell-index = <1>;
+		compatible = "qcom,i2c-qup";
+		reg = <0xf9923000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		interrupts = <0 95 0>;
+		interrupt-names = "qup_err_intr";
+		qcom,i2c-bus-freq = <100000>;
+		qcom,i2c-src-freq = <19200000>;
+		qcom,scl-gpio = <&msmgpio 3 0>;
+		qcom,sda-gpio = <&msmgpio 2 0>;
+		status = "disabled";
+	};
+
 	i2c_2: i2c@f9924000 {
 		cell-index = <2>;
 		compatible = "qcom,i2c-qup";
@@ -1102,6 +1125,7 @@
 
 		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
 		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index ad95601..de88ff1 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -37,6 +37,10 @@
 	};
 };
 
+&hsic_host {
+	qcom,disable-park-mode;
+};
+
 &ipa_hw {
 	qcom,ipa-hw-ver = <1>; /* IPA h-w revision */
 };
diff --git a/arch/arm/boot/dts/msm9625-v2.dtsi b/arch/arm/boot/dts/msm9625-v2.dtsi
index 3ce6844..81d8e00 100644
--- a/arch/arm/boot/dts/msm9625-v2.dtsi
+++ b/arch/arm/boot/dts/msm9625-v2.dtsi
@@ -35,6 +35,10 @@
 	qcom,ipa-hw-ver = <2>; /* IPA h-w revision */
 };
 
+&hsic_host {
+	qcom,disable-park-mode;
+};
+
 &sfpb_spinlock {
 	status = "disable";
 };
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index a79f403..3e2eab3 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -155,7 +155,7 @@
 		qcom,hsusb-otg-disable-reset;
 		qcom,hsusb-otg-lpm-on-dev-suspend;
 		qcom,hsusb-otg-clk-always-on-workaround;
-		qcom,hsusb-otg-delay-lpm;
+		qcom,hsusb-otg-delay-lpm-hndshk-on-disconnect;
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
@@ -205,6 +205,7 @@
 			qcom,src-bam-pipe-index = <1>;
 			qcom,data-fifo-size = <0x8000>;
 			qcom,descriptor-fifo-size = <0x2000>;
+			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe1 {
 			label = "hsusb-ipa-in-0";
@@ -217,6 +218,7 @@
 			qcom,dst-bam-pipe-index = <0>;
 			qcom,data-fifo-size = <0x8000>;
 			qcom,descriptor-fifo-size = <0x2000>;
+			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe2 {
 			label = "hsusb-qdss-in-0";
@@ -755,6 +757,7 @@
 
 		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
 		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
 
 		/* GPIO output to mss */
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index db61dab..3f51659 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -37,12 +37,70 @@
 		qcom,direct-connect-irqs = <8>;
 	};
 
-	timer: msm-qtimer@f9021000 {
-		compatible = "arm,armv7-timer";
-		reg = <0xf9021000 0x1000>;
-		interrupts = <0 7 0>;
-		irq-is-not-percpu;
+	timer@f9020000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0xf9020000 0x1000>;
 		clock-frequency = <19200000>;
+
+		frame@f9021000 {
+			frame-number = <0>;
+			interrupts = <0 7 0x4>,
+				     <0 6 0x4>;
+			reg = <0xf9021000 0x1000>,
+			      <0xf9022000 0x1000>;
+		};
+
+		frame@f9023000 {
+			frame-number = <1>;
+			interrupts = <0 8 0x4>;
+			reg = <0xf9023000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9024000 {
+			frame-number = <2>;
+			interrupts = <0 9 0x4>;
+			reg = <0xf9024000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9025000 {
+			frame-number = <3>;
+			interrupts = <0 10 0x4>;
+			reg = <0xf9025000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9026000 {
+			frame-number = <4>;
+			interrupts = <0 11 0x4>;
+			reg = <0xf9026000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9027000 {
+			frame-number = <5>;
+			interrupts = <0 12 0x4>;
+			reg = <0xf9027000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9028000 {
+			frame-number = <6>;
+			interrupts = <0 13 0x4>;
+			reg = <0xf9028000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9029000 {
+			frame-number = <7>;
+			interrupts = <0 14 0x4>;
+			reg = <0xf9029000 0x1000>;
+			status = "disabled";
+		};
 	};
 
 	uartdm3: serial@f991f000 {
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index c47117e..a1fa53c 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -74,8 +74,6 @@
 CONFIG_MSM_L2_ERP_PORT_PANIC=y
 CONFIG_MSM_L2_ERP_1BIT_PANIC=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
-CONFIG_MSM_CACHE_DUMP=y
-CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_ARM_LPAE=y
 CONFIG_NO_HZ=y
@@ -284,6 +282,7 @@
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
 CONFIG_FB_MSM_MDSS=y
@@ -313,6 +312,23 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
+CONFIG_MMC_BLOCK_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_DIAG_CHAR=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_BACKLIGHT=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
new file mode 100644
index 0000000..5660dec
--- /dev/null
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -0,0 +1,369 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-perf"
+CONFIG_SYSVIPC=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM8610=y
+CONFIG_ARCH_MSM8226=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_CPU_HAS_L2_PMU=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_LOGGING=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_PIL_LPASS_QDSP6V5=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_MSM_PIL_VENUS=y
+CONFIG_MSM_PIL_PRONTO=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
+CONFIG_MSM_ADSP_LOADER=m
+CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_NONSECURE=y
+CONFIG_MSM_OCMEM_POWER_DISABLE=y
+CONFIG_SENSORS_ADSP=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_USE_OF=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCISMD=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+CONFIG_CMA=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_MSM_RMNET is not set
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPMI=y
+CONFIG_MSM_BUS_SCALING=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
+CONFIG_MSM_QPNP_INT=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_CHARGER=y
+CONFIG_QPNP_BMS=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_WCD9306_CODEC=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_MSM_CAMERA is not set
+CONFIG_OV8825=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_ISPIF=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_OV9724=y
+CONFIG_MSMB_JPEG=y
+CONFIG_SWITCH=y
+CONFIG_MSM_WFD=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_MSM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MSM8226=y
+CONFIG_SND_SOC_MSM8X10=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_SPS=y
+CONFIG_USB_BAM=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_PWM=y
+CONFIG_QPNP_POWER_ON=y
+CONFIG_MSM_IOMMU=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_EVENT=m
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_QPNP_VIBRATOR=y
+CONFIG_QSEECOM=y
\ No newline at end of file
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 3291919..6253629 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -59,7 +59,6 @@
 CONFIG_MSM_WATCHDOG_V2=y
 CONFIG_MSM_MEMORY_DUMP=y
 CONFIG_MSM_DLOAD_MODE=y
-CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_ADSP_LOADER=m
 CONFIG_MSM_OCMEM=y
 CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
@@ -69,6 +68,7 @@
 CONFIG_SENSORS_ADSP=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
@@ -278,7 +278,6 @@
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_FB=y
-CONFIG_FB_VIRTUAL=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
 CONFIG_FB_MSM_MDSS=y
@@ -377,3 +376,7 @@
 CONFIG_CRC_CCITT=y
 CONFIG_QPNP_VIBRATOR=y
 CONFIG_QSEECOM=y
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_CRYPTO_DEV_QCEDEV=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 59cafd1..dc84558 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -25,6 +25,7 @@
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
 CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_KPROBES=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index ae73bad..1e0134a 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -25,6 +25,7 @@
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_KALLSYMS_ALL=y
 CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
 CONFIG_MODULES=y
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index c1295c4..70d82ec 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -119,16 +119,16 @@
  */
 extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long,
 	size_t, unsigned int, void *);
-extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int,
+extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int,
 	void *);
 
 extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
-extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
-extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached);
+extern void __iomem *__arm_ioremap(phys_addr_t, size_t, unsigned int);
+extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached);
 extern void __iounmap(volatile void __iomem *addr);
 extern void __arm_iounmap(volatile void __iomem *addr);
 
-extern void __iomem * (*arch_ioremap_caller)(unsigned long, size_t,
+extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t,
 	unsigned int, void *);
 extern void (*arch_iounmap)(volatile void __iomem *);
 
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 84560dc..7b6f42a 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -313,6 +313,7 @@
  * We provide our own arch_get_unmapped_area to cope with VIPT caches.
  */
 #define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
 
 /*
  * remap a physical page `pfn' of size `size' with page protection `prot'
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 8e2bb29..07209d7 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -126,6 +126,8 @@
 
 #endif
 
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
 #endif
 
 #endif /* __ASM_ARM_PROCESSOR_H */
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index b06ed1c..3729448 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1093,7 +1093,7 @@
 	default "0x00000000" if ARCH_MSM8610
 	default "0x10000000" if ARCH_FSM9XXX
 	default "0x00200000" if ARCH_MSM9625
-	default "0x00200000" if ARCH_MSMKRYPTON
+	default "0x00000000" if ARCH_MSMKRYPTON
 	default "0x00200000" if !MSM_STACKED_MEMORY
 	default "0x00000000" if ARCH_QSD8X50 && MSM_SOC_REV_A
 	default "0x20000000" if ARCH_QSD8X50
@@ -1113,14 +1113,14 @@
 config KERNEL_PMEM_SMI_REGION
 	bool "Enable in-kernel PMEM region for SMI"
 	default y if ARCH_MSM8X60
-	depends on ANDROID_PMEM && ((ARCH_QSD8X50 && !PMEM_GPU0) || (ARCH_MSM8X60 && !VCM))
+	depends on (ARCH_QSD8X50 && !PMEM_GPU0) || (ARCH_MSM8X60 && !VCM)
 	help
 	   Enable the in-kernel PMEM allocator to use SMI memory.
 
 config PMEM_GPU0
 	bool "Enable PMEM GPU0 region"
 	default y
-	depends on ARCH_QSD8X50 && ANDROID_PMEM
+	depends on ARCH_QSD8X50
 	help
 	  Enable the PMEM GPU0 device on SMI Memory.
 
@@ -1856,7 +1856,6 @@
 
 config MSM_HW3D
 	tristate "MSM Hardware 3D Register Driver"
-	depends on ANDROID_PMEM
 	help
 	  Provides access to registers needed by the userspace OpenGL|ES
 	  library.
@@ -1864,7 +1863,6 @@
 config MSM_ADSP
 	depends on (ARCH_MSM7X01A || ARCH_MSM7X25 || ARCH_MSM7X27)
 	tristate "MSM ADSP driver"
-	depends on ANDROID_PMEM
 	default y
 	help
 	  Provides access to registers needed by the userspace aDSP library.
@@ -1890,7 +1888,7 @@
 
 config MSM7KV2_AUDIO
 	bool "MSM7K v2 audio"
-	depends on (ARCH_MSM7X30 && ANDROID_PMEM)
+	depends on ARCH_MSM7X30
 	default y
 	help
 	  Enables QDSP5V2-based audio drivers for audio playbacks and
@@ -1906,14 +1904,14 @@
 
 config MSM_QDSP6
 	tristate "QDSP6 support"
-	depends on ARCH_QSD8X50 && ANDROID_PMEM
+	depends on ARCH_QSD8X50
 	default y
 	help
 	  Enable support for qdsp6. This provides audio and video functionality.
 
 config MSM8X60_AUDIO
 	tristate "MSM8X60 audio support"
-	depends on ARCH_MSM8X60 && ANDROID_PMEM
+	depends on ARCH_MSM8X60
 	default y
 	help
 	  Enable support for qdsp6v2. This provides audio functionality.
@@ -1972,7 +1970,7 @@
 
 config QSD_AUDIO
 	bool "QSD audio"
-	depends on ARCH_MSM_SCORPION && MSM_DALRPC && ANDROID_PMEM && !MSM_SMP
+	depends on ARCH_MSM_SCORPION && MSM_DALRPC && !MSM_SMP
 	default y
 	help
 	  Provides PCM, MP3, and AAC audio playback.
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index a45f5ec..43b243d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -7,7 +7,6 @@
 obj-y += clock.o clock-voter.o clock-dummy.o
 obj-y += modem_notifier.o
 obj-$(CONFIG_USE_OF) += board-dt.o
-obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
 obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o
 obj-$(CONFIG_KEXEC) += msm_kexec.o
 
@@ -316,6 +315,7 @@
 obj-$(CONFIG_ARCH_MSM8226) += acpuclock-8226.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += clock-local2.o clock-pll.o clock-8610.o clock-rpm.o clock-voter.o
+obj-$(CONFIG_ARCH_MSM8610) += clock-dsi-8610.o
 
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -428,3 +428,4 @@
 
 obj-$(CONFIG_ARCH_MSM8974) += msm_mpmctr.o
 obj-$(CONFIG_MSM_CPR_REGULATOR) += cpr-regulator.o
+obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index b2fe474..d57709d 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -64,7 +64,7 @@
         dtb-$(CONFIG_ARCH_APQ8084)	+= apq8084-sim.dtb
 
 # MSMKRYPTON
-   zreladdr-$(CONFIG_ARCH_MSMKRYPTON)	:= 0x00208000
+   zreladdr-$(CONFIG_ARCH_MSMKRYPTON)	:= 0x00008000
 	dtb-$(CONFIG_ARCH_MSMKRYPTON)	+= msmkrypton-sim.dtb
 
 # MSM9615
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index a0727b7..8262946 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -131,7 +131,6 @@
 	[12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 5 },
 	[13] = { { 1080000, HFPLL, 1, 0x28 }, 1150000, 1150000, 5 },
 	[14] = { { 1134000, HFPLL, 1, 0x2A }, 1150000, 1150000, 5 },
-	[15] = { { 1188000, HFPLL, 1, 0x2C }, 1150000, 1150000, 5 },
 	{ }
 };
 
@@ -149,15 +148,15 @@
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1100000 },
 	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(5),  1125000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1125000 },
-	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1175000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1175000 },
-	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1200000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1200000 },
-	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(15), 1225000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1225000 },
-	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(15), 1237500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1237500 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1250000 },
+	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(14), 1175000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1175000 },
+	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(14), 1200000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1200000 },
+	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(14), 1225000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1225000 },
+	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(14), 1237500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1237500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1250000 },
 	{ 0, { 0 } }
 };
 
@@ -175,15 +174,15 @@
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1050000 },
 	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(5),  1075000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1075000 },
-	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1125000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1125000 },
-	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1150000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1150000 },
-	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(15), 1175000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1175000 },
-	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(15), 1187500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1187500 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1200000 },
+	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(14), 1125000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1125000 },
+	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(14), 1150000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1150000 },
+	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(14), 1175000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1175000 },
+	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(14), 1187500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1187500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1200000 },
 	{ 0, { 0 } }
 };
 
@@ -201,15 +200,15 @@
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1000000 },
 	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(5),  1025000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1025000 },
-	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1075000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
-	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1100000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1100000 },
-	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(15), 1125000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1125000 },
-	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(15), 1137500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1137500 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1150000 },
+	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(14), 1075000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1075000 },
+	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(14), 1100000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1100000 },
+	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(14), 1125000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1125000 },
+	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(14), 1137500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1137500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1150000 },
 	{ 0, { 0 } }
 };
 
@@ -227,15 +226,15 @@
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   975000 },
 	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(5),  1000000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1000000 },
-	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1050000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1050000 },
-	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1075000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1075000 },
-	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(15), 1100000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1100000 },
-	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(15), 1112500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1112500 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1125000 },
+	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(14), 1050000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1050000 },
+	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(14), 1075000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1075000 },
+	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(14), 1100000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1100000 },
+	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(14), 1112500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1112500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1125000 },
 	{ 0, { 0 } }
 };
 
@@ -247,11 +246,11 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),  1000000 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1025000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1037500 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1087500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1125000 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1150000 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1162500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1075000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1087500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1125000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1150000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1162500 },
 	{ 0, { 0 } }
 };
 
@@ -263,11 +262,11 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   975000 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1000000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1012500 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1037500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1050000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1087500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1112500 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1125000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1037500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1050000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1087500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1112500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1125000 },
 	{ 0, { 0 } }
 };
 
@@ -279,11 +278,11 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   937500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   950000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   975000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1075000 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1087500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1000000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1012500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1037500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1075000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1087500 },
 	{ 0, { 0 } }
 };
 
@@ -295,11 +294,11 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   900000 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   925000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   950000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  975000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  987500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1037500 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1050000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  975000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  987500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1000000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1037500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1050000 },
 	{ 0, { 0 } }
 };
 
@@ -311,11 +310,11 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  950000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  962500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  975000 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1000000 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1012500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  950000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  962500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  975000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1000000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1012500 },
 	{ 0, { 0 } }
 };
 
@@ -327,11 +326,11 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  987500 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1000000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14),  987500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14), 1000000 },
 	{ 0, { 0 } }
 };
 
@@ -343,11 +342,11 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  975000 },
-	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15),  987500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14),  975000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(14),  987500 },
 	{ 0, { 0 } }
 };
 
@@ -359,13 +358,13 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),  1000000 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1025000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1037500 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1087500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1125000 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1150000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1175000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1225000 },
-	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(15), 1250000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1075000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1087500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1125000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1150000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1175000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1225000 },
+	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(14), 1250000 },
 	{ 0, { 0 } }
 };
 
@@ -377,13 +376,13 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   975000 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1000000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1012500 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1037500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1050000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1087500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1112500 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1150000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1187500 },
-	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(15), 1200000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1037500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1050000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1087500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1112500 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1150000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1187500 },
+	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(14), 1200000 },
 	{ 0, { 0 } }
 };
 
@@ -395,13 +394,13 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   937500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   950000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   975000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1075000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1100000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1137500 },
-	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(15), 1162500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1000000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1012500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1037500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1075000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1100000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1137500 },
+	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(14), 1162500 },
 	{ 0, { 0 } }
 };
 
@@ -413,13 +412,13 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   900000 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   925000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   950000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  975000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  987500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1037500 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1062500 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1100000 },
-	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(15), 1125000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  975000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  987500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1000000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1037500 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1062500 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1100000 },
+	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(14), 1125000 },
 	{ 0, { 0 } }
 };
 
@@ -431,13 +430,13 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  950000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  962500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  975000 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1000000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1037500 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1075000 },
-	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(15), 1100000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  950000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  962500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  975000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1000000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1037500 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1075000 },
+	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(14), 1100000 },
 	{ 0, { 0 } }
 };
 
@@ -449,13 +448,13 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  987500 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1012500 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1050000 },
-	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(15), 1075000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14),  987500 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1012500 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1050000 },
+	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(14), 1075000 },
 	{ 0, { 0 } }
 };
 
@@ -467,13 +466,13 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  975000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1000000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1025000 },
-	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(15), 1050000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14),  975000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1000000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1025000 },
+	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(14), 1050000 },
 	{ 0, { 0 } }
 };
 
@@ -485,14 +484,14 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   962500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   975000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1000000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1025000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1037500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1062500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1100000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1125000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1175000 },
-	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(15), 1225000 },
-	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(15), 1287500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1025000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1037500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1062500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1100000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1125000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1175000 },
+	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(14), 1225000 },
+	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(14), 1287500 },
 	{ 0, { 0 } }
 };
 
@@ -504,14 +503,14 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   937500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   950000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   975000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1075000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1100000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1137500 },
-	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(15), 1187500 },
-	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(15), 1250000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14), 1000000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14), 1012500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1037500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1075000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1100000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1137500 },
+	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(14), 1187500 },
+	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(14), 1250000 },
 	{ 0, { 0 } }
 };
 
@@ -523,14 +522,14 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   912500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   925000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   950000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  975000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  987500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1012500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1050000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1075000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1112500 },
-	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(15), 1162500 },
-	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(15), 1212500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  975000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  987500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1012500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1050000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1075000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1112500 },
+	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(14), 1162500 },
+	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(14), 1212500 },
 	{ 0, { 0 } }
 };
 
@@ -542,14 +541,14 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   900000 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   912500 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   937500 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  962500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  975000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1025000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1050000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1087500 },
-	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(15), 1137500 },
-	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(15), 1175000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  962500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  975000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14), 1000000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1025000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1050000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1087500 },
+	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(14), 1137500 },
+	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(14), 1175000 },
 	{ 0, { 0 } }
 };
 
@@ -561,14 +560,14 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  950000 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  962500 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  975000 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1000000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1037500 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1075000 },
-	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(15), 1112500 },
-	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(15), 1150000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  950000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  962500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  975000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14), 1000000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1037500 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1075000 },
+	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(14), 1112500 },
+	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(14), 1150000 },
 	{ 0, { 0 } }
 };
 
@@ -580,14 +579,14 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  987500 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1012500 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1050000 },
-	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(15), 1087500 },
-	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(15), 1125000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14),  987500 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1012500 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1050000 },
+	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(14), 1087500 },
+	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(14), 1125000 },
 	{ 0, { 0 } }
 };
 
@@ -599,14 +598,14 @@
 	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
 	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
 	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
-	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
-	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
-	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
-	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  975000 },
-	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1000000 },
-	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1025000 },
-	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(15), 1062500 },
-	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(15), 1100000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(14),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(14),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(14),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(14),  975000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(14), 1000000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(14), 1025000 },
+	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(14), 1062500 },
+	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(14), 1100000 },
 	{ 0, { 0 } }
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 25bebd1..a6f772d 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -65,24 +65,23 @@
  * 3) Depending on Frodo version, may need minimum of LVL_NOM
  */
 static struct clkctl_acpu_speed acpu_freq_tbl_8226[] = {
-	{ 0,   19200, CXO,     0, 0,   CPR_CORNER_SVS,   1150000, 0 },
-	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,   1150000, 4 },
-	{ 1,  384000, ACPUPLL, 5, 0,   CPR_CORNER_SVS,   1150000, 4 },
-	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL,   1150000, 6 },
-	{ 1,  787200, ACPUPLL, 5, 0,   CPR_CORNER_NORMAL,   1150000, 7 },
-	{ 0,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,   1150000, 7 },
-	{ 0, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,   1150000, 7 },
+	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,    0, 4 },
+	{ 1,  384000, ACPUPLL, 5, 0,   CPR_CORNER_SVS,    0, 4 },
+	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL, 0, 6 },
+	{ 1,  787200, ACPUPLL, 5, 0,   CPR_CORNER_NORMAL, 0, 7 },
+	{ 1,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 1, 1094400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
+	{ 0, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 7 },
 	{ 0 }
 };
 
 static struct clkctl_acpu_speed acpu_freq_tbl_8610[] = {
-	{ 0,   19200, CXO,     0, 0,   CPR_CORNER_SVS,   1150000, 0 },
-	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,   1150000, 3 },
-	{ 1,  384000, ACPUPLL, 5, 0,   CPR_CORNER_SVS,   1150000, 3 },
-	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL,   1150000, 4 },
-	{ 1,  787200, ACPUPLL, 5, 0,   CPR_CORNER_NORMAL,   1150000, 4 },
-	{ 0,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,   1275000, 5 },
-	{ 0, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,   1275000, 5 },
+	{ 1,  300000, PLL0,    4, 2,   CPR_CORNER_SVS,    0, 3 },
+	{ 1,  384000, ACPUPLL, 5, 0,   CPR_CORNER_SVS,    0, 3 },
+	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL, 0, 4 },
+	{ 1,  787200, ACPUPLL, 5, 0,   CPR_CORNER_NORMAL, 0, 4 },
+	{ 0,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 5 },
+	{ 0, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 5 },
 	{ 0 }
 };
 
@@ -91,7 +90,6 @@
 	.current_speed = &(struct clkctl_acpu_speed){ 0 },
 	.bus_scale = &bus_client_pdata,
 	.vdd_max_cpu = CPR_CORNER_TURBO,
-	.vdd_max_mem = 1150000,
 	.src_clocks = {
 		[PLL0].name = "gpll0",
 		[ACPUPLL].name = "a7sspll",
@@ -130,12 +128,6 @@
 		return PTR_ERR(drv_data.vdd_cpu);
 	}
 
-	drv_data.vdd_mem = devm_regulator_get(&pdev->dev, "a7_mem");
-	if (IS_ERR(drv_data.vdd_mem)) {
-		dev_err(&pdev->dev, "regulator for %s get failed\n", "a7_mem");
-		return PTR_ERR(drv_data.vdd_mem);
-	}
-
 	for (i = 0; i < NUM_SRC; i++) {
 		if (!drv_data.src_clocks[i].name)
 			continue;
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index c60e89a..a61f5ca 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -128,122 +128,122 @@
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),  825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),  825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),  825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),  825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),  825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),  825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10), 825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10), 825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10), 825000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10), 825000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12), 885000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),  825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),  825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),  825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),  825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),  825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),  825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),  825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10), 825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10), 825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10), 825000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10), 825000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12), 885000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 950000, 506 },
 	{ 0, { 0 } }
 };
 
@@ -284,618 +284,618 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  815000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  835000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  845000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  855000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  865000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  875000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  890000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  900000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  915000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  925000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  940000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  950000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  965000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  980000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  995000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16), 1010000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1025000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1040000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1055000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1070000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1085000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  815000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  835000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  845000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  855000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  865000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  875000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  890000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  900000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  915000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  925000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  940000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  950000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  965000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  980000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  995000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16), 1010000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1025000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1040000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1055000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1070000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1085000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  810000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  820000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  830000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  840000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  850000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  860000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  875000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  885000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  895000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  920000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  930000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  945000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  975000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1005000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1020000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1030000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1045000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1060000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  810000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  820000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  830000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  840000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  850000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  860000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  875000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  885000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  895000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  920000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  930000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  945000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  975000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1005000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1020000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1030000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1045000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1060000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  785000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  795000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  910000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  955000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1005000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1020000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1035000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  785000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  795000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  910000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  955000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1005000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1020000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1035000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  780000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  790000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  935000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  970000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  985000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  995000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1010000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  780000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  790000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  935000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  970000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  985000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  995000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1010000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  780000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  790000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  870000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  880000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  950000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  960000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  975000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  985000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  780000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  790000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  870000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  880000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  950000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  960000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  975000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  985000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  760000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  770000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  780000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  790000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  800000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  810000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  820000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  830000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  840000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  860000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  870000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  880000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  920000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  930000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  940000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  955000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  965000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  760000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  770000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  780000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  790000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  800000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  810000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  820000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  830000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  840000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  860000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  870000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  880000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  920000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  930000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  940000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  955000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  965000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  760000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  770000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  870000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  905000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  915000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  760000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  770000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  870000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  905000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  915000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  915000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  950000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  965000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1010000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1025000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1040000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  915000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  950000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  965000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1010000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1025000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1040000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  920000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  930000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  945000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  975000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  990000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1005000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1020000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  920000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  930000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  945000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  975000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  990000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1005000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1020000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  785000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  795000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  805000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  815000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  835000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  845000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  865000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  875000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  890000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  900000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  910000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  925000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  955000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  970000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  980000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  995000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  785000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  795000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  805000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  815000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  825000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  835000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  845000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  865000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  875000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  890000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  900000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  910000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  925000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  955000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  970000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  980000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  995000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  885000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  895000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  935000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  950000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  960000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  970000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  985000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  995000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  885000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  895000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  935000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  950000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  960000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  970000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  985000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  995000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  870000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  880000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  920000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  930000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  940000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  950000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  960000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  975000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  985000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  870000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  880000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  920000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  930000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  940000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  950000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  960000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  975000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  985000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  760000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  770000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  890000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  900000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  910000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  920000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  930000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  940000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  955000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  965000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  760000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  770000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  890000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  900000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  910000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  920000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  930000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  940000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  955000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  965000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  975000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  875000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  885000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  895000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  905000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  915000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  920000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  930000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  940000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  875000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  885000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  895000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  905000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  915000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  920000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  930000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  940000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  950000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  805000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  815000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  835000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  845000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  855000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  865000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  890000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  900000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  915000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  940000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  965000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  980000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  995000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1010000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1025000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  805000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  815000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  825000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  835000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  845000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  855000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  865000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  890000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  900000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  915000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  940000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  965000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  980000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  995000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1010000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1025000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  875000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  885000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  945000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  960000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  975000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  990000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1005000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  875000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  885000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  945000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  960000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  975000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  990000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1005000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  785000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  795000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  805000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  815000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  825000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  845000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  855000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  865000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  940000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  955000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  970000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  980000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  785000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  795000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  805000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  815000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  825000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  835000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  845000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  855000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  865000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  940000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  955000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  970000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  980000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  925000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  935000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  950000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  960000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  995000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  925000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  935000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  950000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  960000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  995000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  775000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  895000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  910000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  975000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  985000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  775000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  895000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  910000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  975000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  985000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  880000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  890000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  900000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  910000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  920000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  955000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  965000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  880000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  890000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  900000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  910000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  920000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  955000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  965000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  975000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  750000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  760000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  770000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  780000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  790000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  810000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  820000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  830000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  840000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  850000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  870000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  875000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  885000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  895000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  905000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  930000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  940000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  750000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  760000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  770000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  780000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  790000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  810000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  820000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  830000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  840000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  850000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  870000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  875000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  885000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  895000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  905000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  930000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  940000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  950000, 691 },
 	{ 0, { 0 } }
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
index 47bf27a..0c80a56 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.c
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -66,11 +66,17 @@
 {
 	int rc = 0;
 
-	/* Increase vdd_mem before vdd_cpu. vdd_mem should be >= vdd_cpu. */
-	rc = regulator_set_voltage(priv->vdd_mem, vdd_mem, priv->vdd_max_mem);
-	if (rc) {
-		pr_err("vdd_mem increase failed (%d)\n", rc);
-		return rc;
+	if (priv->vdd_mem) {
+		/*
+		 * Increase vdd_mem before vdd_cpu. vdd_mem should
+		 * be >= vdd_cpu.
+		 */
+		rc = regulator_set_voltage(priv->vdd_mem, vdd_mem,
+						priv->vdd_max_mem);
+		if (rc) {
+			pr_err("vdd_mem increase failed (%d)\n", rc);
+			return rc;
+		}
 	}
 
 	rc = regulator_set_voltage(priv->vdd_cpu, vdd_cpu, priv->vdd_max_cpu);
@@ -92,6 +98,9 @@
 		return;
 	}
 
+	if (!priv->vdd_mem)
+		return;
+
 	/* Decrease vdd_mem after vdd_cpu. vdd_mem should be >= vdd_cpu. */
 	ret = regulator_set_voltage(priv->vdd_mem, vdd_mem, priv->vdd_max_mem);
 	if (ret)
@@ -343,10 +352,12 @@
 	if (rc)
 		goto err_vdd;
 
-	rc = regulator_enable(priv->vdd_mem);
-	if (rc) {
-		dev_err(&pdev->dev, "regulator_enable for mem failed\n");
-		goto err_vdd;
+	if (priv->vdd_mem) {
+		rc = regulator_enable(priv->vdd_mem);
+		if (rc) {
+			dev_err(&pdev->dev, "regulator_enable for mem failed\n");
+			goto err_vdd;
+		}
 	}
 
 	rc = regulator_enable(priv->vdd_cpu);
@@ -369,7 +380,8 @@
 	return 0;
 
 err_vdd_cpu:
-	regulator_disable(priv->vdd_mem);
+	if (priv->vdd_mem)
+		regulator_disable(priv->vdd_mem);
 err_vdd:
 	return rc;
 }
diff --git a/arch/arm/mach-msm/board-8084.c b/arch/arm/mach-msm/board-8084.c
index 828ae9c..0a13c56 100644
--- a/arch/arm/mach-msm/board-8084.c
+++ b/arch/arm/mach-msm/board-8084.c
@@ -53,6 +53,14 @@
 	.paddr_to_memtype = apq8084_paddr_to_memtype,
 };
 
+static struct of_dev_auxdata apq8084_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9824000, \
+			"msm_sdcc.1", NULL),
+	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
+			"msm_sdcc.2", NULL),
+	{}
+};
+
 void __init apq8084_reserve(void)
 {
 	reserve_info = &apq8084_reserve_info;
@@ -69,6 +77,17 @@
 static struct clk_lookup msm_clocks_dummy[] = {
 	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
 	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("core_clk",	SDC1_CLK,	"msm_sdcc.1", OFF),
+	CLK_DUMMY("iface_clk",	SDC1_P_CLK,	"msm_sdcc.1", OFF),
+	CLK_DUMMY("core_clk",	SDC2_CLK,	"msm_sdcc.2", OFF),
+	CLK_DUMMY("iface_clk",	SDC2_P_CLK,	"msm_sdcc.2", OFF),
+	CLK_DUMMY("xo",   NULL, "f9200000.qcom,ssusb", OFF),
+	CLK_DUMMY("core_clk",   NULL, "f9200000.qcom,ssusb", OFF),
+	CLK_DUMMY("iface_clk",  NULL, "f9200000.qcom,ssusb", OFF),
+	CLK_DUMMY("sleep_clk",  NULL, "f9200000.qcom,ssusb", OFF),
+	CLK_DUMMY("sleep_a_clk",   NULL, "f9200000.qcom,ssusb", OFF),
+	CLK_DUMMY("utmi_clk",   NULL, "f9200000.qcom,ssusb", OFF),
+	CLK_DUMMY("ref_clk",    NULL, "f9200000.qcom,ssusb", OFF),
 };
 
 static struct clock_init_data msm_dummy_clock_init_data __initdata = {
@@ -95,11 +114,13 @@
 
 void __init apq8084_init(void)
 {
+	struct of_dev_auxdata *adata = apq8084_auxdata_lookup;
+
 	if (socinfo_init() < 0)
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	apq8084_init_gpiomux();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
 	apq8084_add_drivers();
 }
 
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 4b435de..93645c7 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -23,6 +23,12 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+static struct gpiomux_setting gpio_cam_i2c_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct gpiomux_setting gpio_spi_config = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_6MA,
@@ -60,6 +66,18 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting gpio_keys_active = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting gpio_keys_suspend = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
 	{
 		.gpio = 41,
@@ -91,6 +109,18 @@
 		},
 	},
 	{
+		.gpio      = 16,	/* BLSP1 QUP6 I2C_SDA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_cam_i2c_config,
+		},
+	},
+	{
+		.gpio      = 17,	/* BLSP1 QUP6 I2C_SCL */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_cam_i2c_config,
+		},
+	},
+	{
 		.gpio      = 0,		/* BLSP1 QUP1 SPI_DATA_MOSI */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
@@ -154,6 +184,54 @@
 	},
 };
 
+static struct msm_gpiomux_config msm_keypad_configs[] __initdata = {
+	{
+		.gpio = 72,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &gpio_keys_active,
+			[GPIOMUX_SUSPENDED] = &gpio_keys_suspend,
+		},
+	},
+	{
+		.gpio = 73,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &gpio_keys_active,
+			[GPIOMUX_SUSPENDED] = &gpio_keys_suspend,
+		},
+	},
+	{
+		.gpio = 74,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &gpio_keys_active,
+			[GPIOMUX_SUSPENDED] = &gpio_keys_suspend,
+		},
+	},
+};
+
+static struct gpiomux_setting sd_card_det_active_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_IN,
+};
+
+static struct gpiomux_setting sd_card_det_suspend_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+	.dir = GPIOMUX_IN,
+};
+
+static struct msm_gpiomux_config sd_card_det[] __initdata = {
+	{
+		.gpio = 42,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sd_card_det_active_config,
+			[GPIOMUX_SUSPENDED] = &sd_card_det_suspend_config,
+		},
+	},
+};
+
 void __init msm8610_init_gpiomux(void)
 {
 	int rc;
@@ -168,4 +246,7 @@
 	msm_gpiomux_install(wcnss_5wire_interface,
 			ARRAY_SIZE(wcnss_5wire_interface));
 	msm_gpiomux_install(msm_lcd_configs, ARRAY_SIZE(msm_lcd_configs));
+	msm_gpiomux_install(msm_keypad_configs,
+				ARRAY_SIZE(msm_keypad_configs));
+	msm_gpiomux_install(sd_card_det, ARRAY_SIZE(sd_card_det));
 }
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 6ccaba6..f404e42 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -2356,6 +2356,7 @@
 	&msm_pcm_hostless,
 	&msm_multi_ch_pcm,
 	&msm_lowlatency_pcm,
+	&msm_fm_loopback,
 };
 
 static void __init msm8930_i2c_init(void)
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index cd0d337..486842f 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -169,7 +169,7 @@
 	VDD_DIG_NUM
 };
 
-static const int *vdd_corner[] = {
+static int *vdd_corner[] = {
 	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
 	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
 	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
@@ -2753,7 +2753,7 @@
 	VDD_SR2_PLL_NUM
 };
 
-static const int *vdd_sr2_levels[] = {
+static int *vdd_sr2_levels[] = {
 	[VDD_SR2_PLL_OFF] = VDD_UV(0,       RPM_REGULATOR_CORNER_NONE),
 	[VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
 	[VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
@@ -2766,6 +2766,7 @@
 	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL( 787200000, 41, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL( 998400000, 52, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1094400000, 57, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1190400000, 62, 0x0, 0x1, 0x0, 0x0, 0x0),
 	PLL_F_END
 };
@@ -3428,6 +3429,18 @@
 	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16390"),
 	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16391"),
 
+	/* Add QCEDEV clocks */
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,      "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,  "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,  "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,      "fd400000.qcom,qcedev"),
+
+	/* Add QCRYPTO clocks */
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,     "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c, "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c, "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,     "fd404000.qcom,qcrypto"),
+
 };
 
 static struct clk_lookup msm_clocks_8226_rumi[] = {
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 3cb3ea4..1de6abf 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -30,6 +30,7 @@
 #include "clock-rpm.h"
 #include "clock-voter.h"
 #include "clock.h"
+#include "clock-dsi-8610.h"
 
 enum {
 	GCC_BASE,
@@ -255,6 +256,7 @@
 #define          MMSS_MMSSNOC_AXI_CBCR	    0x506C
 #define                   BIMC_GFX_BCR	    0x5090
 #define                  BIMC_GFX_CBCR	    0x5094
+#define                MMSS_CAMSS_MISC	    0x3718
 
 #define				AUDIO_CORE_GDSCR	    0x7000
 #define                                 SPDM_BCR	    0x1000
@@ -432,7 +434,7 @@
 	VDD_DIG_NUM
 };
 
-static const int *vdd_corner[] = {
+static int *vdd_corner[] = {
 	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
 	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
 	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
@@ -531,7 +533,7 @@
 	VDD_SR2_PLL_NUM
 };
 
-static const int *vdd_sr2_levels[] = {
+static int *vdd_sr2_levels[] = {
 	[VDD_SR2_PLL_OFF] = VDD_UV(0,       RPM_REGULATOR_CORNER_NONE),
 	[VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
 	[VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
@@ -1560,21 +1562,85 @@
 static DEFINE_CLK_VOTER(mdp_axi_clk_src, &axi_clk_src.c, 200000000);
 static DEFINE_CLK_VOTER(mmssnoc_axi_clk_src, &axi_clk_src.c, 200000000);
 
-static struct clk_freq_tbl ftbl_dsi_pclk_clk[] = {
-	F_MDSS( 50000000, dsipll, 10, 0, 0),
-	F_MDSS(103330000, dsipll,  9, 0, 0),
-	F_END,
+static struct clk_ops dsi_byte_clk_src_ops;
+static struct clk_ops dsi_pixel_clk_src_ops;
+static struct clk_ops dsi_dsi_clk_src_ops;
+
+static struct dsi_pll_vco_clk dsi_vco  = {
+	.vco_clk_min =  600000000,
+	.vco_clk_max = 1200000000,
+	.pref_div_ratio = 26,
+	.c = {
+		.parent = &gcc_xo_clk_src.c,
+		.dbg_name = "dsi_vco",
+		.ops = &clk_ops_dsi_vco,
+		CLK_INIT(dsi_vco.c),
+	},
 };
 
+static struct clk dsi_pll_byte = {
+	.parent = &dsi_vco.c,
+	.dbg_name = "dsi_pll_byte",
+	.ops = &clk_ops_dsi_byteclk,
+	CLK_INIT(dsi_pll_byte),
+};
+
+static struct clk dsi_pll_pixel = {
+	.parent = &dsi_vco.c,
+	.dbg_name = "dsi_pll_pixel",
+	.ops = &clk_ops_dsi_dsiclk,
+	CLK_INIT(dsi_pll_pixel),
+};
+
+static struct clk_freq_tbl pixel_freq_tbl[] = {
+	{
+		.src_clk = &dsi_pll_pixel,
+		.div_src_val = BVAL(10, 8, dsipll_mm_source_val),
+	},
+	F_END
+};
+
+#define CFG_RCGR_DIV_MASK		BM(4, 0)
+
+static int set_rate_pixel_byte_clk(struct clk *clk, unsigned long rate)
+{
+	struct rcg_clk *rcg = to_rcg_clk(clk);
+	struct clk *pll = clk->parent;
+	unsigned long source_rate, div;
+	struct clk_freq_tbl *cur_freq = rcg->current_freq;
+	int rc;
+
+	if (rate == 0)
+		return clk_set_rate(pll, 0);
+
+	source_rate = clk_round_rate(pll, rate);
+	if (!source_rate || ((2 * source_rate) % rate))
+		return -EINVAL;
+
+	div = ((2 * source_rate)/rate) - 1;
+	if (div > CFG_RCGR_DIV_MASK)
+		return -EINVAL;
+
+	rc = clk_set_rate(pll, source_rate);
+	if (rc)
+		return rc;
+
+	cur_freq->div_src_val &= ~CFG_RCGR_DIV_MASK;
+	cur_freq->div_src_val |= BVAL(4, 0, div);
+	rcg->set_rate(rcg, cur_freq);
+
+	return 0;
+}
+
 static struct rcg_clk dsi_pclk_clk_src = {
 	.cmd_rcgr_reg =  DSI_PCLK_CMD_RCGR,
 	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_dsi_pclk_clk,
-	.current_freq = &rcg_dummy_freq,
+	.current_freq = pixel_freq_tbl,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
+		.parent = &dsi_pll_pixel,
 		.dbg_name = "dsi_pclk_clk_src",
-		.ops = &clk_ops_rcg_mnd,
+		.ops = &dsi_pixel_clk_src_ops,
 		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 103330000),
 		CLK_INIT(dsi_pclk_clk_src.c),
 	},
@@ -1686,41 +1752,60 @@
 	},
 };
 
-static struct clk_freq_tbl ftbl_dsi_clk[] = {
-	F_MDSS(155000000,  dsipll, 6, 0, 0),
-	F_MDSS(310000000,  dsipll, 3, 0, 0),
-	F_END,
+/*
+ * The DSI clock will always use a divider of 1. However, we still
+ * need to set the right voltage and source.
+ */
+static int set_rate_dsi_clk(struct clk *clk, unsigned long rate)
+{
+	struct rcg_clk *rcg = to_rcg_clk(clk);
+	struct clk_freq_tbl *cur_freq = rcg->current_freq;
+
+	rcg->set_rate(rcg, cur_freq);
+
+	return 0;
+}
+
+static struct clk_freq_tbl dsi_freq_tbl[] = {
+	{
+		.src_clk = &dsi_pll_pixel,
+		.div_src_val =  BVAL(4, 0, 0) |
+			BVAL(10, 8, dsipll_mm_source_val),
+	},
+	F_END
 };
 
 static struct rcg_clk dsi_clk_src = {
 	.cmd_rcgr_reg =  DSI_CMD_RCGR,
 	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_dsi_clk,
-	.current_freq = &rcg_dummy_freq,
+	.current_freq = dsi_freq_tbl,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
+		.parent = &dsi_pll_pixel,
 		.dbg_name = "dsi_clk_src",
-		.ops = &clk_ops_rcg_mnd,
+		.ops = &dsi_dsi_clk_src_ops,
 		VDD_DIG_FMAX_MAP2(LOW, 155000000, NOMINAL, 310000000),
 		CLK_INIT(dsi_clk_src.c),
 	},
 };
 
-static struct clk_freq_tbl ftbl_dsi_byte_clk[] = {
-	F_MDSS( 62500000, dsipll, 12, 0, 0),
-	F_MDSS(125000000, dsipll,  6, 0, 0),
-	F_END,
+static struct clk_freq_tbl byte_freq_tbl[] = {
+	{
+		.src_clk = &dsi_pll_byte,
+		.div_src_val = BVAL(10, 8, dsipll_mm_source_val),
+	},
+	F_END
 };
 
 static struct rcg_clk dsi_byte_clk_src = {
 	.cmd_rcgr_reg = DSI_BYTE_CMD_RCGR,
 	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_dsi_byte_clk,
-	.current_freq = &rcg_dummy_freq,
+	.current_freq = byte_freq_tbl,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
+		.parent = &dsi_pll_byte,
 		.dbg_name = "dsi_byte_clk_src",
-		.ops = &clk_ops_rcg,
+		.ops = &dsi_byte_clk_src_ops,
 		VDD_DIG_FMAX_MAP2(LOW, 62500000, NOMINAL, 125000000),
 		CLK_INIT(dsi_byte_clk_src.c),
 	},
@@ -1932,6 +2017,115 @@
 	},
 };
 
+static struct mux_clk csi0phy_mux_clk = {
+	.enable_reg = MMSS_CAMSS_MISC,
+	.enable_mask = BIT(11),
+	.select_reg = MMSS_CAMSS_MISC,
+	.select_mask = BIT(9),
+	.sources = (struct mux_source[]) {
+		{ &csi0phy_clk.c,     0 },
+		{ &csi1phy_clk.c, BIT(9) },
+		{ 0 },
+	},
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi0phy_mux_clk",
+		.ops = &clk_ops_mux,
+		CLK_INIT(csi0phy_mux_clk.c),
+	},
+};
+
+static struct mux_clk csi1phy_mux_clk = {
+	.enable_reg = MMSS_CAMSS_MISC,
+	.enable_mask = BIT(10),
+	.select_reg = MMSS_CAMSS_MISC,
+	.select_mask = BIT(8),
+	.sources = (struct mux_source[]) {
+		{ &csi0phy_clk.c,     0 },
+		{ &csi1phy_clk.c, BIT(8) },
+		{ 0 },
+	},
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi1phy_mux_clk",
+		.ops = &clk_ops_mux,
+		CLK_INIT(csi1phy_mux_clk.c),
+	},
+};
+
+static struct mux_clk csi0pix_mux_clk = {
+	.enable_reg = MMSS_CAMSS_MISC,
+	.enable_mask = BIT(7),
+	.select_reg = MMSS_CAMSS_MISC,
+	.select_mask = BIT(3),
+	.sources = (struct mux_source[]) {
+		{ &csi0pix_clk.c,      0 },
+		{ &csi1pix_clk.c, BIT(3) },
+		{ 0 },
+	},
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "csi0pix_mux_clk",
+		.ops = &clk_ops_mux,
+		CLK_INIT(csi0pix_mux_clk.c),
+	},
+};
+
+
+static struct mux_clk rdi2_mux_clk = {
+	.enable_reg = MMSS_CAMSS_MISC,
+	.enable_mask = BIT(6),
+	.select_reg = MMSS_CAMSS_MISC,
+	.select_mask = BIT(2),
+	.sources = (struct mux_source[]) {
+		{ &csi0rdi_clk.c,      0 },
+		{ &csi1rdi_clk.c, BIT(2) },
+		{ 0 },
+	},
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "rdi2_mux_clk",
+		.ops = &clk_ops_mux,
+		CLK_INIT(rdi2_mux_clk.c),
+	},
+};
+
+static struct mux_clk rdi1_mux_clk = {
+	.enable_reg = MMSS_CAMSS_MISC,
+	.enable_mask = BIT(5),
+	.select_reg = MMSS_CAMSS_MISC,
+	.select_mask = BIT(1),
+	.sources = (struct mux_source[]) {
+		{ &csi0rdi_clk.c,      0 },
+		{ &csi1rdi_clk.c, BIT(1) },
+		{ 0 },
+	},
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "rdi1_mux_clk",
+		.ops = &clk_ops_mux,
+		CLK_INIT(rdi1_mux_clk.c),
+	},
+};
+
+static struct mux_clk rdi0_mux_clk = {
+	.enable_reg = MMSS_CAMSS_MISC,
+	.enable_mask = BIT(4),
+	.select_reg = MMSS_CAMSS_MISC,
+	.select_mask = BIT(0),
+	.sources = (struct mux_source[]) {
+		{ &csi0rdi_clk.c,      0 },
+		{ &csi1rdi_clk.c, BIT(0) },
+		{ 0 },
+	},
+	.base = &virt_bases[MMSS_BASE],
+	.c = {
+		.dbg_name = "rdi0_mux_clk",
+		.ops = &clk_ops_mux,
+		CLK_INIT(rdi0_mux_clk.c),
+	},
+};
+
 static struct branch_clk csi_ahb_clk = {
 	.cbcr_reg = CSI_AHB_CBCR,
 	.has_sibling = 1,
@@ -2004,7 +2198,6 @@
 
 static struct branch_clk dsi_pclk_clk = {
 	.cbcr_reg = DSI_PCLK_CBCR,
-	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.parent = &dsi_pclk_clk_src.c,
@@ -2691,7 +2884,8 @@
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup4_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup5_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup5_spi_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk",  gcc_blsp1_qup6_i2c_apps_clk.c, ""),
+	CLK_LOOKUP("iface_clk",           gcc_blsp1_ahb_clk.c, "f9928000.i2c"),
+	CLK_LOOKUP("core_clk",  gcc_blsp1_qup6_i2c_apps_clk.c, "f9928000.i2c"),
 	CLK_LOOKUP("core_clk",  gcc_blsp1_qup6_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",     gcc_blsp1_uart1_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk",     gcc_blsp1_uart2_apps_clk.c, ""),
@@ -2773,6 +2967,13 @@
 	CLK_LOOKUP("core_clk",                  vfe_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk",                  vfe_axi_clk.c, ""),
 
+	CLK_LOOKUP("core_clk",              csi0pix_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",              csi0phy_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",              csi1phy_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",                 rdi2_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",                 rdi1_mux_clk.c, ""),
+	CLK_LOOKUP("core_clk",                 rdi0_mux_clk.c, ""),
+
 	CLK_LOOKUP("core_clk",   oxili_gfx3d_clk.c, "fdc00000.qcom,kgsl-3d0"),
 	CLK_LOOKUP("iface_clk",    oxili_ahb_clk.c, "fdc00000.qcom,kgsl-3d0"),
 	CLK_LOOKUP("mem_iface_clk", bimc_gfx_clk.c, "fdc00000.qcom,kgsl-3d0"),
@@ -2957,6 +3158,26 @@
 	clk_set_rate(&mclk1_clk_src.c, mclk1_clk_src.freq_tbl[0].freq_hz);
 }
 
+static void dsi_init(void)
+{
+	dsi_byte_clk_src_ops = clk_ops_rcg;
+	dsi_byte_clk_src_ops.set_rate = set_rate_pixel_byte_clk;
+	dsi_byte_clk_src_ops.handoff = byte_rcg_handoff;
+	dsi_byte_clk_src_ops.get_parent = NULL;
+
+	dsi_dsi_clk_src_ops = clk_ops_rcg_mnd;
+	dsi_dsi_clk_src_ops.set_rate = set_rate_dsi_clk;
+	dsi_dsi_clk_src_ops.handoff = pixel_rcg_handoff;
+	dsi_dsi_clk_src_ops.get_parent = NULL;
+
+	dsi_pixel_clk_src_ops = clk_ops_rcg_mnd;
+	dsi_pixel_clk_src_ops.set_rate = set_rate_pixel_byte_clk;
+	dsi_pixel_clk_src_ops.handoff = pixel_rcg_handoff;
+	dsi_pixel_clk_src_ops.get_parent = NULL;
+
+	dsi_clk_ctrl_init(&dsi_ahb_clk.c);
+}
+
 #define GCC_CC_PHYS		0xFC400000
 #define GCC_CC_SIZE		SZ_16K
 
@@ -3016,6 +3237,8 @@
 
 	reg_init();
 
+	dsi_init();
+
 	/* Maintain the max nominal frequency on the MMSSNOC AHB bus. */
 	clk_set_rate(&mmssnoc_ahb_a_clk.c,  40000000);
 	clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 707e6b6..ad19fd2 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -638,7 +638,7 @@
 	VDD_DIG_NUM
 };
 
-static const int *vdd_corner[] = {
+static int *vdd_corner[] = {
 	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
 	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
 	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
@@ -920,6 +920,7 @@
 };
 
 static struct clk_freq_tbl ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk[] = {
+	F(19200000,    cxo,   1,   0,   0),
 	F(50000000,  gpll0,  12,   0,   0),
 	F_END
 };
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 4984255..65176b4 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -280,7 +280,7 @@
 	VDD_DIG_NUM
 };
 
-static const int *vdd_corner[] = {
+static int *vdd_corner[] = {
 	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
 	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
 	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
@@ -1620,11 +1620,6 @@
 	{&gcc_sdcc2_ahb_clk.c,			GCC_BASE, 0x0071},
 	{&gcc_ce1_clk.c,			GCC_BASE, 0x0138},
 	{&gcc_sys_noc_ipa_axi_clk.c,		GCC_BASE, 0x0007},
-	{&gcc_ipa_clk.c,			GCC_BASE, 0x01E0},
-	{&gcc_ipa_cnoc_clk.c,			GCC_BASE, 0x01E1},
-	{&gcc_ipa_sleep_clk.c,			GCC_BASE, 0x01E2},
-	{&gcc_qpic_clk.c,			GCC_BASE, 0x01D8},
-	{&gcc_qpic_ahb_clk.c,			GCC_BASE, 0x01D9},
 
 	{&a5_m_clk,				APCS_BASE, 0x3},
 
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index d540f2b..fe43b72 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2007-2013, The Linux Foundation. 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
@@ -21,10 +21,23 @@
 #include <linux/clk.h>
 #include <linux/list.h>
 #include <linux/clkdev.h>
+#include <linux/uaccess.h>
 #include <mach/clk-provider.h>
 
 #include "clock.h"
 
+static LIST_HEAD(clk_list);
+static DEFINE_SPINLOCK(clk_list_lock);
+
+static struct dentry *debugfs_base;
+static u32 debug_suspend;
+
+struct clk_table {
+	struct list_head node;
+	struct clk_lookup *clocks;
+	size_t num_clocks;
+};
+
 static int clock_debug_rate_set(void *data, u64 val)
 {
 	struct clk *clock = data;
@@ -218,35 +231,68 @@
 	.release	= seq_release,
 };
 
-static int clock_parent_show(struct seq_file *m, void *unused)
+static ssize_t clock_parent_read(struct file *filp, char __user *ubuf,
+		size_t cnt, loff_t *ppos)
 {
-	struct clk *clock = m->private;
-	struct clk *parent = clk_get_parent(clock);
+	struct clk *clock = filp->private_data;
+	struct clk *p = clock->parent;
+	char name[256] = {0};
 
-	seq_printf(m, "%s\n", (parent ? parent->dbg_name : "None"));
+	snprintf(name, sizeof(name), "%s\n", p ? p->dbg_name : "None\n");
 
-	return 0;
+	return simple_read_from_buffer(ubuf, cnt, ppos, name, strlen(name));
 }
 
-static int clock_parent_open(struct inode *inode, struct file *file)
+
+static ssize_t clock_parent_write(struct file *filp,
+		const char __user *ubuf, size_t cnt, loff_t *ppos)
 {
-	return single_open(file, clock_parent_show, inode->i_private);
+	struct clk *clock = filp->private_data;
+	char buf[256];
+	char *cmp;
+	unsigned long flags;
+	struct clk_table *table;
+	int i, ret;
+	struct clk *parent = NULL;
+
+	cnt = min(cnt, sizeof(buf) - 1);
+	if (copy_from_user(&buf, ubuf, cnt))
+		return -EFAULT;
+	buf[cnt] = '\0';
+	cmp = strstrip(buf);
+
+	spin_lock_irqsave(&clk_list_lock, flags);
+	list_for_each_entry(table, &clk_list, node) {
+		for (i = 0; i < table->num_clocks; i++)
+			if (!strcmp(cmp, table->clocks[i].clk->dbg_name)) {
+				parent = table->clocks[i].clk;
+				break;
+			}
+		if (parent)
+			break;
+	}
+
+	if (!parent) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	spin_unlock_irqrestore(&clk_list_lock, flags);
+	ret = clk_set_parent(clock, table->clocks[i].clk);
+	if (ret)
+		return ret;
+
+	return cnt;
+err:
+	spin_unlock_irqrestore(&clk_list_lock, flags);
+	return ret;
 }
 
+
 static const struct file_operations clock_parent_fops = {
-	.open		= clock_parent_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-static struct dentry *debugfs_base;
-static u32 debug_suspend;
-
-struct clk_table {
-	struct list_head node;
-	struct clk_lookup *clocks;
-	size_t num_clocks;
+	.open		= simple_open,
+	.read		= clock_parent_read,
+	.write		= clock_parent_write,
 };
 
 static int clock_debug_add(struct clk *clock)
@@ -305,8 +351,6 @@
 	debugfs_remove_recursive(clk_dir);
 	return -ENOMEM;
 }
-static LIST_HEAD(clk_list);
-static DEFINE_SPINLOCK(clk_list_lock);
 
 /**
  * clock_debug_register() - Add additional clocks to clock debugfs hierarchy
diff --git a/arch/arm/mach-msm/clock-dsi-8610.c b/arch/arm/mach-msm/clock-dsi-8610.c
new file mode 100644
index 0000000..44b332e
--- /dev/null
+++ b/arch/arm/mach-msm/clock-dsi-8610.c
@@ -0,0 +1,408 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/iopoll.h>
+#include <linux/clk.h>
+
+#include <asm/processor.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk-provider.h>
+
+#include "clock-dsi-8610.h"
+
+#define DSI_PHY_PHYS		0xFDD00000
+#define DSI_PHY_SIZE		0x00100000
+
+#define DSI_CTRL		0x0000
+#define DSI_DSIPHY_PLL_CTRL_0	0x0200
+#define DSI_DSIPHY_PLL_CTRL_1	0x0204
+#define DSI_DSIPHY_PLL_CTRL_2	0x0208
+#define DSI_DSIPHY_PLL_CTRL_3	0x020C
+#define DSI_DSIPHY_PLL_RDY	0x0280
+#define DSI_DSIPHY_PLL_CTRL_8	0x0220
+#define DSI_DSIPHY_PLL_CTRL_9	0x0224
+#define DSI_DSIPHY_PLL_CTRL_10	0x0228
+
+#define DSI_BPP			3
+#define DSI_PLL_RDY_BIT		0x01
+#define DSI_PLL_RDY_LOOP_COUNT	80000
+#define DSI_MAX_DIVIDER		256
+
+static unsigned char *dsi_base;
+static struct clk *dsi_ahb_clk;
+
+int __init dsi_clk_ctrl_init(struct clk *ahb_clk)
+{
+	dsi_base = ioremap(DSI_PHY_PHYS, DSI_PHY_SIZE);
+	if (!dsi_base) {
+		pr_err("unable to remap dsi base\n");
+		return -ENODEV;
+	}
+
+	dsi_ahb_clk = ahb_clk;
+	return 0;
+}
+
+static int dsi_pll_vco_enable(struct clk *c)
+{
+	u32 status;
+	int i = 0, ret = 0;
+
+	ret = clk_enable(dsi_ahb_clk);
+	if (ret) {
+		pr_err("fail to enable dsi ahb clk\n");
+		return ret;
+	}
+
+	writel_relaxed(0x01, dsi_base + DSI_DSIPHY_PLL_CTRL_0);
+
+	do {
+		status = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_RDY);
+	} while (!(status & DSI_PLL_RDY_BIT) && (i++ < DSI_PLL_RDY_LOOP_COUNT));
+
+	if (!(status & DSI_PLL_RDY_BIT)) {
+		pr_err("DSI PLL not ready, polling time out!\n");
+		ret = -ETIMEDOUT;
+	}
+
+	clk_disable(dsi_ahb_clk);
+
+	return ret;
+}
+
+static void dsi_pll_vco_disable(struct clk *c)
+{
+	int ret;
+
+	ret = clk_enable(dsi_ahb_clk);
+	if (ret) {
+		pr_err("fail to enable dsi ahb clk\n");
+		return;
+	}
+
+	writel_relaxed(0x00, dsi_base + DSI_DSIPHY_PLL_CTRL_0);
+	clk_disable(dsi_ahb_clk);
+}
+
+static int dsi_pll_vco_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret;
+	u32 temp, val;
+	unsigned long fb_divider;
+	struct clk *parent = c->parent;
+	struct dsi_pll_vco_clk *vco_clk =
+				container_of(c, struct dsi_pll_vco_clk, c);
+
+	if (!rate)
+		return 0;
+
+	ret = clk_prepare_enable(dsi_ahb_clk);
+	if (ret) {
+		pr_err("fail to enable dsi ahb clk\n");
+		return ret;
+	}
+
+	temp = rate / 10;
+	val = parent->rate / 10;
+	fb_divider = (temp * vco_clk->pref_div_ratio) / val;
+	fb_divider = fb_divider / 2 - 1;
+
+	temp =  readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_1);
+	val = (temp & 0xFFFFFF00) | (fb_divider & 0xFF);
+	writel_relaxed(val, dsi_base + DSI_DSIPHY_PLL_CTRL_1);
+
+	temp =  readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_2);
+	val = (temp & 0xFFFFFFF8) | ((fb_divider >> 8) & 0x07);
+	writel_relaxed(val, dsi_base + DSI_DSIPHY_PLL_CTRL_2);
+
+	temp =  readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_3);
+	val = (temp & 0xFFFFFFC0) | (vco_clk->pref_div_ratio - 1);
+	writel_relaxed(val, dsi_base + DSI_DSIPHY_PLL_CTRL_3);
+
+	clk_disable_unprepare(dsi_ahb_clk);
+
+	return 0;
+}
+
+/* rate is the bit clk rate */
+static long dsi_pll_vco_round_rate(struct clk *c, unsigned long rate)
+{
+	long vco_rate;
+	struct dsi_pll_vco_clk *vco_clk =
+		container_of(c, struct dsi_pll_vco_clk, c);
+
+
+	vco_rate = rate;
+	if (rate < vco_clk->vco_clk_min)
+		vco_rate = vco_clk->vco_clk_min;
+	else if (rate > vco_clk->vco_clk_max)
+		vco_rate = vco_clk->vco_clk_max;
+
+	return vco_rate;
+}
+
+static unsigned long dsi_pll_vco_get_rate(struct clk *c)
+{
+	u32 fb_divider, ref_divider, vco_rate;
+	u32 temp, status;
+	struct clk *parent = c->parent;
+
+	status = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_RDY);
+	if (status & DSI_PLL_RDY_BIT) {
+		fb_divider = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_1);
+		fb_divider &= 0xFF;
+		temp = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_2) & 0x07;
+		fb_divider = (temp << 8) | fb_divider;
+		fb_divider += 1;
+
+		ref_divider = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_3);
+		ref_divider &= 0x3F;
+		ref_divider += 1;
+
+		vco_rate = (parent->rate / ref_divider) * fb_divider;
+	} else {
+		vco_rate = 0;
+	}
+	return vco_rate;
+}
+
+static enum handoff dsi_pll_vco_handoff(struct clk *c)
+{
+	u32 status;
+
+	if (clk_prepare_enable(dsi_ahb_clk)) {
+		pr_err("fail to enable dsi ahb clk\n");
+		return HANDOFF_DISABLED_CLK;
+	}
+
+	status = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_0);
+	if (!status & DSI_PLL_RDY_BIT) {
+		pr_err("DSI PLL not ready\n");
+		clk_disable(dsi_ahb_clk);
+		return HANDOFF_DISABLED_CLK;
+	}
+
+	c->rate = dsi_pll_vco_get_rate(c);
+
+	clk_disable_unprepare(dsi_ahb_clk);
+
+	return HANDOFF_ENABLED_CLK;
+}
+
+static int dsi_byteclk_set_rate(struct clk *c, unsigned long rate)
+{
+	int div, ret;
+	long vco_rate;
+	unsigned long bitclk_rate;
+	u32 temp, val;
+	struct clk *parent = clk_get_parent(c);
+
+	if (rate == 0) {
+		ret = clk_set_rate(parent, 0);
+		return ret;
+	}
+
+	bitclk_rate = rate * 8;
+	for (div = 1; div < DSI_MAX_DIVIDER; div++) {
+		vco_rate = clk_round_rate(parent, bitclk_rate * div);
+
+		if (vco_rate == bitclk_rate * div)
+			break;
+
+		if (vco_rate < bitclk_rate * div)
+			return -EINVAL;
+	}
+
+	if (vco_rate != bitclk_rate * div)
+		return -EINVAL;
+
+	ret = clk_set_rate(parent, vco_rate);
+	if (ret) {
+		pr_err("fail to set vco rate\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(dsi_ahb_clk);
+	if (ret) {
+		pr_err("fail to enable dsi ahb clk\n");
+		return ret;
+	}
+
+	/* set the bit clk divider */
+	temp =  readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_8);
+	val = (temp & 0xFFFFFFF0) | (div - 1);
+	writel_relaxed(val, dsi_base + DSI_DSIPHY_PLL_CTRL_8);
+
+	/* set the byte clk divider */
+	temp = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_9);
+	val = (temp & 0xFFFFFF00) | (vco_rate / rate - 1);
+	writel_relaxed(val, dsi_base + DSI_DSIPHY_PLL_CTRL_9);
+	clk_disable_unprepare(dsi_ahb_clk);
+
+	return 0;
+}
+
+static long dsi_byteclk_round_rate(struct clk *c, unsigned long rate)
+{
+	int div;
+	long vco_rate;
+	unsigned long bitclk_rate;
+	struct clk *parent = clk_get_parent(c);
+
+	if (rate == 0)
+		return -EINVAL;
+
+	bitclk_rate = rate * 8;
+	for (div = 1; div < DSI_MAX_DIVIDER; div++) {
+		vco_rate = clk_round_rate(parent, bitclk_rate * div);
+		if (vco_rate == bitclk_rate * div)
+			break;
+		if (vco_rate < bitclk_rate * div)
+			return -EINVAL;
+	}
+
+	if (vco_rate != bitclk_rate * div)
+		return -EINVAL;
+
+	return rate;
+}
+
+static enum handoff dsi_byteclk_handoff(struct clk *c)
+{
+	struct clk *parent = clk_get_parent(c);
+	unsigned long vco_rate = clk_get_rate(parent);
+	u32 out_div2;
+
+	if (vco_rate == 0)
+		return HANDOFF_DISABLED_CLK;
+
+	if (clk_prepare_enable(dsi_ahb_clk)) {
+		pr_err("fail to enable dsi ahb clk\n");
+		return HANDOFF_DISABLED_CLK;
+	}
+
+	out_div2 = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_9);
+	out_div2 &= 0xFF;
+	c->rate = vco_rate / (out_div2 + 1);
+	clk_disable_unprepare(dsi_ahb_clk);
+
+	return HANDOFF_ENABLED_CLK;
+}
+
+static int dsi_dsiclk_set_rate(struct clk *c, unsigned long rate)
+{
+	u32 temp, val;
+	int ret;
+	struct clk *parent = clk_get_parent(c);
+	unsigned long vco_rate = clk_get_rate(parent);
+
+	if (rate == 0)
+		return 0;
+
+	if (vco_rate % rate != 0) {
+		pr_err("dsiclk_set_rate invalid rate\n");
+		return -EINVAL;
+	}
+
+	ret = clk_prepare_enable(dsi_ahb_clk);
+	if (ret) {
+		pr_err("fail to enable dsi ahb clk\n");
+		return ret;
+	}
+	temp =	readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_10);
+	val = (temp & 0xFFFFFF00) | (vco_rate / rate - 1);
+	writel_relaxed(val, dsi_base + DSI_DSIPHY_PLL_CTRL_10);
+	clk_disable_unprepare(dsi_ahb_clk);
+
+	return 0;
+}
+
+static long dsi_dsiclk_round_rate(struct clk *c, unsigned long rate)
+{
+	/* rate is the pixel clk rate, translate into dsi clk rate*/
+	struct clk *parent = clk_get_parent(c);
+	unsigned long vco_rate = clk_get_rate(parent);
+
+	rate *= DSI_BPP;
+
+	if (vco_rate < rate)
+		return -EINVAL;
+
+	if (vco_rate % rate != 0)
+		return -EINVAL;
+
+	return rate;
+}
+
+static enum handoff dsi_dsiclk_handoff(struct clk *c)
+{
+	struct clk *parent = clk_get_parent(c);
+	unsigned long vco_rate = clk_get_rate(parent);
+	u32 out_div3;
+
+	if (vco_rate == 0)
+		return HANDOFF_DISABLED_CLK;
+
+	if (clk_prepare_enable(dsi_ahb_clk)) {
+		pr_err("fail to enable dsi ahb clk\n");
+		return HANDOFF_DISABLED_CLK;
+	}
+
+	out_div3 = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_10);
+	out_div3 &= 0xFF;
+	c->rate = vco_rate / (out_div3 + 1);
+	clk_disable_unprepare(dsi_ahb_clk);
+
+	return HANDOFF_ENABLED_CLK;
+}
+
+int dsi_prepare(struct clk *clk)
+{
+	return clk_prepare(dsi_ahb_clk);
+}
+
+void dsi_unprepare(struct clk *clk)
+{
+	clk_unprepare(dsi_ahb_clk);
+}
+
+struct clk_ops clk_ops_dsi_dsiclk = {
+	.prepare = dsi_prepare,
+	.unprepare = dsi_unprepare,
+	.set_rate = dsi_dsiclk_set_rate,
+	.round_rate = dsi_dsiclk_round_rate,
+	.handoff = dsi_dsiclk_handoff,
+};
+
+struct clk_ops clk_ops_dsi_byteclk = {
+	.prepare = dsi_prepare,
+	.unprepare = dsi_unprepare,
+	.set_rate = dsi_byteclk_set_rate,
+	.round_rate = dsi_byteclk_round_rate,
+	.handoff = dsi_byteclk_handoff,
+};
+
+struct clk_ops clk_ops_dsi_vco = {
+	.prepare = dsi_prepare,
+	.unprepare = dsi_unprepare,
+	.enable = dsi_pll_vco_enable,
+	.disable = dsi_pll_vco_disable,
+	.set_rate = dsi_pll_vco_set_rate,
+	.round_rate = dsi_pll_vco_round_rate,
+	.handoff = dsi_pll_vco_handoff,
+};
+
diff --git a/arch/arm/mach-msm/clock-dsi-8610.h b/arch/arm/mach-msm/clock-dsi-8610.h
new file mode 100644
index 0000000..4c09790
--- /dev/null
+++ b/arch/arm/mach-msm/clock-dsi-8610.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_CLOCK_DSI_8610
+#define __ARCH_ARM_MACH_MSM_CLOCK_DSI_8610
+
+#include <mach/clk-provider.h>
+
+struct dsi_pll_vco_clk {
+	const unsigned long vco_clk_min;
+	const unsigned long vco_clk_max;
+	const unsigned pref_div_ratio;
+	int factor;
+	struct clk c;
+};
+
+extern struct clk_ops clk_ops_dsi_vco;
+extern struct clk_ops clk_ops_dsi_byteclk;
+extern struct clk_ops clk_ops_dsi_dsiclk;
+
+int dsi_clk_ctrl_init(struct clk *ahb_clk);
+
+#endif
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 0d1104e..8915bad 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -476,10 +476,7 @@
 	if (branch->max_div)
 		return branch->c.rate;
 
-	if (!branch->has_sibling)
-		return clk_get_rate(c->parent);
-
-	return 0;
+	return clk_get_rate(c->parent);
 }
 
 static int branch_clk_list_rate(struct clk *c, unsigned n)
@@ -670,7 +667,7 @@
 	return HANDOFF_ENABLED_CLK;
 }
 
-static enum handoff byte_rcg_handoff(struct clk *clk)
+enum handoff byte_rcg_handoff(struct clk *clk)
 {
 	struct rcg_clk *rcg = to_rcg_clk(clk);
 	u32 div_val;
@@ -721,7 +718,7 @@
 	return 0;
 }
 
-static enum handoff pixel_rcg_handoff(struct clk *clk)
+enum handoff pixel_rcg_handoff(struct clk *clk)
 {
 	struct rcg_clk *rcg = to_rcg_clk(clk);
 	u32 div_val, mval, nval, cfg_regval;
@@ -812,6 +809,155 @@
 }
 
 
+#define ENABLE_REG(x)	(*(x)->base + (x)->enable_reg)
+#define SELECT_REG(x)	(*(x)->base + (x)->select_reg)
+
+/*
+ * mux clock functions
+ */
+static void mux_clk_halt_check(void)
+{
+	/* Ensure that the delay starts after the mux disable/enable. */
+	mb();
+	udelay(HALT_CHECK_DELAY_US);
+}
+
+static int mux_clk_enable(struct clk *c)
+{
+	unsigned long flags;
+	u32 regval;
+	struct mux_clk *mux = to_mux_clk(c);
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	regval = readl_relaxed(ENABLE_REG(mux));
+	regval |= mux->enable_mask;
+	writel_relaxed(regval, ENABLE_REG(mux));
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	/* Wait for clock to enable before continuing. */
+	mux_clk_halt_check();
+
+	return 0;
+}
+
+static void mux_clk_disable(struct clk *c)
+{
+	unsigned long flags;
+	struct mux_clk *mux = to_mux_clk(c);
+	u32 regval;
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	regval = readl_relaxed(ENABLE_REG(mux));
+	regval &= ~mux->enable_mask;
+	writel_relaxed(regval, ENABLE_REG(mux));
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	/* Wait for clock to disable before continuing. */
+	mux_clk_halt_check();
+}
+
+static int mux_source_switch(struct mux_clk *mux, struct mux_source *dest)
+{
+	unsigned long flags;
+	u32 regval;
+	int ret = 0;
+
+	ret = __clk_pre_reparent(&mux->c, dest->clk, &flags);
+	if (ret)
+		goto out;
+
+	regval = readl_relaxed(SELECT_REG(mux));
+	regval &= ~mux->select_mask;
+	regval |= dest->select_val;
+	writel_relaxed(regval, SELECT_REG(mux));
+
+	/* Make sure switch request goes through before proceeding. */
+	mb();
+
+	__clk_post_reparent(&mux->c, mux->c.parent, &flags);
+out:
+	return ret;
+}
+
+static int mux_clk_set_parent(struct clk *c, struct clk *parent)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	struct mux_source *dest = NULL;
+	int ret;
+
+	if (!mux->sources || !parent)
+		return -EPERM;
+
+	dest = mux->sources;
+
+	while (dest->clk) {
+		if (dest->clk == parent)
+			break;
+		dest++;
+	}
+
+	if (!dest->clk)
+		return -EPERM;
+
+	ret = mux_source_switch(mux, dest);
+	if (ret)
+		return ret;
+
+	mux->c.rate = clk_get_rate(dest->clk);
+
+	return 0;
+}
+
+static enum handoff mux_clk_handoff(struct clk *c)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	u32 mask = mux->enable_mask;
+	u32 regval = readl_relaxed(ENABLE_REG(mux));
+
+	c->rate = clk_get_rate(c->parent);
+
+	if (mask == (regval & mask))
+		return HANDOFF_ENABLED_CLK;
+
+	return HANDOFF_DISABLED_CLK;
+}
+
+static struct clk *mux_clk_get_parent(struct clk *c)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	struct mux_source *parent = NULL;
+	u32 regval = readl_relaxed(SELECT_REG(mux));
+
+	if (!mux->sources)
+		return ERR_PTR(-EPERM);
+
+	parent = mux->sources;
+
+	while (parent->clk) {
+		if ((regval & mux->select_mask) == parent->select_val)
+			return parent->clk;
+
+		parent++;
+	}
+
+	return ERR_PTR(-EPERM);
+}
+
+static int mux_clk_list_rate(struct clk *c, unsigned n)
+{
+	struct mux_clk *mux = to_mux_clk(c);
+	int i;
+
+	for (i = 0; i < n; i++)
+		if (!mux->sources[i].clk)
+			break;
+
+	if (!mux->sources[i].clk)
+		return -ENXIO;
+
+	return clk_get_rate(mux->sources[i].clk);
+}
+
 struct clk_ops clk_ops_empty;
 
 struct clk_ops clk_ops_rcg = {
@@ -875,3 +1021,14 @@
 	.reset = local_vote_clk_reset,
 	.handoff = local_vote_clk_handoff,
 };
+
+struct clk_ops clk_ops_mux = {
+	.enable = mux_clk_enable,
+	.disable = mux_clk_disable,
+	.set_parent = mux_clk_set_parent,
+	.get_parent = mux_clk_get_parent,
+	.handoff = mux_clk_handoff,
+	.list_rate = mux_clk_list_rate,
+};
+
+
diff --git a/arch/arm/mach-msm/clock-local2.h b/arch/arm/mach-msm/clock-local2.h
index 7ac7bd3..f33cf9c 100644
--- a/arch/arm/mach-msm/clock-local2.h
+++ b/arch/arm/mach-msm/clock-local2.h
@@ -157,6 +157,38 @@
 	return container_of(clk, struct measure_clk, c);
 }
 
+struct mux_source {
+	struct clk *const clk;
+	const u32 select_val;
+};
+
+/**
+ * struct mux_clk - branch clock
+ * @c: clk
+ * @enable_reg: register that contains the enable bit(s) for the mux
+ * @select_reg: register that contains the source selection bits for the mux
+ * @enable_mask: mask that enables the mux
+ * @select_mask: mask for the source selection bits
+ * @sources: list of mux sources
+ * @base: pointer to base address of ioremapped registers.
+ */
+struct mux_clk {
+	struct clk c;
+	const u32 enable_reg;
+	const u32 select_reg;
+	const u32 enable_mask;
+	const u32 select_mask;
+
+	struct mux_source *sources;
+
+	void *const __iomem *base;
+};
+
+static inline struct mux_clk *to_mux_clk(struct clk *clk)
+{
+	return container_of(clk, struct mux_clk, c);
+}
+
 /*
  * Generic set-rate implementations
  */
@@ -168,6 +200,7 @@
  */
 extern spinlock_t local_clock_reg_lock;
 
+extern struct clk_ops clk_ops_mux;
 extern struct clk_ops clk_ops_empty;
 extern struct clk_ops clk_ops_rcg;
 extern struct clk_ops clk_ops_rcg_mnd;
@@ -177,6 +210,9 @@
 extern struct clk_ops clk_ops_byte;
 extern struct clk_ops clk_ops_pixel;
 
+enum handoff pixel_rcg_handoff(struct clk *clk);
+enum handoff byte_rcg_handoff(struct clk *clk);
+
 /*
  * Clock definition macros
  */
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 044fc2c..2e12e27 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -62,7 +62,7 @@
 {
 	int level, rc = 0, i;
 	struct regulator **r = vdd_class->regulator;
-	const int **vdd_uv = vdd_class->vdd_uv;
+	int **vdd_uv = vdd_class->vdd_uv;
 	int max_level = vdd_class->num_levels - 1;
 
 	for (level = max_level; level > 0; level--)
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index d02ab66..24a1e96 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -410,4 +410,4 @@
 	return cpufreq_register_driver(&msm_cpufreq_driver);
 }
 
-late_initcall(msm_cpufreq_register);
+device_initcall(msm_cpufreq_register);
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 837aef3..cb8ffc1 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -2510,6 +2510,11 @@
 	.id	= -1,
 };
 
+struct platform_device msm_fm_loopback = {
+	.name	= "msm-pcm-loopback",
+	.id	= -1,
+};
+
 static struct fs_driver_data gfx2d0_fs_data = {
 	.clks = (struct fs_clk_data[]){
 		{ .name = "core_clk" },
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 327c11d..eb12383 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -260,6 +260,7 @@
 extern struct platform_device msm_i2s_cpudai4;
 extern struct platform_device msm_i2s_cpudai5;
 extern struct platform_device msm_cpudai_stub;
+extern struct platform_device msm_fm_loopback;
 
 extern struct platform_device msm_pil_q6v3;
 extern struct platform_device msm_pil_modem;
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index a07b13d..6665d66 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -38,7 +38,7 @@
 #define EN_FEW_WAIT_VAL		(0x8 << 16)
 #define CLK_DIS_WAIT_VAL	(0x2 << 12)
 
-#define TIMEOUT_US		1000
+#define TIMEOUT_US		100
 
 struct gdsc {
 	struct regulator_dev	*rdev;
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 2a33228..b358b53 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -59,7 +59,7 @@
 	struct regulator **regulator;
 	int num_regulators;
 	int (*set_vdd)(struct clk_vdd_class *v_class, int level);
-	const int **vdd_uv;
+	int **vdd_uv;
 	int *level_votes;
 	int num_levels;
 	unsigned long cur_level;
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 9a89508..7157d12 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -122,6 +122,7 @@
 					unsigned long size);
 
 extern int msm_register_domain(struct msm_iova_layout *layout);
+extern int msm_unregister_domain(struct iommu_domain *domain);
 
 #else
 static inline void msm_iommu_set_client_name(struct iommu_domain *domain,
@@ -195,6 +196,11 @@
 {
 	return -ENODEV;
 }
+
+static inline int msm_unregister_domain(struct iommu_domain *domain)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/ipa.h b/arch/arm/mach-msm/include/mach/ipa.h
index 90757b6..b4fbaee 100644
--- a/arch/arm/mach-msm/include/mach/ipa.h
+++ b/arch/arm/mach-msm/include/mach/ipa.h
@@ -583,6 +583,8 @@
  */
 int ipa_rm_create_resource(struct ipa_rm_create_params *create_params);
 
+int ipa_rm_delete_resource(enum ipa_rm_resource_name resource_name);
+
 int ipa_rm_register(enum ipa_rm_resource_name resource_name,
 			struct ipa_rm_register_params *reg_params);
 
@@ -955,6 +957,12 @@
 	return -EPERM;
 }
 
+static inline int ipa_rm_delete_resource(
+		enum ipa_rm_resource_name resource_name)
+{
+	return -EPERM;
+}
+
 static inline int ipa_rm_register(enum ipa_rm_resource_name resource_name,
 			struct ipa_rm_register_params *reg_params)
 {
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8610.h b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
index 2a62460..18e448d 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
@@ -24,6 +24,9 @@
 
 #define MSM8610_MSM_SHARED_RAM_PHYS	0x0D900000
 
+#define MSM8610_QGIC_DIST_PHYS	0xF9000000
+#define MSM8610_QGIC_DIST_SIZE	SZ_4K
+
 #define MSM8610_APCS_GCC_PHYS	0xF9011000
 #define MSM8610_APCS_GCC_SIZE	SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index a90e78a..8f48e94 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -115,7 +115,8 @@
 
 
 #if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27) \
-	|| defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM9625)
+	|| defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM9625) \
+	|| defined(CONFIG_ARCH_MSM8610) || defined(CONFIG_ARCH_MSM8226)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 #else
 #define MSM_SHARED_RAM_SIZE	SZ_2M
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index 20dc851..e889242 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -18,6 +18,14 @@
 
 #define QSEECOM_KEY_ID_SIZE   32
 
+#define	QSEOS_RESULT_FAIL_LOAD_KS         -48
+#define	QSEOS_RESULT_FAIL_SAVE_KS         -49
+#define	QSEOS_RESULT_FAIL_MAX_KEYS        -50
+#define	QSEOS_RESULT_FAIL_KEY_ID_EXISTS   -51
+#define	QSEOS_RESULT_FAIL_KEY_ID_DNE      -52
+#define	QSEOS_RESULT_FAIL_KS_OP           -53
+#define	QSEOS_RESULT_FAIL_CE_PIPE_INVALID -54
+
 enum qseecom_command_scm_resp_type {
 	QSEOS_APP_ID = 0xEE01,
 	QSEOS_LISTENER_ID
@@ -49,6 +57,22 @@
 	QSEOS_RESULT_FAILURE  = 0xFFFFFFFF
 };
 
+/* Key Management requests */
+enum qseecom_qceos_key_gen_cmd_id {
+	QSEOS_GENERATE_KEY  = 0x11,
+	QSEOS_DELETE_KEY,
+	QSEOS_MAX_KEY_COUNT,
+	QSEOS_SET_KEY,
+	QSEOS_KEY_CMD_MAX   = 0xEFFFFFFF
+};
+
+enum qseecom_pipe_type {
+	QSEOS_PIPE_ENC = 0,
+	QSEOS_PIPE_ENC_XTS,
+	QSEOS_PIPE_AUTH,
+	QSEOS_PIPE_ENUM_FILL = 0x7FFFFFFF
+};
+
 __packed  struct qsee_apps_region_info_ireq {
 	uint32_t qsee_cmd_id;
 	uint32_t addr;
@@ -143,29 +167,24 @@
 	unsigned int rsp_len; /* in/out */
 };
 
-/* Key Management requests */
-enum qseecom_qceos_key_gen_cmd_id {
-	QSEOS_GENERATE_KEY      = 0x02,
-	QSEOS_SET_KEY,
-	QSEOS_DELETE_KEY,
-	QSEOS_MAX_KEY_COUNT,
-	QSEOS_KEY_CMD_MAX     = 0xEFFFFFFF
-};
-
 __packed struct qseecom_key_generate_ireq {
+	uint32_t qsee_command_id;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
 };
 
 __packed struct qseecom_key_select_ireq {
+	uint32_t qsee_command_id;
 	uint32_t ce;
 	uint32_t pipe;
+	uint32_t pipe_type;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
 	unsigned char hash[QSEECOM_HASH_SIZE];
 };
 
 __packed struct qseecom_key_delete_ireq {
+	uint32_t qsee_command_id;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
 };
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 42e04dd..4186603 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -22,7 +22,6 @@
 #define SCM_SVC_FUSE			0x8
 #define SCM_SVC_PWR			0x9
 #define SCM_SVC_MP			0xC
-#define SCM_SVC_CRYPTO			0xA
 #define SCM_SVC_DCVS			0xD
 #define SCM_SVC_ES			0x10
 #define SCM_SVC_TZSCHEDULER		0xFC
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 67f643e..4d4703f 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -55,6 +55,7 @@
 	int (*powerup)(const struct subsys_desc *desc);
 	void (*crash_shutdown)(const struct subsys_desc *desc);
 	int (*ramdump)(int, const struct subsys_desc *desc);
+	unsigned int err_ready_irq;
 };
 
 #if defined(CONFIG_MSM_SUBSYSTEM_RESTART)
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index 68313c5..da7c039 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -42,6 +42,12 @@
 	OCI_MEM,		/* Shared memory among peripherals */
 };
 
+enum usb_bam_event_type {
+	USB_BAM_EVENT_WAKEUP_PIPE = 0,	/* Wake a pipe */
+	USB_BAM_EVENT_WAKEUP,		/* Wake a bam (first pipe waked) */
+	USB_BAM_EVENT_INACTIVITY,	/* Inactivity on all pipes */
+};
+
 struct usb_bam_connect_ipa_params {
 	u8 src_idx;
 	u8 dst_idx;
@@ -57,16 +63,20 @@
 	void *priv;
 	void (*notify)(void *priv, enum ipa_dp_evt_type evt,
 			unsigned long data);
+	int (*activity_notify)(void *priv);
+	int (*inactivity_notify)(void *priv);
 };
 
 /**
 * struct usb_bam_event_info: suspend/resume event information.
+* @type: usb bam event type.
 * @event: holds event data.
 * @callback: suspend/resume callback.
 * @param: port num (for suspend) or NULL (for resume).
 * @event_w: holds work queue parameters.
 */
 struct usb_bam_event_info {
+	enum usb_bam_event_type type;
 	struct sps_register_event event;
 	int (*callback)(void *);
 	void *param;
@@ -89,8 +99,12 @@
 * @desc_fifo_size: descriptor fifo size.
 * @data_mem_buf: data fifo buffer.
 * @desc_mem_buf: descriptor fifo buffer.
-* @wake_event: event for wakeup.
+* @event: event for wakeup.
 * @enabled: true if pipe is enabled.
+* @priv: private data to return upon activity_notify
+*	or inactivity_notify callbacks.
+* @activity_notify: callback to invoke on activity on one of the in pipes.
+* @inactivity_notify: callback to invoke on inactivity on all pipes.
 */
 struct usb_bam_pipe_connect {
 	const char *name;
@@ -109,8 +123,11 @@
 	u32 desc_fifo_size;
 	struct sps_mem_buffer data_mem_buf;
 	struct sps_mem_buffer desc_mem_buf;
-	struct usb_bam_event_info wake_event;
+	struct usb_bam_event_info event;
 	bool enabled;
+	void *priv;
+	int (*activity_notify)(void *priv);
+	int (*inactivity_notify)(void *priv);
 };
 
 /**
@@ -154,7 +171,10 @@
 /**
  * Connect USB-to-IPA SPS connection.
  *
- * This function returns the allocated pipes number and clnt handles.
+ * This function returns the allocated pipes number and clnt
+ * handles. Assumes that the user first connects producer pipes
+ * and only after that consumer pipes, since that's the correct
+ * sequence for the handshake with the IPA.
  *
  * @ipa_params - in/out parameters
  *
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 37dbbab..1c4a317 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -574,6 +574,7 @@
 
 #ifdef CONFIG_ARCH_MSM8610
 static struct map_desc msm8610_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(QGIC_DIST, MSM8610),
 	MSM_CHIP_DEVICE(APCS_GCC, MSM8610),
 	MSM_CHIP_DEVICE(TLMM, MSM8610),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8610),
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 18562a3..f4ac37e 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -21,6 +21,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/idr.h>
 #include <asm/sizes.h>
 #include <asm/page.h>
 #include <mach/iommu.h>
@@ -36,9 +37,14 @@
 	int domain_num;
 };
 
+struct msm_iommu_data_entry {
+	struct list_head list;
+	void *data;
+};
+
 static struct rb_root domain_root;
 DEFINE_MUTEX(domain_mutex);
-static atomic_t domain_nums = ATOMIC_INIT(-1);
+static DEFINE_IDA(domain_nums);
 
 void msm_iommu_set_client_name(struct iommu_domain *domain, char const *name)
 {
@@ -273,6 +279,27 @@
 	return 0;
 }
 
+static int remove_domain(struct iommu_domain *domain)
+{
+	struct rb_root *root = &domain_root;
+	struct rb_node *n;
+	struct msm_iova_data *node;
+	int ret = -EINVAL;
+
+	mutex_lock(&domain_mutex);
+
+	for (n = rb_first(root); n; n = rb_next(n)) {
+		node = rb_entry(n, struct msm_iova_data, node);
+		if (node->domain == domain) {
+			rb_erase(&node->node, &domain_root);
+			ret = 0;
+			break;
+		}
+	}
+	mutex_unlock(&domain_mutex);
+	return ret;
+}
+
 struct iommu_domain *msm_get_iommu_domain(int domain_num)
 {
 	struct msm_iova_data *data;
@@ -307,6 +334,27 @@
 }
 EXPORT_SYMBOL(msm_find_domain_no);
 
+static struct msm_iova_data *msm_domain_to_iova_data(struct iommu_domain
+						     const *domain)
+{
+	struct rb_root *root = &domain_root;
+	struct rb_node *n;
+	struct msm_iova_data *node;
+	struct msm_iova_data *iova_data = ERR_PTR(-EINVAL);
+
+	mutex_lock(&domain_mutex);
+
+	for (n = rb_first(root); n; n = rb_next(n)) {
+		node = rb_entry(n, struct msm_iova_data, node);
+		if (node->domain == domain) {
+			iova_data = node;
+			break;
+		}
+	}
+	mutex_unlock(&domain_mutex);
+	return iova_data;
+}
+
 int msm_allocate_iova_address(unsigned int iommu_domain,
 					unsigned int partition_no,
 					unsigned long size,
@@ -330,7 +378,9 @@
 	if (!pool->gpool)
 		return -EINVAL;
 
+	mutex_lock(&pool->pool_mutex);
 	va = gen_pool_alloc_aligned(pool->gpool, size, ilog2(align));
+	mutex_unlock(&pool->pool_mutex);
 	if (va) {
 		pool->free -= size;
 		/* Offset because genpool can't handle 0 addresses */
@@ -375,7 +425,9 @@
 	if (pool->paddr == 0)
 		iova += SZ_4K;
 
+	mutex_lock(&pool->pool_mutex);
 	gen_pool_free(pool->gpool, iova, size);
+	mutex_unlock(&pool->pool_mutex);
 }
 
 int msm_register_domain(struct msm_iova_layout *layout)
@@ -393,11 +445,11 @@
 	if (!data)
 		return -ENOMEM;
 
-	pools = kmalloc(sizeof(struct mem_pool) * layout->npartitions,
+	pools = kzalloc(sizeof(struct mem_pool) * layout->npartitions,
 			GFP_KERNEL);
 
 	if (!pools)
-		goto out;
+		goto free_data;
 
 	for (i = 0; i < layout->npartitions; i++) {
 		if (layout->partitions[i].size == 0)
@@ -410,6 +462,7 @@
 
 		pools[i].paddr = layout->partitions[i].start;
 		pools[i].size = layout->partitions[i].size;
+		mutex_init(&pools[i].pool_mutex);
 
 		/*
 		 * genalloc can't handle a pool starting at address 0.
@@ -435,10 +488,13 @@
 
 	data->pools = pools;
 	data->npools = layout->npartitions;
-	data->domain_num = atomic_inc_return(&domain_nums);
+	data->domain_num = ida_simple_get(&domain_nums, 0, 0, GFP_KERNEL);
+	if (data->domain_num < 0)
+		goto free_pools;
+
 	data->domain = iommu_domain_alloc(bus, layout->domain_flags);
 	if (!data->domain)
-		goto out;
+		goto free_domain_num;
 
 	msm_iommu_set_client_name(data->domain, layout->client_name);
 
@@ -446,13 +502,50 @@
 
 	return data->domain_num;
 
-out:
+free_domain_num:
+	ida_simple_remove(&domain_nums, data->domain_num);
+
+free_pools:
+	for (i = 0; i < layout->npartitions; i++) {
+		if (pools[i].gpool)
+			gen_pool_destroy(pools[i].gpool);
+	}
+	kfree(pools);
+free_data:
 	kfree(data);
 
 	return -EINVAL;
 }
 EXPORT_SYMBOL(msm_register_domain);
 
+int msm_unregister_domain(struct iommu_domain *domain)
+{
+	unsigned int i;
+	struct msm_iova_data *data = msm_domain_to_iova_data(domain);
+
+	if (IS_ERR_OR_NULL(data)) {
+		pr_err("%s: Could not find iova_data\n", __func__);
+		return -EINVAL;
+	}
+
+	if (remove_domain(data->domain)) {
+		pr_err("%s: Domain not found. Failed to remove domain\n",
+			__func__);
+	}
+
+	iommu_domain_free(domain);
+
+	ida_simple_remove(&domain_nums, data->domain_num);
+
+	for (i = 0; i < data->npools; ++i)
+		gen_pool_destroy(data->pools[i].gpool);
+
+	kfree(data->pools);
+	kfree(data);
+	return 0;
+}
+EXPORT_SYMBOL(msm_unregister_domain);
+
 static int find_and_add_contexts(struct iommu_group *group,
 				 const struct device_node *node,
 				 unsigned int num_contexts)
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 0d617a6..c31c969 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -133,15 +133,21 @@
 	struct msm_ipc_router_xprt_info *xprt_info;
 };
 
+struct msm_ipc_resume_tx_port {
+	struct list_head list;
+	uint32_t port_id;
+	uint32_t node_id;
+};
+
 #define RP_HASH_SIZE 32
 struct msm_ipc_router_remote_port {
 	struct list_head list;
 	uint32_t node_id;
 	uint32_t port_id;
 	uint32_t restart_state;
-	wait_queue_head_t quota_wait;
 	uint32_t tx_quota_cnt;
 	struct mutex quota_lock;
+	struct list_head resume_tx_port_list;
 	void *sec_rule;
 };
 
@@ -657,8 +663,8 @@
 	rport_ptr->restart_state = RESTART_NORMAL;
 	rport_ptr->sec_rule = NULL;
 	rport_ptr->tx_quota_cnt = 0;
-	init_waitqueue_head(&rport_ptr->quota_wait);
 	mutex_init(&rport_ptr->quota_lock);
+	INIT_LIST_HEAD(&rport_ptr->resume_tx_port_list);
 	list_add_tail(&rport_ptr->list,
 		      &rt_entry->remote_port_list[key]);
 	mutex_unlock(&rt_entry->lock);
@@ -666,6 +672,97 @@
 	return rport_ptr;
 }
 
+/**
+ * msm_ipc_router_free_resume_tx_port() - Free the resume_tx ports
+ * @rport_ptr: Pointer to the remote port.
+ *
+ * This function deletes all the resume_tx ports associated with a remote port
+ * and frees the memory allocated to each resume_tx port.
+ *
+ * Must be called with rport_ptr->quota_lock locked.
+ */
+static void msm_ipc_router_free_resume_tx_port(
+	struct msm_ipc_router_remote_port *rport_ptr)
+{
+	struct msm_ipc_resume_tx_port *rtx_port, *tmp_rtx_port;
+
+	list_for_each_entry_safe(rtx_port, tmp_rtx_port,
+			&rport_ptr->resume_tx_port_list, list) {
+		list_del(&rtx_port->list);
+		kfree(rtx_port);
+	}
+}
+
+/**
+ * msm_ipc_router_lookup_resume_tx_port() - Lookup resume_tx port list
+ * @rport_ptr: Remote port whose resume_tx port list needs to be looked.
+ * @port_id: Port ID which needs to be looked from the list.
+ *
+ * return 1 if the port_id is found in the list, else 0.
+ *
+ * This function is used to lookup the existence of a local port in
+ * remote port's resume_tx list. This function is used to ensure that
+ * the same port is not added to the remote_port's resume_tx list repeatedly.
+ *
+ * Must be called with rport_ptr->quota_lock locked.
+ */
+static int msm_ipc_router_lookup_resume_tx_port(
+	struct msm_ipc_router_remote_port *rport_ptr, uint32_t port_id)
+{
+	struct msm_ipc_resume_tx_port *rtx_port;
+
+	list_for_each_entry(rtx_port, &rport_ptr->resume_tx_port_list, list) {
+		if (port_id == rtx_port->port_id)
+			return 1;
+	}
+	return 0;
+}
+
+/**
+ * post_resume_tx() - Post the resume_tx event
+ * @rport_ptr: Pointer to the remote port
+ * @pkt : The data packet that is received on a resume_tx event
+ *
+ * This function informs about the reception of the resume_tx message from a
+ * remote port pointed by rport_ptr to all the local ports that are in the
+ * resume_tx_ports_list of this remote port. On posting the information, this
+ * function sequentially deletes each entry in the resume_tx_port_list of the
+ * remote port.
+ *
+ * Must be called with rport_ptr->quota_lock locked.
+ */
+static void post_resume_tx(struct msm_ipc_router_remote_port *rport_ptr,
+						   struct rr_packet *pkt)
+{
+	struct msm_ipc_resume_tx_port *rtx_port, *tmp_rtx_port;
+	struct msm_ipc_port *local_port;
+	struct rr_packet *cloned_pkt;
+
+	list_for_each_entry_safe(rtx_port, tmp_rtx_port,
+				&rport_ptr->resume_tx_port_list, list) {
+		mutex_lock(&local_ports_lock);
+		local_port =
+			msm_ipc_router_lookup_local_port(rtx_port->port_id);
+		if (local_port) {
+			cloned_pkt = clone_pkt(pkt);
+			if (cloned_pkt) {
+				mutex_lock(&local_port->port_rx_q_lock);
+				list_add_tail(&cloned_pkt->list,
+						&local_port->port_rx_q);
+				wake_up(&local_port->port_rx_wait_q);
+				mutex_unlock(&local_port->port_rx_q_lock);
+			} else {
+				pr_err("%s: Clone_pkt failed for %08x:%08x\n",
+					__func__, local_port->this_port.node_id,
+					local_port->this_port.port_id);
+			}
+		}
+		mutex_unlock(&local_ports_lock);
+		list_del(&rtx_port->list);
+		kfree(rtx_port);
+	}
+}
+
 static void msm_ipc_router_destroy_remote_port(
 	struct msm_ipc_router_remote_port *rport_ptr)
 {
@@ -683,7 +780,9 @@
 		pr_err("%s: Node %d is not up\n", __func__, node_id);
 		return;
 	}
-
+	mutex_lock(&rport_ptr->quota_lock);
+	msm_ipc_router_free_resume_tx_port(rport_ptr);
+	mutex_unlock(&rport_ptr->quota_lock);
 	mutex_lock(&rt_entry->lock);
 	list_del(&rport_ptr->list);
 	kfree(rport_ptr);
@@ -1158,7 +1257,7 @@
 	}
 	mutex_lock(&rport_ptr->quota_lock);
 	rport_ptr->restart_state = RESTART_PEND;
-	wake_up(&rport_ptr->quota_wait);
+	msm_ipc_router_free_resume_tx_port(rport_ptr);
 	mutex_unlock(&rport_ptr->quota_lock);
 	return;
 }
@@ -1240,7 +1339,8 @@
 						continue;
 					mutex_lock(&rport_ptr->quota_lock);
 					rport_ptr->restart_state = RESTART_PEND;
-					wake_up(&rport_ptr->quota_wait);
+					msm_ipc_router_free_resume_tx_port(
+								rport_ptr);
 					mutex_unlock(&rport_ptr->quota_lock);
 					ctl.cli.node_id = rport_ptr->node_id;
 					ctl.cli.port_id = rport_ptr->port_id;
@@ -1531,8 +1631,8 @@
 		}
 		mutex_lock(&rport_ptr->quota_lock);
 		rport_ptr->tx_quota_cnt = 0;
+		post_resume_tx(rport_ptr, pkt);
 		mutex_unlock(&rport_ptr->quota_lock);
-		wake_up(&rport_ptr->quota_wait);
 		break;
 
 	case IPC_ROUTER_CTRL_CMD_NEW_SERVER:
@@ -1939,8 +2039,8 @@
 	struct rr_header *hdr;
 	struct msm_ipc_router_xprt_info *xprt_info;
 	struct msm_ipc_routing_table_entry *rt_entry;
+	struct msm_ipc_resume_tx_port  *resume_tx_port;
 	int ret;
-	DEFINE_WAIT(__wait);
 
 	if (!rport_ptr || !src || !pkt)
 		return -EINVAL;
@@ -1965,29 +2065,33 @@
 	hdr->dst_port_id = rport_ptr->port_id;
 	pkt->length += IPC_ROUTER_HDR_SIZE;
 
-	for (;;) {
-		prepare_to_wait(&rport_ptr->quota_wait, &__wait,
-				TASK_INTERRUPTIBLE);
-		mutex_lock(&rport_ptr->quota_lock);
-		if (rport_ptr->restart_state != RESTART_NORMAL)
-			break;
-		if (rport_ptr->tx_quota_cnt <
-		     IPC_ROUTER_DEFAULT_RX_QUOTA)
-			break;
-		if (signal_pending(current))
-			break;
-		mutex_unlock(&rport_ptr->quota_lock);
-		schedule();
-	}
-	finish_wait(&rport_ptr->quota_wait, &__wait);
-
+	mutex_lock(&rport_ptr->quota_lock);
 	if (rport_ptr->restart_state != RESTART_NORMAL) {
 		mutex_unlock(&rport_ptr->quota_lock);
 		return -ENETRESET;
 	}
-	if (signal_pending(current)) {
+	if (rport_ptr->tx_quota_cnt == IPC_ROUTER_DEFAULT_RX_QUOTA) {
+		if (msm_ipc_router_lookup_resume_tx_port(
+			rport_ptr, src->this_port.port_id)) {
+			mutex_unlock(&rport_ptr->quota_lock);
+			return -EAGAIN;
+		}
+		resume_tx_port =
+			kzalloc(sizeof(struct msm_ipc_resume_tx_port),
+							GFP_KERNEL);
+		if (!resume_tx_port) {
+			pr_err("%s: Resume_Tx port allocation failed\n",
+								__func__);
+			mutex_unlock(&rport_ptr->quota_lock);
+			return -ENOMEM;
+		}
+		INIT_LIST_HEAD(&resume_tx_port->list);
+		resume_tx_port->port_id = src->this_port.port_id;
+		resume_tx_port->node_id = src->this_port.node_id;
+		list_add_tail(&resume_tx_port->list,
+				&rport_ptr->resume_tx_port_list);
 		mutex_unlock(&rport_ptr->quota_lock);
-		return -ERESTARTSYS;
+		return -EAGAIN;
 	}
 	rport_ptr->tx_quota_cnt++;
 	if (rport_ptr->tx_quota_cnt == IPC_ROUTER_DEFAULT_RX_QUOTA)
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 342663e..64d8fed 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -197,6 +197,7 @@
 	struct sockaddr_msm_ipc *addr;
 	struct rr_header *hdr;
 	struct sk_buff *temp;
+	union rr_control_msg *ctl_msg;
 	int offset = 0, data_len = 0, copy_len;
 
 	if (!m || !msg_head) {
@@ -207,6 +208,16 @@
 
 	temp = skb_peek(msg_head);
 	hdr = (struct rr_header *)(temp->data);
+	if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX)) {
+		skb_pull(temp, IPC_ROUTER_HDR_SIZE);
+		ctl_msg = (union rr_control_msg *)(temp->data);
+		addr->family = AF_MSM_IPC;
+		addr->address.addrtype = MSM_IPC_ADDR_ID;
+		addr->address.addr.port_addr.node_id = ctl_msg->cli.node_id;
+		addr->address.addr.port_addr.port_id = ctl_msg->cli.port_id;
+		m->msg_namelen = sizeof(struct sockaddr_msm_ipc);
+		return offset;
+	}
 	if (addr && (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
 		addr->family = AF_MSM_IPC;
 		addr->address.addrtype = MSM_IPC_ADDR_ID;
@@ -415,8 +426,10 @@
 				return -EFAULT;
 		}
 
-		if (timeout == 0)
+		if (timeout == 0) {
+			m->msg_namelen = 0;
 			return 0;
+		}
 		lock_sock(sk);
 		mutex_lock(&port_ptr->port_rx_q_lock);
 	}
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 953f941d..33a0aff 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -61,9 +61,7 @@
 #define PMIC_VOLTAGE_MAX		1355000
 #define LV_RANGE_STEP			5000
 
-#define LOAD_PER_PHASE			3200000
-
-#define CORE_VOLTAGE_MIN		900000
+#define CORE_VOLTAGE_BOOTUP		900000
 
 #define KRAIT_LDO_VOLTAGE_MIN		465000
 #define KRAIT_LDO_VOLTAGE_OFFSET	465000
@@ -146,7 +144,10 @@
  *				regulator's callback functions to prevent
  *				simultaneous updates to the pmic's phase
  *				voltage.
- * @apcs_gcc_base		virtual address of the APCS GCC registers
+ * @apcs_gcc_base:		virtual address of the APCS GCC registers
+ * @manage_phases:		begin phase control
+ * @pfm_threshold:		the sum of coefficients below which PFM can be
+ *				enabled
  */
 struct pmic_gang_vreg {
 	const char		*name;
@@ -159,6 +160,8 @@
 	bool			retention_enabled;
 	bool			use_phase_switching;
 	void __iomem		*apcs_gcc_base;
+	bool			manage_phases;
+	int			pfm_threshold;
 };
 
 static struct pmic_gang_vreg *the_gang;
@@ -168,6 +171,9 @@
 	LDO_MODE = REGULATOR_MODE_IDLE,
 };
 
+#define WAIT_FOR_LOAD		0x2
+#define WAIT_FOR_VOLTAGE	0x1
+
 struct krait_power_vreg {
 	struct list_head		link;
 	struct regulator_desc		desc;
@@ -175,7 +181,7 @@
 	const char			*name;
 	struct pmic_gang_vreg		*pvreg;
 	int				uV;
-	int				load_uA;
+	int				load;
 	enum krait_supply_mode		mode;
 	void __iomem			*reg_base;
 	void __iomem			*mdd_base;
@@ -185,7 +191,10 @@
 	int				ldo_threshold_uV;
 	int				ldo_delta_uV;
 	int				cpu_num;
+	int				coeff1;
+	int				coeff2;
 	bool				online;
+	int				online_at_probe;
 };
 
 DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
@@ -293,14 +302,263 @@
 	return 0;
 }
 
+#define COEFF2_UV_THRESHOLD 850000
+static int get_coeff2(int krait_uV)
+{
+	int coeff2 = 0;
+	int krait_mV = krait_uV / 1000;
+
+	if (krait_uV <= COEFF2_UV_THRESHOLD)
+		coeff2 = (612229 * krait_mV) / 1000 - 211258;
+	else
+		coeff2 = (892564 * krait_mV) / 1000 - 449543;
+
+	return  coeff2;
+}
+
+static int get_coeff1(int actual_uV, int requested_uV, int load)
+{
+	int ratio = actual_uV * 1000 / requested_uV;
+	int coeff1 = 330 * load + (load * 673 * ratio / 1000);
+
+	return coeff1;
+}
+
+static int get_coeff_total(struct krait_power_vreg *from)
+{
+	int coeff_total = 0;
+	struct krait_power_vreg *kvreg;
+	struct pmic_gang_vreg *pvreg = from->pvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		if (!kvreg->online)
+			continue;
+
+		if (kvreg->mode == LDO_MODE) {
+			kvreg->coeff1 =
+				get_coeff1(kvreg->uV - kvreg->ldo_delta_uV,
+							kvreg->uV, kvreg->load);
+			kvreg->coeff2 =
+				get_coeff2(kvreg->uV - kvreg->ldo_delta_uV);
+		} else {
+			kvreg->coeff1 =
+				get_coeff1(pvreg->pmic_vmax_uV,
+							kvreg->uV, kvreg->load);
+			kvreg->coeff2 = get_coeff2(pvreg->pmic_vmax_uV);
+		}
+		coeff_total += kvreg->coeff1 + kvreg->coeff2;
+	}
+
+	return coeff_total;
+}
+
+static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
+{
+	pr_debug("programming phase_count = %d\n", phase_count);
+	if (pvreg->use_phase_switching)
+		/*
+		 * note the PMIC sets the phase count to one more than
+		 * the value in the register - hence subtract 1 from it
+		 */
+		return msm_spm_apcs_set_phase(phase_count - 1);
+	else
+		return 0;
+}
+
+static int num_online(struct pmic_gang_vreg *pvreg)
+{
+	int online_total = 0;
+	struct krait_power_vreg *kvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		if (kvreg->online)
+			online_total++;
+	}
+	return online_total;
+}
+
+static int get_total_load(struct krait_power_vreg *from)
+{
+	int load_total = 0;
+	struct krait_power_vreg *kvreg;
+	struct pmic_gang_vreg *pvreg = from->pvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		if (!kvreg->online)
+			continue;
+		load_total += kvreg->load;
+	}
+
+	return load_total;
+}
+
+static bool enable_phase_management(struct pmic_gang_vreg *pvreg)
+{
+	struct krait_power_vreg *kvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		pr_debug("%s online_at_probe:0x%x\n", kvreg->name,
+							kvreg->online_at_probe);
+		if (kvreg->online_at_probe)
+			return false;
+	}
+	return true;
+}
+
+#define PMIC_FTS_MODE_PFM	0x00
+#define PMIC_FTS_MODE_PWM	0x80
+#define ONE_PHASE_COEFF		1000000
+#define TWO_PHASE_COEFF		2000000
+
+#define PWM_SETTLING_TIME_US		50
+#define PHASE_SETTLING_TIME_US		50
+static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
+				int coeff_total)
+{
+	struct pmic_gang_vreg *pvreg = from->pvreg;
+	int phase_count;
+	int rc = 0;
+	int n_online = num_online(pvreg);
+	int load_total;
+
+	load_total = get_total_load(from);
+
+	if (pvreg->manage_phases == false) {
+		if (enable_phase_management(pvreg))
+			pvreg->manage_phases = true;
+		else
+			return 0;
+	}
+
+	/* First check if the coeff is low for PFM mode */
+	if (load_total <= pvreg->pfm_threshold && n_online == 1) {
+		if (!pvreg->pfm_mode) {
+			rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
+			if (rc) {
+				pr_err("%s PFM en failed load_t %d rc = %d\n",
+					from->name, load_total, rc);
+				return rc;
+			} else {
+				pvreg->pfm_mode = true;
+			}
+		}
+		return rc;
+	}
+
+	/* coeff is high switch to PWM mode before changing phases */
+	if (pvreg->pfm_mode) {
+		rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
+		if (rc) {
+			pr_err("%s PFM exit failed load %d rc = %d\n",
+				from->name, coeff_total, rc);
+			return rc;
+		} else {
+			pvreg->pfm_mode = false;
+			udelay(PWM_SETTLING_TIME_US);
+		}
+	}
+
+	/* calculate phases */
+	if (coeff_total < ONE_PHASE_COEFF)
+		phase_count = 1;
+	else if (coeff_total < TWO_PHASE_COEFF)
+		phase_count = 2;
+	else
+		phase_count = 4;
+
+	/* don't increase the phase count higher than number of online cpus */
+	if (phase_count > n_online)
+		phase_count = n_online;
+
+	if (phase_count != pvreg->pmic_phase_count) {
+		rc = set_pmic_gang_phases(pvreg, phase_count);
+		if (rc < 0) {
+			pr_err("%s failed set phase %d rc = %d\n",
+				from->name, phase_count, rc);
+			return rc;
+		}
+
+		/* complete the writes before the delay */
+		mb();
+
+		/*
+		 * delay until the phases are settled when
+		 * the count is raised
+		 */
+		if (phase_count > pvreg->pmic_phase_count)
+			udelay(PHASE_SETTLING_TIME_US);
+
+		pvreg->pmic_phase_count = phase_count;
+	}
+
+	return rc;
+}
+
+static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
+			int input_uV, int output_uV, int load)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+	int coeff_total;
+	int rc;
+
+	kvreg->online_at_probe &= ~WAIT_FOR_LOAD;
+	coeff_total = get_coeff_total(kvreg);
+
+	rc = pmic_gang_set_phases(kvreg, coeff_total);
+	if (rc < 0) {
+		dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
+				kvreg->name, coeff_total, rc);
+	}
+
+	return kvreg->mode;
+}
+
+static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
+			int input_uV, int output_uV, int load_uA)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
+	int rc;
+
+	mutex_lock(&pvreg->krait_power_vregs_lock);
+	kvreg->load = load_uA;
+	if (!kvreg->online) {
+		mutex_unlock(&pvreg->krait_power_vregs_lock);
+		return kvreg->mode;
+	}
+
+	rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
+	mutex_unlock(&pvreg->krait_power_vregs_lock);
+
+	return rc;
+}
+
+static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	return 0;
+}
+
+static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+
+	return kvreg->mode;
+}
+
 static int switch_to_using_hs(struct krait_power_vreg *kvreg)
 {
 	if (kvreg->mode == HS_MODE)
 		return 0;
 	/* enable bhs */
+	krait_masked_write(kvreg, APC_PWR_GATE_CTL, BHS_EN_MASK, BHS_EN_MASK);
+	/* complete the above write before the delay */
+	mb();
+	/* wait for the bhs to settle */
+	udelay(BHS_SETTLING_DELAY_US);
+
+	/* Turn on BHS segments */
 	krait_masked_write(kvreg, APC_PWR_GATE_CTL,
-		BHS_SEG_EN_MASK | BHS_EN_MASK,
-		BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS | BHS_EN_MASK);
+		BHS_SEG_EN_MASK, BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS);
 
 	/* complete the above write before the delay */
 	mb();
@@ -368,19 +626,6 @@
 	return 0;
 }
 
-static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
-{
-	pr_debug("programming phase_count = %d\n", phase_count);
-	if (pvreg->use_phase_switching)
-		/*
-		 * note the PMIC sets the phase count to one more than
-		 * the value in the register - hence subtract 1 from it
-		 */
-		return msm_spm_apcs_set_phase(phase_count - 1);
-	else
-		return 0;
-}
-
 static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
 {
 	int setpoint;
@@ -524,46 +769,6 @@
 	return rc;
 }
 
-#define PHASE_SETTLING_TIME_US		10
-static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
-				int load_uA)
-{
-	struct pmic_gang_vreg *pvreg = from->pvreg;
-	int phase_count = DIV_ROUND_UP(load_uA, LOAD_PER_PHASE);
-	int rc = 0;
-
-	if (phase_count <= 0)
-		phase_count = 1;
-
-	 /* Increase phases if it is less than the number of cpus online */
-	if (phase_count < num_online_cpus()) {
-		phase_count = num_online_cpus();
-	}
-
-	if (phase_count != pvreg->pmic_phase_count) {
-		rc = set_pmic_gang_phases(pvreg, phase_count);
-		if (rc < 0) {
-			dev_err(&from->rdev->dev,
-				"%s failed set phase %d rc = %d\n",
-				pvreg->name, phase_count, rc);
-			return rc;
-		}
-
-		/* complete the writes before the delay */
-		mb();
-
-		/*
-		 * delay until the phases are settled when
-		 * the count is raised
-		 */
-		if (phase_count > pvreg->pmic_phase_count)
-			udelay(PHASE_SETTLING_TIME_US);
-
-		pvreg->pmic_phase_count = phase_count;
-	}
-	return rc;
-}
-
 static int krait_power_get_voltage(struct regulator_dev *rdev)
 {
 	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -590,21 +795,6 @@
 	return vmax;
 }
 
-static int get_total_load(struct krait_power_vreg *from)
-{
-	int load_total = 0;
-	struct krait_power_vreg *kvreg;
-	struct pmic_gang_vreg *pvreg = from->pvreg;
-
-	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
-		if (!kvreg->online)
-			continue;
-		load_total += kvreg->load_uA;
-	}
-
-	return load_total;
-}
-
 #define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
 static int _set_voltage(struct regulator_dev *rdev,
 			int orig_krait_uV, int requested_uV)
@@ -613,6 +803,7 @@
 	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
 	int rc;
 	int vmax;
+	int coeff_total;
 
 	pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
 	/*
@@ -636,6 +827,11 @@
 				kvreg->name, requested_uV, orig_krait_uV, rc);
 	}
 
+	kvreg->online_at_probe &= ~WAIT_FOR_VOLTAGE;
+	coeff_total = get_coeff_total(kvreg);
+	/* adjust the phases since coeff2 would have changed */
+	rc = pmic_gang_set_phases(kvreg, coeff_total);
+
 	return rc;
 }
 
@@ -670,89 +866,6 @@
 	return rc;
 }
 
-#define PMIC_FTS_MODE_PFM	0x00
-#define PMIC_FTS_MODE_PWM	0x80
-#define PFM_LOAD_UA		500000
-static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
-			int input_uV, int output_uV, int load_uA)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
-	int rc;
-	int load_total_uA;
-
-	load_total_uA = get_total_load(kvreg);
-
-	if (load_total_uA < PFM_LOAD_UA) {
-		if (!pvreg->pfm_mode) {
-			rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
-			if (rc) {
-				dev_err(&rdev->dev,
-					"%s enter PFM failed load %d rc = %d\n",
-					kvreg->name, load_total_uA, rc);
-				goto out;
-			} else {
-				pvreg->pfm_mode = true;
-			}
-		}
-		return kvreg->mode;
-	}
-
-	if (pvreg->pfm_mode) {
-		rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
-		if (rc) {
-			dev_err(&rdev->dev,
-				"%s exit PFM failed load %d rc = %d\n",
-				kvreg->name, load_total_uA, rc);
-			goto out;
-		} else {
-			pvreg->pfm_mode = false;
-		}
-	}
-
-	rc = pmic_gang_set_phases(kvreg, load_total_uA);
-	if (rc < 0) {
-		dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
-				kvreg->name, load_total_uA, rc);
-		goto out;
-	}
-
-out:
-	return kvreg->mode;
-}
-
-static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
-			int input_uV, int output_uV, int load_uA)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
-	int rc;
-
-	mutex_lock(&pvreg->krait_power_vregs_lock);
-	kvreg->load_uA = load_uA;
-	if (!kvreg->online) {
-		mutex_unlock(&pvreg->krait_power_vregs_lock);
-		return kvreg->mode;
-	}
-
-	rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
-	mutex_unlock(&pvreg->krait_power_vregs_lock);
-
-	return rc;
-}
-
-static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
-{
-	return 0;
-}
-
-static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-
-	return kvreg->mode;
-}
-
 static int krait_power_is_enabled(struct regulator_dev *rdev)
 {
 	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -769,7 +882,7 @@
 	mutex_lock(&pvreg->krait_power_vregs_lock);
 	__krait_power_mdd_enable(kvreg, true);
 	kvreg->online = true;
-	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
+	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
 	if (rc < 0)
 		goto en_err;
 	/*
@@ -791,8 +904,7 @@
 	mutex_lock(&pvreg->krait_power_vregs_lock);
 	kvreg->online = false;
 
-	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV,
-							kvreg->load_uA);
+	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
 	if (rc < 0)
 		goto dis_err;
 
@@ -851,8 +963,10 @@
 DEFINE_SIMPLE_ATTRIBUTE(retention_fops,
 			get_retention_dbg_uV, set_retention_dbg_uV, "%llu\n");
 
+#define CPU_PWR_CTL_ONLINE_MASK 0x80
 static void kvreg_hw_init(struct krait_power_vreg *kvreg)
 {
+	int online;
 	/*
 	 * bhs_cnt value sets the ramp-up time from power collapse,
 	 * initialize the ramp up time
@@ -865,6 +979,10 @@
 	/* Enable MDD */
 	writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
 	mb();
+	online = CPU_PWR_CTL_ONLINE_MASK
+			& readl_relaxed(kvreg->reg_base + CPU_PWR_CTL);
+	kvreg->online_at_probe
+		= online ? (WAIT_FOR_LOAD | WAIT_FOR_VOLTAGE) : 0x0;
 }
 
 static void glb_init(void __iomem *apcs_gcc_base)
@@ -1012,7 +1130,7 @@
 	kvreg->desc.ops		= &krait_power_ops;
 	kvreg->desc.type	= REGULATOR_VOLTAGE;
 	kvreg->desc.owner	= THIS_MODULE;
-	kvreg->uV		= CORE_VOLTAGE_MIN;
+	kvreg->uV		= CORE_VOLTAGE_BOOTUP;
 	kvreg->mode		= HS_MODE;
 	kvreg->desc.ops		= &krait_power_ops;
 	kvreg->headroom_uV	= headroom_uV;
@@ -1111,6 +1229,7 @@
 {
 	int rc;
 	bool use_phase_switching = false;
+	int pfm_threshold;
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
 	struct pmic_gang_vreg *pvreg;
@@ -1123,6 +1242,13 @@
 
 	use_phase_switching = of_property_read_bool(node,
 						"qcom,use-phase-switching");
+
+	rc = of_property_read_u32(node, "qcom,pfm-threshold", &pfm_threshold);
+	if (rc < 0) {
+		dev_err(dev, "pfm-threshold missing rc=%d, pfm disabled\n", rc);
+		return -EINVAL;
+	}
+
 	pvreg = devm_kzalloc(&pdev->dev,
 			sizeof(struct pmic_gang_vreg), GFP_KERNEL);
 	if (!pvreg) {
@@ -1148,6 +1274,7 @@
 	pvreg->retention_enabled = true;
 	pvreg->pmic_min_uV_for_retention = INT_MAX;
 	pvreg->use_phase_switching = use_phase_switching;
+	pvreg->pfm_threshold = pfm_threshold;
 
 	mutex_init(&pvreg->krait_power_vregs_lock);
 	INIT_LIST_HEAD(&pvreg->krait_power_vregs);
@@ -1208,32 +1335,32 @@
 
 void secondary_cpu_hs_init(void *base_ptr)
 {
+	uint32_t reg_val;
+
 	/* Turn on the BHS, turn off LDO Bypass and power down LDO */
-	writel_relaxed(
-		BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
+	reg_val =  BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
 		| LDO_PWR_DWN_MASK
 		| CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
-		| BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
-		| BHS_EN_MASK,
-		base_ptr + APC_PWR_GATE_CTL);
+		| BHS_EN_MASK;
+	writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL);
 
 	/* complete the above write before the delay */
 	mb();
+	/* wait for the bhs to settle */
+	udelay(BHS_SETTLING_DELAY_US);
 
-	/*
-	 * wait for the bhs to settle
-	 */
+	/* Turn on BHS segments */
+	reg_val |= BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS;
+	writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL);
+
+	/* complete the above write before the delay */
+	mb();
+	 /* wait for the bhs to settle */
 	udelay(BHS_SETTLING_DELAY_US);
 
 	/* Finally turn on the bypass so that BHS supplies power */
-	writel_relaxed(
-		BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
-		| LDO_PWR_DWN_MASK
-		| CLK_SRC_DEFAULT << CLK_SRC_SEL_BIT_POS
-		| LDO_BYP_MASK
-		| BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
-		| BHS_EN_MASK,
-		base_ptr + APC_PWR_GATE_CTL);
+	reg_val |= LDO_BYP_MASK;
+	writel_relaxed(reg_val, base_ptr + APC_PWR_GATE_CTL);
 }
 
 MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index 4adfe4d..5002a7d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -314,7 +314,7 @@
 	struct msm_bus_inode_info *info;
 	int next_pnode;
 	int64_t add_bw = req_bw - curr_bw;
-	unsigned bwsum = 0;
+	uint64_t bwsum = 0;
 	uint64_t req_clk_hz, curr_clk_hz, bwsum_hz;
 	int *master_tiers;
 	struct msm_bus_fabric_device *fabdev = msm_bus_get_fabric_device
@@ -398,7 +398,7 @@
 		/* Update Bandwidth */
 		fabdev->algo->update_bw(fabdev, hop, info, add_bw,
 			master_tiers, ctx);
-		bwsum = (uint16_t)*hop->link_info.sel_bw;
+		bwsum = *hop->link_info.sel_bw;
 		/* Update Fabric clocks */
 		curr_clk_hz = BW_TO_CLK_FREQ_HZ(hop->node_info->buswidth,
 			curr_clk);
@@ -574,6 +574,10 @@
 
 	curr = client->curr;
 	pdata = client->pdata;
+	if (!pdata) {
+		MSM_BUS_ERR("Null pdata passed to update-request\n");
+		return -ENXIO;
+	}
 
 	if (index >= pdata->num_usecases) {
 		MSM_BUS_ERR("Client %u passed invalid index: %d\n",
@@ -718,7 +722,7 @@
 {
 	int i, src, pnode, index;
 	struct msm_bus_client *client = (struct msm_bus_client *)(cl);
-	if (IS_ERR(client)) {
+	if (IS_ERR_OR_NULL(client)) {
 		MSM_BUS_ERR("msm_bus_scale_reset_pnodes error\n");
 		return;
 	}
@@ -739,7 +743,7 @@
 void msm_bus_scale_unregister_client(uint32_t cl)
 {
 	struct msm_bus_client *client = (struct msm_bus_client *)(cl);
-	if (IS_ERR(client) || (!client))
+	if (IS_ERR_OR_NULL(client))
 		return;
 	if (client->curr != 0)
 		msm_bus_scale_client_update_request(cl, 0);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
index b45efad..ff3dc21 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
@@ -437,10 +437,7 @@
 	},
 };
 
-static int mport_mdp[] = {
-	MSM_BUS_MASTER_PORT_MDP_PORT0,
-	MSM_BUS_MASTER_PORT_MDP_PORT1,
-};
+static int mport_mdp[] = {MSM_BUS_MASTER_PORT_MDP_PORT0,};
 static int mport_mdp1[] = {MSM_BUS_MASTER_PORT_MDP_PORT1,};
 static int mport_rotator[] = {MSM_BUS_MASTER_PORT_ROTATOR,};
 static int mport_graphics_3d_port0[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D_PORT0,};
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
index 91d106e..af51355 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
@@ -377,10 +377,7 @@
 	},
 };
 
-static int mport_mdp[] = {
-	MSM_BUS_MASTER_PORT_MDP_PORT0,
-	MSM_BUS_MASTER_PORT_MDP_PORT1,
-};
+static int mport_mdp[] = {MSM_BUS_MASTER_PORT_MDP_PORT0,};
 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,};
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 158dee3..295b91b 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -440,10 +440,7 @@
 	},
 };
 
-static int mport_mdp[] = {
-	MSM_BUS_MASTER_PORT_MDP_PORT0,
-	MSM_BUS_MASTER_PORT_MDP_PORT1,
-};
+static int mport_mdp[] = {MSM_BUS_MASTER_PORT_MDP_PORT0,};
 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,};
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index fd2dbb5..98419a4 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -36,7 +36,7 @@
 	(((slv >= MSM_BUS_SLAVE_FIRST) && (slv <= MSM_BUS_SLAVE_LAST)) ? 1 : 0)
 
 #define INTERLEAVED_BW(fab_pdata, bw, ports) \
-	((fab_pdata->il_flag) ? msm_bus_div64((bw), (ports)) : (bw))
+	((fab_pdata->il_flag) ? msm_bus_div64((ports), (bw)) : (bw))
 #define INTERLEAVED_VAL(fab_pdata, n) \
 	((fab_pdata->il_flag) ? (n) : 1)
 
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 4ea1de9..4ed4eda 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -97,9 +97,12 @@
 #define REGION_SLEEP_PERI_ON 0x00007777
 
 #define REGION_DEFAULT_OFF REGION_SLEEP_NO_RETENTION
-#define REGION_DEFAULT_ON REGION_NORMAL_PASSTHROUGH
+#define REGION_DEFAULT_ON REGION_FORCE_CORE_ON
 #define REGION_DEFAULT_RETENTION REGION_SLEEP_PERI_OFF
 
+#define REGION_STAGING_SET(x) (REGION_SLEEP_PERI_OFF & (0xF << (x * 0x4)))
+#define REGION_ON_SET(x) (REGION_DEFAULT_OFF & (0xF << (x * 0x4)))
+
 enum rpm_macro_state {
 	rpm_macro_off = 0x0,
 	rpm_macro_retain,
@@ -195,6 +198,51 @@
 
 	return state;
 }
+#ifndef CONFIG_MSM_OCMEM_POWER_DISABLE
+static int commit_region_staging(unsigned region_num, unsigned start_m,
+				unsigned new_state)
+{
+	int rc = -1;
+	unsigned state = 0x0;
+	unsigned read_state = 0x0;
+	unsigned curr_state = 0x0;
+
+	if (region_num >= num_regions)
+		return -EINVAL;
+
+	if (rpm_power_control)
+		return 0;
+	else {
+		if (new_state != REGION_DEFAULT_OFF) {
+			curr_state = read_region_state(region_num);
+			state = curr_state | REGION_STAGING_SET(start_m);
+			rc = ocmem_write(state,
+				ocmem_base + PSCGC_CTL_n(region_num));
+			/* Barrier to commit the region state */
+			mb();
+			read_state = read_region_state(region_num);
+			if (new_state == REGION_DEFAULT_ON) {
+				curr_state = read_region_state(region_num);
+				state = curr_state ^ REGION_ON_SET(start_m);
+				rc = ocmem_write(state,
+					ocmem_base + PSCGC_CTL_n(region_num));
+				/* Barrier to commit the region state */
+				mb();
+				read_state = read_region_state(region_num);
+			}
+		} else {
+			curr_state = read_region_state(region_num);
+			state = curr_state ^ REGION_STAGING_SET(start_m);
+			rc = ocmem_write(state,
+				ocmem_base + PSCGC_CTL_n(region_num));
+			/* Barrier to commit the region state */
+			mb();
+			read_state = read_region_state(region_num);
+		}
+	}
+	return 0;
+}
+#endif
 
 /* Returns the current state of a OCMEM macro that belongs to a region */
 static int read_macro_state(unsigned region_num, unsigned macro_num)
@@ -948,9 +996,11 @@
 			apply_macro_vote(id, i, j,
 				hw_macro_state(new_state));
 			aggregate_macro_state(i, j);
+			commit_region_staging(i, j, new_state);
 		}
 		aggregate_region_state(i);
-		commit_region_state(i);
+		if (rpm_power_control)
+			commit_region_state(i);
 		len -= region_size;
 
 		/* If we voted ON/retain the banks must never be OFF */
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 8afe695..a14b960 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -1515,6 +1515,18 @@
 				pr_err("ocmem: Failed to unmap %p\n", req);
 				goto free_fail;
 			}
+			/* Turn off the memory */
+			if (req->req_sz != 0) {
+
+				offset = phys_to_offset(req->req_start);
+				rc = ocmem_memory_off(req->owner, offset,
+					req->req_sz);
+
+				if (rc < 0) {
+					pr_err("Failed to switch OFF memory macros\n");
+					goto free_fail;
+				}
+			}
 
 			rc = do_free(req);
 			if (rc < 0) {
@@ -1525,21 +1537,19 @@
 			pr_debug("request %p was already shrunk to 0\n", req);
 	}
 
-	/* Turn off the memory */
-	if (req->req_sz != 0) {
+	if (!TEST_STATE(req, R_FREE)) {
+		/* Turn off the memory */
+		if (req->req_sz != 0) {
 
-		offset = phys_to_offset(req->req_start);
+			offset = phys_to_offset(req->req_start);
+			rc = ocmem_memory_off(req->owner, offset, req->req_sz);
 
-		rc = ocmem_memory_off(req->owner, offset, req->req_sz);
-
-		if (rc < 0) {
-			pr_err("Failed to switch OFF memory macros\n");
-			goto free_fail;
+			if (rc < 0) {
+				pr_err("Failed to switch OFF memory macros\n");
+				goto free_fail;
+			}
 		}
 
-	}
-
-	if (!TEST_STATE(req, R_FREE)) {
 		/* free the allocation */
 		rc = do_free(req);
 		if (rc < 0)
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 056da7d..475e8a1 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -290,10 +290,12 @@
 static void pil_dump_segs(const struct pil_priv *priv)
 {
 	struct pil_seg *seg;
+	phys_addr_t seg_h_paddr;
 
 	list_for_each_entry(seg, &priv->segs, list) {
-		pil_info(priv->desc, "%d: %#08zx %#08lx\n", seg->num,
-				seg->paddr, seg->paddr + seg->sz);
+		seg_h_paddr = seg->paddr + seg->sz;
+		pil_info(priv->desc, "%d: %pa %pa\n", seg->num,
+				&seg->paddr, &seg_h_paddr);
 	}
 }
 
@@ -322,7 +324,7 @@
 				return 0;
 		}
 	}
-	pil_err(priv->desc, "entry address %08zx not within range\n", entry);
+	pil_err(priv->desc, "entry address %pa not within range\n", &entry);
 	pil_dump_segs(priv);
 	return -EADDRNOTAVAIL;
 }
@@ -489,7 +491,8 @@
 
 static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg)
 {
-	int ret = 0, count, paddr;
+	int ret = 0, count;
+	phys_addr_t paddr;
 	char fw_name[30];
 	const struct firmware *fw = NULL;
 	const u8 *data;
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index ff10fe5..5aeeaf3 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -55,7 +55,8 @@
 	int (*init_image)(struct pil_desc *pil, const u8 *metadata,
 			  size_t size);
 	int (*mem_setup)(struct pil_desc *pil, phys_addr_t addr, size_t size);
-	int (*verify_blob)(struct pil_desc *pil, u32 phy_addr, size_t size);
+	int (*verify_blob)(struct pil_desc *pil, phys_addr_t phy_addr,
+			   size_t size);
 	int (*proxy_vote)(struct pil_desc *pil);
 	int (*auth_and_reset)(struct pil_desc *pil);
 	void (*proxy_unvote)(struct pil_desc *pil);
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index d44add6..65f86bc 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -203,7 +203,7 @@
 {
 	struct gss_data *drv = dev_get_drvdata(pil->dev);
 	void __iomem *base = drv->base;
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 	void __iomem *cbase = drv->cbase;
 	int ret;
 
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 30f480a..8398206 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -93,7 +93,7 @@
 {
 	u32 reg;
 	const struct modem_data *drv = dev_get_drvdata(pil->dev);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 
 	/* Put modem AHB0,1,2 clocks into reset */
 	writel_relaxed(BIT(0) | BIT(1), drv->cbase + MAHB0_SFAB_PORT_RESET);
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 0df8739..cf29cf1 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -123,7 +123,7 @@
 	int rc;
 	struct pronto_data *drv = dev_get_drvdata(pil->dev);
 	void __iomem *base = drv->base;
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 
 	/* Deassert reset to subsystem and wait for propagation */
 	reg = readl_relaxed(drv->reset_base);
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 0575a3d..a369878 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -116,7 +116,7 @@
 {
 	u32 reg;
 	struct q6v3_data *drv = dev_get_drvdata(pil->dev);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 
 	/* Put Q6 into reset */
 	reg = readl_relaxed(drv->cbase + LCC_Q6_FUNC);
diff --git a/arch/arm/mach-msm/pil-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
index 29d14dd..51f7aa2 100644
--- a/arch/arm/mach-msm/pil-q6v4.c
+++ b/arch/arm/mach-msm/pil-q6v4.c
@@ -130,7 +130,7 @@
 {
 	u32 reg, err;
 	const struct q6v4_data *drv = pil_to_q6v4_data(pil);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 
 	/* Enable Q6 ACLK */
 	writel_relaxed(0x10, drv->aclk_reg);
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 277addc..04c1be3 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -127,7 +127,7 @@
 static int pil_lpass_reset(struct pil_desc *pil)
 {
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 	int ret;
 
 	/* Deassert reset to subsystem and wait for propagation */
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index c3a0d32..3ce1283 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -243,7 +243,7 @@
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
 	struct platform_device *pdev = to_platform_device(pil->dev);
 	struct mba_data *mba = platform_get_drvdata(pdev);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 	int ret;
 
 	/*
@@ -402,7 +402,7 @@
 	return ret;
 }
 
-static int pil_mba_verify_blob(struct pil_desc *pil, u32 phy_addr,
+static int pil_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr,
 			       size_t size)
 {
 	struct mba_data *drv = dev_get_drvdata(pil->dev);
@@ -650,6 +650,17 @@
 	drv->subsys_desc.start = mss_start;
 	drv->subsys_desc.stop = mss_stop;
 
+	ret = of_get_named_gpio(pdev->dev.of_node,
+			"qcom,gpio-err-ready", 0);
+	if (ret < 0)
+		return ret;
+
+	ret = gpio_to_irq(ret);
+	if (ret < 0)
+		return ret;
+
+	drv->subsys_desc.err_ready_irq = ret;
+
 	drv->subsys = subsys_register(&drv->subsys_desc);
 	if (IS_ERR(drv->subsys)) {
 		ret = PTR_ERR(drv->subsys);
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index a2665b4..d72b848 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -134,7 +134,7 @@
 	u32 reg, sel;
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
 	void __iomem *base = drv->base;
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 	void __iomem *cbase = drv->cbase;
 	bool use_cxo = cxo_is_needed(drv);
 
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 5a6e66a..4fca346 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -64,7 +64,6 @@
 	(container_of(attr, struct msm_pm_kobj_attribute, ka)->cpu)
 
 #define SCLK_HZ (32768)
-#define MSM_PM_SLEEP_TICK_LIMIT (0x6DDD000)
 
 #define NUM_OF_COUNTERS 3
 #define MAX_BUF_SIZE  512
@@ -127,7 +126,6 @@
 static bool msm_pm_use_sync_timer;
 static struct msm_pm_cp15_save_data cp15_data;
 static bool msm_pm_retention_calls_tz;
-static uint32_t msm_pm_max_sleep_time;
 static bool msm_no_ramp_down_pc;
 static struct msm_pm_sleep_status_data *msm_pm_slp_sts;
 static bool msm_pm_pc_reset_timer;
@@ -405,39 +403,6 @@
 	return;
 }
 
-/*
- * Convert time from nanoseconds to slow clock ticks, then cap it to the
- * specified limit
- */
-static int64_t msm_pm_convert_and_cap_time(int64_t time_ns, int64_t limit)
-{
-	do_div(time_ns, NSEC_PER_SEC / SCLK_HZ);
-	return (time_ns > limit) ? limit : time_ns;
-}
-
-/*
- * Set the sleep time for suspend.  0 means infinite sleep time.
- */
-void msm_pm_set_max_sleep_time(int64_t max_sleep_time_ns)
-{
-	if (max_sleep_time_ns == 0) {
-		msm_pm_max_sleep_time = 0;
-	} else {
-		msm_pm_max_sleep_time =
-			(uint32_t)msm_pm_convert_and_cap_time(
-			max_sleep_time_ns, MSM_PM_SLEEP_TICK_LIMIT);
-
-		if (msm_pm_max_sleep_time == 0)
-			msm_pm_max_sleep_time = 1;
-	}
-
-	if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
-		pr_info("%s: Requested %lld ns Giving %u sclk ticks\n",
-			__func__, max_sleep_time_ns,
-			msm_pm_max_sleep_time);
-}
-EXPORT_SYMBOL(msm_pm_set_max_sleep_time);
-
 static void msm_pm_save_cpu_reg(void)
 {
 	int i;
@@ -869,9 +834,8 @@
 	int exit_stat = -1;
 	enum msm_pm_sleep_mode sleep_mode;
 	void *msm_pm_idle_rs_limits = NULL;
-	int sleep_delay = 1;
+	uint32_t sleep_delay = 1;
 	int ret = -ENODEV;
-	int64_t timer_expiration = 0;
 	int notify_rpm = false;
 	bool timer_halted = false;
 
@@ -891,10 +855,8 @@
 
 	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
 		notify_rpm = true;
-		timer_expiration = msm_pm_timer_enter_idle();
+		sleep_delay = (uint32_t)msm_pm_timer_enter_idle();
 
-		sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
-			timer_expiration, MSM_PM_SLEEP_TICK_LIMIT);
 		if (sleep_delay == 0) /* 0 would mean infinite time */
 			sleep_delay = 1;
 	}
@@ -1081,6 +1043,7 @@
 		void *rs_limits = NULL;
 		int ret = -ENODEV;
 		uint32_t power;
+		uint32_t msm_pm_max_sleep_time = 0;
 
 		if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
 			pr_info("%s: power collapse\n", __func__);
@@ -1090,8 +1053,8 @@
 		if (msm_pm_sleep_time_override > 0) {
 			int64_t ns = NSEC_PER_SEC *
 				(int64_t) msm_pm_sleep_time_override;
-			msm_pm_set_max_sleep_time(ns);
-			msm_pm_sleep_time_override = 0;
+			do_div(ns, NSEC_PER_SEC / SCLK_HZ);
+			msm_pm_max_sleep_time = (uint32_t) ns;
 		}
 
 		if (pm_sleep_ops.lowest_limits)
@@ -1405,7 +1368,7 @@
 	if (!data)
 		return -EINVAL;
 
-	if (!bufu || count < 0)
+	if (!bufu)
 		return -EINVAL;
 
 	if (!access_ok(VERIFY_WRITE, bufu, count))
diff --git a/arch/arm/mach-msm/pm-data.c b/arch/arm/mach-msm/pm-data.c
index 249032f..f41c569 100644
--- a/arch/arm/mach-msm/pm-data.c
+++ b/arch/arm/mach-msm/pm-data.c
@@ -125,4 +125,11 @@
 		.idle_enabled = 1,
 		.suspend_enabled = 0,
 	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_NR)] = {
+		.idle_supported = 0,
+		.suspend_supported = 0,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
 };
diff --git a/arch/arm/mach-msm/rpm_log.c b/arch/arm/mach-msm/rpm_log.c
index 53d5752..58e8588 100644
--- a/arch/arm/mach-msm/rpm_log.c
+++ b/arch/arm/mach-msm/rpm_log.c
@@ -213,7 +213,7 @@
 		return -EINVAL;
 	if (!buf->data)
 		return -ENOMEM;
-	if (!bufu || count < 0)
+	if (!bufu || count == 0)
 		return -EINVAL;
 	if (!access_ok(VERIFY_WRITE, bufu, count))
 		return -EFAULT;
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 424d310..20a6165 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -41,7 +41,7 @@
 #ifdef CONFIG_ARCH_FSM9XXX
 #define NUM_SMD_PKT_PORTS 4
 #else
-#define NUM_SMD_PKT_PORTS 27
+#define NUM_SMD_PKT_PORTS 28
 #endif
 
 #define PDRIVER_NAME_MAX_SIZE 32
@@ -729,6 +729,7 @@
 	"smd_test_framework",
 	"smd_logging_0",
 	"smd_data_0",
+	"apr",
 	"smd_pkt_loopback",
 };
 
@@ -759,6 +760,7 @@
 	"TESTFRAMEWORK",
 	"LOGGING",
 	"DATA",
+	"apr",
 	"LOOPBACK",
 };
 
@@ -789,6 +791,7 @@
 	SMD_APPS_QDSP,
 	SMD_APPS_QDSP,
 	SMD_APPS_QDSP,
+	SMD_APPS_QDSP,
 	SMD_APPS_MODEM,
 };
 #endif
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 174d444..8e94b3a 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -76,7 +76,7 @@
 	info.vlevel = vlevel;
 	info.err = -ENODEV;
 
-	if (cpu_online(cpu)) {
+	if ((smp_processor_id() != cpu) && cpu_online(cpu)) {
 		/**
 		 * We do not want to set the voltage of another core from
 		 * this core, as its possible that we may race the vdd change
@@ -404,21 +404,28 @@
 	memset(&modes, 0,
 		(MSM_SPM_MODE_NR - 2) * sizeof(struct msm_spm_seq_entry));
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		goto fail;
-
-	spm_data.reg_base_addr = devm_ioremap(&pdev->dev, res->start,
-					resource_size(res));
-	if (!spm_data.reg_base_addr)
-		return -ENOMEM;
-
 	key = "qcom,core-id";
 	ret = of_property_read_u32(node, key, &val);
 	if (ret)
 		goto fail;
 	cpu = val;
 
+	/*
+	 * Device with id 0..NR_CPUS are SPM for apps cores
+	 * Device with id 0xFFFF is for L2 SPM.
+	 */
+	if (cpu >= 0 && cpu < num_possible_cpus()) {
+		mode_of_data = of_cpu_modes;
+		num_modes = ARRAY_SIZE(of_cpu_modes);
+		dev = &per_cpu(msm_cpu_spm_device, cpu);
+
+	} else if (cpu == 0xffff) {
+		mode_of_data = of_l2_modes;
+		num_modes = ARRAY_SIZE(of_l2_modes);
+		dev = &msm_spm_l2_device;
+	} else
+		return ret;
+
 	key = "qcom,saw2-ver-reg";
 	ret = of_property_read_u32(node, key, &val);
 	if (ret)
@@ -429,21 +436,17 @@
 	ret = of_property_read_u32(node, key, &val);
 	if (!ret)
 		spm_data.vctl_timeout_us = val;
+	else if (cpu == 0xffff)
+		goto fail;
 
-	/*
-	 * Device with id 0..NR_CPUS are SPM for apps cores
-	 * Device with id 0xFFFF is for L2 SPM.
-	 */
-	if (cpu >= 0 && cpu < num_possible_cpus()) {
-		mode_of_data = of_cpu_modes;
-		num_modes = ARRAY_SIZE(of_cpu_modes);
-		dev = &per_cpu(msm_cpu_spm_device, cpu);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto fail;
 
-	} else {
-		mode_of_data = of_l2_modes;
-		num_modes = ARRAY_SIZE(of_l2_modes);
-		dev = &msm_spm_l2_device;
-	}
+	spm_data.reg_base_addr = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+	if (!spm_data.reg_base_addr)
+		return -ENOMEM;
 
 	spm_data.vctl_port = -1;
 	spm_data.phase_port = -1;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 5fe7a29..fb44e16 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -31,6 +31,7 @@
 #include <linux/idr.h>
 #include <linux/debugfs.h>
 #include <linux/miscdevice.h>
+#include <linux/interrupt.h>
 
 #include <asm/current.h>
 
@@ -132,6 +133,7 @@
  * @restart_order: order of other devices this devices restarts with
  * @dentry: debugfs directory for this device
  * @do_ramdump_on_put: ramdump on subsystem_put() if true
+ * @err_ready: completion variable to record error ready from subsystem
  */
 struct subsys_device {
 	struct subsys_desc *desc;
@@ -154,6 +156,7 @@
 	bool do_ramdump_on_put;
 	struct miscdevice misc_dev;
 	char miscdevice_name[32];
+	struct completion err_ready;
 };
 
 static struct subsys_device *to_subsys(struct device *d)
@@ -412,6 +415,21 @@
 	}
 }
 
+static int wait_for_err_ready(struct subsys_device *subsys)
+{
+	int ret;
+
+	if (!subsys->desc->err_ready_irq)
+		return 0;
+
+	ret = wait_for_completion_timeout(&subsys->err_ready,
+					  msecs_to_jiffies(10000));
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
 static void subsystem_shutdown(struct subsys_device *dev, void *data)
 {
 	const char *name = dev->desc->name;
@@ -436,10 +454,17 @@
 static void subsystem_powerup(struct subsys_device *dev, void *data)
 {
 	const char *name = dev->desc->name;
+	int ret;
 
 	pr_info("[%p]: Powering up %s\n", current, name);
+	init_completion(&dev->err_ready);
 	if (dev->desc->powerup(dev->desc) < 0)
-		panic("[%p]: Failed to powerup %s!", current, name);
+		panic("[%p]: Powerup error: %s!", current, name);
+
+	ret = wait_for_err_ready(dev);
+	if (ret)
+		panic("[%p]: Timed out waiting for error ready: %s!",
+			current, name);
 	subsys_set_state(dev, SUBSYS_ONLINE);
 }
 
@@ -465,8 +490,18 @@
 {
 	int ret;
 
+	init_completion(&subsys->err_ready);
 	ret = subsys->desc->start(subsys->desc);
-	if (!ret)
+	if (ret)
+		return ret;
+
+	ret = wait_for_err_ready(subsys);
+	if (ret)
+		/* pil-boot succeeded but we need to shutdown
+		 * the device because error ready timed out.
+		 */
+		subsys->desc->stop(subsys->desc);
+	else
 		subsys_set_state(subsys, SUBSYS_ONLINE);
 
 	return ret;
@@ -895,6 +930,14 @@
 	ida_simple_remove(&subsys_ida, subsys->id);
 	kfree(subsys);
 }
+static irqreturn_t subsys_err_ready_intr_handler(int irq, void *subsys)
+{
+	struct subsys_device *subsys_dev = subsys;
+	pr_info("Error ready interrupt occured for %s\n",
+		 subsys_dev->desc->name);
+	complete(&subsys_dev->err_ready);
+	return IRQ_HANDLED;
+}
 
 static int subsys_misc_device_add(struct subsys_device *subsys_dev)
 {
@@ -971,8 +1014,24 @@
 		goto err_register;
 	}
 
+	if (subsys->desc->err_ready_irq) {
+		ret = devm_request_irq(&subsys->dev,
+					subsys->desc->err_ready_irq,
+					subsys_err_ready_intr_handler,
+					IRQF_TRIGGER_RISING,
+					"error_ready_interrupt", subsys);
+		if (ret < 0) {
+			dev_err(&subsys->dev,
+				"[%s]: Unable to register err ready handler\n",
+				subsys->desc->name);
+			goto err_misc_device;
+		}
+	}
+
 	return subsys;
 
+err_misc_device:
+	subsys_misc_device_remove(subsys);
 err_register:
 	subsys_debugfs_remove(subsys);
 err_debugfs:
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 8df41e2..07b6f6c 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -280,11 +280,11 @@
 	return (void __iomem *) (offset + addr);
 }
 
-void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size,
+void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size,
 	unsigned int mtype, void *caller)
 {
-	unsigned long last_addr;
- 	unsigned long offset = phys_addr & ~PAGE_MASK;
+	phys_addr_t last_addr;
+	phys_addr_t offset = phys_addr & ~PAGE_MASK;
  	unsigned long pfn = __phys_to_pfn(phys_addr);
 
  	/*
@@ -316,12 +316,12 @@
 }
 EXPORT_SYMBOL(__arm_ioremap_pfn);
 
-void __iomem * (*arch_ioremap_caller)(unsigned long, size_t,
+void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t,
 				      unsigned int, void *) =
 	__arm_ioremap_caller;
 
 void __iomem *
-__arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
+__arm_ioremap(phys_addr_t phys_addr, size_t size, unsigned int mtype)
 {
 	return arch_ioremap_caller(phys_addr, size, mtype,
 		__builtin_return_address(0));
@@ -336,7 +336,7 @@
  * CONFIG_GENERIC_ALLOCATOR for allocating external memory.
  */
 void __iomem *
-__arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached)
+__arm_ioremap_exec(phys_addr_t phys_addr, size_t size, bool cached)
 {
 	unsigned int mtype;
 
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 06262c5..ce8cb19 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -11,10 +11,49 @@
 #include <linux/random.h>
 #include <asm/cachetype.h>
 
+static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
+					      unsigned long pgoff)
+{
+	unsigned long base = addr & ~(SHMLBA-1);
+	unsigned long off = (pgoff << PAGE_SHIFT) & (SHMLBA-1);
+
+	if (base + off <= addr)
+		return base + off;
+
+	return base - off;
+}
+
 #define COLOUR_ALIGN(addr,pgoff)		\
 	((((addr)+SHMLBA-1)&~(SHMLBA-1)) +	\
 	 (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
 
+/* gap between mmap and stack */
+#define MIN_GAP (128*1024*1024UL)
+#define MAX_GAP ((TASK_SIZE)/6*5)
+
+static int mmap_is_legacy(void)
+{
+	if (current->personality & ADDR_COMPAT_LAYOUT)
+		return 1;
+
+	if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
+		return 1;
+
+	return sysctl_legacy_va_layout;
+}
+
+static unsigned long mmap_base(unsigned long rnd)
+{
+	unsigned long gap = rlimit(RLIMIT_STACK);
+
+	if (gap < MIN_GAP)
+		gap = MIN_GAP;
+	else if (gap > MAX_GAP)
+		gap = MAX_GAP;
+
+	return PAGE_ALIGN(TASK_SIZE - gap - rnd);
+}
+
 /*
  * We need to ensure that shared mappings are correctly aligned to
  * avoid aliasing issues with VIPT caches.  We need to ensure that
@@ -68,13 +107,9 @@
 	if (len > mm->cached_hole_size) {
 	        start_addr = addr = mm->free_area_cache;
 	} else {
-		start_addr = addr = TASK_UNMAPPED_BASE;
+	        start_addr = addr = mm->mmap_base;
 	        mm->cached_hole_size = 0;
 	}
-	/* 8 bits of randomness in 20 address space bits */
-	if ((current->flags & PF_RANDOMIZE) &&
-	    !(current->personality & ADDR_NO_RANDOMIZE))
-		addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT;
 
 full_search:
 	if (do_align)
@@ -111,6 +146,134 @@
 	}
 }
 
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+			const unsigned long len, const unsigned long pgoff,
+			const unsigned long flags)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long addr = addr0;
+	int do_align = 0;
+	int aliasing = cache_is_vipt_aliasing();
+
+	/*
+	 * We only need to do colour alignment if either the I or D
+	 * caches alias.
+	 */
+	if (aliasing)
+		do_align = filp || (flags & MAP_SHARED);
+
+	/* requested length too big for entire address space */
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	if (flags & MAP_FIXED) {
+		if (aliasing && flags & MAP_SHARED &&
+		    (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
+			return -EINVAL;
+		return addr;
+	}
+
+	/* requesting a specific address */
+	if (addr) {
+		if (do_align)
+			addr = COLOUR_ALIGN(addr, pgoff);
+		else
+			addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+				(!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+	/* check if free_area_cache is useful for us */
+	if (len <= mm->cached_hole_size) {
+		mm->cached_hole_size = 0;
+		mm->free_area_cache = mm->mmap_base;
+	}
+
+	/* either no address requested or can't fit in requested address hole */
+	addr = mm->free_area_cache;
+	if (do_align) {
+		unsigned long base = COLOUR_ALIGN_DOWN(addr - len, pgoff);
+		addr = base + len;
+	}
+
+	/* make sure it can fit in the remaining address space */
+	if (addr > len) {
+		vma = find_vma(mm, addr-len);
+		if (!vma || addr <= vma->vm_start)
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr-len);
+	}
+
+	if (mm->mmap_base < len)
+		goto bottomup;
+
+	addr = mm->mmap_base - len;
+	if (do_align)
+		addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+
+	do {
+		/*
+		 * Lookup failure means no vma is above this address,
+		 * else if new region fits below vma->vm_start,
+		 * return with success:
+		 */
+		vma = find_vma(mm, addr);
+		if (!vma || addr+len <= vma->vm_start)
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr);
+
+		/* remember the largest hole we saw so far */
+		if (addr + mm->cached_hole_size < vma->vm_start)
+			mm->cached_hole_size = vma->vm_start - addr;
+
+		/* try just below the current vma->vm_start */
+		addr = vma->vm_start - len;
+		if (do_align)
+			addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+	} while (len < vma->vm_start);
+
+bottomup:
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	mm->cached_hole_size = ~0UL;
+	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+	/*
+	 * Restore the topdown base:
+	 */
+	mm->free_area_cache = mm->mmap_base;
+	mm->cached_hole_size = ~0UL;
+
+	return addr;
+}
+
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	unsigned long random_factor = 0UL;
+
+	/* 8 bits of randomness in 20 address space bits */
+	if ((current->flags & PF_RANDOMIZE) &&
+	    !(current->personality & ADDR_NO_RANDOMIZE))
+		random_factor = (get_random_int() % (1 << 8)) << PAGE_SHIFT;
+
+	if (mmap_is_legacy()) {
+		mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
+		mm->get_unmapped_area = arch_get_unmapped_area;
+		mm->unmap_area = arch_unmap_area;
+	} else {
+		mm->mmap_base = mmap_base(random_factor);
+		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+		mm->unmap_area = arch_unmap_area_topdown;
+	}
+}
 
 /*
  * You really shouldn't be using read() or write() on /dev/mem.  This
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 9e36e1e..04c3300 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -481,6 +481,7 @@
 	driver->feature_mask->ctrl_pkt_data_len = 4 + FEATURE_MASK_LEN_BYTES;
 	driver->feature_mask->feature_mask_len = FEATURE_MASK_LEN_BYTES;
 	memcpy(buf, driver->feature_mask, header_size);
+	feature_byte |= F_DIAG_INT_FEATURE_MASK;
 	feature_byte |= APPS_RESPOND_LOG_ON_DEMAND;
 	memcpy(buf+header_size, &feature_byte, FEATURE_MASK_LEN_BYTES);
 
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 2ebae71..7022a6f 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -2071,6 +2071,7 @@
 	diagchar_cleanup();
 	diagfwd_exit();
 	diagfwd_cntl_exit();
+	diag_dci_exit();
 	diag_masks_exit();
 	diag_sdio_fn(EXIT);
 	diagfwd_bridge_fn(EXIT);
@@ -2085,6 +2086,7 @@
 	diagmem_exit(driver, POOL_TYPE_ALL);
 	diagfwd_exit();
 	diagfwd_cntl_exit();
+	diag_dci_exit();
 	diag_masks_exit();
 	diag_sdio_fn(EXIT);
 	diagfwd_bridge_fn(EXIT);
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 7cd1866..9c2c691 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -30,6 +30,9 @@
 /* Send Diag F3 mask */
 #define DIAG_CTRL_MSG_F3_MASK_V2	11
 
+/* Denotes that we support sending/receiving the feature mask */
+#define F_DIAG_INT_FEATURE_MASK	0x01
+
 struct cmd_code_range {
 	uint16_t cmd_code_lo;
 	uint16_t cmd_code_hi;
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index c758b3a..99ace44 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -306,7 +306,7 @@
 config CRYPTO_DEV_QCE
 	tristate "Qualcomm Crypto Engine (QCE) module"
 	select  CRYPTO_DEV_QCE40 if ARCH_MSM8960 || ARCH_MSM9615
-	select  CRYPTO_DEV_QCE50 if ARCH_MSM8974 || ARCH_MSM9625
+	select  CRYPTO_DEV_QCE50 if ARCH_MSM8974 || ARCH_MSM9625 || ARCH_MSM8226
 	default n
 	help
           This driver supports Qualcomm Crypto Engine in MSM7x30, MSM8660
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 245272b..c8d5101 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -62,6 +62,7 @@
 	dma_addr_t coh_pmem;	    /* Allocated coherent physical memory */
 	int memsize;				/* Memory allocated */
 	int is_shared;				/* CE HW is shared */
+	bool support_cmd_dscr;
 
 	void __iomem *iobase;	    /* Virtual io base of CE HW  */
 	unsigned int phy_iobase;    /* Physical io base of CE HW    */
@@ -84,6 +85,7 @@
 	int dir;
 	void *areq;
 	enum qce_cipher_mode_enum mode;
+	struct qce_ce_cfg_reg_setting reg;
 	struct ce_sps_data ce_sps;
 };
 
@@ -494,25 +496,17 @@
 		for (i = 0; i < noncelen32; i++, pce++)
 			pce->data = nonce32[i];
 
-		/* TBD  NEW FEATURE partial AES CCM  pkt support set last bit */
-		auth_cfg |= ((1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST));
+		if (creq->authklen ==  AES128_KEY_SIZE)
+			auth_cfg = pce_dev->reg.auth_cfg_aes_ccm_128;
+		else {
+			if (creq->authklen ==  AES256_KEY_SIZE)
+				auth_cfg = pce_dev->reg.auth_cfg_aes_ccm_256;
+		}
 		if (creq->dir == QCE_ENCRYPT)
 			auth_cfg |= (CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
 		else
 			auth_cfg |= (CRYPTO_AUTH_POS_AFTER << CRYPTO_AUTH_POS);
 		auth_cfg |= ((creq->authsize - 1) << CRYPTO_AUTH_SIZE);
-		auth_cfg |= (CRYPTO_AUTH_MODE_CCM << CRYPTO_AUTH_MODE);
-		if (creq->authklen ==  AES128_KEY_SIZE)
-			auth_cfg |= (CRYPTO_AUTH_KEY_SZ_AES128 <<
-						CRYPTO_AUTH_KEY_SIZE);
-		else {
-			if (creq->authklen ==  AES256_KEY_SIZE)
-				auth_cfg |= (CRYPTO_AUTH_KEY_SZ_AES256 <<
-							CRYPTO_AUTH_KEY_SIZE);
-		}
-		auth_cfg |= (CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG);
-		auth_cfg |= ((MAX_NONCE/sizeof(uint32_t)) <<
-						CRYPTO_AUTH_NONCE_NUM_WORDS);
 
 		if (use_hw_key == true)	{
 			auth_cfg |= (1 << CRYPTO_USE_HW_KEY_AUTH);
@@ -542,21 +536,37 @@
 	}
 	switch (creq->mode) {
 	case QCE_MODE_ECB:
-		encr_cfg |= (CRYPTO_ENCR_MODE_ECB << CRYPTO_ENCR_MODE);
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ecb_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ecb_256;
 		break;
 	case QCE_MODE_CBC:
-		encr_cfg |= (CRYPTO_ENCR_MODE_CBC << CRYPTO_ENCR_MODE);
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_cbc_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_cbc_256;
 		break;
 	case QCE_MODE_XTS:
-		encr_cfg |= (CRYPTO_ENCR_MODE_XTS << CRYPTO_ENCR_MODE);
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_xts_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_xts_256;
 		break;
 	case QCE_MODE_CCM:
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ccm_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ccm_256;
 		encr_cfg |= (CRYPTO_ENCR_MODE_CCM << CRYPTO_ENCR_MODE) |
 				(CRYPTO_LAST_CCM_XFR << CRYPTO_LAST_CCM);
 		break;
 	case QCE_MODE_CTR:
 	default:
-		encr_cfg |= (CRYPTO_ENCR_MODE_CTR << CRYPTO_ENCR_MODE);
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ctr_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ctr_256;
 		break;
 	}
 	pce_dev->mode = creq->mode;
@@ -600,13 +610,15 @@
 			uint32_t xtsklen =
 					creq->encklen/(2 * sizeof(uint32_t));
 
-			_byte_stream_to_net_words(xtskey32, (creq->enckey +
-					creq->encklen/2), creq->encklen/2);
-			/* write xts encr key */
-			pce = cmdlistinfo->encr_xts_key;
-			for (i = 0; i < xtsklen; i++, pce++)
-				pce->data = xtskey32[i];
-
+			if ((use_hw_key == false) && (use_pipe_key == false)) {
+				_byte_stream_to_net_words(xtskey32,
+					(creq->enckey + creq->encklen/2),
+							creq->encklen/2);
+				/* write xts encr key */
+				pce = cmdlistinfo->encr_xts_key;
+				for (i = 0; i < xtsklen; i++, pce++)
+					pce->data = xtskey32[i];
+			}
 			/* write xts du size */
 			pce = cmdlistinfo->encr_xts_du_size;
 			if (use_pipe_key == true)
@@ -642,26 +654,13 @@
 		if (creq->op == QCE_REQ_ABLK_CIPHER_NO_KEY) {
 				encr_cfg |= (CRYPTO_ENCR_KEY_SZ_AES128 <<
 						CRYPTO_ENCR_KEY_SZ);
-			encr_cfg |= CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG;
 		} else {
 			if (use_hw_key == false) {
 				/* write encr key */
 				pce = cmdlistinfo->encr_key;
 				for (i = 0; i < enck_size_in_word; i++, pce++)
 					pce->data = enckey32[i];
-				switch (key_size) {
-				case AES128_KEY_SIZE:
-					encr_cfg |= (CRYPTO_ENCR_KEY_SZ_AES128
-							 << CRYPTO_ENCR_KEY_SZ);
-					break;
-				case AES256_KEY_SIZE:
-				default:
-					encr_cfg |= (CRYPTO_ENCR_KEY_SZ_AES256
-							 << CRYPTO_ENCR_KEY_SZ);
-				break;
-				} /* end of switch (creq->encklen) */
 			}
-			encr_cfg |= CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG;
 		} /* else of if (creq->op == QCE_REQ_ABLK_CIPHER_NO_KEY) */
 		break;
 	} /* end of switch (creq->mode)  */
@@ -706,10 +705,499 @@
 	return 0;
 };
 
+static int _ce_setup_hash_direct(struct qce_device *pce_dev,
+				struct qce_sha_req *sreq)
+{
+	uint32_t auth32[SHA256_DIGEST_SIZE / sizeof(uint32_t)];
+	uint32_t diglen;
+	bool use_hw_key = false;
+	int i;
+	uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	bool sha1 = false;
+	uint32_t auth_cfg = 0;
+
+	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/*
+	 * Ensure previous instructions (setting the CONFIG register)
+	 * was completed before issuing starting to set other config register
+	 * This is to ensure the configurations are done in correct endian-ness
+	 * as set in the CONFIG registers
+	 */
+	mb();
+
+	if (sreq->alg == QCE_HASH_AES_CMAC) {
+		/* write seg_cfg */
+		writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_SEG_CFG_REG);
+		/* write seg_cfg */
+		writel_relaxed(0, pce_dev->iobase + CRYPTO_ENCR_SEG_CFG_REG);
+		/* write seg_cfg */
+		writel_relaxed(0, pce_dev->iobase + CRYPTO_ENCR_SEG_SIZE_REG);
+
+		/* Clear auth_ivn, auth_keyn registers  */
+		for (i = 0; i < 16; i++) {
+			writel_relaxed(0, (pce_dev->iobase +
+				(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t))));
+			writel_relaxed(0, (pce_dev->iobase +
+				(CRYPTO_AUTH_KEY0_REG + i*sizeof(uint32_t))));
+		}
+		/* write auth_bytecnt 0/1/2/3, start with 0 */
+		for (i = 0; i < 4; i++)
+			writel_relaxed(0, pce_dev->iobase +
+						CRYPTO_AUTH_BYTECNT0_REG +
+						i * sizeof(uint32_t));
+
+		if (sreq->authklen == AES128_KEY_SIZE)
+			auth_cfg = pce_dev->reg.auth_cfg_cmac_128;
+		else
+			auth_cfg = pce_dev->reg.auth_cfg_cmac_256;
+	}
+
+	if ((sreq->alg == QCE_HASH_SHA1_HMAC) ||
+			(sreq->alg == QCE_HASH_SHA256_HMAC) ||
+			(sreq->alg ==  QCE_HASH_AES_CMAC)) {
+		uint32_t authk_size_in_word = sreq->authklen/sizeof(uint32_t);
+
+		_byte_stream_to_net_words(mackey32, sreq->authkey,
+						sreq->authklen);
+
+		/* check for null key. If null, use hw key*/
+		for (i = 0; i < authk_size_in_word; i++) {
+			if (mackey32[i] != 0)
+				break;
+		}
+
+		if (i == authk_size_in_word)
+			use_hw_key = true;
+		else
+			/* Clear auth_ivn, auth_keyn registers  */
+			for (i = 0; i < authk_size_in_word; i++)
+				writel_relaxed(mackey32[i], (pce_dev->iobase +
+					(CRYPTO_AUTH_KEY0_REG +
+							i*sizeof(uint32_t))));
+	}
+
+	if (sreq->alg ==  QCE_HASH_AES_CMAC)
+		goto go_proc;
+
+	/* if not the last, the size has to be on the block boundary */
+	if (sreq->last_blk == 0 && (sreq->size % SHA256_BLOCK_SIZE))
+		return -EIO;
+
+	switch (sreq->alg) {
+	case QCE_HASH_SHA1:
+		auth_cfg = pce_dev->reg.auth_cfg_sha1;
+		diglen = SHA1_DIGEST_SIZE;
+		sha1 = true;
+		break;
+	case QCE_HASH_SHA1_HMAC:
+		auth_cfg = pce_dev->reg.auth_cfg_hmac_sha1;
+		diglen = SHA1_DIGEST_SIZE;
+		sha1 = true;
+		break;
+	case QCE_HASH_SHA256:
+		auth_cfg = pce_dev->reg.auth_cfg_sha256;
+		diglen = SHA256_DIGEST_SIZE;
+		break;
+	case QCE_HASH_SHA256_HMAC:
+		auth_cfg = pce_dev->reg.auth_cfg_hmac_sha256;
+		diglen = SHA256_DIGEST_SIZE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* write 20/32 bytes, 5/8 words into auth_iv for SHA1/SHA256 */
+	if (sreq->first_blk) {
+		if (sha1) {
+			for (i = 0; i < 5; i++)
+				auth32[i] = _std_init_vector_sha1[i];
+		} else {
+			for (i = 0; i < 8; i++)
+				auth32[i] = _std_init_vector_sha256[i];
+		}
+	} else {
+		_byte_stream_to_net_words(auth32, sreq->digest, diglen);
+	}
+
+	/* Set auth_ivn, auth_keyn registers  */
+	for (i = 0; i < 5; i++)
+		writel_relaxed(auth32[i], (pce_dev->iobase +
+			(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t))));
+
+	if ((sreq->alg == QCE_HASH_SHA256) ||
+			(sreq->alg == QCE_HASH_SHA256_HMAC)) {
+		for (i = 5; i < 8; i++)
+			writel_relaxed(auth32[i], (pce_dev->iobase +
+				(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t))));
+	}
+
+
+	/* write auth_bytecnt 0/1/2/3, start with 0 */
+	for (i = 0; i < 2; i++)
+		writel_relaxed(sreq->auth_data[i], pce_dev->iobase +
+					CRYPTO_AUTH_BYTECNT0_REG +
+						i * sizeof(uint32_t));
+
+	/* Set/reset  last bit in CFG register  */
+	if (sreq->last_blk)
+		auth_cfg |= 1 << CRYPTO_LAST;
+	else
+		auth_cfg &= ~(1 << CRYPTO_LAST);
+	if (sreq->first_blk)
+		auth_cfg |= 1 << CRYPTO_FIRST;
+	else
+		auth_cfg &= ~(1 << CRYPTO_FIRST);
+go_proc:
+	 /* write seg_cfg */
+	writel_relaxed(auth_cfg, pce_dev->iobase + CRYPTO_AUTH_SEG_CFG_REG);
+	/* write auth seg_size   */
+	writel_relaxed(sreq->size, pce_dev->iobase + CRYPTO_AUTH_SEG_SIZE_REG);
+
+	/* write auth_seg_start   */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_SEG_START_REG);
+
+	/* reset encr seg_cfg   */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_ENCR_SEG_CFG_REG);
+
+	/* write seg_size   */
+	writel_relaxed(sreq->size, pce_dev->iobase + CRYPTO_SEG_SIZE_REG);
+
+	writel_relaxed(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/* issue go to crypto   */
+	if (use_hw_key == false)
+		writel_relaxed(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+				pce_dev->iobase + CRYPTO_GOPROC_REG);
+	else
+		writel_relaxed(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+				pce_dev->iobase + CRYPTO_GOPROC_QC_KEY_REG);
+	/*
+	 * Ensure previous instructions (setting the GO register)
+	 * was completed before issuing a DMA transfer request
+	 */
+	mb();
+	return 0;
+}
+
+static int _ce_setup_cipher_direct(struct qce_device *pce_dev,
+		struct qce_req *creq, uint32_t totallen_in, uint32_t coffset)
+{
+	uint32_t enckey32[(MAX_CIPHER_KEY_SIZE * 2)/sizeof(uint32_t)] = {
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	uint32_t enciv32[MAX_IV_LENGTH / sizeof(uint32_t)] = {
+			0, 0, 0, 0};
+	uint32_t enck_size_in_word = 0;
+	uint32_t key_size;
+	bool use_hw_key = false;
+	bool use_pipe_key = false;
+	uint32_t encr_cfg = 0;
+	uint32_t ivsize = creq->ivsize;
+	int i;
+
+	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/*
+	 * Ensure previous instructions (setting the CONFIG register)
+	 * was completed before issuing starting to set other config register
+	 * This is to ensure the configurations are done in correct endian-ness
+	 * as set in the CONFIG registers
+	 */
+	mb();
+
+	if (creq->mode == QCE_MODE_XTS)
+		key_size = creq->encklen/2;
+	else
+		key_size = creq->encklen;
+
+	_byte_stream_to_net_words(enckey32, creq->enckey, key_size);
+
+	/* check for null key. If null, use hw key*/
+	enck_size_in_word = key_size/sizeof(uint32_t);
+	for (i = 0; i < enck_size_in_word; i++) {
+		if (enckey32[i] != 0)
+			break;
+	}
+	if (i == enck_size_in_word)
+		use_hw_key = true;
+
+	if (use_hw_key == false) {
+		for (i = 0; i < enck_size_in_word; i++) {
+			if (enckey32[i] != 0xFFFFFFFF)
+				break;
+		}
+		if (i == enck_size_in_word)
+			use_pipe_key = true;
+	}
+
+	if ((creq->op == QCE_REQ_AEAD) && (creq->mode == QCE_MODE_CCM)) {
+		uint32_t authklen32 = creq->encklen/sizeof(uint32_t);
+		uint32_t noncelen32 = MAX_NONCE/sizeof(uint32_t);
+		uint32_t nonce32[MAX_NONCE/sizeof(uint32_t)] = {0, 0, 0, 0};
+		uint32_t auth_cfg = 0;
+
+		/* Clear auth_ivn, auth_keyn registers  */
+		for (i = 0; i < 16; i++) {
+			writel_relaxed(0, (pce_dev->iobase +
+				(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t))));
+			writel_relaxed(0, (pce_dev->iobase +
+				(CRYPTO_AUTH_KEY0_REG + i*sizeof(uint32_t))));
+		}
+		/* write auth_bytecnt 0/1/2/3, start with 0 */
+		for (i = 0; i < 4; i++)
+			writel_relaxed(0, pce_dev->iobase +
+						CRYPTO_AUTH_BYTECNT0_REG +
+						i * sizeof(uint32_t));
+		/* write nonce */
+		_byte_stream_to_net_words(nonce32, creq->nonce, MAX_NONCE);
+		for (i = 0; i < noncelen32; i++)
+			writel_relaxed(nonce32[i], pce_dev->iobase +
+				CRYPTO_AUTH_INFO_NONCE0_REG +
+					(i*sizeof(uint32_t)));
+
+		if (creq->authklen ==  AES128_KEY_SIZE)
+			auth_cfg = pce_dev->reg.auth_cfg_aes_ccm_128;
+		else {
+			if (creq->authklen ==  AES256_KEY_SIZE)
+				auth_cfg = pce_dev->reg.auth_cfg_aes_ccm_256;
+		}
+		if (creq->dir == QCE_ENCRYPT)
+			auth_cfg |= (CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+		else
+			auth_cfg |= (CRYPTO_AUTH_POS_AFTER << CRYPTO_AUTH_POS);
+		auth_cfg |= ((creq->authsize - 1) << CRYPTO_AUTH_SIZE);
+
+		if (use_hw_key == true)	{
+			auth_cfg |= (1 << CRYPTO_USE_HW_KEY_AUTH);
+		} else {
+			auth_cfg &= ~(1 << CRYPTO_USE_HW_KEY_AUTH);
+			/* write auth key */
+			for (i = 0; i < authklen32; i++)
+				writel_relaxed(enckey32[i], pce_dev->iobase +
+				CRYPTO_AUTH_KEY0_REG + (i*sizeof(uint32_t)));
+		}
+		writel_relaxed(auth_cfg, pce_dev->iobase +
+						CRYPTO_AUTH_SEG_CFG_REG);
+		if (creq->dir == QCE_ENCRYPT)
+			writel_relaxed(totallen_in, pce_dev->iobase +
+						CRYPTO_AUTH_SEG_SIZE_REG);
+		else
+			writel_relaxed((totallen_in - creq->authsize),
+				pce_dev->iobase + CRYPTO_AUTH_SEG_SIZE_REG);
+		writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_SEG_START_REG);
+	} else {
+		if (creq->op != QCE_REQ_AEAD)
+			writel_relaxed(0, pce_dev->iobase +
+						CRYPTO_AUTH_SEG_CFG_REG);
+	}
+	/*
+	 * Ensure previous instructions (write to all AUTH registers)
+	 * was completed before accessing a register that is not in
+	 * in the same 1K range.
+	 */
+	mb();
+	switch (creq->mode) {
+	case QCE_MODE_ECB:
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ecb_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ecb_256;
+		break;
+	case QCE_MODE_CBC:
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_cbc_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_cbc_256;
+		break;
+	case QCE_MODE_XTS:
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_xts_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_xts_256;
+		break;
+	case QCE_MODE_CCM:
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ccm_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ccm_256;
+		break;
+	case QCE_MODE_CTR:
+	default:
+		if (key_size == AES128_KEY_SIZE)
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ctr_128;
+		else
+			encr_cfg = pce_dev->reg.encr_cfg_aes_ctr_256;
+		break;
+	}
+	pce_dev->mode = creq->mode;
+
+	switch (creq->alg) {
+	case CIPHER_ALG_DES:
+		if (creq->mode !=  QCE_MODE_ECB) {
+			encr_cfg = pce_dev->reg.encr_cfg_des_cbc;
+			_byte_stream_to_net_words(enciv32, creq->iv, ivsize);
+			writel_relaxed(enciv32[0], pce_dev->iobase +
+						CRYPTO_CNTR0_IV0_REG);
+			writel_relaxed(enciv32[1], pce_dev->iobase +
+						CRYPTO_CNTR1_IV1_REG);
+		} else {
+			encr_cfg = pce_dev->reg.encr_cfg_des_ecb;
+		}
+		if (use_hw_key == false) {
+			writel_relaxed(enckey32[0], pce_dev->iobase +
+							CRYPTO_ENCR_KEY0_REG);
+			writel_relaxed(enckey32[1], pce_dev->iobase +
+							CRYPTO_ENCR_KEY1_REG);
+		}
+		break;
+	case CIPHER_ALG_3DES:
+		if (creq->mode !=  QCE_MODE_ECB) {
+			_byte_stream_to_net_words(enciv32, creq->iv, ivsize);
+			writel_relaxed(enciv32[0], pce_dev->iobase +
+						CRYPTO_CNTR0_IV0_REG);
+			writel_relaxed(enciv32[1], pce_dev->iobase +
+						CRYPTO_CNTR1_IV1_REG);
+			encr_cfg = pce_dev->reg.encr_cfg_3des_cbc;
+		} else {
+			encr_cfg = pce_dev->reg.encr_cfg_3des_ecb;
+		}
+		if (use_hw_key == false) {
+			/* write encr key */
+			for (i = 0; i < 6; i++)
+				writel_relaxed(enckey32[0], (pce_dev->iobase +
+				(CRYPTO_ENCR_KEY0_REG + i * sizeof(uint32_t))));
+		}
+		break;
+	case CIPHER_ALG_AES:
+	default:
+		if (creq->mode ==  QCE_MODE_XTS) {
+			uint32_t xtskey32[MAX_CIPHER_KEY_SIZE/sizeof(uint32_t)]
+					= {0, 0, 0, 0, 0, 0, 0, 0};
+			uint32_t xtsklen =
+					creq->encklen/(2 * sizeof(uint32_t));
+
+			if ((use_hw_key == false) && (use_pipe_key == false)) {
+				_byte_stream_to_net_words(xtskey32,
+					(creq->enckey + creq->encklen/2),
+							creq->encklen/2);
+				/* write xts encr key */
+				for (i = 0; i < xtsklen; i++)
+					writel_relaxed(xtskey32[i],
+						pce_dev->iobase +
+						CRYPTO_ENCR_XTS_KEY0_REG +
+						(i * sizeof(uint32_t)));
+			}
+			/* write xts du size */
+			if (use_pipe_key == true)
+				writel_relaxed(min((uint32_t)QCE_SECTOR_SIZE,
+						creq->cryptlen),
+						pce_dev->iobase +
+						CRYPTO_ENCR_XTS_DU_SIZE_REG);
+			else
+				writel_relaxed(creq->cryptlen ,
+						pce_dev->iobase +
+						CRYPTO_ENCR_XTS_DU_SIZE_REG);
+		}
+		if (creq->mode !=  QCE_MODE_ECB) {
+			if (creq->mode ==  QCE_MODE_XTS)
+				_byte_stream_swap_to_net_words(enciv32,
+							creq->iv, ivsize);
+			else
+				_byte_stream_to_net_words(enciv32, creq->iv,
+								ivsize);
+
+			/* write encr cntr iv */
+			for (i = 0; i <= 3; i++)
+				writel_relaxed(enciv32[i], pce_dev->iobase +
+							CRYPTO_CNTR0_IV0_REG +
+							(i * sizeof(uint32_t)));
+
+			if (creq->mode == QCE_MODE_CCM) {
+				/* write cntr iv for ccm */
+				for (i = 0; i <= 3; i++)
+					writel_relaxed(enciv32[i],
+						pce_dev->iobase +
+						CRYPTO_ENCR_CCM_INT_CNTR0_REG +
+							(i * sizeof(uint32_t)));
+				/* update cntr_iv[3] by one */
+				writel_relaxed((enciv32[3] + 1),
+							pce_dev->iobase +
+							CRYPTO_CNTR0_IV0_REG +
+							(3 * sizeof(uint32_t)));
+			}
+		}
+
+		if (creq->op == QCE_REQ_ABLK_CIPHER_NO_KEY) {
+				encr_cfg |= (CRYPTO_ENCR_KEY_SZ_AES128 <<
+						CRYPTO_ENCR_KEY_SZ);
+		} else {
+			if ((use_hw_key == false) && (use_pipe_key == false)) {
+				for (i = 0; i < enck_size_in_word; i++)
+					writel_relaxed(enckey32[i],
+						pce_dev->iobase +
+							CRYPTO_ENCR_KEY0_REG +
+							(i * sizeof(uint32_t)));
+			}
+		} /* else of if (creq->op == QCE_REQ_ABLK_CIPHER_NO_KEY) */
+		break;
+	} /* end of switch (creq->mode)  */
+
+	if (use_pipe_key)
+		encr_cfg |= (CRYPTO_USE_PIPE_KEY_ENCR_ENABLED
+					<< CRYPTO_USE_PIPE_KEY_ENCR);
+
+	/* write encr seg cfg */
+	encr_cfg |= ((creq->dir == QCE_ENCRYPT) ? 1 : 0) << CRYPTO_ENCODE;
+	if (use_hw_key == true)
+		encr_cfg |= (CRYPTO_USE_HW_KEY << CRYPTO_USE_HW_KEY_ENCR);
+	else
+		encr_cfg &= ~(CRYPTO_USE_HW_KEY << CRYPTO_USE_HW_KEY_ENCR);
+	/* write encr seg cfg */
+	writel_relaxed(encr_cfg, pce_dev->iobase + CRYPTO_ENCR_SEG_CFG_REG);
+
+	/* write encr seg size */
+	if ((creq->mode == QCE_MODE_CCM) && (creq->dir == QCE_DECRYPT))
+		writel_relaxed((creq->cryptlen + creq->authsize),
+				pce_dev->iobase + CRYPTO_ENCR_SEG_SIZE_REG);
+	else
+		writel_relaxed(creq->cryptlen,
+				pce_dev->iobase + CRYPTO_ENCR_SEG_SIZE_REG);
+
+	/* write encr seg start */
+	writel_relaxed((coffset & 0xffff),
+			pce_dev->iobase + CRYPTO_ENCR_SEG_START_REG);
+	/* write encr seg start */
+	writel_relaxed(0xffffffff,
+			pce_dev->iobase + CRYPTO_CNTR_MASK_REG);
+
+	/* write seg size  */
+	writel_relaxed(totallen_in, pce_dev->iobase + CRYPTO_SEG_SIZE_REG);
+
+	writel_relaxed(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/* issue go to crypto   */
+	if (use_hw_key == false)
+		writel_relaxed(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+				pce_dev->iobase + CRYPTO_GOPROC_REG);
+	else
+		writel_relaxed(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+				pce_dev->iobase + CRYPTO_GOPROC_QC_KEY_REG);
+	/*
+	 * Ensure previous instructions (setting the GO register)
+	 * was completed before issuing a DMA transfer request
+	 */
+	mb();
+	return 0;
+};
+
 static int _qce_unlock_other_pipes(struct qce_device *pce_dev)
 {
 	int rc = 0;
 
+	if (pce_dev->support_cmd_dscr == false)
+		return rc;
+
 	pce_dev->ce_sps.consumer.event.callback = NULL;
 	rc = sps_transfer_one(pce_dev->ce_sps.consumer.pipe,
 	GET_PHYS_ADDR(pce_dev->ce_sps.cmdlistptr.unlock_all_pipes.cmdlist),
@@ -1216,7 +1704,14 @@
 	bam.summing_threshold = 64;
 	/* SPS driver wll handle the crypto BAM IRQ */
 	bam.irq = (u32)pce_dev->ce_sps.bam_irq;
-	bam.manage = SPS_BAM_MGR_LOCAL;
+	/*
+	 * Set flag to indicate BAM global device control is managed
+	 * remotely.
+	 */
+	if (pce_dev->support_cmd_dscr == false)
+		bam.manage = SPS_BAM_MGR_DEVICE_REMOTE;
+	else
+		bam.manage = SPS_BAM_MGR_LOCAL;
 	bam.ee = 1;
 
 	pr_debug("bam physical base=0x%x\n", (u32)bam.phys_addr);
@@ -1411,20 +1906,11 @@
 	uint32_t key_reg = 0;
 	uint32_t xts_key_reg = 0;
 	uint32_t iv_reg = 0;
-	uint32_t crypto_cfg = 0;
-	uint32_t beats = (pdev->ce_sps.ce_burst_size >> 3) - 1;
-	uint32_t pipe_pair = pdev->ce_sps.pipe_pair_index;
 
 	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
 					pdev->ce_sps.ce_burst_size);
 	ce_vaddr = (struct sps_command_element *)(*pvaddr);
 	ce_vaddr_start = (uint32_t)(*pvaddr);
-	crypto_cfg = (beats << CRYPTO_REQ_SIZE) |
-			BIT(CRYPTO_MASK_DOUT_INTR) |
-			BIT(CRYPTO_MASK_DIN_INTR) |
-			BIT(CRYPTO_MASK_OP_DONE_INTR) |
-			(0 << CRYPTO_HIGH_SPD_EN_N) |
-			(pipe_pair << CRYPTO_PIPE_SET_SELECT);
 	/*
 	 * Designate chunks of the allocated memory to various
 	 * command list pointers related to AES cipher operations defined
@@ -1437,11 +1923,10 @@
 			cmdlistptr->cipher_aes_128_cbc_ctr.cmdlist =
 							(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_aes_128_cbc_ctr);
-
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_AES128 <<
-						CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_AES <<
-						CRYPTO_ENCR_ALG);
+			if (mode == QCE_MODE_CBC)
+				encr_cfg = pdev->reg.encr_cfg_aes_cbc_128;
+			else
+				encr_cfg = pdev->reg.encr_cfg_aes_ctr_128;
 			iv_reg = 4;
 			key_reg = 4;
 			xts_key_reg = 0;
@@ -1450,10 +1935,10 @@
 							(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_aes_256_cbc_ctr);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_AES256 <<
-							CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_AES <<
-							CRYPTO_ENCR_ALG);
+			if (mode == QCE_MODE_CBC)
+				encr_cfg = pdev->reg.encr_cfg_aes_cbc_256;
+			else
+				encr_cfg = pdev->reg.encr_cfg_aes_ctr_256;
 			iv_reg = 4;
 			key_reg = 8;
 			xts_key_reg = 0;
@@ -1465,12 +1950,7 @@
 							(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_aes_128_ecb);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_AES128 <<
-						CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_AES <<
-						CRYPTO_ENCR_ALG) |
-					(CRYPTO_ENCR_MODE_ECB <<
-						CRYPTO_ENCR_MODE);
+			encr_cfg = pdev->reg.encr_cfg_aes_ecb_128;
 			iv_reg = 0;
 			key_reg = 4;
 			xts_key_reg = 0;
@@ -1479,12 +1959,7 @@
 							(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_aes_256_ecb);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_AES256 <<
-							CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_AES <<
-							CRYPTO_ENCR_ALG) |
-					(CRYPTO_ENCR_MODE_ECB <<
-						CRYPTO_ENCR_MODE);
+			encr_cfg = pdev->reg.encr_cfg_aes_ecb_256;
 			iv_reg = 0;
 			key_reg = 8;
 			xts_key_reg = 0;
@@ -1496,12 +1971,7 @@
 							(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_aes_128_xts);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_AES128 <<
-						CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_AES <<
-						CRYPTO_ENCR_ALG) |
-					(CRYPTO_ENCR_MODE_XTS <<
-						CRYPTO_ENCR_MODE);
+			encr_cfg = pdev->reg.encr_cfg_aes_xts_128;
 			iv_reg = 4;
 			key_reg = 4;
 			xts_key_reg = 4;
@@ -1510,12 +1980,7 @@
 							(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_aes_256_xts);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_AES256 <<
-							CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_AES <<
-							CRYPTO_ENCR_ALG) |
-					(CRYPTO_ENCR_MODE_XTS <<
-						CRYPTO_ENCR_MODE);
+			encr_cfg = pdev->reg.encr_cfg_aes_xts_256;
 			iv_reg = 4;
 			key_reg = 8;
 			xts_key_reg = 8;
@@ -1528,8 +1993,8 @@
 	break;
 	}
 
-	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG, crypto_cfg,
-						&pcl_info->crypto_cfg);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_SEG_SIZE_REG, 0,
 						&pcl_info->seg_size);
@@ -1583,7 +2048,7 @@
 						0, &pcl_info->auth_seg_size);
 	}
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-				(crypto_cfg | CRYPTO_LITTLE_ENDIAN_MASK), NULL);
+			pdev->reg.crypto_cfg_le, NULL);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
 			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
@@ -1608,20 +2073,11 @@
 	uint32_t encr_cfg = 0;
 	uint32_t key_reg = 0;
 	uint32_t iv_reg = 0;
-	uint32_t crypto_cfg = 0;
-	uint32_t beats = (pdev->ce_sps.ce_burst_size >> 3) - 1;
-	uint32_t pipe_pair = pdev->ce_sps.pipe_pair_index;
 
 	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
 					pdev->ce_sps.ce_burst_size);
 	ce_vaddr = (struct sps_command_element *)(*pvaddr);
 	ce_vaddr_start = (uint32_t)(*pvaddr);
-	crypto_cfg = (beats << CRYPTO_REQ_SIZE) |
-			BIT(CRYPTO_MASK_DOUT_INTR) |
-			BIT(CRYPTO_MASK_DIN_INTR) |
-			BIT(CRYPTO_MASK_OP_DONE_INTR) |
-			(0 << CRYPTO_HIGH_SPD_EN_N) |
-			(pipe_pair << CRYPTO_PIPE_SET_SELECT);
 
 	/*
 	 * Designate chunks of the allocated memory to various
@@ -1635,12 +2091,8 @@
 						(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_des_cbc);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_DES <<
-						CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_DES <<
-						CRYPTO_ENCR_ALG) |
-					(CRYPTO_ENCR_MODE_CBC <<
-							CRYPTO_ENCR_MODE);
+
+			encr_cfg = pdev->reg.encr_cfg_des_cbc;
 			iv_reg = 2;
 			key_reg = 2;
 		} else {
@@ -1648,12 +2100,7 @@
 						(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_des_ecb);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_DES <<
-						CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_DES <<
-						CRYPTO_ENCR_ALG) |
-					(CRYPTO_ENCR_MODE_ECB <<
-						CRYPTO_ENCR_MODE);
+			encr_cfg = pdev->reg.encr_cfg_des_ecb;
 			iv_reg = 0;
 			key_reg = 2;
 		}
@@ -1664,12 +2111,7 @@
 						(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_3des_cbc);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_3DES <<
-						CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_DES <<
-						CRYPTO_ENCR_ALG) |
-					(CRYPTO_ENCR_MODE_CBC <<
-							CRYPTO_ENCR_MODE);
+			encr_cfg = pdev->reg.encr_cfg_3des_cbc;
 			iv_reg = 2;
 			key_reg = 6;
 		} else {
@@ -1677,12 +2119,7 @@
 						(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->cipher_3des_ecb);
 
-			encr_cfg = (CRYPTO_ENCR_KEY_SZ_3DES <<
-						CRYPTO_ENCR_KEY_SZ) |
-					(CRYPTO_ENCR_ALG_DES <<
-						CRYPTO_ENCR_ALG) |
-					(CRYPTO_ENCR_MODE_ECB <<
-						CRYPTO_ENCR_MODE);
+			encr_cfg = pdev->reg.encr_cfg_3des_ecb;
 			iv_reg = 0;
 			key_reg = 6;
 		}
@@ -1693,8 +2130,8 @@
 	break;
 	}
 
-	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG, crypto_cfg,
-						&pcl_info->crypto_cfg);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_SEG_SIZE_REG, 0,
 						&pcl_info->seg_size);
@@ -1727,8 +2164,7 @@
 						0, &pcl_info->auth_seg_size);
 	}
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-			(crypto_cfg | CRYPTO_LITTLE_ENDIAN_MASK),
-			NULL);
+			pdev->reg.crypto_cfg_le, NULL);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
 			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
@@ -1752,20 +2188,12 @@
 	uint32_t key_reg = 0;
 	uint32_t auth_cfg = 0;
 	uint32_t iv_reg = 0;
-	uint32_t crypto_cfg = 0;
-	uint32_t beats = (pdev->ce_sps.ce_burst_size >> 3) - 1;
-	uint32_t pipe_pair = pdev->ce_sps.pipe_pair_index;
 
 	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
 					pdev->ce_sps.ce_burst_size);
 	ce_vaddr_start = (uint32_t)(*pvaddr);
 	ce_vaddr = (struct sps_command_element *)(*pvaddr);
-	crypto_cfg = (beats << CRYPTO_REQ_SIZE) |
-			BIT(CRYPTO_MASK_DOUT_INTR) |
-			BIT(CRYPTO_MASK_DIN_INTR) |
-			BIT(CRYPTO_MASK_OP_DONE_INTR) |
-			(0 << CRYPTO_HIGH_SPD_EN_N) |
-			(pipe_pair << CRYPTO_PIPE_SET_SELECT);
+
 	/*
 	 * Designate chunks of the allocated memory to various
 	 * command list pointers related to authentication operations
@@ -1776,13 +2204,10 @@
 		cmdlistptr->auth_sha1.cmdlist = (uint32_t)ce_vaddr;
 		pcl_info = &(cmdlistptr->auth_sha1);
 
-		auth_cfg = (CRYPTO_AUTH_MODE_HASH << CRYPTO_AUTH_MODE)|
-				(CRYPTO_AUTH_SIZE_SHA1 << CRYPTO_AUTH_SIZE) |
-				(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
-				(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+		auth_cfg = pdev->reg.auth_cfg_sha1;
 		iv_reg = 5;
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					crypto_cfg, &pcl_info->crypto_cfg);
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
 							0, NULL);
 
@@ -1791,13 +2216,10 @@
 		cmdlistptr->auth_sha256.cmdlist = (uint32_t)ce_vaddr;
 		pcl_info = &(cmdlistptr->auth_sha256);
 
-		auth_cfg = (CRYPTO_AUTH_MODE_HASH << CRYPTO_AUTH_MODE)|
-				(CRYPTO_AUTH_SIZE_SHA256 << CRYPTO_AUTH_SIZE) |
-				(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
-				(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+		auth_cfg = pdev->reg.auth_cfg_sha256;
 		iv_reg = 8;
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					crypto_cfg, &pcl_info->crypto_cfg);
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
@@ -1808,14 +2230,11 @@
 		cmdlistptr->auth_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
 		pcl_info = &(cmdlistptr->auth_sha1_hmac);
 
-		auth_cfg = (CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
-				(CRYPTO_AUTH_SIZE_SHA1 << CRYPTO_AUTH_SIZE) |
-				(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
-				(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+		auth_cfg = pdev->reg.auth_cfg_hmac_sha1;
 		key_reg = 16;
 		iv_reg = 5;
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					crypto_cfg, &pcl_info->crypto_cfg);
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
 							0, NULL);
 	break;
@@ -1823,16 +2242,11 @@
 		cmdlistptr->aead_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
 		pcl_info = &(cmdlistptr->aead_sha1_hmac);
 
-		auth_cfg = (CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
-				(CRYPTO_AUTH_SIZE_SHA1 << CRYPTO_AUTH_SIZE) |
-				(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
-				(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS) |
-				(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST);
-
+		auth_cfg = pdev->reg.auth_cfg_aead_sha1_hmac;
 		key_reg = 16;
 		iv_reg = 5;
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					crypto_cfg, &pcl_info->crypto_cfg);
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
@@ -1843,15 +2257,12 @@
 		cmdlistptr->auth_sha256_hmac.cmdlist = (uint32_t)ce_vaddr;
 		pcl_info = &(cmdlistptr->auth_sha256_hmac);
 
-		auth_cfg = (CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
-				(CRYPTO_AUTH_SIZE_SHA256 << CRYPTO_AUTH_SIZE) |
-				(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
-				(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+		auth_cfg = pdev->reg.auth_cfg_hmac_sha256;
 		key_reg = 16;
 		iv_reg = 8;
 
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					crypto_cfg, &pcl_info->crypto_cfg);
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
@@ -1864,32 +2275,18 @@
 						(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->auth_aes_128_cmac);
 
-			auth_cfg = (1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
-				(CRYPTO_AUTH_MODE_CMAC << CRYPTO_AUTH_MODE)|
-				(CRYPTO_AUTH_SIZE_ENUM_16_BYTES <<
-							CRYPTO_AUTH_SIZE) |
-				(CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG) |
-				(CRYPTO_AUTH_KEY_SZ_AES128 <<
-							CRYPTO_AUTH_KEY_SIZE) |
-				(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+			auth_cfg = pdev->reg.auth_cfg_cmac_128;
 			key_reg = 4;
 		} else {
 			cmdlistptr->auth_aes_256_cmac.cmdlist =
 							(uint32_t)ce_vaddr;
 			pcl_info = &(cmdlistptr->auth_aes_256_cmac);
 
-			auth_cfg = (1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST)|
-				(CRYPTO_AUTH_MODE_CMAC << CRYPTO_AUTH_MODE)|
-				(CRYPTO_AUTH_SIZE_ENUM_16_BYTES <<
-							CRYPTO_AUTH_SIZE) |
-				(CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG) |
-				(CRYPTO_AUTH_KEY_SZ_AES256 <<
-							CRYPTO_AUTH_KEY_SIZE) |
-				(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+			auth_cfg = pdev->reg.auth_cfg_cmac_256;
 			key_reg = 8;
 		}
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-					crypto_cfg, &pcl_info->crypto_cfg);
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
@@ -1946,8 +2343,7 @@
 				0, NULL);
 	}
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-			(crypto_cfg | CRYPTO_LITTLE_ENDIAN_MASK),
-			NULL);
+					pdev->reg.crypto_cfg_le, NULL);
 
 	if (alg != QCE_AEAD_SHA1_HMAC)
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
@@ -1971,20 +2367,12 @@
 	uint32_t encr_cfg = 0;
 	uint32_t auth_cfg = 0;
 	uint32_t key_reg = 0;
-	uint32_t crypto_cfg = 0;
-	uint32_t beats = (pdev->ce_sps.ce_burst_size >> 3) - 1;
-	uint32_t pipe_pair = pdev->ce_sps.pipe_pair_index;
 
 	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
 					pdev->ce_sps.ce_burst_size);
 	ce_vaddr_start = (uint32_t)(*pvaddr);
 	ce_vaddr = (struct sps_command_element *)(*pvaddr);
-	crypto_cfg = (beats << CRYPTO_REQ_SIZE) |
-			BIT(CRYPTO_MASK_DOUT_INTR) |
-			BIT(CRYPTO_MASK_DIN_INTR) |
-			BIT(CRYPTO_MASK_OP_DONE_INTR) |
-			(0 << CRYPTO_HIGH_SPD_EN_N) |
-			(pipe_pair << CRYPTO_PIPE_SET_SELECT);
+
 	/*
 	 * Designate chunks of the allocated memory to various
 	 * command list pointers related to aead operations
@@ -1994,36 +2382,21 @@
 		cmdlistptr->aead_aes_128_ccm.cmdlist = (uint32_t)ce_vaddr;
 		pcl_info = &(cmdlistptr->aead_aes_128_ccm);
 
-		auth_cfg = (1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
-			(CRYPTO_AUTH_MODE_CCM << CRYPTO_AUTH_MODE)|
-			(CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG) |
-			(CRYPTO_AUTH_KEY_SZ_AES128 << CRYPTO_AUTH_KEY_SIZE);
-		auth_cfg &= ~(1 << CRYPTO_USE_HW_KEY_AUTH);
-		encr_cfg = (CRYPTO_ENCR_KEY_SZ_AES128 << CRYPTO_ENCR_KEY_SZ) |
-			(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
-			((CRYPTO_ENCR_MODE_CCM << CRYPTO_ENCR_MODE));
+		auth_cfg = pdev->reg.auth_cfg_aes_ccm_128;
+		encr_cfg = pdev->reg.encr_cfg_aes_ccm_128;
 		key_reg = 4;
 	} else {
 
 		cmdlistptr->aead_aes_256_ccm.cmdlist = (uint32_t)ce_vaddr;
 		pcl_info = &(cmdlistptr->aead_aes_256_ccm);
 
-		auth_cfg = (1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
-			(CRYPTO_AUTH_MODE_CCM << CRYPTO_AUTH_MODE)|
-			(CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG) |
-			(CRYPTO_AUTH_KEY_SZ_AES256 << CRYPTO_AUTH_KEY_SIZE) |
-			((MAX_NONCE/sizeof(uint32_t)) <<
-						CRYPTO_AUTH_NONCE_NUM_WORDS);
-		auth_cfg &= ~(1 << CRYPTO_USE_HW_KEY_AUTH);
-		encr_cfg = (CRYPTO_ENCR_KEY_SZ_AES256 << CRYPTO_ENCR_KEY_SZ) |
-			(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
-			(CRYPTO_ENCR_MODE_CCM << CRYPTO_ENCR_MODE) |
-			(CRYPTO_LAST_CCM_XFR << CRYPTO_LAST_CCM);
+		auth_cfg = pdev->reg.auth_cfg_aes_ccm_256;
+		encr_cfg = pdev->reg.encr_cfg_aes_ccm_256;
 
 		key_reg = 8;
 	}
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-				crypto_cfg, &pcl_info->crypto_cfg);
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG, 0, NULL);
@@ -2093,8 +2466,7 @@
 			0, NULL);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
-			(crypto_cfg | CRYPTO_LITTLE_ENDIAN_MASK),
-			NULL);
+					pdev->reg.crypto_cfg_le, NULL);
 
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
 			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
@@ -2197,7 +2569,8 @@
 					(uint32_t)GET_PHYS_ADDR(vaddr);
 	vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec);
 
-	qce_setup_cmdlistptrs(pce_dev, &vaddr);
+	if (pce_dev->support_cmd_dscr)
+		qce_setup_cmdlistptrs(pce_dev, &vaddr);
 	vaddr = (unsigned char *) ALIGN(((unsigned int)vaddr),
 					pce_dev->ce_sps.ce_burst_size);
 	pce_dev->ce_sps.result_dump = (uint32_t)vaddr;
@@ -2207,6 +2580,160 @@
 	return 0;
 }
 
+static int qce_init_ce_cfg_val(struct qce_device *pce_dev)
+{
+	uint32_t beats = (pce_dev->ce_sps.ce_burst_size >> 3) - 1;
+	uint32_t pipe_pair = pce_dev->ce_sps.pipe_pair_index;
+
+	pce_dev->reg.crypto_cfg_be = (beats << CRYPTO_REQ_SIZE) |
+		BIT(CRYPTO_MASK_DOUT_INTR) | BIT(CRYPTO_MASK_DIN_INTR) |
+		BIT(CRYPTO_MASK_OP_DONE_INTR) | (0 << CRYPTO_HIGH_SPD_EN_N) |
+		(pipe_pair << CRYPTO_PIPE_SET_SELECT);
+
+	pce_dev->reg.crypto_cfg_le =
+		(pce_dev->reg.crypto_cfg_be | CRYPTO_LITTLE_ENDIAN_MASK);
+
+	/* Initialize encr_cfg register for AES alg */
+	pce_dev->reg.encr_cfg_aes_cbc_128 =
+		(CRYPTO_ENCR_KEY_SZ_AES128 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_CBC << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_aes_cbc_256 =
+		(CRYPTO_ENCR_KEY_SZ_AES256 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_CBC << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_aes_ctr_128 =
+		(CRYPTO_ENCR_KEY_SZ_AES128 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_CTR << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_aes_ctr_256 =
+		(CRYPTO_ENCR_KEY_SZ_AES256 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_CTR << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_aes_xts_128 =
+		(CRYPTO_ENCR_KEY_SZ_AES128 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_XTS << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_aes_xts_256 =
+		(CRYPTO_ENCR_KEY_SZ_AES256 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_XTS << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_aes_ecb_128 =
+		(CRYPTO_ENCR_KEY_SZ_AES128 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_ECB << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_aes_ecb_256 =
+		(CRYPTO_ENCR_KEY_SZ_AES256 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_ECB << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_aes_ccm_128 =
+		(CRYPTO_ENCR_KEY_SZ_AES128 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		((CRYPTO_ENCR_MODE_CCM << CRYPTO_ENCR_MODE));
+
+	pce_dev->reg.encr_cfg_aes_ccm_256 =
+		(CRYPTO_ENCR_KEY_SZ_AES256 << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_AES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_CCM << CRYPTO_ENCR_MODE) |
+		(CRYPTO_LAST_CCM_XFR << CRYPTO_LAST_CCM);
+
+	/* Initialize encr_cfg register for DES alg */
+	pce_dev->reg.encr_cfg_des_ecb =
+		(CRYPTO_ENCR_KEY_SZ_DES << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_DES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_ECB << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_des_cbc =
+		(CRYPTO_ENCR_KEY_SZ_DES << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_DES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_CBC << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_3des_ecb =
+		(CRYPTO_ENCR_KEY_SZ_3DES << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_DES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_ECB << CRYPTO_ENCR_MODE);
+
+	pce_dev->reg.encr_cfg_3des_cbc =
+		(CRYPTO_ENCR_KEY_SZ_3DES << CRYPTO_ENCR_KEY_SZ) |
+		(CRYPTO_ENCR_ALG_DES << CRYPTO_ENCR_ALG) |
+		(CRYPTO_ENCR_MODE_CBC << CRYPTO_ENCR_MODE);
+
+	/* Initialize auth_cfg register for CMAC alg */
+	pce_dev->reg.auth_cfg_cmac_128 =
+		(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
+		(CRYPTO_AUTH_MODE_CMAC << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_SIZE_ENUM_16_BYTES << CRYPTO_AUTH_SIZE) |
+		(CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_KEY_SZ_AES128 << CRYPTO_AUTH_KEY_SIZE);
+
+	pce_dev->reg.auth_cfg_cmac_256 =
+		(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
+		(CRYPTO_AUTH_MODE_CMAC << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_SIZE_ENUM_16_BYTES << CRYPTO_AUTH_SIZE) |
+		(CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_KEY_SZ_AES256 << CRYPTO_AUTH_KEY_SIZE);
+
+	/* Initialize auth_cfg register for HMAC alg */
+	pce_dev->reg.auth_cfg_hmac_sha1 =
+		(CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_SIZE_SHA1 << CRYPTO_AUTH_SIZE) |
+		(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+
+	pce_dev->reg.auth_cfg_hmac_sha256 =
+		(CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_SIZE_SHA256 << CRYPTO_AUTH_SIZE) |
+		(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+
+	/* Initialize auth_cfg register for SHA1/256 alg */
+	pce_dev->reg.auth_cfg_sha1 =
+		(CRYPTO_AUTH_MODE_HASH << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_SIZE_SHA1 << CRYPTO_AUTH_SIZE) |
+		(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+
+	pce_dev->reg.auth_cfg_sha256 =
+		(CRYPTO_AUTH_MODE_HASH << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_SIZE_SHA256 << CRYPTO_AUTH_SIZE) |
+		(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS);
+
+	/* Initialize auth_cfg register for AEAD alg */
+	pce_dev->reg.auth_cfg_aead_sha1_hmac =
+		(CRYPTO_AUTH_MODE_HMAC << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_SIZE_SHA1 << CRYPTO_AUTH_SIZE) |
+		(CRYPTO_AUTH_ALG_SHA << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_POS_BEFORE << CRYPTO_AUTH_POS) |
+		(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST);
+
+	pce_dev->reg.auth_cfg_aes_ccm_128 =
+		(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
+		(CRYPTO_AUTH_MODE_CCM << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_KEY_SZ_AES128 << CRYPTO_AUTH_KEY_SIZE) |
+		((MAX_NONCE/sizeof(uint32_t)) << CRYPTO_AUTH_NONCE_NUM_WORDS);
+	pce_dev->reg.auth_cfg_aes_ccm_128 &= ~(1 << CRYPTO_USE_HW_KEY_AUTH);
+
+	pce_dev->reg.auth_cfg_aes_ccm_256 =
+		(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
+		(CRYPTO_AUTH_MODE_CCM << CRYPTO_AUTH_MODE)|
+		(CRYPTO_AUTH_ALG_AES << CRYPTO_AUTH_ALG) |
+		(CRYPTO_AUTH_KEY_SZ_AES256 << CRYPTO_AUTH_KEY_SIZE) |
+		((MAX_NONCE/sizeof(uint32_t)) << CRYPTO_AUTH_NONCE_NUM_WORDS);
+	pce_dev->reg.auth_cfg_aes_ccm_256 &= ~(1 << CRYPTO_USE_HW_KEY_AUTH);
+
+	return 0;
+}
+
 int qce_aead_sha1_hmac_setup(struct qce_req *creq, struct crypto_aead *aead,
 				struct qce_cmdlist_info *cmdlistinfo)
 {
@@ -2301,10 +2828,16 @@
 		pce_dev->dst_nents = pce_dev->src_nents;
 	}
 
-	_ce_get_cipher_cmdlistinfo(pce_dev, q_req, &cmdlistinfo);
-	/* set up crypto device */
-	rc = _ce_setup_cipher(pce_dev, q_req, totallen_in,
-				areq->assoclen + ivsize, cmdlistinfo);
+	if (pce_dev->support_cmd_dscr) {
+		_ce_get_cipher_cmdlistinfo(pce_dev, q_req, &cmdlistinfo);
+		/* set up crypto device */
+		rc = _ce_setup_cipher(pce_dev, q_req, totallen_in,
+					areq->assoclen + ivsize, cmdlistinfo);
+	} else {
+		/* set up crypto device */
+		rc = _ce_setup_cipher_direct(pce_dev, q_req, totallen_in,
+					areq->assoclen + ivsize);
+	}
 	if (rc < 0)
 		goto bad;
 
@@ -2334,7 +2867,8 @@
 	}
 	_qce_sps_iovec_count_init(pce_dev);
 
-	_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
+	if (pce_dev->support_cmd_dscr)
+		_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
 					&pce_dev->ce_sps.in_transfer);
 
 	if (pce_dev->ce_sps.minor_version == 0) {
@@ -2445,7 +2979,6 @@
 
 	pce_dev->src_nents = 0;
 	pce_dev->dst_nents = 0;
-	_ce_get_cipher_cmdlistinfo(pce_dev, c_req, &cmdlistinfo);
 
 	/* cipher input */
 	pce_dev->src_nents = count_sg(areq->src, areq->nbytes);
@@ -2472,7 +3005,13 @@
 	}
 
 	/* set up crypto device */
-	rc = _ce_setup_cipher(pce_dev, c_req, areq->nbytes, 0, cmdlistinfo);
+	if (pce_dev->support_cmd_dscr) {
+		_ce_get_cipher_cmdlistinfo(pce_dev, c_req, &cmdlistinfo);
+		rc = _ce_setup_cipher(pce_dev, c_req, areq->nbytes, 0,
+							cmdlistinfo);
+	} else {
+		rc = _ce_setup_cipher_direct(pce_dev, c_req, areq->nbytes, 0);
+	}
 	if (rc < 0)
 		goto bad;
 
@@ -2491,8 +3030,8 @@
 		goto bad;
 	}
 	_qce_sps_iovec_count_init(pce_dev);
-
-	_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
+	if (pce_dev->support_cmd_dscr)
+		_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
 					&pce_dev->ce_sps.in_transfer);
 	if (_qce_sps_add_sg_data(pce_dev, areq->src, areq->nbytes,
 					&pce_dev->ce_sps.in_transfer))
@@ -2547,10 +3086,15 @@
 	struct qce_cmdlist_info *cmdlistinfo = NULL;
 
 	pce_dev->src_nents = count_sg(sreq->src, sreq->size);
-	_ce_get_hash_cmdlistinfo(pce_dev, sreq, &cmdlistinfo);
 	qce_dma_map_sg(pce_dev->pdev, sreq->src, pce_dev->src_nents,
 							DMA_TO_DEVICE);
-	rc = _ce_setup_hash(pce_dev, sreq, cmdlistinfo);
+
+	if (pce_dev->support_cmd_dscr) {
+		_ce_get_hash_cmdlistinfo(pce_dev, sreq, &cmdlistinfo);
+		rc = _ce_setup_hash(pce_dev, sreq, cmdlistinfo);
+	} else {
+		rc = _ce_setup_hash_direct(pce_dev, sreq);
+	}
 	if (rc < 0)
 		goto bad;
 
@@ -2568,7 +3112,8 @@
 	}
 	_qce_sps_iovec_count_init(pce_dev);
 
-	_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
+	if (pce_dev->support_cmd_dscr)
+		_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
 					&pce_dev->ce_sps.in_transfer);
 	if (_qce_sps_add_sg_data(pce_dev, areq->src, areq->nbytes,
 						 &pce_dev->ce_sps.in_transfer))
@@ -2602,7 +3147,6 @@
 
 	pce_dev->is_shared = of_property_read_bool((&pdev->dev)->of_node,
 				"qcom,ce-hw-shared");
-
 	if (of_property_read_u32((&pdev->dev)->of_node,
 				"qcom,bam-pipe-pair",
 				&pce_dev->ce_sps.pipe_pair_index)) {
@@ -2637,7 +3181,7 @@
 		pce_dev->ce_sps.bam_mem = resource->start;
 		pce_dev->ce_sps.bam_iobase = ioremap_nocache(resource->start,
 					resource_size(resource));
-		if (!pce_dev->iobase) {
+		if (!pce_dev->ce_sps.bam_iobase) {
 			rc = -ENOMEM;
 			pr_err("Can not map BAM io memory\n");
 			goto err_getting_bam_info;
@@ -2650,7 +3194,6 @@
 	pr_warn("ce_bam_phy_reg_base=0x%x  ", pce_dev->ce_sps.bam_mem);
 	pr_warn("ce_bam_virt_reg_base=0x%x\n",
 				(uint32_t)pce_dev->ce_sps.bam_iobase);
-
 	resource  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (resource) {
 		pce_dev->ce_sps.bam_irq = resource->start;
@@ -2816,6 +3359,7 @@
 void *qce_open(struct platform_device *pdev, int *rc)
 {
 	struct qce_device *pce_dev;
+	uint32_t bam_cfg = 0 ;
 
 	pce_dev = kzalloc(sizeof(struct qce_device), GFP_KERNEL);
 	if (!pce_dev) {
@@ -2857,9 +3401,16 @@
 		goto err;
 	}
 	*rc = 0;
+
+	bam_cfg = readl_relaxed(pce_dev->ce_sps.bam_iobase +
+					CRYPTO_BAM_CNFG_BITS_REG);
+	pce_dev->support_cmd_dscr = (bam_cfg & CRYPTO_BAM_CD_ENABLE_MASK) ?
+								true : false;
+	qce_init_ce_cfg_val(pce_dev);
 	qce_setup_ce_sps_data(pce_dev);
 	qce_sps_init(pce_dev);
 
+
 	qce_disable_clk(pce_dev);
 
 	return pce_dev;
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index f5123df..38515fb 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -109,6 +109,45 @@
 	struct qce_cmdlist_info unlock_all_pipes;
 };
 
+struct qce_ce_cfg_reg_setting {
+	uint32_t crypto_cfg_be;
+	uint32_t crypto_cfg_le;
+
+	uint32_t encr_cfg_aes_cbc_128;
+	uint32_t encr_cfg_aes_cbc_256;
+
+	uint32_t encr_cfg_aes_ecb_128;
+	uint32_t encr_cfg_aes_ecb_256;
+
+	uint32_t encr_cfg_aes_xts_128;
+	uint32_t encr_cfg_aes_xts_256;
+
+	uint32_t encr_cfg_aes_ctr_128;
+	uint32_t encr_cfg_aes_ctr_256;
+
+	uint32_t encr_cfg_aes_ccm_128;
+	uint32_t encr_cfg_aes_ccm_256;
+
+	uint32_t encr_cfg_des_cbc;
+	uint32_t encr_cfg_des_ecb;
+
+	uint32_t encr_cfg_3des_cbc;
+	uint32_t encr_cfg_3des_ecb;
+
+	uint32_t auth_cfg_cmac_128;
+	uint32_t auth_cfg_cmac_256;
+
+	uint32_t auth_cfg_sha1;
+	uint32_t auth_cfg_sha256;
+
+	uint32_t auth_cfg_hmac_sha1;
+	uint32_t auth_cfg_hmac_sha256;
+
+	uint32_t auth_cfg_aes_ccm_128;
+	uint32_t auth_cfg_aes_ccm_256;
+	uint32_t auth_cfg_aead_sha1_hmac;
+
+};
 
 /* DM data structure with buffers, commandlists & commmand pointer lists */
 struct ce_sps_data {
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index e91dcaa..7666e74 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1559,34 +1559,54 @@
 static int qcedev_check_cipher_key(struct qcedev_cipher_op_req *req,
 						struct qcedev_control *podev)
 {
+
+	if (req->encklen < 0) {
+		pr_err("%s: Invalid key size: %d\n", __func__, req->encklen);
+		return -EINVAL;
+	}
 	/* if intending to use HW key make sure key fields are set
 	 * correctly and HW key is indeed supported in target
 	 */
 	if (req->encklen == 0) {
 		int i;
-		for (i = 0; i < QCEDEV_MAX_KEY_SIZE; i++)
-			if (req->enckey[i])
+		for (i = 0; i < QCEDEV_MAX_KEY_SIZE; i++) {
+			if (req->enckey[i]) {
+				pr_err("%s: Invalid key: non-zero key input\n",
+								__func__);
 				goto error;
+			}
+		}
 		if ((req->op != QCEDEV_OPER_ENC_NO_KEY) &&
 			(req->op != QCEDEV_OPER_DEC_NO_KEY))
-			if (!podev->platform_support.hw_key_support)
+			if (!podev->platform_support.hw_key_support) {
+				pr_err("%s: Invalid op %d\n", __func__,
+						(uint32_t)req->op);
 				goto error;
+			}
 	} else {
 		if (req->encklen == QCEDEV_AES_KEY_192) {
-			if (!podev->ce_support.aes_key_192)
+			if (!podev->ce_support.aes_key_192) {
+				pr_err("%s: AES-192 not supported\n", __func__);
 				goto error;
+			}
 		} else {
 			/* if not using HW key make sure key
 			 * length is valid
 			 */
 			if ((req->mode == QCEDEV_AES_MODE_XTS)) {
-				if (!((req->encklen == QCEDEV_AES_KEY_128*2) ||
-					(req->encklen == QCEDEV_AES_KEY_256*2)))
+				if ((req->encklen != QCEDEV_AES_KEY_128*2) &&
+				(req->encklen != QCEDEV_AES_KEY_256*2)) {
+					pr_err("%s: unsupported key size: %d\n",
+							__func__, req->encklen);
 					goto error;
+				}
 			} else {
-				if (!((req->encklen == QCEDEV_AES_KEY_128) ||
-					(req->encklen == QCEDEV_AES_KEY_256)))
+				if ((req->encklen != QCEDEV_AES_KEY_128) &&
+					(req->encklen != QCEDEV_AES_KEY_256)) {
+					pr_err("%s: unsupported key size %d\n",
+							__func__, req->encklen);
 					goto error;
+				}
 			}
 		}
 	}
@@ -1602,32 +1622,48 @@
 		pr_err("%s: Use of PMEM is not supported\n", __func__);
 		goto error;
 	}
-	if ((req->entries == 0) || (req->data_len == 0))
+	if ((req->entries == 0) || (req->data_len == 0) ||
+			(req->entries > QCEDEV_MAX_BUFFERS)) {
+		pr_err("%s: Invalid cipher length/entries\n", __func__);
 		goto error;
+	}
 	if ((req->alg >= QCEDEV_ALG_LAST) ||
-		(req->mode >= QCEDEV_AES_DES_MODE_LAST))
+		(req->mode >= QCEDEV_AES_DES_MODE_LAST)) {
+		pr_err("%s: Invalid algorithm %d\n", __func__,
+						(uint32_t)req->alg);
 		goto error;
-
-	if ((req->mode == QCEDEV_AES_MODE_XTS) && (!podev->ce_support.aes_xts))
-					goto error;
-
-	if (req->alg == QCEDEV_ALG_AES)
+	}
+	if ((req->mode == QCEDEV_AES_MODE_XTS) &&
+				(!podev->ce_support.aes_xts)) {
+		pr_err("%s: XTS algorithm is not supported\n", __func__);
+		goto error;
+	}
+	if (req->alg == QCEDEV_ALG_AES) {
 		if (qcedev_check_cipher_key(req, podev))
-					goto error;
+			goto error;
+
+	}
 	/* if using a byteoffset, make sure it is CTR mode using vbuf */
 	if (req->byteoffset) {
-		if (req->mode != QCEDEV_AES_MODE_CTR)
+		if (req->mode != QCEDEV_AES_MODE_CTR) {
+			pr_err("%s: Operation on byte offset not supported\n",
+								 __func__);
 			goto error;
+		}
 	}
 	/* Ensure zer ivlen for ECB  mode  */
-	if (req->ivlen != 0) {
+	if (req->ivlen > 0) {
 		if ((req->mode == QCEDEV_AES_MODE_ECB) ||
-				(req->mode == QCEDEV_DES_MODE_ECB))
+				(req->mode == QCEDEV_DES_MODE_ECB)) {
+			pr_err("%s: Expecting a zero length IV\n", __func__);
 			goto error;
+		}
 	} else {
 		if ((req->mode != QCEDEV_AES_MODE_ECB) &&
-				(req->mode != QCEDEV_DES_MODE_ECB))
+				(req->mode != QCEDEV_DES_MODE_ECB)) {
+			pr_err("%s: Expecting a non-zero ength IV\n", __func__);
 			goto error;
+		}
 	}
 
 	return 0;
@@ -1640,20 +1676,42 @@
 						struct qcedev_control *podev)
 {
 	if ((req->alg == QCEDEV_ALG_AES_CMAC) &&
-				(!podev->ce_support.cmac))
+				(!podev->ce_support.cmac)) {
+		pr_err("%s: CMAC not supported\n", __func__);
 		goto sha_error;
-
-	if ((req->entries == 0) || (req->data_len == 0))
+	}
+	if ((req->entries == 0) || (req->data_len == 0) ||
+			(req->entries > QCEDEV_MAX_BUFFERS)) {
+		pr_err("%s: Invalid data length (%d)/ num entries (%d)\n",
+				__func__, req->data_len, req->entries);
 		goto sha_error;
+	}
 
-	if (req->alg >= QCEDEV_ALG_SHA_ALG_LAST)
+	if (req->alg >= QCEDEV_ALG_SHA_ALG_LAST) {
+		pr_err("%s: Invalid algorithm (%d)\n", __func__, req->alg);
 		goto sha_error;
-
+	}
 	if ((req->alg == QCEDEV_ALG_SHA1_HMAC) ||
 			(req->alg == QCEDEV_ALG_SHA1_HMAC)) {
-		if (req->authklen == 0)
+		if (req->authkey == NULL) {
+			pr_err("%s: Invalid authkey pointer\n", __func__);
 			goto sha_error;
+		}
+		if (req->authklen <= 0) {
+			pr_err("%s: Invalid authkey length (%d)\n",
+						__func__, req->authklen);
+			goto sha_error;
+		}
 	}
+
+	if (req->alg == QCEDEV_ALG_AES_CMAC) {
+		if ((req->authklen != QCEDEV_AES_KEY_128) &&
+					(req->authklen != QCEDEV_AES_KEY_256)) {
+			pr_err("%s: unsupported key length\n", __func__);
+			goto sha_error;
+		}
+	}
+
 	return 0;
 sha_error:
 	return -EINVAL;
diff --git a/drivers/crypto/msm/qcryptohw_50.h b/drivers/crypto/msm/qcryptohw_50.h
index 245d737..6c532d7 100644
--- a/drivers/crypto/msm/qcryptohw_50.h
+++ b/drivers/crypto/msm/qcryptohw_50.h
@@ -14,6 +14,10 @@
 #define _DRIVERS_CRYPTO_MSM_QCRYPTOHW_50_H_
 
 
+#define CRYPTO_BAM_CNFG_BITS_REG		0x0007C
+#define CRYPTO_BAM_CD_ENABLE			27
+#define CRYPTO_BAM_CD_ENABLE_MASK		(1 << CRYPTO_BAM_CD_ENABLE)
+
 #define QCE_AUTH_REG_BYTE_COUNT 4
 #define CRYPTO_VERSION_REG			0x1A000
 
diff --git a/drivers/gpu/ion/Kconfig b/drivers/gpu/ion/Kconfig
index 39133b5..5bb254b 100644
--- a/drivers/gpu/ion/Kconfig
+++ b/drivers/gpu/ion/Kconfig
@@ -16,12 +16,3 @@
 	depends on ARCH_MSM && ION
 	help
 	  Choose this option if you wish to use ion on an MSM target.
-
-config ION_LEAK_CHECK
-	bool "Check for leaked Ion buffers (debugging)"
-	depends on ION
-	help
-	  Choose this option if you wish to enable checking for leaked
-	  ion buffers at runtime. Choosing this option will also add a
-	  debugfs node under the ion directory that can be used to
-	  enable/disable the leak checking.
diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile
index d7ff73a..0e460c8 100644
--- a/drivers/gpu/ion/Makefile
+++ b/drivers/gpu/ion/Makefile
@@ -1,6 +1,5 @@
-obj-$(CONFIG_ION) +=	ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o \
-			ion_iommu_heap.o ion_cp_heap.o ion_removed_heap.o \
-			ion_page_pool.o ion_chunk_heap.o
+obj-$(CONFIG_ION) +=	ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \
+			ion_carveout_heap.o ion_chunk_heap.o
 obj-$(CONFIG_CMA) += ion_cma_heap.o ion_cma_secure_heap.o
 obj-$(CONFIG_ION_TEGRA) += tegra/
-obj-$(CONFIG_ION_MSM) += msm/
+obj-$(CONFIG_ION_MSM) += ion_iommu_heap.o ion_cp_heap.o ion_removed_heap.o msm/
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 4282f02..250b387 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -16,7 +16,6 @@
  *
  */
 
-#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/file.h>
 #include <linux/freezer.h>
@@ -27,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/memblock.h>
 #include <linux/miscdevice.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/mm_types.h>
 #include <linux/rbtree.h>
@@ -41,7 +41,6 @@
 #include <trace/events/kmem.h>
 
 
-#include <mach/iommu_domains.h>
 #include "ion_priv.h"
 
 /**
@@ -83,7 +82,6 @@
 	struct ion_device *dev;
 	struct rb_root handles;
 	struct mutex lock;
-	unsigned int heap_type_mask;
 	char *name;
 	struct task_struct *task;
 	pid_t pid;
@@ -108,7 +106,6 @@
 	struct ion_buffer *buffer;
 	struct rb_node node;
 	unsigned int kmap_cnt;
-	unsigned int iommu_map_cnt;
 };
 
 bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer)
@@ -545,8 +542,8 @@
 	mutex_lock(&client->lock);
 	valid_handle = ion_handle_validate(client, handle);
 	if (!valid_handle) {
-		mutex_unlock(&client->lock);
 		WARN(1, "%s: invalid handle passed to free.\n", __func__);
+		mutex_unlock(&client->lock);
 		return;
 	}
 	ion_handle_put(handle);
@@ -678,30 +675,21 @@
 	struct ion_client *client = s->private;
 	struct rb_node *n;
 
-	seq_printf(s, "%16.16s: %16.16s : %16.16s : %12.12s : %12.12s : %s\n",
+	seq_printf(s, "%16.16s: %16.16s : %16.16s : %12.12s\n",
 			"heap_name", "size_in_bytes", "handle refcount",
-			"buffer", "physical", "[domain,partition] - virt");
+			"buffer");
 
 	mutex_lock(&client->lock);
 	for (n = rb_first(&client->handles); n; n = rb_next(n)) {
 		struct ion_handle *handle = rb_entry(n, struct ion_handle,
 						     node);
 
-		enum ion_heap_type type = handle->buffer->heap->type;
-
 		seq_printf(s, "%16.16s: %16x : %16d : %12p",
 				handle->buffer->heap->name,
 				handle->buffer->size,
 				atomic_read(&handle->ref.refcount),
 				handle->buffer);
 
-		if (type == ION_HEAP_TYPE_SYSTEM_CONTIG ||
-			type == ION_HEAP_TYPE_CARVEOUT ||
-			type == (enum ion_heap_type) ION_HEAP_TYPE_CP)
-			seq_printf(s, " : %12pa", &handle->buffer->priv_phys);
-		else
-			seq_printf(s, " : %12s", "N/A");
-
 		seq_printf(s, "\n");
 	}
 	mutex_unlock(&client->lock);
@@ -1287,8 +1275,8 @@
 		ion_free(client, data.handle);
 		break;
 	}
-	case ION_IOC_MAP:
 	case ION_IOC_SHARE:
+	case ION_IOC_MAP:
 	{
 		struct ion_fd_data data;
 		if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
@@ -1391,7 +1379,7 @@
 };
 
 static size_t ion_debug_heap_total(struct ion_client *client,
-				   enum ion_heap_ids id)
+				   unsigned int id)
 {
 	size_t size = 0;
 	struct rb_node *n;
@@ -1560,7 +1548,6 @@
 	size_t total_size = 0;
 	size_t total_orphaned_size = 0;
 
-	mutex_lock(&dev->buffer_lock);
 	seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size");
 	seq_printf(s, "----------------------------------------------------\n");
 
@@ -1584,25 +1571,31 @@
 	seq_printf(s, "----------------------------------------------------\n");
 	seq_printf(s, "orphaned allocations (info is from last known client):"
 		   "\n");
+	mutex_lock(&dev->buffer_lock);
 	for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
 		struct ion_buffer *buffer = rb_entry(n, struct ion_buffer,
 						     node);
-		if (buffer->heap->type == heap->type)
-			total_size += buffer->size;
+		if (buffer->heap->id != heap->id)
+			continue;
+		total_size += buffer->size;
 		if (!buffer->handle_count) {
-			seq_printf(s, "%16.s %16u %16u\n", buffer->task_comm,
-				   buffer->pid, buffer->size);
+			seq_printf(s, "%16.s %16u %16u %d %d\n", buffer->task_comm,
+				   buffer->pid, buffer->size, buffer->kmap_cnt,
+				   atomic_read(&buffer->ref.refcount));
 			total_orphaned_size += buffer->size;
 		}
 	}
+	mutex_unlock(&dev->buffer_lock);
 	seq_printf(s, "----------------------------------------------------\n");
 	seq_printf(s, "%16.s %16u\n", "total orphaned",
 		   total_orphaned_size);
 	seq_printf(s, "%16.s %16u\n", "total ", total_size);
 	seq_printf(s, "----------------------------------------------------\n");
 
+	if (heap->debug_show)
+		heap->debug_show(heap, s, unused);
+
 	ion_heap_print_debug(s, heap);
-	mutex_unlock(&dev->buffer_lock);
 	return 0;
 }
 
@@ -1662,8 +1655,8 @@
 		return false;
 	rt_mutex_lock(&heap->lock);
 	list_for_each_entry_safe(buffer, tmp, &heap->free_list, list) {
-		_ion_buffer_destroy(buffer);
 		list_del(&buffer->list);
+		_ion_buffer_destroy(buffer);
 	}
 	BUG_ON(!list_empty(&heap->free_list));
 	rt_mutex_unlock(&heap->lock);
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 0dd3054..08921299 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -37,7 +37,6 @@
 	ion_phys_addr_t base;
 	unsigned long allocated_bytes;
 	unsigned long total_size;
-	unsigned int has_outer_cache;
 };
 
 ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
@@ -254,7 +253,6 @@
 	carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
 	carveout_heap->allocated_bytes = 0;
 	carveout_heap->total_size = heap_data->size;
-	carveout_heap->has_outer_cache = heap_data->has_outer_cache;
 
 	return &carveout_heap->heap;
 }
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 53d853d..bc9bddd 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -27,6 +27,7 @@
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 #include <mach/iommu_domains.h>
+#include <trace/events/kmem.h>
 
 struct ion_iommu_heap {
 	struct ion_heap heap;
@@ -83,9 +84,13 @@
 		} else {
 			gfp |= GFP_KERNEL;
 		}
+		trace_alloc_pages_iommu_start(gfp, orders[i]);
 		page = alloc_pages(gfp, orders[i]);
-		if (!page)
+		trace_alloc_pages_iommu_end(gfp, orders[i]);
+		if (!page) {
+			trace_alloc_pages_iommu_fail(gfp, orders[i]);
 			continue;
+		}
 
 		info = kmalloc(sizeof(struct page_info), GFP_KERNEL);
 		info->page = page;
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 4b724df..e3fbbda 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -247,14 +247,12 @@
 				      unsigned long align);
 void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
 		       unsigned long size);
-
 /**
  * The carveout heap returns physical addresses, since 0 may be a valid
  * physical address, this is used to indicate allocation failed
  */
 #define ION_CARVEOUT_ALLOCATE_FAIL -1
 
-
 /**
  * functions for creating and destroying a heap pool -- allows you
  * to keep a pool of pre allocated memory to use from your heap.  Keeping
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 02f6d93..fb6dc2d 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -25,15 +25,9 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/seq_file.h>
 #include "ion_priv.h"
-#include <mach/memory.h>
-#include <asm/cacheflush.h>
-#include <linux/msm_ion.h>
 #include <linux/dma-mapping.h>
-
-static atomic_t system_heap_allocated;
-static atomic_t system_contig_heap_allocated;
+#include <trace/events/kmem.h>
 
 static unsigned int high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO |
 					    __GFP_NOWARN | __GFP_NORETRY |
@@ -85,9 +79,13 @@
 
 		if (order > 4)
 			gfp_flags = high_order_gfp_flags;
+		trace_alloc_pages_sys_start(gfp_flags, order);
 		page = alloc_pages(gfp_flags, order);
-		if (!page)
+		trace_alloc_pages_sys_end(gfp_flags, order);
+		if (!page) {
+			trace_alloc_pages_sys_fail(gfp_flags, order);
 			return 0;
+		}
 		sg_init_table(&sg, 1);
 		sg_set_page(&sg, page, PAGE_SIZE << order, 0);
 		dma_sync_sg_for_device(NULL, &sg, 1, DMA_BIDIRECTIONAL);
@@ -207,7 +205,6 @@
 	}
 
 	buffer->priv_virt = table;
-	atomic_add(size, &system_heap_allocated);
 	return 0;
 err1:
 	kfree(table);
@@ -241,7 +238,6 @@
 				get_order(sg_dma_len(sg)));
 	sg_free_table(table);
 	kfree(table);
-	atomic_sub(buffer->size, &system_heap_allocated);
 }
 
 struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap,
@@ -256,15 +252,6 @@
 	return;
 }
 
-static int ion_system_print_debug(struct ion_heap *heap, struct seq_file *s,
-				  const struct rb_root *unused)
-{
-	seq_printf(s, "total bytes currently allocated: %lx\n",
-			(unsigned long) atomic_read(&system_heap_allocated));
-
-	return 0;
-}
-
 static struct ion_heap_ops system_heap_ops = {
 	.allocate = ion_system_heap_allocate,
 	.free = ion_system_heap_free,
@@ -273,10 +260,29 @@
 	.map_kernel = ion_heap_map_kernel,
 	.unmap_kernel = ion_heap_unmap_kernel,
 	.map_user = ion_heap_map_user,
-	.print_debug = ion_system_print_debug,
 };
 
-struct ion_heap *ion_system_heap_create(struct ion_platform_heap *pheap)
+static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s,
+				      void *unused)
+{
+
+	struct ion_system_heap *sys_heap = container_of(heap,
+							struct ion_system_heap,
+							heap);
+	int i;
+	for (i = 0; i < num_orders; i++) {
+		struct ion_page_pool *pool = sys_heap->pools[i];
+		seq_printf(s, "%d order %u highmem pages in pool = %lu total\n",
+			   pool->high_count, pool->order,
+			   (1 << pool->order) * PAGE_SIZE * pool->high_count);
+		seq_printf(s, "%d order %u lowmem pages in pool = %lu total\n",
+			   pool->low_count, pool->order,
+			   (1 << pool->order) * PAGE_SIZE * pool->low_count);
+	}
+	return 0;
+}
+
+struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused)
 {
 	struct ion_system_heap *heap;
 	int i;
@@ -302,6 +308,7 @@
 			goto err_create_pool;
 		heap->pools[i] = pool;
 	}
+	heap->heap.debug_show = ion_system_heap_debug_show;
 	return &heap->heap;
 err_create_pool:
 	for (i = 0; i < num_orders; i++)
@@ -335,14 +342,12 @@
 	buffer->priv_virt = kzalloc(len, GFP_KERNEL);
 	if (!buffer->priv_virt)
 		return -ENOMEM;
-	atomic_add(len, &system_contig_heap_allocated);
 	return 0;
 }
 
 void ion_system_contig_heap_free(struct ion_buffer *buffer)
 {
 	kfree(buffer->priv_virt);
-	atomic_sub(buffer->size, &system_contig_heap_allocated);
 }
 
 static int ion_system_contig_heap_phys(struct ion_heap *heap,
@@ -380,44 +385,6 @@
 	kfree(buffer->sg_table);
 }
 
-int ion_system_contig_heap_map_user(struct ion_heap *heap,
-				    struct ion_buffer *buffer,
-				    struct vm_area_struct *vma)
-{
-	unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv_virt));
-
-	if (ION_IS_CACHED(buffer->flags))
-		return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
-			       vma->vm_end - vma->vm_start,
-			       vma->vm_page_prot);
-	else {
-		pr_err("%s: cannot map system heap uncached\n", __func__);
-		return -EINVAL;
-	}
-}
-
-static int ion_system_contig_print_debug(struct ion_heap *heap,
-					 struct seq_file *s,
-					 const struct rb_root *unused)
-{
-	seq_printf(s, "total bytes currently allocated: %lx\n",
-		(unsigned long) atomic_read(&system_contig_heap_allocated));
-
-	return 0;
-}
-
-void *ion_system_contig_heap_map_kernel(struct ion_heap *heap,
-	struct ion_buffer *buffer)
-{
-	return buffer->priv_virt;
-}
-
-void ion_system_contig_heap_unmap_kernel(struct ion_heap *heap,
-	struct ion_buffer *buffer)
-{
-	return;
-}
-
 static struct ion_heap_ops kmalloc_ops = {
 	.allocate = ion_system_contig_heap_allocate,
 	.free = ion_system_contig_heap_free,
@@ -426,11 +393,10 @@
 	.unmap_dma = ion_system_contig_heap_unmap_dma,
 	.map_kernel = ion_heap_map_kernel,
 	.unmap_kernel = ion_heap_unmap_kernel,
-	.map_user = ion_system_contig_heap_map_user,
-	.print_debug = ion_system_contig_print_debug,
+	.map_user = ion_heap_map_user,
 };
 
-struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *pheap)
+struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused)
 {
 	struct ion_heap *heap;
 
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index f43d276..4a45313 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -89,7 +89,7 @@
 	},
 	{
 		.id	= ION_QSECOM_HEAP_ID,
-		.type	= ION_HEAP_TYPE_CARVEOUT,
+		.type	= ION_HEAP_TYPE_DMA,
 		.name	= ION_QSECOM_HEAP_NAME,
 	},
 	{
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 60bab32..e6c345b 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -810,8 +810,10 @@
 	int num_iommu_units;
 	struct kgsl_context *context;
 	struct adreno_context *adreno_ctx = NULL;
+	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	if (!adreno_dev->drawctxt_active) {
+	if (!adreno_dev->drawctxt_active ||
+		KGSL_STATE_ACTIVE != device->state) {
 		kgsl_mmu_device_setstate(&device->mmu, flags);
 		return;
 	}
@@ -863,12 +865,9 @@
 	 */
 	adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE,
 			&link[0], sizedwords);
-	/* timestamp based clock gating is currently unstable on iommuv1 */
-	if (msm_soc_version_supports_iommu_v0()) {
-		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-		kgsl_mmu_disable_clk_on_ts(&device->mmu,
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
-	}
+
+	kgsl_mmu_disable_clk_on_ts(&device->mmu,
+		rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
 
 	kgsl_context_put(context);
 }
@@ -2324,7 +2323,7 @@
 	}
 
 	/* Check if we detected a long running IB, if false return */
-	if (adreno_dev->long_ib) {
+	if ((adreno_context) && (adreno_dev->long_ib)) {
 		long_ib = _adreno_check_long_ib(device);
 		if (!long_ib) {
 			adreno_context->flags &= ~CTXT_FLAGS_GPU_HANG;
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index a76ed87..967e4ab 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -785,13 +785,13 @@
 
 			struct kgsl_memdesc *memdesc =
 				adreno_find_ctxtmem(device, ptbase, ibaddr,
-					ibsize);
+					ibsize << 2);
 
 			/* IOMMU uses a NOP IB placed in setsate memory */
 			if (NULL == memdesc)
 				if (kgsl_gpuaddr_in_memdesc(
 						&device->mmu.setstate_memory,
-						ibaddr, ibsize))
+						ibaddr, ibsize << 2))
 					memdesc = &device->mmu.setstate_memory;
 			/*
 			 * The IB from CP_IB1_BASE and the IBs for legacy
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index 6dc2ccc..ef2a19a 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -363,9 +363,11 @@
 
 	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
 		kgsl_cffdump_memory_base(device->id,
-			kgsl_mmu_get_base_addr(&device->mmu),
-			kgsl_mmu_get_ptsize(&device->mmu) +
-			KGSL_IOMMU_GLOBAL_MEM_SIZE, adreno_dev->gmem_size);
+			KGSL_PAGETABLE_BASE,
+			KGSL_IOMMU_GLOBAL_MEM_BASE +
+			KGSL_IOMMU_GLOBAL_MEM_SIZE -
+			KGSL_PAGETABLE_BASE,
+			adreno_dev->gmem_size);
 	} else {
 		kgsl_cffdump_memory_base(device->id,
 			kgsl_mmu_get_base_addr(&device->mmu),
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 15f35c9..869ab25 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -46,7 +46,7 @@
 	{ 0x03C, 1 },			/* TLBLKCR */
 	{ 0x818, 1 },			/* V2PUR */
 	{ 0x2C, 1 },			/* FSYNR0 */
-	{ 0x2C, 1 },			/* FSYNR0 */
+	{ 0x30, 1 },			/* FSYNR1 */
 	{ 0, 0 },			/* TLBSYNC, not in v0 */
 	{ 0, 0 },			/* TLBSTATUS, not in v0 */
 	{ 0, 0 }			/* IMPLDEF_MICRO_MMU_CRTL, not in v0 */
@@ -390,18 +390,20 @@
 	kgsl_sharedmem_readl(&device->memstore, &curr_context_id,
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context));
 	context = idr_find(&device->context_idr, curr_context_id);
-	if (context != NULL)
+	if (context != NULL) {
 			curr_context = context->devctxt;
 
-	kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
-		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp));
+		kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
+			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+			eoptimestamp));
 
-	/*
-	 * Store pagefault's timestamp in adreno context,
-	 * this information will be used in GFT
-	 */
-	curr_context->pagefault = 1;
-	curr_context->pagefault_ts = curr_global_ts;
+		/*
+		 * Store pagefault's timestamp in adreno context,
+		 * this information will be used in GFT
+		 */
+		curr_context->pagefault = 1;
+		curr_context->pagefault_ts = curr_global_ts;
+	}
 
 	trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
 			kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
@@ -624,8 +626,10 @@
 {
 	struct kgsl_iommu_pt *iommu_pt = pt->priv;
 	if (iommu_pt->domain)
-		iommu_domain_free(iommu_pt->domain);
+		msm_unregister_domain(iommu_pt->domain);
+
 	kfree(iommu_pt);
+	iommu_pt = NULL;
 }
 
 /*
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 813305a..aad8ef1 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -168,7 +168,6 @@
 fail_event:
 fail_copy_fd:
 	/* clean up sync_fence_install */
-	sync_fence_put(fence);
 	put_unused_fd(priv.fence_fd);
 fail_fd:
 	/* clean up sync_fence_create */
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index b3b5643..0fab4d1 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -373,7 +373,7 @@
 {
 	struct qpnp_vadc_linear_graph btm_param;
 	int64_t low_output = 0, high_output = 0;
-	int rc = 0;
+	int rc = 0, sign = 0;
 
 	rc = qpnp_get_vadc_gain_and_offset(&btm_param, CALIB_ABSOLUTE);
 	if (rc < 0) {
@@ -384,19 +384,36 @@
 	/* Convert to Kelvin and account for voltage to be written as 2mV/K */
 	low_output = (param->low_temp + KELVINMIL_DEGMIL) * 2;
 	/* Convert to voltage threshold */
-	low_output *= btm_param.dy;
-	do_div(low_output, btm_param.adc_vref);
+	low_output = (low_output - QPNP_ADC_625_UV) * btm_param.dy;
+	if (low_output < 0) {
+		sign = 1;
+		low_output = -low_output;
+	}
+	do_div(low_output, QPNP_ADC_625_UV);
+	if (sign)
+		low_output = -low_output;
 	low_output += btm_param.adc_gnd;
 
+	sign = 0;
 	/* Convert to Kelvin and account for voltage to be written as 2mV/K */
 	high_output = (param->high_temp + KELVINMIL_DEGMIL) * 2;
 	/* Convert to voltage threshold */
-	high_output *= btm_param.dy;
-	do_div(high_output, btm_param.adc_vref);
+	high_output = (high_output - QPNP_ADC_625_UV) * btm_param.dy;
+	if (high_output < 0) {
+		sign = 1;
+		high_output = -high_output;
+	}
+	do_div(high_output, QPNP_ADC_625_UV);
+	if (sign)
+		high_output = -high_output;
 	high_output += btm_param.adc_gnd;
 
-	*low_threshold = low_output;
-	*high_threshold = high_output;
+	*low_threshold = (uint32_t) low_output;
+	*high_threshold = (uint32_t) high_output;
+	pr_debug("high_temp:%d, low_temp:%d\n", param->high_temp,
+				param->low_temp);
+	pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
+				*low_threshold);
 
 	return 0;
 }
@@ -637,7 +654,7 @@
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
 	struct qpnp_vadc_linear_graph vbatt_param;
-	int rc = 0;
+	int rc = 0, sign = 0;
 	int64_t low_thr = 0, high_thr = 0;
 
 	rc = qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
@@ -646,12 +663,25 @@
 
 	low_thr = (((param->low_thr/3) - QPNP_ADC_625_UV) *
 				vbatt_param.dy);
+	if (low_thr < 0) {
+		sign = 1;
+		low_thr = -low_thr;
+	}
 	do_div(low_thr, QPNP_ADC_625_UV);
+	if (sign)
+		low_thr = -low_thr;
 	*low_threshold = low_thr + vbatt_param.adc_gnd;
 
+	sign = 0;
 	high_thr = (((param->high_thr/3) - QPNP_ADC_625_UV) *
 				vbatt_param.dy);
+	if (high_thr < 0) {
+		sign = 1;
+		high_thr = -high_thr;
+	}
 	do_div(high_thr, QPNP_ADC_625_UV);
+	if (sign)
+		high_thr = -high_thr;
 	*high_threshold = high_thr + vbatt_param.adc_gnd;
 
 	pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
@@ -877,8 +907,6 @@
 
 	init_completion(&adc_qpnp->adc_rslt_completion);
 
-	mutex_init(&adc_qpnp->adc_lock);
-
 	return 0;
 }
 EXPORT_SYMBOL(qpnp_adc_get_devicetree_data);
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 66811bf..275291f 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -830,6 +830,8 @@
 		goto fail;
 	}
 
+	mutex_init(&iadc->adc->adc_lock);
+
 	rc = of_property_read_u32(node, "qcom,rsense",
 			&iadc->rsense);
 	if (rc)
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index d296a47..d78d2ea 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -431,12 +431,32 @@
 	return 0;
 }
 
-static uint32_t qpnp_vadc_calib_device(void)
+static void qpnp_vadc_625mv_channel_sel(uint32_t *ref_channel_sel)
+{
+	struct qpnp_vadc_drv *vadc = qpnp_vadc;
+	uint32_t dt_index = 0;
+
+	/* Check if the buffered 625mV channel exists */
+	while ((vadc->adc->adc_channels[dt_index].channel_num
+		!= SPARE1) && (dt_index < vadc->max_channels_available))
+		dt_index++;
+
+	if (dt_index >= vadc->max_channels_available) {
+		pr_debug("Use default 625mV ref channel\n");
+		*ref_channel_sel = REF_625MV;
+	} else {
+		pr_debug("Use buffered 625mV ref channel\n");
+		*ref_channel_sel = SPARE1;
+	}
+}
+
+static int32_t qpnp_vadc_calib_device(void)
 {
 	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	struct qpnp_adc_amux_properties conv;
 	int rc, calib_read_1, calib_read_2, count = 0;
 	u8 status1 = 0;
+	uint32_t ref_channel_sel = 0;
 
 	conv.amux_channel = REF_125V;
 	conv.decimation = DECIMATION_TYPE2;
@@ -470,7 +490,8 @@
 		goto calib_fail;
 	}
 
-	conv.amux_channel = REF_625MV;
+	qpnp_vadc_625mv_channel_sel(&ref_channel_sel);
+	conv.amux_channel = ref_channel_sel;
 	conv.decimation = DECIMATION_TYPE2;
 	conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
 	conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
@@ -647,6 +668,7 @@
 {
 	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	int rc = 0, scale_type, amux_prescaling, dt_index = 0;
+	uint32_t ref_channel;
 
 	if (!vadc || !vadc->vadc_initialized)
 		return -EPROBE_DEFER;
@@ -666,6 +688,11 @@
 			vadc->vadc_init_calib = true;
 	}
 
+	if (channel == REF_625MV) {
+		qpnp_vadc_625mv_channel_sel(&ref_channel);
+		channel = ref_channel;
+	}
+
 	vadc->adc->amux_prop->amux_channel = channel;
 
 	while ((vadc->adc->adc_channels[dt_index].channel_num
@@ -982,6 +1009,7 @@
 		dev_err(&spmi->dev, "failed to read device tree\n");
 		goto fail;
 	}
+	mutex_init(&vadc->adc->adc_lock);
 
 	rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
 				qpnp_vadc_isr, IRQF_TRIGGER_RISING,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 4e2b1a4..426c7e7 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -103,6 +103,10 @@
 
 static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data);
 
+#ifdef CONFIG_PM
+static int synaptics_rmi4_suspend(struct device *dev);
+
+static int synaptics_rmi4_resume(struct device *dev);
 #ifdef CONFIG_HAS_EARLYSUSPEND
 static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
 		struct device_attribute *attr, char *buf);
@@ -113,10 +117,7 @@
 static void synaptics_rmi4_early_suspend(struct early_suspend *h);
 
 static void synaptics_rmi4_late_resume(struct early_suspend *h);
-
-static int synaptics_rmi4_suspend(struct device *dev);
-
-static int synaptics_rmi4_resume(struct device *dev);
+#endif
 #endif
 
 static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
@@ -1081,17 +1082,25 @@
 		bool enable)
 {
 	int retval = 0;
-	unsigned char intr_status;
+	unsigned char *intr_status;
 
 	if (enable) {
 		if (rmi4_data->irq_enabled)
 			return retval;
 
+		intr_status = kzalloc(rmi4_data->num_of_intr_regs, GFP_KERNEL);
+		if (!intr_status) {
+			dev_err(&rmi4_data->i2c_client->dev,
+					"%s: Failed to alloc memory\n",
+					__func__);
+			return -ENOMEM;
+		}
 		/* Clear interrupts first */
 		retval = synaptics_rmi4_i2c_read(rmi4_data,
 				rmi4_data->f01_data_base_addr + 1,
-				&intr_status,
+				intr_status,
 				rmi4_data->num_of_intr_regs);
+		kfree(intr_status);
 		if (retval < 0)
 			return retval;
 
@@ -1838,7 +1847,7 @@
 				RMI4_VTG_MIN_UV, RMI4_VTG_MAX_UV);
 			if (retval) {
 				dev_err(&rmi4_data->i2c_client->dev,
-					"regulator set_vtg failed retval=%d\n",
+					"regulator set_vtg failed retval =%d\n",
 					retval);
 				goto err_set_vtg_vdd;
 			}
@@ -1861,7 +1870,7 @@
 				RMI4_I2C_VTG_MIN_UV, RMI4_I2C_VTG_MAX_UV);
 			if (retval) {
 				dev_err(&rmi4_data->i2c_client->dev,
-					"reg set i2c vtg failed retval=%d\n",
+					"reg set i2c vtg failed retval =%d\n",
 					retval);
 			goto err_set_vtg_i2c;
 			}
@@ -2492,6 +2501,75 @@
 }
 #endif
 
+static int synaptics_rmi4_regulator_lpm(struct synaptics_rmi4_data *rmi4_data,
+						bool on)
+{
+	int retval;
+
+	if (on == false)
+		goto regulator_hpm;
+
+	retval = reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_LPM_LOAD_UA);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+			"Regulator vcc_ana set_opt failed rc=%d\n",
+			retval);
+		goto fail_regulator_lpm;
+	}
+
+	if (rmi4_data->board->i2c_pull_up) {
+		retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
+			RMI4_I2C_LOAD_UA);
+		if (retval < 0) {
+			dev_err(&rmi4_data->i2c_client->dev,
+				"Regulator vcc_i2c set_opt failed rc=%d\n",
+				retval);
+			goto fail_regulator_lpm;
+		}
+	}
+
+	return 0;
+
+regulator_hpm:
+
+	retval = reg_set_optimum_mode_check(rmi4_data->vdd,
+				RMI4_ACTIVE_LOAD_UA);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+			"Regulator vcc_ana set_opt failed rc=%d\n",
+			retval);
+		goto fail_regulator_hpm;
+	}
+
+	if (rmi4_data->board->i2c_pull_up) {
+		retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
+			RMI4_I2C_LOAD_UA);
+		if (retval < 0) {
+			dev_err(&rmi4_data->i2c_client->dev,
+				"Regulator vcc_i2c set_opt failed rc=%d\n",
+				retval);
+			goto fail_regulator_hpm;
+		}
+	}
+
+	return 0;
+
+fail_regulator_lpm:
+	reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_ACTIVE_LOAD_UA);
+	if (rmi4_data->board->i2c_pull_up)
+		reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
+						RMI4_I2C_LOAD_UA);
+
+	return retval;
+
+fail_regulator_hpm:
+	reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_LPM_LOAD_UA);
+	if (rmi4_data->board->i2c_pull_up)
+		reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
+						RMI4_I2C_LPM_LOAD_UA);
+	return retval;
+}
+
  /**
  * synaptics_rmi4_suspend()
  *
@@ -2505,6 +2583,7 @@
 static int synaptics_rmi4_suspend(struct device *dev)
 {
 	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+	int retval;
 
 	if (!rmi4_data->sensor_sleep) {
 		rmi4_data->touch_stopped = true;
@@ -2513,6 +2592,12 @@
 		synaptics_rmi4_sensor_sleep(rmi4_data);
 	}
 
+	retval = synaptics_rmi4_regulator_lpm(rmi4_data, true);
+	if (retval < 0) {
+		dev_err(dev, "failed to enter low power mode\n");
+		return retval;
+	}
+
 	return 0;
 }
 
@@ -2529,6 +2614,13 @@
 static int synaptics_rmi4_resume(struct device *dev)
 {
 	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+	int retval;
+
+	retval = synaptics_rmi4_regulator_lpm(rmi4_data, false);
+	if (retval < 0) {
+		dev_err(dev, "failed to enter active power mode\n");
+		return retval;
+	}
 
 	synaptics_rmi4_sensor_wake(rmi4_data);
 	rmi4_data->touch_stopped = false;
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 8a26003..8e68beb 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -804,6 +804,19 @@
 	ctx_drvdata = dev_get_drvdata(&pdev->dev);
 	BUG_ON(!ctx_drvdata);
 
+	if (!drvdata->ctx_attach_count) {
+		pr_err("Unexpected IOMMU page fault!\n");
+		pr_err("name = %s\n", drvdata->name);
+		pr_err("Power is OFF. Unable to read page fault information\n");
+		/*
+		 * We cannot determine which context bank caused the issue so
+		 * we just return handled here to ensure IRQ handler code is
+		 * happy
+		 */
+		ret = IRQ_HANDLED;
+		goto fail;
+	}
+
 	ret = __enable_clocks(drvdata);
 	if (ret) {
 		ret = IRQ_NONE;
diff --git a/drivers/iommu/msm_iommu_pagetable.c b/drivers/iommu/msm_iommu_pagetable.c
index 9614692..b871a5a 100644
--- a/drivers/iommu/msm_iommu_pagetable.c
+++ b/drivers/iommu/msm_iommu_pagetable.c
@@ -21,6 +21,7 @@
 
 #include <mach/iommu.h>
 #include <mach/msm_iommu_priv.h>
+#include <trace/events/kmem.h>
 #include "msm_iommu_pagetable.h"
 
 /* Sharability attributes of MSM IOMMU mappings */
@@ -471,6 +472,8 @@
 			chunk_size = SZ_1M;
 		/* 64k or 4k determined later */
 
+		trace_iommu_map_range(va, pa, sg->length, chunk_size);
+
 		/* for 1M and 16M, only first level entries are required */
 		if (chunk_size >= SZ_1M) {
 			if (chunk_size == SZ_16M) {
@@ -529,6 +532,9 @@
 			else
 				chunk_size = SZ_4K;
 
+			trace_iommu_map_range(va, pa, sg->length,
+							chunk_size);
+
 			if (chunk_size == SZ_4K) {
 				sl_4k(&sl_table[sl_offset], pa, pgprot4k);
 				sl_offset++;
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 3667296..5d5ff43 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -180,6 +180,20 @@
 #define LED_MPP_EN_DISABLE		0x00
 
 #define MPP_SOURCE_DTEST1		0x08
+
+#define KPDBL_MAX_LEVEL			LED_FULL
+#define KPDBL_ROW_SRC_SEL(base)		(base + 0x40)
+#define KPDBL_ENABLE(base)		(base + 0x46)
+#define KPDBL_ROW_SRC(base)		(base + 0xE5)
+
+#define KPDBL_ROW_SRC_SEL_VAL_MASK	0x0F
+#define KPDBL_ROW_SCAN_EN_MASK		0x80
+#define KPDBL_ROW_SCAN_VAL_MASK		0x0F
+#define KPDBL_ROW_SCAN_EN_SHIFT		7
+#define KPDBL_MODULE_EN			0x80
+#define KPDBL_MODULE_DIS		0x00
+#define KPDBL_MODULE_EN_MASK		0x80
+
 /**
  * enum qpnp_leds - QPNP supported led ids
  * @QPNP_ID_WLED - White led backlight
@@ -192,6 +206,7 @@
 	QPNP_ID_RGB_GREEN,
 	QPNP_ID_RGB_BLUE,
 	QPNP_ID_LED_MPP,
+	QPNP_ID_KPDBL,
 	QPNP_ID_MAX,
 };
 
@@ -237,9 +252,9 @@
 	DELAY_128us,
 };
 
-enum rgb_mode {
-	RGB_MODE_PWM = 0,
-	RGB_MODE_LPG,
+enum led_mode {
+	PWM_MODE = 0,
+	LPG_MODE,
 };
 
 static u8 wled_debug_regs[] = {
@@ -267,6 +282,10 @@
 	0x40, 0x41, 0x42, 0x45, 0x46, 0x4c,
 };
 
+static u8 kpdbl_debug_regs[] = {
+	0x40, 0x46, 0xb1, 0xb3, 0xb4, 0xe5,
+};
+
 /**
  *  wled_config_data - wled configuration data
  *  @num_strings - number of wled strings supported
@@ -331,6 +350,25 @@
 };
 
 /**
+ *  kpdbl_config_data - kpdbl configuration data
+ *  @pwm_device - pwm device
+ *  @pwm_channel - pwm channel to be configured for led
+ *  @pwm_period_us - period for pwm, in us
+ *  @row_src_sel_val - select source, 0 for vph_pwr and 1 for vbst
+ *  @row_scan_en - enable row scan
+ *  @row_scan_val - map to enable needed rows
+ */
+struct kpdbl_config_data {
+	struct pwm_device	*pwm_dev;
+	int	pwm_channel;
+	u32	pwm_period_us;
+	u32	row_src_sel_val;
+	u32	row_scan_en;
+	u32	row_scan_val;
+	u8	mode;
+};
+
+/**
  *  rgb_config_data - rgb configuration data
  *  @lut_params - lut parameters to be used by pwm driver
  *  @pwm_device - pwm device
@@ -372,6 +410,7 @@
 	spinlock_t		lock;
 	struct wled_config_data *wled_cfg;
 	struct flash_config_data	*flash_cfg;
+	struct kpdbl_config_data	*kpdbl_cfg;
 	struct rgb_config_data	*rgb_cfg;
 	struct mpp_config_data	*mpp_cfg;
 	int			max_current;
@@ -414,7 +453,8 @@
 					led->spmi_dev->sid,
 					led->base + regs[i],
 					&val, sizeof(val));
-		pr_debug("0x%x = 0x%x\n", led->base + regs[i], val);
+		pr_debug("%s: 0x%x = 0x%x\n", led->cdev.name,
+					led->base + regs[i], val);
 	}
 	pr_debug("===== %s LED register dump end =====\n", led->cdev.name);
 }
@@ -770,20 +810,57 @@
 	return 0;
 }
 
+static int qpnp_kpdbl_set(struct qpnp_led_data *led)
+{
+	int duty_us;
+	int rc;
+
+	if (led->cdev.brightness) {
+		rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
+				KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
+		duty_us = (led->kpdbl_cfg->pwm_period_us *
+			led->cdev.brightness) / KPDBL_MAX_LEVEL;
+		rc = pwm_config(led->kpdbl_cfg->pwm_dev, duty_us,
+				led->kpdbl_cfg->pwm_period_us);
+		if (rc < 0) {
+			dev_err(&led->spmi_dev->dev, "pwm config failed\n");
+			return rc;
+		}
+		rc = pwm_enable(led->kpdbl_cfg->pwm_dev);
+		if (rc < 0) {
+			dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
+			return rc;
+		}
+	} else {
+		pwm_disable(led->kpdbl_cfg->pwm_dev);
+		rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
+				KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Failed to write led enable reg\n");
+			return rc;
+		}
+	}
+
+	qpnp_dump_regs(led, kpdbl_debug_regs, ARRAY_SIZE(kpdbl_debug_regs));
+
+	return 0;
+}
+
 static int qpnp_rgb_set(struct qpnp_led_data *led)
 {
 	int duty_us;
 	int rc;
 
 	if (led->cdev.brightness) {
-		if (led->rgb_cfg->mode == RGB_MODE_PWM) {
+		if (led->rgb_cfg->mode == PWM_MODE) {
 			duty_us = (led->rgb_cfg->pwm_period_us *
 				led->cdev.brightness) / LED_FULL;
 			rc = pwm_config(led->rgb_cfg->pwm_dev, duty_us,
 					led->rgb_cfg->pwm_period_us);
 			if (rc < 0) {
-				dev_err(&led->spmi_dev->dev, "Failed to " \
-					"configure pwm for new values\n");
+				dev_err(&led->spmi_dev->dev,
+					"pwm config failed\n");
 				return rc;
 			}
 		}
@@ -796,6 +873,10 @@
 			return rc;
 		}
 		rc = pwm_enable(led->rgb_cfg->pwm_dev);
+		if (rc < 0) {
+			dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
+			return rc;
+		}
 	} else {
 		pwm_disable(led->rgb_cfg->pwm_dev);
 		rc = qpnp_led_masked_write(led,
@@ -855,6 +936,11 @@
 		if (rc < 0)
 			dev_err(&led->spmi_dev->dev,
 					"MPP set brightness failed (%d)\n", rc);
+	case QPNP_ID_KPDBL:
+		rc = qpnp_kpdbl_set(led);
+		if (rc < 0)
+			dev_err(&led->spmi_dev->dev,
+				"KPDBL set brightness failed (%d)\n", rc);
 		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
@@ -881,6 +967,9 @@
 	case QPNP_ID_LED_MPP:
 		led->cdev.max_brightness = MPP_MAX_LEVEL;
 		break;
+	case QPNP_ID_KPDBL:
+		led->cdev.max_brightness = KPDBL_MAX_LEVEL;
+		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		return -EINVAL;
@@ -1226,6 +1315,81 @@
 	return 0;
 }
 
+static int __devinit qpnp_kpdbl_init(struct qpnp_led_data *led)
+{
+	int rc;
+	u8 val;
+
+	/* enable row source selct */
+	rc = qpnp_led_masked_write(led, KPDBL_ROW_SRC_SEL(led->base),
+		KPDBL_ROW_SRC_SEL_VAL_MASK, led->kpdbl_cfg->row_src_sel_val);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Enable row src sel write failed(%d)\n", rc);
+		return rc;
+	}
+
+	/* row source */
+	rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
+				KPDBL_ROW_SRC(led->base), &val, 1);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Unable to read from addr=%x, rc(%d)\n",
+			KPDBL_ROW_SRC(led->base), rc);
+		return rc;
+	}
+
+	val &= ~KPDBL_ROW_SCAN_VAL_MASK;
+	val |= led->kpdbl_cfg->row_scan_val;
+
+	led->kpdbl_cfg->row_scan_en <<= KPDBL_ROW_SCAN_EN_SHIFT;
+	val &= ~KPDBL_ROW_SCAN_EN_MASK;
+	val |= led->kpdbl_cfg->row_scan_en;
+
+	rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+		KPDBL_ROW_SRC(led->base), &val, 1);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Unable to write to addr=%x, rc(%d)\n",
+			KPDBL_ROW_SRC(led->base), rc);
+		return rc;
+	}
+
+	/* enable module */
+	rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
+		KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Enable module write failed(%d)\n", rc);
+		return rc;
+	}
+
+	if (led->kpdbl_cfg->pwm_channel != -1) {
+		led->kpdbl_cfg->pwm_dev =
+			pwm_request(led->kpdbl_cfg->pwm_channel,
+						led->cdev.name);
+
+		if (IS_ERR_OR_NULL(led->kpdbl_cfg->pwm_dev)) {
+			dev_err(&led->spmi_dev->dev,
+				"could not acquire PWM Channel %d, " \
+				"error %ld\n",
+				led->kpdbl_cfg->pwm_channel,
+				PTR_ERR(led->kpdbl_cfg->pwm_dev));
+			led->kpdbl_cfg->pwm_dev = NULL;
+			return -ENODEV;
+		}
+	} else {
+		dev_err(&led->spmi_dev->dev,
+			"Invalid PWM channel\n");
+		return -EINVAL;
+	}
+
+	/* dump kpdbl registers */
+	qpnp_dump_regs(led, kpdbl_debug_regs, ARRAY_SIZE(kpdbl_debug_regs));
+
+	return 0;
+}
+
 static int __devinit qpnp_rgb_init(struct qpnp_led_data *led)
 {
 	int rc, start_idx, idx_len;
@@ -1253,7 +1417,7 @@
 			return -ENODEV;
 		}
 
-		if (led->rgb_cfg->mode == RGB_MODE_LPG) {
+		if (led->rgb_cfg->mode == LPG_MODE) {
 			start_idx =
 			led->rgb_cfg->duty_cycles->start_idx;
 			idx_len =
@@ -1296,7 +1460,7 @@
 
 static int __devinit qpnp_led_initialize(struct qpnp_led_data *led)
 {
-	int rc;
+	int rc = 0;
 
 	switch (led->id) {
 	case QPNP_ID_WLED:
@@ -1322,12 +1486,18 @@
 		break;
 	case QPNP_ID_LED_MPP:
 		break;
+	case QPNP_ID_KPDBL:
+		rc = qpnp_kpdbl_init(led);
+		if (rc)
+			dev_err(&led->spmi_dev->dev,
+				"KPDBL initialize failed(%d)\n", rc);
+		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		return -EINVAL;
 	}
 
-	return 0;
+	return rc;
 }
 
 static int __devinit qpnp_get_common_configs(struct qpnp_led_data *led,
@@ -1512,6 +1682,63 @@
 	return 0;
 }
 
+static int __devinit qpnp_get_config_kpdbl(struct qpnp_led_data *led,
+				struct device_node *node)
+{
+	int rc;
+	u32 val;
+
+	led->kpdbl_cfg = devm_kzalloc(&led->spmi_dev->dev,
+				sizeof(struct kpdbl_config_data), GFP_KERNEL);
+	if (!led->kpdbl_cfg) {
+		dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode", &val);
+	if (!rc)
+		led->kpdbl_cfg->mode = (u8) val;
+	else
+		return rc;
+
+	if (led->kpdbl_cfg->mode == LPG_MODE) {
+		dev_err(&led->spmi_dev->dev, "LPG mode not supported\n");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
+	if (!rc)
+		led->kpdbl_cfg->pwm_channel = (u8) val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,pwm-us", &val);
+	if (!rc)
+		led->kpdbl_cfg->pwm_period_us = val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,row-src-sel-val", &val);
+	if (!rc)
+		led->kpdbl_cfg->row_src_sel_val = val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,row-scan-val", &val);
+	if (!rc)
+		led->kpdbl_cfg->row_scan_val = val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,row-scan-en", &val);
+	if (!rc)
+		led->kpdbl_cfg->row_scan_en = val;
+	else
+		return rc;
+
+	return 0;
+}
+
 static int __devinit qpnp_get_config_rgb(struct qpnp_led_data *led,
 				struct device_node *node)
 {
@@ -1548,7 +1775,7 @@
 	else
 		return rc;
 
-	if (led->rgb_cfg->mode == RGB_MODE_PWM) {
+	if (led->rgb_cfg->mode == PWM_MODE) {
 		rc = of_property_read_u32(node, "qcom,pwm-us", &val);
 		if (!rc)
 			led->rgb_cfg->pwm_period_us = val;
@@ -1556,7 +1783,7 @@
 			return rc;
 	}
 
-	if (led->rgb_cfg->mode == RGB_MODE_LPG) {
+	if (led->rgb_cfg->mode == LPG_MODE) {
 		led->rgb_cfg->duty_cycles =
 			devm_kzalloc(&led->spmi_dev->dev,
 			sizeof(struct pwm_duty_cycles), GFP_KERNEL);
@@ -1791,6 +2018,12 @@
 			if (rc < 0) {
 				dev_err(&led->spmi_dev->dev,
 						"Unable to read mpp config data\n");
+			}
+		} else if (strncmp(led_label, "kpdbl", sizeof("kpdbl")) == 0) {
+			rc = qpnp_get_config_kpdbl(led, temp);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev,
+					"Unable to read kpdbl config data\n");
 				goto fail_id_check;
 			}
 		} else {
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 89500f9..fcade49 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -246,7 +246,10 @@
 				struct dmx_secure_mode *sec_mode);
 	int (*oob_command) (struct dmx_ts_feed *feed,
 			struct dmx_oob_command *cmd);
-
+	int (*ts_insertion_init)(struct dmx_ts_feed *feed);
+	int (*ts_insertion_terminate)(struct dmx_ts_feed *feed);
+	int (*ts_insertion_insert_buffer)(struct dmx_ts_feed *feed,
+			char *data, size_t size);
 };
 
 /*--------------------------------------------------------------------------*/
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 5e7a09e..7347b37 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -34,6 +34,8 @@
 #include <linux/uaccess.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
 #include "dmxdev.h"
 
 static int debug;
@@ -416,7 +418,33 @@
 	return 0;
 }
 
-static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
+static inline int dvb_dmxdev_check_data(struct dmxdev_filter *filter,
+			struct dvb_ringbuffer *src)
+{
+	int data_status_change;
+
+	if (filter)
+		if (mutex_lock_interruptible(&filter->mutex))
+			return -ERESTARTSYS;
+
+	if (!src->data ||
+		!dvb_ringbuffer_empty(src) ||
+		src->error ||
+		(filter &&
+		 (filter->state != DMXDEV_STATE_GO) &&
+		 (filter->state != DMXDEV_STATE_DONE)))
+		data_status_change = 1;
+	else
+		data_status_change = 0;
+
+	if (filter)
+		mutex_unlock(&filter->mutex);
+
+	return data_status_change;
+}
+
+static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_filter *filter,
+					struct dvb_ringbuffer *src,
 					int non_blocking, char __user *buf,
 					size_t count, loff_t *ppos)
 {
@@ -439,9 +467,26 @@
 			break;
 		}
 
-		ret = wait_event_interruptible(src->queue, (!src->data) ||
-						!dvb_ringbuffer_empty(src) ||
-						(src->error != 0));
+		if (filter) {
+			if ((filter->state == DMXDEV_STATE_DONE) &&
+				dvb_ringbuffer_empty(src))
+				break;
+
+			mutex_unlock(&filter->mutex);
+		}
+
+		ret = wait_event_interruptible(src->queue,
+				dvb_dmxdev_check_data(filter, src));
+
+		if (filter) {
+			if (mutex_lock_interruptible(&filter->mutex))
+				return -ERESTARTSYS;
+
+			if ((filter->state != DMXDEV_STATE_GO) &&
+				(filter->state != DMXDEV_STATE_DONE))
+				return -ENODEV;
+		}
+
 		if (ret < 0)
 			break;
 
@@ -1108,9 +1153,9 @@
 	if (dmxdev->exit)
 		return -ENODEV;
 
-	res = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
-				      file->f_flags & O_NONBLOCK,
-				      buf, count, ppos);
+	res = dvb_dmxdev_buffer_read(NULL, &dmxdev->dvr_buffer,
+				file->f_flags & O_NONBLOCK,
+				buf, count, ppos);
 
 	if (res > 0) {
 		dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, res);
@@ -1751,6 +1796,213 @@
 	return 0;
 }
 
+static void dvb_dmxdev_ts_insertion_timer(unsigned long data)
+{
+	struct ts_insertion_buffer *ts_buffer =
+		(struct ts_insertion_buffer *)data;
+
+	if (ts_buffer && !ts_buffer->abort)
+		schedule_work(&ts_buffer->work);
+}
+
+static void dvb_dmxdev_ts_insertion_work(struct work_struct *worker)
+{
+	struct ts_insertion_buffer *ts_buffer =
+		container_of(worker, struct ts_insertion_buffer, work);
+	struct dmxdev_feed *feed;
+	size_t free_bytes;
+	struct dmx_ts_feed *ts;
+
+	mutex_lock(&ts_buffer->dmxdevfilter->mutex);
+
+	if (ts_buffer->abort ||
+		(ts_buffer->dmxdevfilter->state != DMXDEV_STATE_GO)) {
+		mutex_unlock(&ts_buffer->dmxdevfilter->mutex);
+		return;
+	}
+
+	feed = list_first_entry(&ts_buffer->dmxdevfilter->feed.ts,
+				struct dmxdev_feed, next);
+	ts = feed->ts;
+	free_bytes = dvb_ringbuffer_free(&ts_buffer->dmxdevfilter->buffer);
+
+	mutex_unlock(&ts_buffer->dmxdevfilter->mutex);
+
+	if (ts_buffer->size < free_bytes)
+		ts->ts_insertion_insert_buffer(ts,
+			ts_buffer->buffer, ts_buffer->size);
+
+	if (ts_buffer->repetition_time)
+		mod_timer(&ts_buffer->timer, jiffies +
+				msecs_to_jiffies(ts_buffer->repetition_time));
+}
+
+static void dvb_dmxdev_queue_ts_insertion(
+		struct ts_insertion_buffer *ts_buffer)
+{
+	size_t tsp_size;
+
+	if (ts_buffer->dmxdevfilter->dmx_tsp_format == DMX_TSP_FORMAT_188)
+		tsp_size = 188;
+	else
+		tsp_size = 192;
+
+	if (ts_buffer->size % tsp_size) {
+		printk(KERN_ERR "%s: Wrong buffer alignment, size=%d, tsp_size=%d\n",
+			__func__, ts_buffer->size, tsp_size);
+		return;
+	}
+
+	ts_buffer->abort = 0;
+	schedule_work(&ts_buffer->work);
+}
+
+static void dvb_dmxdev_cancel_ts_insertion(
+		struct ts_insertion_buffer *ts_buffer)
+{
+	/*
+	 * This function assumes it is called while mutex
+	 * of demux filter is taken. Since work in workqueue
+	 * captures the filter's mutex to protect against the DB,
+	 * mutex needs to be released before waiting for the work
+	 * to get finished otherwise work in workqueue will
+	 * never be finished.
+	 */
+	if (!mutex_is_locked(&ts_buffer->dmxdevfilter->mutex)) {
+		printk(KERN_ERR "%s: mutex is not locked!\n", __func__);
+		return;
+	}
+
+	/*
+	 * Work should be stopped first as it might re-trigger the timer
+	 * until it is stopped. Timer would not re-schedule the work
+	 * due to the abort flag.
+	 */
+	ts_buffer->abort = 1;
+
+	mutex_unlock(&ts_buffer->dmxdevfilter->mutex);
+	cancel_work_sync(&ts_buffer->work);
+	del_timer_sync(&ts_buffer->timer);
+	mutex_lock(&ts_buffer->dmxdevfilter->mutex);
+}
+
+static int dvb_dmxdev_set_ts_insertion(struct dmxdev_filter *dmxdevfilter,
+		struct dmx_set_ts_insertion *params)
+{
+	int ret = 0;
+	int first_buffer;
+	struct dmxdev_feed *feed;
+	struct ts_insertion_buffer *ts_buffer;
+
+	if (!params ||
+		!params->size ||
+		!(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+		(dmxdevfilter->state < DMXDEV_STATE_SET) ||
+		(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
+		((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
+		 (dmxdevfilter->params.pes.output != DMX_OUT_TSDEMUX_TAP)))
+		return -EINVAL;
+
+	ts_buffer = vmalloc(sizeof(struct ts_insertion_buffer));
+	if (!ts_buffer)
+		return -ENOMEM;
+
+	ts_buffer->buffer = vmalloc(params->size);
+	if (!ts_buffer->buffer) {
+		vfree(ts_buffer);
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(ts_buffer->buffer,
+			params->ts_packets, params->size)) {
+		vfree(ts_buffer->buffer);
+		vfree(ts_buffer);
+		return -EFAULT;
+	}
+
+	if (params->repetition_time &&
+		params->repetition_time < DMX_MIN_INSERTION_REPETITION_TIME)
+		params->repetition_time = DMX_MIN_INSERTION_REPETITION_TIME;
+
+	ts_buffer->size = params->size;
+	ts_buffer->identifier = params->identifier;
+	ts_buffer->repetition_time = params->repetition_time;
+	ts_buffer->dmxdevfilter = dmxdevfilter;
+	init_timer(&ts_buffer->timer);
+	ts_buffer->timer.function = dvb_dmxdev_ts_insertion_timer;
+	ts_buffer->timer.data = (unsigned long)ts_buffer;
+	ts_buffer->timer.expires = 0xffffffffL;
+	INIT_WORK(&ts_buffer->work, dvb_dmxdev_ts_insertion_work);
+
+	first_buffer = list_empty(&dmxdevfilter->insertion_buffers);
+	list_add_tail(&ts_buffer->next, &dmxdevfilter->insertion_buffers);
+
+	if (dmxdevfilter->state != DMXDEV_STATE_GO)
+		return 0;
+
+	feed = list_first_entry(&dmxdevfilter->feed.ts,
+				struct dmxdev_feed, next);
+
+	if (first_buffer && feed->ts->ts_insertion_init)
+		ret = feed->ts->ts_insertion_init(feed->ts);
+
+	if (!ret) {
+		dvb_dmxdev_queue_ts_insertion(ts_buffer);
+	} else {
+		list_del(&ts_buffer->next);
+		vfree(ts_buffer->buffer);
+		vfree(ts_buffer);
+	}
+
+	return ret;
+}
+
+static int dvb_dmxdev_abort_ts_insertion(struct dmxdev_filter *dmxdevfilter,
+		struct dmx_abort_ts_insertion *params)
+{
+	int ret = 0;
+	int found_buffer;
+	struct dmxdev_feed *feed;
+	struct ts_insertion_buffer *ts_buffer, *tmp;
+
+	if (!params ||
+		!(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+		(dmxdevfilter->state < DMXDEV_STATE_SET) ||
+		(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
+		((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
+		 (dmxdevfilter->params.pes.output != DMX_OUT_TSDEMUX_TAP)))
+		return -EINVAL;
+
+	found_buffer = 0;
+	list_for_each_entry_safe(ts_buffer, tmp,
+			&dmxdevfilter->insertion_buffers, next) {
+		if (ts_buffer->identifier == params->identifier) {
+			list_del(&ts_buffer->next);
+			found_buffer = 1;
+			break;
+		}
+	}
+
+	if (!found_buffer)
+		return -EINVAL;
+
+	if (dmxdevfilter->state == DMXDEV_STATE_GO) {
+		dvb_dmxdev_cancel_ts_insertion(ts_buffer);
+		if (list_empty(&dmxdevfilter->insertion_buffers)) {
+			feed = list_first_entry(&dmxdevfilter->feed.ts,
+						struct dmxdev_feed, next);
+			if (feed->ts->ts_insertion_terminate)
+				ret = feed->ts->ts_insertion_terminate(
+							feed->ts);
+		}
+	}
+
+	vfree(ts_buffer->buffer);
+	vfree(ts_buffer);
+
+	return ret;
+}
+
 static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter,
 				int required_space)
 {
@@ -2006,6 +2258,9 @@
 		dvb_ringbuffer_flush(&dmxdevfilter->buffer);
 		dvb_dmxdev_notify_data_read(dmxdevfilter, flush_len);
 		dmxdevfilter->buffer.error = 0;
+	} else if (event->type == DMX_EVENT_SECTION_TIMEOUT) {
+		/* clear buffer error now that user was notified */
+		dmxdevfilter->buffer.error = 0;
 	}
 
 	/*
@@ -2036,10 +2291,13 @@
 static void dvb_dmxdev_filter_timeout(unsigned long data)
 {
 	struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data;
+	struct dmx_filter_event event;
 
 	dmxdevfilter->buffer.error = -ETIMEDOUT;
 	spin_lock_irq(&dmxdevfilter->dev->lock);
 	dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
+	event.type = DMX_EVENT_SECTION_TIMEOUT;
+	dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
 	spin_unlock_irq(&dmxdevfilter->dev->lock);
 	wake_up_all(&dmxdevfilter->buffer.queue);
 }
@@ -2612,6 +2870,7 @@
 {
 	struct dmxdev_feed *feed;
 	struct dmx_demux *demux;
+	struct ts_insertion_buffer *ts_buffer;
 
 	if (dmxdevfilter->state < DMXDEV_STATE_GO)
 		return 0;
@@ -2631,6 +2890,18 @@
 	case DMXDEV_TYPE_PES:
 		dvb_dmxdev_feed_stop(dmxdevfilter);
 		demux = dmxdevfilter->dev->demux;
+
+		if (!list_empty(&dmxdevfilter->insertion_buffers)) {
+			feed = list_first_entry(&dmxdevfilter->feed.ts,
+				struct dmxdev_feed, next);
+
+			list_for_each_entry(ts_buffer,
+					&dmxdevfilter->insertion_buffers, next)
+				dvb_dmxdev_cancel_ts_insertion(ts_buffer);
+			if (feed->ts->ts_insertion_terminate)
+				feed->ts->ts_insertion_terminate(feed->ts);
+		}
+
 		list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) {
 			demux->release_ts_feed(demux, feed->ts);
 			feed->ts = NULL;
@@ -2971,6 +3242,29 @@
 	}
 
 	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
+
+	if ((filter->type == DMXDEV_TYPE_PES) &&
+		!list_empty(&filter->insertion_buffers)) {
+		struct ts_insertion_buffer *ts_buffer;
+
+		feed = list_first_entry(&filter->feed.ts,
+			struct dmxdev_feed, next);
+
+		ret = 0;
+		if (feed->ts->ts_insertion_init)
+			ret = feed->ts->ts_insertion_init(feed->ts);
+		if (!ret) {
+			list_for_each_entry(ts_buffer,
+				&filter->insertion_buffers, next)
+				dvb_dmxdev_queue_ts_insertion(
+					ts_buffer);
+		} else {
+			printk(KERN_ERR
+				"%s: ts_insertion_init failed, err %d\n",
+				__func__, ret);
+		}
+	}
+
 	return 0;
 }
 
@@ -3017,6 +3311,8 @@
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 	init_timer(&dmxdevfilter->timer);
 
+	INIT_LIST_HEAD(&dmxdevfilter->insertion_buffers);
+
 	dmxdevfilter->dmx_tsp_format = DMX_TSP_FORMAT_188;
 	dvbdev->users++;
 
@@ -3027,6 +3323,8 @@
 static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
 				  struct dmxdev_filter *dmxdevfilter)
 {
+	struct ts_insertion_buffer *ts_buffer, *tmp;
+
 	mutex_lock(&dmxdev->mutex);
 	mutex_lock(&dmxdevfilter->mutex);
 
@@ -3034,6 +3332,13 @@
 
 	dvb_dmxdev_filter_reset(dmxdevfilter);
 
+	list_for_each_entry_safe(ts_buffer, tmp,
+			&dmxdevfilter->insertion_buffers, next) {
+		list_del(&ts_buffer->next);
+		vfree(ts_buffer->buffer);
+		vfree(ts_buffer);
+	}
+
 	if (dmxdevfilter->buffer.data) {
 		void *mem = dmxdevfilter->buffer.data;
 
@@ -3098,12 +3403,20 @@
 static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev,
 				  struct dmxdev_filter *filter, u16 pid)
 {
+	int feed_count;
 	struct dmxdev_feed *feed, *tmp;
 
 	if ((filter->type != DMXDEV_TYPE_PES) ||
 	    (filter->state < DMXDEV_STATE_SET))
 		return -EINVAL;
 
+	feed_count = 0;
+	list_for_each_entry(tmp, &filter->feed.ts, next)
+		feed_count++;
+
+	if (feed_count <= 1)
+		return -EINVAL;
+
 	list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) {
 		if (feed->pid == pid) {
 			if (feed->ts != NULL) {
@@ -3283,7 +3596,7 @@
 		hcount = 3 + dfil->todo;
 		if (hcount > count)
 			hcount = count;
-		result = dvb_dmxdev_buffer_read(&dfil->buffer,
+		result = dvb_dmxdev_buffer_read(dfil, &dfil->buffer,
 						file->f_flags & O_NONBLOCK,
 						buf, hcount, ppos);
 		if (result < 0) {
@@ -3304,7 +3617,7 @@
 	}
 	if (count > dfil->todo)
 		count = dfil->todo;
-	result = dvb_dmxdev_buffer_read(&dfil->buffer,
+	result = dvb_dmxdev_buffer_read(dfil, &dfil->buffer,
 					file->f_flags & O_NONBLOCK,
 					buf, count, ppos);
 	if (result < 0)
@@ -3333,9 +3646,10 @@
 	if (dmxdevfilter->type == DMXDEV_TYPE_SEC)
 		ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
 	else
-		ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
-					    file->f_flags & O_NONBLOCK,
-					    buf, count, ppos);
+		ret = dvb_dmxdev_buffer_read(dmxdevfilter,
+					&dmxdevfilter->buffer,
+					file->f_flags & O_NONBLOCK,
+					buf, count, ppos);
 
 	if (ret > 0) {
 		dvb_dmxdev_notify_data_read(dmxdevfilter, ret);
@@ -3625,6 +3939,24 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_SET_TS_INSERTION:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_set_ts_insertion(dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_ABORT_TS_INSERTION:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_abort_ts_insertion(dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 2ed99ae..d8cd982 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -114,6 +114,35 @@
 	struct dmx_filter_event queue[DMX_EVENT_QUEUE_SIZE];
 };
 
+#define DMX_MIN_INSERTION_REPETITION_TIME	25 /* in msec */
+struct ts_insertion_buffer {
+	/* work scheduled for insertion of this buffer */
+	struct work_struct work;
+
+	struct list_head next;
+
+	/* buffer holding TS packets for insertion */
+	char *buffer;
+
+	/* buffer size */
+	size_t size;
+
+	/* buffer ID from user */
+	u32 identifier;
+
+	/* repetition time for the buffer insertion */
+	u32 repetition_time;
+
+	/* timer used for insertion of the buffer */
+	struct timer_list timer;
+
+	/* the recording filter to which this buffer belongs */
+	struct dmxdev_filter *dmxdevfilter;
+
+	/* indication whether insertion should be aborted */
+	int abort;
+};
+
 struct dmxdev_filter {
 	union {
 		struct dmx_section_filter *sec;
@@ -145,6 +174,9 @@
 	enum dmx_tsp_format_t dmx_tsp_format;
 	u32 rec_chunk_size;
 
+	/* list of buffers used for insertion (struct ts_insertion_buffer) */
+	struct list_head insertion_buffers;
+
 	/* End-of-stream indication has been received */
 	int eos_state;
 
@@ -170,6 +202,8 @@
 #define DMXDEV_CAP_PULL_MODE	0x02
 #define DMXDEV_CAP_INDEXING	0x04
 #define DMXDEV_CAP_EXTERNAL_BUFFS_ONLY	0x08
+#define DMXDEV_CAP_TS_INSERTION	0x10
+
 
 	enum dmx_playback_mode_t playback_mode;
 	dmx_source_t source;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 3f3d222..939d591 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -2331,6 +2331,25 @@
 	return ret;
 }
 
+static int dvbdmx_ts_insertion_insert_buffer(struct dmx_ts_feed *ts_feed,
+			char *data, size_t size)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+	if (!ts_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return 0;
+	}
+
+	feed->cb.ts(data, size, NULL, 0, ts_feed, DMX_OK);
+
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dmx_ts_set_tsp_out_format(
 	struct dmx_ts_feed *ts_feed,
 	enum dmx_tsp_format_t tsp_format)
@@ -2401,6 +2420,10 @@
 	(*ts_feed)->notify_data_read = NULL;
 	(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
 	(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
+	(*ts_feed)->ts_insertion_init = NULL;
+	(*ts_feed)->ts_insertion_terminate = NULL;
+	(*ts_feed)->ts_insertion_insert_buffer =
+		dvbdmx_ts_insertion_insert_buffer;
 
 	if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
 		feed->state = DMX_STATE_FREE;
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c
index 84f7307..9370fc9 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -142,7 +142,7 @@
 	buf_p = msm_gemini_hw_pingpong_active_buffer(&we_pingpong_buf);
 	if (buf_p) {
 		buf_p->framedone_len = msm_gemini_hw_encode_output_size();
-		GMN_DBG("%s:%d] framedone_len %d\n", __func__, __LINE__,
+		pr_debug("%s:%d] framedone_len %d\n", __func__, __LINE__,
 			buf_p->framedone_len);
 	}
 
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c
index 0cbb101..79c533e 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010,2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -297,6 +297,8 @@
 
 	struct msm_gemini_hw_cmd *hw_cmd_p;
 
+	pr_debug("%s:%d] pingpong index %d", __func__, __LINE__,
+		pingpong_index);
 	if (pingpong_index == 0) {
 		hw_cmd_p = &hw_cmd_we_ping_update[0];
 
@@ -486,40 +488,38 @@
 	return is_copy_to_user;
 }
 
-void msm_gemini_hw_region_dump(int size)
+#ifdef MSM_GMN_DBG_DUMP
+void msm_gemini_io_dump(int size)
 {
-	uint32_t *p;
-	uint8_t *p8;
-
-	if (size > gemini_region_size)
-		GMN_PR_ERR("%s:%d] wrong region dump size\n",
-			__func__, __LINE__);
-
-	p = (uint32_t *) gemini_region_base;
-	while (size >= 16) {
-		GMN_DBG("0x%08X] %08X %08X %08X %08X\n",
-			gemini_region_size - size,
-			readl(p), readl(p+1), readl(p+2), readl(p+3));
-		p += 4;
-		size -= 16;
-	}
-
-	if (size > 0) {
-		uint32_t d;
-		GMN_DBG("0x%08X] ", gemini_region_size - size);
-		while (size >= 4) {
-			GMN_DBG("%08X ", readl(p++));
-			size -= 4;
+	char line_str[128], *p_str;
+	void __iomem *addr = gemini_region_base;
+	int i;
+	u32 *p = (u32 *) addr;
+	u32 data;
+	pr_info("%s: %p %d reg_size %d\n", __func__, addr, size,
+							gemini_region_size);
+	line_str[0] = '\0';
+	p_str = line_str;
+	for (i = 0; i < size/4; i++) {
+		if (i % 4 == 0) {
+			snprintf(p_str, 12, "%08x: ", (u32) p);
+			p_str += 10;
 		}
-
-		d = readl(p);
-		p8 = (uint8_t *) &d;
-		while (size) {
-			GMN_DBG("%02X", *p8++);
-			size--;
+		data = readl_relaxed(p++);
+		snprintf(p_str, 12, "%08x ", data);
+		p_str += 9;
+		if ((i + 1) % 4 == 0) {
+			pr_info("%s\n", line_str);
+			line_str[0] = '\0';
+			p_str = line_str;
 		}
-
-		GMN_DBG("\n");
 	}
+	if (line_str[0] != '\0')
+		pr_info("%s\n", line_str);
 }
+#else
+void msm_gemini_io_dump(int size)
+{
 
+}
+#endif
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h
index 1c8de19..aa6c4aa1 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -95,7 +95,7 @@
 int msm_gemini_hw_wait(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us);
 void msm_gemini_hw_delay(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us);
 int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, int m_cmds);
-void msm_gemini_hw_region_dump(int size);
+void msm_gemini_io_dump(int size);
 
 #define MSM_GEMINI_PIPELINE_CLK_128MHZ 128 /* 8MP  128MHz */
 #define MSM_GEMINI_PIPELINE_CLK_140MHZ 140 /* 9MP  140MHz */
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h
index ea13d68..2fe6038 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010, 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -171,6 +171,6 @@
 #define HWIO_JPEG_IRQ_STATUS_RMSK 0xffffffff
 
 #define HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_ADDR (GEMINI_REG_BASE + 0x00000034)
-#define HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_RMSK 0xffffff
+#define HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_RMSK 0xffffffff
 
 #endif /* MSM_GEMINI_HW_REG_H */
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c
index ed2222a..50c7284 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,8 @@
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <media/msm_gemini.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
 #include "msm_gemini_sync.h"
 #include "msm_gemini_core.h"
 #include "msm_gemini_platform.h"
@@ -23,6 +25,9 @@
 
 static int release_buf;
 
+/* size is based on 4k page size */
+static const int g_max_out_size = 0x7ff000;
+
 /*************** queue helper ****************/
 inline void msm_gemini_q_init(char const *name, struct msm_gemini_q *q_p)
 {
@@ -180,7 +185,7 @@
 {
 	int rc = 0;
 
-	GMN_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	pr_debug("%s:%d] buf_in %p", __func__, __LINE__, buf_in);
 
 	if (buf_in) {
 		buf_in->vbuf.framedone_len = buf_in->framedone_len;
@@ -266,19 +271,88 @@
 
 /*************** output queue ****************/
 
+int msm_gemini_get_out_buffer(struct msm_gemini_device *pgmn_dev,
+	struct msm_gemini_hw_buf *p_outbuf)
+{
+	int buf_size = 0;
+	int bytes_remaining = 0;
+	if (pgmn_dev->out_offset >= pgmn_dev->out_buf.y_len) {
+		GMN_PR_ERR("%s:%d] no more buffers", __func__, __LINE__);
+		return -EINVAL;
+	}
+	bytes_remaining = pgmn_dev->out_buf.y_len - pgmn_dev->out_offset;
+	buf_size = min(bytes_remaining, pgmn_dev->max_out_size);
+
+	pgmn_dev->out_frag_cnt++;
+	pr_debug("%s:%d] buf_size[%d] %d", __func__, __LINE__,
+		pgmn_dev->out_frag_cnt, buf_size);
+	p_outbuf->y_len = buf_size;
+	p_outbuf->y_buffer_addr = pgmn_dev->out_buf.y_buffer_addr +
+		pgmn_dev->out_offset;
+	pgmn_dev->out_offset += buf_size;
+	return 0;
+}
+
+int msm_gemini_outmode_single_we_pingpong_irq(
+	struct msm_gemini_device *pgmn_dev,
+	struct msm_gemini_core_buf *buf_in)
+{
+	int rc = 0;
+	struct msm_gemini_core_buf out_buf;
+	int frame_done = buf_in &&
+		buf_in->vbuf.type == MSM_GEMINI_EVT_FRAMEDONE;
+	pr_debug("%s:%d] framedone %d", __func__, __LINE__, frame_done);
+	if (!pgmn_dev->out_buf_set) {
+		pr_err("%s:%d] output buffer not set",
+			__func__, __LINE__);
+		return -EFAULT;
+	}
+	if (frame_done) {
+		/* send the buffer back */
+		pgmn_dev->out_buf.vbuf.framedone_len = buf_in->framedone_len;
+		pgmn_dev->out_buf.vbuf.type = MSM_GEMINI_EVT_FRAMEDONE;
+		rc = msm_gemini_q_in_buf(&pgmn_dev->output_rtn_q,
+			&pgmn_dev->out_buf);
+		if (rc) {
+			pr_err("%s:%d] cannot queue the output buffer",
+				 __func__, __LINE__);
+			return -EFAULT;
+		}
+		rc =  msm_gemini_q_wakeup(&pgmn_dev->output_rtn_q);
+		/* reset the output buffer since the ownership is
+			transferred to the rtn queue */
+		if (!rc)
+			pgmn_dev->out_buf_set = 0;
+	} else {
+		/* configure ping/pong */
+		rc = msm_gemini_get_out_buffer(pgmn_dev, &out_buf);
+		if (rc)
+			msm_gemini_core_we_buf_reset(&out_buf);
+		else
+			msm_gemini_core_we_buf_update(&out_buf);
+	}
+	return rc;
+}
+
 int msm_gemini_we_pingpong_irq(struct msm_gemini_device *pgmn_dev,
 	struct msm_gemini_core_buf *buf_in)
 {
 	int rc = 0;
 	struct msm_gemini_core_buf *buf_out;
 
-	GMN_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	pr_debug("%s:%d] Enter mode %d", __func__, __LINE__,
+		pgmn_dev->out_mode);
+
+	if (pgmn_dev->out_mode == MSM_GMN_OUTMODE_SINGLE)
+		return msm_gemini_outmode_single_we_pingpong_irq(pgmn_dev,
+			buf_in);
+
 	if (buf_in) {
-		GMN_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		pr_debug("%s:%d] 0x%08x %d\n", __func__, __LINE__,
 			(int) buf_in->y_buffer_addr, buf_in->y_len);
 		rc = msm_gemini_q_in_buf(&pgmn_dev->output_rtn_q, buf_in);
 	} else {
-		GMN_DBG("%s:%d] no output return buffer\n", __func__,
+		pr_debug("%s:%d] no output return buffer\n", __func__,
 			__LINE__);
 		rc = -1;
 		return rc;
@@ -291,7 +365,7 @@
 		kfree(buf_out);
 	} else {
 		msm_gemini_core_we_buf_reset(buf_in);
-		GMN_DBG("%s:%d] no output buffer\n", __func__, __LINE__);
+		pr_debug("%s:%d] no output buffer\n", __func__, __LINE__);
 		rc = -2;
 	}
 
@@ -339,6 +413,43 @@
 	return 0;
 }
 
+int msm_gemini_set_output_buf(struct msm_gemini_device *pgmn_dev,
+	void __user *arg)
+{
+	struct msm_gemini_buf buf_cmd;
+
+	if (pgmn_dev->out_buf_set) {
+		pr_err("%s:%d] outbuffer buffer already provided",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_gemini_buf))) {
+		pr_err("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	GMN_DBG("%s:%d] output addr 0x%08x len %d", __func__, __LINE__,
+		(int) buf_cmd.vaddr,
+		buf_cmd.y_len);
+
+	pgmn_dev->out_buf.y_buffer_addr = msm_gemini_platform_v2p(
+		buf_cmd.fd,
+		buf_cmd.y_len,
+		&pgmn_dev->out_buf.file,
+		&pgmn_dev->out_buf.handle);
+	if (!pgmn_dev->out_buf.y_buffer_addr) {
+		pr_err("%s:%d] cannot map the output address",
+			__func__, __LINE__);
+		return -EFAULT;
+	}
+	pgmn_dev->out_buf.y_len = buf_cmd.y_len;
+	pgmn_dev->out_buf.vbuf = buf_cmd;
+	pgmn_dev->out_buf_set = 1;
+
+	return 0;
+}
+
 int msm_gemini_output_buf_enqueue(struct msm_gemini_device *pgmn_dev,
 	void __user *arg)
 {
@@ -456,6 +567,7 @@
 	struct msm_gemini_core_buf *buf_p;
 	struct msm_gemini_buf buf_cmd;
 	int rc = 0;
+	struct msm_bus_scale_pdata *p_bus_scale_data = NULL;
 
 	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_gemini_buf))) {
 		GMN_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
@@ -484,9 +596,9 @@
 			return rc;
 		}
 	} else {
-	buf_p->y_buffer_addr    = msm_gemini_platform_v2p(buf_cmd.fd,
-		buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
-		&buf_p->handle)	+ buf_cmd.offset + buf_cmd.y_off;
+		buf_p->y_buffer_addr    = msm_gemini_platform_v2p(buf_cmd.fd,
+			buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
+			&buf_p->handle)	+ buf_cmd.offset + buf_cmd.y_off;
 	}
 	buf_p->y_len          = buf_cmd.y_len;
 
@@ -504,6 +616,30 @@
 		return -1;
 	}
 	buf_p->vbuf           = buf_cmd;
+	buf_p->vbuf.type      = MSM_GEMINI_EVT_RESET;
+
+	/* Set bus vectors */
+	p_bus_scale_data = (struct msm_bus_scale_pdata *)
+		pgmn_dev->pdev->dev.platform_data;
+	if (pgmn_dev->bus_perf_client &&
+		(MSM_GMN_OUTMODE_SINGLE == pgmn_dev->out_mode)) {
+		int rc;
+		struct msm_bus_paths *path = &(p_bus_scale_data->usecase[1]);
+		GMN_DBG("%s:%d] Update bus bandwidth", __func__, __LINE__);
+		if (pgmn_dev->op_mode & MSM_GEMINI_MODE_OFFLINE_ENCODE) {
+			path->vectors[0].ab = (buf_p->y_len + buf_p->cbcr_len) *
+				15 * 2;
+			path->vectors[0].ib = path->vectors[0].ab;
+			path->vectors[1].ab = 0;
+			path->vectors[1].ib = 0;
+		}
+		rc = msm_bus_scale_client_update_request(
+			pgmn_dev->bus_perf_client, 1);
+		if (rc < 0) {
+			GMN_PR_ERR("%s:%d] update_request fails %d",
+				__func__, __LINE__, rc);
+		}
+	}
 
 	msm_gemini_q_in(&pgmn_dev->input_buf_q, buf_p);
 
@@ -545,6 +681,9 @@
 int __msm_gemini_open(struct msm_gemini_device *pgmn_dev)
 {
 	int rc;
+	struct msm_bus_scale_pdata *p_bus_scale_data =
+		(struct msm_bus_scale_pdata *)pgmn_dev->pdev->dev.
+			platform_data;
 
 	mutex_lock(&pgmn_dev->lock);
 	if (pgmn_dev->open_count) {
@@ -576,7 +715,23 @@
 	msm_gemini_q_cleanup(&pgmn_dev->input_rtn_q);
 	msm_gemini_q_cleanup(&pgmn_dev->input_buf_q);
 	msm_gemini_core_init();
+	pgmn_dev->out_mode = MSM_GMN_OUTMODE_FRAGMENTED;
+	pgmn_dev->out_buf_set = 0;
+	pgmn_dev->out_offset = 0;
+	pgmn_dev->max_out_size = g_max_out_size;
+	pgmn_dev->out_frag_cnt = 0;
+	pgmn_dev->bus_perf_client = 0;
 
+	if (p_bus_scale_data) {
+		GMN_DBG("%s:%d] register bus client", __func__, __LINE__);
+		pgmn_dev->bus_perf_client =
+			msm_bus_scale_register_client(p_bus_scale_data);
+		if (!pgmn_dev->bus_perf_client) {
+			GMN_PR_ERR("%s:%d] bus client register failed",
+				__func__, __LINE__);
+			return -EINVAL;
+		}
+	}
 	GMN_DBG("%s:%d] success\n", __func__, __LINE__);
 	return rc;
 }
@@ -593,13 +748,23 @@
 	pgmn_dev->open_count--;
 	mutex_unlock(&pgmn_dev->lock);
 
-	msm_gemini_core_release(release_buf);
+	if (pgmn_dev->out_mode == MSM_GMN_OUTMODE_FRAGMENTED) {
+		msm_gemini_core_release(release_buf);
+	} else if (pgmn_dev->out_buf_set) {
+		msm_gemini_platform_p2v(pgmn_dev->out_buf.file,
+			&pgmn_dev->out_buf.handle);
+	}
 	msm_gemini_q_cleanup(&pgmn_dev->evt_q);
 	msm_gemini_q_cleanup(&pgmn_dev->output_rtn_q);
 	msm_gemini_outbuf_q_cleanup(&pgmn_dev->output_buf_q);
 	msm_gemini_q_cleanup(&pgmn_dev->input_rtn_q);
 	msm_gemini_outbuf_q_cleanup(&pgmn_dev->input_buf_q);
 
+	if (pgmn_dev->bus_perf_client) {
+		msm_bus_scale_unregister_client(pgmn_dev->bus_perf_client);
+		pgmn_dev->bus_perf_client = 0;
+	}
+
 	if (pgmn_dev->open_count)
 		GMN_PR_ERR(KERN_ERR "%s: multiple opens\n", __func__);
 
@@ -699,29 +864,63 @@
 		}
 	}
 
-	for (i = 0; i < 2; i++) {
-		buf_out_free[i] = msm_gemini_q_out(&pgmn_dev->output_buf_q);
+	if (pgmn_dev->out_mode == MSM_GMN_OUTMODE_FRAGMENTED) {
+		for (i = 0; i < 2; i++) {
+			buf_out_free[i] =
+				msm_gemini_q_out(&pgmn_dev->output_buf_q);
 
-		if (buf_out_free[i]) {
-			msm_gemini_core_we_buf_update(buf_out_free[i]);
-		} else if (i == 1) {
-			/* set the pong to same address as ping */
-			buf_out_free[0]->y_len >>= 1;
-			buf_out_free[0]->y_buffer_addr +=
-				buf_out_free[0]->y_len;
-			msm_gemini_core_we_buf_update(buf_out_free[0]);
-			/* since ping and pong are same buf release only once*/
-			release_buf = 0;
-		} else {
-			GMN_DBG("%s:%d] no output buffer\n",
-			__func__, __LINE__);
-			break;
+			if (buf_out_free[i]) {
+				msm_gemini_core_we_buf_update(buf_out_free[i]);
+			} else if (i == 1) {
+				/* set the pong to same address as ping */
+				buf_out_free[0]->y_len >>= 1;
+				buf_out_free[0]->y_buffer_addr +=
+					buf_out_free[0]->y_len;
+				msm_gemini_core_we_buf_update(buf_out_free[0]);
+				/*
+				 * since ping and pong are same buf
+				 * release only once
+				 */
+				release_buf = 0;
+			} else {
+				GMN_DBG("%s:%d] no output buffer\n",
+					__func__, __LINE__);
+				break;
+			}
 		}
+		for (i = 0; i < 2; i++)
+			kfree(buf_out_free[i]);
+	} else {
+		struct msm_gemini_core_buf out_buf;
+		/*
+		 * Since the same buffer is fragmented, p2v need not be
+		 * called for all the buffers
+		 */
+		release_buf = 0;
+		if (!pgmn_dev->out_buf_set) {
+			GMN_PR_ERR("%s:%d] output buffer not set",
+				__func__, __LINE__);
+			return -EFAULT;
+		}
+		/* configure ping */
+		rc = msm_gemini_get_out_buffer(pgmn_dev, &out_buf);
+		if (rc) {
+			GMN_PR_ERR("%s:%d] no output buffer for ping",
+				__func__, __LINE__);
+			return rc;
+		}
+		msm_gemini_core_we_buf_update(&out_buf);
+		/* configure pong */
+		rc = msm_gemini_get_out_buffer(pgmn_dev, &out_buf);
+		if (rc) {
+			GMN_DBG("%s:%d] no output buffer for pong",
+				__func__, __LINE__);
+			/* fall through to configure same buffer */
+		}
+		msm_gemini_core_we_buf_update(&out_buf);
+		msm_gemini_io_dump(0x150);
 	}
 
-	for (i = 0; i < 2; i++)
-		kfree(buf_out_free[i]);
-
 	rc = msm_gemini_ioctl_hw_cmds(pgmn_dev, arg);
 	GMN_DBG("%s:%d]\n", __func__, __LINE__);
 	return rc;
@@ -746,12 +945,22 @@
 	return rc;
 }
 
-int msm_gemini_ioctl_test_dump_region(struct msm_gemini_device *pgmn_dev,
-	unsigned long arg)
+int msm_gemini_ioctl_set_outmode(struct msm_gemini_device *pgmn_dev,
+	void * __user arg)
 {
-	GMN_DBG("%s:%d] Enter\n", __func__, __LINE__);
-	msm_gemini_hw_region_dump(arg);
-	return 0;
+	int rc = 0;
+	enum msm_gmn_out_mode mode;
+
+	if (copy_from_user(&mode, arg, sizeof(mode))) {
+		GMN_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+	GMN_DBG("%s:%d] mode %d", __func__, __LINE__, mode);
+
+	if ((mode == MSM_GMN_OUTMODE_FRAGMENTED)
+		|| (mode == MSM_GMN_OUTMODE_SINGLE))
+		pgmn_dev->out_mode = mode;
+	return rc;
 }
 
 long __msm_gemini_ioctl(struct msm_gemini_device *pgmn_dev,
@@ -790,8 +999,12 @@
 		break;
 
 	case MSM_GMN_IOCTL_OUTPUT_BUF_ENQUEUE:
-		rc = msm_gemini_output_buf_enqueue(pgmn_dev,
-			(void __user *) arg);
+		if (pgmn_dev->out_mode == MSM_GMN_OUTMODE_FRAGMENTED)
+			rc = msm_gemini_output_buf_enqueue(pgmn_dev,
+				(void __user *) arg);
+		else
+			rc = msm_gemini_set_output_buf(pgmn_dev,
+				(void __user *) arg);
 		break;
 
 	case MSM_GMN_IOCTL_OUTPUT_GET:
@@ -818,8 +1031,8 @@
 		rc = msm_gemini_ioctl_hw_cmds(pgmn_dev, (void __user *) arg);
 		break;
 
-	case MSM_GMN_IOCTL_TEST_DUMP_REGION:
-		rc = msm_gemini_ioctl_test_dump_region(pgmn_dev, arg);
+	case MSM_GMN_IOCTL_SET_MODE:
+		rc = msm_gemini_ioctl_set_outmode(pgmn_dev, (void __user *)arg);
 		break;
 
 	default:
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h
index d1a43e1..88e9615 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010,2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -74,6 +74,16 @@
 	struct msm_gemini_q input_buf_q;
 
 	struct v4l2_subdev subdev;
+	enum msm_gmn_out_mode out_mode;
+
+	/* single out mode parameters */
+	struct msm_gemini_hw_buf out_buf;
+	int out_offset;
+	int out_buf_set;
+	int max_out_size;
+	int out_frag_cnt;
+
+	uint32_t bus_perf_client;
 };
 
 int __msm_gemini_open(struct msm_gemini_device *pgmn_dev);
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 71087d9..4579cee 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -595,13 +595,18 @@
 	struct v4l2_event event;
 	struct msm_video_device *pvdev = video_drvdata(filep);
 	struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
-
 	BUG_ON(!pvdev);
 
 	atomic_sub_return(1, &pvdev->opened);
 
 	if (atomic_read(&pvdev->opened) == 0) {
 
+		camera_pack_event(filep, MSM_CAMERA_SET_PARM,
+			MSM_CAMERA_PRIV_DEL_STREAM, -1, &event);
+
+		/* Donot wait, imaging server may have crashed */
+		msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
+
 		camera_pack_event(filep, MSM_CAMERA_DEL_SESSION, 0, -1, &event);
 
 		/* Donot wait, imaging server may have crashed */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 04afec0..59858b5 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -256,6 +256,13 @@
 				buf_info->state ==
 					MSM_ISP_BUFFER_STATE_INITIALIZED)
 			continue;
+
+		if (!BUF_SRC(bufq->stream_id)) {
+			if (buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED ||
+			buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED)
+				buf_mgr->vb2_ops->put_buf(buf_info->vb2_buf,
+					bufq->session_id, bufq->stream_id);
+		}
 		msm_isp_unprepare_v4l2_buf(buf_mgr, buf_info);
 	}
 	return 0;
@@ -287,13 +294,15 @@
 					bufq->buf_client_count)
 					list_del_init(
 					&temp_buf_info->share_list);
-				if (temp_buf_info->buf_reuse_flag)
+				if (temp_buf_info->buf_reuse_flag) {
 					kfree(temp_buf_info);
-				else
+				} else {
 					*buf_info = temp_buf_info;
+					rc = 0;
+				}
 				spin_unlock_irqrestore(
 					&bufq->bufq_lock, flags);
-				return 0;
+				return rc;
 			}
 		}
 	}
@@ -342,6 +351,7 @@
 			(*buf_info)->buf_used[id] = 1;
 			(*buf_info)->buf_get_count = 1;
 			(*buf_info)->buf_put_count = 0;
+			(*buf_info)->buf_reuse_flag = 0;
 			list_add_tail(&(*buf_info)->share_list,
 						  &bufq->share_head);
 		}
@@ -375,7 +385,6 @@
 	switch (buf_info->state) {
 	case MSM_ISP_BUFFER_STATE_PREPARED:
 	case MSM_ISP_BUFFER_STATE_DEQUEUED:
-	case MSM_ISP_BUFFER_STATE_DISPATCHED:
 	case MSM_ISP_BUFFER_STATE_DIVERTED:
 		if (BUF_SRC(bufq->stream_id))
 			list_add_tail(&buf_info->list, &bufq->head);
@@ -385,6 +394,13 @@
 		buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
 		rc = 0;
 		break;
+	case MSM_ISP_BUFFER_STATE_DISPATCHED:
+		buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
+		rc = 0;
+		break;
+	case MSM_ISP_BUFFER_STATE_QUEUED:
+		rc = 0;
+		break;
 	default:
 		pr_err("%s: incorrect state = %d",
 			__func__, buf_info->state);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index a251f0a..679c5cb 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -142,14 +142,13 @@
 		return;
 
 	if (irq_status0 & BIT(0)) {
-		ISP_DBG("%s: PIX0 frame id: %lu\n", __func__,
-			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
-		msm_isp_sof_notify(vfe_dev, VFE_PIX_0, ts);
 		ISP_DBG("%s: SOF IRQ\n", __func__);
 		if (vfe_dev->axi_data.src_info[VFE_PIX_0].raw_stream_count > 0
 			&& vfe_dev->axi_data.src_info[VFE_PIX_0].
 			pix_stream_count == 0) {
 			msm_isp_sof_notify(vfe_dev, VFE_PIX_0, ts);
+			if (vfe_dev->axi_data.stream_update)
+				msm_isp_axi_stream_update(vfe_dev);
 			msm_isp_update_framedrop_reg(vfe_dev);
 		}
 	}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 5a17635..731056b 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -299,6 +299,8 @@
 			&& vfe_dev->axi_data.src_info[VFE_PIX_0].
 			pix_stream_count == 0) {
 			msm_isp_sof_notify(vfe_dev, VFE_PIX_0, ts);
+			if (vfe_dev->axi_data.stream_update)
+				msm_isp_axi_stream_update(vfe_dev);
 			msm_isp_update_framedrop_reg(vfe_dev);
 		}
 	}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 728e172..13160ee 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -399,7 +399,10 @@
 	uint32_t framedrop_period = msm_isp_get_framedrop_period(
 	   stream_cfg_cmd->frame_skip_pattern);
 
-	stream_info->framedrop_pattern = 0x1;
+	if (stream_cfg_cmd->frame_skip_pattern == SKIP_ALL)
+		stream_info->framedrop_pattern = 0x0;
+	else
+		stream_info->framedrop_pattern = 0x1;
 	stream_info->framedrop_period = framedrop_period - 1;
 
 	if (stream_cfg_cmd->init_frame_drop < framedrop_period) {
@@ -706,35 +709,60 @@
 	}
 }
 
-enum msm_isp_camif_update_state
-	msm_isp_update_camif_output_count(
-	struct vfe_device *vfe_dev,
+static enum msm_isp_camif_update_state
+	msm_isp_get_camif_update_state(struct vfe_device *vfe_dev,
 	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd)
 {
 	int i;
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	uint8_t cur_pix_count = axi_data->src_info[VFE_PIX_0].
-		pix_stream_count;
-	uint8_t cur_raw_count = axi_data->src_info[VFE_PIX_0].
-		raw_stream_count;
-	uint8_t pix_stream_cnt = 0;
+	uint8_t pix_stream_cnt = 0, cur_pix_stream_cnt;
+	cur_pix_stream_cnt =
+		axi_data->src_info[VFE_PIX_0].pix_stream_count +
+		axi_data->src_info[VFE_PIX_0].raw_stream_count;
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		stream_info =
 			&axi_data->stream_info[
 			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
 		if (stream_info->stream_src  < RDI_INTF_0)
 			pix_stream_cnt++;
+	}
+
+	if (pix_stream_cnt) {
+		if (cur_pix_stream_cnt == 0 && pix_stream_cnt &&
+			stream_cfg_cmd->cmd == START_STREAM)
+			return ENABLE_CAMIF;
+		else if (cur_pix_stream_cnt &&
+			(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
+			stream_cfg_cmd->cmd == STOP_STREAM)
+			return DISABLE_CAMIF;
+	}
+	return NO_UPDATE;
+}
+
+static void msm_isp_update_camif_output_count(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd)
+{
+	int i;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		stream_info =
+			&axi_data->stream_info[
+			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+		if (stream_info->stream_src >= RDI_INTF_0)
+			return;
 		if (stream_info->stream_src == PIX_ENCODER ||
-				stream_info->stream_src == PIX_VIEWFINDER) {
+			stream_info->stream_src == PIX_VIEWFINDER ||
+			stream_info->stream_src == IDEAL_RAW) {
 			if (stream_cfg_cmd->cmd == START_STREAM)
 				vfe_dev->axi_data.src_info[VFE_PIX_0].
 					pix_stream_count++;
 			else
 				vfe_dev->axi_data.src_info[VFE_PIX_0].
 					pix_stream_count--;
-		} else if (stream_info->stream_src == CAMIF_RAW ||
-				stream_info->stream_src == IDEAL_RAW) {
+		} else if (stream_info->stream_src == CAMIF_RAW) {
 			if (stream_cfg_cmd->cmd == START_STREAM)
 				vfe_dev->axi_data.src_info[VFE_PIX_0].
 					raw_stream_count++;
@@ -743,25 +771,6 @@
 					raw_stream_count--;
 		}
 	}
-	if (pix_stream_cnt) {
-		if ((cur_pix_count + cur_raw_count == 0) &&
-				(axi_data->src_info[VFE_PIX_0].
-				pix_stream_count +
-				axi_data->src_info[VFE_PIX_0].
-					raw_stream_count != 0)) {
-			return ENABLE_CAMIF;
-		}
-
-		if ((cur_pix_count + cur_raw_count != 0) &&
-				(axi_data->src_info[VFE_PIX_0].
-				pix_stream_count +
-				axi_data->src_info[VFE_PIX_0].
-					raw_stream_count == 0)) {
-			return DISABLE_CAMIF;
-		}
-	}
-
-	return NO_UPDATE;
 }
 
 void msm_camera_io_dump_2(void __iomem *addr, int size)
@@ -886,6 +895,20 @@
 	return rc;
 }
 
+static void msm_isp_deinit_stream_ping_pong_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	int i;
+	for (i = 0; i < 2; i++) {
+		struct msm_isp_buffer *buf;
+		buf = stream_info->buf[i];
+		if (buf)
+			vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
+				buf->bufq_handle, buf->buf_idx);
+	}
+}
+
 static void msm_isp_get_stream_wm_mask(
 	struct msm_vfe_axi_stream *stream_info,
 	uint32_t *wm_reload_mask)
@@ -937,6 +960,7 @@
 	vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask);
 	vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
 
+	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
 	if (camif_update == ENABLE_CAMIF)
 		vfe_dev->hw_info->vfe_ops.core_ops.
 			update_camif_state(vfe_dev, camif_update);
@@ -969,6 +993,13 @@
 	if (camif_update == DISABLE_CAMIF)
 		vfe_dev->hw_info->vfe_ops.core_ops.
 			update_camif_state(vfe_dev, DISABLE_CAMIF);
+	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
+
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		stream_info = &axi_data->stream_info[
+			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+		msm_isp_deinit_stream_ping_pong_reg(vfe_dev, stream_info);
+	}
 	return rc;
 }
 
@@ -990,8 +1021,7 @@
 		/*Configure UB*/
 		vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
 	}
-	camif_update =
-		msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
+	camif_update = msm_isp_get_camif_update_state(vfe_dev, stream_cfg_cmd);
 
 	if (stream_cfg_cmd->cmd == START_STREAM)
 		rc = msm_isp_start_axi_stream(
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index e08dea2..ce71235 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -206,7 +206,11 @@
 
 	framedrop_period = msm_isp_get_framedrop_period(
 	   stream_req_cmd->framedrop_pattern);
-	stream_info->framedrop_pattern = 0x1;
+
+	if (stream_req_cmd->framedrop_pattern == SKIP_ALL)
+		stream_info->framedrop_pattern = 0x0;
+	else
+		stream_info->framedrop_pattern = 0x1;
 	stream_info->framedrop_period = framedrop_period - 1;
 
 	if (!stream_info->composite_flag)
@@ -277,6 +281,20 @@
 	return rc;
 }
 
+static void msm_isp_deinit_stats_ping_pong_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_stats_stream *stream_info)
+{
+	int i;
+	struct msm_isp_buffer *buf;
+	for (i = 0; i < 2; i++) {
+		buf = stream_info->buf[i];
+		if (buf)
+			vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
+				buf->bufq_handle, buf->buf_idx);
+	}
+}
+
 void msm_isp_stats_stream_update(struct vfe_device *vfe_dev)
 {
 	int i;
@@ -415,6 +433,12 @@
 		vfe_dev->hw_info->vfe_ops.stats_ops.cfg_comp_mask(
 		   vfe_dev, comp_stats_mask, 0);
 	}
+
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
+		stream_info = &stats_data->stream_info[idx];
+		msm_isp_deinit_stats_ping_pong_reg(vfe_dev, stream_info);
+	}
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index c981901..613ad86 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -174,6 +174,8 @@
 	case EVERY_32FRAME:
 		return 32;
 		break;
+	case SKIP_ALL:
+		return 1;
 	default:
 		return 1;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 9f1c81a..be9f613 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -661,6 +661,7 @@
 			rc = -ETIMEDOUT;
 		}
 		if (rc < 0) {
+			pr_err("%s: rc = %d\n", __func__, rc);
 			mutex_unlock(&session->lock);
 			return rc;
 		}
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 35210a0..b0ff832 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -35,7 +35,7 @@
 	new_entry->vb2_buf = buf_mngr_dev->vb2_ops.get_buf(buf_info->session_id,
 		buf_info->stream_id);
 	if (!new_entry->vb2_buf) {
-		pr_err("%s:Get buf is null\n", __func__);
+		pr_debug("%s:Get buf is null\n", __func__);
 		kfree(new_entry);
 		return -EINVAL;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 8cdaa4b..5a174f5 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -860,7 +860,7 @@
 	rc = v4l2_subdev_call(cpp_dev->buf_mgr_subdev, core, ioctl,
 		buff_mgr_ops, buff_mgr_info);
 	if (rc < 0)
-		pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
+		pr_debug("%s: line %d rc = %d\n", __func__, __LINE__, rc);
 	return rc;
 }
 
@@ -1010,7 +1010,7 @@
 		&buff_mgr_info);
 	if (rc < 0) {
 		rc = -EAGAIN;
-		pr_err("error getting buffer rc:%d\n", rc);
+		pr_debug("error getting buffer rc:%d\n", rc);
 		goto ERROR2;
 	}
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
index e5093f8..ba964a2 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
@@ -14,7 +14,7 @@
 #define MSM_CSIPHY_HWREG_H
 
 /*MIPI CSI PHY registers*/
-#define MIPI_CSIPHY_HW_VERSION_ADDR              0x180
+#define MIPI_CSIPHY_HW_VERSION_ADDR              0x17C
 #define MIPI_CSIPHY_LNn_CFG1_ADDR                0x0
 #define MIPI_CSIPHY_LNn_CFG2_ADDR                0x4
 #define MIPI_CSIPHY_LNn_CFG3_ADDR                0x8
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
index 7dbbc03..e30e798 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
@@ -122,7 +122,7 @@
 				rc = PTR_ERR(clk_ptr[i]);
 				goto cam_clk_get_err;
 			}
-			if (clk_info[i].clk_rate >= 0) {
+			if (clk_info[i].clk_rate > 0) {
 				rc = clk_set_rate(clk_ptr[i],
 							clk_info[i].clk_rate);
 				if (rc < 0) {
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 8855e85..29369de 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -703,7 +703,8 @@
 	mpq_demux->dmxdev.capabilities =
 		DMXDEV_CAP_DUPLEX |
 		DMXDEV_CAP_PULL_MODE |
-		DMXDEV_CAP_INDEXING;
+		DMXDEV_CAP_INDEXING |
+		DMXDEV_CAP_TS_INSERTION;
 
 	mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
 	mpq_demux->dmxdev.demux->get_stc = mpq_tsif_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 43a65e9..5e14d0c 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1759,7 +1759,8 @@
 	mpq_demux->dmxdev.capabilities =
 		DMXDEV_CAP_DUPLEX |
 		DMXDEV_CAP_PULL_MODE |
-		DMXDEV_CAP_INDEXING;
+		DMXDEV_CAP_INDEXING |
+		DMXDEV_CAP_TS_INSERTION;
 
 	mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
 	mpq_demux->dmxdev.demux->get_stc = mpq_tspp_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index c306488..60e3cb4 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
@@ -143,7 +143,8 @@
 	mpq_demux->dmxdev.capabilities =
 		DMXDEV_CAP_DUPLEX |
 		DMXDEV_CAP_PULL_MODE |
-		DMXDEV_CAP_INDEXING;
+		DMXDEV_CAP_INDEXING |
+		DMXDEV_CAP_TS_INSERTION;
 
 	mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
 	mpq_demux->dmxdev.demux->get_caps = mpq_tspp_dmx_get_caps;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index f458a0a..1611a09 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -1143,6 +1143,11 @@
 			goto exit;
 		}
 		rc = msm_comm_try_state(inst, MSM_VIDC_CLOSE_DONE);
+		/* Clients rely on this event for joining poll thread.
+		 * This event should be returned even if firmware has
+		 * failed to respond */
+		dqevent.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
+		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 		break;
 	default:
 		dprintk(VIDC_ERR, "Unknown Decoder Command\n");
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 5f47ae1..66a3b6e 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -20,6 +20,7 @@
 
 #define MSM_VENC_DVC_NAME "msm_venc_8974"
 #define MIN_NUM_OUTPUT_BUFFERS 4
+#define MIN_NUM_CAPTURE_BUFFERS 4
 #define MIN_BIT_RATE 64000
 #define MAX_BIT_RATE 160000000
 #define DEFAULT_BIT_RATE 64000
@@ -777,16 +778,21 @@
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		*num_planes = 1;
 		buff_req = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
-		*num_buffers = buff_req->buffer_count_actual =
+		if (buff_req) {
+			*num_buffers = buff_req->buffer_count_actual =
 			max(*num_buffers, buff_req->buffer_count_actual);
-			if (*num_buffers > VIDEO_MAX_FRAME) {
-				dprintk(VIDC_ERR,
+		}
+		if (*num_buffers < MIN_NUM_CAPTURE_BUFFERS)
+			*num_buffers = MIN_NUM_CAPTURE_BUFFERS;
+
+		if (*num_buffers > VIDEO_MAX_FRAME) {
+			dprintk(VIDC_ERR,
 					"Failed : No of slices requested = %d"\
 					" Max supported slices = %d",
 					*num_buffers, VIDEO_MAX_FRAME);
-				rc = -EINVAL;
-				break;
-			}
+			rc = -EINVAL;
+			break;
+		}
 		ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
 				V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA);
 		if (ctrl)
@@ -1899,6 +1905,11 @@
 			dprintk(VIDC_ERR, "Failed to release persist buf:%d\n",
 				rc);
 		rc = msm_comm_try_state(inst, MSM_VIDC_CLOSE_DONE);
+		/* Clients rely on this event for joining poll thread.
+		 * This event should be returned even if firmware has
+		 * failed to respond */
+		dqevent.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
+		v4l2_event_queue_fh(&inst->event_handler, &dqevent);
 		break;
 	}
 	if (rc)
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 1ee9c67..feb239e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -582,7 +582,6 @@
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
 		signal_session_msg_receipt(cmd, inst);
-		queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_CLOSE_DONE);
 		inst->session = NULL;
 		show_stats(inst);
 	} else {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index ed4f317..b96a6dc 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -219,6 +219,9 @@
 	}
 	queue->qhdr_write_idx = new_write_idx;
 	*rx_req_is_set = (1 == queue->qhdr_rx_req) ? 1 : 0;
+	/*Memory barrier to make sure data is written before an
+	 * interupt is raised on venus.*/
+	mb();
 	dprintk(VIDC_DBG, "Out : ");
 	return 0;
 }
@@ -282,6 +285,7 @@
 	u32 packet_size_in_words, new_read_idx;
 	u32 *read_ptr;
 	struct vidc_iface_q_info *qinfo;
+	int rc = 0;
 
 	if (!info || !packet || !pb_tx_req_is_set) {
 		dprintk(VIDC_ERR, "Invalid Params");
@@ -293,6 +297,9 @@
 		dprintk(VIDC_WARN, "Queues have already been freed\n");
 		return -EINVAL;
 	}
+	/*Memory barrier to make sure data is valid before
+	 *reading it*/
+	mb();
 	queue = (struct hfi_queue_header *) qinfo->q_hdr;
 
 	if (!queue) {
@@ -317,17 +324,27 @@
 
 	new_read_idx = queue->qhdr_read_idx + packet_size_in_words;
 	dprintk(VIDC_DBG, "Read Ptr: %d", (u32) new_read_idx);
-	if (new_read_idx < queue->qhdr_q_size) {
-		memcpy(packet, read_ptr,
-			packet_size_in_words << 2);
-	} else {
-		new_read_idx -= queue->qhdr_q_size;
-		memcpy(packet, read_ptr,
+	if (((packet_size_in_words << 2) <= VIDC_IFACEQ_MED_PKT_SIZE)
+			&& queue->qhdr_read_idx <= queue->qhdr_q_size) {
+		if (new_read_idx < queue->qhdr_q_size) {
+			memcpy(packet, read_ptr,
+					packet_size_in_words << 2);
+		} else {
+			new_read_idx -= queue->qhdr_q_size;
+			memcpy(packet, read_ptr,
 			(packet_size_in_words - new_read_idx) << 2);
-		memcpy(packet + ((packet_size_in_words -
-			new_read_idx) << 2),
-			(u8 *)qinfo->q_array.align_virtual_addr,
-			new_read_idx << 2);
+			memcpy(packet + ((packet_size_in_words -
+					new_read_idx) << 2),
+					(u8 *)qinfo->q_array.align_virtual_addr,
+					new_read_idx << 2);
+		}
+	} else {
+		dprintk(VIDC_WARN,
+			"BAD packet received, read_idx: 0x%x, pkt_size: %d\n",
+			queue->qhdr_read_idx, packet_size_in_words << 2);
+		dprintk(VIDC_WARN, "Dropping this packet\n");
+		new_read_idx = queue->qhdr_write_idx;
+		rc = -ENODATA;
 	}
 
 	queue->qhdr_read_idx = new_read_idx;
@@ -340,7 +357,7 @@
 	*pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0;
 	venus_hfi_hal_sim_modify_msg_packet(packet);
 	dprintk(VIDC_DBG, "Out : ");
-	return 0;
+	return rc;
 }
 
 static int venus_hfi_alloc(void *mem, void *clnt, u32 size, u32 align,
@@ -1072,7 +1089,6 @@
 		if (!(dev->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK))
 			disable_irq_nosync(dev->hal_data->irq);
 		dev->intr_status = 0;
-		venus_hfi_interface_queues_release(dev);
 		mutex_unlock(&dev->clock_lock);
 	}
 	dprintk(VIDC_INFO, "HAL exited\n");
@@ -2783,6 +2799,7 @@
 		flush_workqueue(device->vidc_workq);
 		venus_hfi_disable_clks(device);
 		subsystem_put(device->resources.fw.cookie);
+		venus_hfi_interface_queues_release(dev);
 		venus_hfi_iommu_detach(device);
 		device->resources.fw.cookie = NULL;
 	}
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 075b391..1311752 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -113,8 +113,6 @@
 
 #define HFI_PROPERTY_SYS_OX_START			\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x0000)
-#define HFI_PROPERTY_SYS_IDLE_INDICATOR		\
-	(HFI_PROPERTY_SYS_OX_START + 0x001)
 
 #define HFI_PROPERTY_PARAM_OX_START				\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x1000)
@@ -333,7 +331,6 @@
 
 #define HFI_MSG_SYS_OX_START			\
 (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
-#define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_OX_START + 0x1)
 #define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
 #define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
 #define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 66eade1..6234dba 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -195,6 +195,8 @@
 	(HFI_PROPERTY_SYS_COMMON_START + 0x002)
 #define HFI_PROPERTY_SYS_CONFIG_VCODEC_CLKFREQ				\
 	(HFI_PROPERTY_SYS_COMMON_START + 0x003)
+#define HFI_PROPERTY_SYS_IDLE_INDICATOR         \
+	(HFI_PROPERTY_SYS_COMMON_START + 0x004)
 
 #define HFI_PROPERTY_PARAM_COMMON_START	\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x1000)
@@ -697,6 +699,7 @@
 #define HFI_MSG_SYS_DEBUG			(HFI_MSG_SYS_COMMON_START + 0x4)
 #define HFI_MSG_SYS_SESSION_INIT_DONE	(HFI_MSG_SYS_COMMON_START + 0x6)
 #define HFI_MSG_SYS_SESSION_END_DONE	(HFI_MSG_SYS_COMMON_START + 0x7)
+#define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_COMMON_START + 0x8)
 
 #define HFI_MSG_SESSION_COMMON_START		\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET +	\
diff --git a/drivers/media/platform/msm/wfd/enc-mfc-subdev.c b/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
index ceb0149..26e24da 100644
--- a/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,7 @@
 #include <media/msm/vcd_property.h>
 #include <linux/time.h>
 #include <linux/ktime.h>
+#include <linux/slab.h>
 
 #define VID_ENC_MAX_ENCODER_CLIENTS 1
 #define MAX_NUM_CTRLS 20
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 4f7fb44..722aa8f 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/wait.h>
+#include <linux/slab.h>
 #include <mach/iommu_domains.h>
 #include <media/msm_vidc.h>
 #include <media/v4l2-subdev.h>
diff --git a/drivers/media/platform/msm/wfd/mdp-4-subdev.c b/drivers/media/platform/msm/wfd/mdp-4-subdev.c
index 465ec21..2d79622 100644
--- a/drivers/media/platform/msm/wfd/mdp-4-subdev.c
+++ b/drivers/media/platform/msm/wfd/mdp-4-subdev.c
@@ -11,6 +11,7 @@
 *
 */
 #include <linux/msm_mdp.h>
+#include <linux/slab.h>
 #include <mach/iommu_domains.h>
 #include <media/videobuf2-core.h>
 #include "enc-subdev.h"
diff --git a/drivers/media/platform/msm/wfd/mdp-5-subdev.c b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
index 3c546d0..6399117 100644
--- a/drivers/media/platform/msm/wfd/mdp-5-subdev.c
+++ b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
@@ -11,6 +11,7 @@
 *
 */
 #include <linux/msm_mdp.h>
+#include <linux/slab.h>
 #include <mach/iommu_domains.h>
 #include <media/videobuf2-core.h>
 #include "enc-subdev.h"
diff --git a/drivers/media/platform/msm/wfd/mdp-dummy-subdev.c b/drivers/media/platform/msm/wfd/mdp-dummy-subdev.c
index 2242c76..10ba3c3 100644
--- a/drivers/media/platform/msm/wfd/mdp-dummy-subdev.c
+++ b/drivers/media/platform/msm/wfd/mdp-dummy-subdev.c
@@ -12,6 +12,7 @@
 */
 #include <linux/list.h>
 #include <linux/msm_mdp.h>
+#include <linux/slab.h>
 #include <media/videobuf2-core.h>
 
 #include "enc-subdev.h"
diff --git a/drivers/media/platform/msm/wfd/vsg-subdev.c b/drivers/media/platform/msm/wfd/vsg-subdev.c
index 90b1957..e0a46cc 100644
--- a/drivers/media/platform/msm/wfd/vsg-subdev.c
+++ b/drivers/media/platform/msm/wfd/vsg-subdev.c
@@ -13,6 +13,7 @@
 #include <linux/hrtimer.h>
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/slab.h>
 #include <media/videobuf2-core.h>
 #include "enc-subdev.h"
 #include "vsg-subdev.h"
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index b1b1980..2bb8375 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -18,10 +18,10 @@
 #include <linux/init.h>
 #include <linux/version.h>
 #include <linux/platform_device.h>
-
 #include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/time.h>
+#include <linux/slab.h>
 #include <mach/board.h>
 
 #include <media/v4l2-dev.h>
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 356aecb..5efd905 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -25,6 +25,7 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 #include <mach/cpuidle.h>
 
 #define BYTE_BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_BYTE))
@@ -226,9 +227,11 @@
 {
 	int ret;
 	int i;
+	char linebuf[128];
 	struct wcd9xxx *wcd9xxx = data;
 	int num_irq_regs = wcd9xxx_num_irq_regs(wcd9xxx);
-	u8 status[num_irq_regs];
+	u8 status[num_irq_regs], status1[num_irq_regs];
+	static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 1);
 
 	if (unlikely(wcd9xxx_lock_sleep(wcd9xxx) == false)) {
 		dev_err(wcd9xxx->dev, "Failed to hold suspend\n");
@@ -250,12 +253,17 @@
 	for (i = 0; i < num_irq_regs; i++)
 		status[i] &= ~wcd9xxx->irq_masks_cur[i];
 
+	memcpy(status1, status, sizeof(status1));
+
 	/* Find out which interrupt was triggered and call that interrupt's
 	 * handler function
 	 */
 	if (status[BIT_BYTE(WCD9XXX_IRQ_SLIMBUS)] &
-	    BYTE_BIT_MASK(WCD9XXX_IRQ_SLIMBUS))
+	    BYTE_BIT_MASK(WCD9XXX_IRQ_SLIMBUS)) {
 		wcd9xxx_irq_dispatch(wcd9xxx, WCD9XXX_IRQ_SLIMBUS);
+		status1[BIT_BYTE(WCD9XXX_IRQ_SLIMBUS)] &=
+		    ~BYTE_BIT_MASK(WCD9XXX_IRQ_SLIMBUS);
+	}
 
 	/* Since codec has only one hardware irq line which is shared by
 	 * codec's different internal interrupts, so it's possible master irq
@@ -264,13 +272,43 @@
 	 * machine's order */
 	for (i = WCD9XXX_IRQ_MBHC_INSERTION;
 	     i >= WCD9XXX_IRQ_MBHC_REMOVAL; i--) {
-		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i))
+		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
 			wcd9xxx_irq_dispatch(wcd9xxx, i);
+			status1[BIT_BYTE(i)] &= ~BYTE_BIT_MASK(i);
+		}
 	}
 	for (i = WCD9XXX_IRQ_BG_PRECHARGE; i < wcd9xxx->codec_type->num_irqs;
 	     i++) {
-		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i))
+		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
 			wcd9xxx_irq_dispatch(wcd9xxx, i);
+			status1[BIT_BYTE(i)] &= ~BYTE_BIT_MASK(i);
+		}
+	}
+
+	/*
+	 * As a failsafe if unhandled irq is found, clear it to prevent
+	 * interrupt storm.
+	 * Note that we can say there was an unhandled irq only when no irq
+	 * handled by nested irq handler since Taiko supports qdsp as irqs'
+	 * destination for few irqs.  Therefore driver shouldn't clear pending
+	 * irqs when few handled while few others not.
+	 */
+	if (unlikely(!memcmp(status, status1, sizeof(status)))) {
+		if (__ratelimit(&ratelimit)) {
+			pr_warn("%s: Unhandled irq found\n", __func__);
+			hex_dump_to_buffer(status, sizeof(status), 16, 1,
+					   linebuf, sizeof(linebuf), false);
+			pr_warn("%s: status0 : %s\n", __func__, linebuf);
+			hex_dump_to_buffer(status1, sizeof(status1), 16, 1,
+					   linebuf, sizeof(linebuf), false);
+			pr_warn("%s: status1 : %s\n", __func__, linebuf);
+		}
+
+		memset(status, 0xff, num_irq_regs);
+		wcd9xxx_bulk_write(wcd9xxx, WCD9XXX_A_INTR_CLEAR0,
+				   num_irq_regs, status);
+		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+			wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_MODE, 0x02);
 	}
 	wcd9xxx_unlock_sleep(wcd9xxx);
 
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index ac77bfb..fcadc30 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -52,6 +52,8 @@
 #define QSEE_VERSION_02			0x402000
 #define QSEE_VERSION_03			0x403000
 #define QSEE_VERSION_04			0x404000
+#define QSEE_VERSION_05			0x405000
+
 
 
 #define QSEOS_CHECK_VERSION_CMD		0x00001803
@@ -2381,9 +2383,11 @@
 
 	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
 	ireq.flags = flags;
+	ireq.qsee_command_id = QSEOS_GENERATE_KEY;
 
 	__qseecom_enable_clk(CLK_QSEE);
-	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_GENERATE_KEY,
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
 				&ireq, sizeof(struct qseecom_key_generate_ireq),
 				&resp, sizeof(resp));
 	if (ret) {
@@ -2395,10 +2399,19 @@
 	switch (resp.result) {
 	case QSEOS_RESULT_SUCCESS:
 		break;
+	case QSEOS_RESULT_FAIL_KEY_ID_EXISTS:
+		break;
 	case QSEOS_RESULT_INCOMPLETE:
 		ret = __qseecom_process_incomplete_cmd(data, &resp);
-		if (ret)
-			pr_err("process_incomplete_cmd FAILED\n");
+		if (ret) {
+			if (resp.result == QSEOS_RESULT_FAIL_KEY_ID_EXISTS) {
+				pr_warn("process_incomplete_cmd return Key ID exits.\n");
+				ret = 0;
+			} else {
+				pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
+					resp.result);
+			}
+		}
 		break;
 	case QSEOS_RESULT_FAILURE:
 	default:
@@ -2425,9 +2438,11 @@
 
 	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
 	ireq.flags = flags;
+	ireq.qsee_command_id = QSEOS_DELETE_KEY;
 
 	__qseecom_enable_clk(CLK_QSEE);
-	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_DELETE_KEY,
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
 				&ireq, sizeof(struct qseecom_key_delete_ireq),
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
@@ -2442,7 +2457,8 @@
 	case QSEOS_RESULT_INCOMPLETE:
 		ret = __qseecom_process_incomplete_cmd(data, &resp);
 		if (ret)
-			pr_err("process_incomplete_cmd FAILED\n");
+			pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
+					resp.result);
 		break;
 	case QSEOS_RESULT_FAILURE:
 	default:
@@ -2474,10 +2490,14 @@
 		__qseecom_enable_clk(CLK_CE_DRV);
 
 	memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
+	ireq.qsee_command_id = QSEOS_SET_KEY;
 	ireq.ce = set_key_para->ce_hw;
 	ireq.pipe = set_key_para->pipe;
 	ireq.flags = set_key_para->flags;
 
+	/* set PIPE_ENC */
+	ireq.pipe_type = QSEOS_PIPE_ENC;
+
 	if (set_key_para->set_clear_key_flag ==
 			QSEECOM_SET_CE_KEY_CMD)
 		memcpy((void *)ireq.hash, (void *)set_key_para->hash32,
@@ -2485,11 +2505,22 @@
 	else
 		memset((void *)ireq.hash, 0, QSEECOM_HASH_SIZE);
 
-	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_SET_KEY,
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
 				&ireq, sizeof(struct qseecom_key_select_ireq),
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
-		pr_err("scm call to set key failed : %d\n", ret);
+		pr_err("scm call to set QSEOS_PIPE_ENC key failed : %d\n", ret);
+		return ret;
+	}
+
+	/* set PIPE_ENC_XTS */
+	ireq.pipe_type = QSEOS_PIPE_ENC_XTS;
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
+				&ireq, sizeof(struct qseecom_key_select_ireq),
+				&resp, sizeof(struct qseecom_command_scm_resp));
+	if (ret) {
+		pr_err("scm call to set QSEOS_PIPE_ENC_XTS key failed : %d\n",
+			ret);
 		return ret;
 	}
 
@@ -2499,7 +2530,8 @@
 	case QSEOS_RESULT_INCOMPLETE:
 		ret = __qseecom_process_incomplete_cmd(data, &resp);
 		if (ret)
-			pr_err("process_incomplete_cmd FAILED\n");
+			pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
+					resp.result);
 		break;
 	case QSEOS_RESULT_FAILURE:
 	default:
@@ -2878,6 +2910,11 @@
 		break;
 	}
 	case QSEECOM_IOCTL_CREATE_KEY_REQ: {
+		if (qseecom.qsee_version < QSEE_VERSION_05) {
+			pr_err("Create Key feature not supported in qsee version %u\n",
+				qseecom.qsee_version);
+			return -EINVAL;
+		}
 		data->released = true;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
@@ -2890,6 +2927,11 @@
 		break;
 	}
 	case QSEECOM_IOCTL_WIPE_KEY_REQ: {
+		if (qseecom.qsee_version < QSEE_VERSION_05) {
+			pr_err("Wipe Key feature not supported in qsee version %u\n",
+				qseecom.qsee_version);
+			return -EINVAL;
+		}
 		data->released = true;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 9f12142..21e65b9 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -228,6 +228,7 @@
 	md = mmc_blk_get(dev_to_disk(dev));
 	card = md->queue.card;
 
+	mmc_rpm_hold(card->host, &card->dev);
 	mmc_claim_host(card->host);
 
 	ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
@@ -240,6 +241,7 @@
 		card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
 
 	mmc_release_host(card->host);
+	mmc_rpm_release(card->host, &card->dev);
 
 	if (!ret) {
 		pr_info("%s: Locking boot partition ro until next power on\n",
@@ -602,7 +604,7 @@
 	md = mmc_blk_get(bdev->bd_disk);
 	if (!md) {
 		err = -EINVAL;
-		goto cmd_done;
+		goto blk_err;
 	}
 
 	card = md->queue.card;
@@ -707,6 +709,7 @@
 
 cmd_done:
 	mmc_blk_put(md);
+blk_err:
 	kfree(idata->buf);
 	kfree(idata);
 	return err;
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 8b7e0bd..903decf 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -176,9 +176,11 @@
 	if (val > host->f_max)
 		return -EINVAL;
 
+	mmc_rpm_hold(host, &host->class_dev);
 	mmc_claim_host(host);
 	mmc_set_clock(host, (unsigned int) val);
 	mmc_release_host(host);
+	mmc_rpm_release(host, &host->class_dev);
 
 	return 0;
 }
@@ -208,6 +210,7 @@
 	if (!host || (val < host->f_min))
 		goto out;
 
+	mmc_rpm_hold(host, &host->class_dev);
 	mmc_claim_host(host);
 	if (host->bus_ops && host->bus_ops->change_bus_speed) {
 		old_freq = host->f_max;
@@ -219,6 +222,7 @@
 			host->f_max = old_freq;
 	}
 	mmc_release_host(host);
+	mmc_rpm_release(host, &host->class_dev);
 out:
 	return err;
 }
@@ -286,6 +290,7 @@
 	u32		status;
 	int		ret;
 
+	mmc_rpm_hold(card->host, &card->dev);
 	mmc_claim_host(card->host);
 
 	ret = mmc_send_status(data, &status);
@@ -293,6 +298,7 @@
 		*val = status;
 
 	mmc_release_host(card->host);
+	mmc_rpm_release(card->host, &card->dev);
 
 	return ret;
 }
@@ -319,9 +325,11 @@
 		goto out_free;
 	}
 
+	mmc_rpm_hold(card->host, &card->dev);
 	mmc_claim_host(card->host);
 	err = mmc_send_ext_csd(card, ext_csd);
 	mmc_release_host(card->host);
+	mmc_rpm_release(card->host, &card->dev);
 	if (err)
 		goto out_free;
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 9c30cd1..3f3687b 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -4683,10 +4683,10 @@
 	}
 	/* Now save the sps pipe handle */
 	ep->pipe_handle = sps_pipe_handle;
-	pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"
-		" desc_fifo.phys_base=0x%x\n", mmc_hostname(host->mmc),
+	pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"\
+		" desc_fifo.phys_base=%pa\n", mmc_hostname(host->mmc),
 		__func__, is_producer ? "READ" : "WRITE",
-		(u32)sps_pipe_handle, sps_config->desc.phys_base);
+		(u32)sps_pipe_handle, &sps_config->desc.phys_base);
 	goto out;
 
 reg_event_err:
@@ -4929,11 +4929,8 @@
 	host->bam_base = ioremap(host->bam_memres->start,
 				resource_size(host->bam_memres));
 	if (!host->bam_base) {
-		pr_err("%s: BAM ioremap() failed!!! phys_addr=0x%x,"
-			" size=0x%x", mmc_hostname(host->mmc),
-			host->bam_memres->start,
-			(host->bam_memres->end -
-			host->bam_memres->start));
+		pr_err("%s: BAM ioremap() failed!!! resource: %pr\n",
+			mmc_hostname(host->mmc), host->bam_memres);
 		rc = -ENOMEM;
 		goto out;
 	}
@@ -4954,7 +4951,7 @@
 	 */
 	bam.summing_threshold = SPS_MIN_XFER_SIZE;
 	/* SPS driver wll handle the SDCC BAM IRQ */
-	bam.irq = (u32)host->bam_irqres->start;
+	bam.irq = host->bam_irqres->start;
 	bam.manage = SPS_BAM_MGR_LOCAL;
 	bam.callback = msmsdcc_sps_bam_global_irq_cb;
 	bam.user = (void *)host;
@@ -4990,10 +4987,8 @@
 	if (rc)
 		goto cons_conn_err;
 
-	pr_info("%s: Qualcomm MSM SDCC-BAM at 0x%016llx irq %d\n",
-		mmc_hostname(host->mmc),
-		(unsigned long long)host->bam_memres->start,
-		(unsigned int)host->bam_irqres->start);
+	pr_info("%s: Qualcomm MSM SDCC-BAM at %pr %pr\n",
+		mmc_hostname(host->mmc), host->bam_memres, host->bam_irqres);
 	goto out;
 
 cons_conn_err:
@@ -5180,15 +5175,16 @@
 }
 
 static void msmsdcc_print_regs(const char *name, void __iomem *base,
-			       u32 phys_base, unsigned int no_of_regs)
+				resource_size_t phys_base,
+				unsigned int no_of_regs)
 {
 	unsigned int i;
 
 	if (!base)
 		return;
 
-	pr_err("===== %s: Register Dumps @phys_base=0x%x, @virt_base=0x%x"
-		" =====\n", name, phys_base, (u32)base);
+	pr_err("===== %s: Register Dumps @phys_base=%pa, @virt_base=0x%x"\
+		" =====\n", name, &phys_base, (u32)base);
 	for (i = 0; i < no_of_regs; i = i + 4) {
 		pr_err("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x\n", i*4,
 			(u32)readl_relaxed(base + i*4),
@@ -6275,10 +6271,8 @@
 	mmc->clk_scaling.polling_delay_ms = 100;
 	mmc->caps2 |= MMC_CAP2_CLK_SCALE;
 
-	pr_info("%s: Qualcomm MSM SDCC-core at 0x%016llx irq %d,%d dma %d"
-		" dmacrcri %d\n", mmc_hostname(mmc),
-		(unsigned long long)core_memres->start,
-		(unsigned int) core_irqres->start,
+	pr_info("%s: Qualcomm MSM SDCC-core %pr %pr,%d dma %d dmacrcri %d\n",
+		mmc_hostname(mmc), core_memres, core_irqres,
 		(unsigned int) plat->status_irq, host->dma.channel,
 		host->dma.crci);
 
@@ -6300,11 +6294,11 @@
 
 	if (is_dma_mode(host) && host->dma.channel != -1
 			&& host->dma.crci != -1) {
-		pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
-		       mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
-		pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
-		       mmc_hostname(mmc), host->dma.cmd_busaddr,
-		       host->dma.cmdptr_busaddr);
+		pr_info("%s: DM non-cached buffer at %p, dma_addr: %pa\n",
+		       mmc_hostname(mmc), host->dma.nc, &host->dma.nc_busaddr);
+		pr_info("%s: DM cmd busaddr: %pa, cmdptr busaddr: %pa\n",
+		       mmc_hostname(mmc), &host->dma.cmd_busaddr,
+		       &host->dma.cmdptr_busaddr);
 	} else if (is_sps_mode(host)) {
 		pr_info("%s: SPS-BAM data transfer mode available\n",
 			mmc_hostname(mmc));
diff --git a/drivers/mmc/host/msm_sdcc_dml.c b/drivers/mmc/host/msm_sdcc_dml.c
index 91ab7e3..2562436 100644
--- a/drivers/mmc/host/msm_sdcc_dml.c
+++ b/drivers/mmc/host/msm_sdcc_dml.c
@@ -166,17 +166,13 @@
 		host->dml_base = ioremap(host->dml_memres->start,
 					resource_size(host->dml_memres));
 		if (!host->dml_base) {
-			pr_err("%s: DML ioremap() failed!!! phys_addr=0x%x,"
-				" size=0x%x", mmc_hostname(host->mmc),
-				host->dml_memres->start,
-				(host->dml_memres->end -
-				host->dml_memres->start));
+			pr_err("%s: DML ioremap() failed!!! %pr\n",
+				mmc_hostname(host->mmc), host->dml_memres);
 			rc = -ENOMEM;
 			goto out;
 		}
-		pr_info("%s: Qualcomm MSM SDCC-DML at 0x%016llx\n",
-			mmc_hostname(host->mmc),
-			(unsigned long long)host->dml_memres->start);
+		pr_info("%s: Qualcomm MSM SDCC-DML %pr\n",
+			mmc_hostname(host->mmc), host->dml_memres);
 	}
 
 	dml_base = host->dml_base;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 49222b9..89730b0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -38,6 +38,7 @@
 #include <linux/dma-mapping.h>
 #include <mach/gpio.h>
 #include <mach/msm_bus.h>
+#include <linux/iopoll.h>
 
 #include "sdhci-pltfm.h"
 
@@ -81,6 +82,31 @@
 #define CORE_CLK_PWRSAVE	(1 << 1)
 #define CORE_IO_PAD_PWR_SWITCH	(1 << 16)
 
+#define CORE_MCI_DATA_CTRL	0x2C
+#define CORE_MCI_DPSM_ENABLE	(1 << 0)
+
+#define CORE_TESTBUS_CONFIG	0x0CC
+#define CORE_TESTBUS_ENA	(1 << 3)
+#define CORE_TESTBUS_SEL2	(1 << 4)
+
+/*
+ * Waiting until end of potential AHB access for data:
+ * 16 AHB cycles (160ns for 100MHz and 320ns for 50MHz) +
+ * delay on AHB (2us) = maximum 2.32us
+ * Taking x10 times margin
+ */
+#define CORE_AHB_DATA_DELAY_US  23
+/* Waiting until end of potential AHB access for descriptor:
+ * Single (1 AHB cycle) + delay on AHB bus = max 2us
+ * INCR4 (4 AHB cycles) + delay on AHB bus = max 2us
+ * Single (1 AHB cycle) + delay on AHB bus = max 2us
+ * Total 8 us delay with margin
+ */
+#define CORE_AHB_DESC_DELAY_US  8
+
+#define CORE_SDCC_DEBUG_REG	0x124
+#define CORE_DEBUG_REG_AHB_HTRANS       (3 << 12)
+
 /* 8KB descriptors */
 #define SDHCI_MSM_MAX_SEGMENTS  (1 << 13)
 #define SDHCI_MSM_MMC_CLK_GATE_DELAY	200 /* msecs */
@@ -2044,6 +2070,51 @@
 	return 0;
 }
 
+/*
+ * sdhci_msm_disable_data_xfer - disable undergoing AHB bus data transfer
+ *
+ * Write 0 to bit 0 in MCI_DATA_CTL (offset 0x2C) - clearing TxActive bit by
+ * access to legacy registers. It will stop current burst and prevent start of
+ * the next on.
+ *
+ * Polling CORE_AHB_DATA_DELAY_US timeout, by reading bit 13:12 until they are 0
+ * in CORE_SDCC_DEBUG_REG (offset 0x124) will validate that AHB burst was
+ * completed and a new one didn't start.
+ *
+ * Waiting for 4us while AHB finishes descriptors fetch.
+ */
+static void sdhci_msm_disable_data_xfer(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	u32 value;
+	int ret;
+
+	value = readl_relaxed(msm_host->core_mem + CORE_MCI_DATA_CTRL);
+	value &= ~(u32)CORE_MCI_DPSM_ENABLE;
+	writel_relaxed(value, msm_host->core_mem + CORE_MCI_DATA_CTRL);
+
+	/* Enable the test bus for device slot */
+	writel_relaxed(CORE_TESTBUS_ENA | CORE_TESTBUS_SEL2,
+			msm_host->core_mem + CORE_TESTBUS_CONFIG);
+
+	ret = readl_poll_timeout_noirq(msm_host->core_mem
+			+ CORE_SDCC_DEBUG_REG, value,
+			!(value & CORE_DEBUG_REG_AHB_HTRANS),
+			CORE_AHB_DATA_DELAY_US, 1);
+	if (ret) {
+		pr_err("%s: %s: can't stop ongoing AHB bus access by ADMA\n",
+				mmc_hostname(host->mmc), __func__);
+		BUG();
+	}
+	/* Disable the test bus for device slot */
+	value = readl_relaxed(msm_host->core_mem + CORE_TESTBUS_CONFIG);
+	value &= ~CORE_TESTBUS_ENA;
+	writel_relaxed(value, msm_host->core_mem + CORE_TESTBUS_CONFIG);
+
+	udelay(CORE_AHB_DESC_DELAY_US);
+}
+
 static struct sdhci_ops sdhci_msm_ops = {
 	.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
 	.check_power_status = sdhci_msm_check_power_status,
@@ -2054,6 +2125,7 @@
 	.platform_bus_voting = sdhci_msm_bus_voting,
 	.get_min_clock = sdhci_msm_get_min_clock,
 	.get_max_clock = sdhci_msm_get_max_clock,
+	.disable_data_xfer = sdhci_msm_disable_data_xfer,
 };
 
 static int __devinit sdhci_msm_probe(struct platform_device *pdev)
@@ -2064,7 +2136,8 @@
 	struct resource *core_memres = NULL;
 	int ret = 0, dead = 0;
 	u32 vdd_max_current;
-	u32 host_version;
+	u16 host_version;
+	u32 pwr;
 
 	pr_debug("%s: Enter %s\n", dev_name(&pdev->dev), __func__);
 	msm_host = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_msm_host),
@@ -2173,7 +2246,21 @@
 	}
 
 	/* Set SW_RST bit in POWER register (Offset 0x0) */
-	writel_relaxed(CORE_SW_RST, msm_host->core_mem + CORE_POWER);
+	writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |
+			CORE_SW_RST, msm_host->core_mem + CORE_POWER);
+	/*
+	 * SW reset can take upto 10HCLK + 15MCLK cycles.
+	 * Calculating based on min clk rates (hclk = 27MHz,
+	 * mclk = 400KHz) it comes to ~40us. Let's poll for
+	 * max. 1ms for reset completion.
+	 */
+	ret = readl_poll_timeout(msm_host->core_mem + CORE_POWER,
+			pwr, !(pwr & CORE_SW_RST), 100, 10);
+
+	if (ret) {
+		dev_err(&pdev->dev, "reset failed (%d)\n", ret);
+		goto vreg_deinit;
+	}
 	/* Set HC_MODE_EN bit in HC_MODE register */
 	writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
 
@@ -2192,7 +2279,7 @@
 	host->quirks2 |= SDHCI_QUIRK2_BROKEN_PRESET_VALUE;
 	host->quirks2 |= SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT;
 
-	host_version = readl_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
+	host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
 	dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
 		host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
 		  SDHCI_VENDOR_VER_SHIFT));
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0549b4a..3efea77 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2126,7 +2126,49 @@
 
 static int sdhci_stop_request(struct mmc_host *mmc)
 {
-	return -ENOSYS;
+	struct sdhci_host *host = mmc_priv(mmc);
+	unsigned long flags;
+	struct mmc_data *data;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (!host->mrq || !host->data)
+		goto out;
+
+	data = host->data;
+
+	if (host->ops->disable_data_xfer)
+		host->ops->disable_data_xfer(host);
+
+	sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+
+	if (host->flags & SDHCI_REQ_USE_DMA) {
+		if (host->flags & SDHCI_USE_ADMA) {
+			sdhci_adma_table_post(host, data);
+		} else {
+			if (!data->host_cookie)
+				dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+					     data->sg_len,
+					     (data->flags & MMC_DATA_READ) ?
+					     DMA_FROM_DEVICE : DMA_TO_DEVICE);
+		}
+	}
+	del_timer(&host->timer);
+	host->mrq = NULL;
+	host->cmd = NULL;
+	host->data = NULL;
+out:
+	spin_unlock_irqrestore(&host->lock, flags);
+	return 0;
+}
+
+static unsigned int sdhci_get_xfer_remain(struct mmc_host *mmc)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	u32 present_state = 0;
+
+	present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
+
+	return present_state & SDHCI_DOING_WRITE;
 }
 
 static const struct mmc_host_ops sdhci_ops = {
@@ -2143,6 +2185,7 @@
 	.enable		= sdhci_enable,
 	.disable	= sdhci_disable,
 	.stop_request = sdhci_stop_request,
+	.get_xfer_remain = sdhci_get_xfer_remain,
 };
 
 /*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index c6bef8a..a3d8442 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -286,6 +286,7 @@
 	void	(*toggle_cdr)(struct sdhci_host *host, bool enable);
 	unsigned int	(*get_max_segments)(void);
 	void	(*platform_bus_voting)(struct sdhci_host *host, u32 enable);
+	void    (*disable_data_xfer)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 570c257..0b04bbf 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -691,9 +691,9 @@
 
 	/* Lookup the 'APPS' partition's first page address */
 	for (i = 0; i < FLASH_PTABLE_MAX_PARTS_V4; i++) {
-		if (!strncmp("apps", ptable.part_entry[i].name,
-				strlen(ptable.part_entry[i].name))) {
-			page_address = ptable.part_entry[i].offset << 6;
+		if (!strncmp("apps", mtd_part[i].name,
+				strlen(mtd_part[i].name))) {
+			page_address = mtd_part[i].offset << 6;
 			break;
 		}
 	}
@@ -1458,7 +1458,7 @@
 	int ret;
 	struct mtd_oob_ops ops;
 
-	ops.mode = MTD_OPS_PLACE_OOB;
+	ops.mode = MTD_OPS_AUTO_OOB;
 	ops.len = len;
 	ops.retlen = 0;
 	ops.ooblen = 0;
@@ -1643,7 +1643,7 @@
 	int ret;
 	struct mtd_oob_ops ops;
 
-	ops.mode = MTD_OPS_PLACE_OOB;
+	ops.mode = MTD_OPS_AUTO_OOB;
 	ops.len = len;
 	ops.retlen = 0;
 	ops.ooblen = 0;
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index f6b8051..3c3a62b 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -49,18 +49,11 @@
 /**
  * struct ecm_ipa_dev - main driver context parameters
  * @net: network interface struct implemented by this driver
- * @folder: debugfs folder for various debuging switches
+ * @directory: debugfs directory for various debuging switches
  * @tx_enable: flag that enable/disable Tx path to continue to IPA
  * @rx_enable: flag that enable/disable Rx path to continue to IPA
  * @rm_enable: flag that enable/disable Resource manager request prior to Tx
  * @dma_enable: flag that allow on-the-fly DMA mode for IPA
- * @tx_file: saved debugfs entry to allow cleanup
- * @rx_file: saved debugfs entry to allow cleanup
- * @rm_file: saved debugfs entry to allow cleanup
- * @outstanding_file:  saved debugfs entry to allow cleanup
- * @outstanding_high_file saved debugfs entry to allow cleanup
- * @outstanding_low_file saved debugfs entry to allow cleanup
- * @dma_file: saved debugfs entry to allow cleanup
  * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table
  * @eth_ipv6_hdr_hdl: saved handle for ipv6 header-insertion table
  * @usb_to_ipa_hdl: save handle for IPA pipe operations
@@ -72,18 +65,11 @@
  */
 struct ecm_ipa_dev {
 	struct net_device *net;
-	bool tx_enable;
-	bool rx_enable;
-	bool rm_enable;
+	u32 tx_enable;
+	u32 rx_enable;
+	u32  rm_enable;
 	bool dma_enable;
-	struct dentry *folder;
-	struct dentry *tx_file;
-	struct dentry *rx_file;
-	struct dentry *rm_file;
-	struct dentry *outstanding_high_file;
-	struct dentry *outstanding_low_file;
-	struct dentry *dma_file;
-	struct dentry *outstanding_file;
+	struct dentry *directory;
 	uint32_t eth_ipv4_hdr_hdl;
 	uint32_t eth_ipv6_hdr_hdl;
 	u32 usb_to_ipa_hdl;
@@ -127,9 +113,6 @@
 static void ecm_ipa_deregister_properties(void);
 static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *dev);
 static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *dev);
-static int ecm_ipa_debugfs_tx_open(struct inode *inode, struct file *file);
-static int ecm_ipa_debugfs_rx_open(struct inode *inode, struct file *file);
-static int ecm_ipa_debugfs_rm_open(struct inode *inode, struct file *file);
 static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file);
 static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file);
 static ssize_t ecm_ipa_debugfs_enable_read(struct file *file,
@@ -149,25 +132,12 @@
 	.ndo_start_xmit = ecm_ipa_start_xmit,
 	.ndo_set_mac_address = eth_mac_addr,
 };
+
 static const struct ethtool_ops ops = {
 	.get_drvinfo = eth_get_drvinfo,
 	.get_link = ethtool_op_get_link,
 };
-const struct file_operations ecm_ipa_debugfs_tx_ops = {
-	.open = ecm_ipa_debugfs_tx_open,
-	.read = ecm_ipa_debugfs_enable_read,
-	.write = ecm_ipa_debugfs_enable_write,
-};
-const struct file_operations ecm_ipa_debugfs_rx_ops = {
-	.open = ecm_ipa_debugfs_rx_open,
-	.read = ecm_ipa_debugfs_enable_read,
-	.write = ecm_ipa_debugfs_enable_write,
-};
-const struct file_operations ecm_ipa_debugfs_rm_ops = {
-	.open = ecm_ipa_debugfs_rm_open,
-	.read = ecm_ipa_debugfs_enable_read,
-	.write = ecm_ipa_debugfs_enable_write,
-};
+
 const struct file_operations ecm_ipa_debugfs_dma_ops = {
 	.open = ecm_ipa_debugfs_dma_open,
 	.read = ecm_ipa_debugfs_enable_read,
@@ -209,6 +179,8 @@
 	NULL_CHECK(ecm_ipa_rx_dp_notify);
 	NULL_CHECK(ecm_ipa_tx_dp_notify);
 	NULL_CHECK(priv);
+	pr_debug("rx_cb=0x%p, tx_cb=0x%p priv=0x%p\n",
+			ecm_ipa_rx_dp_notify, ecm_ipa_tx_dp_notify, *priv);
 	net = alloc_etherdev(sizeof(struct ecm_ipa_dev));
 	if (!net) {
 		ret = -ENOMEM;
@@ -430,8 +402,8 @@
 	NULL_CHECK(dev);
 	net = dev->net;
 	NULL_CHECK(net);
-	pr_debug("host_ethaddr=%pM device_ethaddr=%pM\n",
-					host_ethaddr, device_ethaddr);
+	pr_debug("priv=0x%p, host_ethaddr=%pM device_ethaddr=%pM\n",
+					priv, host_ethaddr, device_ethaddr);
 	result = ecm_ipa_create_rm_resource(dev);
 	if (result) {
 		ECM_IPA_ERROR("fail on RM create\n");
@@ -482,8 +454,8 @@
 	struct ecm_ipa_dev *dev = priv;
 	ECM_IPA_LOG_ENTRY();
 	NULL_CHECK(priv);
-	pr_debug("usb_to_ipa_hdl = %d, ipa_to_usb_hdl = %d\n",
-					usb_to_ipa_hdl, ipa_to_usb_hdl);
+	pr_debug("usb_to_ipa_hdl = %d, ipa_to_usb_hdl = %d, priv=0x%p\n",
+					usb_to_ipa_hdl, ipa_to_usb_hdl, priv);
 	if (!usb_to_ipa_hdl || usb_to_ipa_hdl >= IPA_CLIENT_MAX) {
 		ECM_IPA_ERROR("usb_to_ipa_hdl(%d) is not a valid ipa handle\n",
 				usb_to_ipa_hdl);
@@ -512,6 +484,7 @@
 	struct ecm_ipa_dev *dev = priv;
 	ECM_IPA_LOG_ENTRY();
 	NULL_CHECK(dev);
+	pr_debug("priv=0x%p\n", priv);
 	netif_carrier_off(dev->net);
 	ECM_IPA_LOG_EXIT();
 	return 0;
@@ -632,6 +605,7 @@
 {
 	struct ecm_ipa_dev *dev = priv;
 	ECM_IPA_LOG_ENTRY();
+	pr_debug("priv=0x%p\n", priv);
 	if (!dev) {
 		ECM_IPA_ERROR("dev NULL pointer\n");
 		return;
@@ -640,10 +614,9 @@
 	ecm_ipa_destory_rm_resource(dev);
 	ecm_ipa_debugfs_destroy(dev);
 
-	if (!dev->net) {
-		unregister_netdev(dev->net);
-		free_netdev(dev->net);
-	}
+	unregister_netdev(dev->net);
+	free_netdev(dev->net);
+
 	pr_debug("cleanup done\n");
 	ecm_ipa_ctx = NULL;
 	ECM_IPA_LOG_EXIT();
@@ -708,9 +681,6 @@
 		goto resource_busy;
 	}
 
-	pr_debug("Before sending packet the outstanding packets counter is %d\n",
-				atomic_read(&dev->outstanding_pkts));
-
 	if (atomic_read(&dev->outstanding_pkts) >= dev->outstanding_high) {
 		pr_debug("Outstanding high boundary reached (%d)- stopping queue\n",
 				dev->outstanding_high);
@@ -809,40 +779,11 @@
 				dev->outstanding_low);
 		netif_wake_queue(dev->net);
 	}
-	pr_debug("After Tx-complete the outstanding packets counter is %d\n",
-				atomic_read(&dev->outstanding_pkts));
 
 	dev_kfree_skb_any(skb);
 	return;
 }
 
-static int ecm_ipa_debugfs_tx_open(struct inode *inode, struct file *file)
-{
-	struct ecm_ipa_dev *dev = inode->i_private;
-	ECM_IPA_LOG_ENTRY();
-	file->private_data = &(dev->tx_enable);
-	ECM_IPA_LOG_ENTRY();
-	return 0;
-}
-
-static int ecm_ipa_debugfs_rx_open(struct inode *inode, struct file *file)
-{
-	struct ecm_ipa_dev *dev = inode->i_private;
-	ECM_IPA_LOG_ENTRY();
-	file->private_data = &(dev->rx_enable);
-	ECM_IPA_LOG_EXIT();
-	return 0;
-}
-
-static int ecm_ipa_debugfs_rm_open(struct inode *inode, struct file *file)
-{
-	struct ecm_ipa_dev *dev = inode->i_private;
-	ECM_IPA_LOG_ENTRY();
-	file->private_data = &(dev->rm_enable);
-	ECM_IPA_LOG_EXIT();
-	return 0;
-}
-
 static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file)
 {
 	struct ecm_ipa_dev *dev = inode->i_private;
@@ -937,82 +878,74 @@
 
 static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *dev)
 {
-	const mode_t flags = S_IRUGO | S_IWUGO;
+	const mode_t flags_read_write = S_IRUGO | S_IWUGO;
 	const mode_t flags_read_only = S_IRUGO;
+	struct dentry *file;
 
-	int ret = -EINVAL;
 	ECM_IPA_LOG_ENTRY();
+
 	if (!dev)
 		return -EINVAL;
-	dev->folder = debugfs_create_dir("ecm_ipa", NULL);
-	if (!dev->folder) {
-		ECM_IPA_ERROR("could not create debugfs folder entry\n");
-		ret = -EFAULT;
-		goto fail_folder;
-	}
-	dev->tx_file = debugfs_create_file("tx_enable", flags, dev->folder, dev,
-		   &ecm_ipa_debugfs_tx_ops);
-	if (!dev->tx_file) {
-		ECM_IPA_ERROR("could not create debugfs tx file\n");
-		ret = -EFAULT;
-		goto fail_file;
-	}
-	dev->rx_file = debugfs_create_file("rx_enable", flags, dev->folder, dev,
-			&ecm_ipa_debugfs_rx_ops);
-	if (!dev->rx_file) {
-		ECM_IPA_ERROR("could not create debugfs rx file\n");
-		ret = -EFAULT;
-		goto fail_file;
-	}
-	dev->rm_file = debugfs_create_file("rm_enable", flags, dev->folder, dev,
-			&ecm_ipa_debugfs_rm_ops);
-	if (!dev->rm_file) {
-		ECM_IPA_ERROR("could not create debugfs rm file\n");
-		ret = -EFAULT;
-		goto fail_file;
-	}
-	dev->dma_file = debugfs_create_file("dma_enable", flags, dev->folder,
-			dev, &ecm_ipa_debugfs_dma_ops);
-	if (!dev->dma_file) {
-		ECM_IPA_ERROR("could not create debugfs dma file\n");
-		ret = -EFAULT;
-		goto fail_file;
-	}
 
-	dev->outstanding_high_file = debugfs_create_u8("outstanding_high",
-			flags, dev->folder, &dev->outstanding_high);
-	if (!dev->outstanding_high_file) {
+	dev->directory = debugfs_create_dir("ecm_ipa", NULL);
+	if (!dev->directory) {
+		ECM_IPA_ERROR("could not create debugfs directory entry\n");
+		goto fail_directory;
+	}
+	file = debugfs_create_bool("tx_enable", flags_read_write,
+			dev->directory, &dev->tx_enable);
+	if (!file) {
+		ECM_IPA_ERROR("could not create debugfs tx file\n");
+		goto fail_file;
+	}
+	file = debugfs_create_bool("rx_enable", flags_read_write,
+			dev->directory, &dev->rx_enable);
+	if (!file) {
+		ECM_IPA_ERROR("could not create debugfs rx file\n");
+		goto fail_file;
+	}
+	file = debugfs_create_bool("rm_enable", flags_read_write,
+			dev->directory, &dev->rm_enable);
+	if (!file) {
+		ECM_IPA_ERROR("could not create debugfs rm file\n");
+		goto fail_file;
+	}
+	file = debugfs_create_u8("outstanding_high", flags_read_write,
+			dev->directory, &dev->outstanding_high);
+	if (!file) {
 		ECM_IPA_ERROR("could not create outstanding_high file\n");
-		ret = -EFAULT;
 		goto fail_file;
 	}
-	dev->outstanding_low_file = debugfs_create_u8("outstanding_low",
-			flags, dev->folder, &dev->outstanding_low);
-	if (!dev->outstanding_low_file) {
+	file = debugfs_create_u8("outstanding_low", flags_read_write,
+			dev->directory, &dev->outstanding_low);
+	if (!file) {
 		ECM_IPA_ERROR("could not create outstanding_low file\n");
-		ret = -EFAULT;
 		goto fail_file;
 	}
-	dev->outstanding_file = debugfs_create_file("outstanding",
-			flags_read_only, dev->folder, dev,
-			&ecm_ipa_debugfs_atomic_ops);
-	if (!dev->outstanding_file) {
+	file = debugfs_create_file("dma_enable", flags_read_write,
+			dev->directory, dev, &ecm_ipa_debugfs_dma_ops);
+	if (!file) {
+		ECM_IPA_ERROR("could not create debugfs dma file\n");
+		goto fail_file;
+	}
+	file = debugfs_create_file("outstanding", flags_read_only,
+			dev->directory, dev, &ecm_ipa_debugfs_atomic_ops);
+	if (!file) {
 		ECM_IPA_ERROR("could not create outstanding file\n");
-		ret = -EFAULT;
 		goto fail_file;
 	}
 
 	ECM_IPA_LOG_EXIT();
 	return 0;
 fail_file:
-	debugfs_remove_recursive(dev->folder);
-fail_folder:
-	return ret;
+	debugfs_remove_recursive(dev->directory);
+fail_directory:
+	return -EFAULT;
 }
 
 static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *dev)
 {
-	debugfs_remove_recursive(dev->folder);
+	debugfs_remove_recursive(dev->directory);
 }
 
 static void eth_get_drvinfo(struct net_device *net,
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 0970505..5f0ba94 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -214,7 +214,7 @@
 #if defined(CONFIG_MICROBLAZE)
 	dev->archdata.dma_mask = 0xffffffffUL;
 #endif
-	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	dev->dev.coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
 	dev->dev.bus = &platform_bus_type;
 	dev->dev.platform_data = platform_data;
 
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index 1b33dc0..bbf9719 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -491,10 +491,6 @@
 				__func__);
 		return -EFAULT;
 	}
-	ret = sps_device_reset(a2_mux_ctx->a2_device_handle);
-	if (ret)
-		IPAERR("%s: device reset failed ret = %d\n",
-		       __func__, ret);
 	memset(&connect_params, 0, sizeof(struct ipa_sys_connect_params));
 	connect_params.client = IPA_CLIENT_A2_TETHERED_CONS;
 	connect_params.notify = ipa_tethered_notify;
@@ -606,12 +602,6 @@
 				__func__, ret);
 		return ret;
 	}
-	ret = sps_device_reset(a2_mux_ctx->a2_device_handle);
-	if (ret) {
-		IPAERR("%s: device reset failed ret = %d\n",
-			__func__, ret);
-		return ret;
-	}
 	verify_tx_queue_is_empty(__func__);
 	(void) ipa_rm_release_resource(IPA_RM_RESOURCE_A2_PROD);
 	if (a2_mux_ctx->disconnect_ack)
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 466e694..35b2561 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -778,66 +778,6 @@
 	return ret;
 }
 
-static int ipa_handle_tx_poll_for_pipe(struct ipa_sys_context *sys,
-		bool process_all)
-{
-	struct ipa_tx_pkt_wrapper *tx_pkt, *t;
-	struct sps_iovec iov;
-	unsigned long irq_flags;
-	int ret;
-	int cnt = 0;
-
-	do {
-		iov.addr = 0;
-		ret = sps_get_iovec(sys->ep->ep_hdl, &iov);
-		if (ret) {
-			pr_err("%s: sps_get_iovec failed %d\n", __func__, ret);
-			break;
-		}
-		if (!iov.addr)
-			break;
-		spin_lock_irqsave(&sys->spinlock, irq_flags);
-		tx_pkt = list_first_entry(&sys->head_desc_list,
-					  struct ipa_tx_pkt_wrapper, link);
-		spin_unlock_irqrestore(&sys->spinlock, irq_flags);
-
-		switch (tx_pkt->cnt) {
-		case 1:
-			ipa_wq_write_done(&tx_pkt->work);
-			++cnt;
-			break;
-		case 0xFFFF:
-			/* reached end of set */
-			spin_lock_irqsave(&sys->spinlock, irq_flags);
-			list_for_each_entry_safe(tx_pkt, t,
-						 &sys->wait_desc_list, link) {
-				list_del(&tx_pkt->link);
-				list_add(&tx_pkt->link, &sys->head_desc_list);
-			}
-			tx_pkt =
-			   list_first_entry(&sys->head_desc_list,
-					    struct ipa_tx_pkt_wrapper, link);
-			spin_unlock_irqrestore(&sys->spinlock, irq_flags);
-			ipa_wq_write_done(&tx_pkt->work);
-			++cnt;
-			break;
-		default:
-			/* keep looping till reach the end of the set */
-			spin_lock_irqsave(&sys->spinlock,
-					  irq_flags);
-			list_del(&tx_pkt->link);
-			list_add_tail(&tx_pkt->link,
-				      &sys->wait_desc_list);
-			spin_unlock_irqrestore(&sys->spinlock,
-					       irq_flags);
-			++cnt;
-			break;
-		}
-	} while (process_all);
-
-	return cnt;
-}
-
 static void ipa_poll_function(struct work_struct *work)
 {
 	int ret;
@@ -857,13 +797,15 @@
 
 		/* check all the system pipes for tx comp and rx avail */
 		if (ipa_ctx->sys[IPA_A5_LAN_WAN_IN].ep->valid)
-			cnt |= ipa_handle_rx_core(false, true);
+			cnt |= ipa_handle_rx_core(
+					&ipa_ctx->sys[IPA_A5_LAN_WAN_IN],
+					false, true);
 
 		for (i = 0; i < num_tx_pipes; i++)
 			if (ipa_ctx->sys[tx_pipes[i]].ep->valid)
-				cnt |= ipa_handle_tx_poll_for_pipe(
+				cnt |= ipa_handle_tx_core(
 						&ipa_ctx->sys[tx_pipes[i]],
-						false);
+						false, true);
 	} while (cnt);
 
 	/* re-post the poll work */
@@ -1666,10 +1608,6 @@
 
 	IPADBG("polling_mode=%u delay_ms=%u\n", polling_mode, polling_delay_ms);
 	ipa_ctx->polling_mode = polling_mode;
-	if (ipa_ctx->polling_mode)
-		atomic_set(&ipa_ctx->curr_polling_state, 1);
-	else
-		atomic_set(&ipa_ctx->curr_polling_state, 0);
 	IPADBG("hdr_lcl=%u ip4_rt=%u ip6_rt=%u ip4_flt=%u ip6_flt=%u\n",
 	       hdr_tbl_lcl, ip4_rt_tbl_lcl, ip6_rt_tbl_lcl, ip4_flt_tbl_lcl,
 	       ip6_flt_tbl_lcl);
@@ -1891,7 +1829,10 @@
 			ipa_ctx->sys[i].ep = &ipa_ctx->ep[i];
 		else
 			ipa_ctx->sys[i].ep = &ipa_ctx->ep[WLAN_AMPDU_TX_EP];
-		INIT_LIST_HEAD(&ipa_ctx->sys[i].wait_desc_list);
+		if (ipa_ctx->polling_mode)
+			atomic_set(&ipa_ctx->sys[i].curr_polling_state, 1);
+		else
+			atomic_set(&ipa_ctx->sys[i].curr_polling_state, 0);
 	}
 
 	ipa_ctx->rx_wq = create_singlethread_workqueue("ipa rx wq");
@@ -1901,7 +1842,8 @@
 		goto fail_rx_wq;
 	}
 
-	ipa_ctx->tx_wq = create_singlethread_workqueue("ipa tx wq");
+	ipa_ctx->tx_wq = alloc_workqueue("ipa tx wq", WQ_MEM_RECLAIM |
+			WQ_CPU_INTENSIVE, 2);
 	if (!ipa_ctx->tx_wq) {
 		IPAERR(":fail to create tx wq\n");
 		result = -ENOMEM;
diff --git a/drivers/platform/msm/ipa/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_debugfs.c
index fb69817..b11c7da 100644
--- a/drivers/platform/msm/ipa/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_debugfs.c
@@ -104,6 +104,7 @@
 static struct dentry *dfile_stats;
 static struct dentry *dfile_dbg_cnt;
 static struct dentry *dfile_msg;
+static struct dentry *dfile_ip4_nat;
 static char dbg_buff[IPA_MAX_MSG_LEN];
 static s8 ep_reg_idx;
 
@@ -608,6 +609,7 @@
 			"rx=%u\n"
 			"rx_repl_repost=%u\n"
 			"x_intr_repost=%u\n"
+			"x_intr_repost_tx=%u\n"
 			"rx_q_len=%u\n"
 			"act_clnt=%u\n"
 			"con_clnt_bmap=0x%x\n"
@@ -622,6 +624,7 @@
 			ipa_ctx->stats.rx_pkts,
 			ipa_ctx->stats.rx_repl_repost,
 			ipa_ctx->stats.x_intr_repost,
+			ipa_ctx->stats.x_intr_repost_tx,
 			ipa_ctx->stats.rx_q_len,
 			ipa_ctx->ipa_active_clients,
 			connect,
@@ -720,6 +723,238 @@
 	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
 }
 
+static ssize_t ipa_read_nat4(struct file *file,
+		char __user *ubuf, size_t count,
+		loff_t *ppos) {
+
+#define ENTRY_U32_FIELDS 8
+#define NAT_ENTRY_ENABLE 0x8000
+#define NAT_ENTRY_RST_FIN_BIT 0x4000
+#define BASE_TABLE 0
+#define EXPANSION_TABLE 1
+
+	u32 *base_tbl, *indx_tbl;
+	u32 tbl_size, *tmp;
+	u32 value, i, j, rule_id;
+	u16 enable, tbl_entry, flag;
+	int nbytes, cnt;
+
+	cnt = 0;
+	value = ipa_ctx->nat_mem.public_ip_addr;
+	nbytes = scnprintf(dbg_buff + cnt,
+				IPA_MAX_MSG_LEN,
+				"Table IP Address:%d.%d.%d.%d\n",
+				((value & 0xFF000000) >> 24),
+				((value & 0x00FF0000) >> 16),
+				((value & 0x0000FF00) >> 8),
+				((value & 0x000000FF)));
+	cnt += nbytes;
+
+	nbytes = scnprintf(dbg_buff + cnt,
+				IPA_MAX_MSG_LEN,
+				"Table Size:%d\n",
+				ipa_ctx->nat_mem.size_base_tables);
+	cnt += nbytes;
+
+	nbytes = scnprintf(dbg_buff + cnt,
+				IPA_MAX_MSG_LEN,
+				"Expansion Table Size:%d\n",
+				ipa_ctx->nat_mem.size_expansion_tables);
+	cnt += nbytes;
+
+	if (!ipa_ctx->nat_mem.is_sys_mem) {
+		nbytes = scnprintf(dbg_buff + cnt,
+					IPA_MAX_MSG_LEN,
+					"Not supported for local(shared) memory\n");
+		cnt += nbytes;
+
+		return simple_read_from_buffer(ubuf, count,
+						ppos, dbg_buff, cnt);
+	}
+
+
+	/* Print Base tables */
+	rule_id = 0;
+	for (j = 0; j < 2; j++) {
+		if (j == BASE_TABLE) {
+			tbl_size = ipa_ctx->nat_mem.size_base_tables;
+			base_tbl = (u32 *)ipa_ctx->nat_mem.ipv4_rules_addr;
+
+			nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN,
+					"\nBase Table:\n");
+			cnt += nbytes;
+		} else {
+			tbl_size = ipa_ctx->nat_mem.size_expansion_tables;
+			base_tbl =
+			 (u32 *)ipa_ctx->nat_mem.ipv4_expansion_rules_addr;
+
+			nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN,
+					"\nExpansion Base Table:\n");
+			cnt += nbytes;
+		}
+
+		if (base_tbl != NULL) {
+			for (i = 0; i <= tbl_size; i++, rule_id++) {
+				tmp = base_tbl;
+				value = tmp[4];
+				enable = ((value & 0xFFFF0000) >> 16);
+
+				if (enable & NAT_ENTRY_ENABLE) {
+					nbytes = scnprintf(dbg_buff + cnt,
+								IPA_MAX_MSG_LEN,
+								"Rule:%d ",
+								rule_id);
+					cnt += nbytes;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"Private_IP:%d.%d.%d.%d ",
+						((value & 0xFF000000) >> 24),
+						((value & 0x00FF0000) >> 16),
+						((value & 0x0000FF00) >> 8),
+						((value & 0x000000FF)));
+					cnt += nbytes;
+					tmp++;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"Target_IP:%d.%d.%d.%d ",
+						((value & 0xFF000000) >> 24),
+						((value & 0x00FF0000) >> 16),
+						((value & 0x0000FF00) >> 8),
+						((value & 0x000000FF)));
+					cnt += nbytes;
+					tmp++;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"Next_Index:%d  Public_Port:%d ",
+						(value & 0x0000FFFF),
+						((value & 0xFFFF0000) >> 16));
+					cnt += nbytes;
+					tmp++;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"Private_Port:%d  Target_Port:%d ",
+						(value & 0x0000FFFF),
+						((value & 0xFFFF0000) >> 16));
+					cnt += nbytes;
+					tmp++;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"IP-CKSM-delta:0x%x  ",
+						(value & 0x0000FFFF));
+					cnt += nbytes;
+
+					flag = ((value & 0xFFFF0000) >> 16);
+					if (flag & NAT_ENTRY_RST_FIN_BIT) {
+						nbytes =
+						 scnprintf(dbg_buff + cnt,
+							  IPA_MAX_MSG_LEN,
+								"IP_CKSM_delta:0x%x  Flags:%s ",
+							  (value & 0x0000FFFF),
+								"Direct_To_A5");
+						cnt += nbytes;
+					} else {
+						nbytes =
+						 scnprintf(dbg_buff + cnt,
+							IPA_MAX_MSG_LEN,
+							"IP_CKSM_delta:0x%x  Flags:%s ",
+							(value & 0x0000FFFF),
+							"Fwd_to_route");
+						cnt += nbytes;
+					}
+					tmp++;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"Time_stamp:0x%x Proto:%d ",
+						(value & 0x00FFFFFF),
+						((value & 0xFF000000) >> 27));
+					cnt += nbytes;
+					tmp++;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"Prev_Index:%d  Indx_tbl_entry:%d ",
+						(value & 0x0000FFFF),
+						((value & 0xFFFF0000) >> 16));
+					cnt += nbytes;
+					tmp++;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"TCP_UDP_cksum_delta:0x%x\n",
+						((value & 0xFFFF0000) >> 16));
+					cnt += nbytes;
+				}
+
+				base_tbl += ENTRY_U32_FIELDS;
+
+			}
+		}
+	}
+
+	/* Print Index tables */
+	rule_id = 0;
+	for (j = 0; j < 2; j++) {
+		if (j == BASE_TABLE) {
+			tbl_size = ipa_ctx->nat_mem.size_base_tables;
+			indx_tbl = (u32 *)ipa_ctx->nat_mem.index_table_addr;
+
+			nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN,
+					"\nIndex Table:\n");
+			cnt += nbytes;
+		} else {
+			tbl_size = ipa_ctx->nat_mem.size_expansion_tables;
+			indx_tbl =
+			 (u32 *)ipa_ctx->nat_mem.index_table_expansion_addr;
+
+			nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN,
+					"\nExpansion Index Table:\n");
+			cnt += nbytes;
+		}
+
+		if (indx_tbl != NULL) {
+			for (i = 0; i <= tbl_size; i++, rule_id++) {
+				tmp = indx_tbl;
+				value = *tmp;
+				tbl_entry = (value & 0x0000FFFF);
+
+				if (tbl_entry) {
+					nbytes = scnprintf(dbg_buff + cnt,
+								IPA_MAX_MSG_LEN,
+								"Rule:%d ",
+								rule_id);
+					cnt += nbytes;
+
+					value = *tmp;
+					nbytes = scnprintf(dbg_buff + cnt,
+						IPA_MAX_MSG_LEN,
+						"Table_Entry:%d  Next_Index:%d\n",
+						tbl_entry,
+						((value & 0xFFFF0000) >> 16));
+					cnt += nbytes;
+				}
+
+				indx_tbl++;
+			}
+		}
+	}
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
+}
+
 const struct file_operations ipa_gen_reg_ops = {
 	.read = ipa_read_gen_reg,
 };
@@ -763,6 +998,10 @@
 	.write = ipa_write_dbg_cnt,
 };
 
+const struct file_operations ipa_nat4_ops = {
+	.read = ipa_read_nat4,
+};
+
 void ipa_debugfs_init(void)
 {
 	const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
@@ -860,6 +1099,13 @@
 		goto fail;
 	}
 
+	dfile_ip4_nat = debugfs_create_file("ip4_nat", read_only_mode, dent,
+			0, &ipa_nat4_ops);
+	if (!dfile_ip4_nat || IS_ERR(dfile_ip4_nat)) {
+		IPAERR("fail to create file for debug_fs ip4 nat\n");
+		goto fail;
+	}
+
 	return;
 
 fail:
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 228c77fe..67728c2 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -20,14 +20,15 @@
 #define list_next_entry(pos, member) \
 	list_entry(pos->member.next, typeof(*pos), member)
 #define IPA_LAST_DESC_CNT 0xFFFF
-#define POLLING_INACTIVITY 40
-#define POLLING_MIN_SLEEP 950
-#define POLLING_MAX_SLEEP 1050
+#define POLLING_INACTIVITY_RX 40
+#define POLLING_MIN_SLEEP_RX 950
+#define POLLING_MAX_SLEEP_RX 1050
+#define POLLING_INACTIVITY_TX 40
+#define POLLING_MIN_SLEEP_TX 400
+#define POLLING_MAX_SLEEP_TX 500
 
 static void replenish_rx_work_func(struct work_struct *work);
 static struct delayed_work replenish_rx_work;
-static void switch_to_intr_work_func(struct work_struct *work);
-static struct delayed_work switch_to_intr_work;
 static void ipa_wq_handle_rx(struct work_struct *work);
 static DECLARE_WORK(rx_work, ipa_wq_handle_rx);
 
@@ -47,57 +48,164 @@
 void ipa_wq_write_done(struct work_struct *work)
 {
 	struct ipa_tx_pkt_wrapper *tx_pkt;
-	struct ipa_tx_pkt_wrapper *next_pkt;
 	struct ipa_tx_pkt_wrapper *tx_pkt_expected;
 	unsigned long irq_flags;
-	struct ipa_mem_buffer mult = { 0 };
-	int i;
-	u32 cnt;
 
 	tx_pkt = container_of(work, struct ipa_tx_pkt_wrapper, work);
-	cnt = tx_pkt->cnt;
-	IPADBG("cnt=%d\n", cnt);
 
-	if (unlikely(cnt == 0))
+	if (unlikely(tx_pkt == NULL))
 		WARN_ON(1);
+	WARN_ON(tx_pkt->cnt != 1);
 
-	if (cnt > 1 && cnt != IPA_LAST_DESC_CNT)
-		mult = tx_pkt->mult;
+	spin_lock_irqsave(&tx_pkt->sys->spinlock, irq_flags);
+	tx_pkt_expected = list_first_entry(&tx_pkt->sys->head_desc_list,
+					   struct ipa_tx_pkt_wrapper,
+					   link);
+	if (unlikely(tx_pkt != tx_pkt_expected)) {
+		spin_unlock_irqrestore(&tx_pkt->sys->spinlock,
+				irq_flags);
+		WARN_ON(1);
+	}
+	list_del(&tx_pkt->link);
+	spin_unlock_irqrestore(&tx_pkt->sys->spinlock, irq_flags);
+	if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0)) {
+		dma_pool_free(ipa_ctx->dma_pool,
+				tx_pkt->bounce,
+				tx_pkt->mem.phys_base);
+	} else {
+		dma_unmap_single(NULL, tx_pkt->mem.phys_base,
+				tx_pkt->mem.size,
+				DMA_TO_DEVICE);
+	}
 
-	for (i = 0; i < cnt; i++) {
-		if (unlikely(tx_pkt == NULL))
-			WARN_ON(1);
-		spin_lock_irqsave(&tx_pkt->sys->spinlock, irq_flags);
-		tx_pkt_expected = list_first_entry(&tx_pkt->sys->head_desc_list,
-						   struct ipa_tx_pkt_wrapper,
-						   link);
-		if (unlikely(tx_pkt != tx_pkt_expected)) {
-			spin_unlock_irqrestore(&tx_pkt->sys->spinlock,
-					irq_flags);
-			WARN_ON(1);
+	if (tx_pkt->callback)
+		tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
+
+	kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+}
+
+int ipa_handle_tx_core(struct ipa_sys_context *sys, bool process_all,
+		bool in_poll_state)
+{
+	struct ipa_tx_pkt_wrapper *tx_pkt;
+	struct sps_iovec iov;
+	int ret;
+	int cnt = 0;
+	unsigned long irq_flags;
+
+	while ((in_poll_state ? atomic_read(&sys->curr_polling_state) :
+				!atomic_read(&sys->curr_polling_state))) {
+		if (cnt && !process_all)
+			break;
+		ret = sps_get_iovec(sys->ep->ep_hdl, &iov);
+		if (ret) {
+			IPAERR("sps_get_iovec failed %d\n", ret);
+			break;
 		}
-		next_pkt = list_next_entry(tx_pkt, link);
+
+		if (iov.addr == 0)
+			break;
+
+		if (unlikely(list_empty(&sys->head_desc_list)))
+			continue;
+
+		spin_lock_irqsave(&sys->spinlock, irq_flags);
+		tx_pkt = list_first_entry(&sys->head_desc_list,
+					  struct ipa_tx_pkt_wrapper, link);
+
+		sys->len--;
 		list_del(&tx_pkt->link);
-		spin_unlock_irqrestore(&tx_pkt->sys->spinlock, irq_flags);
-		if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0)) {
+		spin_unlock_irqrestore(&sys->spinlock, irq_flags);
+
+		IPADBG("--curr_cnt=%d\n", sys->len);
+
+		if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
 			dma_pool_free(ipa_ctx->dma_pool,
 					tx_pkt->bounce,
 					tx_pkt->mem.phys_base);
-		} else {
+		else
 			dma_unmap_single(NULL, tx_pkt->mem.phys_base,
 					tx_pkt->mem.size,
 					DMA_TO_DEVICE);
-		}
 
 		if (tx_pkt->callback)
 			tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
 
+		if (tx_pkt->cnt > 1 && tx_pkt->cnt != IPA_LAST_DESC_CNT)
+			dma_pool_free(ipa_ctx->dma_pool, tx_pkt->mult.base,
+					tx_pkt->mult.phys_base);
+
 		kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
-		tx_pkt = next_pkt;
+		cnt++;
+	};
+
+	return cnt;
+}
+
+/**
+ * ipa_tx_switch_to_intr_mode() - Operate the Tx data path in interrupt mode
+ */
+static void ipa_tx_switch_to_intr_mode(struct ipa_sys_context *sys)
+{
+	int ret;
+
+	if (!atomic_read(&sys->curr_polling_state)) {
+		IPAERR("already in intr mode\n");
+		goto fail;
 	}
 
-	if (mult.phys_base)
-		dma_pool_free(ipa_ctx->dma_pool, mult.base, mult.phys_base);
+	ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
+	if (ret) {
+		IPAERR("sps_get_config() failed %d\n", ret);
+		goto fail;
+	}
+	sys->event.options = SPS_O_EOT;
+	ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
+	if (ret) {
+		IPAERR("sps_register_event() failed %d\n", ret);
+		goto fail;
+	}
+	sys->ep->connect.options =
+		SPS_O_AUTO_ENABLE | SPS_O_ACK_TRANSFERS | SPS_O_EOT;
+	ret = sps_set_config(sys->ep->ep_hdl, &sys->ep->connect);
+	if (ret) {
+		IPAERR("sps_set_config() failed %d\n", ret);
+		goto fail;
+	}
+	atomic_set(&sys->curr_polling_state, 0);
+	ipa_handle_tx_core(sys, true, false);
+	return;
+
+fail:
+	IPA_STATS_INC_CNT(ipa_ctx->stats.x_intr_repost_tx);
+	schedule_delayed_work(&sys->switch_to_intr_work, msecs_to_jiffies(1));
+	return;
+}
+
+static void ipa_handle_tx(struct ipa_sys_context *sys)
+{
+	int inactive_cycles = 0;
+	int cnt;
+
+	do {
+		cnt = ipa_handle_tx_core(sys, true, true);
+		if (cnt == 0) {
+			inactive_cycles++;
+			usleep_range(POLLING_MIN_SLEEP_TX,
+					POLLING_MAX_SLEEP_TX);
+		} else {
+			inactive_cycles = 0;
+		}
+	} while (inactive_cycles <= POLLING_INACTIVITY_TX);
+
+	ipa_tx_switch_to_intr_mode(sys);
+}
+
+static void ipa_wq_handle_tx(struct work_struct *work)
+{
+	struct ipa_tx_pkt_wrapper *tx_pkt;
+	tx_pkt = container_of(work, struct ipa_tx_pkt_wrapper, work);
+	ipa_handle_tx(tx_pkt->sys);
 }
 
 /**
@@ -165,7 +273,6 @@
 	}
 
 	INIT_LIST_HEAD(&tx_pkt->link);
-	INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
 	tx_pkt->type = desc->type;
 	tx_pkt->cnt = 1;    /* only 1 desc in this "set" */
 
@@ -187,10 +294,15 @@
 		IPADBG("sending cmd=%d pyld_len=%d sps_flags=%x\n",
 				desc->opcode, desc->len, sps_flags);
 		IPA_DUMP_BUFF(desc->pyld, dma_address, desc->len);
+		INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
 	} else {
 		len = desc->len;
+		INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
 	}
 
+	if (unlikely(ipa_ctx->polling_mode))
+		INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
+
 	spin_lock_irqsave(&sys->spinlock, irq_flags);
 	list_add_tail(&tx_pkt->link, &sys->head_desc_list);
 	result = sps_transfer_one(sys->ep->ep_hdl, dma_address, len, tx_pkt,
@@ -286,7 +398,7 @@
 			tx_pkt->mult.base = transfer.iovec;
 			tx_pkt->mult.size = size;
 			tx_pkt->cnt = num_desc;
-			INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
+			INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
 		}
 
 		iovec = &transfer.iovec[i];
@@ -475,6 +587,49 @@
 
 /**
  * ipa_sps_irq_tx_notify() - Callback function which will be called by
+ * the SPS driver to start a Tx poll operation.
+ * Called in an interrupt context.
+ * @notify:	SPS driver supplied notification struct
+ *
+ * This function defer the work for this event to the tx workqueue.
+ */
+static void ipa_sps_irq_tx_notify(struct sps_event_notify *notify)
+{
+	struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT];
+	struct ipa_tx_pkt_wrapper *tx_pkt;
+	int ret;
+
+	IPADBG("event %d notified\n", notify->event_id);
+
+	switch (notify->event_id) {
+	case SPS_EVENT_EOT:
+		tx_pkt = notify->data.transfer.user;
+		if (!atomic_read(&sys->curr_polling_state)) {
+			ret = sps_get_config(sys->ep->ep_hdl,
+					&sys->ep->connect);
+			if (ret) {
+				IPAERR("sps_get_config() failed %d\n", ret);
+				break;
+			}
+			sys->ep->connect.options = SPS_O_AUTO_ENABLE |
+				SPS_O_ACK_TRANSFERS | SPS_O_POLL;
+			ret = sps_set_config(sys->ep->ep_hdl,
+					&sys->ep->connect);
+			if (ret) {
+				IPAERR("sps_set_config() failed %d\n", ret);
+				break;
+			}
+			atomic_set(&sys->curr_polling_state, 1);
+			queue_work(ipa_ctx->tx_wq, &tx_pkt->work);
+		}
+		break;
+	default:
+		IPAERR("recieved unexpected event id %d\n", notify->event_id);
+	}
+}
+
+/**
+ * ipa_sps_irq_tx_no_aggr_notify() - Callback function which will be called by
  * the SPS driver after a Tx operation is complete.
  * Called in an interrupt context.
  * @notify:	SPS driver supplied notification struct
@@ -482,7 +637,7 @@
  * This function defer the work for this event to the tx workqueue.
  * This event will be later handled by ipa_write_done.
  */
-static void ipa_sps_irq_tx_notify(struct sps_event_notify *notify)
+static void ipa_sps_irq_tx_no_aggr_notify(struct sps_event_notify *notify)
 {
 	struct ipa_tx_pkt_wrapper *tx_pkt;
 
@@ -512,7 +667,8 @@
  *  - Call the endpoints notify function, passing the skb in the parameters
  *  - Replenish the rx cache
  */
-int ipa_handle_rx_core(bool process_all, bool in_poll_state)
+int ipa_handle_rx_core(struct ipa_sys_context *sys, bool process_all,
+		bool in_poll_state)
 {
 	struct ipa_a5_mux_hdr *mux_hdr;
 	struct ipa_rx_pkt_wrapper *rx_pkt;
@@ -521,15 +677,14 @@
 	unsigned int pull_len;
 	unsigned int padding;
 	int ret;
-	struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_IN];
 	struct ipa_ep_context *ep;
 	int cnt = 0;
 	struct completion *compl;
 	struct ipa_tree_node *node;
 	unsigned int src_pipe;
 
-	while ((in_poll_state ? atomic_read(&ipa_ctx->curr_polling_state) :
-				!atomic_read(&ipa_ctx->curr_polling_state))) {
+	while ((in_poll_state ? atomic_read(&sys->curr_polling_state) :
+				!atomic_read(&sys->curr_polling_state))) {
 		if (cnt && !process_all)
 			break;
 
@@ -654,19 +809,15 @@
 /**
  * ipa_rx_switch_to_intr_mode() - Operate the Rx data path in interrupt mode
  */
-static void ipa_rx_switch_to_intr_mode(void)
+static void ipa_rx_switch_to_intr_mode(struct ipa_sys_context *sys)
 {
 	int ret;
-	struct ipa_sys_context *sys;
 
-	IPADBG("Enter");
-	if (!atomic_read(&ipa_ctx->curr_polling_state)) {
+	if (!atomic_read(&sys->curr_polling_state)) {
 		IPAERR("already in intr mode\n");
 		goto fail;
 	}
 
-	sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_IN];
-
 	ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
 	if (ret) {
 		IPAERR("sps_get_config() failed %d\n", ret);
@@ -685,15 +836,16 @@
 		IPAERR("sps_set_config() failed %d\n", ret);
 		goto fail;
 	}
-	atomic_set(&ipa_ctx->curr_polling_state, 0);
-	ipa_handle_rx_core(true, false);
+	atomic_set(&sys->curr_polling_state, 0);
+	ipa_handle_rx_core(sys, true, false);
 	return;
 
 fail:
 	IPA_STATS_INC_CNT(ipa_ctx->stats.x_intr_repost);
-	schedule_delayed_work(&switch_to_intr_work, msecs_to_jiffies(1));
+	schedule_delayed_work(&sys->switch_to_intr_work, msecs_to_jiffies(1));
 }
 
+
 /**
  * ipa_rx_notify() - Callback function which is called by the SPS driver when a
  * a packet is received
@@ -709,29 +861,29 @@
  */
 static void ipa_sps_irq_rx_notify(struct sps_event_notify *notify)
 {
-	struct ipa_ep_context *ep;
+	struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_IN];
 	int ret;
 
 	IPADBG("event %d notified\n", notify->event_id);
 
 	switch (notify->event_id) {
 	case SPS_EVENT_EOT:
-		if (!atomic_read(&ipa_ctx->curr_polling_state)) {
-			ep = ipa_ctx->sys[IPA_A5_LAN_WAN_IN].ep;
-
-			ret = sps_get_config(ep->ep_hdl, &ep->connect);
+		if (!atomic_read(&sys->curr_polling_state)) {
+			ret = sps_get_config(sys->ep->ep_hdl,
+					&sys->ep->connect);
 			if (ret) {
 				IPAERR("sps_get_config() failed %d\n", ret);
 				break;
 			}
-			ep->connect.options = SPS_O_AUTO_ENABLE |
+			sys->ep->connect.options = SPS_O_AUTO_ENABLE |
 				SPS_O_ACK_TRANSFERS | SPS_O_POLL;
-			ret = sps_set_config(ep->ep_hdl, &ep->connect);
+			ret = sps_set_config(sys->ep->ep_hdl,
+					&sys->ep->connect);
 			if (ret) {
 				IPAERR("sps_set_config() failed %d\n", ret);
 				break;
 			}
-			atomic_set(&ipa_ctx->curr_polling_state, 1);
+			atomic_set(&sys->curr_polling_state, 1);
 			queue_work(ipa_ctx->rx_wq, &rx_work);
 		}
 		break;
@@ -740,6 +892,51 @@
 	}
 }
 
+static void switch_to_intr_tx_work_func(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct ipa_sys_context *sys;
+	dwork = container_of(work, struct delayed_work, work);
+	sys = container_of(dwork, struct ipa_sys_context, switch_to_intr_work);
+	ipa_handle_tx(sys);
+}
+
+/**
+ * ipa_handle_rx() - handle packet reception. This function is executed in the
+ * context of a work queue.
+ * @work: work struct needed by the work queue
+ *
+ * ipa_handle_rx_core() is run in polling mode. After all packets has been
+ * received, the driver switches back to interrupt mode.
+ */
+static void ipa_handle_rx(struct ipa_sys_context *sys)
+{
+	int inactive_cycles = 0;
+	int cnt;
+
+	do {
+		cnt = ipa_handle_rx_core(sys, true, true);
+		if (cnt == 0) {
+			inactive_cycles++;
+			usleep_range(POLLING_MIN_SLEEP_RX,
+					POLLING_MAX_SLEEP_RX);
+		} else {
+			inactive_cycles = 0;
+		}
+	} while (inactive_cycles <= POLLING_INACTIVITY_RX);
+
+	ipa_rx_switch_to_intr_mode(sys);
+}
+
+static void switch_to_intr_rx_work_func(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct ipa_sys_context *sys;
+	dwork = container_of(work, struct delayed_work, work);
+	sys = container_of(dwork, struct ipa_sys_context, switch_to_intr_work);
+	ipa_handle_rx(sys);
+}
+
 /**
  * ipa_setup_sys_pipe() - Setup an IPA end-point in system-BAM mode and perform
  * IPA EP configuration
@@ -858,14 +1055,18 @@
 
 	switch (ipa_ep_idx) {
 	case 1:
-		/* fall through */
+		sys_idx = ipa_ep_idx;
+		break;
 	case 2:
-		/* fall through */
+		sys_idx = ipa_ep_idx;
+		INIT_DELAYED_WORK(&ipa_ctx->sys[sys_idx].switch_to_intr_work,
+				switch_to_intr_tx_work_func);
+		break;
 	case 3:
 		sys_idx = ipa_ep_idx;
 		INIT_DELAYED_WORK(&replenish_rx_work, replenish_rx_work_func);
-		INIT_DELAYED_WORK(&switch_to_intr_work,
-				switch_to_intr_work_func);
+		INIT_DELAYED_WORK(&ipa_ctx->sys[sys_idx].switch_to_intr_work,
+				switch_to_intr_rx_work_func);
 		break;
 	case WLAN_AMPDU_TX_EP:
 		sys_idx = IPA_A5_WLAN_AMPDU_OUT;
@@ -886,7 +1087,10 @@
 		ipa_ctx->sys[sys_idx].event.callback =
 				IPA_CLIENT_IS_CONS(sys_in->client) ?
 					ipa_sps_irq_rx_notify :
-					ipa_sps_irq_tx_notify;
+					(sys_in->client ==
+					 IPA_CLIENT_A5_LAN_WAN_PROD ?
+					ipa_sps_irq_tx_notify :
+					ipa_sps_irq_tx_no_aggr_notify);
 		result = sps_register_event(ipa_ctx->ep[ipa_ep_idx].ep_hdl,
 					  &ipa_ctx->sys[sys_idx].event);
 		if (result < 0) {
@@ -1078,37 +1282,9 @@
 }
 EXPORT_SYMBOL(ipa_tx_dp);
 
-static void ipa_handle_rx(void)
-{
-	int inactive_cycles = 0;
-	int cnt;
-
-	ipa_inc_client_enable_clks();
-	do {
-		cnt = ipa_handle_rx_core(true, true);
-		if (cnt == 0) {
-			inactive_cycles++;
-			usleep_range(POLLING_MIN_SLEEP, POLLING_MAX_SLEEP);
-		} else {
-			inactive_cycles = 0;
-		}
-	} while (inactive_cycles <= POLLING_INACTIVITY);
-
-	ipa_rx_switch_to_intr_mode();
-	ipa_dec_client_disable_clks();
-}
-
-/**
- * ipa_handle_rx() - handle packet reception. This function is executed in the
- * context of a work queue.
- * @work: work struct needed by the work queue
- *
- * ipa_handle_rx_core() is run in polling mode. After all packets has been
- * received, the driver switches back to interrupt mode.
- */
 static void ipa_wq_handle_rx(struct work_struct *work)
 {
-	ipa_handle_rx();
+	ipa_handle_rx(&ipa_ctx->sys[IPA_A5_LAN_WAN_IN]);
 }
 
 /**
@@ -1202,11 +1378,6 @@
 	ipa_replenish_rx_cache();
 }
 
-static void switch_to_intr_work_func(struct work_struct *work)
-{
-	ipa_handle_rx();
-}
-
 /**
  * ipa_cleanup_rx() - release RX queue resources
  *
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index cc3e630..b57194e 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -372,7 +372,6 @@
  * @spinlock: protects the list and its size
  * @event: used to request CALLBACK mode from SPS driver
  * @ep: IPA EP context
- * @wait_desc_list: used to hold completed Tx packets
  *
  * IPA context specific to the system-bam pipes a.k.a LAN IN/OUT and WAN
  */
@@ -382,7 +381,8 @@
 	spinlock_t spinlock;
 	struct sps_register_event event;
 	struct ipa_ep_context *ep;
-	struct list_head wait_desc_list;
+	atomic_t curr_polling_state;
+	struct delayed_work switch_to_intr_work;
 };
 
 /**
@@ -479,6 +479,14 @@
  * @is_sys_mem: flag indicating if NAT memory is sys memory
  * @is_dev_init: flag indicating if NAT device is initialized
  * @lock: NAT memory mutex
+ * @nat_base_address: nat table virutal address
+ * @ipv4_rules_addr: base nat table address
+ * @ipv4_expansion_rules_addr: expansion table address
+ * @index_table_addr: index table address
+ * @index_table_expansion_addr: index expansion table address
+ * @size_base_tables: base table size
+ * @size_expansion_tables: expansion table size
+ * @public_ip_addr: ip address of nat table
  */
 struct ipa_nat_mem {
 	struct class *class;
@@ -492,6 +500,14 @@
 	bool is_sys_mem;
 	bool is_dev_init;
 	struct mutex lock;
+	void *nat_base_address;
+	char *ipv4_rules_addr;
+	char *ipv4_expansion_rules_addr;
+	char *index_table_addr;
+	char *index_table_expansion_addr;
+	u32 size_base_tables;
+	u32 size_expansion_tables;
+	u32 public_ip_addr;
 };
 
 /**
@@ -530,6 +546,7 @@
 	u32 bridged_pkts[IPA_BRIDGE_TYPE_MAX][IPA_BRIDGE_DIR_MAX];
 	u32 rx_repl_repost;
 	u32 x_intr_repost;
+	u32 x_intr_repost_tx;
 	u32 rx_q_len;
 	u32 msg_w[IPA_EVENT_MAX];
 	u32 msg_r[IPA_EVENT_MAX];
@@ -641,7 +658,6 @@
 	uint aggregation_type;
 	uint aggregation_byte_limit;
 	uint aggregation_time_limit;
-	atomic_t curr_polling_state;
 	struct delayed_work poll_work;
 	bool hdr_tbl_lcl;
 	struct ipa_mem_buffer hdr_mem;
@@ -800,7 +816,10 @@
 void ipa_cleanup_rx(void);
 int ipa_cfg_filter(u32 disable);
 void ipa_wq_write_done(struct work_struct *work);
-int ipa_handle_rx_core(bool process_all, bool in_poll_state);
+int ipa_handle_rx_core(struct ipa_sys_context *sys, bool process_all,
+		bool in_poll_state);
+int ipa_handle_tx_core(struct ipa_sys_context *sys, bool process_all,
+		bool in_poll_state);
 int ipa_pipe_mem_init(u32 start_ofst, u32 size);
 int ipa_pipe_mem_alloc(u32 *ofst, u32 size);
 int ipa_pipe_mem_free(u32 ofst, u32 size);
diff --git a/drivers/platform/msm/ipa/ipa_nat.c b/drivers/platform/msm/ipa/ipa_nat.c
index befa2cf..e2c344f 100644
--- a/drivers/platform/msm/ipa/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_nat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -75,6 +75,7 @@
 			IPAERR("unable to map memory. Err:%d\n", result);
 			goto bail;
 		}
+		ipa_ctx->nat_mem.nat_base_address = nat_ctx->vaddr;
 	} else {
 		IPADBG("Mapping shared(local) memory\n");
 		IPADBG("map sz=0x%lx\n", vsize);
@@ -88,7 +89,7 @@
 			result = -EAGAIN;
 			goto bail;
 		}
-
+		ipa_ctx->nat_mem.nat_base_address = (void *)vma->vm_start;
 	}
 	nat_ctx->is_mapped = true;
 	vma->vm_ops = &ipa_nat_remap_vm_ops;
@@ -299,6 +300,35 @@
 		goto free_cmd;
 	}
 
+	ipa_ctx->nat_mem.public_ip_addr = init->ip_addr;
+	IPADBG("Table ip address:0x%x", ipa_ctx->nat_mem.public_ip_addr);
+
+	ipa_ctx->nat_mem.ipv4_rules_addr =
+	 (char *)ipa_ctx->nat_mem.nat_base_address + init->ipv4_rules_offset;
+	IPADBG("ipv4_rules_addr: 0x%p\n",
+				 ipa_ctx->nat_mem.ipv4_rules_addr);
+
+	ipa_ctx->nat_mem.ipv4_expansion_rules_addr =
+	 (char *)ipa_ctx->nat_mem.nat_base_address + init->expn_rules_offset;
+	IPADBG("ipv4_expansion_rules_addr: 0x%p\n",
+				 ipa_ctx->nat_mem.ipv4_expansion_rules_addr);
+
+	ipa_ctx->nat_mem.index_table_addr =
+		 (char *)ipa_ctx->nat_mem.nat_base_address + init->index_offset;
+	IPADBG("index_table_addr: 0x%p\n",
+				 ipa_ctx->nat_mem.index_table_addr);
+
+	ipa_ctx->nat_mem.index_table_expansion_addr =
+	 (char *)ipa_ctx->nat_mem.nat_base_address + init->index_expn_offset;
+	IPADBG("index_table_expansion_addr: 0x%p\n",
+				 ipa_ctx->nat_mem.index_table_expansion_addr);
+
+	IPADBG("size_base_tables: %d\n", init->table_entries);
+	ipa_ctx->nat_mem.size_base_tables  = init->table_entries;
+
+	IPADBG("size_expansion_tables: %d\n", init->expn_table_entries);
+	ipa_ctx->nat_mem.size_expansion_tables = init->expn_table_entries;
+
 	IPADBG("return\n");
 	result = 0;
 free_cmd:
diff --git a/drivers/platform/msm/ipa/ipa_rm.c b/drivers/platform/msm/ipa/ipa_rm.c
index 1fdd300..88a49c4 100644
--- a/drivers/platform/msm/ipa/ipa_rm.c
+++ b/drivers/platform/msm/ipa/ipa_rm.c
@@ -21,6 +21,7 @@
 struct ipa_rm_context_type {
 	struct ipa_rm_dep_graph *dep_graph;
 	struct workqueue_struct *ipa_rm_wq;
+	rwlock_t lock;
 };
 static struct ipa_rm_context_type *ipa_rm_ctx;
 
@@ -41,10 +42,9 @@
 	struct ipa_rm_resource *resource;
 	int result;
 
-	if (!create_params) {
-		result = -EINVAL;
-		goto bail;
-	}
+	if (!create_params)
+		return -EINVAL;
+	write_lock(&ipa_rm_ctx->lock);
 	if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
 					  create_params->name,
 					  &resource) == 0) {
@@ -59,11 +59,51 @@
 	if (result)
 		ipa_rm_resource_delete(resource);
 bail:
+	write_unlock(&ipa_rm_ctx->lock);
 	return result;
 }
 EXPORT_SYMBOL(ipa_rm_create_resource);
 
 /**
+ * ipa_rm_delete_resource() - delete resource
+ * @resource_name: name of resource to be deleted
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * This function is called by IPA RM client to delete client's resources.
+ *
+ */
+int ipa_rm_delete_resource(enum ipa_rm_resource_name resource_name)
+{
+	struct ipa_rm_resource *resource;
+	int result;
+
+	IPADBG("IPA RM ::ipa_rm_delete_resource num[%d] ENTER\n",
+			resource_name);
+	write_lock(&ipa_rm_ctx->lock);
+	if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
+					resource_name,
+						&resource) != 0) {
+		IPADBG("ipa_rm_delete_resource param are bad********\n");
+		result = -EINVAL;
+		goto bail;
+	}
+	result = ipa_rm_resource_delete(resource);
+	if (result) {
+		IPADBG("error in ipa_rm_resource_delete\n");
+		goto bail;
+	}
+	result = ipa_rm_dep_graph_remove(ipa_rm_ctx->dep_graph,
+								resource_name);
+	IPADBG("IPA RM ::ipa_rm_delete_resource [%d] SUCCESS\n",
+								resource_name);
+bail:
+	write_unlock(&ipa_rm_ctx->lock);
+	return result;
+}
+EXPORT_SYMBOL(ipa_rm_delete_resource);
+
+/**
  * ipa_rm_add_dependency() - create dependency
  *					between 2 resources
  * @resource_name: name of dependent resource
@@ -77,13 +117,19 @@
 int ipa_rm_add_dependency(enum ipa_rm_resource_name resource_name,
 			enum ipa_rm_resource_name depends_on_name)
 {
-	return ipa_rm_dep_graph_add_dependency(
-			ipa_rm_ctx->dep_graph,
-			resource_name,
-			depends_on_name);
+	int result;
+
+	read_lock(&ipa_rm_ctx->lock);
+	result = ipa_rm_dep_graph_add_dependency(
+						ipa_rm_ctx->dep_graph,
+						resource_name,
+						depends_on_name);
+	read_unlock(&ipa_rm_ctx->lock);
+	return result;
 }
 EXPORT_SYMBOL(ipa_rm_add_dependency);
 
+
 /**
  * ipa_rm_delete_dependency() - create dependency
  *					between 2 resources
@@ -98,10 +144,14 @@
 int ipa_rm_delete_dependency(enum ipa_rm_resource_name resource_name,
 			enum ipa_rm_resource_name depends_on_name)
 {
-	return ipa_rm_dep_graph_delete_dependency(
-			ipa_rm_ctx->dep_graph,
-			resource_name,
-			depends_on_name);
+	int result;
+	read_lock(&ipa_rm_ctx->lock);
+	result = ipa_rm_dep_graph_delete_dependency(
+			  ipa_rm_ctx->dep_graph,
+			  resource_name,
+			  depends_on_name);
+	read_unlock(&ipa_rm_ctx->lock);
+	return result;
 }
 EXPORT_SYMBOL(ipa_rm_delete_dependency);
 
@@ -120,10 +170,9 @@
 	int result;
 	IPADBG("IPA RM ::ipa_rm_request_resource ENTER\n");
 
-	if (!IPA_RM_RESORCE_IS_PROD(resource_name)) {
-			result = -EINVAL;
-			goto bail;
-	}
+	if (!IPA_RM_RESORCE_IS_PROD(resource_name))
+			return -EINVAL;
+	read_lock(&ipa_rm_ctx->lock);
 	if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
 			resource_name,
 			&resource) != 0) {
@@ -136,6 +185,7 @@
 bail:
 	IPADBG("IPA RM ::ipa_rm_request_resource EXIT [%d]\n", result);
 
+	read_unlock(&ipa_rm_ctx->lock);
 	return result;
 }
 EXPORT_SYMBOL(ipa_rm_request_resource);
@@ -155,10 +205,9 @@
 	int result;
 	IPADBG("IPA RM ::ipa_rm_release_resource ENTER\n");
 
-	if (!IPA_RM_RESORCE_IS_PROD(resource_name)) {
-		result = -EINVAL;
-		goto bail;
-	}
+	if (!IPA_RM_RESORCE_IS_PROD(resource_name))
+		return -EINVAL;
+	read_lock(&ipa_rm_ctx->lock);
 	if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
 					  resource_name,
 					  &resource) != 0) {
@@ -170,6 +219,7 @@
 
 bail:
 	IPADBG("IPA RM ::ipa_rm_release_resource EXIT [%d]\n", result);
+	read_unlock(&ipa_rm_ctx->lock);
 	return result;
 }
 EXPORT_SYMBOL(ipa_rm_release_resource);
@@ -189,10 +239,10 @@
 {
 	int result;
 	struct ipa_rm_resource *resource;
-	if (!IPA_RM_RESORCE_IS_PROD(resource_name)) {
-		result = -EINVAL;
-		goto bail;
-	}
+
+	if (!IPA_RM_RESORCE_IS_PROD(resource_name))
+		return -EINVAL;
+	read_lock(&ipa_rm_ctx->lock);
 	if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
 				resource_name,
 				&resource) != 0) {
@@ -203,6 +253,7 @@
 			(struct ipa_rm_resource_prod *)resource,
 			reg_params);
 bail:
+	read_unlock(&ipa_rm_ctx->lock);
 	return result;
 }
 EXPORT_SYMBOL(ipa_rm_register);
@@ -222,10 +273,10 @@
 {
 	int result;
 	struct ipa_rm_resource *resource;
-	if (!IPA_RM_RESORCE_IS_PROD(resource_name)) {
-		result = -EINVAL;
-		goto bail;
-	}
+
+	if (!IPA_RM_RESORCE_IS_PROD(resource_name))
+		return -EINVAL;
+	read_lock(&ipa_rm_ctx->lock);
 	if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
 			resource_name,
 			&resource) != 0) {
@@ -236,6 +287,7 @@
 			(struct ipa_rm_resource_prod *)resource,
 			reg_params);
 bail:
+	read_unlock(&ipa_rm_ctx->lock);
 	return result;
 }
 EXPORT_SYMBOL(ipa_rm_deregister);
@@ -278,25 +330,32 @@
 	case IPA_RM_WQ_NOTIFY_PROD:
 		if (!IPA_RM_RESORCE_IS_PROD(ipa_rm_work->resource_name))
 			return;
+		read_lock(&ipa_rm_ctx->lock);
 		if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
 						ipa_rm_work->resource_name,
-						&resource) != 0)
+						&resource) != 0){
+			read_unlock(&ipa_rm_ctx->lock);
 			return;
+		}
 		ipa_rm_resource_producer_notify_clients(
 				(struct ipa_rm_resource_prod *)resource,
 				ipa_rm_work->event);
-
+		read_unlock(&ipa_rm_ctx->lock);
 		break;
 	case IPA_RM_WQ_NOTIFY_CONS:
 		break;
 	case IPA_RM_WQ_RESOURCE_CB:
+		read_lock(&ipa_rm_ctx->lock);
 		if (ipa_rm_dep_graph_get_resource(ipa_rm_ctx->dep_graph,
 						ipa_rm_work->resource_name,
-						&resource) != 0)
+						&resource) != 0){
+			read_unlock(&ipa_rm_ctx->lock);
 			return;
+		}
 		ipa_rm_resource_consumer_handle_cb(
 				(struct ipa_rm_resource_cons *)resource,
 				ipa_rm_work->event);
+		read_unlock(&ipa_rm_ctx->lock);
 		break;
 	default:
 		break;
@@ -351,6 +410,7 @@
 	result = ipa_rm_dep_graph_create(&(ipa_rm_ctx->dep_graph));
 	if (result)
 		goto graph_alloc_fail;
+	rwlock_init(&ipa_rm_ctx->lock);
 	IPADBG("IPA RM ipa_rm_initialize SUCCESS\n");
 	return 0;
 
diff --git a/drivers/platform/msm/ipa/ipa_rm_dependency_graph.c b/drivers/platform/msm/ipa/ipa_rm_dependency_graph.c
index 6afab42..8144a42 100644
--- a/drivers/platform/msm/ipa/ipa_rm_dependency_graph.c
+++ b/drivers/platform/msm/ipa/ipa_rm_dependency_graph.c
@@ -39,7 +39,6 @@
 		result = -ENOMEM;
 		goto bail;
 	}
-	rwlock_init(&((*dep_graph)->lock));
 bail:
 	return result;
 }
@@ -55,12 +54,10 @@
 	int resource_index;
 	if (!graph)
 		return;
-	write_lock(&graph->lock);
 	for (resource_index = 0;
 			resource_index < IPA_RM_RESOURCE_MAX;
 			resource_index++)
 		kfree(graph->resource_table[resource_index]);
-	write_unlock(&graph->lock);
 	memset(graph->resource_table, 0, sizeof(graph->resource_table));
 }
 
@@ -88,9 +85,7 @@
 		result = -EINVAL;
 		goto bail;
 	}
-	read_lock(&graph->lock);
 	*resource = graph->resource_table[resource_index];
-	read_unlock(&graph->lock);
 	if (!*resource) {
 		result = -EINVAL;
 		goto bail;
@@ -112,6 +107,7 @@
 {
 	int result = 0;
 	int resource_index;
+
 	if (!graph || !resource) {
 		result = -EINVAL;
 		goto bail;
@@ -121,14 +117,29 @@
 		result = -EINVAL;
 		goto bail;
 	}
-	write_lock(&graph->lock);
 	graph->resource_table[resource_index] = resource;
-	write_unlock(&graph->lock);
 bail:
 	return result;
 }
 
 /**
+ * ipa_rm_dep_graph_remove() - removes resource from graph
+ * @graph: [in] dependency graph
+ * @resource: [in] resource to add
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_rm_dep_graph_remove(struct ipa_rm_dep_graph *graph,
+		enum ipa_rm_resource_name resource_name)
+{
+	if (!graph)
+		return -EINVAL;
+
+	graph->resource_table[resource_name] = NULL;
+	return 0;
+}
+
+/**
  * ipa_rm_dep_graph_add_dependency() - adds dependency between
  *				two nodes in graph
  * @graph: [in] dependency graph
diff --git a/drivers/platform/msm/ipa/ipa_rm_dependency_graph.h b/drivers/platform/msm/ipa/ipa_rm_dependency_graph.h
index 19d9461..4126819 100644
--- a/drivers/platform/msm/ipa/ipa_rm_dependency_graph.h
+++ b/drivers/platform/msm/ipa/ipa_rm_dependency_graph.h
@@ -19,7 +19,6 @@
 
 struct ipa_rm_dep_graph {
 	struct ipa_rm_resource *resource_table[IPA_RM_RESOURCE_MAX];
-	rwlock_t lock;
 };
 
 int ipa_rm_dep_graph_get_resource(
@@ -34,6 +33,9 @@
 int ipa_rm_dep_graph_add(struct ipa_rm_dep_graph *graph,
 			 struct ipa_rm_resource *resource);
 
+int ipa_rm_dep_graph_remove(struct ipa_rm_dep_graph *graph,
+				enum ipa_rm_resource_name resource_name);
+
 int ipa_rm_dep_graph_add_dependency(struct ipa_rm_dep_graph *graph,
 				enum ipa_rm_resource_name resource_name,
 				enum ipa_rm_resource_name depends_on_name);
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c
index 3615952..0fc4826 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.c
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.c
@@ -80,8 +80,8 @@
 	int result = 0;
 	int driver_result;
 	unsigned long flags;
-	IPADBG("IPA RM ::ipa_rm_resource_consumer_request %d ENTER\n",
-		consumer->resource.name);
+	IPADBG("IPA RM ::%s name %d ENTER\n",
+	       __func__, consumer->resource.name);
 	spin_lock_irqsave(&consumer->resource.state_lock, flags);
 	switch (consumer->resource.state) {
 	case IPA_RM_RELEASED:
@@ -115,8 +115,7 @@
 	consumer->usage_count++;
 bail:
 	spin_unlock_irqrestore(&consumer->resource.state_lock, flags);
-	IPADBG("IPA RM ::ipa_rm_resource_consumer_request %d EXIT %d\n",
-		consumer->resource.name, result);
+	IPADBG("IPA RM ::ipa_rm_resource_consumer_request EXIT [%d]\n", result);
 	return result;
 }
 
@@ -127,8 +126,8 @@
 	int driver_result;
 	unsigned long flags;
 	enum ipa_rm_resource_state save_state;
-	IPADBG("IPA RM ::ipa_rm_resource_consumer_release %d ENTER\n",
-		consumer->resource.name);
+	IPADBG("IPA RM ::%s name %d ENTER\n",
+	       __func__, consumer->resource.name);
 	spin_lock_irqsave(&consumer->resource.state_lock, flags);
 	switch (consumer->resource.state) {
 	case IPA_RM_RELEASED:
@@ -163,8 +162,7 @@
 	}
 bail:
 	spin_unlock_irqrestore(&consumer->resource.state_lock, flags);
-	IPADBG("IPA RM ::ipa_rm_resource_consumer_release %d EXIT %d\n",
-		consumer->resource.name, result);
+	IPADBG("IPA RM ::ipa_rm_resource_consumer_release EXIT [%d]\n", result);
 	return result;
 }
 
@@ -332,19 +330,56 @@
  * ipa_rm_resource_delete() - deletes resource
  * @resource: [in] resource
  *			for resource initialization with IPA RM
+ *
+ * Returns: 0 on success, negative on failure
  */
-void ipa_rm_resource_delete(struct ipa_rm_resource *resource)
+int ipa_rm_resource_delete(struct ipa_rm_resource *resource)
 {
-	if (!resource)
-		return;
-	if (resource->peers_list)
-		ipa_rm_peers_list_delete(resource->peers_list);
+	struct ipa_rm_resource *consumer, *producer;
+	int i, result = 0;
+
+	IPADBG("IPA RM: %s ENTER\n", __func__);
+
+	if (!resource) {
+		IPADBG("ipa_rm_resource_delete ENTER with invalid param\n");
+		return -EINVAL;
+	}
 	if (resource->type == IPA_RM_PRODUCER) {
+		if (resource->peers_list) {
+			for (i = IPA_RM_RESOURCE_PROD_MAX;
+					i < IPA_RM_RESOURCE_MAX;
+						++i) {
+				consumer = ipa_rm_peers_list_get_resource(
+						i,
+						resource->peers_list);
+				if (consumer) {
+					ipa_rm_resource_delete_dependency(
+						resource,
+						consumer);
+				}
+			}
+			ipa_rm_peers_list_delete(resource->peers_list);
+		}
 		ipa_rm_resource_producer_delete(
 				(struct ipa_rm_resource_prod *) resource);
 		kfree((struct ipa_rm_resource_prod *) resource);
-	} else
+	} else if (resource->type == IPA_RM_CONSUMER) {
+		if (resource->peers_list) {
+			for (i = 0; i < IPA_RM_RESOURCE_PROD_MAX; ++i) {
+				producer = ipa_rm_peers_list_get_resource(
+							i,
+							resource->peers_list);
+				if (producer)
+					ipa_rm_resource_delete_dependency(
+							producer,
+							resource);
+			}
+			ipa_rm_peers_list_delete(resource->peers_list);
+		}
 		kfree((struct ipa_rm_resource_cons *) resource);
+	}
+	IPADBG("ipa_rm_resource_delete SUCCESS\n");
+	return result;
 }
 
 /**
@@ -367,6 +402,8 @@
 		result = -EPERM;
 		goto bail;
 	}
+	IPADBG("IPA RM: %s name %d ENTER\n",
+	       __func__, producer->resource.name);
 	read_lock(&producer->event_listeners_lock);
 	list_for_each(pos, &(producer->event_listeners)) {
 		reg_info = list_entry(pos,
@@ -511,6 +548,10 @@
 	unsigned long flags;
 	if (!resource || !depends_on)
 		return -EINVAL;
+	IPADBG("IPA RM: %s from %d to %d ENTER\n",
+			__func__,
+	       resource->name,
+	       depends_on->name);
 	if (!ipa_rm_peers_list_check_dependency(resource->peers_list,
 			resource->name,
 			depends_on->peers_list,
@@ -539,8 +580,6 @@
 		goto bail;
 	}
 	spin_unlock_irqrestore(&resource->state_lock, flags);
-	(void) ipa_rm_resource_consumer_release(
-			(struct ipa_rm_resource_cons *)depends_on);
 	if (ipa_rm_peers_list_has_last_peer(resource->peers_list)) {
 		(void) ipa_rm_wq_send_cmd(IPA_RM_WQ_NOTIFY_PROD,
 				resource->name,
@@ -551,6 +590,12 @@
 			depends_on->name);
 	ipa_rm_peers_list_remove_peer(depends_on->peers_list,
 			resource->name);
+	(void) ipa_rm_resource_consumer_release(
+			(struct ipa_rm_resource_cons *)depends_on);
+	IPADBG("IPA RM: %s from %d to %d SUCCESS\n",
+		__func__,
+		resource->name,
+		depends_on->name);
 bail:
 	return result;
 }
@@ -568,7 +613,7 @@
 	unsigned long flags;
 	struct ipa_rm_resource *consumer;
 	int consumer_result;
-	IPADBG("IPA RM ::ipa_rm_resource_producer_request %d ENTER\n",
+	IPADBG("IPA RM ::ipa_rm_resource_producer_request [%d] ENTER\n",
 			producer->resource.name);
 	if (ipa_rm_peers_list_is_empty(producer->resource.peers_list)) {
 		spin_lock_irqsave(&producer->resource.state_lock, flags);
@@ -628,12 +673,11 @@
 	if (producer->pending_request == 0)
 		producer->resource.state = IPA_RM_GRANTED;
 	spin_unlock_irqrestore(&producer->resource.state_lock, flags);
-	return result;
+	goto bail;
 unlock_and_bail:
 	spin_unlock_irqrestore(&producer->resource.state_lock, flags);
 bail:
-	IPADBG("IPA RM ::ipa_rm_resource_producer_request %d EXIT %d\n",
-		producer->resource.name, result);
+	IPADBG("IPA RM ::ipa_rm_resource_producer_request EXIT[%d]\n", result);
 	return result;
 }
 
@@ -651,8 +695,9 @@
 	unsigned long flags;
 	struct ipa_rm_resource *consumer;
 	int consumer_result;
-	IPADBG("IPA RM ::ipa_rm_resource_producer_release %d ENTER\n",
-		producer->resource.name);
+	IPADBG("IPA RM: %s name %d ENTER\n",
+			__func__,
+			producer->resource.name);
 	if (ipa_rm_peers_list_is_empty(producer->resource.peers_list)) {
 		spin_lock_irqsave(&producer->resource.state_lock, flags);
 		producer->resource.state = IPA_RM_RELEASED;
@@ -708,8 +753,7 @@
 	return result;
 bail:
 	spin_unlock_irqrestore(&producer->resource.state_lock, flags);
-	IPADBG("IPA RM ::ipa_rm_resource_producer_release %d EXIT %d\n",
-		producer->resource.name, result);
+	IPADBG("IPA RM ::ipa_rm_resource_producer_release EXIT[%d]\n", result);
 	return result;
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.h b/drivers/platform/msm/ipa/ipa_rm_resource.h
index b9c2e91..81ccc53 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.h
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.h
@@ -99,7 +99,7 @@
 		struct ipa_rm_create_params *create_params,
 		struct ipa_rm_resource **resource);
 
-void ipa_rm_resource_delete(struct ipa_rm_resource *resource);
+int ipa_rm_resource_delete(struct ipa_rm_resource *resource);
 
 int ipa_rm_resource_producer_register(struct ipa_rm_resource_prod *producer,
 				struct ipa_rm_register_params *reg_params);
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index 40c8fc7..c28a5ee 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -69,6 +69,13 @@
 #define TETH_TOTAL_FLT_ENTRIES_IP 2
 #define TETH_IP_FAMILIES 2
 
+/**
+ * struct mac_addresses_type - store host PC and device MAC addresses
+ * @host_pc_mac_addr: MAC address of the host PC
+ * @host_pc_mac_addr_known: is the MAC address of the host PC known ?
+ * @device_mac_addr: MAC address of the device
+ * @device_mac_addr_known: is the MAC address of the device known ?
+ */
 struct mac_addresses_type {
 	u8 host_pc_mac_addr[ETH_ALEN];
 	bool host_pc_mac_addr_known;
@@ -76,12 +83,59 @@
 	bool device_mac_addr_known;
 };
 
+/**
+ * struct stats - driver statistics, viewable using debugfs
+ * @a2_to_usb_num_sw_tx_packets: number of packets bridged from A2 to USB using
+ * the SW bridge
+ * @usb_to_a2_num_sw_tx_packets: number of packets bridged from USB to A2 using
+ * the SW bridge
+ * @num_sw_tx_packets_during_resource_wakeup: number of packets bridged during a
+ * resource wakeup period, there is a special treatment for these kind of
+ * packets
+ */
 struct stats {
 	u64 a2_to_usb_num_sw_tx_packets;
 	u64 usb_to_a2_num_sw_tx_packets;
 	u64 num_sw_tx_packets_during_resource_wakeup;
 };
 
+/**
+ * struct teth_bridge_ctx - Tethering bridge driver context information
+ * @class: kernel class pointer
+ * @dev_num: kernel device number
+ * @dev: kernel device struct pointer
+ * @cdev: kernel character device struct
+ * @usb_ipa_pipe_hdl: USB to IPA pipe handle
+ * @ipa_usb_pipe_hdl: IPA to USB pipe handle
+ * @a2_ipa_pipe_hdl: A2 to IPA pipe handle
+ * @ipa_a2_pipe_hdl: IPA to A2 pipe handle
+ * @is_connected: is the tethered bridge connected ?
+ * @link_protocol: IP / Ethernet
+ * @mac_addresses: Struct which holds host pc and device MAC addresses, relevant
+ * in ethernet mode only
+ * @is_hw_bridge_complete: is HW bridge setup ?
+ * @aggr_params: aggregation parmeters
+ * @aggr_params_known: are the aggregation parameters known ?
+ * @tethering_mode: Rmnet / MBIM
+ * @is_bridge_prod_up: completion object signaled when the bridge producer
+ * finished its resource request procedure
+ * @is_bridge_prod_down: completion object signaled when the bridge producer
+ * finished its resource release procedure
+ * @comp_hw_bridge_work: used for setting up the HW bridge using a workqueue
+ * @comp_hw_bridge_in_progress: true when the HW bridge setup is in progress
+ * @aggr_caps: aggregation capabilities
+ * @stats: statistics, how many packets were transmitted using the SW bridge
+ * @teth_wq: dedicated workqueue, used for setting up the HW bridge and for
+ * sending packets using the SW bridge when the system is waking up from power
+ * collapse
+ * @a2_ipa_hdr_len: A2 to IPA header length, used to configure the A2 endpoint
+ * for header removal
+ * @hdr_del: array to store the headers handles in order to delete them later
+ * @routing_del: array of routing rules handles, one array for IPv4 and one for
+ * IPv6
+ * @filtering_del: array of routing rules handles, one array for IPv4 and one
+ * for IPv6
+ */
 struct teth_bridge_ctx {
 	struct class *class;
 	dev_t dev_num;
@@ -117,6 +171,12 @@
 	TETH_A2_TO_USB,
 };
 
+/**
+ * struct teth_work - wrapper for an skb which is sent using a workqueue
+ * @work: used by the workqueue
+ * @skb: pointer to the skb to be sent
+ * @dir: direction of send, A2 to USB or USB to A2
+ */
 struct teth_work {
 	struct work_struct work;
 	struct sk_buff *skb;
@@ -128,6 +188,15 @@
 static char dbg_buff[TETH_MAX_MSG_LEN];
 #endif
 
+/**
+ * add_eth_hdrs() - add Ethernet headers to IPA
+ * @hdr_name_ipv4: header name for IPv4
+ * @hdr_name_ipv6: header name for IPv6
+ * @src_mac_addr: source MAC address
+ * @dst_mac_addr: destination MAC address
+ *
+ * This function is called only when link protocol is Ethernet
+ */
 static int add_eth_hdrs(char *hdr_name_ipv4, char *hdr_name_ipv6,
 			u8 *src_mac_addr, u8 *dst_mac_addr)
 {
@@ -269,6 +338,12 @@
 	return res;
 }
 
+/**
+ * configure_ipa_header_block() - adds headers and configures endpoint registers
+ *
+ * - For IP link protocol and MBIM aggregation, configure MBIM header
+ * - For Ethernet link protocol, configure Ethernet headers
+ */
 static int configure_ipa_header_block(void)
 {
 	int res;
@@ -412,6 +487,14 @@
 	return res;
 }
 
+/**
+ * configure_ipa_routing_block() - Configure the IPA routing block
+ *
+ * This function configures IPA for:
+ * - Route all packets from USB to A2
+ * - Route all packets from A2 to USB
+ * - Use the correct headers in Ethernet or MBIM cases
+ */
 static int configure_ipa_routing_block(void)
 {
 	int res;
@@ -547,6 +630,13 @@
 	return res;
 }
 
+/**
+ * configure_ipa_filtering_block() - Configures IPA filtering block
+ *
+ * This function configures IPA for:
+ * - Filter all traffic coming from USB to A2 pointing routing table
+ * - Filter all traffic coming from A2 to USB pointing routing table
+ */
 static int configure_ipa_filtering_block(void)
 {
 	int res;
@@ -663,6 +753,11 @@
 	}
 }
 
+/**
+ * teth_set_aggregation() - set aggregation parameters to IPA
+ *
+ * The parameters to this function are passed in the context variable ipa_ctx.
+ */
 static int teth_set_aggregation(void)
 {
 	int res;
@@ -727,6 +822,14 @@
 	return res;
 }
 
+/**
+ * teth_request_resource() - wrapper function to
+ * ipa_rm_inactivity_timer_request_resource()
+ *
+ * - initialize the is_bridge_prod_up completion object
+ * - request the resource
+ * - error handling
+ */
 static int teth_request_resource(void)
 {
 	int res;
@@ -744,6 +847,10 @@
 	return 0;
 }
 
+/**
+ * complete_hw_bridge() - setup the HW bridge from USB to A2 and back through
+ * IPA
+ */
 static void complete_hw_bridge(struct work_struct *work)
 {
 	int res;
@@ -812,6 +919,20 @@
 		  mac_addr[4], mac_addr[5]);
 }
 
+/**
+ * check_to_complete_hw_bridge() - can HW bridge be set up ?
+ * @param skb: pointer to socket buffer
+ * @param my_mac_addr: pointer to write 'my' extracted MAC address to
+ * @param my_mac_addr_known: pointer to update whether 'my' extracted MAC
+ * address is known
+ * @param peer_mac_addr_known: pointer to update whether the 'peer' extracted
+ * MAC address is known
+ *
+ * This function is used by both A2 and USB callback functions, therefore the
+ * meaning of 'my' and 'peer' changes according to the context.
+ * Extracts MAC address from the packet in Ethernet link protocol,
+ * Sets up the HW bridge in case all conditions are met.
+ */
 static void check_to_complete_hw_bridge(struct sk_buff *skb,
 					u8 *my_mac_addr,
 					bool *my_mac_addr_known,
@@ -841,6 +962,9 @@
 	}
 }
 
+/**
+ * teth_send_skb_work() - workqueue function for sending a packet
+ */
 static void teth_send_skb_work(struct work_struct *work)
 {
 	struct teth_work *work_data =
@@ -887,6 +1011,15 @@
 	kfree(work_data);
 }
 
+/**
+ * defer_skb_send() - defer sending an skb using the SW bridge to a workqueue
+ * @param skb: pointer to the socket buffer
+ * @param dir: direction of send
+ *
+ * In case where during a packet send, the A2 or USB needs to wake up from power
+ * collapse, defer the send and return the context to IPA driver. This is
+ * important since IPA driver has a single threaded Rx path.
+ */
 static void defer_skb_send(struct sk_buff *skb, enum teth_packet_direction dir)
 {
 	struct teth_work *work = kmalloc(sizeof(struct teth_work), GFP_KERNEL);
@@ -909,6 +1042,30 @@
 	queue_work(teth_ctx->teth_wq, &work->work);
 }
 
+/**
+ * usb_notify_cb() - callback function for sending packets from USB to A2
+ * @param priv: private data
+ * @param evt: event - RECEIVE or WRITE_DONE
+ * @param data: pointer to skb to be sent
+ *
+ * This callback function is installed by the IPA driver, it is invoked in 2
+ * cases:
+ * 1. When a packet comes from the USB pipe and is routed to A5 (SW bridging)
+ * 2. After a packet has been bridged from USB to A2 and its skb should be freed
+ *
+ * Invocation: sps driver --> IPA driver --> bridge driver
+ *
+ * In the event of IPA_RECEIVE:
+ * - Checks whether the HW bridge can be set up..
+ * - Requests the BRIDGE_PROD resource so that A2 and USB are not in power
+ * collapse. In case where the resource is waking up, defer the send operation
+ * to a workqueue in order to not block the IPA driver single threaded Rx path.
+ * - Sends the packets to A2 using a2_service driver API.
+ * - Releases the BRIDGE_PROD resource.
+ *
+ * In the event of IPA_WRITE_DONE:
+ * - Frees the skb memory
+ */
 static void usb_notify_cb(void *priv,
 			  enum ipa_dp_evt_type evt,
 			  unsigned long data)
@@ -969,6 +1126,30 @@
 	return;
 }
 
+/**
+ * a2_notify_cb() - callback function for sending packets from A2 to USB
+ * @param user_data: private data
+ * @param event: event - RECEIVE or WRITE_DONE
+ * @param data: pointer to skb to be sent
+ *
+ * This callback function is installed by the IPA driver, it is invoked in 2
+ * cases:
+ * 1. When a packet comes from the A2 pipe and is routed to A5 (SW bridging)
+ * 2. After a packet has been bridged from A2 to USB and its skb should be freed
+ *
+ * Invocation: sps driver --> IPA driver --> a2_service driver --> bridge driver
+ *
+ * In the event of A2_MUX_RECEIVE:
+ * - Checks whether the HW bridge can be set up..
+ * - Requests the BRIDGE_PROD resource so that A2 and USB are not in power
+ * collapse. In case where the resource is waking up, defer the send operation
+ * to a workqueue in order to not block the IPA driver single threaded Rx path.
+ * - Sends the packets to USB using IPA drivers ipa_tx_dp() API.
+ * - Releases the BRIDGE_PROD resource.
+ *
+ * In the event of A2_MUX_WRITE_DONE:
+ * - Frees the skb memory
+ */
 static void a2_notify_cb(void *user_data,
 			 enum a2_mux_event_type event,
 			 unsigned long data)
@@ -1031,6 +1212,15 @@
 	return;
 }
 
+/**
+ * bridge_prod_notify_cb() - IPA Resource Manager callback function
+ * @param notify_cb_data: private data
+ * @param event: RESOURCE_GRANTED / RESOURCE_RELEASED
+ * @param data: not used in this case
+ *
+ * This callback function is called by IPA resource manager to notify the
+ * BRIDGE_PROD entity of events like RESOURCE_GRANTED and RESOURCE_RELEASED.
+ */
 static void bridge_prod_notify_cb(void *notify_cb_data,
 				  enum ipa_rm_event event,
 				  unsigned long data)
@@ -1075,10 +1265,17 @@
 
 /**
 * teth_bridge_init() - Initialize the Tethering bridge driver
-* @usb_notify_cb_ptr:	Callback function which should be used
-*			by the caller. Output parameter.
-* @private_data_ptr:	Data for the callback function. Should
-*			be used by the caller. Output parameter.
+* @usb_notify_cb_ptr:	Callback function which should be used by the caller.
+* Output parameter.
+* @private_data_ptr:	Data for the callback function. Should be used by the
+* caller. Output parameter.
+*
+* USB driver gets a pointer to a callback function (usb_notify_cb) and an
+* associated data. USB driver installs this callback function in the call to
+* ipa_connect().
+*
+* Builds IPA resource manager dependency graph.
+*
 * Return codes: 0: success,
 *		-EINVAL - Bad parameter
 *		Other negative value - Failure
@@ -1145,6 +1342,9 @@
 }
 EXPORT_SYMBOL(teth_bridge_init);
 
+/**
+ * initialize_context() - Initialize the ipa_ctx struct
+ */
 static void initialize_context(void)
 {
 	TETH_DBG_FUNC_ENTRY();
@@ -1198,10 +1398,6 @@
 
 /**
 * teth_bridge_disconnect() - Disconnect tethering bridge module
-*
-* Return codes:	0: success
-*		-EPERM: Operation not permitted as the bridge is already
-*		disconnected
 */
 int teth_bridge_disconnect(void)
 {
@@ -1384,6 +1580,9 @@
 		   TETH_AGGR_MAX_AGGR_PACKET_SIZE_DEFAULT;
 }
 
+/**
+ * teth_set_bridge_mode() - set the link protocol (IP / Ethernet)
+ */
 static void teth_set_bridge_mode(enum teth_link_protocol_type link_protocol)
 {
 	teth_ctx->link_protocol = link_protocol;
@@ -1391,6 +1590,14 @@
 	memset(&teth_ctx->mac_addresses, 0, sizeof(teth_ctx->mac_addresses));
 }
 
+/**
+ * teth_bridge_set_aggr_params() - kernel API to set aggregation parameters
+ * @param aggr_params: aggregation parmeters for uplink and downlink
+ *
+ * Besides setting the aggregation parameters, the function enforces max tranfer
+ * size which is less then 8K and also forbids Ethernet link protocol with MBIM
+ * aggregation which is not supported by HW.
+ */
 int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params)
 {
 	int res;
@@ -1540,6 +1747,10 @@
 	return res;
 }
 
+/**
+ * set_aggr_capabilities() - allocates and fills the aggregation capabilities
+ * struct
+ */
 static int set_aggr_capabilities(void)
 {
 	u16 NUM_PROTOCOLS = 2;
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 52c523e..442d18f 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -319,6 +319,7 @@
 #define QPNP_ENABLE_LUT_CONTROL		qpnp_set_control(0, 0, 0, 0, 1)
 #define QPNP_ENABLE_PWM_CONTROL		qpnp_set_control(0, 0, 0, 1, 0)
 #define QPNP_ENABLE_PWM_MODE		qpnp_set_control(1, 1, 1, 1, 0)
+#define QPNP_ENABLE_PWM_MODE_GPLED_CHANNEL	qpnp_set_control(1, 1, 1, 1, 1)
 #define QPNP_ENABLE_LPG_MODE		qpnp_set_control(1, 1, 1, 0, 1)
 #define QPNP_DISABLE_PWM_MODE		qpnp_set_control(0, 0, 0, 1, 0)
 #define QPNP_DISABLE_LPG_MODE		qpnp_set_control(0, 0, 0, 0, 1)
@@ -908,6 +909,17 @@
 
 }
 
+#define QPNP_GPLED_LPG_CHANNEL_RANGE_START 8
+#define QPNP_GPLED_LPG_CHANNEL_RANGE_END 11
+
+static inline int qpnp_enable_pwm_mode(struct qpnp_pwm_config *pwm_conf)
+{
+	if (pwm_conf->channel_id >= QPNP_GPLED_LPG_CHANNEL_RANGE_START ||
+		pwm_conf->channel_id <= QPNP_GPLED_LPG_CHANNEL_RANGE_END)
+		return QPNP_ENABLE_PWM_MODE_GPLED_CHANNEL;
+	return QPNP_ENABLE_PWM_MODE;
+}
+
 static int qpnp_lpg_configure_pwm_state(struct pwm_device *pwm,
 					enum qpnp_pwm_state state)
 {
@@ -917,7 +929,7 @@
 	int			rc;
 
 	if (state == QPNP_PWM_ENABLE)
-		value = QPNP_ENABLE_PWM_MODE;
+		value = qpnp_enable_pwm_mode(&pwm->pwm_config);
 	else
 		value = QPNP_DISABLE_PWM_MODE;
 
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 1d0fb5d..2d1b763 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -27,9 +27,11 @@
 #include <linux/workqueue.h>
 #include <linux/dma-mapping.h>
 #include <mach/msm_smsm.h>
+#include <linux/pm_runtime.h>
 
 #define USB_THRESHOLD 512
 #define USB_BAM_MAX_STR_LEN 50
+#define USB_BAM_TIMEOUT (10*HZ)
 
 enum usb_bam_sm {
 	USB_BAM_SM_INIT = 0,
@@ -73,6 +75,11 @@
 *	handle/device of the sps driver.
 * @pipes_enabled_per_bam: This array stores for each BAM
 *	("ssusb", "hsusb" or "hsic") the number of pipes currently enabled.
+* @inactivity_timer_ms: The timeout configuration per each bam for inactivity
+*	timer feature.
+* @is_bam_inactivity: Is there no activity on all pipes belongs to a
+*	specific bam. (no activity = no data is pulled or pushed
+*	from/into ones of the pipes).
 */
 struct usb_bam_ctx_type {
 	struct usb_bam_sps_type usb_bam_sps;
@@ -85,19 +92,61 @@
 	char qdss_core_name[USB_BAM_MAX_STR_LEN];
 	u32 h_bam[MAX_BAMS];
 	u8 pipes_enabled_per_bam[MAX_BAMS];
+	u32 inactivity_timer_ms[MAX_BAMS];
+	bool is_bam_inactivity[MAX_BAMS];
 };
 
-static char *bam_enable_strings[3] = {
+static char *bam_enable_strings[MAX_BAMS] = {
 	[SSUSB_BAM] = "ssusb",
 	[HSUSB_BAM] = "hsusb",
 	[HSIC_BAM]  = "hsic",
 };
 
-static spinlock_t usb_bam_lock;
+static enum usb_bam ipa_rm_bams[] = {HSUSB_BAM, HSIC_BAM};
+
+static enum ipa_client_type ipa_rm_resource_prod[MAX_BAMS] = {
+	[HSUSB_BAM] = IPA_RM_RESOURCE_USB_PROD,
+	[HSIC_BAM]  = IPA_RM_RESOURCE_HSIC_PROD,
+};
+
+static enum ipa_client_type ipa_rm_resource_cons[MAX_BAMS] = {
+	[HSUSB_BAM] = IPA_RM_RESOURCE_USB_CONS,
+	[HSIC_BAM]  = IPA_RM_RESOURCE_HSIC_CONS,
+};
+
+static int usb_cons_request_resource(void);
+static int usb_cons_release_resource(void);
+static int hsic_cons_request_resource(void);
+static int hsic_cons_release_resource(void);
+
+static int (*request_resource_cb[MAX_BAMS])(void) = {
+	[HSUSB_BAM] = usb_cons_request_resource,
+	[HSIC_BAM]  = hsic_cons_request_resource,
+};
+
+static int (*release_resource_cb[MAX_BAMS])(void)  = {
+	[HSUSB_BAM] = usb_cons_release_resource,
+	[HSIC_BAM]  = hsic_cons_release_resource,
+};
+
+static enum ipa_rm_event cur_prod_state[MAX_BAMS];
+static enum ipa_rm_event cur_cons_state[MAX_BAMS];
+static int sched_lpm;
+static int lpm_wait_handshake;
+static struct completion prod_avail[MAX_BAMS];
+static struct completion cons_avail[MAX_BAMS];
+static struct completion cons_released[MAX_BAMS];
+static struct completion prod_released[MAX_BAMS];
+
+static spinlock_t usb_bam_peer_handshake_info_lock;
 static struct usb_bam_peer_handshake_info peer_handshake_info;
+static spinlock_t usb_bam_lock; /* Protect ctx and usb_bam_connections */
 static struct usb_bam_pipe_connect *usb_bam_connections;
 static struct usb_bam_ctx_type ctx;
 
+static int __usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
+	void *param, bool trigger_cb_per_pipe);
+
 static int get_bam_type_from_core_name(const char *name)
 {
 	if (strnstr(name, bam_enable_strings[SSUSB_BAM],
@@ -128,6 +177,42 @@
 	return false;
 }
 
+static void usb_bam_set_inactivity_timer(enum usb_bam bam)
+{
+	struct sps_timer_ctrl timer_ctrl;
+	struct usb_bam_pipe_connect *pipe_connect;
+	struct sps_pipe *pipe = NULL;
+	int i;
+
+	/*
+	 * Since we configure global incativity timer for all pipes
+	 * and not per each pipe, it is enough to use some pipe
+	 * handle associated with this bam, so just find the first one.
+	 * This pipe handle is required due to SPS driver API we use below.
+	 */
+	for (i = 0; i < ctx.max_connections; i++) {
+		pipe_connect = &usb_bam_connections[i];
+		if (pipe_connect->bam_type == bam) {
+			pipe = ctx.usb_bam_sps.sps_pipes[i];
+			break;
+		}
+	}
+
+	if (!pipe) {
+		pr_err("%s: Bam %s has no pipes\n", __func__,
+			bam_enable_strings[bam]);
+		return;
+	}
+
+	timer_ctrl.op = SPS_TIMER_OP_CONFIG;
+	timer_ctrl.mode = SPS_TIMER_MODE_ONESHOT;
+	timer_ctrl.timeout_msec = ctx.inactivity_timer_ms[bam];
+	sps_timer_ctrl(pipe, &timer_ctrl, NULL);
+
+	timer_ctrl.op = SPS_TIMER_OP_RESET;
+	sps_timer_ctrl(pipe, &timer_ctrl, NULL);
+}
+
 static int connect_pipe(u8 idx, u32 *usb_pipe_idx)
 {
 	int ret, ram1_value;
@@ -281,6 +366,7 @@
 		pr_err("%s: sps_connect failed %d\n", __func__, ret);
 		goto error;
 	}
+
 	return 0;
 
 error:
@@ -323,6 +409,10 @@
 		return ret;
 	}
 
+	pipe_connect->activity_notify = ipa_params->activity_notify;
+	pipe_connect->inactivity_notify = ipa_params->inactivity_notify;
+	pipe_connect->priv = ipa_params->priv;
+
 	/* IPA input parameters */
 	ipa_in_params.client_bam_hdl = usb_handle;
 	ipa_in_params.desc_fifo_sz = pipe_connect->desc_fifo_size;
@@ -395,6 +485,7 @@
 			__func__,
 			pipe_connect->src_pipe_index,
 			pipe_connect->dst_pipe_index);
+		sps_connection->options = SPS_O_NO_DISABLE;
 	} else {
 		/* IPA src, USB dest */
 		sps_connection->mode = SPS_MODE_DEST;
@@ -409,12 +500,13 @@
 			__func__,
 			pipe_connect->src_pipe_index,
 			pipe_connect->dst_pipe_index);
+		sps_connection->options = 0;
 	}
 
 	sps_connection->data = sps_out_params.data;
 	sps_connection->desc = sps_out_params.desc;
 	sps_connection->event_thresh = 16;
-	sps_connection->options = SPS_O_AUTO_ENABLE;
+	sps_connection->options |= SPS_O_AUTO_ENABLE;
 
 	ret = sps_connect(*pipe, sps_connection);
 	if (ret < 0) {
@@ -422,6 +514,16 @@
 		goto error;
 	}
 
+	spin_lock(&usb_bam_lock);
+
+	/* Set global inactivity timer upon first pipe connection */
+	if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0 &&
+		ctx.inactivity_timer_ms[pipe_connect->bam_type] &&
+		pipe_connect->inactivity_notify)
+		usb_bam_set_inactivity_timer(pipe_connect->bam_type);
+
+	spin_unlock(&usb_bam_lock);
+
 	return 0;
 
 error:
@@ -505,6 +607,8 @@
 		return -EINVAL;
 	}
 
+	spin_lock(&usb_bam_lock);
+
 	/* Check if BAM requires RESET before connect and reset of first pipe */
 	if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
 	    (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
@@ -513,24 +617,34 @@
 	ret = connect_pipe(idx, bam_pipe_idx);
 	if (ret) {
 		pr_err("%s: pipe connection[%d] failure\n", __func__, idx);
+		spin_unlock(&usb_bam_lock);
 		return ret;
 	}
 
 	pipe_connect->enabled = 1;
 	ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
 
+	spin_unlock(&usb_bam_lock);
 	return 0;
 }
 
 static void usb_prod_notify_cb(void *user_data, enum ipa_rm_event event,
 	unsigned long data)
 {
+	enum usb_bam *cur_bam = (void *)user_data;
+
 	switch (event) {
 	case IPA_RM_RESOURCE_GRANTED:
-		pr_debug("USB_PROD resource granted\n");
+		pr_debug("%s: %s_PROD resource granted\n",
+			__func__, bam_enable_strings[*cur_bam]);
+		cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_GRANTED;
+		complete_all(&prod_avail[*cur_bam]);
 		break;
 	case IPA_RM_RESOURCE_RELEASED:
-		pr_debug("USB_PROD resource released\n");
+		pr_debug("%s: %s_PROD resource released\n",
+			__func__, bam_enable_strings[*cur_bam]);
+		cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_RELEASED;
+		complete_all(&prod_released[*cur_bam]);
 		break;
 	default:
 		break;
@@ -538,50 +652,130 @@
 	return;
 }
 
+static int cons_request_resource(enum usb_bam cur_bam)
+{
+	pr_debug("%s: Request %s_CONS resource\n",
+			__func__, bam_enable_strings[cur_bam]);
+
+	cur_cons_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
+	complete_all(&cons_avail[cur_bam]);
+
+	if (ctx.pipes_enabled_per_bam[cur_bam])
+		return 0;
+
+	return -EINPROGRESS;
+}
+
 static int usb_cons_request_resource(void)
 {
-	pr_debug(": Requesting USB_CONS resource\n");
-	return 0;
+	return cons_request_resource(HSUSB_BAM);
+}
+
+static int hsic_cons_request_resource(void)
+{
+	return cons_request_resource(HSIC_BAM);
+}
+
+static int cons_release_resource(enum usb_bam cur_bam)
+{
+	pr_debug("%s: Release %s_CONS resource\n",
+			__func__, bam_enable_strings[cur_bam]);
+
+	cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
+	complete_all(&cons_released[cur_bam]);
+
+	if (!ctx.pipes_enabled_per_bam[cur_bam])
+		return 0;
+
+	return -EINPROGRESS;
+}
+
+static int hsic_cons_release_resource(void)
+{
+	return cons_release_resource(HSIC_BAM);
 }
 
 static int usb_cons_release_resource(void)
 {
-	pr_debug(": Releasing USB_CONS resource\n");
-	return 0;
+	return cons_release_resource(HSUSB_BAM);
 }
 
 static void usb_bam_ipa_create_resources(void)
 {
 	struct ipa_rm_create_params usb_prod_create_params;
 	struct ipa_rm_create_params usb_cons_create_params;
+	enum usb_bam cur_bam;
+	int ret, i;
+
+	for (i = 0; i < ARRAY_SIZE(ipa_rm_bams); i++) {
+		/* Create USB/HSIC_PROD entity */
+		cur_bam = ipa_rm_bams[i];
+
+		memset(&usb_prod_create_params, 0,
+					sizeof(usb_prod_create_params));
+		usb_prod_create_params.name = ipa_rm_resource_prod[cur_bam];
+		usb_prod_create_params.reg_params.notify_cb =
+							usb_prod_notify_cb;
+		usb_prod_create_params.reg_params.user_data = &ipa_rm_bams[i];
+		ret = ipa_rm_create_resource(&usb_prod_create_params);
+		if (ret) {
+			pr_err("%s: Failed to create USB_PROD resource\n",
+								__func__);
+			return;
+		}
+
+		/* Create USB_CONS entity */
+		memset(&usb_cons_create_params, 0,
+					sizeof(usb_cons_create_params));
+		usb_cons_create_params.name = ipa_rm_resource_cons[cur_bam];
+		usb_cons_create_params.request_resource =
+						request_resource_cb[cur_bam];
+		usb_cons_create_params.release_resource =
+						release_resource_cb[cur_bam];
+		ret = ipa_rm_create_resource(&usb_cons_create_params);
+		if (ret) {
+			pr_err("%s: Failed to create USB_CONS resource\n",
+								__func__);
+			return ;
+		}
+	}
+}
+
+static void wait_for_prod_granted(enum usb_bam cur_bam)
+{
 	int ret;
 
-	/* Create USB_PROD entity */
-	memset(&usb_prod_create_params, 0, sizeof(usb_prod_create_params));
-	usb_prod_create_params.name = IPA_RM_RESOURCE_USB_PROD;
-	usb_prod_create_params.reg_params.notify_cb = usb_prod_notify_cb;
-	usb_prod_create_params.reg_params.user_data = NULL;
-	ret = ipa_rm_create_resource(&usb_prod_create_params);
-	if (ret) {
-		pr_err("%s: Failed to create USB_PROD resource\n", __func__);
-		return;
-	}
+	pr_debug("%s Request %s_PROD_RES\n", __func__,
+		bam_enable_strings[cur_bam]);
+	if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
+		pr_debug("%s: CONS already granted for some reason\n",
+			__func__);
+	if (cur_prod_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
+		pr_debug("%s: PROD already granted for some reason\n",
+			__func__);
 
-	/* Create USB_CONS entity */
-	memset(&usb_cons_create_params, 0, sizeof(usb_cons_create_params));
-	usb_cons_create_params.name = IPA_RM_RESOURCE_USB_CONS;
-	usb_cons_create_params.request_resource = usb_cons_request_resource;
-	usb_cons_create_params.release_resource = usb_cons_release_resource;
-	ret = ipa_rm_create_resource(&usb_cons_create_params);
-	if (ret) {
-		pr_err("%s: Failed to create USB_CONS resource\n", __func__);
-		return ;
-	}
+	init_completion(&prod_avail[cur_bam]);
+	init_completion(&cons_avail[cur_bam]);
+
+	ret = ipa_rm_request_resource(ipa_rm_resource_prod[cur_bam]);
+	if (!ret) {
+		cur_prod_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
+		complete_all(&prod_avail[cur_bam]);
+		pr_debug("%s: PROD_GRANTED without wait\n", __func__);
+	} else if (ret == -EINPROGRESS) {
+		pr_debug("%s: Waiting for PROD_GRANTED\n", __func__);
+		if (!wait_for_completion_timeout(&prod_avail[cur_bam],
+			USB_BAM_TIMEOUT))
+			pr_err("%s: Timeout wainting for PROD_GRANTED\n",
+				__func__);
+	} else
+		pr_err("%s: ipa_rm_request_resource ret =%d\n", __func__, ret);
 }
 
 int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	u8 idx;
+	enum usb_bam cur_bam;
 	struct usb_bam_pipe_connect *pipe_connect;
 	int ret;
 	struct msm_usb_bam_platform_data *pdata =
@@ -604,6 +798,14 @@
 		return -EINVAL;
 	}
 	pipe_connect = &usb_bam_connections[idx];
+	cur_bam = pipe_connect->bam_type;
+
+	if (cur_bam == HSUSB_BAM) {
+		spin_lock(&usb_bam_lock);
+		sched_lpm = 0;
+		lpm_wait_handshake = 1;
+		spin_unlock(&usb_bam_lock);
+	}
 
 	if (pipe_connect->enabled) {
 		pr_debug("%s: connection %d was already established\n",
@@ -611,21 +813,40 @@
 		return 0;
 	}
 
-	/* Check if BAM requires RESET before connect and reset of first pipe */
-	if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
-	    (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
-		sps_device_reset(ctx.h_bam[pipe_connect->bam_type]);
+	spin_lock(&usb_bam_lock);
+
+	 /* Check if BAM requires RESET before connect and reset first pipe */
+	 if ((pdata->reset_on_connect[cur_bam] == true) &&
+		 (ctx.pipes_enabled_per_bam[cur_bam] == 0))
+			sps_device_reset(ctx.h_bam[cur_bam]);
+
+	spin_unlock(&usb_bam_lock);
+
+	if (ipa_params->dir == USB_TO_PEER_PERIPHERAL) {
+		pr_debug("%s: Starting connect sequence\n", __func__);
+		wait_for_prod_granted(cur_bam);
+	}
 
 	ret = connect_pipe_ipa(idx, ipa_params);
-	ipa_rm_request_resource(IPA_RM_RESOURCE_USB_PROD);
-
 	if (ret) {
-		pr_err("%s: dst pipe connection failure\n", __func__);
+		pr_err("%s: pipe connection failure\n", __func__);
 		return ret;
 	}
 
+	spin_lock(&usb_bam_lock);
+
 	pipe_connect->enabled = 1;
-	ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
+	ctx.pipes_enabled_per_bam[cur_bam] += 1;
+
+	if (ipa_params->dir == PEER_PERIPHERAL_TO_USB &&
+		cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED) {
+		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
+					 ipa_rm_resource_cons[cur_bam]);
+		pr_debug("%s: Ended connect sequence\n", __func__);
+	}
+
+	spin_unlock(&usb_bam_lock);
 
 	return 0;
 }
@@ -633,22 +854,22 @@
 
 int usb_bam_client_ready(bool ready)
 {
-	spin_lock(&usb_bam_lock);
+	spin_lock(&usb_bam_peer_handshake_info_lock);
 	if (peer_handshake_info.client_ready == ready) {
 		pr_debug("%s: client state is already %d\n",
 			__func__, ready);
-		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_peer_handshake_info_lock);
 		return 0;
 	}
 
 	peer_handshake_info.client_ready = ready;
 
-	spin_unlock(&usb_bam_lock);
+	spin_unlock(&usb_bam_peer_handshake_info_lock);
 	if (!queue_work(ctx.usb_bam_wq,
 			&peer_handshake_info.reset_event.event_w)) {
-		spin_lock(&usb_bam_lock);
+		spin_lock(&usb_bam_peer_handshake_info_lock);
 		peer_handshake_info.pending_work++;
-		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_peer_handshake_info_lock);
 	}
 
 	return 0;
@@ -656,18 +877,108 @@
 
 static void usb_bam_work(struct work_struct *w)
 {
+	int i;
 	struct usb_bam_event_info *event_info =
 		container_of(w, struct usb_bam_event_info, event_w);
+	struct usb_bam_pipe_connect *pipe_connect =
+		container_of(event_info, struct usb_bam_pipe_connect, event);
+	struct usb_bam_pipe_connect *pipe_connect_iter;
+	int (*callback)(void *priv);
+	void *param = NULL;
 
-	event_info->callback(event_info->param);
+	switch (event_info->type) {
+	case USB_BAM_EVENT_WAKEUP:
+	case USB_BAM_EVENT_WAKEUP_PIPE:
+
+		pr_debug("%s recieved USB_BAM_EVENT_WAKEUP\n", __func__);
+
+		/* Notify about wakeup / activity of the bam */
+		event_info->callback(event_info->param);
+
+		/*
+		 * Reset inactivity timer counter if this pipe's bam
+		 * has inactivity timeout.
+		 */
+		spin_lock(&usb_bam_lock);
+		if (ctx.inactivity_timer_ms[pipe_connect->bam_type])
+			usb_bam_set_inactivity_timer(pipe_connect->bam_type);
+		spin_unlock(&usb_bam_lock);
+
+		break;
+
+	case USB_BAM_EVENT_INACTIVITY:
+
+		pr_debug("%s recieved USB_BAM_EVENT_INACTIVITY\n", __func__);
+
+		/*
+		 * Since event info is one structure per pipe, it might be
+		 * overriden when we will register the wakeup events below,
+		 * and still we want ot register the wakeup events before we
+		 * notify on the inactivity in order to identify the next
+		 * activity as soon as possible.
+		 */
+		callback = event_info->callback;
+		param = event_info->param;
+
+		/*
+		 * Upon inactivity, configure wakeup irq for all pipes
+		 * that are into the usb bam.
+		 */
+		spin_lock(&usb_bam_lock);
+		for (i = 0; i < ctx.max_connections; i++) {
+			pipe_connect_iter = &usb_bam_connections[i];
+			if (pipe_connect_iter->bam_type ==
+				pipe_connect->bam_type &&
+			    pipe_connect_iter->dir ==
+				PEER_PERIPHERAL_TO_USB &&
+				pipe_connect_iter->enabled) {
+				__usb_bam_register_wake_cb(i,
+					pipe_connect_iter->activity_notify,
+					pipe_connect_iter->priv,
+					false);
+			}
+		}
+		spin_unlock(&usb_bam_lock);
+
+		/* Notify about the inactivity */
+		if (callback)
+			callback(param);
+
+		break;
+	default:
+		pr_err("%s: unknown usb bam event type %d\n", __func__,
+			event_info->type);
+	}
 }
 
 static void usb_bam_wake_cb(struct sps_event_notify *notify)
 {
-	struct usb_bam_event_info *wake_event_info =
+	struct usb_bam_event_info *event_info =
 		(struct usb_bam_event_info *)notify->user;
+	struct usb_bam_pipe_connect *pipe_connect =
+		container_of(event_info,
+			     struct usb_bam_pipe_connect,
+			     event);
 
-	queue_work(ctx.usb_bam_wq, &wake_event_info->event_w);
+	spin_lock(&usb_bam_lock);
+
+	if (event_info->type == USB_BAM_EVENT_WAKEUP_PIPE)
+		queue_work(ctx.usb_bam_wq, &event_info->event_w);
+	else if (event_info->type == USB_BAM_EVENT_WAKEUP &&
+			ctx.is_bam_inactivity[pipe_connect->bam_type]) {
+
+		/*
+		 * Sps wake event is per pipe, so usb_bam_wake_cb is
+		 * called per pipe. However, we want to filter the wake
+		 * event to be wake event per all the pipes.
+		 * Therefore, the first pipe that awaked will be considered
+		 * as global bam wake event.
+		 */
+		ctx.is_bam_inactivity[pipe_connect->bam_type] = false;
+		queue_work(ctx.usb_bam_wq, &event_info->event_w);
+	}
+
+	spin_unlock(&usb_bam_lock);
 }
 
 static void usb_bam_sm_work(struct work_struct *w)
@@ -675,15 +986,15 @@
 	pr_debug("%s: current state: %d\n", __func__,
 		peer_handshake_info.state);
 
-	spin_lock(&usb_bam_lock);
+	spin_lock(&usb_bam_peer_handshake_info_lock);
 
 	switch (peer_handshake_info.state) {
 	case USB_BAM_SM_INIT:
 		if (peer_handshake_info.client_ready) {
-			spin_unlock(&usb_bam_lock);
+			spin_unlock(&usb_bam_peer_handshake_info_lock);
 			smsm_change_state(SMSM_APPS_STATE, 0,
 				SMSM_USB_PLUG_UNPLUG);
-			spin_lock(&usb_bam_lock);
+			spin_lock(&usb_bam_peer_handshake_info_lock);
 			peer_handshake_info.state = USB_BAM_SM_PLUG_NOTIFIED;
 		}
 		break;
@@ -695,19 +1006,19 @@
 		break;
 	case USB_BAM_SM_PLUG_ACKED:
 		if (!peer_handshake_info.client_ready) {
-			spin_unlock(&usb_bam_lock);
+			spin_unlock(&usb_bam_peer_handshake_info_lock);
 			smsm_change_state(SMSM_APPS_STATE,
 				SMSM_USB_PLUG_UNPLUG, 0);
-			spin_lock(&usb_bam_lock);
+			spin_lock(&usb_bam_peer_handshake_info_lock);
 			peer_handshake_info.state = USB_BAM_SM_UNPLUG_NOTIFIED;
 		}
 		break;
 	case USB_BAM_SM_UNPLUG_NOTIFIED:
 		if (peer_handshake_info.ack_received) {
-			spin_unlock(&usb_bam_lock);
+			spin_unlock(&usb_bam_peer_handshake_info_lock);
 			peer_handshake_info.reset_event.
 				callback(peer_handshake_info.reset_event.param);
-			spin_lock(&usb_bam_lock);
+			spin_lock(&usb_bam_peer_handshake_info_lock);
 			peer_handshake_info.state = USB_BAM_SM_INIT;
 			peer_handshake_info.ack_received = 0;
 		}
@@ -716,12 +1027,12 @@
 
 	if (peer_handshake_info.pending_work) {
 		peer_handshake_info.pending_work--;
-		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_peer_handshake_info_lock);
 		queue_work(ctx.usb_bam_wq,
 			&peer_handshake_info.reset_event.event_w);
-		spin_lock(&usb_bam_lock);
+		spin_lock(&usb_bam_peer_handshake_info_lock);
 	}
-	spin_unlock(&usb_bam_lock);
+	spin_unlock(&usb_bam_peer_handshake_info_lock);
 }
 
 static void usb_bam_ack_toggle_cb(void *priv,
@@ -730,29 +1041,29 @@
 	static int last_processed_state;
 	int current_state;
 
-	spin_lock(&usb_bam_lock);
+	spin_lock(&usb_bam_peer_handshake_info_lock);
 
 	current_state = new_state & SMSM_USB_PLUG_UNPLUG;
 
 	if (current_state == last_processed_state) {
-		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_peer_handshake_info_lock);
 		return;
 	}
 
 	last_processed_state = current_state;
 	peer_handshake_info.ack_received = true;
 
-	spin_unlock(&usb_bam_lock);
+	spin_unlock(&usb_bam_peer_handshake_info_lock);
 	if (!queue_work(ctx.usb_bam_wq,
 			&peer_handshake_info.reset_event.event_w)) {
-		spin_lock(&usb_bam_lock);
+		spin_lock(&usb_bam_peer_handshake_info_lock);
 		peer_handshake_info.pending_work++;
-		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_peer_handshake_info_lock);
 	}
 }
 
-int usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
-	void *param)
+static int __usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
+	void *param, bool trigger_cb_per_pipe)
 {
 	struct sps_pipe *pipe = ctx.usb_bam_sps.sps_pipes[idx];
 	struct sps_connect *sps_connection;
@@ -767,8 +1078,11 @@
 	pipe = ctx.usb_bam_sps.sps_pipes[idx];
 	sps_connection = &ctx.usb_bam_sps.sps_connections[idx];
 	pipe_connect = &usb_bam_connections[idx];
-	wake_event_info = &pipe_connect->wake_event;
+	wake_event_info = &pipe_connect->event;
 
+	wake_event_info->type = (trigger_cb_per_pipe ?
+				USB_BAM_EVENT_WAKEUP_PIPE :
+				USB_BAM_EVENT_WAKEUP);
 	wake_event_info->param = param;
 	wake_event_info->callback = callback;
 	wake_event_info->event.mode = SPS_TRIGGER_CALLBACK;
@@ -794,6 +1108,12 @@
 	return 0;
 }
 
+int usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
+	void *param)
+{
+	return __usb_bam_register_wake_cb(idx, callback, param, true);
+}
+
 int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param)
 {
 	u32 ret = 0;
@@ -831,44 +1151,121 @@
 	pipe_connect = &usb_bam_connections[idx];
 
 	if (!pipe_connect->enabled) {
-		pr_debug("%s: connection %d isn't enabled\n",
+		pr_err("%s: connection %d isn't enabled\n",
 			__func__, idx);
 		return 0;
 	}
 
+	spin_lock(&usb_bam_lock);
+
 	ret = disconnect_pipe(idx);
 	if (ret) {
-		pr_err("%s: src pipe connection failure\n", __func__);
+		pr_err("%s: src pipe disconnection failure\n", __func__);
+		spin_unlock(&usb_bam_lock);
 		return ret;
 	}
 
 	pipe_connect->enabled = 0;
+
 	if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0)
 		pr_err("%s: wrong pipes enabled counter for bam_type=%d\n",
 			__func__, pipe_connect->bam_type);
 	else
 		ctx.pipes_enabled_per_bam[pipe_connect->bam_type] -= 1;
 
+	spin_unlock(&usb_bam_lock);
+
 	return 0;
 }
 
+static void usb_bam_start_lpm(void)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+	BUG_ON(trans == NULL);
+	spin_lock(&usb_bam_lock);
+	lpm_wait_handshake = 0;
+	if (sched_lpm) {
+		pr_debug("%s: Going to LPM\n", __func__);
+		spin_unlock(&usb_bam_lock);
+		pm_runtime_resume(trans->dev);
+		pm_runtime_put_noidle(trans->dev);
+		pm_runtime_suspend(trans->dev);
+		return;
+	}
+	spin_unlock(&usb_bam_lock);
+}
+
+static void wait_for_prod_release(enum usb_bam cur_bam)
+{
+	int ret;
+
+	if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pr_debug("%s consumer already released\n", __func__);
+	 if (cur_prod_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pr_debug("%s producer already released\n", __func__);
+
+	init_completion(&prod_released[cur_bam]);
+	init_completion(&cons_released[cur_bam]);
+	pr_debug("%s: Releasing %s_PROD\n", __func__,
+				bam_enable_strings[cur_bam]);
+	ret = ipa_rm_release_resource(ipa_rm_resource_prod[cur_bam]);
+	if (!ret) {
+		pr_debug("%s: Released without waiting\n", __func__);
+		cur_prod_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
+		complete_all(&prod_released[cur_bam]);
+	} else if (ret == -EINPROGRESS) {
+		pr_debug("%s: Waiting for PROD_RELEASED\n", __func__);
+		if (!wait_for_completion_timeout(&prod_released[cur_bam],
+						USB_BAM_TIMEOUT))
+			pr_err("%s: Timeout waiting for PROD_RELEASED\n",
+			__func__);
+	} else
+		pr_err("%s: ipa_rm_request_resource ret =%d", __func__, ret);
+}
+
+static void wait_for_cons_release(enum usb_bam cur_bam)
+{
+	 pr_debug("%s: Waiting for CONS release\n", __func__);
+	 if (cur_prod_state[cur_bam] != IPA_RM_RESOURCE_RELEASED) {
+		if (!wait_for_completion_timeout(&cons_released[cur_bam],
+						  USB_BAM_TIMEOUT))
+			pr_err("%s: Timeout wainting for CONS_RELEASE\n",
+				__func__);
+	 } else
+		pr_debug("%s Didn't need to wait for CONS release\n",
+		     __func__);
+}
+
 int usb_bam_disconnect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	int ret;
 	u8 idx;
 	struct usb_bam_pipe_connect *pipe_connect;
 	struct sps_connect *sps_connection;
+	enum usb_bam cur_bam;
 
+
+	if (!ipa_params->prod_clnt_hdl && !ipa_params->cons_clnt_hdl) {
+		pr_err("%s: Both of the handles is missing\n", __func__);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: Starting disconnect sequence\n", __func__);
+	/* Delay USB core to go into lpm before we finish our handshake */
 	if (ipa_params->prod_clnt_hdl) {
-		/* close USB -> IPA pipe */
 		idx = ipa_params->dst_idx;
+		pipe_connect = &usb_bam_connections[idx];
+
+		/* Do the release handshake with the A2 via RM */
+		cur_bam = pipe_connect->bam_type;
+		wait_for_prod_release(cur_bam);
+		/* close USB -> IPA pipe */
 		ret = ipa_disconnect(ipa_params->prod_clnt_hdl);
 		if (ret) {
 			pr_err("%s: dst pipe disconnection failure\n",
 				__func__);
 			return ret;
 		}
-		pipe_connect = &usb_bam_connections[idx];
 		sps_connection = &ctx.usb_bam_sps.sps_connections[idx];
 		sps_connection->data.phys_base = 0;
 		sps_connection->desc.phys_base = 0;
@@ -880,16 +1277,20 @@
 			return ret;
 		}
 	}
+
 	if (ipa_params->cons_clnt_hdl) {
-		/* close IPA -> USB pipe */
 		idx = ipa_params->src_idx;
+		pipe_connect = &usb_bam_connections[idx];
+		cur_bam = pipe_connect->bam_type;
+		wait_for_cons_release(cur_bam);
+		/* close IPA -> USB pipe */
 		ret = ipa_disconnect(ipa_params->cons_clnt_hdl);
 		if (ret) {
 			pr_err("%s: src pipe disconnection failure\n",
 				__func__);
 			return ret;
 		}
-		pipe_connect = &usb_bam_connections[idx];
+
 		sps_connection = &ctx.usb_bam_sps.sps_connections[idx];
 		sps_connection->data.phys_base = 0;
 		sps_connection->desc.phys_base = 0;
@@ -900,9 +1301,15 @@
 				__func__, idx);
 			return ret;
 		}
+		pr_debug("%s: Notify CONS release\n", __func__);
+
+		if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
+				ipa_rm_resource_cons[cur_bam]);
+		pr_debug("%s Ended disconnect sequence\n", __func__);
+		usb_bam_start_lpm();
 	}
 
-	ipa_rm_release_resource(IPA_RM_RESOURCE_USB_PROD);
 	return 0;
 }
 EXPORT_SYMBOL(usb_bam_disconnect_ipa);
@@ -965,6 +1372,53 @@
 	return ret;
 }
 
+static void usb_bam_sps_events(enum sps_callback_case sps_cb_case, void *user)
+{
+	int i;
+	enum usb_bam bam;
+	struct usb_bam_pipe_connect *pipe_connect;
+	struct usb_bam_event_info *event_info;
+
+	switch (sps_cb_case) {
+	case SPS_CALLBACK_BAM_TIMER_IRQ:
+
+		pr_debug("%s:recieved SPS_CALLBACK_BAM_TIMER_IRQ\n", __func__);
+
+		spin_lock(&usb_bam_lock);
+
+		bam = get_bam_type_from_core_name((char *)user);
+		ctx.is_bam_inactivity[bam] = true;
+		pr_debug("%s: Incativity happened on bam=%s,%d\n", __func__,
+			(char *)user, bam);
+
+		for (i = 0; i < ctx.max_connections; i++) {
+			pipe_connect = &usb_bam_connections[i];
+
+			/*
+			 * Notify inactivity once, Since it is global
+			 * for all pipes on bam.
+			 */
+			if (pipe_connect->bam_type == bam) {
+				event_info = &pipe_connect->event;
+				event_info->type = USB_BAM_EVENT_INACTIVITY;
+				event_info->param = pipe_connect->priv;
+				event_info->callback =
+					pipe_connect->inactivity_notify;
+				queue_work(ctx.usb_bam_wq,
+						&event_info->event_w);
+				break;
+			}
+		}
+
+		spin_unlock(&usb_bam_lock);
+
+		break;
+	default:
+		pr_debug("%s:received sps_cb_case=%d\n", __func__,
+			(int)sps_cb_case);
+	}
+}
+
 static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
 	struct platform_device *pdev)
 {
@@ -1174,6 +1628,9 @@
 	props.summing_threshold = USB_THRESHOLD;
 	props.event_threshold = USB_THRESHOLD;
 	props.num_pipes = pdata->usb_bam_num_pipes;
+	props.callback = usb_bam_sps_events;
+	props.user = bam_enable_strings[bam_idx];
+
 	/*
 	* HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
 	* Hence, let BAM to ignore acknowledge from USB while resetting PIPE
@@ -1234,6 +1691,76 @@
 	return 0;
 }
 
+static ssize_t
+usb_bam_show_inactivity_timer(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	char *buff = buf;
+	int i;
+
+	spin_lock(&usb_bam_lock);
+
+	for (i = 0; i < ARRAY_SIZE(bam_enable_strings); i++) {
+		buff += snprintf(buff, PAGE_SIZE, "%s: %dms\n",
+					bam_enable_strings[i],
+					ctx.inactivity_timer_ms[i]);
+	}
+
+	spin_unlock(&usb_bam_lock);
+
+	return buff - buf;
+}
+
+static ssize_t usb_bam_store_inactivity_timer(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buff, size_t count)
+{
+	char buf[USB_BAM_MAX_STR_LEN];
+	char *trimmed_buf, *bam_str, *bam_name, *timer;
+	int timer_d;
+	enum usb_bam bam;
+
+	if (strnstr(buff, "help", USB_BAM_MAX_STR_LEN)) {
+		pr_info("Usage: <bam_name> <ms>,<bam_name> <ms>,...\n");
+		pr_info("\tbam_name: [%s, %s, %s]\n",
+			bam_enable_strings[SSUSB_BAM],
+			bam_enable_strings[HSUSB_BAM],
+			bam_enable_strings[HSIC_BAM]);
+		pr_info("\tms: time in ms. Use 0 to disable timer\n");
+		return count;
+	}
+
+	strlcpy(buf, buff, sizeof(buf));
+	trimmed_buf = strim(buf);
+
+	while (trimmed_buf) {
+		bam_str = strsep(&trimmed_buf, ",");
+		if (bam_str) {
+			bam_name = strsep(&bam_str, " ");
+			bam = get_bam_type_from_core_name(bam_name);
+
+			timer = strsep(&bam_str, " ");
+			sscanf(timer, "%d", &timer_d);
+
+			spin_lock(&usb_bam_lock);
+
+			ctx.inactivity_timer_ms[bam] = timer_d;
+			/* Apply new timer setting if bam has running pipes */
+			if (ctx.pipes_enabled_per_bam[bam] > 0)
+				usb_bam_set_inactivity_timer(bam);
+
+			spin_unlock(&usb_bam_lock);
+		}
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(inactivity_timer, S_IWUSR | S_IRUSR,
+		   usb_bam_show_inactivity_timer,
+		   usb_bam_store_inactivity_timer);
+
+
 static int usb_bam_probe(struct platform_device *pdev)
 {
 	int ret, i;
@@ -1241,10 +1768,14 @@
 
 	dev_dbg(&pdev->dev, "usb_bam_probe\n");
 
+	ret = device_create_file(&pdev->dev, &dev_attr_inactivity_timer);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to create fs node\n");
+		return ret;
+	}
+
 	ctx.mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
 	if (IS_ERR(ctx.mem_clk))
-
-
 		dev_dbg(&pdev->dev, "failed to get mem_clock\n");
 
 	ctx.mem_iface_clk = devm_clk_get(&pdev->dev, "mem_iface_clk");
@@ -1269,14 +1800,27 @@
 
 	for (i = 0; i < ctx.max_connections; i++) {
 		usb_bam_connections[i].enabled = 0;
-		INIT_WORK(&usb_bam_connections[i].wake_event.event_w,
+		INIT_WORK(&usb_bam_connections[i].event.event_w,
 			usb_bam_work);
 	}
 
-	for (i = 0; i < MAX_BAMS; i++)
+	for (i = 0; i < MAX_BAMS; i++) {
 		ctx.pipes_enabled_per_bam[i] = 0;
+		ctx.inactivity_timer_ms[i] = 0;
+		ctx.is_bam_inactivity[i] = false;
+		init_completion(&prod_avail[i]);
+		complete(&prod_avail[i]);
+		init_completion(&cons_avail[i]);
+		complete(&cons_avail[i]);
+		init_completion(&cons_released[i]);
+		complete(&cons_released[i]);
+		init_completion(&prod_released[i]);
+		complete(&prod_released[i]);
+		cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
+		cur_cons_state[i] = IPA_RM_RESOURCE_RELEASED;
+	}
 
-	spin_lock_init(&usb_bam_lock);
+	spin_lock_init(&usb_bam_peer_handshake_info_lock);
 	INIT_WORK(&peer_handshake_info.reset_event.event_w, usb_bam_sm_work);
 
 	ctx.usb_bam_wq = alloc_workqueue("usb_bam_wq",
@@ -1293,6 +1837,8 @@
 	}
 	usb_bam_ipa_create_resources();
 
+	spin_lock_init(&usb_bam_lock);
+
 	return ret;
 }
 
@@ -1361,6 +1907,22 @@
 }
 EXPORT_SYMBOL(usb_bam_get_connection_idx);
 
+bool msm_bam_lpm_ok(void)
+{
+	spin_lock(&usb_bam_lock);
+	if (lpm_wait_handshake) {
+		sched_lpm = 1;
+		spin_unlock(&usb_bam_lock);
+		pr_err("%s: Scheduling LPM for later\n", __func__);
+		return 0;
+	} else {
+		spin_unlock(&usb_bam_lock);
+		pr_err("%s: Going to LPM now\n", __func__);
+		return 1;
+	}
+}
+EXPORT_SYMBOL(msm_bam_lpm_ok);
+
 static int usb_bam_remove(struct platform_device *pdev)
 {
 	destroy_workqueue(ctx.usb_bam_wq);
diff --git a/drivers/power/bq28400_battery.c b/drivers/power/bq28400_battery.c
index beab4e2..79ed2b1 100644
--- a/drivers/power/bq28400_battery.c
+++ b/drivers/power/bq28400_battery.c
@@ -164,6 +164,9 @@
 	u16	subcmd;
 };
 
+static int fake_battery = -EINVAL;
+module_param(fake_battery, int, 0644);
+
 #define BQ28400_DEBUG_REG(x) {#x, SBS_##x, 0}
 #define BQ28400_DEBUG_SUBREG(x, y) {#y, SBS_##x, SUBCMD_##y}
 
@@ -403,6 +406,11 @@
 {
 	int percentage = 0;
 
+	if (fake_battery != -EINVAL) {
+		pr_debug("Reporting Fake SOC = %d\n", fake_battery);
+		return fake_battery;
+	}
+
 	/* This register is only 1 byte */
 	percentage = i2c_smbus_read_byte_data(client, SBS_RSOC);
 
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index e00e1c3..1ad7f21 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -83,6 +83,7 @@
 #define CHG_COMP_OVR		0x20A
 #define IUSB_FINE_RES		0x2B6
 #define OVP_USB_UVD		0x2B7
+#define PM8921_USB_TRIM_SEL	0x339
 
 /* check EOC every 10 seconds */
 #define EOC_CHECK_PERIOD_MS	10000
@@ -777,6 +778,44 @@
 };
 
 /* USB Trim tables */
+static int usb_trim_pm8921_table_1[USB_TRIM_ENTRIES] = {
+	0x0,
+	0x0,
+	-0x5,
+	0x0,
+	-0x7,
+	0x0,
+	-0x9,
+	-0xA,
+	0x0,
+	0x0,
+	-0xE,
+	0x0,
+	-0xF,
+	0x0,
+	-0x10,
+	0x0
+};
+
+static int usb_trim_pm8921_table_2[USB_TRIM_ENTRIES] = {
+	0x0,
+	0x0,
+	-0x2,
+	0x0,
+	-0x4,
+	0x0,
+	-0x4,
+	-0x5,
+	0x0,
+	0x0,
+	-0x6,
+	0x0,
+	-0x6,
+	0x0,
+	-0x6,
+	0x0
+};
+
 static int usb_trim_8038_table[USB_TRIM_ENTRIES] = {
 	0x0,
 	0x0,
@@ -844,6 +883,8 @@
 #define REG_USB_OVP_TRIM_ORIG_MSB	0x09C
 #define REG_USB_OVP_TRIM_PM8917		0x2B5
 #define REG_USB_OVP_TRIM_PM8917_BIT	BIT(0)
+#define USB_TRIM_MAX_DATA_PM8917	0x3F
+#define USB_TRIM_POLARITY_PM8917_BIT	BIT(6)
 static int pm_chg_usb_trim(struct pm8921_chg_chip *chip, int index)
 {
 	u8 temp, sbi_config, msb, lsb, mask;
@@ -3805,11 +3846,14 @@
 		}
 }
 
+#define PM8921_USB_TRIM_SEL_BIT		BIT(6)
 /* determines the initial present states */
 static void __devinit determine_initial_state(struct pm8921_chg_chip *chip)
 {
 	int fsm_state;
 	int is_fast_chg;
+	int rc = 0;
+	u8 trim_sel_reg = 0, regsbi;
 
 	chip->dc_present = !!is_dc_chg_plugged_in(chip);
 	chip->usb_present = !!is_usb_chg_plugged_in(chip);
@@ -3872,10 +3916,26 @@
 			fsm_state);
 
 	/* Determine which USB trim column to use */
-	if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
+	if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917) {
 		chip->usb_trim_table = usb_trim_8917_table;
-	else if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8038)
+	} else if (pm8xxx_get_version(chip->dev->parent) ==
+						PM8XXX_VERSION_8038) {
 		chip->usb_trim_table = usb_trim_8038_table;
+	} else if (pm8xxx_get_version(chip->dev->parent) ==
+						PM8XXX_VERSION_8921) {
+		rc = pm8xxx_readb(chip->dev->parent, REG_SBI_CONFIG, &regsbi);
+		rc |= pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, 0x5E);
+		rc |= pm8xxx_readb(chip->dev->parent, PM8921_USB_TRIM_SEL,
+								&trim_sel_reg);
+		rc |= pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, regsbi);
+		if (rc)
+			pr_err("Failed to read trim sel register rc=%d\n", rc);
+
+		if (trim_sel_reg & PM8921_USB_TRIM_SEL_BIT)
+			chip->usb_trim_table = usb_trim_pm8921_table_1;
+		else
+			chip->usb_trim_table = usb_trim_pm8921_table_2;
+	}
 }
 
 struct pm_chg_irq_init_data {
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 6a2ce8d..8207cd6 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1564,9 +1564,9 @@
 
 			rc |= devm_request_irq(chip->dev, chip->chg_failed_irq,
 				qpnp_chg_chgr_chg_failed_irq_handler,
-				IRQF_TRIGGER_RISING, "chg_failed", chip);
+				IRQF_TRIGGER_RISING, "chg-failed", chip);
 			if (rc < 0) {
-				pr_err("Can't request %d chg_failed chg: %d\n",
+				pr_err("Can't request %d chg-failed: %d\n",
 						chip->chg_failed_irq, rc);
 				return rc;
 			}
@@ -1584,7 +1584,7 @@
 			rc |= devm_request_irq(chip->dev, chip->chg_trklchg_irq,
 				qpnp_chg_chgr_chg_trklchg_irq_handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-				"fast-chg-on", chip);
+				"trkl-chg-on", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d trkl-chg-on: %d\n",
 						chip->chg_trklchg_irq, rc);
@@ -1607,7 +1607,7 @@
 			rc = devm_request_irq(chip->dev, chip->batt_pres_irq,
 				qpnp_chg_bat_if_batt_pres_irq_handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-				"bat_if_batt_pres", chip);
+				"batt-pres", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d batt-pres irq: %d\n",
 						chip->batt_pres_irq, rc);
@@ -1628,9 +1628,9 @@
 			rc = devm_request_irq(chip->dev, chip->usbin_valid_irq,
 				qpnp_chg_usb_usbin_valid_irq_handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-					"chg_usbin_valid", chip);
+					"usbin-valid", chip);
 			if (rc < 0) {
-				pr_err("Can't request %d usbinvalid: %d\n",
+				pr_err("Can't request %d usbin-valid: %d\n",
 						chip->usbin_valid_irq, rc);
 				return rc;
 			}
@@ -1644,9 +1644,9 @@
 			rc = devm_request_irq(chip->dev, chip->chg_gone_irq,
 				qpnp_chg_usb_chg_gone_irq_handler,
 				IRQF_TRIGGER_RISING,
-					"chg_gone_irq", chip);
+					"chg-gone", chip);
 			if (rc < 0) {
-				pr_err("Can't request %d chg_gone: %d\n",
+				pr_err("Can't request %d chg-gone: %d\n",
 						chip->chg_gone_irq, rc);
 				return rc;
 			}
@@ -1663,9 +1663,9 @@
 			rc = devm_request_irq(chip->dev, chip->dcin_valid_irq,
 				qpnp_chg_dc_dcin_valid_irq_handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-				"chg_dcin_valid", chip);
+				"dcin-valid", chip);
 			if (rc < 0) {
-				pr_err("Can't request %d dcinvalid: %d\n",
+				pr_err("Can't request %d dcin-valid: %d\n",
 						chip->dcin_valid_irq, rc);
 				return rc;
 			}
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 139bc06..086ff03 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -36,10 +36,20 @@
 #ifndef _UFS_H
 #define _UFS_H
 
+#include <linux/mutex.h>
+#include <linux/types.h>
+
 #define MAX_CDB_SIZE	16
+#define GENERAL_UPIU_REQUEST_SIZE 32
+#define UPIU_HEADER_DATA_SEGMENT_MAX_SIZE	((ALIGNED_UPIU_SIZE) - \
+					(GENERAL_UPIU_REQUEST_SIZE))
+#define QUERY_OSF_SIZE			((GENERAL_UPIU_REQUEST_SIZE) - \
+					(sizeof(struct utp_upiu_header)))
+#define UFS_QUERY_RESERVED_SCSI_CMD 0xCC
+#define UFS_QUERY_CMD_SIZE 10
 
 #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
-			((byte3 << 24) | (byte2 << 16) |\
+			cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
 			 (byte1 << 8) | (byte0))
 
 /*
@@ -62,7 +72,7 @@
 	UPIU_TRANSACTION_COMMAND	= 0x01,
 	UPIU_TRANSACTION_DATA_OUT	= 0x02,
 	UPIU_TRANSACTION_TASK_REQ	= 0x04,
-	UPIU_TRANSACTION_QUERY_REQ	= 0x26,
+	UPIU_TRANSACTION_QUERY_REQ	= 0x16,
 };
 
 /* UTP UPIU Transaction Codes Target to Initiator */
@@ -73,6 +83,7 @@
 	UPIU_TRANSACTION_TASK_RSP	= 0x24,
 	UPIU_TRANSACTION_READY_XFER	= 0x31,
 	UPIU_TRANSACTION_QUERY_RSP	= 0x36,
+	UPIU_TRANSACTION_REJECT_UPIU	= 0x3F,
 };
 
 /* UPIU Read/Write flags */
@@ -90,6 +101,12 @@
 	UPIU_TASK_ATTR_ACA	= 0x03,
 };
 
+/* UPIU Query request function */
+enum {
+	UPIU_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01,
+	UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81,
+};
+
 /* UTP QUERY Transaction Specific Fields OpCode */
 enum {
 	UPIU_QUERY_OPCODE_NOP		= 0x0,
@@ -103,6 +120,21 @@
 	UPIU_QUERY_OPCODE_TOGGLE_FLAG	= 0x8,
 };
 
+/* Query response result code */
+enum {
+	QUERY_RESULT_SUCCESS			= 0x00,
+	QUERY_RESULT_NOT_READABLE		= 0xF6,
+	QUERY_RESULT_NOT_WRITEABLE		= 0xF7,
+	QUERY_RESULT_ALREADY_WRITTEN		= 0xF8,
+	QUERY_RESULT_INVALID_LENGTH		= 0xF9,
+	QUERY_RESULT_INVALID_VALUE		= 0xFA,
+	QUERY_RESULT_INVALID_SELECTOR		= 0xFB,
+	QUERY_RESULT_INVALID_INDEX		= 0xFC,
+	QUERY_RESULT_INVALID_IDN		= 0xFD,
+	QUERY_RESULT_INVALID_OPCODE		= 0xFE,
+	QUERY_RESULT_GENERAL_FAILURE		= 0xFF,
+};
+
 /* UTP Transfer Request Command Type (CT) */
 enum {
 	UPIU_COMMAND_SET_TYPE_SCSI	= 0x0,
@@ -110,10 +142,17 @@
 	UPIU_COMMAND_SET_TYPE_QUERY	= 0x2,
 };
 
+/* UTP Transfer Request Command Offset */
+#define UPIU_COMMAND_TYPE_OFFSET	28
+
+/* Offset of the response code in the UPIU header */
+#define UPIU_RSP_CODE_OFFSET		8
+
 enum {
 	MASK_SCSI_STATUS	= 0xFF,
 	MASK_TASK_RESPONSE	= 0xFF00,
 	MASK_RSP_UPIU_RESULT	= 0xFFFF,
+	MASK_QUERY_DATA_SEG_LEN	= 0xFFFF,
 };
 
 /* Task management service response */
@@ -138,26 +177,59 @@
 
 /**
  * struct utp_upiu_cmd - Command UPIU structure
- * @header: UPIU header structure DW-0 to DW-2
  * @data_transfer_len: Data Transfer Length DW-3
  * @cdb: Command Descriptor Block CDB DW-4 to DW-7
  */
 struct utp_upiu_cmd {
-	struct utp_upiu_header header;
 	u32 exp_data_transfer_len;
 	u8 cdb[MAX_CDB_SIZE];
 };
 
 /**
- * struct utp_upiu_rsp - Response UPIU structure
- * @header: UPIU header DW-0 to DW-2
+ * struct utp_upiu_query - upiu request buffer structure for
+ * query request.
+ * @opcode: command to perform B-0
+ * @idn: a value that indicates the particular type of data B-1
+ * @index: Index to further identify data B-2
+ * @selector: Index to further identify data B-3
+ * @reserved_osf: spec reserved field B-4,5
+ * @length: number of descriptor bytes to read/write B-6,7
+ * @value: Attribute value to be written DW-6
+ * @reserved: spec reserved DW-7,8
+ */
+struct utp_upiu_query {
+	u8 opcode;
+	u8 idn;
+	u8 index;
+	u8 selector;
+	u16 reserved_osf;
+	u16 length;
+	u32 value;
+	u32 reserved[2];
+};
+
+/**
+ * struct utp_upiu_req - general upiu request structure
+ * @header:UPIU header structure DW-0 to DW-2
+ * @sc: fields structure for scsi command
+ * @qr: fields structure for query request
+ */
+struct utp_upiu_req {
+	struct utp_upiu_header header;
+	union {
+		struct utp_upiu_cmd sc;
+		struct utp_upiu_query qr;
+	};
+};
+
+/**
+ * struct utp_cmd_rsp - Response UPIU structure
  * @residual_transfer_count: Residual transfer count DW-3
  * @reserved: Reserved double words DW-4 to DW-7
  * @sense_data_len: Sense data length DW-8 U16
  * @sense_data: Sense data field DW-8 to DW-12
  */
-struct utp_upiu_rsp {
-	struct utp_upiu_header header;
+struct utp_cmd_rsp {
 	u32 residual_transfer_count;
 	u32 reserved[4];
 	u16 sense_data_len;
@@ -165,6 +237,20 @@
 };
 
 /**
+ * struct utp_upiu_rsp - general upiu response structure
+ * @header: UPIU header structure DW-0 to DW-2
+ * @sc: fields structure for scsi command
+ * @qr: fields structure for query request
+ */
+struct utp_upiu_rsp {
+	struct utp_upiu_header header;
+	union {
+		struct utp_cmd_rsp sc;
+		struct utp_upiu_query qr;
+	};
+};
+
+/**
  * struct utp_upiu_task_req - Task request UPIU structure
  * @header - UPIU header structure DW0 to DW-2
  * @input_param1: Input parameter 1 DW-3
@@ -194,4 +280,24 @@
 	u32 reserved[3];
 };
 
+/**
+ * struct ufs_query_req - parameters for building a query request
+ * @query_func: UPIU header query function
+ * @upiu_req: the query request data
+ */
+struct ufs_query_req {
+	u8 query_func;
+	struct utp_upiu_query upiu_req;
+};
+
+/**
+ * struct ufs_query_resp - UPIU QUERY
+ * @response: device response code
+ * @upiu_res: query response data
+ */
+struct ufs_query_res {
+	u8 response;
+	struct utp_upiu_query upiu_res;
+};
+
 #endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c32a478..e12b9b4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -202,18 +202,13 @@
 }
 
 /**
- * ufshcd_is_valid_req_rsp - checks if controller TR response is valid
+ * ufshcd_get_req_rsp - returns the TR response
  * @ucd_rsp_ptr: pointer to response UPIU
- *
- * This function checks the response UPIU for valid transaction type in
- * response field
- * Returns 0 on success, non-zero on failure
  */
 static inline int
-ufshcd_is_valid_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr)
+ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr)
 {
-	return ((be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24) ==
-		 UPIU_TRANSACTION_RESPONSE) ? 0 : DID_ERROR << 16;
+	return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24;
 }
 
 /**
@@ -316,14 +311,71 @@
 {
 	int len;
 	if (lrbp->sense_buffer) {
-		len = be16_to_cpu(lrbp->ucd_rsp_ptr->sense_data_len);
+		len = be16_to_cpu(lrbp->ucd_rsp_ptr->sc.sense_data_len);
 		memcpy(lrbp->sense_buffer,
-			lrbp->ucd_rsp_ptr->sense_data,
+			lrbp->ucd_rsp_ptr->sc.sense_data,
 			min_t(int, len, SCSI_SENSE_BUFFERSIZE));
 	}
 }
 
 /**
+ * ufshcd_query_to_cpu() - formats the received buffer in to the native cpu
+ * endian
+ * @response: upiu query response to convert
+ */
+static inline void ufshcd_query_to_cpu(struct utp_upiu_query *response)
+{
+	response->length = be16_to_cpu(response->length);
+	response->value = be32_to_cpu(response->value);
+}
+
+/**
+ * ufshcd_query_to_be() - formats the buffer before sending in to big endian
+ * @response: upiu query request to convert
+ */
+static inline void ufshcd_query_to_be(struct utp_upiu_query *request)
+{
+	request->length = cpu_to_be16(request->length);
+	request->value = cpu_to_be32(request->value);
+}
+
+/**
+ * ufshcd_copy_query_response() - Copy Query Response and descriptor
+ * @lrb - pointer to local reference block
+ * @query_res - pointer to the query result
+ */
+static
+void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+{
+	struct ufs_query_res *query_res = hba->query.response;
+
+	/* Get the UPIU response */
+	if (query_res) {
+		query_res->response = ufshcd_get_rsp_upiu_result(
+			lrbp->ucd_rsp_ptr) >> UPIU_RSP_CODE_OFFSET;
+
+		memcpy(&query_res->upiu_res, &lrbp->ucd_rsp_ptr->qr,
+			QUERY_OSF_SIZE);
+		ufshcd_query_to_cpu(&query_res->upiu_res);
+	}
+
+	/* Get the descriptor */
+	if (hba->query.descriptor && lrbp->ucd_rsp_ptr->qr.opcode ==
+			UPIU_QUERY_OPCODE_READ_DESC) {
+		u8 *descp = (u8 *)&lrbp->ucd_rsp_ptr +
+				GENERAL_UPIU_REQUEST_SIZE;
+		u16 len;
+
+		/* data segment length */
+		len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) &
+						MASK_QUERY_DATA_SEG_LEN;
+
+		memcpy(hba->query.descriptor, descp,
+			min_t(u16, len, UPIU_HEADER_DATA_SEGMENT_MAX_SIZE));
+	}
+}
+
+/**
  * ufshcd_hba_capabilities - Read controller capabilities
  * @hba: per adapter instance
  */
@@ -423,76 +475,159 @@
 }
 
 /**
+ * ufshcd_prepare_req_desc - Fills the requests header
+ * descriptor according to request
+ * lrbp: pointer to local reference block
+ * upiu_flags: flags required in the header
+ */
+static void ufshcd_prepare_req_desc(struct ufshcd_lrb *lrbp, u32 *upiu_flags)
+{
+	struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
+	enum dma_data_direction cmd_dir =
+		lrbp->cmd->sc_data_direction;
+	u32 data_direction;
+	u32 dword_0;
+
+	if (cmd_dir == DMA_FROM_DEVICE) {
+		data_direction = UTP_DEVICE_TO_HOST;
+		*upiu_flags = UPIU_CMD_FLAGS_READ;
+	} else if (cmd_dir == DMA_TO_DEVICE) {
+		data_direction = UTP_HOST_TO_DEVICE;
+		*upiu_flags = UPIU_CMD_FLAGS_WRITE;
+	} else {
+		data_direction = UTP_NO_DATA_TRANSFER;
+		*upiu_flags = UPIU_CMD_FLAGS_NONE;
+	}
+
+	dword_0 = data_direction | (lrbp->command_type
+				<< UPIU_COMMAND_TYPE_OFFSET);
+
+	/* Transfer request descriptor header fields */
+	req_desc->header.dword_0 = cpu_to_le32(dword_0);
+
+	/*
+	 * assigning invalid value for command status. Controller
+	 * updates OCS on command completion, with the command
+	 * status
+	 */
+	req_desc->header.dword_2 =
+		cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+}
+
+static inline bool ufshcd_is_query_req(struct ufshcd_lrb *lrbp)
+{
+	return lrbp->cmd ? lrbp->cmd->cmnd[0] == UFS_QUERY_RESERVED_SCSI_CMD :
+		false;
+}
+
+/**
+ * ufshcd_prepare_utp_scsi_cmd_upiu() - fills the utp_transfer_req_desc,
+ * for scsi commands
+ * @lrbp - local reference block pointer
+ * @upiu_flags - flags
+ */
+static
+void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags)
+{
+	struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
+
+	/* command descriptor fields */
+	ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
+				UPIU_TRANSACTION_COMMAND, upiu_flags,
+				lrbp->lun, lrbp->task_tag);
+	ucd_req_ptr->header.dword_1 = UPIU_HEADER_DWORD(
+				UPIU_COMMAND_SET_TYPE_SCSI, 0, 0, 0);
+
+	/* Total EHS length and Data segment length will be zero */
+	ucd_req_ptr->header.dword_2 = 0;
+
+	ucd_req_ptr->sc.exp_data_transfer_len =
+		cpu_to_be32(lrbp->cmd->sdb.length);
+
+	memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd,
+		(min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE)));
+}
+
+/**
+ * ufshcd_prepare_utp_query_req_upiu() - fills the utp_transfer_req_desc,
+ * for query requsts
+ * @hba: UFS hba
+ * @lrbp: local reference block pointer
+ * @upiu_flags: flags
+ */
+static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
+					struct ufshcd_lrb *lrbp,
+					u32 upiu_flags)
+{
+	struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
+	u16 len = hba->query.request->upiu_req.length;
+	u8 *descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
+
+	/* Query request header */
+	ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
+			UPIU_TRANSACTION_QUERY_REQ, upiu_flags,
+			lrbp->lun, lrbp->task_tag);
+	ucd_req_ptr->header.dword_1 = UPIU_HEADER_DWORD(
+			0, hba->query.request->query_func, 0, 0);
+
+	/* Data segment length */
+	ucd_req_ptr->header.dword_2 = UPIU_HEADER_DWORD(
+			0, 0, len >> 8, (u8)len);
+
+	/* Copy the Query Request buffer as is */
+	memcpy(&lrbp->ucd_req_ptr->qr, &hba->query.request->upiu_req,
+			QUERY_OSF_SIZE);
+	ufshcd_query_to_be(&lrbp->ucd_req_ptr->qr);
+
+	/* Copy the Descriptor */
+	if (hba->query.descriptor != NULL && len > 0 &&
+		(hba->query.request->upiu_req.opcode ==
+					UPIU_QUERY_OPCODE_WRITE_DESC)) {
+		memcpy(descp, hba->query.descriptor,
+			min_t(u16, len, UPIU_HEADER_DATA_SEGMENT_MAX_SIZE));
+	}
+
+}
+
+/**
  * ufshcd_compose_upiu - form UFS Protocol Information Unit(UPIU)
+ * @hba - UFS hba
  * @lrb - pointer to local reference block
  */
-static void ufshcd_compose_upiu(struct ufshcd_lrb *lrbp)
+static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
 {
-	struct utp_transfer_req_desc *req_desc;
-	struct utp_upiu_cmd *ucd_cmd_ptr;
-	u32 data_direction;
 	u32 upiu_flags;
-
-	ucd_cmd_ptr = lrbp->ucd_cmd_ptr;
-	req_desc = lrbp->utr_descriptor_ptr;
+	int ret = 0;
 
 	switch (lrbp->command_type) {
 	case UTP_CMD_TYPE_SCSI:
-		if (lrbp->cmd->sc_data_direction == DMA_FROM_DEVICE) {
-			data_direction = UTP_DEVICE_TO_HOST;
-			upiu_flags = UPIU_CMD_FLAGS_READ;
-		} else if (lrbp->cmd->sc_data_direction == DMA_TO_DEVICE) {
-			data_direction = UTP_HOST_TO_DEVICE;
-			upiu_flags = UPIU_CMD_FLAGS_WRITE;
-		} else {
-			data_direction = UTP_NO_DATA_TRANSFER;
-			upiu_flags = UPIU_CMD_FLAGS_NONE;
-		}
-
-		/* Transfer request descriptor header fields */
-		req_desc->header.dword_0 =
-			cpu_to_le32(data_direction | UTP_SCSI_COMMAND);
-
-		/*
-		 * assigning invalid value for command status. Controller
-		 * updates OCS on command completion, with the command
-		 * status
-		 */
-		req_desc->header.dword_2 =
-			cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-
-		/* command descriptor fields */
-		ucd_cmd_ptr->header.dword_0 =
-			cpu_to_be32(UPIU_HEADER_DWORD(UPIU_TRANSACTION_COMMAND,
-						      upiu_flags,
-						      lrbp->lun,
-						      lrbp->task_tag));
-		ucd_cmd_ptr->header.dword_1 =
-			cpu_to_be32(
-				UPIU_HEADER_DWORD(UPIU_COMMAND_SET_TYPE_SCSI,
-						  0,
-						  0,
-						  0));
-
-		/* Total EHS length and Data segment length will be zero */
-		ucd_cmd_ptr->header.dword_2 = 0;
-
-		ucd_cmd_ptr->exp_data_transfer_len =
-			cpu_to_be32(lrbp->cmd->sdb.length);
-
-		memcpy(ucd_cmd_ptr->cdb,
-		       lrbp->cmd->cmnd,
-		       (min_t(unsigned short,
-			      lrbp->cmd->cmd_len,
-			      MAX_CDB_SIZE)));
-		break;
 	case UTP_CMD_TYPE_DEV_MANAGE:
-		/* For query function implementation */
+		ufshcd_prepare_req_desc(lrbp, &upiu_flags);
+		if (lrbp->cmd && lrbp->command_type == UTP_CMD_TYPE_SCSI)
+			ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
+		else if (lrbp->cmd)
+			ufshcd_prepare_utp_query_req_upiu(hba, lrbp,
+								upiu_flags);
+		else {
+			dev_err(hba->dev, "%s: Invalid UPIU request\n",
+				__func__);
+			ret = -EINVAL;
+		}
 		break;
 	case UTP_CMD_TYPE_UFS:
 		/* For UFS native command implementation */
+		dev_err(hba->dev, "%s: UFS native command are not supported\n",
+			__func__);
+		ret = -ENOTSUPP;
+		break;
+	default:
+		ret = -ENOTSUPP;
+		dev_err(hba->dev, "%s: unknown command type: 0x%x\n",
+				__func__, lrbp->command_type);
 		break;
 	} /* end of switch */
+
+	return ret;
 }
 
 /**
@@ -527,10 +662,13 @@
 	lrbp->task_tag = tag;
 	lrbp->lun = cmd->device->lun;
 
-	lrbp->command_type = UTP_CMD_TYPE_SCSI;
+	if (ufshcd_is_query_req(lrbp))
+		lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
+	else
+		lrbp->command_type = UTP_CMD_TYPE_SCSI;
 
 	/* form UPIU before issuing the command */
-	ufshcd_compose_upiu(lrbp);
+	ufshcd_compose_upiu(hba, lrbp);
 	err = ufshcd_map_sg(lrbp);
 	if (err)
 		goto out;
@@ -544,6 +682,110 @@
 }
 
 /**
+ *  ufshcd_query_request() - Entry point for issuing query request to a
+ *  ufs device.
+ *  @hba: ufs driver context
+ *  @query: params for query request
+ *  @descriptor: buffer for sending/receiving descriptor
+ *  @response: pointer to a buffer that will contain the response code and
+ *           response upiu
+ *  @timeout: time limit for the command in seconds
+ *  @retries: number of times to try executing the command
+ *
+ *  The query request is submitted to the same request queue as the rest of
+ *  the scsi commands passed to the UFS controller. In order to use this
+ *  queue, we need to receive a tag, same as all other commands. The tags
+ *  are issued from the block layer. To simulate a request from the block
+ *  layer, we use the same interface as the SCSI layer does when it issues
+ *  commands not generated by users. To distinguish a query request from
+ *  the SCSI commands, we use a vendor specific unused SCSI command
+ *  op-code. This op-code is not part of the SCSI command subset used in
+ *  UFS. In such way it is easy to check the command in the driver and
+ *  handle it appropriately.
+ *
+ *  All necessary fields for issuing a query and receiving its response are
+ *  stored in the UFS hba struct. We can use this method since we know
+ *  there is only one active query request at all times.
+ *
+ *  The request that will pass to the device is stored in "query" argument
+ *  passed to this function, while the "response" argument (which is output
+ *  field) will hold the query response from the device along with the
+ *  response code.
+ */
+int ufshcd_query_request(struct ufs_hba *hba,
+			struct ufs_query_req *query,
+			u8 *descriptor,
+			struct ufs_query_res *response,
+			int timeout,
+			int retries)
+{
+	struct scsi_device *sdev;
+	u8 cmd[UFS_QUERY_CMD_SIZE] = {0};
+	int result;
+	bool sdev_lookup = true;
+
+	if (!hba || !query || !response) {
+		dev_err(hba->dev,
+			"%s: NULL pointer hba = %p, query = %p response = %p\n",
+			__func__, hba, query, response);
+		return -EINVAL;
+	}
+
+	/*
+	 * A SCSI command structure is composed from opcode at the
+	 * begining and 0 at the end.
+	 */
+	cmd[0] = UFS_QUERY_RESERVED_SCSI_CMD;
+
+	/* extracting the SCSI Device */
+	sdev = scsi_device_lookup(hba->host, 0, 0, 0);
+	if (!sdev) {
+		/**
+		 * There are some Query Requests that are sent during device
+		 * initialization, this happens before the scsi device was
+		 * initialized. If there is no scsi device, we generate a
+		 * temporary device to allow the Query Request flow.
+		 */
+		sdev_lookup = false;
+		sdev = scsi_get_host_dev(hba->host);
+	}
+
+	if (!sdev) {
+		dev_err(hba->dev, "%s: Could not fetch scsi device\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&hba->query.lock_ufs_query);
+	hba->query.request = query;
+	hba->query.descriptor = descriptor;
+	hba->query.response = response;
+
+	/* wait until request is completed */
+	result = scsi_execute(sdev, cmd, DMA_NONE, NULL, 0, NULL,
+				timeout, retries, 0, NULL);
+	if (result) {
+		dev_err(hba->dev,
+			"%s: Query with opcode 0x%x, failed with result %d\n",
+			__func__, query->upiu_req.opcode, result);
+		result = -EIO;
+	}
+
+	hba->query.request = NULL;
+	hba->query.descriptor = NULL;
+	hba->query.response = NULL;
+	mutex_unlock(&hba->query.lock_ufs_query);
+
+	/* Releasing scsi device resource */
+	if (sdev_lookup)
+		scsi_device_put(sdev);
+	else
+		scsi_free_host_dev(sdev);
+
+	return result;
+}
+
+/**
  * ufshcd_memory_alloc - allocate memory for host memory space data structures
  * @hba: per adapter instance
  *
@@ -677,8 +919,8 @@
 				cpu_to_le16(ALIGNED_UPIU_SIZE);
 
 		hba->lrb[i].utr_descriptor_ptr = (utrdlp + i);
-		hba->lrb[i].ucd_cmd_ptr =
-			(struct utp_upiu_cmd *)(cmd_descp + i);
+		hba->lrb[i].ucd_req_ptr =
+			(struct utp_upiu_req *)(cmd_descp + i);
 		hba->lrb[i].ucd_rsp_ptr =
 			(struct utp_upiu_rsp *)cmd_descp[i].response_upiu;
 		hba->lrb[i].ucd_prdt_ptr =
@@ -1101,7 +1343,9 @@
  * @hba: per adapter instance
  * @lrb: pointer to local reference block of completed command
  *
- * Returns result of the command to notify SCSI midlayer
+ * Returns result of the command to notify SCSI midlayer. In
+ * case of query request specific result, returns DID_OK, and
+ * the error will be handled by the dispatcher.
  */
 static inline int
 ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
@@ -1115,27 +1359,46 @@
 
 	switch (ocs) {
 	case OCS_SUCCESS:
-
 		/* check if the returned transfer response is valid */
-		result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
-		if (result) {
-			dev_err(hba->dev,
-				"Invalid response = %x\n", result);
+		result = ufshcd_get_req_rsp(lrbp->ucd_rsp_ptr);
+
+		switch (result) {
+		case UPIU_TRANSACTION_RESPONSE:
+			/*
+			 * get the response UPIU result to extract
+			 * the SCSI command status
+			 */
+			result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr);
+
+			/*
+			 * get the result based on SCSI status response
+			 * to notify the SCSI midlayer of the command status
+			 */
+			scsi_status = result & MASK_SCSI_STATUS;
+			result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
 			break;
+		case UPIU_TRANSACTION_QUERY_RSP:
+			/*
+			 *  Return result = ok, since SCSI layer wouldn't
+			 *  know how to handle errors from query requests.
+			 *  The result is saved with the response so that
+			 *  the ufs_core layer will handle it.
+			 */
+			result |= DID_OK << 16;
+			ufshcd_copy_query_response(hba, lrbp);
+			break;
+		case UPIU_TRANSACTION_REJECT_UPIU:
+			/* TODO: handle Reject UPIU Response */
+			result |= DID_ERROR << 16;
+			dev_err(hba->dev,
+				"Reject UPIU not fully implemented\n");
+			break;
+		default:
+			result |= DID_ERROR << 16;
+			dev_err(hba->dev,
+				"Unexpected request response code = %x\n",
+				result);
 		}
-
-		/*
-		 * get the response UPIU result to extract
-		 * the SCSI command status
-		 */
-		result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr);
-
-		/*
-		 * get the result based on SCSI status response
-		 * to notify the SCSI midlayer of the command status
-		 */
-		scsi_status = result & MASK_SCSI_STATUS;
-		result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
 		break;
 	case OCS_ABORTED:
 		result |= DID_ABORT << 16;
@@ -1364,10 +1627,10 @@
 	task_req_upiup =
 		(struct utp_upiu_task_req *) task_req_descp->task_req_upiu;
 	task_req_upiup->header.dword_0 =
-		cpu_to_be32(UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0,
-					      lrbp->lun, lrbp->task_tag));
+		UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0,
+					      lrbp->lun, lrbp->task_tag);
 	task_req_upiup->header.dword_1 =
-	cpu_to_be32(UPIU_HEADER_DWORD(0, tm_function, 0, 0));
+		UPIU_HEADER_DWORD(0, tm_function, 0, 0);
 
 	task_req_upiup->input_param1 = lrbp->lun;
 	task_req_upiup->input_param1 =
@@ -1670,6 +1933,9 @@
 	INIT_WORK(&hba->uic_workq, ufshcd_uic_cc_handler);
 	INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
 
+	/* Initialize mutex for query requests */
+	mutex_init(&hba->query.lock_ufs_query);
+
 	/* IRQ registration */
 	err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
 	if (err) {
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 6b99a42..336980b 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -60,6 +60,7 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
 
 #include "ufs.h"
 #include "ufshci.h"
@@ -88,7 +89,7 @@
 /**
  * struct ufshcd_lrb - local reference block
  * @utr_descriptor_ptr: UTRD address of the command
- * @ucd_cmd_ptr: UCD address of the command
+ * @ucd_req_ptr: UCD address of the command
  * @ucd_rsp_ptr: Response UPIU address for this command
  * @ucd_prdt_ptr: PRDT address of the command
  * @cmd: pointer to SCSI command
@@ -101,7 +102,7 @@
  */
 struct ufshcd_lrb {
 	struct utp_transfer_req_desc *utr_descriptor_ptr;
-	struct utp_upiu_cmd *ucd_cmd_ptr;
+	struct utp_upiu_req *ucd_req_ptr;
 	struct utp_upiu_rsp *ucd_rsp_ptr;
 	struct ufshcd_sg_entry *ucd_prdt_ptr;
 
@@ -115,6 +116,19 @@
 	unsigned int lun;
 };
 
+/**
+ * struct ufs_query - keeps the query request information
+ * @request: request upiu and function
+ * @descriptor: buffer for sending/receiving descriptor
+ * @response: response upiu and response
+ * @mutex: lock to allow one query at a time
+ */
+struct ufs_query {
+	struct ufs_query_req *request;
+	u8 *descriptor;
+	struct ufs_query_res *response;
+	struct mutex lock_ufs_query;
+};
 
 /**
  * struct ufs_hba - per adapter private structure
@@ -143,6 +157,7 @@
  * @uic_workq: Work queue for UIC completion handling
  * @feh_workq: Work queue for fatal controller error handling
  * @errors: HBA errors
+ * @query: query request information
  */
 struct ufs_hba {
 	void __iomem *mmio_base;
@@ -184,6 +199,9 @@
 
 	/* HBA Errors */
 	u32 errors;
+
+	/* Query Request */
+	struct ufs_query query;
 };
 
 int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 0c16484..4a86247 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -39,7 +39,7 @@
 enum {
 	TASK_REQ_UPIU_SIZE_DWORDS	= 8,
 	TASK_RSP_UPIU_SIZE_DWORDS	= 8,
-	ALIGNED_UPIU_SIZE		= 128,
+	ALIGNED_UPIU_SIZE		= 512,
 };
 
 /* UFSHCI Registers */
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 6cd30f1..3abc3b9 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -2525,14 +2525,38 @@
 			struct binder_transaction *t;
 
 			t = container_of(w, struct binder_transaction, work);
-			if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
+			if (t->buffer->target_node &&
+			    !(t->flags & TF_ONE_WAY)) {
 				binder_send_failed_reply(t, BR_DEAD_REPLY);
+			} else {
+				binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+					"binder: undelivered transaction %d\n",
+					t->debug_id);
+				t->buffer->transaction = NULL;
+				kfree(t);
+				binder_stats_deleted(BINDER_STAT_TRANSACTION);
+			}
 		} break;
 		case BINDER_WORK_TRANSACTION_COMPLETE: {
+			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+				"binder: undelivered TRANSACTION_COMPLETE\n");
 			kfree(w);
 			binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 		} break;
+		case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+		case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
+			struct binder_ref_death *death;
+
+			death = container_of(w, struct binder_ref_death, work);
+			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+				"binder: undelivered death notification, %p\n",
+				death->cookie);
+			kfree(death);
+			binder_stats_deleted(BINDER_STAT_DEATH);
+		} break;
 		default:
+			pr_err("binder: unexpected work type, %d, not freed\n",
+			       w->type);
 			break;
 		}
 	}
@@ -3009,6 +3033,7 @@
 		nodes++;
 		rb_erase(&node->rb_node, &proc->nodes);
 		list_del_init(&node->work.entry);
+		binder_release_work(&node->async_todo);
 		if (hlist_empty(&node->refs)) {
 			kfree(node);
 			binder_stats_deleted(BINDER_STAT_NODE);
@@ -3047,6 +3072,7 @@
 		binder_delete_ref(ref);
 	}
 	binder_release_work(&proc->todo);
+	binder_release_work(&proc->delivered_death);
 	buffers = 0;
 
 	while ((n = rb_first(&proc->allocated_buffers))) {
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 12ac3bc..dc756bb 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -28,6 +28,7 @@
 #include <linux/of.h>
 #include <linux/sysfs.h>
 #include <linux/types.h>
+#include <linux/android_alarm.h>
 #include <mach/cpufreq.h>
 #include <mach/rpm-regulator.h>
 #include <mach/rpm-regulator-smd.h>
@@ -41,6 +42,10 @@
 static bool core_control_enabled;
 static uint32_t cpus_offlined;
 static DEFINE_MUTEX(core_control_mutex);
+static uint32_t wakeup_ms;
+static struct alarm thermal_rtc;
+static struct kobject *tt_kobj;
+static struct work_struct timer_work;
 
 static int enabled;
 static int rails_cnt;
@@ -58,6 +63,7 @@
 static bool psm_enabled;
 static bool psm_nodes_called;
 static bool psm_probed;
+static int *tsens_id_map;
 static DEFINE_MUTEX(vdd_rstr_mutex);
 static DEFINE_MUTEX(psm_mutex);
 
@@ -103,6 +109,7 @@
 	ko_attr.attr.mode = 444; \
 	ko_attr.show = vdd_rstr_reg_##_name##_show; \
 	ko_attr.store = NULL; \
+	sysfs_attr_init(&ko_attr.attr); \
 	_rail.attr_gp.attrs[j] = &ko_attr.attr;
 
 #define VDD_RES_RW_ATTRIB(_rail, ko_attr, j, _name) \
@@ -110,6 +117,7 @@
 	ko_attr.attr.mode = 644; \
 	ko_attr.show = vdd_rstr_reg_##_name##_show; \
 	ko_attr.store = vdd_rstr_reg_##_name##_store; \
+	sysfs_attr_init(&ko_attr.attr); \
 	_rail.attr_gp.attrs[j] = &ko_attr.attr;
 
 #define VDD_RSTR_ENABLE_FROM_ATTRIBS(attr) \
@@ -126,6 +134,7 @@
 	ko_attr.attr.mode = 644; \
 	ko_attr.show = psm_reg_##_name##_show; \
 	ko_attr.store = psm_reg_##_name##_store; \
+	sysfs_attr_init(&ko_attr.attr); \
 	_rail.attr_gp.attrs[j] = &ko_attr.attr;
 
 #define PSM_REG_MODE_FROM_ATTRIBS(attr) \
@@ -392,7 +401,7 @@
 	if (vdd_rstr_en.enabled == 0)
 		goto done_store_level;
 
-	ret = kstrtoint(buf, 10, &val);
+	ret = kstrtouint(buf, 10, &val);
 	if (ret) {
 		pr_err("Invalid input %s for level\n", buf);
 		goto done_store_level;
@@ -465,6 +474,62 @@
 	return count;
 }
 
+
+static int check_sensor_id(int sensor_id)
+{
+	int i = 0;
+	bool hw_id_found;
+	int ret = 0;
+
+	for (i = 0; i < max_tsens_num; i++) {
+		if (sensor_id == tsens_id_map[i]) {
+			hw_id_found = true;
+			break;
+		}
+	}
+	if (!hw_id_found) {
+		pr_err("%s: Invalid sensor hw id :%d\n", __func__, sensor_id);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int create_sensor_id_map(void)
+{
+	int i = 0;
+	int ret = 0;
+
+	tsens_id_map = kzalloc(sizeof(int) * max_tsens_num,
+			GFP_KERNEL);
+	if (!tsens_id_map) {
+		pr_err("%s: Cannot allocate memory for tsens_id_map\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < max_tsens_num; i++) {
+		ret = tsens_get_hw_id_mapping(i, &tsens_id_map[i]);
+		/* If return -ENXIO, hw_id is default in sequence */
+		if (ret) {
+			if (ret == -ENXIO) {
+				tsens_id_map[i] = i;
+				ret = 0;
+			} else {
+				pr_err( \
+				"%s: Failed to get hw id for sw id %d\n",
+				__func__, i);
+				goto fail;
+			}
+		}
+	}
+
+	return ret;
+fail:
+	kfree(tsens_id_map);
+	return ret;
+}
+
 static int msm_thermal_get_freq_table(void)
 {
 	int ret = 0;
@@ -575,7 +640,7 @@
 
 	mutex_lock(&vdd_rstr_mutex);
 	for (i = 0; i < max_tsens_num; i++) {
-		tsens_dev.sensor_num = i;
+		tsens_dev.sensor_num = tsens_id_map[i];
 		ret = tsens_get_temp(&tsens_dev, &temp);
 		if (ret) {
 			pr_debug("%s: Unable to read TSENS sensor %d\n",
@@ -620,7 +685,7 @@
 
 	mutex_lock(&psm_mutex);
 	for (i = 0; i < max_tsens_num; i++) {
-		tsens_dev.sensor_num = i;
+		tsens_dev.sensor_num = tsens_id_map[i];
 		ret = tsens_get_temp(&tsens_dev, &temp);
 		if (ret) {
 			pr_debug("%s: Unable to read TSENS sensor %d\n",
@@ -746,6 +811,39 @@
 	.notifier_call = msm_thermal_cpu_callback,
 };
 
+static void thermal_rtc_setup(void)
+{
+	ktime_t wakeup_time;
+	ktime_t curr_time;
+
+	curr_time = alarm_get_elapsed_realtime();
+	wakeup_time = ktime_add_us(curr_time,
+			(wakeup_ms * USEC_PER_MSEC));
+	alarm_start_range(&thermal_rtc, wakeup_time,
+			wakeup_time);
+	pr_debug("%s: Current Time: %ld %ld, Alarm set to: %ld %ld\n",
+			KBUILD_MODNAME,
+			ktime_to_timeval(curr_time).tv_sec,
+			ktime_to_timeval(curr_time).tv_usec,
+			ktime_to_timeval(wakeup_time).tv_sec,
+			ktime_to_timeval(wakeup_time).tv_usec);
+
+}
+
+static void timer_work_fn(struct work_struct *work)
+{
+	sysfs_notify(tt_kobj, NULL, "wakeup_ms");
+}
+
+static void thermal_rtc_callback(struct alarm *al)
+{
+	struct timeval ts;
+	ts = ktime_to_timeval(alarm_get_elapsed_realtime());
+	schedule_work(&timer_work);
+	pr_debug("%s: Time on alarm expiry: %ld %ld\n", KBUILD_MODNAME,
+			ts.tv_sec, ts.tv_usec);
+}
+
 /**
  * We will reset the cpu frequencies limits here. The core online/offline
  * status will be carried over to the process stopping the msm_thermal, as
@@ -902,6 +1000,52 @@
 	.attrs = cc_attrs,
 };
 
+static ssize_t show_wakeup_ms(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", wakeup_ms);
+}
+
+static ssize_t store_wakeup_ms(struct kobject *kobj,
+		struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	ret = kstrtouint(buf, 10, &wakeup_ms);
+
+	if (ret) {
+		pr_err("%s: Trying to set invalid wakeup timer\n",
+				KBUILD_MODNAME);
+		return ret;
+	}
+
+	if (wakeup_ms > 0) {
+		thermal_rtc_setup();
+		pr_debug("%s: Timer started for %ums\n", KBUILD_MODNAME,
+				wakeup_ms);
+	} else {
+		ret = alarm_cancel(&thermal_rtc);
+		if (ret)
+			pr_debug("%s: Timer canceled\n", KBUILD_MODNAME);
+		else
+			pr_debug("%s: No active timer present to cancel\n",
+					KBUILD_MODNAME);
+
+	}
+	return count;
+}
+
+static __cpuinitdata struct kobj_attribute timer_attr =
+__ATTR(wakeup_ms, 0644, show_wakeup_ms, store_wakeup_ms);
+
+static __cpuinitdata struct attribute *tt_attrs[] = {
+	&timer_attr.attr,
+	NULL,
+};
+
+static __cpuinitdata struct attribute_group tt_attr_group = {
+	.attrs = tt_attrs,
+};
+
 static __init int msm_thermal_add_cc_nodes(void)
 {
 	struct kobject *module_kobj = NULL;
@@ -938,15 +1082,54 @@
 	return ret;
 }
 
+static __init int msm_thermal_add_timer_nodes(void)
+{
+	struct kobject *module_kobj = NULL;
+	int ret = 0;
+
+	module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+	if (!module_kobj) {
+		pr_err("%s: cannot find kobject for module\n",
+			KBUILD_MODNAME);
+		ret = -ENOENT;
+		goto failed;
+	}
+
+	tt_kobj = kobject_create_and_add("thermal_timer", module_kobj);
+	if (!tt_kobj) {
+		pr_err("%s: cannot create timer kobj\n",
+				KBUILD_MODNAME);
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	ret = sysfs_create_group(tt_kobj, &tt_attr_group);
+	if (ret) {
+		pr_err("%s: cannot create group\n", KBUILD_MODNAME);
+		goto failed;
+	}
+
+	return 0;
+
+failed:
+	if (tt_kobj)
+		kobject_del(tt_kobj);
+	return ret;
+}
+
 int __devinit msm_thermal_init(struct msm_thermal_data *pdata)
 {
 	int ret = 0;
 
 	BUG_ON(!pdata);
 	tsens_get_max_sensor_num(&max_tsens_num);
-	BUG_ON(msm_thermal_info.sensor_id >= max_tsens_num);
 	memcpy(&msm_thermal_info, pdata, sizeof(struct msm_thermal_data));
 
+	if (create_sensor_id_map())
+		return -EINVAL;
+	if (check_sensor_id(msm_thermal_info.sensor_id))
+		return -EINVAL;
+
 	enabled = 1;
 	core_control_enabled = 1;
 	INIT_DELAYED_WORK(&check_temp_work, check_temp);
@@ -1449,6 +1632,10 @@
 	msm_thermal_add_cc_nodes();
 	msm_thermal_add_psm_nodes();
 	msm_thermal_add_vdd_rstr_nodes();
+	alarm_init(&thermal_rtc, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
+			thermal_rtc_callback);
+	INIT_WORK(&timer_work, timer_work_fn);
+	msm_thermal_add_timer_nodes();
 
 	return 0;
 }
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index d848a18..26a12d0 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1200,22 +1200,28 @@
 		}
 	}
 
-	rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_MULTI_MEAS_EN,
-		sensor_mask, false);
-	if (rc < 0) {
-		pr_err("multi meas disable for channel failed\n");
-		goto fail;
-	}
+	if (adc_tm_high_enable || adc_tm_low_enable) {
+		rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_MULTI_MEAS_EN,
+			sensor_mask, false);
+		if (rc < 0) {
+			pr_err("multi meas disable for channel failed\n");
+			goto fail;
+		}
 
-	rc = qpnp_adc_tm_enable_if_channel_meas();
-	if (rc < 0) {
-		pr_err("re-enabling measurement failed\n");
-		return rc;
-	}
+		rc = qpnp_adc_tm_enable_if_channel_meas();
+		if (rc < 0) {
+			pr_err("re-enabling measurement failed\n");
+			return rc;
+		}
+	} else
+		pr_debug("No threshold status enable %d for high/low??\n",
+								sensor_mask);
+
 fail:
 	mutex_unlock(&adc_tm->adc->adc_lock);
 
-	schedule_work(&adc_tm->sensor[sensor_num].work);
+	if (adc_tm_high_enable || adc_tm_low_enable)
+		schedule_work(&adc_tm->sensor[sensor_num].work);
 
 	return rc;
 }
@@ -1528,6 +1534,7 @@
 		dev_err(&spmi->dev, "failed to read device tree\n");
 		goto fail;
 	}
+	mutex_init(&adc_tm->adc->adc_lock);
 
 	/* Register the ADC peripheral interrupt */
 	adc_tm->adc->adc_high_thr_irq = spmi_get_irq_byname(spmi,
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index ad7c702..f695870 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -2340,9 +2340,7 @@
 	msm_hs_start_rx_locked(uport);
 
 	spin_unlock_irqrestore(&uport->lock, flags);
-	ret = pm_runtime_set_active(uport->dev);
-	if (ret)
-		dev_err(uport->dev, "set active error:%d\n", ret);
+
 	pm_runtime_enable(uport->dev);
 
 	return 0;
@@ -3180,7 +3178,6 @@
 	cancel_delayed_work_sync(&msm_uport->rx.flip_insert_work);
 	flush_workqueue(msm_uport->hsuart_wq);
 	pm_runtime_disable(uport->dev);
-	pm_runtime_set_suspended(uport->dev);
 
 	/* Disable the transmitter */
 	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_DISABLE_BMSK);
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 7aa14de..d520253 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -364,6 +364,22 @@
 	return msm_hsl_port->uart.line;
 }
 
+static int bus_vote(uint32_t client, int vector)
+{
+	int ret = 0;
+
+	if (!client)
+		return ret;
+
+	pr_debug("Voting for bus scaling:%d\n", vector);
+
+	ret = msm_bus_scale_client_update_request(client, vector);
+	if (ret)
+		pr_err("Failed to request bus bw vector %d\n", vector);
+
+	return ret;
+}
+
 static int clk_en(struct uart_port *port, int enable)
 {
 	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
@@ -372,9 +388,13 @@
 	if (enable) {
 
 		msm_hsl_port->clk_enable_count++;
-		ret = clk_prepare_enable(msm_hsl_port->clk);
+		ret = bus_vote(msm_hsl_port->bus_perf_client,
+				!!msm_hsl_port->clk_enable_count);
 		if (ret)
 			goto err;
+		ret = clk_prepare_enable(msm_hsl_port->clk);
+		if (ret)
+			goto err_bus;
 		if (msm_hsl_port->pclk) {
 			ret = clk_prepare_enable(msm_hsl_port->pclk);
 			if (ret)
@@ -386,23 +406,17 @@
 		clk_disable_unprepare(msm_hsl_port->clk);
 		if (msm_hsl_port->pclk)
 			clk_disable_unprepare(msm_hsl_port->pclk);
-	}
-
-	if (msm_hsl_port->bus_perf_client) {
-			pr_debug("Voting for bus scaling:%d\n",
-					!!msm_hsl_port->clk_enable_count);
-			ret = msm_bus_scale_client_update_request(
-				msm_hsl_port->bus_perf_client,
+		ret = bus_vote(msm_hsl_port->bus_perf_client,
 				!!msm_hsl_port->clk_enable_count);
-			if (ret)
-				pr_err("Failed to request bus bw vector %d\n",
-					!!msm_hsl_port->clk_enable_count);
 	}
 
 	return ret;
 
 err_clk_disable:
 	clk_disable_unprepare(msm_hsl_port->clk);
+err_bus:
+	bus_vote(msm_hsl_port->bus_perf_client,
+			!!(msm_hsl_port->clk_enable_count - 1));
 err:
 	msm_hsl_port->clk_enable_count--;
 	return ret;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 924e8f4..a27eb09 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1309,8 +1309,14 @@
 	data |= (0x7F | (1 << 14));
 	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1002, data);
 
-	/* Set LOS_BIAS to 0x5 */
-	dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1, 0x07, 0x5);
+	/*
+	 * Set the QSCRATCH SS_PHY_PARAM_CTRL1 parameters as follows
+	 * TX_FULL_SWING [26:20] amplitude to 127
+	 * TX_DEEMPH_3_5DB [13:8] to 22
+	 * LOS_BIAS [2:0] to 0x5
+	 */
+	dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1,
+				0x07f03f07, 0x07f01605);
 }
 
 /* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
@@ -2433,6 +2439,8 @@
 	msm->charger.charging_disabled = of_property_read_bool(node,
 				"qcom,charging-disabled");
 
+	msm->charger.skip_chg_detect = of_property_read_bool(node,
+				"qcom,skip-charger-detection");
 	/*
 	 * DWC3 has separate IRQ line for OTG events (ID/BSV) and for
 	 * DP and DM linestate transitions during low power mode.
@@ -2606,12 +2614,17 @@
 	msm->otg_xceiv = usb_get_transceiver();
 	/* Register with OTG if present, ignore USB2 OTG using other PHY */
 	if (msm->otg_xceiv && !(msm->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
-		msm->charger.start_detection = dwc3_start_chg_det;
-		ret = dwc3_set_charger(msm->otg_xceiv->otg, &msm->charger);
-		if (ret || !msm->charger.notify_detection_complete) {
-			dev_err(&pdev->dev, "failed to register charger: %d\n",
-									ret);
-			goto put_xcvr;
+		/* Skip charger detection for simulator targets */
+		if (!msm->charger.skip_chg_detect) {
+			msm->charger.start_detection = dwc3_start_chg_det;
+			ret = dwc3_set_charger(msm->otg_xceiv->otg,
+					&msm->charger);
+			if (ret || !msm->charger.notify_detection_complete) {
+				dev_err(&pdev->dev,
+					"failed to register charger: %d\n",
+					ret);
+				goto put_xcvr;
+			}
 		}
 
 		if (msm->ext_xceiv.otg_capability)
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index c2fab53..90e26cf 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -77,6 +77,8 @@
 	unsigned		max_power;
 	bool			charging_disabled;
 
+	bool			skip_chg_detect;
+
 	/* start/stop charger detection, provided by external charger module */
 	void	(*start_detection)(struct dwc3_charger *charger, bool start);
 
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 8d2ec97..bb0b2fb 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -751,6 +751,9 @@
 	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;
 
 	r = next_request(&ep0->request_list);
+	if (r == NULL)
+		return;
+
 	ur = &r->request;
 	if ((epnum & 1) && ur->zero &&
 		(ur->length % ep0->endpoint.maxpacket == 0)) {
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 705600d..147e3db 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2689,6 +2689,8 @@
 		of_property_read_u32(pdev->dev.of_node,
 				"qcom,android-usb-swfi-latency",
 				&pdata->swfi_latency);
+		pdata->cdrom = of_property_read_bool(pdev->dev.of_node,
+				"qcom,android-usb-cdrom");
 	} else {
 		pdata = pdev->dev.platform_data;
 	}
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index d0ebda1..01d8be1 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2268,8 +2268,8 @@
 	gadget->otg_srp_reqd = 0;
 
 	udc->driver->disconnect(gadget);
-	usb_ep_fifo_flush(&udc->ep0out.ep);
-	usb_ep_fifo_flush(&udc->ep0in.ep);
+	_ep_nuke(&udc->ep0out);
+	_ep_nuke(&udc->ep0in);
 
 	if (udc->ep0in.last_zptr) {
 		dma_pool_free(udc->ep0in.td_pool, udc->ep0in.last_zptr,
@@ -3023,21 +3023,24 @@
 
 	trace("%p, %p, %X", ep, req, gfp_flags);
 
-	if (ep == NULL || req == NULL || mEp->desc == NULL)
-		return -EINVAL;
-
-	if (!udc->softconnect)
-		return -ENODEV;
-
 	spin_lock_irqsave(mEp->lock, flags);
+	if (ep == NULL || req == NULL || mEp->desc == NULL) {
+		retval = -EINVAL;
+		goto done;
+	}
+
+	if (!udc->softconnect) {
+		retval = -ENODEV;
+		goto done;
+	}
 
 	if (!udc->configured && mEp->type !=
 		USB_ENDPOINT_XFER_CONTROL) {
-		spin_unlock_irqrestore(mEp->lock, flags);
 		trace("usb is not configured"
 			"ept #%d, ept name#%s\n",
 			mEp->num, mEp->ep.name);
-		return -ESHUTDOWN;
+		retval = -ESHUTDOWN;
+		goto done;
 	}
 
 	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
@@ -3117,12 +3120,19 @@
 
 	trace("%p, %p", ep, req);
 
+	spin_lock_irqsave(mEp->lock, flags);
+	/*
+	 * Only ep0 IN is exposed to composite.  When a req is dequeued
+	 * on ep0, check both ep0 IN and ep0 OUT queues.
+	 */
 	if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
 		mEp->desc == NULL || list_empty(&mReq->queue) ||
-		list_empty(&mEp->qh.queue))
+		(list_empty(&mEp->qh.queue) && ((mEp->type !=
+			USB_ENDPOINT_XFER_CONTROL) ||
+			list_empty(&_udc->ep0out.qh.queue)))) {
+		spin_unlock_irqrestore(mEp->lock, flags);
 		return -EINVAL;
-
-	spin_lock_irqsave(mEp->lock, flags);
+	}
 
 	dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
 
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index bac8b68..87a3fd5 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2510,7 +2510,8 @@
 		goto reset_bulk_int;
 	fsg->bulk_out->driver_data = common;
 	fsg->bulk_out_enabled = 1;
-	common->bulk_out_maxpacket = le16_to_cpu(fsg->bulk_in->desc->wMaxPacketSize);
+	common->bulk_out_maxpacket =
+			le16_to_cpu(fsg->bulk_out->desc->wMaxPacketSize);
 	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 	csw_hack_sent = 0;
 	write_error_after_csw_sent = 0;
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 46a6bba..8e7cbb2 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -430,8 +430,6 @@
 
 	bam_data_disconnect(&ecm_qc_bam_port, 0);
 
-	ecm_ipa_cleanup(ipa_params.ipa_priv);
-
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index f3c6481..1017900 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -25,11 +25,6 @@
 #include "u_ether.h"
 #include "rndis.h"
 
-static bool rndis_multipacket_dl_disable;
-module_param(rndis_multipacket_dl_disable, bool, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(rndis_multipacket_dl_disable,
-	"Disable RNDIS Multi-packet support in DownLink");
-
 /*
  * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
  * been promoted instead of the standard CDC Ethernet.  The published RNDIS
@@ -71,6 +66,16 @@
  *   - MS-Windows drivers sometimes emit undocumented requests.
  */
 
+static bool rndis_multipacket_dl_disable;
+module_param(rndis_multipacket_dl_disable, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(rndis_multipacket_dl_disable,
+	"Disable RNDIS Multi-packet support in DownLink");
+
+static unsigned int rndis_ul_max_pkt_per_xfer = 1;
+module_param(rndis_ul_max_pkt_per_xfer, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(rndis_ul_max_pkt_per_xfer,
+	"Disable RNDIS Multi-packet support in DownLink");
+
 struct f_rndis {
 	struct gether			port;
 	u8				ctrl_id, data_id;
@@ -799,6 +804,7 @@
 
 	rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
 	rndis_set_host_mac(rndis->config, rndis->ethaddr);
+	rndis_set_max_pkt_xfer(rndis->config, rndis_ul_max_pkt_per_xfer);
 
 	if (rndis->manufacturer && rndis->vendorID &&
 			rndis_set_param_vendor(rndis->config, rndis->vendorID,
@@ -945,6 +951,7 @@
 	rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
 	rndis->port.wrap = rndis_add_header;
 	rndis->port.unwrap = rndis_rm_hdr;
+	rndis->port.ul_max_pkts_per_xfer = rndis_ul_max_pkt_per_xfer;
 
 	rndis->port.func.name = "rndis";
 	rndis->port.func.strings = rndis_strings;
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 7ac5b64..07f4d26 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -59,6 +59,16 @@
 
 #define RNDIS_MAX_CONFIGS	1
 
+int rndis_ul_max_pkt_per_xfer_rcvd;
+module_param(rndis_ul_max_pkt_per_xfer_rcvd, int, S_IRUGO);
+MODULE_PARM_DESC(rndis_ul_max_pkt_per_xfer_rcvd,
+	"Max num of REMOTE_NDIS_PACKET_MSGs received in a single transfer");
+
+int rndis_ul_max_xfer_size_rcvd;
+module_param(rndis_ul_max_xfer_size_rcvd, int, S_IRUGO);
+MODULE_PARM_DESC(rndis_ul_max_xfer_size_rcvd,
+	"Max size of bus transfer received");
+
 
 static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
 
@@ -590,7 +600,6 @@
 		(params->dev->mtu
 		+ sizeof(struct ethhdr)
 		+ sizeof(struct rndis_packet_msg_type)
-
 		+ 22));
 	resp->PacketAlignmentFactor = cpu_to_le32(params->pkt_alignment_factor);
 	resp->AFListOffset = cpu_to_le32(0);
@@ -1051,25 +1060,77 @@
 			struct sk_buff *skb,
 			struct sk_buff_head *list)
 {
-	/* tmp points to a struct rndis_packet_msg_type */
-	__le32 *tmp = (void *)skb->data;
+	int num_pkts = 1;
 
-	/* MessageType, MessageLength */
-	if (cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
-			!= get_unaligned(tmp++)) {
-		dev_kfree_skb_any(skb);
-		return -EINVAL;
-	}
-	tmp++;
+	if (skb->len > rndis_ul_max_xfer_size_rcvd)
+		rndis_ul_max_xfer_size_rcvd = skb->len;
 
-	/* DataOffset, DataLength */
-	if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) {
-		dev_kfree_skb_any(skb);
-		return -EOVERFLOW;
+	while (skb->len) {
+		struct rndis_packet_msg_type *hdr;
+		struct sk_buff		*skb2;
+		u32		msg_len, data_offset, data_len;
+
+		/* some rndis hosts send extra byte to avoid zlp, ignore it */
+		if (skb->len == 1) {
+			dev_kfree_skb_any(skb);
+			return 0;
+		}
+
+		if (skb->len < sizeof *hdr) {
+			pr_err("invalid rndis pkt: skblen:%u hdr_len:%u",
+					skb->len, sizeof *hdr);
+			dev_kfree_skb_any(skb);
+			return -EINVAL;
+		}
+
+		hdr = (void *)skb->data;
+		msg_len = le32_to_cpu(hdr->MessageLength);
+		data_offset = le32_to_cpu(hdr->DataOffset);
+		data_len = le32_to_cpu(hdr->DataLength);
+
+		if (skb->len < msg_len ||
+			((data_offset + data_len + 8) > msg_len)) {
+			pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n",
+				le32_to_cpu(hdr->MessageType),
+				msg_len, data_offset, data_len, skb->len);
+			dev_kfree_skb_any(skb);
+			return -EOVERFLOW;
+		}
+
+		if (le32_to_cpu(hdr->MessageType) != REMOTE_NDIS_PACKET_MSG) {
+			pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n",
+				le32_to_cpu(hdr->MessageType),
+				msg_len, data_offset, data_len, skb->len);
+			dev_kfree_skb_any(skb);
+			return -EINVAL;
+		}
+
+		skb_pull(skb, data_offset + 8);
+
+		if (msg_len == skb->len) {
+			skb_trim(skb, data_len);
+			break;
+		}
+
+		skb2 = skb_clone(skb, GFP_ATOMIC);
+		if (!skb2) {
+			pr_err("%s:skb clone failed\n", __func__);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+
+		skb_pull(skb, msg_len - sizeof *hdr);
+		skb_trim(skb2, data_len);
+		skb_queue_tail(list, skb2);
+
+		num_pkts++;
 	}
-	skb_trim(skb, get_unaligned_le32(tmp++));
+
+	if (num_pkts > rndis_ul_max_pkt_per_xfer_rcvd)
+		rndis_ul_max_pkt_per_xfer_rcvd = num_pkts;
 
 	skb_queue_tail(list, skb);
+
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 8a6a630..d00f81f 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -252,6 +252,7 @@
 int  rndis_set_param_vendor (u8 configNr, u32 vendorID,
 			    const char *vendorDescr);
 int  rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
+void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer);
 void rndis_add_hdr (struct sk_buff *skb);
 int rndis_rm_hdr(struct gether *port, struct sk_buff *skb,
 			struct sk_buff_head *list);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index c601000..c05f683 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -667,11 +667,11 @@
 	int ret;
 
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		teth_bridge_disconnect();
 		ret = usb_bam_disconnect_ipa(&d->ipa_params);
 		if (ret)
 			pr_err("%s: usb_bam_disconnect_ipa failed: err:%d\n",
 				__func__, ret);
-		teth_bridge_disconnect();
 	}
 }
 
@@ -742,8 +742,8 @@
 		d->ipa_params.priv = priv;
 		d->ipa_params.ipa_ep_cfg.mode.mode = IPA_BASIC;
 
-		d->ipa_params.client = IPA_CLIENT_USB_CONS;
-		d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
+		d->ipa_params.client = IPA_CLIENT_USB_PROD;
+		d->ipa_params.dir = USB_TO_PEER_PERIPHERAL;
 		ret = usb_bam_connect_ipa(&d->ipa_params);
 		if (ret) {
 			pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
@@ -751,8 +751,8 @@
 			return;
 		}
 
-		d->ipa_params.client = IPA_CLIENT_USB_PROD;
-		d->ipa_params.dir = USB_TO_PEER_PERIPHERAL;
+		d->ipa_params.client = IPA_CLIENT_USB_CONS;
+		d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
 		ret = usb_bam_connect_ipa(&d->ipa_params);
 		if (ret) {
 			pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index eec9e37..2abe2ef 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -219,10 +219,10 @@
 			d->ipa_params.ipa_ep_cfg.mode.mode = IPA_BASIC;
 		}
 
-		d->ipa_params.client = IPA_CLIENT_USB_CONS;
-		d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
+		d->ipa_params.client = IPA_CLIENT_USB_PROD;
+		d->ipa_params.dir = USB_TO_PEER_PERIPHERAL;
 		if (d->func_type == USB_FUNC_ECM) {
-			d->ipa_params.notify = ecm_qc_get_ipa_tx_cb();
+			d->ipa_params.notify = ecm_qc_get_ipa_rx_cb();
 			d->ipa_params.priv = ecm_qc_get_ipa_priv();
 		}
 		ret = usb_bam_connect_ipa(&d->ipa_params);
@@ -232,10 +232,10 @@
 			return;
 		}
 
-		d->ipa_params.client = IPA_CLIENT_USB_PROD;
-		d->ipa_params.dir = USB_TO_PEER_PERIPHERAL;
+		d->ipa_params.client = IPA_CLIENT_USB_CONS;
+		d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
 		if (d->func_type == USB_FUNC_ECM) {
-			d->ipa_params.notify = ecm_qc_get_ipa_rx_cb();
+			d->ipa_params.notify = ecm_qc_get_ipa_tx_cb();
 			d->ipa_params.priv = ecm_qc_get_ipa_priv();
 		}
 		ret = usb_bam_connect_ipa(&d->ipa_params);
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 2d974ab..d4c21dd 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -70,6 +70,7 @@
 	struct sk_buff_head	rx_frames;
 
 	unsigned		header_len;
+	unsigned		ul_max_pkts_per_xfer;
 	struct sk_buff		*(*wrap)(struct gether *, struct sk_buff *skb);
 	int			(*unwrap)(struct gether *,
 						struct sk_buff *skb,
@@ -233,9 +234,13 @@
 	size += out->maxpacket - 1;
 	size -= size % out->maxpacket;
 
+	if (dev->ul_max_pkts_per_xfer)
+		size *= dev->ul_max_pkts_per_xfer;
+
 	if (dev->port_usb->is_fixed)
 		size = max_t(size_t, size, dev->port_usb->fixed_out_len);
 
+	pr_debug("%s: size: %d", __func__, size);
 	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
 	if (skb == NULL) {
 		DBG(dev, "no rx skb\n");
@@ -1076,6 +1081,7 @@
 		dev->header_len = link->header_len;
 		dev->unwrap = link->unwrap;
 		dev->wrap = link->wrap;
+		dev->ul_max_pkts_per_xfer = link->ul_max_pkts_per_xfer;
 
 		spin_lock(&dev->lock);
 		dev->tx_skb_hold_count = 0;
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index faa9a3b..7040ab0 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -53,6 +53,8 @@
 	bool				is_fixed;
 	u32				fixed_out_len;
 	u32				fixed_in_len;
+
+	unsigned			ul_max_pkts_per_xfer;
 /* Max number of SKB packets to be used to create Multi Packet RNDIS */
 #define TX_SKB_HOLD_THRESHOLD		3
 	bool				multi_pkt_xfer;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 7674d88..ede8bdb 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1851,6 +1851,8 @@
 				"qcom,pool-64-bit-align");
 	pdata->enable_hbm = of_property_read_bool(node,
 				"qcom,enable-hbm");
+	pdata->disable_park_mode = (of_property_read_bool(node,
+				"qcom,disable-park-mode"));
 
 	return pdata;
 }
@@ -2088,7 +2090,7 @@
 		pm_runtime_put_sync(pdev->dev.parent);
 
 	if (mehci->enable_hbm)
-		hbm_init(hcd);
+		hbm_init(hcd, pdata->disable_park_mode);
 
 	return 0;
 
diff --git a/drivers/usb/host/hbm.c b/drivers/usb/host/hbm.c
index 1a0c0aa..d34301d 100644
--- a/drivers/usb/host/hbm.c
+++ b/drivers/usb/host/hbm.c
@@ -44,6 +44,7 @@
 struct hbm_msm {
 	u32 *base;
 	struct usb_hcd *hcd;
+	bool disable_park_mode;
 };
 
 static struct hbm_msm *hbm_ctx;
@@ -173,8 +174,8 @@
 		USB_OTG_HS_HBM_PIPE_PRODUCER, 1 << pipe_num,
 		(is_consumer ? 0 : 1));
 
-	/*  disable park mode as default */
-	set_disable_park_mode(pipe_num, true);
+	/*  set park mode */
+	set_disable_park_mode(pipe_num, hbm_ctx->disable_park_mode);
 
 	/*  enable zlt as default*/
 	set_disable_zlt(pipe_num, false);
@@ -186,7 +187,7 @@
 	return 0;
 }
 
-void hbm_init(struct usb_hcd *hcd)
+void hbm_init(struct usb_hcd *hcd, bool disable_park_mode)
 {
 	pr_info("%s\n", __func__);
 
@@ -198,6 +199,7 @@
 
 	hbm_ctx->base = hcd->regs;
 	hbm_ctx->hcd = hcd;
+	hbm_ctx->disable_park_mode = disable_park_mode;
 
 	/* reset hbm */
 	hbm_reset(true);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 4865b03..d4d7ee9 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -869,6 +869,9 @@
 	if (atomic_read(&motg->in_lpm))
 		return 0;
 
+	if (motg->pdata->delay_lpm_hndshk_on_disconnect && !msm_bam_lpm_ok())
+		return 0;
+
 	disable_irq(motg->irq);
 	host_bus_suspend = !test_bit(MHL, &motg->inputs) && phy->otg->host &&
 		!test_bit(ID, &motg->inputs);
@@ -3802,6 +3805,8 @@
 				"qcom,hsusb-otg-clk-always-on-workaround");
 	pdata->delay_lpm_on_disconnect = of_property_read_bool(node,
 				"qcom,hsusb-otg-delay-lpm");
+	pdata->delay_lpm_hndshk_on_disconnect = of_property_read_bool(node,
+				"qcom,hsusb-otg-delay-lpm-hndshk-on-disconnect");
 	pdata->dp_manual_pullup = of_property_read_bool(node,
 				"qcom,dp-manual-pullup");
 	pdata->enable_sec_phy = of_property_read_bool(node,
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 5be0173..3bb4bdc 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -110,6 +110,10 @@
 	void *video_intf;
 	u32 nintf;
 
+	struct mdss_ad_info *ad_cfgs;
+	u32 nad_cfgs;
+	struct workqueue_struct *ad_calc_wq;
+
 	struct ion_client *iclient;
 	int iommu_attached;
 	struct mdss_iommu_map_type *iommu_map;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index acac6b9..5d56df4 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -414,6 +414,8 @@
 	/* disable DSI controller */
 	mdss_dsi_controller_cfg(0, pdata);
 
+	/* disable DSI phy */
+	mdss_dsi_phy_enable(ctrl_pdata->ctrl_base, 0);
 	ret = mdss_dsi_panel_power_on(pdata, 0);
 	if (ret) {
 		pr_err("%s: Panel power off failed\n", __func__);
@@ -1078,12 +1080,12 @@
 	cont_splash_enabled = of_property_read_bool(pdev->dev.of_node,
 			"qcom,cont-splash-enabled");
 	if (!cont_splash_enabled) {
-		pr_info("%s:%d Continous splash flag not found.\n",
+		pr_info("%s:%d Continuous splash flag not found.\n",
 				__func__, __LINE__);
 		ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 0;
 		ctrl_pdata->panel_data.panel_info.panel_power_on = 0;
 	} else {
-		pr_info("%s:%d Continous splash flag enabled.\n",
+		pr_info("%s:%d Continuous splash flag enabled.\n",
 				__func__, __LINE__);
 
 		ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 1;
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 22ff08c..3c0dfc2 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -52,6 +52,8 @@
 
 void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl)
 {
+	int ret;
+
 	if (ctrl->panel_data.panel_info.pdest == DISPLAY_1) {
 		mdss_dsi0_hw.ptr = (void *)(ctrl);
 		ctrl->mdss_hw = &mdss_dsi0_hw;
@@ -60,7 +62,8 @@
 		ctrl->mdss_hw = &mdss_dsi1_hw;
 	}
 
-	if (!mdss_register_irq(ctrl->mdss_hw))
+	ret = mdss_register_irq(ctrl->mdss_hw);
+	if (ret)
 		pr_err("%s: mdss_register_irq failed.\n", __func__);
 }
 
@@ -813,7 +816,6 @@
 
 	dsi_ctrl |= BIT(0);	/* enable dsi */
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
-	mdss_dsi_irq_ctrl(ctrl_pdata, 1, 0); /* enable dsi irq */
 
 	wmb();
 }
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index eb4eee2..98b9db5 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -143,9 +143,9 @@
 	if (!bl_lvl && value)
 		bl_lvl = 1;
 
-	mutex_lock(&mfd->lock);
+	mutex_lock(&mfd->bl_lock);
 	mdss_fb_set_backlight(mfd, bl_lvl);
-	mutex_unlock(&mfd->lock);
+	mutex_unlock(&mfd->bl_lock);
 }
 
 static struct led_classdev backlight_led = {
@@ -263,6 +263,7 @@
 	mfd->mdp = *mdp_instance;
 
 	mutex_init(&mfd->lock);
+	mutex_init(&mfd->bl_lock);
 
 	fbi_list[fbi_list_index++] = fbi;
 
@@ -524,7 +525,7 @@
 	(*bl_lvl) = temp;
 }
 
-/* must call this function from within mfd->lock */
+/* must call this function from within mfd->bl_lock */
 void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
 {
 	struct mdss_panel_data *pdata;
@@ -566,11 +567,11 @@
 	if (unset_bl_level && !bl_updated) {
 		pdata = dev_get_platdata(&mfd->pdev->dev);
 		if ((pdata) && (pdata->set_backlight)) {
-			mutex_lock(&mfd->lock);
+			mutex_lock(&mfd->bl_lock);
 			mfd->bl_level = unset_bl_level;
 			pdata->set_backlight(pdata, mfd->bl_level);
 			bl_level_old = unset_bl_level;
-			mutex_unlock(&mfd->lock);
+			mutex_unlock(&mfd->bl_lock);
 			bl_updated = 1;
 		}
 	}
@@ -626,12 +627,7 @@
 static int mdss_fb_blank(int blank_mode, struct fb_info *info)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	if (blank_mode == FB_BLANK_POWERDOWN) {
-		struct fb_event event;
-		event.info = info;
-		event.data = &blank_mode;
-		fb_notifier_call_chain(FB_EVENT_BLANK, &event);
-	}
+
 	mdss_fb_pan_idle(mfd);
 	if (mfd->op_enable == 0) {
 		if (blank_mode == FB_BLANK_UNBLANK)
@@ -1210,6 +1206,7 @@
 		mdss_fb_wait_for_fence(mfd);
 		if (mfd->mdp.kickoff_fnc)
 			mfd->mdp.kickoff_fnc(mfd);
+		mdss_fb_update_backlight(mfd);
 		mdss_fb_signal_timeline(mfd);
 	} else {
 		var = &fb_backup->disp_commit.var;
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index fdbbea9..6f6f490 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -102,6 +102,7 @@
 	u32 bl_level;
 	u32 bl_scale;
 	u32 bl_min_lvl;
+	struct mutex bl_lock;
 	struct mutex lock;
 
 	struct platform_device *pdev;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_cec.c b/drivers/video/msm/mdss/mdss_hdmi_cec.c
index 694fcde..2cf47fc 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_cec.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_cec.c
@@ -785,12 +785,16 @@
 
 	io = cec_ctrl->init_data.io;
 
-	if (!cec_ctrl->cec_enabled)
-		return 0;
-
 	cec_intr = DSS_REG_R_ND(io, HDMI_CEC_INT);
 	DEV_DBG("%s: cec interrupt status is [0x%x]\n", __func__, cec_intr);
 
+	if (!cec_ctrl->cec_enabled) {
+		DEV_ERR("%s: cec is not enabled. Just clear int and return.\n",
+			__func__);
+		DSS_REG_W(io, HDMI_CEC_INT, cec_intr);
+		return 0;
+	}
+
 	cec_status = DSS_REG_R_ND(io, HDMI_CEC_STATUS);
 	DEV_DBG("%s: cec status is [0x%x]\n", __func__, cec_status);
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index ef17229..f726e79 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -1057,11 +1057,16 @@
 
 	io = hdcp_ctrl->init_data.core_io;
 
-	/* Ignore HDCP interrupts if HDCP is disabled */
-	if (HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state)
-		return 0;
-
 	hdcp_int_val = DSS_REG_R(io, HDMI_HDCP_INT_CTRL);
+
+	/* Ignore HDCP interrupts if HDCP is disabled */
+	if (HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) {
+		DEV_ERR("%s: HDCP inactive. Just clear int and return.\n",
+			__func__);
+		DSS_REG_W(io, HDMI_HDCP_INT_CTRL, hdcp_int_val);
+		return 0;
+	}
+
 	if (hdcp_int_val & BIT(0)) {
 		/* AUTH_SUCCESS_INT */
 		DSS_REG_W(io, HDMI_HDCP_INT_CTRL, (hdcp_int_val | BIT(1)));
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 9a90b88..dc51b1b 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -84,6 +84,8 @@
 static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
 static irqreturn_t hdmi_tx_isr(int irq, void *data);
 static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
+static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
+	enum hdmi_tx_power_module_type module, int enable);
 
 struct mdss_hw hdmi_tx_hw = {
 	.hw_ndx = MDSS_HW_HDMI,
@@ -93,12 +95,15 @@
 
 struct dss_gpio hpd_gpio_config[] = {
 	{0, 1, COMPATIBLE_NAME "-hpd"},
-	{0, 1, COMPATIBLE_NAME "-ddc-clk"},
-	{0, 1, COMPATIBLE_NAME "-ddc-data"},
 	{0, 1, COMPATIBLE_NAME "-mux-en"},
 	{0, 0, COMPATIBLE_NAME "-mux-sel"}
 };
 
+struct dss_gpio ddc_gpio_config[] = {
+	{0, 1, COMPATIBLE_NAME "-ddc-clk"},
+	{0, 1, COMPATIBLE_NAME "-ddc-data"}
+};
+
 struct dss_gpio core_gpio_config[] = {
 };
 
@@ -110,6 +115,7 @@
 {
 	switch (module) {
 	case HDMI_TX_HPD_PM:	return "HDMI_TX_HPD_PM";
+	case HDMI_TX_DDC_PM:	return "HDMI_TX_DDC_PM";
 	case HDMI_TX_CORE_PM:	return "HDMI_TX_CORE_PM";
 	case HDMI_TX_CEC_PM:	return "HDMI_TX_CEC_PM";
 	default: return "???";
@@ -187,6 +193,7 @@
 {
 	switch (module) {
 	case HDMI_TX_HPD_PM:	return "HDMI_TX_HPD_PM";
+	case HDMI_TX_DDC_PM:	return "HDMI_TX_DDC_PM";
 	case HDMI_TX_CORE_PM:	return "HDMI_TX_CORE_PM";
 	case HDMI_TX_CEC_PM:	return "HDMI_TX_CEC_PM";
 	default: return "???";
@@ -810,11 +817,19 @@
 	DEV_DBG("%s: Got HPD interrupt\n", __func__);
 
 	if (hdmi_ctrl->hpd_state) {
+		if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, true)) {
+			DEV_ERR("%s: Failed to enable ddc power\n", __func__);
+			return;
+		}
+
 		hdmi_tx_read_sink_info(hdmi_ctrl);
 		hdmi_tx_send_cable_notification(hdmi_ctrl, 1);
 		DEV_INFO("%s: sense cable CONNECTED: state switch to %d\n",
 			__func__, hdmi_ctrl->sdev.state);
 	} else {
+		if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
+			DEV_WARN("%s: Failed to disable ddc power\n", __func__);
+
 		hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
 		DEV_INFO("%s: sense cable DISCONNECTED: state switch to %d\n",
 			__func__, hdmi_ctrl->sdev.state);
@@ -2298,6 +2313,7 @@
 static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
+	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -2309,10 +2325,26 @@
 		return;
 	}
 
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return;
+	}
+
+	/* Turn off HPD interrupts */
+	DSS_REG_W(io, HDMI_HPD_INT_CTRL, 0);
+
 	mdss_disable_irq(&hdmi_tx_hw);
 
 	hdmi_tx_set_mode(hdmi_ctrl, false);
 
+	if (hdmi_ctrl->hpd_state) {
+		rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, 0);
+		if (rc)
+			DEV_INFO("%s: Failed to disable ddc power. Error=%d\n",
+				__func__, rc);
+	}
+
 	rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, 0);
 	if (rc)
 		DEV_INFO("%s: Failed to disable hpd power. Error=%d\n",
@@ -2411,7 +2443,7 @@
 	struct dss_io_data *io = NULL;
 	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;
 
-	if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
+	if (!hdmi_ctrl) {
 		DEV_WARN("%s: invalid input data, ISR ignored\n", __func__);
 		return IRQ_HANDLED;
 	}
@@ -2874,6 +2906,7 @@
 		mp->clk_config[1].rate = 0;
 		break;
 
+	case HDMI_TX_DDC_PM:
 	case HDMI_TX_CEC_PM:
 		mp->num_clk = 0;
 		DEV_DBG("%s: no clk\n", __func__);
@@ -2933,6 +2966,9 @@
 	case HDMI_TX_HPD_PM:
 		mod_name = "hpd";
 		break;
+	case HDMI_TX_DDC_PM:
+		mod_name = "ddc";
+		break;
 	case HDMI_TX_CORE_PM:
 		mod_name = "core";
 		break;
@@ -3129,6 +3165,10 @@
 		gpio_list_size = ARRAY_SIZE(hpd_gpio_config);
 		gpio_list = hpd_gpio_config;
 		break;
+	case HDMI_TX_DDC_PM:
+		gpio_list_size = ARRAY_SIZE(ddc_gpio_config);
+		gpio_list = ddc_gpio_config;
+		break;
 	case HDMI_TX_CORE_PM:
 		gpio_list_size = ARRAY_SIZE(core_gpio_config);
 		gpio_list = core_gpio_config;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 8d9a477..ce3c00c 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -25,6 +25,7 @@
 
 enum hdmi_tx_power_module_type {
 	HDMI_TX_HPD_PM,
+	HDMI_TX_DDC_PM,
 	HDMI_TX_CORE_PM,
 	HDMI_TX_CEC_PM,
 	HDMI_TX_MAX_PM
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 2f09fee..b9457be 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -134,6 +134,7 @@
 				       char *prop_name);
 static int mdss_mdp_parse_dt_smp(struct platform_device *pdev);
 static int mdss_mdp_parse_dt_misc(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_ad_cfg(struct platform_device *pdev);
 
 int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd)
 {
@@ -387,12 +388,11 @@
 
 		bus_idx = (current_bus_idx % (num_cases - 1)) + 1;
 
-		/* aligning to avoid performing updates for small changes */
-		ab_quota = ALIGN(ab_quota, SZ_64M);
-		ib_quota = ALIGN(ib_quota, SZ_64M);
-
 		vect = mdp_bus_scale_table.usecase[current_bus_idx].vectors;
-		if ((ab_quota == vect->ab) && (ib_quota == vect->ib)) {
+
+		/* avoid performing updates for small changes */
+		if ((ALIGN(ab_quota, SZ_64M) == ALIGN(vect->ab, SZ_64M)) &&
+			(ALIGN(ib_quota, SZ_64M) == ALIGN(vect->ib, SZ_64M))) {
 			pr_debug("skip bus scaling, no change in vectors\n");
 			return 0;
 		}
@@ -1161,6 +1161,12 @@
 		return rc;
 	}
 
+	rc = mdss_mdp_parse_dt_ad_cfg(pdev);
+	if (rc) {
+		pr_err("Error in device tree : ad\n");
+		return rc;
+	}
+
 	return 0;
 }
 
@@ -1483,6 +1489,41 @@
 	return 0;
 }
 
+static int mdss_mdp_parse_dt_ad_cfg(struct platform_device *pdev)
+{
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+	u32 *ad_offsets = NULL;
+	int rc;
+
+	mdata->nad_cfgs = mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-ad-off");
+
+	if (mdata->nad_cfgs == 0) {
+		mdata->ad_cfgs = NULL;
+		return 0;
+	}
+	if (mdata->nad_cfgs > mdata->nmixers_intf)
+		return -EINVAL;
+
+	ad_offsets = kzalloc(sizeof(u32) * mdata->nad_cfgs, GFP_KERNEL);
+	if (!ad_offsets) {
+		pr_err("no mem assigned: kzalloc fail\n");
+		return -ENOMEM;
+	}
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-ad-off", ad_offsets,
+					mdata->nad_cfgs);
+	if (rc)
+		goto parse_done;
+
+	rc = mdss_mdp_ad_addr_setup(mdata, ad_offsets);
+	if (rc)
+		pr_err("unable to setup assertive display\n");
+
+parse_done:
+	kfree(ad_offsets);
+	return rc;
+}
+
 static int mdss_mdp_parse_dt_handler(struct platform_device *pdev,
 		char *prop_name, u32 *offsets, int len)
 {
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 6018e6f..6be2b73 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -109,6 +109,12 @@
 struct mdss_mdp_ctl;
 typedef void (*mdp_vsync_handler_t)(struct mdss_mdp_ctl *, ktime_t);
 
+struct mdss_mdp_vsync_handler {
+	mdp_vsync_handler_t vsync_handler;
+	u32 ref_cnt;
+	struct list_head list;
+};
+
 struct mdss_mdp_ctl {
 	u32 num;
 	char __iomem *base;
@@ -144,14 +150,18 @@
 	struct mutex lock;
 
 	struct mdss_panel_data *panel_data;
+	struct mdss_mdp_vsync_handler vsync_handler;
 
 	int (*start_fnc) (struct mdss_mdp_ctl *ctl);
 	int (*stop_fnc) (struct mdss_mdp_ctl *ctl);
 	int (*prepare_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
 	int (*display_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
 	int (*wait_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
-	int (*set_vsync_handler) (struct mdss_mdp_ctl *, mdp_vsync_handler_t);
 	u32 (*read_line_cnt_fnc) (struct mdss_mdp_ctl *);
+	int (*add_vsync_handler) (struct mdss_mdp_ctl *,
+					struct mdss_mdp_vsync_handler *);
+	int (*remove_vsync_handler) (struct mdss_mdp_ctl *,
+					struct mdss_mdp_vsync_handler *);
 
 	void *priv_data;
 };
@@ -237,6 +247,25 @@
 	spinlock_t hist_lock;
 };
 
+struct mdss_ad_info {
+	char __iomem *base;
+	u8 num;
+	u32 sts;
+	u32 state;
+	u32 ad_data;
+	u32 ad_data_mode;
+	struct mdss_ad_init init;
+	struct mdss_ad_cfg cfg;
+	struct mutex lock;
+	struct work_struct calc_work;
+	struct msm_fb_data_type *mfd;
+	struct mdss_mdp_vsync_handler handle;
+	struct completion comp;
+	u32 last_str;
+	u32 last_bl;
+	u32 calc_itr;
+};
+
 struct pp_sts_type {
 	u32 pa_sts;
 	u32 pcc_sts;
@@ -413,7 +442,7 @@
 int mdss_mdp_pp_init(struct device *dev);
 void mdss_mdp_pp_term(struct device *dev);
 
-int mdss_mdp_pp_resume(u32 mixer_num);
+int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 mixer_num);
 
 int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_pp_setup_locked(struct mdss_mdp_ctl *ctl);
@@ -453,6 +482,13 @@
 				struct mdp_histogram_data *hist);
 void mdss_mdp_hist_intr_done(u32 isr);
 
+int mdss_ad_init_checks(struct msm_fb_data_type *mfd);
+int mdss_mdp_ad_config(struct msm_fb_data_type *mfd,
+				struct mdss_ad_init_cfg *init_cfg);
+int mdss_mdp_ad_input(struct msm_fb_data_type *mfd,
+				struct mdss_ad_input *input);
+int mdss_mdp_ad_addr_setup(struct mdss_data_type *mdata, u32 *ad_off);
+
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(struct mdss_mdp_mixer *mixer,
 					  u32 type);
 struct mdss_mdp_pipe *mdss_mdp_pipe_get(struct mdss_data_type *mdata, u32 ndx);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index d9b1f0c..568fc37 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -292,6 +292,7 @@
 	}
 	mutex_lock(&mdss_mdp_ctl_lock);
 	ctl->ref_cnt--;
+	ctl->intf_num = MDSS_MDP_NO_INTF;
 	ctl->is_secure = false;
 	ctl->power_on = false;
 	ctl->start_fnc = NULL;
@@ -299,8 +300,9 @@
 	ctl->prepare_fnc = NULL;
 	ctl->display_fnc = NULL;
 	ctl->wait_fnc = NULL;
-	ctl->set_vsync_handler = NULL;
 	ctl->read_line_cnt_fnc = NULL;
+	ctl->add_vsync_handler = NULL;
+	ctl->remove_vsync_handler = NULL;
 	mutex_unlock(&mdss_mdp_ctl_lock);
 
 	return 0;
@@ -889,7 +891,7 @@
 		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(i), 0);
 
 	mixer = ctl->mixer_left;
-	mdss_mdp_pp_resume(mixer->num);
+	mdss_mdp_pp_resume(ctl, mixer->num);
 	mixer->params_changed++;
 
 	temp = MDSS_MDP_REG_READ(MDSS_MDP_REG_DISP_INTF_SEL);
@@ -936,7 +938,7 @@
 	ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_RESET, NULL);
 	if (ret) {
 		pr_err("panel power on failed ctl=%d\n", ctl->num);
-		return ret;
+		goto error;
 	}
 
 	ret = mdss_mdp_ctl_start_sub(ctl);
@@ -949,7 +951,7 @@
 			struct mdss_mdp_mixer *mixer = ctl->mixer_right;
 			u32 out, off;
 
-			mdss_mdp_pp_resume(mixer->num);
+			mdss_mdp_pp_resume(ctl, mixer->num);
 			mixer->params_changed++;
 			out = (mixer->height << 16) | mixer->width;
 			off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
@@ -959,6 +961,7 @@
 	}
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+error:
 	mutex_unlock(&ctl->lock);
 
 	return ret;
@@ -1301,9 +1304,10 @@
 	if (mutex_lock_interruptible(&ctl->lock))
 		return -EINTR;
 
-	mixer->params_changed++;
-	mixer->stage_pipe[pipe->mixer_stage] = NULL;
-
+	if (pipe == mixer->stage_pipe[pipe->mixer_stage]) {
+		mixer->params_changed++;
+		mixer->stage_pipe[pipe->mixer_stage] = NULL;
+	}
 	mutex_unlock(&ctl->lock);
 
 	return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index a59560e..6ec5b63 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -351,6 +351,41 @@
 #define MDSS_MDP_REG_WB_DST_ADDR_SW_STATUS		0x2B0
 
 
+#define MDSS_MDP_REG_AD_BYPASS				0x000
+#define MDSS_MDP_REG_AD_CTRL_0				0x004
+#define MDSS_MDP_REG_AD_CTRL_1				0x008
+#define MDSS_MDP_REG_AD_FRAME_SIZE			0x00C
+#define MDSS_MDP_REG_AD_CON_CTRL_0			0x010
+#define MDSS_MDP_REG_AD_CON_CTRL_1			0x014
+#define MDSS_MDP_REG_AD_STR_MAN				0x018
+#define MDSS_MDP_REG_AD_VAR				0x01C
+#define MDSS_MDP_REG_AD_DITH				0x020
+#define MDSS_MDP_REG_AD_DITH_CTRL			0x024
+#define MDSS_MDP_REG_AD_AMP_LIM				0x028
+#define MDSS_MDP_REG_AD_SLOPE				0x02C
+#define MDSS_MDP_REG_AD_BW_LVL				0x030
+#define MDSS_MDP_REG_AD_LOGO_POS			0x034
+#define MDSS_MDP_REG_AD_LUT_FI				0x038
+#define MDSS_MDP_REG_AD_LUT_CC				0x07C
+#define MDSS_MDP_REG_AD_STR_LIM				0x0C8
+#define MDSS_MDP_REG_AD_CALIB_AB			0x0CC
+#define MDSS_MDP_REG_AD_CALIB_CD			0x0D0
+#define MDSS_MDP_REG_AD_MODE_SEL			0x0D4
+#define MDSS_MDP_REG_AD_TFILT_CTRL			0x0D8
+#define MDSS_MDP_REG_AD_BL_MINMAX			0x0DC
+#define MDSS_MDP_REG_AD_BL				0x0E0
+#define MDSS_MDP_REG_AD_BL_MAX				0x0E8
+#define MDSS_MDP_REG_AD_AL				0x0EC
+#define MDSS_MDP_REG_AD_AL_MIN				0x0F0
+#define MDSS_MDP_REG_AD_AL_FILT				0x0F4
+#define MDSS_MDP_REG_AD_CFG_BUF				0x0F8
+#define MDSS_MDP_REG_AD_LUT_AL				0x100
+#define MDSS_MDP_REG_AD_TARG_STR			0x144
+#define MDSS_MDP_REG_AD_START_CALC			0x148
+#define MDSS_MDP_REG_AD_STR_OUT				0x14C
+#define MDSS_MDP_REG_AD_BL_OUT				0x154
+#define MDSS_MDP_REG_AD_CALC_DONE			0x158
+
 enum mdss_mdp_dspp_index {
 	MDSS_MDP_DSPP0,
 	MDSS_MDP_DSPP1,
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index fff8a6e..eb2bd21 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -44,13 +44,21 @@
 
 	/* te config */
 	u8 tear_check;
-	u16 total_lcd_lines;
-	u16 v_porch;	/* vertical porches */
-	u32 vsync_cnt;
+	u16 height;	/* panel height */
+	u16 vporch;	/* vertical porches */
+	u32 vclk_line;	/* vsync clock per line */
 };
 
 struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS];
 
+/*
+ * TE configuration:
+ * dsi byte clock calculated base on 70 fps
+ * around 14 ms to complete a kickoff cycle if te disabled
+ * vclk_line base on 60 fps
+ * write is faster than read
+ * init == start == rdptr
+ */
 static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,
 			struct mdss_mdp_cmd_ctx *ctx, int enable)
 {
@@ -59,15 +67,21 @@
 	cfg = BIT(19); /* VSYNC_COUNTER_EN */
 	if (ctx->tear_check)
 		cfg |= BIT(20);	/* VSYNC_IN_EN */
-	cfg |= ctx->vsync_cnt;
+	cfg |= ctx->vclk_line;
 
 	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
 	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT,
 				0xfff0); /* set to verh height */
-	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_VSYNC_INIT_VAL, 0);
-	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_RD_PTR_IRQ, 0);
 
-	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_START_POS, ctx->v_porch);
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_VSYNC_INIT_VAL,
+						ctx->height);
+
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_RD_PTR_IRQ,
+						ctx->height + 1);
+
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_START_POS,
+						ctx->height);
+
 	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_THRESH,
 			   (CONTINUE_TRESHOLD << 16) | (START_THRESHOLD));
 
@@ -85,7 +99,6 @@
 
 	if (pinfo->mipi.vsync_enable && enable) {
 		u32 mdp_vsync_clk_speed_hz, total_lines;
-		u32 vsync_cnt_cfg_dem;
 
 		mdss_mdp_vsync_clk_enable(1);
 
@@ -100,21 +113,18 @@
 		}
 
 		ctx->tear_check = pinfo->mipi.hw_vsync_mode;
-
-		total_lines = pinfo->lcdc.v_back_porch +
-				    pinfo->lcdc.v_front_porch +
-				    pinfo->lcdc.v_pulse_width + pinfo->yres;
-
-		vsync_cnt_cfg_dem =
-			mult_frac(pinfo->mipi.frame_rate * total_lines,
-						1, 100);
-
-		ctx->vsync_cnt = mdp_vsync_clk_speed_hz / vsync_cnt_cfg_dem;
-
-		ctx->v_porch = pinfo->lcdc.v_back_porch +
+		ctx->height = pinfo->yres;
+		ctx->vporch = pinfo->lcdc.v_back_porch +
 				    pinfo->lcdc.v_front_porch +
 				    pinfo->lcdc.v_pulse_width;
-		ctx->total_lcd_lines = total_lines;
+
+		total_lines = ctx->height + ctx->vporch;
+		total_lines *= pinfo->mipi.frame_rate;
+		ctx->vclk_line = mdp_vsync_clk_speed_hz / total_lines;
+
+		pr_debug("%s: fr=%d tline=%d vcnt=%d vrate=%d\n",
+			__func__, pinfo->mipi.frame_rate, total_lines,
+				ctx->vclk_line, mdp_vsync_clk_speed_hz);
 	} else {
 		enable = 0;
 	}
@@ -225,7 +235,7 @@
 }
 
 static int mdss_mdp_cmd_vsync_ctrl(struct mdss_mdp_ctl *ctl,
-		mdp_vsync_handler_t send_vsync)
+		struct mdss_mdp_vsync_handler *handler)
 {
 	struct mdss_mdp_cmd_ctx *ctx;
 	unsigned long flags;
@@ -237,7 +247,7 @@
 		return -ENODEV;
 	}
 
-	enable = (send_vsync != NULL);
+	enable = (handler->vsync_handler != NULL);
 
 	pr_debug("%s: ctx=%p ctx=%d enabled=%d %d clk_enabled=%d clk_ctrl=%d\n",
 			__func__, ctx, ctx->pp_num, ctx->vsync_enabled, enable,
@@ -253,7 +263,7 @@
 		spin_lock_irqsave(&ctx->clk_lock, flags);
 		ctx->clk_control = 0;
 		ctx->expire = 0;
-		ctx->send_vsync = send_vsync;
+		ctx->send_vsync = handler->vsync_handler;
 		spin_unlock_irqrestore(&ctx->clk_lock, flags);
 		if (ctx->clk_enabled == 0) {
 			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
@@ -366,6 +376,7 @@
 {
 	struct mdss_mdp_cmd_ctx *ctx;
 	int need_wait = 0;
+	struct mdss_mdp_vsync_handler null_handle;
 	int ret;
 
 	ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
@@ -389,7 +400,8 @@
 
 	ctx->panel_on = 0;
 
-	mdss_mdp_cmd_vsync_ctrl(ctl, NULL);
+	null_handle.vsync_handler = NULL;
+	mdss_mdp_cmd_vsync_ctrl(ctl, &null_handle);
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctl->intf_num,
 				   NULL, NULL);
@@ -468,7 +480,8 @@
 	ctl->stop_fnc = mdss_mdp_cmd_stop;
 	ctl->display_fnc = mdss_mdp_cmd_kickoff;
 	ctl->wait_fnc = mdss_mdp_cmd_wait4comp;
-	ctl->set_vsync_handler = mdss_mdp_cmd_vsync_ctrl;
+	ctl->add_vsync_handler = mdss_mdp_cmd_vsync_ctrl;
+	ctl->remove_vsync_handler = mdss_mdp_cmd_vsync_ctrl;
 
 	pr_debug("%s:-\n", __func__);
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 94ae710..d68a3d4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -13,11 +13,16 @@
 
 #define pr_fmt(fmt)	"%s: " fmt, __func__
 
+#include <linux/iopoll.h>
+
 #include "mdss_fb.h"
 #include "mdss_mdp.h"
 
-/* wait for at most 2 vsync for lowest refresh rate (24hz) */
-#define VSYNC_TIMEOUT msecs_to_jiffies(84)
+/* wait for at least 2 vsyncs for lowest refresh rate (24hz) */
+#define VSYNC_TIMEOUT_US 100000
+
+#define MDP_INTR_MASK_INTF_VSYNC(intf_num) \
+	(1 << (2 * (intf_num - MDSS_MDP_INTF0) + MDSS_MDP_IRQ_INTF_VSYNC))
 
 /* intf timing settings */
 struct intf_timing_params {
@@ -45,12 +50,14 @@
 	u8 ref_cnt;
 
 	u8 timegen_en;
+	bool polling_en;
+	u32 poll_cnt;
 	struct completion vsync_comp;
 	int wait_pending;
 
 	atomic_t vsync_ref;
 	spinlock_t vsync_lock;
-	mdp_vsync_handler_t vsync_handler;
+	struct list_head vsync_handlers;
 };
 
 static inline void mdp_video_write(struct mdss_mdp_video_ctx *ctx,
@@ -92,6 +99,7 @@
 				offsets[i], head[i].base);
 		head[i].ref_cnt = 0;
 		head[i].intf_num = i + MDSS_MDP_INTF0;
+		INIT_LIST_HEAD(&head[i].vsync_handlers);
 	}
 
 	mdata->video_intf = head;
@@ -212,12 +220,54 @@
 		mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
 }
 
-static int mdss_mdp_video_set_vsync_handler(struct mdss_mdp_ctl *ctl,
-		mdp_vsync_handler_t vsync_handler)
+static int mdss_mdp_video_add_vsync_handler(struct mdss_mdp_ctl *ctl,
+		struct mdss_mdp_vsync_handler *handle)
 {
 	struct mdss_mdp_video_ctx *ctx;
 	unsigned long flags;
-	int need_update;
+	struct mdss_mdp_vsync_handler *tmp;
+	bool exist = false;
+	int ret = 0;
+
+	if (!handle || !(handle->vsync_handler)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
+	if (!ctx) {
+		pr_err("invalid ctx for ctl=%d\n", ctl->num);
+		ret = -ENODEV;
+		goto exit;
+	}
+
+	spin_lock_irqsave(&ctx->vsync_lock, flags);
+	list_for_each_entry(tmp, &(ctx->vsync_handlers), list) {
+		if (tmp->vsync_handler == handle->vsync_handler) {
+			exist = true;
+			tmp->ref_cnt++;
+		}
+	}
+	if (!exist) {
+		handle->ref_cnt = 1;
+		list_add(&handle->list, &ctx->vsync_handlers);
+	}
+
+	video_vsync_irq_enable(ctl);
+	spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+exit:
+	return ret;
+}
+
+/* passing NULL as handle or vsync_handler will clear all handlers */
+static int mdss_mdp_video_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
+		struct mdss_mdp_vsync_handler *handle)
+{
+	struct mdss_mdp_video_ctx *ctx;
+	unsigned long flags;
+	struct mdss_mdp_vsync_handler *tmp, *q;
+	bool exist = true;
+	bool used = false;
 
 	ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
 	if (!ctx) {
@@ -226,18 +276,20 @@
 	}
 
 	spin_lock_irqsave(&ctx->vsync_lock, flags);
-	need_update = (!ctx->vsync_handler && vsync_handler) ||
-			(ctx->vsync_handler && !vsync_handler);
-	ctx->vsync_handler = vsync_handler;
-	spin_unlock_irqrestore(&ctx->vsync_lock, flags);
-
-	if (need_update) {
-		if (vsync_handler)
-			video_vsync_irq_enable(ctl);
-		else
-			video_vsync_irq_disable(ctl);
+	list_for_each_entry_safe(tmp, q, &ctx->vsync_handlers, list) {
+		if (handle && handle->vsync_handler)
+			exist = (tmp->vsync_handler == handle->vsync_handler);
+		if (exist) {
+			tmp->ref_cnt--;
+			if (handle && handle->vsync_handler)
+				used = (tmp->ref_cnt != 0);
+			if (!used) {
+				video_vsync_irq_disable(ctl);
+				list_del_init(&tmp->list);
+			}
+		}
 	}
-
+	spin_unlock_irqrestore(&ctx->vsync_lock, flags);
 	return 0;
 }
 
@@ -274,7 +326,7 @@
 			ctl->intf_num);
 	}
 
-	mdss_mdp_video_set_vsync_handler(ctl, NULL);
+	mdss_mdp_video_remove_vsync_handler(ctl, NULL);
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
 				   NULL, NULL);
@@ -291,6 +343,7 @@
 {
 	struct mdss_mdp_ctl *ctl = arg;
 	struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
+	struct mdss_mdp_vsync_handler *tmp;
 	ktime_t vsync_time;
 
 	if (!ctx) {
@@ -304,13 +357,53 @@
 	pr_debug("intr ctl=%d vsync cnt=%u vsync_time=%d\n",
 		 ctl->num, ctl->vsync_cnt, (int)ktime_to_ms(vsync_time));
 
+	ctx->polling_en = false;
 	complete_all(&ctx->vsync_comp);
 	spin_lock(&ctx->vsync_lock);
-	if (ctx->vsync_handler)
-		ctx->vsync_handler(ctl, vsync_time);
+	list_for_each_entry(tmp, &ctx->vsync_handlers, list) {
+		tmp->vsync_handler(ctl, vsync_time);
+	}
 	spin_unlock(&ctx->vsync_lock);
 }
 
+static int mdss_mdp_video_pollwait(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
+	u32 mask, status;
+	int rc;
+
+	mask = MDP_INTR_MASK_INTF_VSYNC(ctl->intf_num);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	rc = readl_poll_timeout(ctl->mdata->mdp_base + MDSS_MDP_REG_INTR_STATUS,
+		status,
+		(status & mask) || try_wait_for_completion(&ctx->vsync_comp),
+		1000,
+		VSYNC_TIMEOUT_US);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	if (rc == 0) {
+		pr_debug("vsync poll successful! rc=%d status=0x%x\n",
+				rc, status);
+		ctx->poll_cnt++;
+		if (status) {
+			struct mdss_mdp_vsync_handler *tmp;
+			unsigned long flags;
+			ktime_t vsync_time = ktime_get();
+
+			spin_lock_irqsave(&ctx->vsync_lock, flags);
+			list_for_each_entry(tmp, &ctx->vsync_handlers, list)
+				tmp->vsync_handler(ctl, vsync_time);
+			spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+		}
+	} else {
+		pr_warn("vsync poll timed out! rc=%d status=0x%x mask=0x%x\n",
+				rc, status, mask);
+	}
+
+	return rc;
+}
+
 static int mdss_mdp_video_wait4comp(struct mdss_mdp_ctl *ctl, void *arg)
 {
 	struct mdss_mdp_video_ctx *ctx;
@@ -324,9 +417,20 @@
 
 	WARN(!ctx->wait_pending, "waiting without commit! ctl=%d", ctl->num);
 
-	rc = wait_for_completion_interruptible_timeout(&ctx->vsync_comp,
-			VSYNC_TIMEOUT);
-	WARN(rc <= 0, "vsync timed out (%d) ctl=%d\n", rc, ctl->num);
+	if (ctx->polling_en) {
+		rc = mdss_mdp_video_pollwait(ctl);
+	} else {
+		rc = wait_for_completion_interruptible_timeout(&ctx->vsync_comp,
+				usecs_to_jiffies(VSYNC_TIMEOUT_US));
+		if (rc < 0) {
+			pr_warn("vsync wait interrupted ctl=%d\n", ctl->num);
+		} else if (rc == 0) {
+			pr_warn("vsync wait timeout %d, fallback to poll mode\n",
+					ctl->num);
+			ctx->polling_en++;
+			rc = mdss_mdp_video_pollwait(ctl);
+		}
+	}
 
 	if (ctx->wait_pending) {
 		ctx->wait_pending = 0;
@@ -343,7 +447,7 @@
 		return;
 
 	ctl->underrun_cnt++;
-	pr_warn("display underrun detected for ctl=%d count=%d\n", ctl->num,
+	pr_debug("display underrun detected for ctl=%d count=%d\n", ctl->num,
 			ctl->underrun_cnt);
 }
 
@@ -381,7 +485,7 @@
 		wmb();
 
 		rc = wait_for_completion_interruptible_timeout(&ctx->vsync_comp,
-				VSYNC_TIMEOUT);
+				usecs_to_jiffies(VSYNC_TIMEOUT_US));
 		WARN(rc <= 0, "timeout (%d) enabling timegen on ctl=%d\n",
 				rc, ctl->num);
 
@@ -471,8 +575,9 @@
 	ctl->stop_fnc = mdss_mdp_video_stop;
 	ctl->display_fnc = mdss_mdp_video_display;
 	ctl->wait_fnc = mdss_mdp_video_wait4comp;
-	ctl->set_vsync_handler = mdss_mdp_video_set_vsync_handler;
 	ctl->read_line_cnt_fnc = mdss_mdp_video_line_count;
+	ctl->add_vsync_handler = mdss_mdp_video_add_vsync_handler;
+	ctl->remove_vsync_handler = mdss_mdp_video_remove_vsync_handler;
 
 	return 0;
 }
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 024b73f..7363325 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -179,6 +179,14 @@
 			       req->src_rect.h, req->dst_rect.h);
 			return -EINVAL;
 		}
+
+		if (req->flags & MDP_BWC_EN) {
+			if ((req->src.width != req->src_rect.w) ||
+			    (req->src.height != req->src_rect.h)) {
+				pr_err("BWC: unequal src img and rect w,h\n");
+				return -EINVAL;
+			}
+		}
 	}
 
 	if (fmt->is_yuv) {
@@ -189,6 +197,13 @@
 		}
 	}
 
+	if (req->flags & MDP_DEINTERLACE) {
+		if ((req->src.width % 4 != 0) || (req->src.height % 4 != 0)) {
+			pr_err("interlaced fmt w,h need to be even post div\n");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
@@ -322,7 +337,7 @@
 	if (pipe && pipe->ndx != req->id) {
 		pr_debug("replacing pnum=%d at stage=%d mux=%d\n",
 				pipe->num, req->z_order, mixer_mux);
-		pipe->params_changed = true;
+		mdss_mdp_mixer_pipe_unstage(pipe);
 	}
 
 	mixer = mdss_mdp_mixer_get(mdp5_data->ctl, mixer_mux);
@@ -774,6 +789,7 @@
 			buf = &pipe->front_buf;
 		} else {
 			pr_warn("pipe queue w/o buffer. unstaging layer\n");
+			pipe->params_changed = 0;
 			mdss_mdp_mixer_pipe_unstage(pipe);
 			continue;
 		}
@@ -1301,7 +1317,7 @@
 
 	if (!ctl)
 		return -ENODEV;
-	if (!ctl->set_vsync_handler)
+	if (!ctl->add_vsync_handler || !ctl->remove_vsync_handler)
 		return -ENOTSUPP;
 
 	rc = mutex_lock_interruptible(&ctl->lock);
@@ -1324,9 +1340,9 @@
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 	if (en)
-		rc = ctl->set_vsync_handler(ctl, mdss_mdp_overlay_handle_vsync);
+		rc = ctl->add_vsync_handler(ctl, &ctl->vsync_handler);
 	else
-		rc = ctl->set_vsync_handler(ctl, NULL);
+		rc = ctl->remove_vsync_handler(ctl, &ctl->vsync_handler);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
 	mutex_unlock(&ctl->lock);
@@ -1516,7 +1532,7 @@
 {
 	int ret = 0;
 	int curr_bl;
-	mutex_lock(&mfd->lock);
+	mutex_lock(&mfd->bl_lock);
 	curr_bl = mfd->bl_level;
 	mfd->bl_scale = data->scale;
 	mfd->bl_min_lvl = data->min_lvl;
@@ -1525,7 +1541,7 @@
 
 	/* update current backlight to use new scaling*/
 	mdss_fb_set_backlight(mfd, curr_bl);
-	mutex_unlock(&mfd->lock);
+	mutex_unlock(&mfd->bl_lock);
 	return ret;
 }
 
@@ -1599,6 +1615,16 @@
 		ret = mdss_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
 						&mdp_pp.data.bl_scale_data);
 		break;
+	case mdp_op_ad_cfg:
+		ret = mdss_mdp_ad_config(mfd, &mdp_pp.data.ad_init_cfg);
+		break;
+	case mdp_op_ad_input:
+		ret = mdss_mdp_ad_input(mfd, &mdp_pp.data.ad_input);
+		if (ret > 0) {
+			ret = 0;
+			copyback = 1;
+		}
+		break;
 	default:
 		pr_err("Unsupported request to MDP_PP IOCTL.\n");
 		ret = -EINVAL;
@@ -1775,11 +1801,8 @@
 			struct msmfb_overlay_data data;
 
 			ret = copy_from_user(&data, argp, sizeof(data));
-			if (!ret) {
+			if (!ret)
 				ret = mdss_mdp_overlay_play(mfd, &data);
-				if (!IS_ERR_VALUE(ret))
-					mdss_fb_update_backlight(mfd);
-			}
 
 			if (ret)
 				pr_debug("OVERLAY_PLAY failed (%d)\n", ret);
@@ -1867,6 +1890,8 @@
 				mfd->index);
 			return PTR_ERR(ctl);
 		}
+		ctl->vsync_handler.vsync_handler =
+						mdss_mdp_overlay_handle_vsync;
 
 		if (mfd->split_display && pdata->next) {
 			/* enable split display */
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 8bd5674..12ff943 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -119,6 +119,39 @@
 #define PP_STS_ENABLE	0x1
 #define PP_STS_GAMUT_FIRST	0x2
 
+#define PP_AD_STATE_INIT	0x2
+#define PP_AD_STATE_CFG		0x4
+#define PP_AD_STATE_DATA	0x8
+#define PP_AD_STATE_RUN		0x10
+#define PP_AD_STATE_VSYNC	0x20
+
+#define PP_AD_STATE_IS_INITCFG(st)	(((st) & PP_AD_STATE_INIT) &&\
+						((st) & PP_AD_STATE_CFG))
+
+#define PP_AD_STATE_IS_READY(st)	(((st) & PP_AD_STATE_INIT) &&\
+						((st) & PP_AD_STATE_CFG) &&\
+						((st) & PP_AD_STATE_DATA))
+
+#define PP_AD_STS_DIRTY_INIT	0x2
+#define PP_AD_STS_DIRTY_CFG	0x4
+#define PP_AD_STS_DIRTY_DATA	0x8
+#define PP_AD_STS_DIRTY_VSYNC	0x10
+
+#define PP_AD_STS_IS_DIRTY(sts) (((sts) & PP_AD_STS_DIRTY_INIT) ||\
+					((sts) & PP_AD_STS_DIRTY_CFG))
+
+/* Bits 0 and 1 */
+#define MDSS_AD_INPUT_AMBIENT	(0x03)
+/* Bits 3 and 7 */
+#define MDSS_AD_INPUT_STRENGTH	(0x88)
+/*
+ * Check data by shifting by mode to see if it matches to the
+ * MDSS_AD_INPUT_* bitfields
+ */
+#define MDSS_AD_MODE_DATA_MATCH(mode, data) ((1 << (mode)) & (data))
+#define MDSS_AD_RUNNING_AUTO_BL(ad) (((ad)->state & PP_AD_STATE_RUN) &&\
+				((ad)->cfg.mode == MDSS_AD_MODE_AUTO_BL))
+
 #define SHARP_STRENGTH_DEFAULT	32
 #define SHARP_EDGE_THR_DEFAULT	112
 #define SHARP_SMOOTH_THR_DEFAULT	8
@@ -187,7 +220,14 @@
 static void pp_sharp_config(char __iomem *offset,
 				struct pp_sts_type *pp_sts,
 				struct mdp_sharp_cfg *sharp_config);
+static void pp_ad_vsync_handler(struct mdss_mdp_ctl *ctl, ktime_t t);
+static void pp_ad_cfg_write(struct mdss_ad_info *ad);
+static void pp_ad_init_write(struct mdss_ad_info *ad);
+static void pp_ad_input_write(struct mdss_ad_info *ad, u32 bl_lvl);
+static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd);
+static void pp_ad_cfg_lut(char __iomem *offset, u32 *data);
 
+static u32 last_sts, last_state;
 
 int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
 				   struct mdp_csc_cfg *data)
@@ -906,8 +946,11 @@
 	u32 data;
 	char __iomem *basel;
 	int i, ret = 0;
+	struct mdss_data_type *mdata;
 
-	if (!mixer || !ctl)
+	mdata = ctl->mdata;
+
+	if (!mixer || !ctl || !mdata)
 		return -EINVAL;
 
 	dspp_num = mixer->num;
@@ -929,9 +972,15 @@
 	else
 		flags = 0;
 
+	if (dspp_num < mdata->nad_cfgs) {
+		ret = mdss_mdp_ad_setup(ctl->mfd);
+		if (ret < 0)
+			pr_warn("ad_setup(dspp%d) returns %d", dspp_num, ret);
+	}
 	/* nothing to update */
-	if ((!flags) && (!(opmode)))
+	if ((!flags) && (!(opmode)) && (ret <= 0))
 		goto dspp_exit;
+	ret = 0;
 
 	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
 
@@ -1077,16 +1126,30 @@
  * Set dirty and write bits on features that were enabled so they will be
  * reconfigured
  */
-int mdss_mdp_pp_resume(u32 mixer_num)
+int mdss_mdp_pp_resume(struct mdss_mdp_ctl *ctl, u32 mixer_num)
 {
 	u32 flags = 0;
 	struct pp_sts_type pp_sts;
-
+	struct mdss_ad_info *ad;
+	struct mdss_data_type *mdata = ctl->mdata;
 	if (mixer_num >= MDSS_MDP_MAX_DSPP) {
 		pr_warn("invalid mixer_num");
 		return -EINVAL;
 	}
 
+	if (mixer_num < mdata->nad_cfgs) {
+		ad = &mdata->ad_cfgs[mixer_num];
+
+		if (PP_AD_STATE_CFG & ad->state)
+			pp_ad_cfg_write(ad);
+		if (PP_AD_STATE_INIT & ad->state)
+			pp_ad_init_write(ad);
+		if (PP_AD_STATE_DATA & ad->state)
+			pp_ad_input_write(ad, ctl->mfd->bl_level);
+		if ((PP_AD_STATE_VSYNC & ad->state) && ad->calc_itr)
+			ctl->add_vsync_handler(ctl, &ad->handle);
+	}
+
 	pp_sts = mdss_pp_res->pp_dspp_sts[mixer_num];
 
 	if (pp_sts.pa_sts & PP_STS_ENABLE) {
@@ -2519,3 +2582,472 @@
 		}
 	};
 }
+
+#define MDSS_AD_MAX_MIXERS 1
+int mdss_ad_init_checks(struct msm_fb_data_type *mfd)
+{
+	u32 mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
+	u32 mixer_num;
+	u32 ret = -EINVAL;
+	int i = 0;
+	struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+
+	if (!mfd || !mdata)
+		return ret;
+
+	if (mdata->nad_cfgs == 0) {
+		pr_debug("Assertive Display not supported by device");
+		return -ENODEV;
+	}
+
+	if (mfd->panel_info->type == MIPI_CMD_PANEL) {
+		pr_debug("Command panel not supported");
+		return -EINVAL;
+	}
+
+	mixer_num = mdss_mdp_get_ctl_mixers(mfd->index, mixer_id);
+	if (!mixer_num || mixer_num > MDSS_AD_MAX_MIXERS) {
+		pr_err("invalid mixer_num, %d", mixer_num);
+		return ret;
+	}
+
+	do {
+		if (mixer_id[i] >= mdata->nad_cfgs) {
+			pr_err("invalid mixer input, %d", mixer_id[i]);
+			return ret;
+		}
+		i++;
+	} while (i < mixer_num);
+
+	return mixer_id[0];
+}
+
+int mdss_mdp_ad_config(struct msm_fb_data_type *mfd,
+			struct mdss_ad_init_cfg *init_cfg)
+{
+	int ad_num;
+	struct mdss_ad_info *ad;
+	struct mdss_data_type *mdata;
+	struct mdss_mdp_ctl *ctl;
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+
+	ctl = mdp5_data->ctl;
+
+	ad_num = mdss_ad_init_checks(mfd);
+	if (ad_num < 0)
+		return ad_num;
+
+	mdata = mdss_mdp_get_mdata();
+	ad = &mdata->ad_cfgs[ad_num];
+
+	mutex_lock(&ad->lock);
+	if (init_cfg->ops & MDP_PP_AD_INIT) {
+		memcpy(&ad->init, &init_cfg->params.init,
+				sizeof(struct mdss_ad_init));
+		ad->sts |= PP_AD_STS_DIRTY_INIT;
+	} else if (init_cfg->ops & MDP_PP_AD_CFG) {
+		memcpy(&ad->cfg, &init_cfg->params.cfg,
+				sizeof(struct mdss_ad_cfg));
+		/*
+		 * TODO: specify panel independent range of input from cfg,
+		 * scale input backlight_scale to panel bl_max's range
+		 */
+		ad->cfg.backlight_scale = mfd->panel_info->bl_max;
+		ad->sts |= PP_AD_STS_DIRTY_CFG;
+	}
+
+	if (init_cfg->ops & MDP_PP_OPS_DISABLE) {
+		ad->sts &= ~PP_STS_ENABLE;
+		ad->mfd = NULL;
+	} else if (init_cfg->ops & MDP_PP_OPS_ENABLE) {
+		ad->sts |= PP_STS_ENABLE;
+		ad->mfd = mfd;
+	}
+	mutex_unlock(&ad->lock);
+	mdss_mdp_pp_setup(ctl);
+	return 0;
+}
+
+int mdss_mdp_ad_input(struct msm_fb_data_type *mfd,
+			struct mdss_ad_input *input) {
+	int ad_num, ret = 0;
+	struct mdss_ad_info *ad;
+	struct mdss_data_type *mdata;
+	struct mdss_mdp_ctl *ctl;
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+
+	ctl = mdp5_data->ctl;
+
+	ad_num = mdss_ad_init_checks(mfd);
+	if (ad_num < 0)
+		return ad_num;
+
+	mdata = mdss_mdp_get_mdata();
+	ad = &mdata->ad_cfgs[ad_num];
+
+	mutex_lock(&ad->lock);
+	if (!PP_AD_STATE_IS_INITCFG(ad->state) &&
+			!PP_AD_STS_IS_DIRTY(ad->sts)) {
+		pr_warn("AD not initialized or configured.");
+		ret = -EPERM;
+		goto error;
+	}
+	switch (input->mode) {
+	case MDSS_AD_MODE_AUTO_BL:
+	case MDSS_AD_MODE_AUTO_STR:
+		if (!MDSS_AD_MODE_DATA_MATCH(ad->cfg.mode,
+				MDSS_AD_INPUT_AMBIENT)) {
+			ret = -EINVAL;
+			goto error;
+		}
+		ad->ad_data_mode = MDSS_AD_INPUT_AMBIENT;
+
+		ad->ad_data = input->in.amb_light;
+		ad->calc_itr = ad->cfg.stab_itr;
+		ad->sts |= PP_AD_STS_DIRTY_VSYNC;
+		ad->sts |= PP_AD_STS_DIRTY_DATA;
+		break;
+	case MDSS_AD_MODE_TARG_STR:
+	case MDSS_AD_MODE_MAN_STR:
+		if (!MDSS_AD_MODE_DATA_MATCH(ad->cfg.mode,
+				MDSS_AD_INPUT_STRENGTH)) {
+			ret = -EINVAL;
+			goto error;
+		}
+		ad->ad_data_mode = MDSS_AD_INPUT_STRENGTH;
+		ad->ad_data = input->in.strength;
+		ad->calc_itr = ad->cfg.stab_itr;
+		ad->sts |= PP_AD_STS_DIRTY_VSYNC;
+		ad->sts |= PP_AD_STS_DIRTY_DATA;
+		break;
+	default:
+		pr_warn("invalid default %d", input->mode);
+		ret = -EINVAL;
+		goto error;
+	}
+error:
+	mutex_unlock(&ad->lock);
+	if (!ret) {
+		mutex_lock(&ad->lock);
+		init_completion(&ad->comp);
+		mutex_unlock(&ad->lock);
+		mdss_mdp_pp_setup(ctl);
+		ret = wait_for_completion_interruptible_timeout(&ad->comp,
+							HIST_WAIT_TIMEOUT(1));
+		if (ret == 0)
+			ret = -ETIMEDOUT;
+		else if (ret > 0)
+			input->output = ad->last_str;
+	}
+	return ret;
+}
+
+static void pp_ad_input_write(struct mdss_ad_info *ad, u32 bl_lvl)
+{
+	char __iomem *base = ad->base;
+	switch (ad->cfg.mode) {
+	case MDSS_AD_MODE_AUTO_BL:
+		writel_relaxed(ad->ad_data, base + MDSS_MDP_REG_AD_AL);
+		break;
+	case MDSS_AD_MODE_AUTO_STR:
+		writel_relaxed(bl_lvl, base + MDSS_MDP_REG_AD_BL);
+		writel_relaxed(ad->ad_data, base + MDSS_MDP_REG_AD_AL);
+		break;
+	case MDSS_AD_MODE_TARG_STR:
+		writel_relaxed(bl_lvl, base + MDSS_MDP_REG_AD_BL);
+		writel_relaxed(ad->ad_data, base + MDSS_MDP_REG_AD_TARG_STR);
+		break;
+	case MDSS_AD_MODE_MAN_STR:
+		writel_relaxed(bl_lvl, base + MDSS_MDP_REG_AD_BL);
+		writel_relaxed(ad->ad_data, base + MDSS_MDP_REG_AD_STR_MAN);
+		break;
+	default:
+		pr_warn("Invalid mode! %d", ad->cfg.mode);
+		break;
+	}
+}
+
+static void pp_ad_init_write(struct mdss_ad_info *ad)
+{
+	u32 temp;
+	char __iomem *base = ad->base;
+	writel_relaxed(ad->init.i_control[0] & 0x1F,
+				base + MDSS_MDP_REG_AD_CON_CTRL_0);
+	writel_relaxed(ad->init.i_control[1] << 8,
+				base + MDSS_MDP_REG_AD_CON_CTRL_1);
+
+	temp = ad->init.white_lvl << 16;
+	temp |= ad->init.black_lvl & 0xFFFF;
+	writel_relaxed(temp, base + MDSS_MDP_REG_AD_BW_LVL);
+
+	writel_relaxed(ad->init.var, base + MDSS_MDP_REG_AD_VAR);
+
+	writel_relaxed(ad->init.limit_ampl, base + MDSS_MDP_REG_AD_AMP_LIM);
+
+	writel_relaxed(ad->init.i_dither, base + MDSS_MDP_REG_AD_DITH);
+
+	temp = ad->init.slope_max << 8;
+	temp |= ad->init.slope_min & 0xFF;
+	writel_relaxed(temp, base + MDSS_MDP_REG_AD_SLOPE);
+
+	writel_relaxed(ad->init.dither_ctl, base + MDSS_MDP_REG_AD_DITH_CTRL);
+
+	writel_relaxed(ad->init.format, base + MDSS_MDP_REG_AD_CTRL_0);
+	writel_relaxed(ad->init.auto_size, base + MDSS_MDP_REG_AD_CTRL_1);
+
+	temp = ad->init.frame_w << 16;
+	temp |= ad->init.frame_h & 0xFFFF;
+	writel_relaxed(temp, base + MDSS_MDP_REG_AD_FRAME_SIZE);
+
+	temp = ad->init.logo_v << 8;
+	temp |= ad->init.logo_h & 0xFF;
+	writel_relaxed(temp, base + MDSS_MDP_REG_AD_LOGO_POS);
+
+	pp_ad_cfg_lut(base + MDSS_MDP_REG_AD_LUT_FI, ad->init.asym_lut);
+	pp_ad_cfg_lut(base + MDSS_MDP_REG_AD_LUT_CC, ad->init.color_corr_lut);
+}
+
+#define MDSS_PP_AD_DEF_CALIB 0x6E
+static void pp_ad_cfg_write(struct mdss_ad_info *ad)
+{
+	char __iomem *base = ad->base;
+	u32 temp, temp_calib = MDSS_PP_AD_DEF_CALIB;
+	switch (ad->cfg.mode) {
+	case MDSS_AD_MODE_AUTO_BL:
+		temp = ad->cfg.backlight_max << 16;
+		temp |= ad->cfg.backlight_min & 0xFFFF;
+		writel_relaxed(temp, base + MDSS_MDP_REG_AD_BL_MINMAX);
+		writel_relaxed(ad->cfg.amb_light_min,
+				base + MDSS_MDP_REG_AD_AL_MIN);
+		temp = ad->cfg.filter[1] << 16;
+		temp |= ad->cfg.filter[0] & 0xFFFF;
+		writel_relaxed(temp, base + MDSS_MDP_REG_AD_AL_FILT);
+	case MDSS_AD_MODE_AUTO_STR:
+		pp_ad_cfg_lut(base + MDSS_MDP_REG_AD_LUT_AL,
+				ad->cfg.al_calib_lut);
+		writel_relaxed(ad->cfg.strength_limit,
+				base + MDSS_MDP_REG_AD_STR_LIM);
+		temp = ad->cfg.calib[3] << 16;
+		temp |= ad->cfg.calib[2] & 0xFFFF;
+		writel_relaxed(temp, base + MDSS_MDP_REG_AD_CALIB_CD);
+		writel_relaxed(ad->cfg.t_filter_recursion,
+				base + MDSS_MDP_REG_AD_TFILT_CTRL);
+		temp_calib = ad->cfg.calib[0] & 0xFFFF;
+	case MDSS_AD_MODE_TARG_STR:
+		temp = ad->cfg.calib[1] << 16;
+		temp |= temp_calib;
+		writel_relaxed(temp, base + MDSS_MDP_REG_AD_CALIB_AB);
+	case MDSS_AD_MODE_MAN_STR:
+		writel_relaxed(ad->cfg.backlight_scale,
+				base + MDSS_MDP_REG_AD_BL_MAX);
+		writel_relaxed(ad->cfg.mode, base + MDSS_MDP_REG_AD_MODE_SEL);
+		pr_debug("stab_itr = %d", ad->cfg.stab_itr);
+		break;
+	default:
+		break;
+	}
+}
+
+static void pp_ad_vsync_handler(struct mdss_mdp_ctl *ctl, ktime_t t)
+{
+	struct mdss_data_type *mdata = ctl->mdata;
+	struct mdss_ad_info *ad;
+
+	if (ctl->mixer_left && ctl->mixer_left->num < mdata->nad_cfgs) {
+		ad = &mdata->ad_cfgs[ctl->mixer_left->num];
+		queue_work(mdata->ad_calc_wq, &ad->calc_work);
+	}
+}
+
+#define MDSS_PP_AD_BYPASS_DEF 0x101
+static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
+{
+	int ad_num, ret = 0;
+	struct mdss_ad_info *ad;
+	struct mdss_data_type *mdata;
+	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+	char __iomem *base;
+	u32 bypass = MDSS_PP_AD_BYPASS_DEF;
+
+	ad_num = mdss_ad_init_checks(mfd);
+	if (ad_num < 0)
+		return ad_num;
+
+	mdata = mdss_mdp_get_mdata();
+	ad = &mdata->ad_cfgs[ad_num];
+	base = ad->base;
+
+	mutex_lock(&ad->lock);
+	if (ad->sts != last_sts || ad->state != last_state) {
+		last_sts = ad->sts;
+		last_state = ad->state;
+		pr_debug("begining: ad->sts = 0x%08x, state = 0x%08x", ad->sts,
+								ad->state);
+	}
+	if (!PP_AD_STS_IS_DIRTY(ad->sts) &&
+		(ad->sts & PP_AD_STS_DIRTY_DATA ||
+			(ad->state & PP_AD_STATE_RUN &&
+				(ad->cfg.mode == MDSS_AD_MODE_AUTO_STR)))) {
+		/*
+		 * Write inputs to regs when the data has been updated or
+		 * Assertive Display is up and running as long as there are
+		 * no updates to AD init or cfg
+		 */
+		ad->sts &= ~PP_AD_STS_DIRTY_DATA;
+		ad->state |= PP_AD_STATE_DATA;
+		if (mfd->bl_level != ad->last_bl) {
+			ad->last_bl = mfd->bl_level;
+			ad->calc_itr = ad->cfg.stab_itr;
+			ad->sts |= PP_AD_STS_DIRTY_VSYNC;
+		}
+		pp_ad_input_write(ad, mfd->bl_level);
+	}
+
+	if (ad->sts & PP_AD_STS_DIRTY_CFG) {
+		ad->sts &= ~PP_AD_STS_DIRTY_CFG;
+		ad->state |= PP_AD_STATE_CFG;
+
+		pp_ad_cfg_write(ad);
+
+		if (!MDSS_AD_MODE_DATA_MATCH(ad->cfg.mode, ad->ad_data_mode)) {
+			ad->sts &= ~PP_AD_STS_DIRTY_DATA;
+			ad->state &= ~PP_AD_STATE_DATA;
+			pr_debug("Mode switched, data invalidated!");
+		}
+	}
+	if (ad->sts & PP_AD_STS_DIRTY_INIT) {
+		ad->sts &= ~PP_AD_STS_DIRTY_INIT;
+		ad->state |= PP_AD_STATE_INIT;
+		pp_ad_init_write(ad);
+	}
+
+	if ((ad->sts & PP_STS_ENABLE) && PP_AD_STATE_IS_READY(ad->state)) {
+		bypass = 0;
+		ret = 1;
+		ad->state |= PP_AD_STATE_RUN;
+	} else {
+		if (ad->state & PP_AD_STATE_RUN) {
+			ret = 1;
+			ad->sts |= PP_AD_STS_DIRTY_VSYNC;
+		}
+		ad->state &= ~PP_AD_STATE_RUN;
+	}
+	writel_relaxed(bypass, base);
+
+	if (PP_AD_STS_DIRTY_VSYNC & ad->sts) {
+		pr_debug("dirty vsync, calc_itr = %d", ad->calc_itr);
+		ad->sts &= ~PP_AD_STS_DIRTY_VSYNC;
+		if (!(PP_AD_STATE_VSYNC & ad->state) && ad->calc_itr) {
+			ctl->add_vsync_handler(ctl, &ad->handle);
+			ad->state |= PP_AD_STATE_VSYNC;
+		} else if ((PP_AD_STATE_VSYNC & ad->state) &&
+			(!ad->calc_itr || !(PP_AD_STATE_RUN & ad->state))) {
+			ctl->remove_vsync_handler(ctl, &ad->handle);
+			ad->state &= ~PP_AD_STATE_VSYNC;
+		}
+	}
+
+	if (ad->sts != last_sts || ad->state != last_state) {
+		last_sts = ad->sts;
+		last_state = ad->state;
+		pr_debug("end: ad->sts = 0x%08x, state = 0x%08x", ad->sts,
+								ad->state);
+	}
+	mutex_unlock(&ad->lock);
+	return ret;
+}
+
+#define MDSS_PP_AD_SLEEP 10
+static void pp_ad_calc_worker(struct work_struct *work)
+{
+	struct mdss_ad_info *ad;
+	struct mdss_mdp_ctl *ctl;
+	u32 bl, calc_done = 0;
+	ad = container_of(work, struct mdss_ad_info, calc_work);
+	ctl = mfd_to_ctl(ad->mfd);
+
+	mutex_lock(&ad->lock);
+	if (PP_AD_STATE_RUN & ad->state) {
+		/* Kick off calculation */
+		ad->calc_itr--;
+		writel_relaxed(1, ad->base + MDSS_MDP_REG_AD_START_CALC);
+	}
+	if (ad->state & PP_AD_STATE_RUN) {
+		do {
+			calc_done = readl_relaxed(ad->base +
+				MDSS_MDP_REG_AD_CALC_DONE);
+			if (!calc_done)
+				usleep(MDSS_PP_AD_SLEEP);
+		} while (!calc_done && (ad->state & PP_AD_STATE_RUN));
+		if (calc_done) {
+			ad->last_str = 0xFF & readl_relaxed(ad->base +
+						MDSS_MDP_REG_AD_STR_OUT);
+			if (MDSS_AD_RUNNING_AUTO_BL(ad)) {
+				bl = 0xFFFF & readl_relaxed(ad->base +
+						MDSS_MDP_REG_AD_BL_OUT);
+				pr_debug("calc bl = %d", bl);
+				ad->last_str |= bl << 16;
+				mutex_lock(&ad->mfd->bl_lock);
+				mdss_fb_set_backlight(ad->mfd, bl);
+				mutex_unlock(&ad->mfd->bl_lock);
+			}
+			pr_debug("calc_str = %d, calc_itr %d",
+							ad->last_str & 0xFF,
+							ad->calc_itr);
+		} else {
+			ad->last_str = 0xFFFFFFFF;
+		}
+	}
+	complete(&ad->comp);
+
+	if (!ad->calc_itr) {
+		ad->state &= ~PP_AD_STATE_VSYNC;
+		ctl->remove_vsync_handler(ctl, &ad->handle);
+	}
+	mutex_unlock(&ad->lock);
+	mutex_lock(&ad->mfd->lock);
+	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, BIT(13 + ad->num));
+	mutex_unlock(&ad->mfd->lock);
+}
+
+#define PP_AD_LUT_LEN 33
+static void pp_ad_cfg_lut(char __iomem *offset, u32 *data)
+{
+	int i;
+	u32 temp;
+
+	for (i = 0; i < PP_AD_LUT_LEN - 1; i += 2) {
+		temp = data[i+1] << 16;
+		temp |= (data[i] & 0xFFFF);
+		writel_relaxed(temp, offset + (i*2));
+	}
+	writel_relaxed(data[PP_AD_LUT_LEN - 1] << 16,
+			offset + ((PP_AD_LUT_LEN - 1) * 2));
+}
+
+int mdss_mdp_ad_addr_setup(struct mdss_data_type *mdata, u32 *ad_off)
+{
+	u32 i;
+	int rc = 0;
+
+	mdata->ad_cfgs = devm_kzalloc(&mdata->pdev->dev,
+				sizeof(struct mdss_ad_info) * mdata->nad_cfgs,
+				GFP_KERNEL);
+
+	if (!mdata->ad_cfgs) {
+		pr_err("unable to setup assertive display:devm_kzalloc fail\n");
+		return -ENOMEM;
+	}
+
+	mdata->ad_calc_wq = create_singlethread_workqueue("ad_calc_wq");
+	for (i = 0; i < mdata->nad_cfgs; i++) {
+		mdata->ad_cfgs[i].base = mdata->mdp_base + ad_off[i];
+		mdata->ad_cfgs[i].num = i;
+		mdata->ad_cfgs[i].calc_itr = 0;
+		mdata->ad_cfgs[i].last_str = 0xFFFFFFFF;
+		mutex_init(&mdata->ad_cfgs[i].lock);
+		mdata->ad_cfgs[i].handle.vsync_handler = pp_ad_vsync_handler;
+		INIT_WORK(&mdata->ad_cfgs[i].calc_work, pp_ad_calc_worker);
+	}
+	return rc;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 016c973..5d9396a 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -367,6 +367,7 @@
 
 int mdss_mdp_rotator_release(u32 ndx)
 {
+	int rc = 0;
 	struct mdss_mdp_rotator_session *rot;
 	mutex_lock(&rotator_lock);
 	rot = mdss_mdp_rotator_session_get(ndx);
@@ -374,11 +375,11 @@
 		mdss_mdp_rotator_finish(rot);
 	} else {
 		pr_warn("unknown session id=%x\n", ndx);
-		return -ENOENT;
+		rc = -ENOENT;
 	}
 	mutex_unlock(&rotator_lock);
 
-	return 0;
+	return rc;
 }
 
 int mdss_mdp_rotator_release_all(void)
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 7ccf1b9..1f8244d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -194,6 +194,7 @@
 {
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
+	int rc = 0;
 
 	mutex_lock(&mdss_mdp_wb_buf_lock);
 	if (wb == NULL) {
@@ -202,7 +203,8 @@
 		mdp5_data->wb = wb;
 	} else if (mfd->index != wb->fb_ndx) {
 		pr_err("only one writeback intf supported at a time\n");
-		return -EMLINK;
+		rc = -EMLINK;
+		goto error;
 	} else {
 		pr_debug("writeback already initialized\n");
 	}
@@ -217,8 +219,9 @@
 	init_waitqueue_head(&wb->wait_q);
 
 	mdp5_data->wb = wb;
+error:
 	mutex_unlock(&mdss_mdp_wb_buf_lock);
-	return 0;
+	return rc;
 }
 
 static int mdss_mdp_wb_terminate(struct msm_fb_data_type *mfd)
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index d230100..9e8cfa7 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -55,8 +55,35 @@
 	MAX_PHYS_TARGET_NUM,
 };
 
+/**
+ * enum mdss_intf_events - Different events generated by MDP core
+ *
+ * @MDSS_EVENT_RESET:		MDP control path is being (re)initialized.
+ * @MDSS_EVENT_UNBLANK:		Sent before first frame update from MDP is
+ *				sent to panel.
+ * @MDSS_EVENT_PANEL_ON:	After first frame update from MDP.
+ * @MDSS_EVENT_BLANK:		MDP has no contents to display only blank screen
+ *				is shown in panel. Sent before panel off.
+ * @MDSS_EVENT_PANEL_OFF:	MDP has suspended frame updates, panel should be
+ *				completely shutdown after this call.
+ * @MDSS_EVENT_CLOSE:		MDP has tore down entire session.
+ * @MDSS_EVENT_SUSPEND:		Propagation of power suspend event.
+ * @MDSS_EVENT_RESUME:		Propagation of power resume event.
+ * @MDSS_EVENT_CHECK_PARAMS:	Event generated when a panel reconfiguration is
+ *				requested including when resolution changes.
+ *				The event handler receives pointer to
+ *				struct mdss_panel_info and should return one of:
+ *				 - negative if the configuration is invalid
+ *				 - 0 if there is no panel reconfig needed
+ *				 - 1 if reconfig is needed to take effect
+ * @MDSS_EVENT_CONT_SPLASH_FINISH: Special event used to handle transition of
+ *				display state from boot loader to panel driver.
+ * @MDSS_EVENT_FB_REGISTERED:	Called after fb dev driver has been registered,
+ *				panel driver gets ptr to struct fb_info which
+ *				holds fb dev information.
+ */
 enum mdss_intf_events {
-	MDSS_EVENT_RESET,
+	MDSS_EVENT_RESET = 1,
 	MDSS_EVENT_UNBLANK,
 	MDSS_EVENT_PANEL_ON,
 	MDSS_EVENT_BLANK,
@@ -214,7 +241,18 @@
 	void (*set_backlight) (struct mdss_panel_data *pdata, u32 bl_level);
 	unsigned char *mmss_cc_base;
 
-	/* function entry chain */
+	/**
+	 * event_handler() - callback handler for MDP core events
+	 * @pdata:	Pointer refering to the panel struct associated to this
+	 *		event. Can be used to retrieve panel info.
+	 * @e:		Event being generated, see enum mdss_intf_events
+	 * @arg:	Optional argument to pass some info from some events.
+	 *
+	 * Used to register handler to be used to propagate different events
+	 * happening in MDP core driver. Panel driver can listen for any of
+	 * these events to perform appropriate actions for panel initialization
+	 * and teardown.
+	 */
 	int (*event_handler) (struct mdss_panel_data *pdata, int e, void *arg);
 
 	struct mdss_panel_data *next;
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index 96e8b67..08d0693 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -169,6 +169,7 @@
 	cmd_env = vmalloc(sizeof(struct msc_cmd_envelope));
 	if (!cmd_env) {
 		pr_err("%s: out of memory!\n", __func__);
+		mutex_unlock(&msc_send_workqueue_mutex);
 		return -ENOMEM;
 	}
 
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 2b07e43..5564ceb 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -275,8 +275,8 @@
 
 	} else {
 		MIPI_OUTP(ctrl_base + 0x0220, 0x006);
-		usleep(10);
 		MIPI_OUTP(ctrl_base + 0x0470, 0x000);
+		MIPI_OUTP(ctrl_base + 0x0598, 0x000);
 		wmb();
 	}
 }
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index c219725..aa1eba5 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -229,7 +229,15 @@
 	DMX_EVENT_MARKER = 0x00000100,
 
 	/* New indexing entry is ready */
-	DMX_EVENT_NEW_INDEX_ENTRY = 0x00000200
+	DMX_EVENT_NEW_INDEX_ENTRY = 0x00000200,
+
+	/*
+	 * Section filter timer expired. This is notified
+	 * when timeout is configured to section filter
+	 * (dmx_sct_filter_params) and no sections were
+	 * received for the given time.
+	 */
+	DMX_EVENT_SECTION_TIMEOUT = 0x00000400
 };
 
 enum dmx_oob_cmd {
@@ -706,6 +714,46 @@
 	__u64 types;
 };
 
+struct dmx_set_ts_insertion {
+	/*
+	 * Unique identifier managed by the caller.
+	 * This identifier can be used later to remove the
+	 * insertion using DMX_ABORT_TS_INSERTION ioctl.
+	 */
+	__u32 identifier;
+
+	/*
+	 * Repetition time in msec, minimum allowed value is 25msec.
+	 * 0 repetition time means one-shot insertion is done.
+	 * Insertion done based on wall-clock.
+	 */
+	__u32 repetition_time;
+
+	/*
+	 * TS packets buffer to be inserted.
+	 * The buffer is inserted as-is to the recording buffer
+	 * without any modification.
+	 * It is advised to set discontinuity flag in the very
+	 * first TS packet in the buffer.
+	 */
+	const __u8 *ts_packets;
+
+	/*
+	 * Size in bytes of the TS packets buffer to be inserted.
+	 * Should be in multiples of 188 or 192 bytes
+	 * depending on recording filter output format.
+	 */
+	size_t size;
+};
+
+struct dmx_abort_ts_insertion {
+	/*
+	 * Identifier of the insertion buffer previously set
+	 * using DMX_SET_TS_INSERTION.
+	 */
+	__u32 identifier;
+};
+
 #define DMX_START                _IO('o', 41)
 #define DMX_STOP                 _IO('o', 42)
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
@@ -734,5 +782,7 @@
 #define DMX_GET_EVENTS_MASK	_IOR('o', 67, struct dmx_events_mask)
 #define DMX_PUSH_OOB_COMMAND	_IOW('o', 68, struct dmx_oob_command)
 #define DMX_SET_INDEXING_PARAMS _IOW('o', 69, struct dmx_indexing_params)
+#define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
+#define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 3a9b1b9..0d1f49f 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -77,7 +77,8 @@
 	WCD9XXX_IRQ_HPH_L_PA_STARTUP,
 	WCD9XXX_IRQ_HPH_R_PA_STARTUP,
 	WCD9XXX_IRQ_EAR_PA_STARTUP,
-	WCD9XXX_IRQ_RESERVED_0,
+	WCD9310_NUM_IRQS,
+	WCD9XXX_IRQ_RESERVED_0 = WCD9310_NUM_IRQS,
 	WCD9XXX_IRQ_RESERVED_1,
 	/* INTR_REG 3 */
 	WCD9XXX_IRQ_MAD_AUDIO,
@@ -85,12 +86,14 @@
 	WCD9XXX_IRQ_MAD_ULTRASOUND,
 	WCD9XXX_IRQ_SPEAKER_CLIPPING,
 	WCD9XXX_IRQ_MBHC_JACK_SWITCH,
+	WCD9XXX_IRQ_VBAT_MONITOR_ATTACK,
+	WCD9XXX_IRQ_VBAT_MONITOR_RELEASE,
 	WCD9XXX_NUM_IRQS,
 };
 
 enum {
-	TABLA_NUM_IRQS = WCD9XXX_NUM_IRQS,
-	SITAR_NUM_IRQS = WCD9XXX_NUM_IRQS,
+	TABLA_NUM_IRQS = WCD9310_NUM_IRQS,
+	SITAR_NUM_IRQS = WCD9310_NUM_IRQS,
 	TAIKO_NUM_IRQS = WCD9XXX_NUM_IRQS,
 	TAPAN_NUM_IRQS = WCD9XXX_NUM_IRQS,
 };
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index ca7a586..d63232a 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -72,11 +72,9 @@
 #ifdef CONFIG_CMA
 bool is_cma_pageblock(struct page *page);
 #  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
-#  define cma_wmark_pages(zone)	zone->min_cma_pages
 #else
 #  define is_cma_pageblock(page) false
 #  define is_migrate_cma(migratetype) false
-#  define cma_wmark_pages(zone) 0
 #endif
 
 #define for_each_migratetype_order(order, type) \
@@ -385,11 +383,6 @@
 	seqlock_t		span_seqlock;
 #endif
 #ifdef CONFIG_CMA
-	/*
-	 * CMA needs to increase watermark levels during the allocation
-	 * process to make sure that the system is not starved.
-	 */
-	unsigned long		min_cma_pages;
 	bool			cma_alloc;
 #endif
 	struct free_area	free_area[MAX_ORDER];
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index f9e483c..61e9cb1 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -613,6 +613,7 @@
 	uint16_t calib[4];
 	uint8_t strength_limit;
 	uint8_t t_filter_recursion;
+	uint16_t stab_itr;
 };
 
 /* ops uses standard MDP_PP_* flags */
@@ -631,6 +632,7 @@
 		uint32_t amb_light;
 		uint32_t strength;
 	} in;
+	uint32_t output;
 };
 
 enum {
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 5e73bd9..4ae3b79 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -222,6 +222,7 @@
 	bool enable_lpm_on_dev_suspend;
 	bool core_clk_always_on_workaround;
 	bool delay_lpm_on_disconnect;
+	bool delay_lpm_hndshk_on_disconnect;
 	bool dp_manual_pullup;
 	bool enable_sec_phy;
 	struct msm_bus_scale_pdata *bus_scale_table;
@@ -422,6 +423,7 @@
 	u32 standalone_latency;
 	bool pool_64_bit_align;
 	bool enable_hbm;
+	bool disable_park_mode;
 };
 
 struct msm_usb_host_platform_data {
@@ -461,10 +463,13 @@
 	int (*notify)(void *, int, void (*)(int online));
 	void *ctxt;
 };
-
+#ifdef CONFIG_USB_BAM
+bool msm_bam_lpm_ok(void);
+#else
+static inline bool msm_bam_lpm_ok(void) { return true; }
+#endif
 #ifdef CONFIG_USB_CI13XXX_MSM
 void msm_hw_bam_disable(bool bam_disable);
-
 #else
 static inline void msm_hw_bam_disable(bool bam_disable)
 {
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index b71aa30..992649f 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -108,10 +108,10 @@
 	SUB_MODULE_EEPROM,
 	SUB_MODULE_LED_FLASH,
 	SUB_MODULE_STROBE_FLASH,
-	SUB_MODULE_CSIPHY,
-	SUB_MODULE_CSIPHY_3D,
 	SUB_MODULE_CSID,
 	SUB_MODULE_CSID_3D,
+	SUB_MODULE_CSIPHY,
+	SUB_MODULE_CSIPHY_3D,
 	SUB_MODULE_MAX,
 };
 
diff --git a/include/media/msm_gemini.h b/include/media/msm_gemini.h
index 0167335..2209758 100644
--- a/include/media/msm_gemini.h
+++ b/include/media/msm_gemini.h
@@ -51,10 +51,19 @@
 #define MSM_GMN_IOCTL_TEST_DUMP_REGION \
 	_IOW(MSM_GMN_IOCTL_MAGIC, 15, unsigned long)
 
+#define MSM_GMN_IOCTL_SET_MODE \
+	_IOW(MSM_GMN_IOCTL_MAGIC, 16, enum msm_gmn_out_mode)
+
 #define MSM_GEMINI_MODE_REALTIME_ENCODE 0
 #define MSM_GEMINI_MODE_OFFLINE_ENCODE 1
 #define MSM_GEMINI_MODE_REALTIME_ROTATION 2
 #define MSM_GEMINI_MODE_OFFLINE_ROTATION 3
+
+enum msm_gmn_out_mode {
+	MSM_GMN_OUTMODE_FRAGMENTED,
+	MSM_GMN_OUTMODE_SINGLE
+};
+
 struct msm_gemini_ctrl_cmd {
 	uint32_t type;
 	uint32_t len;
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index bf6b23b..3775ddd 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -64,6 +64,7 @@
 	EVERY_8FRAME,
 	EVERY_16FRAME,
 	EVERY_32FRAME,
+	SKIP_ALL,
 	MAX_SKIP,
 };
 
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 42c8823..35c57c0 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1,6 +1,6 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
-   Copyright (c) 2000-2001, 2010-2012 The Linux Foundation. All rights reserved.
+   Copyright (c) 2000-2001, 2010-2013 The Linux Foundation. All rights reserved.
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -1145,6 +1145,11 @@
 	__le16   opcode;
 } __packed;
 
+#define HCI_EV_HARDWARE_ERROR		0x10
+struct hci_ev_hardware_error {
+	__u8   hw_err_code;
+} __packed;
+
 #define HCI_EV_ROLE_CHANGE		0x12
 struct hci_ev_role_change {
 	__u8     status;
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index fa4dedc..f064837 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -634,8 +634,6 @@
  *	when a new port is added here. */
 #define PRIMARY_I2S_RX 0		/* index = 0 */
 #define PRIMARY_I2S_TX 1		/* index = 1 */
-#define PCM_RX 2			/* index = 2 */
-#define PCM_TX 3			/* index = 3 */
 #define SECONDARY_I2S_RX 4		/* index = 4 */
 #define SECONDARY_I2S_TX 5		/* index = 5 */
 #define MI2S_RX 6			/* index = 6 */
@@ -784,26 +782,6 @@
 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX      0x4008
 /* SLIMbus Tx port on channel 4. */
 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX      0x4009
-/* SLIMbus Rx port on channel 0. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX      0x4000
-/* SLIMbus Tx port on channel 0. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX      0x4001
-/* SLIMbus Rx port on channel 1. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX      0x4002
-/* SLIMbus Tx port on channel 1. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX      0x4003
-/* SLIMbus Rx port on channel 2. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX      0x4004
-/* SLIMbus Tx port on channel 2. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX      0x4005
-/* SLIMbus Rx port on channel 3. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_RX      0x4006
-/* SLIMbus Tx port on channel 3. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_TX      0x4007
-/* SLIMbus Rx port on channel 4. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX      0x4008
-/* SLIMbus Tx port on channel 4. */
-#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX      0x4009
 /* SLIMbus Rx port on channel 5. */
 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX      0x400a
 /* SLIMbus Tx port on channel 5. */
@@ -6538,6 +6516,11 @@
 #define AANC_HW_BLOCK_VERSION_1				(1)
 #define AANC_HW_BLOCK_VERSION_2				(2)
 
+/*Clip bank selection*/
+#define AFE_API_VERSION_CLIP_BANK_SEL_CFG 0x1
+#define AFE_CLIP_MAX_BANKS		4
+#define AFE_PARAM_ID_CLIP_BANK_SEL_CFG 0x00010242
+
 struct afe_param_aanc_port_cfg {
 	/* Minor version used for tracking the version of the module's
 	* source port configuration.
@@ -6572,6 +6555,18 @@
 	uint32_t aanc_hw_version;
 } __packed;
 
+struct afe_param_id_clip_bank_sel {
+	/* Minor version used for tracking the version of the module's
+	* hw version
+	*/
+	uint32_t minor_version;
+
+	/* Number of banks to be read */
+	uint32_t num_banks;
+
+	uint32_t bank_map[AFE_CLIP_MAX_BANKS];
+} __packed;
+
 /* ERROR CODES */
 /* Success. The operation completed with no errors. */
 #define ADSP_EOK          0x00000000
@@ -6804,6 +6799,8 @@
 	AFE_SLIMBUS_SLAVE_CONFIG,
 	AFE_CDC_REGISTERS_CONFIG,
 	AFE_AANC_VERSION,
+	AFE_CDC_CLIP_REGISTERS_CONFIG,
+	AFE_CLIP_BANK_SEL,
 	AFE_MAX_CONFIG_TYPES,
 };
 
@@ -6925,4 +6922,10 @@
 /* Dolby DAP topology */
 #define DOLBY_ADM_COPP_TOPOLOGY_ID	0x0001033B
 
+struct afe_svc_cmd_set_clip_bank_selection {
+	struct apr_hdr hdr;
+	struct afe_svc_cmd_set_param param;
+	struct afe_port_param_data_v2 pdata;
+	struct afe_param_id_clip_bank_sel bank_sel;
+} __packed;
 #endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 40b0e1e..81636a3 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1453,6 +1453,23 @@
 	u32                read_format;
 } __attribute__((packed));
 
+#define ASM_STREAM_CMD_OPEN_LOOPBACK	0x00010D6E
+struct asm_stream_cmd_open_loopback {
+	struct apr_hdr         hdr;
+	u32                    mode_flags;
+/* Mode flags.
+ * Bit 0-31: reserved; client should set these bits to 0
+ */
+	u16                    src_endpointype;
+	/* Endpoint type. 0 = Tx Matrix */
+	u16                    sink_endpointype;
+	/* Endpoint type. 0 = Rx Matrix */
+	u32                    postprocopo_id;
+/* Postprocessor topology ID. Specifies the topology of
+ * postprocessing algorithms.
+ */
+} __packed;
+
 #define ADM_CMD_CONNECT_AFE_PORT 0x00010320
 #define ADM_CMD_DISCONNECT_AFE_PORT 0x00010321
 
@@ -1909,5 +1926,4 @@
 
 int srs_ss3d_open(int port_id, int srs_tech_id, void *srs_params);
 /* SRS Studio Sound 3D end */
-
 #endif /*_APR_AUDIO_H_*/
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 2a740f4..1389b2a 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -41,8 +41,8 @@
 enum {
 	IDX_PRIMARY_I2S_RX = 0,
 	IDX_PRIMARY_I2S_TX = 1,
-	IDX_PCM_RX = 2,
-	IDX_PCM_TX = 3,
+	IDX_AFE_PORT_ID_PRIMARY_PCM_RX = 2,
+	IDX_AFE_PORT_ID_PRIMARY_PCM_TX = 3,
 	IDX_SECONDARY_I2S_RX = 4,
 	IDX_SECONDARY_I2S_TX = 5,
 	IDX_MI2S_RX = 6,
@@ -166,7 +166,7 @@
 int afe_port_start(u16 port_id, union afe_port_config *afe_config,
 	u32 rate);
 int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
-	int l_ch, int r_ch);
+	int l_ch, int r_ch, u32 enable);
 int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib);
 int afe_port_stop_nowait(int port_id);
 int afe_apply_gain(u16 port_id, u16 gain);
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 406407d..41f875b 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -207,6 +207,8 @@
 			uint32_t rd_format,
 			uint32_t wr_format);
 
+int q6asm_open_loopack(struct audio_client *ac);
+
 int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
 				uint32_t lsw_ts, uint32_t flags);
 int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h
index a1da44f..909e1b9 100644
--- a/include/trace/events/kmem.h
+++ b/include/trace/events/kmem.h
@@ -495,6 +495,110 @@
 	TP_ARGS(mode)
 );
 
+DECLARE_EVENT_CLASS(ion_alloc_pages,
+
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order),
+
+	TP_STRUCT__entry(
+		__field(gfp_t, gfp_flags)
+		__field(unsigned int, order)
+		),
+
+	TP_fast_assign(
+		__entry->gfp_flags = gfp_flags;
+		__entry->order = order;
+		),
+
+	TP_printk("gfp_flags=%s order=%d",
+		show_gfp_flags(__entry->gfp_flags),
+		__entry->order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_iommu_start,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_iommu_end,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_iommu_fail,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_sys_start,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_sys_end,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_sys_fail,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+
+	);
+
+DECLARE_EVENT_CLASS(smmu_map,
+
+	TP_PROTO(unsigned int va,
+		phys_addr_t pa,
+		unsigned int chunk_size,
+		size_t len),
+
+	TP_ARGS(va, pa, chunk_size, len),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, va)
+		__field(phys_addr_t, pa)
+		__field(unsigned int, chunk_size)
+		__field(size_t, len)
+		),
+
+	TP_fast_assign(
+		__entry->va = va;
+		__entry->pa = pa;
+		__entry->chunk_size = chunk_size;
+		__entry->len = len;
+		),
+
+	TP_printk("v_addr=%p p_addr=%pa chunk_size=0x%x len=%zu",
+		(void *)__entry->va,
+		&__entry->pa,
+		__entry->chunk_size,
+		__entry->len)
+	);
+
+DEFINE_EVENT(smmu_map, iommu_map_range,
+	TP_PROTO(unsigned int va,
+		phys_addr_t pa,
+		unsigned int chunk_size,
+		size_t len),
+
+	TP_ARGS(va, pa, chunk_size, len)
+	);
+
 #endif /* _TRACE_KMEM_H */
 
 /* This part must be outside protection */
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index e6a2e35..edd656c 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -224,13 +224,10 @@
 		raw_spin_unlock(&base->cpu_base->lock);
 		raw_spin_lock(&new_base->cpu_base->lock);
 
-		this_cpu = smp_processor_id();
-
-		if (cpu != this_cpu && (hrtimer_check_target(timer, new_base)
-			|| !cpu_online(cpu))) {
+		if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) {
+			cpu = this_cpu;
 			raw_spin_unlock(&new_base->cpu_base->lock);
 			raw_spin_lock(&base->cpu_base->lock);
-			cpu = smp_processor_id();
 			timer->base = base;
 			goto again;
 		}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 69b9521..798c750 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -785,6 +785,10 @@
 	set_pageblock_migratetype(page, MIGRATE_CMA);
 	__free_pages(page, pageblock_order);
 	totalram_pages += pageblock_nr_pages;
+#ifdef CONFIG_HIGHMEM
+	if (PageHighMem(page))
+		totalhigh_pages += pageblock_nr_pages;
+#endif
 }
 #endif
 
@@ -5199,10 +5203,6 @@
 		zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) + (tmp >> 2);
 		zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1);
 
-		zone->watermark[WMARK_MIN] += cma_wmark_pages(zone);
-		zone->watermark[WMARK_LOW] += cma_wmark_pages(zone);
-		zone->watermark[WMARK_HIGH] += cma_wmark_pages(zone);
-
 		setup_zone_migrate_reserve(zone);
 		spin_unlock_irqrestore(&zone->lock, flags);
 	}
@@ -5820,54 +5820,6 @@
 	return ret > 0 ? 0 : ret;
 }
 
-/*
- * Update zone's cma pages counter used for watermark level calculation.
- */
-static inline void __update_cma_watermarks(struct zone *zone, int count)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&zone->lock, flags);
-	zone->min_cma_pages += count;
-	spin_unlock_irqrestore(&zone->lock, flags);
-	setup_per_zone_wmarks();
-}
-
-/*
- * Trigger memory pressure bump to reclaim some pages in order to be able to
- * allocate 'count' pages in single page units. Does similar work as
- *__alloc_pages_slowpath() function.
- */
-static int __reclaim_pages(struct zone *zone, gfp_t gfp_mask, int count)
-{
-	enum zone_type high_zoneidx = gfp_zone(gfp_mask);
-	struct zonelist *zonelist = node_zonelist(0, gfp_mask);
-	int did_some_progress = 0;
-	int order = 1;
-
-	/*
-	 * Increase level of watermarks to force kswapd do his job
-	 * to stabilise at new watermark level.
-	 */
-	__update_cma_watermarks(zone, count);
-
-	/* Obey watermarks as if the page was being allocated */
-	while (!zone_watermark_ok(zone, 0, low_wmark_pages(zone), 0, 0)) {
-		wake_all_kswapd(order, zonelist, high_zoneidx, zone_idx(zone));
-
-		did_some_progress = __perform_reclaim(gfp_mask, order, zonelist,
-						      NULL);
-		if (!did_some_progress) {
-			/* Exhausted what can be done so it's blamo time */
-			out_of_memory(zonelist, gfp_mask, order, NULL, false);
-		}
-	}
-
-	/* Restore original watermark levels. */
-	__update_cma_watermarks(zone, -count);
-
-	return count;
-}
-
 /**
  * alloc_contig_range() -- tries to allocate given range of pages
  * @start:	start PFN to allocate
@@ -5968,11 +5920,6 @@
 		goto done;
 	}
 
-	/*
-	 * Reclaim enough pages to make sure that contiguous allocation
-	 * will not starve the system.
-	 */
-	__reclaim_pages(zone, GFP_HIGHUSER_MOVABLE, end-start);
 
 	/* Grab isolated pages from freelists. */
 	outer_end = isolate_freepages_range(outer_start, end);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d243646..2dba071 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2426,6 +2426,21 @@
 	}
 }
 
+static inline void hci_hardware_error_evt(struct hci_dev *hdev,
+					struct sk_buff *skb)
+{
+	struct hci_ev_hardware_error *ev = (void *) skb->data;
+
+	BT_ERR("hdev=%p, hw_err_code = %u", hdev, ev->hw_err_code);
+
+	if (hdev && hdev->dev_type == HCI_BREDR) {
+		hci_dev_lock_bh(hdev);
+		mgmt_powered(hdev->id, 1);
+		hci_dev_unlock_bh(hdev);
+	}
+
+}
+
 static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_role_change *ev = (void *) skb->data;
@@ -3555,6 +3570,10 @@
 		hci_cmd_status_evt(hdev, skb);
 		break;
 
+	case HCI_EV_HARDWARE_ERROR:
+		hci_hardware_error_evt(hdev, skb);
+		break;
+
 	case HCI_EV_ROLE_CHANGE:
 		hci_role_change_evt(hdev, skb);
 		break;
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index c8647fb1..e1a904f 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -34,6 +34,7 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
+#include <mach/qdsp6v2/apr.h>
 #include "msm8x10-wcd.h"
 #include "wcd9xxx-resmgr.h"
 #include "msm8x10_wcd_registers.h"
@@ -52,7 +53,7 @@
 
 #define MAX_MSM8X10_WCD_DEVICE	4
 #define CODEC_DT_MAX_PROP_SIZE	40
-#define MSM8X10_WCD_I2C_GSBI_SLAVE_ID "1-000d"
+#define MSM8X10_WCD_I2C_GSBI_SLAVE_ID "5-000d"
 
 enum {
 	MSM8X10_WCD_I2C_TOP_LEVEL = 0,
@@ -82,6 +83,12 @@
 static struct snd_soc_dai_driver msm8x10_wcd_i2s_dai[];
 static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
 
+#define MSM8X10_WCD_ACQUIRE_LOCK(x) do { \
+	mutex_lock_nested(&x, SINGLE_DEPTH_NESTING); \
+} while (0)
+#define MSM8X10_WCD_RELEASE_LOCK(x) do { mutex_unlock(&x); } while (0)
+
+
 /* Codec supports 2 IIR filters */
 enum {
 	IIR1 = 0,
@@ -99,6 +106,12 @@
 	BAND_MAX,
 };
 
+enum msm8x10_wcd_bandgap_type {
+	MSM8X10_WCD_BANDGAP_OFF = 0,
+	MSM8X10_WCD_BANDGAP_AUDIO_MODE,
+	MSM8X10_WCD_BANDGAP_MBHC_MODE,
+};
+
 struct hpf_work {
 	struct msm8x10_wcd_priv *msm8x10_wcd;
 	u32 decimator;
@@ -113,11 +126,14 @@
 	u32 adc_count;
 	u32 rx_bias_count;
 	s32 dmic_1_2_clk_cnt;
-
+	enum msm8x10_wcd_bandgap_type bandgap_type;
+	bool mclk_enabled;
+	bool clock_active;
+	bool config_mode_active;
+	bool mbhc_polling_active;
+	struct mutex codec_resource_lock;
 	/* resmgr module */
 	struct wcd9xxx_resmgr resmgr;
-	/* mbhc module */
-	struct wcd9xxx_mbhc mbhc;
 };
 
 static unsigned short rx_digital_gain_reg[] = {
@@ -139,8 +155,8 @@
 };
 
 static char *msm8x10_wcd_supplies[] = {
-	"cdc-vdd-mic-bias", "cdc-vdda-h", "cdc-vdd-1p2", "cdc-vdd-px",
-	"cdc-vdda-cp",
+	"cdc-vdda-cp", "cdc-vdda-h", "cdc-vdd-px", "cdc-vdd-1p2v",
+	"cdc-vdd-mic-bias",
 };
 
 static int msm8x10_wcd_dt_parse_vreg_info(struct device *dev,
@@ -158,7 +174,6 @@
 {
 	int rtn = 0;
 	int value = ((reg & 0x0f00) >> 8) & 0x000f;
-	pr_debug("%s: reg(0x%x) value(%d)\n", __func__, reg, value);
 	switch (value) {
 	case 0:
 	case 1:
@@ -171,7 +186,7 @@
 	return rtn;
 }
 
-static int msm8x10_wcd_abh_write_device(u16 reg, unsigned int *value, u32 bytes)
+static int msm8x10_wcd_abh_write_device(u16 reg, u8 *value, u32 bytes)
 {
 	u32 temp = ((u32)(*value)) & 0x000000FF;
 	u32 offset = (((u32)(reg)) ^ 0x00000400) & 0x00000FFF;
@@ -179,11 +194,13 @@
 	return 0;
 }
 
-static int msm8x10_wcd_abh_read_device(u16 reg, u32 bytes, unsigned int *value)
+static int msm8x10_wcd_abh_read_device(u16 reg, u32 bytes, u8 *value)
 {
+	u32 temp;
 	u32 offset = (((u32)(reg)) ^ 0x00000400) & 0x00000FFF;
-	*value = ioread32(ioremap(MSM8X10_DINO_CODEC_BASE_ADDR +
+	temp = ioread32(ioremap(MSM8X10_DINO_CODEC_BASE_ADDR +
 				      offset, 4));
+	*value = (u8)temp;
 	return 0;
 }
 
@@ -274,7 +291,7 @@
 			}
 		}
 	}
-	pr_debug("%s: Reg 0x%x = 0x%x\n", __func__, reg, *dest);
+	pr_debug("%s: reg 0x%x = 0x%x\n", __func__, reg, *dest);
 	return 0;
 }
 
@@ -292,20 +309,22 @@
 				u16 reg, unsigned int *val)
 {
 	int ret = -EINVAL;
+	u8 temp;
 
 	/* check if use I2C interface for Helicon or AHB for Dino */
 	mutex_lock(&msm8x10_wcd->io_lock);
 	if (MSM8X10_WCD_IS_HELICON_REG(reg))
-		ret = msm8x10_wcd_i2c_read(reg, 1, val);
+		ret = msm8x10_wcd_i2c_read(reg, 1, &temp);
 	else if (MSM8X10_WCD_IS_DINO_REG(reg))
-		ret = msm8x10_wcd_abh_read_device(reg, 1, val);
+		ret = msm8x10_wcd_abh_read_device(reg, 1, &temp);
 	mutex_unlock(&msm8x10_wcd->io_lock);
+	*val = temp;
 	return ret;
 }
 
 
 static int msm8x10_wcd_reg_write(struct msm8x10_wcd *msm8x10_wcd, u16  reg,
-				 unsigned int val)
+				 u8 val)
 {
 	int ret = -EINVAL;
 
@@ -393,7 +412,7 @@
 				reg, ret);
 	}
 
-	return msm8x10_wcd_reg_write(codec->control_data, reg, value);
+	return msm8x10_wcd_reg_write(codec->control_data, reg, (u8)value);
 }
 
 static unsigned int msm8x10_wcd_read(struct snd_soc_codec *codec,
@@ -438,10 +457,14 @@
 	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
 
 	if (!regnode) {
-		dev_err(dev, "Looking up %s property in node %s failed",
+		dev_err(dev, "Looking up %s property in node %s failed\n",
 			prop_name, dev->of_node->full_name);
 		return -ENODEV;
 	}
+
+	dev_dbg(dev, "Looking up %s property in node %s\n",
+		prop_name, dev->of_node->full_name);
+
 	vreg->name = vreg_name;
 
 	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
@@ -481,17 +504,7 @@
 	u32 prop_val;
 
 	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-		 "qcom,cdc-micbias-ldoh-v");
-	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
-	micbias->ldoh_v = (u8)prop_val;
-
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-		 "qcom,cdc-micbias-cfilt1-mv");
+		 "qcom,cdc-micbias-cfilt-mv");
 	ret = of_property_read_u32(dev->of_node, prop_name,
 				   &micbias->cfilt1_mv);
 	if (ret) {
@@ -501,7 +514,7 @@
 	}
 
 	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-		 "qcom,cdc-micbias1-cfilt-sel");
+		 "qcom,cdc-micbias-cfilt-sel");
 	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
 	if (ret) {
 		dev_err(dev, "Looking up %s property in node %s failed",
@@ -559,23 +572,14 @@
 		if (ret)
 			goto err;
 	}
-
 	ret = msm8x10_wcd_dt_parse_micbias_info(dev, &pdata->micbias);
 	if (ret)
 		goto err;
-
-	pdata->reset_gpio = of_get_named_gpio(dev->of_node,
-				"qcom,cdc-reset-gpio", 0);
-	if (pdata->reset_gpio < 0) {
-		dev_err(dev, "Looking up %s property in node %s failed %d\n",
-			"qcom, cdc-reset-gpio", dev->of_node->full_name,
-			pdata->reset_gpio);
-		goto err;
-	}
-	dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
 	return pdata;
 err:
 	devm_kfree(dev, pdata);
+	dev_err(dev, "%s: Failed to populate DT data ret = %d\n",
+		__func__, ret);
 	return NULL;
 }
 
@@ -611,6 +615,9 @@
 				    MSM8X10_WCD_A_CDC_CLK_OTHR_CTL, 0x01,
 				    0x00);
 		snd_soc_update_bits(codec,
+				    MSM8X10_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL,
+				    0x01, 0x01);
+		snd_soc_update_bits(codec,
 				    MSM8X10_WCD_A_CP_STATIC, 0x08, 0x00);
 		break;
 	}
@@ -846,7 +853,7 @@
 	SOC_ENUM_EXT("EAR PA Gain", msm8x10_wcd_ear_pa_gain_enum[0],
 		msm8x10_wcd_pa_gain_get, msm8x10_wcd_pa_gain_put),
 
-	SOC_SINGLE_TLV("LINEOUT1 Volume", MSM8X10_WCD_A_RX_LINE_1_GAIN,
+	SOC_SINGLE_TLV("LINEOUT Volume", MSM8X10_WCD_A_RX_LINE_1_GAIN,
 		       0, 12, 1, line_gain),
 
 	SOC_SINGLE_TLV("HPHL Volume", MSM8X10_WCD_A_RX_HPH_L_GAIN,
@@ -1102,9 +1109,6 @@
 	switch (decimator) {
 	case 1:
 	case 2:
-		if (dec_mux == 1)
-			adc_dmic_sel = 0x1;
-		else
 			adc_dmic_sel = 0x0;
 		break;
 	default:
@@ -1148,68 +1152,6 @@
 	SOC_DAPM_SINGLE("Switch", MSM8X10_WCD_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
 };
 
-/* virtual port entries */
-static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-
-	ucontrol->value.integer.value[0] = widget->value;
-	return 0;
-}
-
-static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	return 0;
-}
-
-static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
-
-	ucontrol->value.enumerated.item[0] = widget->value;
-	return 0;
-}
-
-static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	return 0;
-}
-
-
-static const char *const slim_rx_mux_text[] = {
-	"ZERO", "AIF1_PB"
-};
-
-static const struct soc_enum slim_rx_mux_enum =
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
-
-static const struct snd_kcontrol_new slim_rx_mux[MSM8X10_WCD_RX_MAX] = {
-	SOC_DAPM_ENUM_EXT("I2S RX1 Mux", slim_rx_mux_enum,
-			  slim_rx_mux_get, slim_rx_mux_put),
-	SOC_DAPM_ENUM_EXT("I2S RX2 Mux", slim_rx_mux_enum,
-			  slim_rx_mux_get, slim_rx_mux_put),
-	SOC_DAPM_ENUM_EXT("I2S RX3 Mux", slim_rx_mux_enum,
-			  slim_rx_mux_get, slim_rx_mux_put),
-};
-
-static const struct snd_kcontrol_new aif_cap_mixer[] = {
-	SOC_SINGLE_EXT("I2S TX1", SND_SOC_NOPM, MSM8X10_WCD_TX1, 1, 0,
-			slim_tx_mixer_get, slim_tx_mixer_put),
-	SOC_SINGLE_EXT("I2S TX2", SND_SOC_NOPM, MSM8X10_WCD_TX2, 1, 0,
-			slim_tx_mixer_get, slim_tx_mixer_put),
-	SOC_SINGLE_EXT("I2S TX3", SND_SOC_NOPM, MSM8X10_WCD_TX3, 1, 0,
-			slim_tx_mixer_get, slim_tx_mixer_put),
-	SOC_SINGLE_EXT("I2S TX4", SND_SOC_NOPM, MSM8X10_WCD_TX4, 1, 0,
-			slim_tx_mixer_get, slim_tx_mixer_put),
-};
-
-
 static void msm8x10_wcd_codec_enable_adc_block(struct snd_soc_codec *codec,
 					 int enable)
 {
@@ -1243,7 +1185,7 @@
 
 	if (w->reg == MSM8X10_WCD_A_TX_1_EN)
 		init_bit_shift = 7;
-	else if (adc_reg == MSM8X10_WCD_A_TX_2_EN)
+	else if (w->reg == MSM8X10_WCD_A_TX_2_EN)
 		init_bit_shift = 6;
 	else {
 		dev_err(codec->dev, "%s: Error, invalid adc register\n",
@@ -1365,54 +1307,36 @@
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
 	u16 micb_int_reg;
-	u8 cfilt_sel_val = 0;
 	char *internal1_text = "Internal1";
 	char *internal2_text = "Internal2";
 	char *internal3_text = "Internal3";
-	enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
 
 	dev_dbg(codec->dev, "%s %d\n", __func__, event);
 	switch (w->reg) {
 	case MSM8X10_WCD_A_MICB_1_CTL:
 		micb_int_reg = MSM8X10_WCD_A_MICB_1_INT_RBIAS;
-		cfilt_sel_val =
-			msm8x10_wcd->resmgr.pdata->micbias.bias1_cfilt_sel;
-		e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
-		e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
-		e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
 		break;
 	default:
 		dev_err(codec->dev,
-			"%s: Error, invalid micbias register\n", __func__);
+			"%s: Error, invalid micbias register 0x%x\n",
+			__func__, w->reg);
 		return -EINVAL;
 	}
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		/* Let MBHC module know so micbias switch to be off */
-		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_pre_on);
-
-		/* Get cfilt */
-		wcd9xxx_resmgr_cfilt_get(&msm8x10_wcd->resmgr, cfilt_sel_val);
-
 		if (strnstr(w->name, internal1_text, 30))
-			snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
+			snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x80);
 		else if (strnstr(w->name, internal2_text, 30))
-			snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
+			snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x10);
 		else if (strnstr(w->name, internal3_text, 30))
-			snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
+			snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x2);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		usleep_range(20000, 20100);
-		/* Let MBHC module know so micbias is on */
-		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_on);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		/* Let MBHC module know so micbias switch to be off */
-		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);
-
 		if (strnstr(w->name, internal1_text, 30))
 			snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
 		else if (strnstr(w->name, internal2_text, 30))
@@ -1420,14 +1344,36 @@
 		else if (strnstr(w->name, internal3_text, 30))
 			snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
 
-		/* Put cfilt */
-		wcd9xxx_resmgr_cfilt_put(&msm8x10_wcd->resmgr, cfilt_sel_val);
 		break;
 	}
-
 	return 0;
 }
 
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work;
+	struct hpf_work *hpf_work;
+	struct msm8x10_wcd_priv *msm8x10_wcd;
+	struct snd_soc_codec *codec;
+	u16 tx_mux_ctl_reg;
+	u8 hpf_cut_of_freq;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	msm8x10_wcd = hpf_work->msm8x10_wcd;
+	codec = hpf_work->msm8x10_wcd->codec;
+	hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+	tx_mux_ctl_reg = MSM8X10_WCD_A_CDC_TX1_MUX_CTL +
+			(hpf_work->decimator - 1) * 32;
+
+	dev_info(codec->dev, "%s(): decimator %u hpf_cut_of_freq 0x%x\n",
+		 __func__, hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+
+	snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
+}
+
+
 #define  TX_MUX_CTL_CUT_OFF_FREQ_MASK	0x30
 #define  CF_MIN_3DB_4HZ			0x0
 #define  CF_MIN_3DB_75HZ		0x1
@@ -1582,6 +1528,7 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 	struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+	msm8x10_wcd->resmgr.codec = codec;
 
 	dev_dbg(codec->dev, "%s %d\n", __func__, event);
 
@@ -1697,21 +1644,12 @@
 
 	{"I2S TX1", NULL, "TX_I2S_CLK"},
 	{"I2S TX2", NULL, "TX_I2S_CLK"},
-	{"I2S TX3", NULL, "TX_I2S_CLK"},
-	{"I2S TX4", NULL, "TX_I2S_CLK"},
 
-	{"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
+	{"DEC1 MUX", NULL, "TX CLK"},
+	{"DEC2 MUX", NULL, "TX CLK"},
 
-	{"AIF1_CAP Mixer", "I2S TX1", "I2S TX1 MUX"},
-	{"AIF1_CAP Mixer", "I2S TX2", "I2S TX2 MUX"},
-	{"AIF1_CAP Mixer", "I2S TX3", "I2S TX3 MUX"},
-	{"AIF1_CAP Mixer", "I2S TX4", "I2S TX4 MUX"},
-
-	{"I2S TX1 MUX", NULL, "DEC1 MUX"},
-	{"I2S TX2 MUX", NULL, "DEC2 MUX"},
-	{"I2S TX3 MUX", NULL, "RX1 MIX1"},
-	{"I2S TX4 MUX", "RMIX2", "RX1 MIX2"},
-	{"I2S TX4 MUX", "RMIX3", "RX1 MIX3"},
+	{"I2S TX1", NULL, "DEC1 MUX"},
+	{"I2S TX2", NULL, "DEC2 MUX"},
 
 	/* Earpiece (RX MIX1) */
 	{"EAR", NULL, "EAR PA"},
@@ -1725,33 +1663,32 @@
 	{"HPHL", NULL, "HPHL DAC"},
 
 	{"HPHR", NULL, "HPHR DAC"},
-	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
 
 	{"HPHL DAC", NULL, "CP"},
 
 	{"HPHR DAC", NULL, "CP"},
+	{"SPK DAC", NULL, "CP"},
 
 	{"DAC1", "Switch", "RX1 CHAIN"},
 	{"HPHL DAC", "Switch", "RX1 CHAIN"},
 	{"HPHR DAC", NULL, "RX2 CHAIN"},
 
-	{"LINEOUT1", NULL, "LINEOUT1 PA"},
+	{"LINEOUT", NULL, "LINEOUT PA"},
 	{"SPK_OUT", NULL, "SPK PA"},
 
-	{"LINEOUT1 PA", NULL, "CP"},
-	{"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
+	{"LINEOUT PA", NULL, "CP"},
+	{"LINEOUT PA", NULL, "LINEOUT DAC"},
 
-	{"LINEOUT1 DAC", "RX2 INPUT", "RX2 MIX1"},
-	{"LINEOUT1 DAC", "RX3 INPUT", "RX3 MIX1"},
-
+	{"CP", NULL, "RX_BIAS"},
 	{"SPK PA", NULL, "SPK DAC"},
-	{"SPK DAC", NULL, "RX7 MIX2"},
+	{"SPK DAC", NULL, "RX3 CHAIN"},
 
+	{"RX1 CHAIN", NULL, "RX1 CLK"},
+	{"RX2 CHAIN", NULL, "RX2 CLK"},
+	{"RX3 CHAIN", NULL, "RX3 CLK"},
 	{"RX1 CHAIN", NULL, "RX1 MIX2"},
 	{"RX2 CHAIN", NULL, "RX2 MIX2"},
-
-	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
-	{"SPK DAC", NULL, "RX_BIAS"},
+	{"RX3 CHAIN", NULL, "RX3 MIX1"},
 
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
@@ -1761,19 +1698,7 @@
 	{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
 	{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
 	{"RX1 MIX2", NULL, "RX1 MIX1"},
-	{"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
-	{"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
 	{"RX2 MIX2", NULL, "RX2 MIX1"},
-	{"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
-	{"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
-
-	{"I2S RX1 MUX", "AIF1_PB", "AIF1 PB"},
-	{"I2S RX2 MUX", "AIF1_PB", "AIF1 PB"},
-	{"I2S RX3 MUX", "AIF1_PB", "AIF1 PB"},
-
-	{"I2S RX1", NULL, "I2S RX1 MUX"},
-	{"I2S RX2", NULL, "I2S RX2 MUX"},
-	{"I2S RX3", NULL, "I2S RX3 MUX"},
 
 	{"RX1 MIX1 INP1", "RX1", "I2S RX1"},
 	{"RX1 MIX1 INP1", "RX2", "I2S RX2"},
@@ -1825,41 +1750,109 @@
 	{"IIR1", NULL, "IIR1 INP1 MUX"},
 	{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
 	{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
-
-	/* There is no LDO_H in Helicon */
-	{"MIC BIAS1 Internal1", NULL, "LDO_H"},
-	{"MIC BIAS1 Internal2", NULL, "LDO_H"},
-	{"MIC BIAS1 External", NULL, "LDO_H"},
+	{"MIC BIAS Internal2", NULL, "INT_LDO_H"},
+	{"MIC BIAS External", NULL, "INT_LDO_H"},
 };
 
 static int msm8x10_wcd_startup(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
-	struct msm8x10_wcd *msm8x10_wcd_core =
-		dev_get_drvdata(dai->codec->dev);
 	dev_dbg(dai->codec->dev, "%s(): substream = %s  stream = %d\n",
 		__func__,
 		substream->name, substream->stream);
-	if ((msm8x10_wcd_core != NULL) &&
-	    (msm8x10_wcd_core->dev != NULL))
-		pm_runtime_get_sync(msm8x10_wcd_core->dev);
-
 	return 0;
 }
 
 static void msm8x10_wcd_shutdown(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
-	struct msm8x10_wcd *msm8x10_wcd_core =
-		dev_get_drvdata(dai->codec->dev);
 	dev_dbg(dai->codec->dev,
 		"%s(): substream = %s  stream = %d\n" , __func__,
 		substream->name, substream->stream);
-	if ((msm8x10_wcd_core != NULL) &&
-	    (msm8x10_wcd_core->dev != NULL)) {
-		pm_runtime_mark_last_busy(msm8x10_wcd_core->dev);
-		pm_runtime_put(msm8x10_wcd_core->dev);
+}
+
+static int msm8x10_wcd_codec_enable_clock_block(struct snd_soc_codec *codec,
+						int enable)
+{
+	if (enable) {
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_MCLK_CTL,
+				    0x01, 0x01);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_PDM_CTL,
+				    0x03, 0x03);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_TOP_CLK_CTL,
+				    0x0f, 0x0d);
+	} else {
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_TOP_CLK_CTL,
+				    0x0f, 0x00);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_MCLK_CTL,
+				    0x01, 0x01);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_MCLK_CTL,
+				    0x03, 0x00);
 	}
+	return 0;
+}
+
+static void msm8x10_wcd_codec_enable_audio_mode_bandgap(struct snd_soc_codec
+							*codec)
+{
+	snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL, 0x80,
+		0x80);
+	snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL, 0x04,
+		0x04);
+	snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL, 0x01,
+		0x01);
+	usleep_range(1000, 1000);
+	snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL, 0x80,
+		0x00);
+}
+
+static void msm8x10_wcd_codec_enable_bandgap(struct snd_soc_codec *codec,
+	enum msm8x10_wcd_bandgap_type choice)
+{
+	struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+
+	/* TODO lock resources accessed by audio streams and threaded
+	 * interrupt handlers
+	 */
+
+	dev_dbg(codec->dev, "%s, choice is %d, current is %d\n",
+		__func__, choice,
+		msm8x10_wcd->bandgap_type);
+
+	if (msm8x10_wcd->bandgap_type == choice)
+		return;
+
+	if ((msm8x10_wcd->bandgap_type == MSM8X10_WCD_BANDGAP_OFF) &&
+		(choice == MSM8X10_WCD_BANDGAP_AUDIO_MODE)) {
+		msm8x10_wcd_codec_enable_audio_mode_bandgap(codec);
+	} else if (choice == MSM8X10_WCD_BANDGAP_MBHC_MODE) {
+		/* bandgap mode becomes fast,
+		 * mclk should be off or clk buff source souldn't be VBG
+		 * Let's turn off mclk always */
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL,
+				    0x2, 0x2);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL,
+				    0x80, 0x80);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL,
+				    0x4, 0x4);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL,
+				    0x01, 0x01);
+		usleep_range(1000, 1000);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL,
+				    0x80, 0x00);
+	} else if ((msm8x10_wcd->bandgap_type ==
+		    MSM8X10_WCD_BANDGAP_MBHC_MODE) &&
+		    (choice == MSM8X10_WCD_BANDGAP_AUDIO_MODE)) {
+		snd_soc_write(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL, 0x50);
+		usleep_range(100, 100);
+		msm8x10_wcd_codec_enable_audio_mode_bandgap(codec);
+	} else if (choice == MSM8X10_WCD_BANDGAP_OFF) {
+		snd_soc_write(codec, MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL, 0x50);
+	} else {
+		dev_err(codec->dev,
+			"%s: Error, Invalid bandgap settings\n", __func__);
+	}
+	msm8x10_wcd->bandgap_type = choice;
 }
 
 int msm8x10_wcd_mclk_enable(struct snd_soc_codec *codec,
@@ -1867,24 +1860,30 @@
 {
 	struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
 
-	dev_dbg(codec->dev,
-		"%s: mclk_enable = %u, dapm = %d\n", __func__,
-		mclk_enable, dapm);
-	WCD9XXX_BCL_LOCK(&msm8x10_wcd->resmgr);
+	dev_dbg(codec->dev, "%s: mclk_enable = %u, dapm = %d\n",
+		__func__, mclk_enable, dapm);
+	if (dapm)
+		MSM8X10_WCD_ACQUIRE_LOCK(msm8x10_wcd->codec_resource_lock);
 	if (mclk_enable) {
-		wcd9xxx_resmgr_get_bandgap(&msm8x10_wcd->resmgr,
-					   WCD9XXX_BANDGAP_AUDIO_MODE);
-		wcd9xxx_resmgr_get_clk_block(&msm8x10_wcd->resmgr,
-					     WCD9XXX_CLK_MCLK);
+		msm8x10_wcd->mclk_enabled = true;
+		msm8x10_wcd_codec_enable_bandgap(codec,
+					   MSM8X10_WCD_BANDGAP_AUDIO_MODE);
+		msm8x10_wcd_codec_enable_clock_block(codec, 1);
 	} else {
-		/* Put clock and BG */
-		wcd9xxx_resmgr_put_clk_block(&msm8x10_wcd->resmgr,
-					     WCD9XXX_CLK_MCLK);
-		wcd9xxx_resmgr_put_bandgap(&msm8x10_wcd->resmgr,
-					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		if (!msm8x10_wcd->mclk_enabled) {
+			if (dapm)
+				MSM8X10_WCD_RELEASE_LOCK(
+				  msm8x10_wcd->codec_resource_lock);
+			dev_err(codec->dev, "Error, MCLK already diabled\n");
+			return -EINVAL;
+		}
+		msm8x10_wcd->mclk_enabled = false;
+		msm8x10_wcd_codec_enable_clock_block(codec, 0);
+		msm8x10_wcd_codec_enable_bandgap(codec,
+						   MSM8X10_WCD_BANDGAP_OFF);
 	}
-	WCD9XXX_BCL_UNLOCK(&msm8x10_wcd->resmgr);
-
+	if (dapm)
+		MSM8X10_WCD_RELEASE_LOCK(msm8x10_wcd->codec_resource_lock);
 	return 0;
 }
 
@@ -2027,7 +2026,7 @@
 			.rate_max = 192000,
 			.rate_min = 8000,
 			.channels_min = 1,
-			.channels_max = 4,
+			.channels_max = 3,
 		},
 		.ops = &msm8x10_wcd_dai_ops,
 	},
@@ -2077,23 +2076,16 @@
 	SND_SOC_DAPM_MIXER("DAC1", MSM8X10_WCD_A_RX_EAR_EN, 6, 0, dac1_switch,
 		ARRAY_SIZE(dac1_switch)),
 
-	SND_SOC_DAPM_AIF_IN("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
-				AIF1_PB, 0),
+	SND_SOC_DAPM_AIF_IN("I2S RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
 
-	SND_SOC_DAPM_MUX("I2S RX1 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX1, 0,
-				&slim_rx_mux[MSM8X10_WCD_RX1]),
-	SND_SOC_DAPM_MUX("I2S RX2 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX2, 0,
-				&slim_rx_mux[MSM8X10_WCD_RX2]),
-	SND_SOC_DAPM_MUX("I2S RX3 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX3, 0,
-				&slim_rx_mux[MSM8X10_WCD_RX3]),
+	SND_SOC_DAPM_AIF_IN("I2S RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
 
-	SND_SOC_DAPM_MIXER("I2S RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("I2S RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("I2S RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("I2S RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("I2S RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_AIF_IN("I2S RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
 
-	/* Headphone */
+	SND_SOC_DAPM_SUPPLY("TX CLK", MSM8X10_WCD_A_CDC_DIG_CLK_CTL,
+			4, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("INT_LDO_H", SND_SOC_NOPM, 1, 0, NULL, 0),
+
 	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
 	SND_SOC_DAPM_PGA_E("HPHL", MSM8X10_WCD_A_RX_HPH_CNP_EN,
 		5, 0, NULL, 0,
@@ -2114,10 +2106,10 @@
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	/* Speaker */
-	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT"),
 	SND_SOC_DAPM_OUTPUT("SPK_OUT"),
 
-	SND_SOC_DAPM_PGA_E("LINEOUT1 PA", MSM8X10_WCD_A_RX_LINE_CNP_EN,
+	SND_SOC_DAPM_PGA_E("LINEOUT PA", MSM8X10_WCD_A_RX_LINE_CNP_EN,
 			0, 0, NULL, 0, msm8x10_wcd_codec_enable_lineout,
 			SND_SOC_DAPM_PRE_PMU |
 			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -2127,7 +2119,7 @@
 			SND_SOC_DAPM_PRE_PMU |
 			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL,
+	SND_SOC_DAPM_DAC_E("LINEOUT DAC", NULL,
 		MSM8X10_WCD_A_RX_LINE_1_DAC_CTL, 7, 0,
 		msm8x10_wcd_lineout_dac_event,
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
@@ -2152,10 +2144,18 @@
 		0, msm8x10_wcd_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 
+	SND_SOC_DAPM_SUPPLY("RX1 CLK", MSM8X10_WCD_A_CDC_DIG_CLK_CTL,
+		0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("RX2 CLK", MSM8X10_WCD_A_CDC_DIG_CLK_CTL,
+		1, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("RX3 CLK", MSM8X10_WCD_A_CDC_DIG_CLK_CTL,
+		2, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("RX1 CHAIN", MSM8X10_WCD_A_CDC_RX1_B6_CTL,
 		5, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("RX2 CHAIN", MSM8X10_WCD_A_CDC_RX2_B6_CTL,
 		5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX3 CHAIN", MSM8X10_WCD_A_CDC_RX3_B6_CTL,
+		5, 0, NULL, 0),
 
 	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 		&rx_mix1_inp1_mux),
@@ -2191,26 +2191,28 @@
 
 
 	SND_SOC_DAPM_INPUT("AMIC1"),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External",
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal1",
 		MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
 		msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1",
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal2",
 		MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
 		msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2",
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal3",
 		MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
 		msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_1_EN, 7, 0,
 		msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_2_EN, 7, 0,
+	SND_SOC_DAPM_ADC_E("ADC2", NULL, MSM8X10_WCD_A_TX_2_EN, 7, 0,
 		msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_MICBIAS("MIC BIAS External", MSM8X10_WCD_A_MICB_1_CTL,
+			     7, 0),
+
 	SND_SOC_DAPM_INPUT("AMIC3"),
 
 	SND_SOC_DAPM_MUX_E("DEC1 MUX",
@@ -2226,11 +2228,13 @@
 		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_INPUT("AMIC2"),
-	SND_SOC_DAPM_AIF_OUT("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
-		AIF1_CAP, 0),
 
-	SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
-		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+	SND_SOC_DAPM_AIF_OUT("I2S TX1", "AIF1 Capture", 0, SND_SOC_NOPM,
+		0, 0),
+	SND_SOC_DAPM_AIF_OUT("I2S TX2", "AIF1 Capture", 0, SND_SOC_NOPM,
+		0, 0),
+	SND_SOC_DAPM_AIF_OUT("I2S TX3", "AIF1 Capture", 0, SND_SOC_NOPM,
+		0, 0),
 
 	/* Digital Mic Inputs */
 	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
@@ -2254,7 +2258,7 @@
 static const struct msm8x10_wcd_reg_mask_val msm8x10_wcd_reg_defaults[] = {
 
 	/* set MCLk to 9.6 */
-	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CHIP_CTL, 0x0A),
+	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CHIP_CTL, 0x00),
 
 	/* EAR PA deafults  */
 	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_EAR_CMBUFF, 0x05),
@@ -2280,7 +2284,12 @@
 
 
 	/* Disable TX7 internal biasing path which can cause leakage */
-	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
+	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_BIAS_CURR_CTL_2, 0x04),
+	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_MICB_CFILT_1_VAL, 0x60),
+	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_MICB_1_CTL, 0x82),
+	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_COM_BIAS, 0xE0),
+	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_1_EN, 0x32),
+	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_2_EN, 0x32),
 };
 
 static void msm8x10_wcd_update_reg_defaults(struct snd_soc_codec *codec)
@@ -2338,12 +2347,36 @@
 
 static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
 {
+	struct msm8x10_wcd_priv *msm8x10_wcd;
+	int i;
 	dev_dbg(codec->dev, "%s()\n", __func__);
 
+	msm8x10_wcd = kzalloc(sizeof(struct msm8x10_wcd_priv), GFP_KERNEL);
+	if (!msm8x10_wcd) {
+		dev_err(codec->dev, "Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0 ; i < NUM_DECIMATORS; i++) {
+		tx_hpf_work[i].msm8x10_wcd = msm8x10_wcd;
+		tx_hpf_work[i].decimator = i + 1;
+		INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+			tx_hpf_corner_freq_callback);
+	}
+
 	codec->control_data = dev_get_drvdata(codec->dev);
+	snd_soc_codec_set_drvdata(codec, msm8x10_wcd);
+	msm8x10_wcd->codec = codec;
 	msm8x10_wcd_codec_init_reg(codec);
 	msm8x10_wcd_update_reg_defaults(codec);
 
+	msm8x10_wcd->mclk_enabled = false;
+	msm8x10_wcd->bandgap_type = MSM8X10_WCD_BANDGAP_OFF;
+	msm8x10_wcd->clock_active = false;
+	msm8x10_wcd->config_mode_active = false;
+	msm8x10_wcd->mbhc_polling_active = false;
+	mutex_init(&msm8x10_wcd->codec_resource_lock);
+	msm8x10_wcd->codec = codec;
 
 	return 0;
 }
@@ -2353,18 +2386,6 @@
 	return 0;
 }
 
-static int msm8x10_wcd_device_init(struct msm8x10_wcd *msm8x10)
-{
-
-	mutex_init(&msm8x10->io_lock);
-	mutex_init(&msm8x10->xfer_lock);
-	mutex_init(&msm8x10->pm_lock);
-	msm8x10->wlock_holders = 0;
-
-	return 0;
-}
-
-
 static struct snd_soc_codec_driver soc_codec_dev_msm8x10_wcd = {
 	.probe	= msm8x10_wcd_codec_probe,
 	.remove	= msm8x10_wcd_codec_remove,
@@ -2387,6 +2408,124 @@
 	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
+static int msm8x10_wcd_enable_supplies(struct msm8x10_wcd *msm8x10,
+				struct msm8x10_wcd_pdata *pdata)
+{
+	int ret;
+	int i;
+	msm8x10->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
+				   ARRAY_SIZE(pdata->regulator),
+				   GFP_KERNEL);
+	if (!msm8x10->supplies) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	msm8x10->num_of_supplies = 0;
+
+	if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
+		dev_err(msm8x10->dev, "%s: Array Size out of bound\n",
+			__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+		if (pdata->regulator[i].name) {
+			msm8x10->supplies[i].supply = pdata->regulator[i].name;
+			msm8x10->num_of_supplies++;
+		}
+	}
+
+	ret = regulator_bulk_get(msm8x10->dev, msm8x10->num_of_supplies,
+				 msm8x10->supplies);
+	if (ret != 0) {
+		dev_err(msm8x10->dev, "Failed to get supplies: err = %d\n",
+							ret);
+		goto err_supplies;
+	}
+
+	for (i = 0; i < msm8x10->num_of_supplies; i++) {
+		ret = regulator_set_voltage(msm8x10->supplies[i].consumer,
+			pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
+		if (ret) {
+			dev_err(msm8x10->dev, "%s: Setting regulator voltage failed for regulator %s err = %d\n",
+				__func__, msm8x10->supplies[i].supply, ret);
+			goto err_get;
+		}
+
+		ret = regulator_set_optimum_mode(msm8x10->supplies[i].consumer,
+			pdata->regulator[i].optimum_uA);
+		if (ret < 0) {
+			dev_err(msm8x10->dev, "%s: Setting regulator optimum mode failed for regulator %s err = %d\n",
+				__func__, msm8x10->supplies[i].supply, ret);
+			goto err_get;
+		}
+	}
+
+	ret = regulator_bulk_enable(msm8x10->num_of_supplies,
+				    msm8x10->supplies);
+	if (ret != 0) {
+		dev_err(msm8x10->dev, "Failed to enable supplies: err = %d\n",
+				ret);
+		goto err_configure;
+	}
+	return ret;
+
+err_configure:
+	for (i = 0; i < msm8x10->num_of_supplies; i++) {
+		regulator_set_voltage(msm8x10->supplies[i].consumer, 0,
+			pdata->regulator[i].max_uV);
+		regulator_set_optimum_mode(msm8x10->supplies[i].consumer, 0);
+	}
+err_get:
+	regulator_bulk_free(msm8x10->num_of_supplies, msm8x10->supplies);
+err_supplies:
+	kfree(msm8x10->supplies);
+err:
+	return ret;
+}
+
+static void msm8x10_wcd_disable_supplies(struct msm8x10_wcd *msm8x10,
+				     struct msm8x10_wcd_pdata *pdata)
+{
+	int i;
+
+	regulator_bulk_disable(msm8x10->num_of_supplies,
+				    msm8x10->supplies);
+	for (i = 0; i < msm8x10->num_of_supplies; i++) {
+		regulator_set_voltage(msm8x10->supplies[i].consumer, 0,
+			pdata->regulator[i].max_uV);
+		regulator_set_optimum_mode(msm8x10->supplies[i].consumer, 0);
+	}
+	regulator_bulk_free(msm8x10->num_of_supplies, msm8x10->supplies);
+	kfree(msm8x10->supplies);
+}
+
+static int msm8x10_wcd_bringup(struct msm8x10_wcd *msm8x10)
+{
+	msm8x10->read_dev = msm8x10_wcd_reg_read;
+	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CDC_RST_CTL, 0x02);
+	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CHIP_CTL, 0x00);
+	usleep_range(5000, 5000);
+	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CDC_RST_CTL, 0x03);
+	return 0;
+}
+
+static int msm8x10_wcd_device_init(struct msm8x10_wcd *msm8x10)
+{
+	mutex_init(&msm8x10->io_lock);
+	mutex_init(&msm8x10->xfer_lock);
+	mutex_init(&msm8x10->pm_lock);
+	msm8x10->wlock_holders = 0;
+
+	iowrite32(0x03C00000, ioremap(0xFD512050, 4));
+	usleep_range(5000, 5000);
+
+	msm8x10_wcd_bringup(msm8x10);
+	return 0;
+}
+
 static int __devinit msm8x10_wcd_i2c_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -2401,7 +2540,7 @@
 
 	if (device_id > 0) {
 		msm8x10_wcd_modules[device_id++].client = client;
-		return ret;
+		goto rtn;
 	}
 
 	dev = &client->dev;
@@ -2421,19 +2560,25 @@
 		dev_err(&client->dev,
 			"%s: error, allocation failed\n", __func__);
 		ret = -ENOMEM;
-		goto fail;
+		goto rtn;
 	}
 
 	msm8x10->dev = &client->dev;
 	msm8x10_wcd_modules[device_id++].client = client;
 	msm8x10->read_dev = msm8x10_wcd_reg_read;
 	msm8x10->write_dev = msm8x10_wcd_reg_write;
+	ret = msm8x10_wcd_enable_supplies(msm8x10, pdata);
+	if (ret) {
+		dev_err(&client->dev, "%s: Fail to enable Codec supplies\n",
+			__func__);
+		goto err_codec;
+	}
 	ret = msm8x10_wcd_device_init(msm8x10);
 	if (ret) {
 		dev_err(&client->dev,
 			"%s:msm8x10_wcd_device_init failed with error %d\n",
 			__func__, ret);
-		goto fail;
+		goto err_supplies;
 	}
 	dev_set_drvdata(&client->dev, msm8x10);
 	ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_msm8x10_wcd,
@@ -2443,7 +2588,14 @@
 		dev_err(&client->dev,
 			"%s:snd_soc_register_codec failed with error %d\n",
 			__func__, ret);
-fail:
+	else
+		goto rtn;
+
+err_supplies:
+	msm8x10_wcd_disable_supplies(msm8x10, pdata);
+err_codec:
+	kfree(msm8x10);
+rtn:
 	return ret;
 }
 
diff --git a/sound/soc/codecs/msm8x10-wcd.h b/sound/soc/codecs/msm8x10-wcd.h
index 44e8a6d..d250e0a 100644
--- a/sound/soc/codecs/msm8x10-wcd.h
+++ b/sound/soc/codecs/msm8x10-wcd.h
@@ -199,7 +199,7 @@
 	int (*read_dev)(struct msm8x10_wcd *msm8x10,
 			unsigned short reg, unsigned int *val);
 	int (*write_dev)(struct msm8x10_wcd *msm8x10,
-			 unsigned short reg, unsigned int val);
+			 unsigned short reg, u8 val);
 
 	u32 num_of_supplies;
 	struct regulator_bulk_data *supplies;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index b8a4a86..29703b9 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -55,9 +55,12 @@
 #define MBHC_FW_READ_ATTEMPTS 15
 #define MBHC_FW_READ_TIMEOUT 2000000
 #define MBHC_VDDIO_SWITCH_WAIT_MS 10
+#define COMP_DIGITAL_DB_GAIN_APPLY(a, b) \
+	(((a) <= 0) ? ((a) - b) : (a))
 
 #define SLIM_CLOSE_TIMEOUT 1000
-
+/* The wait time value comes from codec HW specification */
+#define COMP_BRINGUP_WAIT_TIME  2000
 enum {
 	MBHC_USE_HPHL_TRIGGER = 1,
 	MBHC_USE_MB_TRIGGER = 2
@@ -99,9 +102,7 @@
 	RX_MIX1_INP_SEL_RX6,
 	RX_MIX1_INP_SEL_RX7,
 };
-
-#define TABLA_COMP_DIGITAL_GAIN_HP_OFFSET 3
-#define TABLA_COMP_DIGITAL_GAIN_LINEOUT_OFFSET 6
+#define MAX_PA_GAIN_OPTIONS  13
 
 #define TABLA_MCLK_RATE_12288KHZ 12288000
 #define TABLA_MCLK_RATE_9600KHZ 9600000
@@ -220,6 +221,28 @@
 	u32 shutdown_timeout;
 };
 
+struct comp_dgtl_gain_offset {
+	u8 whole_db_gain;
+	u8 half_db_gain;
+};
+
+static const struct comp_dgtl_gain_offset
+			comp_dgtl_gain[MAX_PA_GAIN_OPTIONS] = {
+	{0, 0},
+	{1, 1},
+	{3, 0},
+	{4, 1},
+	{6, 0},
+	{7, 1},
+	{9, 0},
+	{10, 1},
+	{12, 0},
+	{13, 1},
+	{15, 0},
+	{16, 1},
+	{18, 0},
+};
+
 /* Data used by MBHC */
 struct mbhc_internal_cal_data {
 	u16 dce_z;
@@ -377,6 +400,7 @@
 	/*compander*/
 	int comp_enabled[COMPANDER_MAX];
 	u32 comp_fs[COMPANDER_MAX];
+	u8  comp_gain_offset[TABLA_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS - 1];
 
 	/* Maintain the status of AUX PGA */
 	int aux_pga_cnt;
@@ -547,7 +571,10 @@
 {
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	mutex_lock(&codec->dapm.codec->mutex);
 	ucontrol->value.integer.value[0] = (tabla->anc_func == true ? 1 : 0);
+	mutex_unlock(&codec->dapm.codec->mutex);
 	return 0;
 }
 
@@ -802,34 +829,51 @@
 
 static int tabla_compander_gain_offset(
 	struct snd_soc_codec *codec, u32 enable,
-	unsigned int reg, int mask, int event, u32 comp)
+	unsigned int pa_reg, unsigned int vol_reg,
+	int mask, int event,
+	struct comp_dgtl_gain_offset *gain_offset,
+	int index)
 {
-	int pa_mode = snd_soc_read(codec, reg) & mask;
-	int gain_offset = 0;
-	/*  if PMU && enable is 1-> offset is 3
-	 *  if PMU && enable is 0-> offset is 0
-	 *  if PMD && pa_mode is PA -> offset is 0: PMU compander is off
-	 *  if PMD && pa_mode is comp -> offset is -3: PMU compander is on.
-	 */
+	unsigned int pa_gain = snd_soc_read(codec, pa_reg);
+	unsigned int digital_vol = snd_soc_read(codec, vol_reg);
+	int pa_mode = pa_gain & mask;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: pa_gain(0x%x=0x%x)digital_vol(0x%x=0x%x)event(0x%x) index(%d)\n",
+		 __func__, pa_reg, pa_gain, vol_reg, digital_vol, event, index);
+	if (((pa_gain & 0xF) + 1) > ARRAY_SIZE(comp_dgtl_gain) ||
+		(index >= ARRAY_SIZE(tabla->comp_gain_offset))) {
+		pr_err("%s: Out of array boundary\n", __func__);
+		return -EINVAL;
+	}
 
 	if (SND_SOC_DAPM_EVENT_ON(event) && (enable != 0)) {
-		if (comp == COMPANDER_1)
-			gain_offset = TABLA_COMP_DIGITAL_GAIN_HP_OFFSET;
-		if (comp == COMPANDER_2)
-			gain_offset = TABLA_COMP_DIGITAL_GAIN_LINEOUT_OFFSET;
+		gain_offset->whole_db_gain = COMP_DIGITAL_DB_GAIN_APPLY(
+		  (digital_vol - comp_dgtl_gain[pa_gain & 0xF].whole_db_gain),
+		  comp_dgtl_gain[pa_gain & 0xF].half_db_gain);
+		pr_debug("%s: listed whole_db_gain:0x%x, adjusted whole_db_gain:0x%x\n",
+			 __func__, comp_dgtl_gain[pa_gain & 0xF].whole_db_gain,
+			 gain_offset->whole_db_gain);
+		gain_offset->half_db_gain =
+				comp_dgtl_gain[pa_gain & 0xF].half_db_gain;
+		tabla->comp_gain_offset[index] = digital_vol -
+						 gain_offset->whole_db_gain ;
 	}
 	if (SND_SOC_DAPM_EVENT_OFF(event) && (pa_mode == 0)) {
-		if (comp == COMPANDER_1)
-			gain_offset = -TABLA_COMP_DIGITAL_GAIN_HP_OFFSET;
-		if (comp == COMPANDER_2)
-			gain_offset = -TABLA_COMP_DIGITAL_GAIN_LINEOUT_OFFSET;
-
+		gain_offset->whole_db_gain = digital_vol +
+					     tabla->comp_gain_offset[index];
+		pr_debug("%s: listed whole_db_gain:0x%x, adjusted whole_db_gain:0x%x\n",
+			 __func__, comp_dgtl_gain[pa_gain & 0xF].whole_db_gain,
+			 gain_offset->whole_db_gain);
+		gain_offset->half_db_gain = 0;
 	}
-	pr_debug("%s: compander #%d gain_offset %d\n",
-		 __func__, comp + 1, gain_offset);
-	return gain_offset;
-}
 
+	pr_debug("%s: half_db_gain(%d)whole_db_gain(%d)comp_gain_offset[%d](%d)\n",
+		 __func__, gain_offset->half_db_gain,
+		 gain_offset->whole_db_gain, index,
+		 tabla->comp_gain_offset[index]);
+	return 0;
+}
 
 static int tabla_config_gain_compander(
 				struct snd_soc_codec *codec,
@@ -837,8 +881,7 @@
 {
 	int value = 0;
 	int mask = 1 << 4;
-	int gain = 0;
-	int gain_offset;
+	struct comp_dgtl_gain_offset gain_offset = {0, 0};
 	if (compander >= COMPANDER_MAX) {
 		pr_err("%s: Error, invalid compander channel\n", __func__);
 		return -EINVAL;
@@ -848,43 +891,61 @@
 		value = 1 << 4;
 
 	if (compander == COMPANDER_1) {
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_HPH_L_GAIN, mask, event, compander);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_HPH_L_GAIN,
+				TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 0);
 		snd_soc_update_bits(codec, TABLA_A_RX_HPH_L_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX1_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_HPH_R_GAIN, mask, event, compander);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_HPH_R_GAIN,
+				TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 1);
 		snd_soc_update_bits(codec, TABLA_A_RX_HPH_R_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX2_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX2_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
 	} else if (compander == COMPANDER_2) {
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_LINE_1_GAIN, mask, event, compander);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_LINE_1_GAIN,
+				TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 2);
 		snd_soc_update_bits(codec, TABLA_A_RX_LINE_1_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX3_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_LINE_3_GAIN, mask, event, compander);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX3_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_LINE_3_GAIN,
+				TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 3);
 		snd_soc_update_bits(codec, TABLA_A_RX_LINE_3_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX4_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_LINE_2_GAIN, mask, event, compander);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX4_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_LINE_2_GAIN,
+				TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 4);
 		snd_soc_update_bits(codec, TABLA_A_RX_LINE_2_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX5_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_LINE_4_GAIN, mask, event, compander);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX5_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_LINE_4_GAIN,
+				TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 5);
 		snd_soc_update_bits(codec, TABLA_A_RX_LINE_4_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX6_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX6_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
 	}
 	return 0;
 }
@@ -921,7 +982,6 @@
 	return 0;
 }
 
-
 static int tabla_config_compander(struct snd_soc_dapm_widget *w,
 						  struct snd_kcontrol *kcontrol,
 						  int event)
@@ -929,106 +989,161 @@
 	struct snd_soc_codec *codec = w->codec;
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 	u32 rate = tabla->comp_fs[w->shift];
-	u32 status;
-	unsigned long timeout;
-	pr_debug("%s: compander #%d enable %d event %d\n",
+
+	pr_debug("%s: compander #%d enable %d event %d widget name %s\n",
 		 __func__, w->shift + 1,
-		 tabla->comp_enabled[w->shift], event);
+		 tabla->comp_enabled[w->shift], event , w->name);
+	if (tabla->comp_enabled[w->shift] == 0)
+		goto rtn;
+	if ((w->shift == COMPANDER_1) && (tabla->anc_func)) {
+		pr_debug("%s: ANC is enabled so compander #%d cannot be enabled\n",
+			 __func__, w->shift + 1);
+		goto rtn;
+	}
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (tabla->comp_enabled[w->shift] != 0) {
-			/* Enable both L/R compander clocks */
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_CLK_RX_B2_CTL,
-					1 << comp_shift[w->shift],
-					1 << comp_shift[w->shift]);
-			/* Clear the HALT for the compander*/
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_COMP1_B1_CTL +
-					w->shift * 8, 1 << 2, 0);
-			/* Toggle compander reset bits*/
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_CLK_OTHR_RESET_CTL,
-					1 << comp_shift[w->shift],
-					1 << comp_shift[w->shift]);
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_CLK_OTHR_RESET_CTL,
-					1 << comp_shift[w->shift], 0);
-			tabla_config_gain_compander(codec, w->shift, 1, event);
-			/* Compander enable -> 0x370/0x378*/
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
-					    w->shift * 8, 0x03, 0x03);
-			/* Update the RMS meter resampling*/
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_COMP1_B3_CTL +
-					w->shift * 8, 0xFF, 0x01);
-			snd_soc_update_bits(codec,
-					    TABLA_A_CDC_COMP1_B2_CTL +
-					    w->shift * 8, 0xF0, 0x50);
-			/* Wait for 1ms*/
-			usleep_range(5000, 5000);
-		}
+		/* Update compander sample rate */
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_FS_CFG +
+				    w->shift * 8, 0x07, rate);
+		/* Enable both L/R compander clocks */
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_RX_B2_CTL,
+				    1 << comp_shift[w->shift],
+				    1 << comp_shift[w->shift]);
+		/* Toggle compander reset bits */
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << comp_shift[w->shift],
+				    1 << comp_shift[w->shift]);
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << comp_shift[w->shift], 0);
+		tabla_config_gain_compander(codec, w->shift, 1, event);
+		/* Compander enable -> 0x370/0x378 */
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
+				    w->shift * 8, 0x03, 0x03);
+		/* Update the RMS meter resampling */
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_COMP1_B3_CTL +
+				    w->shift * 8, 0xFF, 0x01);
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0xF0, 0x50);
+		usleep_range(COMP_BRINGUP_WAIT_TIME, COMP_BRINGUP_WAIT_TIME);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
-		/* Set sample rate dependent paramater*/
-		if (tabla->comp_enabled[w->shift] != 0) {
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_FS_CFG +
-			w->shift * 8, 0x07,	rate);
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
-			w->shift * 8, 0x0F,
-			comp_samp_params[rate].peak_det_timeout);
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
-			w->shift * 8, 0xF0,
-			comp_samp_params[rate].rms_meter_div_fact);
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B3_CTL +
-			w->shift * 8, 0xFF,
-			comp_samp_params[rate].rms_meter_resamp_fact);
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
-			w->shift * 8, 0x38,
-			comp_samp_params[rate].shutdown_timeout);
+		/* Set sample rate dependent paramater */
+		if (w->shift == COMPANDER_1) {
+			snd_soc_update_bits(codec,
+					    TABLA_A_CDC_CLSG_CTL,
+					    0x11, 0x00);
+			snd_soc_write(codec,
+				      TABLA_A_CDC_CONN_CLSG_CTL, 0x11);
 		}
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0x0F,
+				    comp_samp_params[rate].peak_det_timeout);
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0xF0,
+				    comp_samp_params[rate].rms_meter_div_fact);
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B3_CTL +
+				w->shift * 8, 0xFF,
+				comp_samp_params[rate].rms_meter_resamp_fact);
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
+				    w->shift * 8, 0x38,
+				    comp_samp_params[rate].shutdown_timeout);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
-		if (tabla->comp_enabled[w->shift] != 0) {
-			status = snd_soc_read(codec,
-					TABLA_A_CDC_COMP1_SHUT_DOWN_STATUS +
-					w->shift * 8);
-			pr_debug("%s: compander #%d shutdown status %d in event %d\n",
-				 __func__, w->shift + 1, status, event);
-			/* Halt the compander*/
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
-					    w->shift * 8, 1 << 2, 1 << 2);
-		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (tabla->comp_enabled[w->shift] != 0) {
-			/* Wait up to a second for shutdown complete */
-			timeout = jiffies + HZ;
-			do {
-				status = snd_soc_read(codec,
-					TABLA_A_CDC_COMP1_SHUT_DOWN_STATUS +
-					w->shift * 8);
-				if (status == 0x3)
-					break;
-				usleep_range(5000, 5000);
-			} while (!(time_after(jiffies, timeout)));
-			/* Restore the gain */
-			tabla_config_gain_compander(codec, w->shift,
-						tabla->comp_enabled[w->shift],
-						event);
-			/* Disable the compander*/
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
-					    w->shift * 8, 0x03, 0x00);
-			/* Turn off the clock for compander in pair*/
-			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_B2_CTL,
-					    0x03 << comp_shift[w->shift], 0);
-			/* Clear the HALT for the compander*/
+		/* Disable the compander */
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
+				    w->shift * 8, 0x03, 0x00);
+		/* Toggle compander reset bits */
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << comp_shift[w->shift],
+				    1 << comp_shift[w->shift]);
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << comp_shift[w->shift], 0);
+		/* Turn off the clock for compander in pair */
+		snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_B2_CTL,
+				    0x03 << comp_shift[w->shift], 0);
+		/* Restore the gain */
+		tabla_config_gain_compander(codec, w->shift,
+					    tabla->comp_enabled[w->shift],
+					    event);
+		if (w->shift == COMPANDER_1) {
 			snd_soc_update_bits(codec,
-					    TABLA_A_CDC_COMP1_B1_CTL +
-					    w->shift * 8, 1 << 2, 0);
+					    TABLA_A_CDC_CLSG_CTL,
+					    0x11, 0x11);
+			snd_soc_write(codec,
+				      TABLA_A_CDC_CONN_CLSG_CTL, 0x14);
 		}
 		break;
 	}
+rtn:
+	return 0;
+}
+
+static int tabla_codec_hphr_dem_input_selection(struct snd_soc_dapm_widget *w,
+						struct snd_kcontrol *kcontrol,
+						int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: compander#1->enable(%d) reg(0x%x = 0x%x) event(%d)\n",
+		__func__, tabla->comp_enabled[COMPANDER_1],
+		TABLA_A_CDC_RX1_B6_CTL,
+		snd_soc_read(codec, TABLA_A_CDC_RX1_B6_CTL), event);
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (tabla->comp_enabled[COMPANDER_1] && !tabla->anc_func)
+			snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL,
+					    1 << w->shift, 0);
+		else
+			snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL,
+					    1 << w->shift, 1 << w->shift);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL,
+				    1 << w->shift, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int tabla_codec_hphl_dem_input_selection(struct snd_soc_dapm_widget *w,
+						struct snd_kcontrol *kcontrol,
+						int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: compander#1->enable(%d) reg(0x%x = 0x%x) event(%d)\n",
+		__func__, tabla->comp_enabled[COMPANDER_1],
+		TABLA_A_CDC_RX2_B6_CTL,
+		snd_soc_read(codec, TABLA_A_CDC_RX2_B6_CTL), event);
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (tabla->comp_enabled[COMPANDER_1] && !tabla->anc_func)
+			snd_soc_update_bits(codec, TABLA_A_CDC_RX2_B6_CTL,
+					    1 << w->shift, 0);
+		else
+			snd_soc_update_bits(codec, TABLA_A_CDC_RX2_B6_CTL,
+					    1 << w->shift, 1 << w->shift);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX2_B6_CTL,
+				    1 << w->shift, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
 	return 0;
 }
 
@@ -5361,8 +5476,12 @@
 		&rx6_dsm_mux, tabla_codec_reset_interpolator,
 		SND_SOC_DAPM_PRE_PMU),
 
-	SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER_E("RX1 CHAIN", SND_SOC_NOPM, 5, 0, NULL,
+		0, tabla_codec_hphr_dem_input_selection,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("RX2 CHAIN", SND_SOC_NOPM, 5, 0, NULL,
+		0, tabla_codec_hphl_dem_input_selection,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
 
 	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 		&rx_mix1_inp1_mux),
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 43a1042..845f1a2 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -110,6 +110,15 @@
 	AANC_FF_GAIN_ADAPTIVE,
 	AANC_FFGAIN_ADAPTIVE_EN,
 	AANC_GAIN_CONTROL,
+	SPKR_CLIP_PIPE_BANK_SEL,
+	SPKR_CLIPDET_VAL0,
+	SPKR_CLIPDET_VAL1,
+	SPKR_CLIPDET_VAL2,
+	SPKR_CLIPDET_VAL3,
+	SPKR_CLIPDET_VAL4,
+	SPKR_CLIPDET_VAL5,
+	SPKR_CLIPDET_VAL6,
+	SPKR_CLIPDET_VAL7,
 	MAX_CFG_REGISTERS,
 };
 
@@ -182,6 +191,74 @@
 		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_GAIN_CTL),
 		AANC_GAIN_CONTROL, 0xFF, 8, 0
 	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_DESTN3),
+		MAD_CLIP_INT_DEST_SELECT_REG, 0x8, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_MASK3),
+		MAD_CLIP_INT_MASK_REG, 0x8, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_STATUS3),
+		MAD_CLIP_INT_STATUS_REG, 0x8, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_CLEAR3),
+		MAD_CLIP_INT_CLEAR_REG, 0x8, 8, 0
+	},
+};
+
+static struct afe_param_cdc_reg_cfg clip_reg_cfg[] = {
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL),
+		SPKR_CLIP_PIPE_BANK_SEL, 0x3, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL0),
+		SPKR_CLIPDET_VAL0, 0xff, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL1),
+		SPKR_CLIPDET_VAL1, 0xff, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL2),
+		SPKR_CLIPDET_VAL2, 0xff, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL3),
+		SPKR_CLIPDET_VAL3, 0xff, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL4),
+		SPKR_CLIPDET_VAL4, 0xff, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL5),
+		SPKR_CLIPDET_VAL5, 0xff, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL6),
+		SPKR_CLIPDET_VAL6, 0xff, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL7),
+		SPKR_CLIPDET_VAL7, 0xff, 8, 0
+	},
 };
 
 static struct afe_param_cdc_reg_cfg_data taiko_audio_reg_cfg = {
@@ -189,11 +266,22 @@
 	.reg_data = audio_reg_cfg,
 };
 
+static struct afe_param_cdc_reg_cfg_data taiko_clip_reg_cfg = {
+	.num_registers = ARRAY_SIZE(clip_reg_cfg),
+	.reg_data = clip_reg_cfg,
+};
+
 static struct afe_param_id_cdc_aanc_version taiko_cdc_aanc_version = {
 	.cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
 	.aanc_hw_version        = AANC_HW_BLOCK_VERSION_2,
 };
 
+static struct afe_param_id_clip_bank_sel clip_bank_sel = {
+	.minor_version = AFE_API_VERSION_CLIP_BANK_SEL_CFG,
+	.num_banks = AFE_CLIP_MAX_BANKS,
+	.bank_map = {0, 1, 2, 3},
+};
+
 module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
 MODULE_PARM_DESC(spkr_drv_wrnd,
 	       "Run software workaround to avoid leakage on the speaker drive");
@@ -4620,9 +4708,6 @@
 	dai = &taiko_p->dai[w->shift];
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
-		/*Enable Clip Detection*/
-		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
-				0x8, 0x8);
 		/*Enable V&I sensing*/
 		snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
 				0x88, 0x88);
@@ -4635,6 +4720,7 @@
 		/*Enable Current Decimator*/
 		snd_soc_update_bits(codec,
 		TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x13);
+		(void) taiko_codec_enable_slim_chmask(dai, true);
 		ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
 					dai->rate, dai->bit_width,
 					&dai->grph);
@@ -4657,9 +4743,6 @@
 		/*Disable V&I sensing*/
 		snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
 				0x88, 0x00);
-		/*Disable clip detection*/
-		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
-				0x8, 0x0);
 		break;
 	}
 out_vi:
@@ -5949,6 +6032,7 @@
 			   enum afe_config_type config_type)
 {
 	struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct wcd9xxx *taiko_core = dev_get_drvdata(codec->dev->parent);
 
 	switch (config_type) {
 	case AFE_SLIMBUS_SLAVE_CONFIG:
@@ -5959,6 +6043,16 @@
 		return &taiko_slimbus_slave_port_cfg;
 	case AFE_AANC_VERSION:
 		return &taiko_cdc_aanc_version;
+	case AFE_CLIP_BANK_SEL:
+		if (!TAIKO_IS_1_0(taiko_core->version))
+			return &clip_bank_sel;
+		else
+			return NULL;
+	case AFE_CDC_CLIP_REGISTERS_CONFIG:
+		if (!TAIKO_IS_1_0(taiko_core->version))
+			return &taiko_clip_reg_cfg;
+		else
+			return NULL;
 	default:
 		pr_err("%s: Unknown config_type 0x%x\n", __func__, config_type);
 		return NULL;
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index ebde90b..7ab4811 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -55,8 +55,7 @@
 # for MSM 8960 sound card driver
 
 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-lowlatency-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o msm-dai-stub.o
+snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-lowlatency-pcm-q6.o msm-pcm-loopback.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 msm-pcm-dtmf.o msm-pcm-host-voice.o
 snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 8db13f6..1b51595 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -236,6 +236,17 @@
 			.rate_min =	8000,
 			.rate_max = 192000,
 		},
+		.capture = {
+			.stream_name = "MultiMedia6 Capture",
+			.aif_name = "MM_UL6",
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+					SNDRV_PCM_RATE_KNOT),
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min =     8000,
+			.rate_max =	48000,
+		},
 		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia6",
 	},
@@ -549,6 +560,34 @@
 		.name = "SEC_I2S_RX_HOSTLESS",
 	},
 	{
+		.capture = {
+			.stream_name = "Primary MI2S_TX Hostless Capture",
+			.aif_name = "PRI_MI2S_UL_HL",
+			.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 = "PRI_MI2S_TX_HOSTLESS",
+	},
+	{
+		.playback = {
+			.stream_name = "Secondary MI2S_RX Hostless Playback",
+			.aif_name = "SEC_MI2S_DL_HL",
+			.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 = "SEC_MI2S_RX_HOSTLESS",
+	},
+	{
 		.playback = {
 			.stream_name = "Voice2 Playback",
 			.aif_name = "VOICE2_DL",
diff --git a/sound/soc/msm/msm-pcm-loopback.c b/sound/soc/msm/msm-pcm-loopback.c
new file mode 100644
index 0000000..84ea9c6
--- /dev/null
+++ b/sound/soc/msm/msm-pcm-loopback.c
@@ -0,0 +1,362 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/apr_audio.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/q6asm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <asm/dma.h>
+#include <linux/dma-mapping.h>
+
+#include "msm-pcm-routing.h"
+
+struct msm_pcm_loopback {
+	struct snd_pcm_substream *playback_substream;
+	struct snd_pcm_substream *capture_substream;
+
+	int instance;
+
+	struct mutex lock;
+
+	uint32_t samp_rate;
+	uint32_t channel_mode;
+
+	int playback_start;
+	int capture_start;
+	int session_id;
+	struct audio_client *audio_client;
+};
+
+static void stop_pcm(struct msm_pcm_loopback *pcm);
+
+static const struct snd_pcm_hardware dummy_pcm_hardware = {
+	.formats                = 0xffffffff,
+	.channels_min           = 1,
+	.channels_max           = UINT_MAX,
+
+	/* Random values to keep userspace happy when checking constraints */
+	.info                   = SNDRV_PCM_INFO_INTERLEAVED |
+				  SNDRV_PCM_INFO_BLOCK_TRANSFER,
+	.buffer_bytes_max       = 128*1024,
+	.period_bytes_min       = 1024,
+	.period_bytes_max       = 1024*2,
+	.periods_min            = 2,
+	.periods_max            = 128,
+};
+
+static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
+					void *priv_data)
+{
+	struct msm_pcm_loopback *pcm = priv_data;
+
+	BUG_ON(!pcm);
+
+	pr_debug("%s: event %x\n", __func__, event);
+
+	switch (event) {
+	case MSM_PCM_RT_EVT_DEVSWITCH:
+		q6asm_cmd(pcm->audio_client, CMD_PAUSE);
+		q6asm_cmd(pcm->audio_client, CMD_FLUSH);
+		q6asm_run(pcm->audio_client, 0, 0, 0);
+	default:
+		break;
+	}
+}
+
+static void msm_pcm_loopback_event_handler(uint32_t opcode,
+		uint32_t token, uint32_t *payload, void *priv)
+{
+	pr_debug("%s\n", __func__);
+	switch (opcode) {
+	case APR_BASIC_RSP_RESULT: {
+		switch (payload[0]) {
+			break;
+		default:
+			break;
+		}
+	}
+	break;
+	default:
+		pr_err("Not Supported Event opcode[0x%x]\n", opcode);
+		break;
+	}
+}
+
+static int msm_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+	struct msm_pcm_loopback *pcm;
+	int ret = 0;
+	struct msm_pcm_routing_evt event;
+
+	pcm = dev_get_drvdata(rtd->platform->dev);
+	mutex_lock(&pcm->lock);
+
+	snd_soc_set_runtime_hwparams(substream, &dummy_pcm_hardware);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		pcm->playback_substream = substream;
+	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		pcm->capture_substream = substream;
+
+	pcm->instance++;
+	dev_dbg(rtd->platform->dev, "%s: pcm out open: %d,%d\n", __func__,
+			pcm->instance, substream->stream);
+	if (pcm->instance == 2) {
+		struct snd_soc_pcm_runtime *soc_pcm_rx =
+				pcm->playback_substream->private_data;
+		struct snd_soc_pcm_runtime *soc_pcm_tx =
+				pcm->capture_substream->private_data;
+		if (pcm->audio_client != NULL)
+			stop_pcm(pcm);
+
+		pcm->audio_client = q6asm_audio_client_alloc(
+				(app_cb)msm_pcm_loopback_event_handler, pcm);
+		if (!pcm->audio_client) {
+			dev_err(rtd->platform->dev,
+				"%s: Could not allocate memory\n", __func__);
+			mutex_unlock(&pcm->lock);
+			return -ENOMEM;
+		}
+		pcm->session_id = pcm->audio_client->session;
+		pcm->audio_client->perf_mode = false;
+		ret = q6asm_open_loopack(pcm->audio_client);
+		if (ret < 0) {
+			dev_err(rtd->platform->dev,
+				"%s: pcm out open failed\n", __func__);
+			q6asm_audio_client_free(pcm->audio_client);
+			mutex_unlock(&pcm->lock);
+			return -ENOMEM;
+		}
+		event.event_func = msm_pcm_route_event_handler;
+		event.priv_data = (void *) pcm;
+		msm_pcm_routing_reg_phy_stream(soc_pcm_tx->dai_link->be_id,
+			pcm->audio_client->perf_mode,
+			pcm->session_id, pcm->capture_substream->stream);
+		msm_pcm_routing_reg_phy_stream_v2(soc_pcm_rx->dai_link->be_id,
+			pcm->audio_client->perf_mode,
+			pcm->session_id, pcm->playback_substream->stream,
+			event);
+	}
+	dev_info(rtd->platform->dev, "%s: Instance = %d, Stream ID = %s\n",
+			__func__ , pcm->instance, substream->pcm->id);
+	runtime->private_data = pcm;
+
+	mutex_unlock(&pcm->lock);
+
+	return 0;
+}
+
+static void stop_pcm(struct msm_pcm_loopback *pcm)
+{
+	struct snd_soc_pcm_runtime *soc_pcm_rx =
+		pcm->playback_substream->private_data;
+	struct snd_soc_pcm_runtime *soc_pcm_tx =
+		pcm->capture_substream->private_data;
+
+	if (pcm->audio_client == NULL)
+		return;
+	q6asm_cmd(pcm->audio_client, CMD_CLOSE);
+
+	msm_pcm_routing_dereg_phy_stream(soc_pcm_rx->dai_link->be_id,
+			SNDRV_PCM_STREAM_PLAYBACK);
+	msm_pcm_routing_dereg_phy_stream(soc_pcm_tx->dai_link->be_id,
+			SNDRV_PCM_STREAM_CAPTURE);
+	q6asm_audio_client_free(pcm->audio_client);
+	pcm->audio_client = NULL;
+}
+
+static int msm_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_pcm_loopback *pcm = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+	int ret = 0;
+
+	mutex_lock(&pcm->lock);
+
+	dev_dbg(rtd->platform->dev, "%s: end pcm call:%d\n",
+		__func__, substream->stream);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		pcm->playback_start = 0;
+	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		pcm->capture_start = 0;
+
+	pcm->instance--;
+	if (!pcm->playback_start || !pcm->capture_start) {
+		dev_dbg(rtd->platform->dev, "%s: end pcm call\n", __func__);
+		stop_pcm(pcm);
+	}
+
+	mutex_unlock(&pcm->lock);
+	return ret;
+}
+
+static int msm_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_pcm_loopback *pcm = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+
+	mutex_lock(&pcm->lock);
+
+	dev_dbg(rtd->platform->dev, "%s: ASM loopback stream:%d\n",
+		__func__, substream->stream);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (!pcm->playback_start)
+			pcm->playback_start = 1;
+	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (!pcm->capture_start)
+			pcm->capture_start = 1;
+	}
+	mutex_unlock(&pcm->lock);
+
+	return ret;
+}
+
+static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_pcm_loopback *pcm = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		dev_dbg(rtd->platform->dev,
+			"%s: playback_start:%d,capture_start:%d\n", __func__,
+			pcm->playback_start, pcm->capture_start);
+		if (pcm->playback_start && pcm->capture_start)
+			q6asm_run_nowait(pcm->audio_client, 0, 0, 0);
+		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_STOP:
+		dev_dbg(rtd->platform->dev,
+			"%s:Pause/Stop - playback_start:%d,capture_start:%d\n",
+			__func__, pcm->playback_start, pcm->capture_start);
+		if (pcm->playback_start && pcm->capture_start)
+			q6asm_cmd_nowait(pcm->audio_client, CMD_PAUSE);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+
+	dev_dbg(rtd->platform->dev, "%s: ASM loopback\n", __func__);
+
+	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+		params_buffer_bytes(params));
+}
+
+static int msm_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static struct snd_pcm_ops msm_pcm_ops = {
+	.open           = msm_pcm_open,
+	.hw_params	= msm_pcm_hw_params,
+	.hw_free	= msm_pcm_hw_free,
+	.close          = msm_pcm_close,
+	.prepare        = msm_pcm_prepare,
+	.trigger        = msm_pcm_trigger,
+};
+
+
+static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_card *card = rtd->card->snd_card;
+	int ret = 0;
+
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+	return ret;
+}
+
+static struct snd_soc_platform_driver msm_soc_platform = {
+	.ops		= &msm_pcm_ops,
+	.pcm_new	= msm_asoc_pcm_new,
+};
+
+static __devinit int msm_pcm_probe(struct platform_device *pdev)
+{
+	struct msm_pcm_loopback *pcm;
+
+	dev_dbg(&pdev->dev, "%s: dev name %s\n",
+		__func__, dev_name(&pdev->dev));
+
+	pcm = kzalloc(sizeof(struct msm_pcm_loopback), GFP_KERNEL);
+	if (!pcm) {
+		dev_err(&pdev->dev, "%s Failed to allocate memory for pcm\n",
+			__func__);
+		return -ENOMEM;
+	} else {
+		mutex_init(&pcm->lock);
+		dev_set_drvdata(&pdev->dev, pcm);
+	}
+	return snd_soc_register_platform(&pdev->dev,
+				   &msm_soc_platform);
+}
+
+static int msm_pcm_remove(struct platform_device *pdev)
+{
+	struct msm_pcm_loopback *pcm;
+
+	pcm = dev_get_drvdata(&pdev->dev);
+	mutex_destroy(&pcm->lock);
+
+	snd_soc_unregister_platform(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver msm_pcm_driver = {
+	.driver = {
+		.name = "msm-pcm-loopback",
+		.owner = THIS_MODULE,
+	},
+	.probe = msm_pcm_probe,
+	.remove = __devexit_p(msm_pcm_remove),
+};
+
+static int __init msm_soc_platform_init(void)
+{
+	return platform_driver_register(&msm_pcm_driver);
+}
+module_init(msm_soc_platform_init);
+
+static void __exit msm_soc_platform_exit(void)
+{
+	platform_driver_unregister(&msm_pcm_driver);
+}
+module_exit(msm_soc_platform_exit);
+
+MODULE_DESCRIPTION("PCM loopback platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index e74a0dd..2c3c6df 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -658,6 +658,11 @@
 				msm_bedais[reg].sample_rate, channels,
 				DEFAULT_COPP_TOPOLOGY);
 
+			if (session_type == SESSION_TYPE_RX &&
+				fdai->event_info.event_func)
+					fdai->event_info.event_func(
+						MSM_PCM_RT_EVT_DEVSWITCH,
+						fdai->event_info.priv_data);
 
 			msm_pcm_routing_build_matrix(val,
 				fdai->strm_id, path_type);
@@ -976,10 +981,8 @@
 static int msm_routing_set_fm_vol_mixer(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	afe_loopback_gain(INT_FM_TX , ucontrol->value.integer.value[0]);
-
+	afe_loopback_gain(INT_FM_TX, ucontrol->value.integer.value[0]);
 	msm_route_fm_vol_control = ucontrol->value.integer.value[0];
-
 	return 0;
 }
 
@@ -1660,6 +1663,9 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
@@ -1696,6 +1702,9 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
@@ -1714,6 +1723,9 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
@@ -1810,6 +1822,12 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new mmul6_mixer_controls[] = {
+	SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -2715,6 +2733,7 @@
 	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
@@ -2828,6 +2847,8 @@
 	mmul4_mixer_controls, ARRAY_SIZE(mmul4_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia5 Mixer", SND_SOC_NOPM, 0, 0,
 	mmul5_mixer_controls, ARRAY_SIZE(mmul5_mixer_controls)),
+	SND_SOC_DAPM_MIXER("MultiMedia6 Mixer", SND_SOC_NOPM, 0, 0,
+	mmul6_mixer_controls, ARRAY_SIZE(mmul6_mixer_controls)),
 	SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -3008,6 +3029,7 @@
 	{"MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"MI2S_RX", NULL, "MI2S_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
@@ -3026,6 +3048,7 @@
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
 
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3040,12 +3063,14 @@
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"AFE_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia5 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"MultiMedia5 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+	{"MultiMedia6 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 
 	{"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"MultiMedia5 Mixer", "AFE_PCM_TX", "PCM_TX"},
@@ -3054,12 +3079,14 @@
 	{"MM_UL2", NULL, "MultiMedia2 Mixer"},
 	{"MM_UL4", NULL, "MultiMedia4 Mixer"},
 	{"MM_UL5", NULL, "MultiMedia5 Mixer"},
+	{"MM_UL6", NULL, "MultiMedia6 Mixer"},
 
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"AUX_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index c42e155..e25a44a 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -117,6 +117,7 @@
 
 enum msm_pcm_routing_event {
 	MSM_PCM_RT_EVT_BUF_RECFG,
+	MSM_PCM_RT_EVT_DEVSWITCH,
 	MSM_PCM_RT_EVT_MAX,
 };
 /* dai_id: front-end ID,
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 737317c..dd92e34 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -1143,6 +1143,22 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
 	},
+	{
+		.name = "MSM8960 FM",
+		.stream_name = "MultiMedia6",
+		.cpu_dai_name	= "MultiMedia6",
+		.platform_name  = "msm-pcm-loopback",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 7acb294..51334f2 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -75,6 +75,11 @@
 #define EXT_CLASS_D_DIS_DELAY 3000
 #define EXT_CLASS_D_DELAY_DELTA 2000
 
+/* It takes about 13ms for Class-AB PAs to ramp-up */
+#define EXT_CLASS_AB_EN_DELAY 10000
+#define EXT_CLASS_AB_DIS_DELAY 1000
+#define EXT_CLASS_AB_DELAY_DELTA 1000
+
 #define NUM_OF_AUXPCM_GPIOS 4
 
 static inline int param_is_mask(int p)
@@ -184,6 +189,8 @@
 static struct platform_device *spdev;
 static struct regulator *ext_spk_amp_regulator;
 static int ext_spk_amp_gpio = -1;
+static int ext_ult_spk_amp_gpio = -1;
+static int ext_ult_lo_amp_gpio = -1;
 static int msm8974_spk_control = 1;
 static int msm8974_ext_spk_pamp;
 static int msm_slim_0_rx_ch = 1;
@@ -231,9 +238,43 @@
 		}
 	}
 
+	ext_ult_spk_amp_gpio = of_get_named_gpio(spdev->dev.of_node,
+		"qcom,ext-ult-spk-amp-gpio", 0);
+
+	if (ext_ult_spk_amp_gpio >= 0) {
+		ret = gpio_request(ext_ult_spk_amp_gpio,
+						   "ext_ult_spk_amp_gpio");
+		if (ret) {
+			pr_err("%s: gpio_request failed for ext-ult_spk-amp-gpio.\n",
+				__func__);
+			return -EINVAL;
+		}
+		gpio_direction_output(ext_ult_spk_amp_gpio, 0);
+	}
+
 	return 0;
 }
 
+static void msm8974_liquid_ext_ult_spk_power_amp_enable(u32 on)
+{
+	if (on) {
+		regulator_enable(ext_spk_amp_regulator);
+		gpio_direction_output(ext_ult_spk_amp_gpio, 1);
+		/* time takes enable the external power class AB amplifier */
+		usleep_range(EXT_CLASS_AB_EN_DELAY,
+			     EXT_CLASS_AB_EN_DELAY + EXT_CLASS_AB_DELAY_DELTA);
+	} else {
+		gpio_direction_output(ext_ult_spk_amp_gpio, 0);
+		regulator_disable(ext_spk_amp_regulator);
+		/* time takes disable the external power class AB amplifier */
+		usleep_range(EXT_CLASS_AB_DIS_DELAY,
+			     EXT_CLASS_AB_DIS_DELAY + EXT_CLASS_AB_DELAY_DELTA);
+	}
+
+	pr_debug("%s: %s external ultrasound SPKR_DRV PAs.\n", __func__,
+			on ? "Enable" : "Disable");
+}
+
 static void msm8974_liquid_ext_spk_power_amp_enable(u32 on)
 {
 	if (on) {
@@ -287,7 +328,6 @@
 
 }
 
-
 static irqreturn_t msm8974_liquid_docking_irq_handler(int irq, void *dev)
 {
 	struct msm8974_liquid_dock_dev *dock_dev = dev;
@@ -351,41 +391,82 @@
 	return 0;
 }
 
-
-
-
-static void msm8974_ext_spk_power_amp_on(u32 spk)
+static int msm8974_liquid_ext_spk_power_amp_on(u32 spk)
 {
-	if (spk & (LO_1_SPK_AMP |
-		   LO_3_SPK_AMP |
-		   LO_2_SPK_AMP |
-		   LO_4_SPK_AMP)) {
+	int rc;
 
-		pr_debug("%s() External Left/Right Speakers already turned on. spk = 0x%08x\n",
-						__func__, spk);
+	if (spk & (LO_1_SPK_AMP | LO_3_SPK_AMP | LO_2_SPK_AMP | LO_4_SPK_AMP)) {
+		pr_debug("%s: External speakers are already on. spk = 0x%x\n",
+			 __func__, spk);
 
 		msm8974_ext_spk_pamp |= spk;
-
 		if ((msm8974_ext_spk_pamp & LO_1_SPK_AMP) &&
-			(msm8974_ext_spk_pamp & LO_3_SPK_AMP) &&
-			(msm8974_ext_spk_pamp & LO_2_SPK_AMP) &&
-			(msm8974_ext_spk_pamp & LO_4_SPK_AMP)) {
-
+		    (msm8974_ext_spk_pamp & LO_3_SPK_AMP) &&
+		    (msm8974_ext_spk_pamp & LO_2_SPK_AMP) &&
+		    (msm8974_ext_spk_pamp & LO_4_SPK_AMP))
 			if (ext_spk_amp_gpio >= 0 &&
-				msm8974_liquid_dock_dev != NULL &&
-				msm8974_liquid_dock_dev->dock_plug_det == 0)
+			    msm8974_liquid_dock_dev &&
+			    msm8974_liquid_dock_dev->dock_plug_det == 0)
 				msm8974_liquid_ext_spk_power_amp_enable(1);
-		}
+		rc = 0;
 	} else  {
+		pr_err("%s: Invalid external speaker ampl. spk = 0x%x\n",
+		       __func__, spk);
+		rc = -EINVAL;
+	}
 
-		pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
+	return rc;
+}
+
+static void msm8974_fluid_ext_us_amp_on(u32 spk)
+{
+	if (!gpio_is_valid(ext_ult_lo_amp_gpio)) {
+		pr_err("%s: ext_ult_lo_amp_gpio isn't configured\n", __func__);
+	} else if (spk & (LO_1_SPK_AMP | LO_3_SPK_AMP)) {
+		pr_debug("%s: External US amp is already on. spk = 0x%x\n",
+			 __func__, spk);
+		msm8974_ext_spk_pamp |= spk;
+		if ((msm8974_ext_spk_pamp & LO_1_SPK_AMP) &&
+		    (msm8974_ext_spk_pamp & LO_3_SPK_AMP))
+			pr_debug("%s: Turn on US amp. spk = 0x%x\n",
+				 __func__, spk);
+			gpio_direction_output(ext_ult_lo_amp_gpio, 1);
+
+	} else  {
+		pr_err("%s: Invalid external speaker ampl. spk = 0x%x\n",
 			__func__, spk);
-		return;
 	}
 }
 
-static void msm8974_ext_spk_power_amp_off(u32 spk)
+static void msm8974_fluid_ext_us_amp_off(u32 spk)
 {
+	if (!gpio_is_valid(ext_ult_lo_amp_gpio)) {
+		pr_err("%s: ext_ult_lo_amp_gpio isn't configured\n", __func__);
+	} else if (spk & (LO_1_SPK_AMP | LO_3_SPK_AMP)) {
+		pr_debug("%s LO1 and LO3. spk = 0x%x", __func__, spk);
+		if (!msm8974_ext_spk_pamp) {
+			pr_debug("%s: Turn off US amp. spk = 0x%x\n",
+				 __func__, spk);
+			gpio_direction_output(ext_ult_lo_amp_gpio, 0);
+			msm8974_ext_spk_pamp = 0;
+		}
+	} else  {
+		pr_err("%s: Invalid external speaker ampl. spk = 0x%x\n",
+			__func__, spk);
+	}
+}
+
+static void msm8974_ext_spk_power_amp_on(u32 spk)
+{
+	if (gpio_is_valid(ext_spk_amp_gpio))
+		msm8974_liquid_ext_spk_power_amp_on(spk);
+	else if (gpio_is_valid(ext_ult_lo_amp_gpio))
+		msm8974_fluid_ext_us_amp_on(spk);
+}
+
+static void msm8974_liquid_ext_spk_power_amp_off(u32 spk)
+{
+
 	if (spk & (LO_1_SPK_AMP |
 		   LO_3_SPK_AMP |
 		   LO_2_SPK_AMP |
@@ -410,6 +491,14 @@
 	}
 }
 
+static void msm8974_ext_spk_power_amp_off(u32 spk)
+{
+	if (gpio_is_valid(ext_spk_amp_gpio))
+		msm8974_liquid_ext_spk_power_amp_off(spk);
+	else if (gpio_is_valid(ext_ult_lo_amp_gpio))
+		msm8974_fluid_ext_us_amp_off(spk);
+}
+
 static void msm8974_ext_control(struct snd_soc_codec *codec)
 {
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
@@ -495,6 +584,33 @@
 
 }
 
+static int msm_ext_spkramp_ultrasound_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *k, int event)
+{
+
+	pr_debug("%s()\n", __func__);
+
+	if (!strncmp(w->name, "SPK_ultrasound amp", 19)) {
+		if (!gpio_is_valid(ext_ult_spk_amp_gpio)) {
+			pr_err("%s: ext_ult_spk_amp_gpio isn't configured\n",
+				__func__);
+			return -EINVAL;
+		}
+
+		if (SND_SOC_DAPM_EVENT_ON(event))
+			msm8974_liquid_ext_ult_spk_power_amp_enable(1);
+		else
+			msm8974_liquid_ext_ult_spk_power_amp_enable(0);
+
+	} else {
+			pr_err("%s() Invalid Speaker Widget = %s\n",
+					__func__, w->name);
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
 					bool dapm)
 {
@@ -567,6 +683,8 @@
 
 	SND_SOC_DAPM_SPK("Lineout_2 amp", msm_ext_spkramp_event),
 	SND_SOC_DAPM_SPK("Lineout_4 amp", msm_ext_spkramp_event),
+	SND_SOC_DAPM_SPK("SPK_ultrasound amp",
+					 msm_ext_spkramp_ultrasound_event),
 
 	SND_SOC_DAPM_MIC("Handset Mic", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
@@ -1306,7 +1424,26 @@
 			__func__, err);
 		goto out;
 	}
-
+	config_data = taiko_get_afe_config(codec,
+				AFE_CDC_CLIP_REGISTERS_CONFIG);
+	if (config_data) {
+		err = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
+					config_data, 0);
+		if (err) {
+			pr_err("%s: Failed to set clip registers %d\n",
+				__func__, err);
+			return err;
+		}
+	}
+	config_data = taiko_get_afe_config(codec, AFE_CLIP_BANK_SEL);
+	if (config_data) {
+		err = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0);
+		if (err) {
+			pr_err("%s: Failed to set AFE bank selection %d\n",
+				__func__, err);
+			return err;
+		}
+	}
 	/* start mbhc */
 	mbhc_cfg.calibration = def_taiko_mbhc_cal();
 	if (mbhc_cfg.calibration) {
@@ -2272,6 +2409,7 @@
 	struct msm8974_asoc_mach_data *pdata;
 	int ret;
 	const char *auxpcm_pri_gpio_set = NULL;
+	const char *prop_name_ult_lo_gpio = "qcom,ext-ult-lo-amp-gpio";
 
 	if (!pdev->dev.of_node) {
 		dev_err(&pdev->dev, "No platform supplied from device tree\n");
@@ -2343,9 +2481,26 @@
 		goto err;
 	}
 
+	ext_ult_lo_amp_gpio = of_get_named_gpio(pdev->dev.of_node,
+						prop_name_ult_lo_gpio, 0);
+	if (!gpio_is_valid(ext_ult_lo_amp_gpio)) {
+		dev_dbg(&pdev->dev,
+			"Couldn't find %s property in node %s, %d\n",
+			prop_name_ult_lo_gpio, pdev->dev.of_node->full_name,
+			ext_ult_lo_amp_gpio);
+	} else {
+		ret = gpio_request(ext_ult_lo_amp_gpio, "US_AMP_GPIO");
+		if (ret) {
+			dev_err(card->dev,
+				"%s: Failed to request US amp gpio %d\n",
+				__func__, ext_ult_lo_amp_gpio);
+			goto err;
+		}
+	}
+
 	ret = msm8974_prepare_codec_mclk(card);
 	if (ret)
-		goto err;
+		goto err1;
 
 	if (of_property_read_bool(pdev->dev.of_node, "qcom,hdmi-audio-rx")) {
 		dev_info(&pdev->dev, "%s(): hdmi audio support present\n",
@@ -2394,7 +2549,7 @@
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
 			ret);
-		goto err;
+		goto err1;
 	}
 
 	ret = of_property_read_string(pdev->dev.of_node,
@@ -2403,7 +2558,7 @@
 		dev_err(&pdev->dev, "Looking up %s property in node %s failed",
 			"qcom,prim-auxpcm-gpio-set",
 			pdev->dev.of_node->full_name);
-		goto err;
+		goto err1;
 	}
 	if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-prim")) {
 		lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
@@ -2413,20 +2568,24 @@
 		dev_err(&pdev->dev, "Invalid value %s for AUXPCM GPIO set\n",
 			auxpcm_pri_gpio_set);
 		ret = -EINVAL;
-		goto err;
+		goto err1;
 	}
 	if (lpaif_pri_muxsel_virt_addr == NULL) {
 		pr_err("%s Pri muxsel virt addr is null\n", __func__);
 		ret = -EINVAL;
-		goto err;
+		goto err1;
 	}
 	lpaif_sec_muxsel_virt_addr = ioremap(LPAIF_SEC_MODE_MUXSEL, 4);
 	if (lpaif_sec_muxsel_virt_addr == NULL) {
 		pr_err("%s Sec muxsel virt addr is null\n", __func__);
 		ret = -EINVAL;
-		goto err;
+		goto err1;
 	}
 	return 0;
+
+err1:
+	gpio_free(ext_ult_lo_amp_gpio);
+	ext_ult_lo_amp_gpio = -1;
 err:
 	if (pdata->mclk_gpio > 0) {
 		dev_dbg(&pdev->dev, "%s free gpio %d\n",
@@ -2452,9 +2611,15 @@
 	if (ext_spk_amp_regulator)
 		regulator_put(ext_spk_amp_regulator);
 
+	if (gpio_is_valid(ext_ult_spk_amp_gpio))
+		gpio_free(ext_ult_spk_amp_gpio);
+
+	if (gpio_is_valid(ext_ult_lo_amp_gpio))
+		gpio_free(ext_ult_lo_amp_gpio);
+
 	gpio_free(pdata->mclk_gpio);
 	gpio_free(pdata->us_euro_gpio);
-	if (ext_spk_amp_gpio >= 0)
+	if (gpio_is_valid(ext_spk_amp_gpio))
 		gpio_free(ext_spk_amp_gpio);
 
 	if (msm8974_liquid_dock_dev != NULL) {
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index 4dd85fc..4db3ea5 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/qpnp/clkdiv.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
@@ -26,8 +27,196 @@
 #include <asm/mach-types.h>
 #include <mach/socinfo.h>
 #include <qdsp6v2/msm-pcm-routing-v2.h>
+#include <sound/q6afe-v2.h>
 #include <linux/module.h>
+#include "../codecs/msm8x10-wcd.h"
 #define DRV_NAME "msm8x10-asoc-wcd"
+#define BTSCO_RATE_8KHZ 8000
+#define BTSCO_RATE_16KHZ 16000
+
+static int msm_btsco_rate = BTSCO_RATE_8KHZ;
+static int msm_btsco_ch = 1;
+
+static int msm_proxy_rx_ch = 2;
+
+#define MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL	0xFE03B004
+#define MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR			0xFE02C000
+#define MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR			0xFE02C004
+#define MSM8X10_DINO_LPASS_DIGCODEC_M				0xFE02C008
+#define MSM8X10_DINO_LPASS_DIGCODEC_N				0xFE02C00C
+#define MSM8X10_DINO_LPASS_DIGCODEC_D				0xFE02C010
+#define MSM8X10_DINO_LPASS_DIGCODEC_CBCR			0xFE02C014
+#define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR			0xFE02C018
+
+/*
+ * There is limitation for the clock root selection from
+ * either MI2S or DIG_CODEC.
+ * If DIG_CODEC root can only provide 9.6MHz clock
+ * to codec while MI2S only can provide
+ * 12.288MHz.
+ */
+enum {
+	DIG_CDC_CLK_SEL_DIG_CODEC,
+	DIG_CDC_CLK_SEL_PRI_MI2S,
+	DIG_CDC_CLK_SEL_SEC_MI2S,
+};
+
+static struct afe_clk_cfg mi2s_rx_clk = {
+	AFE_API_VERSION_I2S_CONFIG,
+	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+	Q6AFE_LPASS_OSR_CLK_12_P288_MHZ,
+	Q6AFE_LPASS_CLK_SRC_INTERNAL,
+	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+	Q6AFE_LPASS_MODE_BOTH_VALID,
+	0,
+};
+
+static struct afe_clk_cfg mi2s_tx_clk = {
+	AFE_API_VERSION_I2S_CONFIG,
+	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+	Q6AFE_LPASS_OSR_CLK_12_P288_MHZ,
+	Q6AFE_LPASS_CLK_SRC_INTERNAL,
+	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+	Q6AFE_LPASS_MODE_BOTH_VALID,
+	0,
+};
+
+static struct afe_digital_clk_cfg digital_cdc_clk = {
+	AFE_API_VERSION_I2S_CONFIG,
+	9600000,
+	5,  /* Digital Codec root */
+	0,
+};
+
+static atomic_t aud_init_rsc_ref;
+
+static int msm8x10_mclk_event(struct snd_soc_dapm_widget *w,
+			      struct snd_kcontrol *kcontrol, int event);
+
+static const struct snd_soc_dapm_route msm8x10_common_audio_map[] = {
+	{"RX_BIAS", NULL, "MCLK"},
+	{"INT_LDO_H", NULL, "MCLK"},
+	{"MIC BIAS External", NULL, "Handset Mic"},
+	{"MIC BIAS Internal2", NULL, "Headset Mic"},
+	{"AMIC1", NULL, "MIC BIAS External"},
+	{"AMIC2", NULL, "MIC BIAS Internal2"},
+
+};
+
+static const struct snd_soc_dapm_widget msm8x10_dapm_widgets[] = {
+
+	SND_SOC_DAPM_SUPPLY("MCLK",  SND_SOC_NOPM, 0, 0,
+	msm8x10_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIC("Handset Mic", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+
+};
+
+/*
+ * This function will be replaced by
+ * afe_set_lpass_internal_digital_codec_clock(port_id, cfg)
+ * in the future after LPASS API fix
+ */
+static int msm_enable_lpass_mclk(void)
+{
+	/* Select the codec root */
+	iowrite32(DIG_CDC_CLK_SEL_DIG_CODEC,
+		  ioremap(MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL,
+		  4));
+	/* Div-2 */
+	iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
+	/* Digital codec clock enable */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
+	/* AHB clock enable */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR, 4));
+	/* Set the update bit to make the settings go through */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
+
+	return 0;
+}
+
+static int msm_enable_mclk_root(u16 port_id, struct afe_digital_clk_cfg *cfg)
+{
+	int ret = 0;
+	/*
+	  * msm_enable_lpass_mclk() function call will be replaced by
+	  * ret =  afe_set_lpass_internal_digital_codec_clock(port_id, cfg)
+	  * in the future. Currentlt there is a bug in LPASS plan which
+	  * doesn't consider the digital codec clock. It will be fixed soon
+	  * in new Q6 image
+	  */
+	msm_enable_lpass_mclk();
+	pr_debug("%s(): return = %d\n", __func__, ret);
+	return ret;
+}
+
+static int msm_config_mclk(u16 port_id, struct afe_digital_clk_cfg *cfg)
+{
+	/* Select the codec root */
+	iowrite32(DIG_CDC_CLK_SEL_DIG_CODEC,
+		  ioremap(MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL,
+		  4));
+	/* Div-2 */
+	iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
+	/* Digital codec clock enable */
+	if (cfg->clk_val == 0) {
+		iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
+		pr_debug("%s(line %d)\n", __func__, __LINE__);
+	} else {
+		iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
+		pr_debug("%s(line %d)\n", __func__, __LINE__);
+	}
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
+	/* AHB clock enable */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR, 4));
+	/* Set the update bit to make the settings go through */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
+
+	return 0;
+
+}
+
+static int msm_config_mi2s_clk(int enable)
+{
+	int ret = 0;
+	pr_debug("%s(line %d):enable = %x\n", __func__, __LINE__, enable);
+	if (enable) {
+		digital_cdc_clk.clk_val = 9600000;
+		mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
+		mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
+		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
+					  &mi2s_rx_clk);
+		mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
+		mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
+		ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
+					  &mi2s_tx_clk);
+		if (ret < 0)
+			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
+
+	} else {
+		digital_cdc_clk.clk_val = 0;
+		mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
+		mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
+		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
+					  &mi2s_rx_clk);
+		mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
+		mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
+		ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
+					  &mi2s_tx_clk);
+		if (ret < 0)
+			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
+
+	}
+	ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX, &digital_cdc_clk);
+	return ret;
+}
+
 
 static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 				struct snd_pcm_hw_params *params)
@@ -41,13 +230,22 @@
 	return 0;
 }
 
-static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
+static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
 {
-	pr_info("%s(), dev_name%s\n", __func__, dev_name(rtd->cpu_dai->dev));
+	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);
+
+	rate->min = rate->max = msm_btsco_rate;
+	channels->min = channels->max = msm_btsco_ch;
+
 	return 0;
 }
 
-static int msm_snd_hw_params(struct snd_pcm_substream *substream,
+static int msm_mi2s_snd_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *params)
 {
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
@@ -55,34 +253,184 @@
 	return 0;
 }
 
-static int msm_snd_startup(struct snd_pcm_substream *substream)
+static int mi2s_clk_ctl(struct snd_pcm_substream *substream, bool enable)
 {
+	int ret = 0;
+	if (enable) {
+		digital_cdc_clk.clk_val = 9600000;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
+			mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
+			ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
+						  &mi2s_rx_clk);
+		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+			mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
+			mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
+			ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
+						  &mi2s_tx_clk);
+		} else
+			pr_err("%s:Not valid substream.\n", __func__);
+
+		if (ret < 0)
+			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
+
+	} else {
+		digital_cdc_clk.clk_val = 0;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
+			mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
+			ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
+						  &mi2s_rx_clk);
+		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+			mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
+			mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
+			ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
+						  &mi2s_tx_clk);
+		} else
+			pr_err("%s:Not valid substream.\n", __func__);
+
+		if (ret < 0)
+			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
+
+	}
+	ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX, &digital_cdc_clk);
+	return ret;
+}
+
+static int msm8x10_enable_codec_ext_clk(struct snd_soc_codec *codec,
+					int enable, bool dapm)
+{
+	int ret = 0;
+
+	pr_debug("%s: enable = %d  codec name %s enable %x\n",
+		   __func__, enable, codec->name, enable);
+	if (enable) {
+		digital_cdc_clk.clk_val = 9600000;
+		msm_config_mi2s_clk(1);
+		ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
+					   &digital_cdc_clk);
+		msm8x10_wcd_mclk_enable(codec, 1, dapm);
+	} else {
+		msm8x10_wcd_mclk_enable(codec, 0, dapm);
+		ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
+					   &digital_cdc_clk);
+		msm_config_mi2s_clk(0);
+	}
+	return ret;
+}
+
+static int msm8x10_mclk_event(struct snd_soc_dapm_widget *w,
+			      struct snd_kcontrol *kcontrol, int event)
+{
+	pr_debug("%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		return msm8x10_enable_codec_ext_clk(w->codec, 1, true);
+	case SND_SOC_DAPM_POST_PMD:
+		return msm8x10_enable_codec_ext_clk(w->codec, 0, true);
+	default:
+		return -EINVAL;
+	}
+}
+
+static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	int ret;
+
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
 		 substream->name, substream->stream);
+	ret = mi2s_clk_ctl(substream, false);
+	if (ret < 0)
+		pr_err("%s:clock disable failed\n", __func__);
+}
+
+static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+
+	ret = mi2s_clk_ctl(substream, true);
+
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		pr_err("set fmt cpu dai failed\n");
+
+	return ret;
+}
+
+static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+
+	pr_debug("%s(),dev_name%s\n", __func__, dev_name(cpu_dai->dev));
+
+	pr_debug("%s(): aud_init_rsc_ref counter = %d\n",
+		__func__, atomic_read(&aud_init_rsc_ref));
+	if (atomic_inc_return(&aud_init_rsc_ref) != 1)
+		goto exit;
+
+	snd_soc_dapm_new_controls(dapm, msm8x10_dapm_widgets,
+				ARRAY_SIZE(msm8x10_dapm_widgets));
+
+	snd_soc_dapm_add_routes(dapm, msm8x10_common_audio_map,
+		ARRAY_SIZE(msm8x10_common_audio_map));
+
+	snd_soc_dapm_sync(dapm);
+	ret =  msm_enable_mclk_root(AFE_PORT_ID_SECONDARY_MI2S_RX,
+				    &digital_cdc_clk);
+exit:
+	return ret;
+}
+
+static int msm_proxy_rx_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: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
+
+	if (channels->max < 2)
+		channels->min = channels->max = 2;
+	channels->min = channels->max = msm_proxy_rx_ch;
+	rate->min = rate->max = 48000;
 	return 0;
 }
 
-
-static void msm_snd_shutdown(struct snd_pcm_substream *substream)
+static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
 {
-	pr_debug("%s(): substream = %s stream = %d\n", __func__,
-		 substream->name, substream->stream);
-}
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
 
-static struct snd_soc_ops msm8x10_be_ops = {
-	.startup = msm_snd_startup,
-	.hw_params = msm_snd_hw_params,
-	.shutdown = msm_snd_shutdown,
+	rate->min = rate->max = 48000;
+	return 0;
+}
+static struct snd_soc_ops msm8x10_mi2s_be_ops = {
+	.startup = msm_mi2s_snd_startup,
+	.hw_params = msm_mi2s_snd_hw_params,
+	.shutdown = msm_mi2s_snd_shutdown,
 };
 
 /* Digital audio interface glue - connects codec <---> CPU */
 static struct snd_soc_dai_link msm8x10_dai[] = {
 	/* FrontEnd DAI Links */
-	{
+	{/* hw:x,0 */
 		.name = "MSM8X10 Media1",
 		.stream_name = "MultiMedia1",
 		.cpu_dai_name	= "MultiMedia1",
-		.platform_name  = "msm-pcm-dsp",
+		.platform_name  = "msm-pcm-dsp.0",
 		.dynamic = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 			SND_SOC_DPCM_TRIGGER_POST},
@@ -93,11 +441,11 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
 	},
-	{
+	{/* hw:x,1 */
 		.name = "MSM8X10 Media2",
 		.stream_name = "MultiMedia2",
 		.cpu_dai_name   = "MultiMedia2",
-		.platform_name  = "msm-pcm-dsp",
+		.platform_name  = "msm-pcm-dsp.0",
 		.dynamic = 1,
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
@@ -108,31 +456,308 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
 	},
+	{/* hw:x,2 */
+		.name = "Circuit-Switch Voice",
+		.stream_name = "CS-Voice",
+		.cpu_dai_name   = "CS-VOICE",
+		.platform_name  = "msm-pcm-voice",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_CS_VOICE,
+	},
+	{/* hw:x,3 */
+		.name = "MSM VoIP",
+		.stream_name = "VoIP",
+		.cpu_dai_name	= "VoIP",
+		.platform_name  = "msm-voip-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_VOIP,
+	},
+	{/* hw:x,4 */
+		.name = "MSM8X10 LPA",
+		.stream_name = "LPA",
+		.cpu_dai_name	= "MultiMedia3",
+		.platform_name  = "msm-pcm-lpa",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+	},
+	/* Hostless PCM purpose */
+	{/* hw:x,5 */
+		.name = "Secondary MI2S RX Hostless",
+		.stream_name = "Secondary MI2S_RX Hostless Playback",
+		.cpu_dai_name = "SEC_MI2S_RX_HOSTLESS",
+		.platform_name	= "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* This dainlink has MI2S support */
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,6 */
+		.name = "INT_FM Hostless",
+		.stream_name = "INT_FM Hostless",
+		.cpu_dai_name	= "INT_FM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,7 */
+		.name = "MSM AFE-PCM RX",
+		.stream_name = "AFE-PROXY RX",
+		.cpu_dai_name = "msm-dai-q6-dev.241",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{/* hw:x,8 */
+		.name = "MSM AFE-PCM TX",
+		.stream_name = "AFE-PROXY TX",
+		.cpu_dai_name = "msm-dai-q6-dev.240",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+	},
+	{/* hw:x,9 */
+		.name = "MSM8X10 Compr",
+		.stream_name = "COMPR",
+		.cpu_dai_name	= "MultiMedia4",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+	},
+	{/* hw:x,10 */
+		.name = "AUXPCM Hostless",
+		.stream_name = "AUXPCM Hostless",
+		.cpu_dai_name   = "AUXPCM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,11 */
+		.name = "Primary MI2S TX Hostless",
+		.stream_name = "Primary MI2S_TX Hostless Capture",
+		.cpu_dai_name = "PRI_MI2S_TX_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* This dainlink has MI2S support */
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,12 */
+		.name = "MSM8x10 LowLatency",
+		.stream_name = "MultiMedia5",
+		.cpu_dai_name   = "MultiMedia5",
+		.platform_name  = "msm-pcm-dsp.1",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+	},
 	/* Backend I2S DAI Links */
 	{
-		.name = LPASS_BE_MI2S_RX,
-		.stream_name = "Primary MI2S Playback",
-		.cpu_dai_name = "msm-dai-q6-mi2s.0",
-		.platform_name = "msm-pcm-routing",
-		.codec_name     = "msm8x10-wcd-i2c-core.1-000d",
-		.codec_dai_name = "msm8x10_wcd_i2s_rx1",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_MI2S_RX,
-		.init = &msm_audrx_init,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ops = &msm8x10_be_ops,
-	},
-	{
-		.name = LPASS_BE_SEC_MI2S_TX,
-		.stream_name = "Secondary MI2S Capture",
+		.name = LPASS_BE_SEC_MI2S_RX,
+		.stream_name = "Secondary MI2S Playback",
 		.cpu_dai_name = "msm-dai-q6-mi2s.1",
 		.platform_name = "msm-pcm-routing",
-		.codec_name     = "msm8x10-wcd-i2c-core.1-000d",
+		.codec_name     = "msm8x10-wcd-i2c-core.5-000d",
+		.codec_dai_name = "msm8x10_wcd_i2s_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+		.init = &msm_audrx_init,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm8x10_mi2s_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_PRI_MI2S_TX,
+		.stream_name = "Primary MI2S Capture",
+		.cpu_dai_name = "msm-dai-q6-mi2s.0",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm8x10-wcd-i2c-core.5-000d",
 		.codec_dai_name = "msm8x10_wcd_i2s_tx1",
 		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
+		.be_id = MSM_BACKEND_DAI_PRI_MI2S_TX,
+		.init = &msm_audrx_init,
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
-		.ops = &msm8x10_be_ops,
+		.ops = &msm8x10_mi2s_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_INT_BT_SCO_RX,
+		.stream_name = "Internal BT-SCO Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.12288",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name	= "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
+		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_INT_BT_SCO_TX,
+		.stream_name = "Internal BT-SCO Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.12289",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name	= "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
+		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_INT_FM_RX,
+		.stream_name = "Internal FM Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.12292",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_FM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_INT_FM_TX,
+		.stream_name = "Internal FM Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.12293",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_FM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_AFE_PCM_RX,
+		.stream_name = "AFE Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.224",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+		.be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_AFE_PCM_TX,
+		.stream_name = "AFE Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.225",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+		.be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Record Uplink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_TX,
+		.stream_name = "Voice Uplink Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.32772",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Record Downlink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_RX,
+		.stream_name = "Voice Downlink Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.32771",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Music BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE_PLAYBACK_TX,
+		.stream_name = "Voice Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32773",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
 	},
 };
 
@@ -165,6 +790,8 @@
 		goto err;
 	}
 
+	atomic_set(&aud_init_rsc_ref, 0);
+
 	return 0;
 err:
 	return ret;
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index f15f4d1..659d5a2 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -912,6 +912,7 @@
 		case ASM_STREAM_CMD_OPEN_WRITE:
 		case ASM_STREAM_CMD_OPEN_WRITE_V2_1:
 		case ASM_STREAM_CMD_OPEN_READWRITE:
+		case ASM_STREAM_CMD_OPEN_LOOPBACK:
 		case ASM_DATA_CMD_MEDIA_FORMAT_UPDATE:
 		case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
 		case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
@@ -1852,6 +1853,45 @@
 	return -EINVAL;
 }
 
+int q6asm_open_loopack(struct audio_client *ac)
+{
+	int rc = 0x00;
+	struct asm_stream_cmd_open_loopback open;
+
+	if ((ac == NULL) || (ac->apr == NULL)) {
+		pr_err("APR handle NULL\n");
+		return -EINVAL;
+	}
+	pr_debug("%s: session[%d]", __func__, ac->session);
+
+	q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
+	open.hdr.opcode = ASM_STREAM_CMD_OPEN_LOOPBACK;
+
+	open.mode_flags = 0;
+	open.src_endpointype = 0;
+	open.sink_endpointype = 0;
+	/* source endpoint : matrix */
+	open.postprocopo_id = get_asm_topology();
+	if (open.postprocopo_id == 0)
+		open.postprocopo_id = DEFAULT_POPP_TOPOLOGY;
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
+	if (rc < 0) {
+		pr_err("open failed op[0x%x]rc[%d]\n", \
+						open.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("timeout. waited for OPEN_WRITE rc[%d]\n", rc);
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return -EINVAL;
+}
+
 int q6asm_run(struct audio_client *ac, uint32_t flags,
 		uint32_t msw_ts, uint32_t lsw_ts)
 {
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 8bb3eaf..7d9cc16 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -190,8 +190,8 @@
 
 	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX
 			|| dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
-		rx_port = PCM_RX;
-		tx_port = PCM_TX;
+		rx_port = AFE_PORT_ID_PRIMARY_PCM_RX;
+		tx_port = AFE_PORT_ID_PRIMARY_PCM_TX;
 	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX
 			|| dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
 		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
@@ -295,8 +295,8 @@
 
 	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
 			dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
-		rx_port = PCM_RX;
-		tx_port = PCM_TX;
+		rx_port = AFE_PORT_ID_PRIMARY_PCM_RX;
+		tx_port = AFE_PORT_ID_PRIMARY_PCM_TX;
 	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
 			dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
 		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
@@ -420,8 +420,8 @@
 
 	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
 			dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
-		rx_port = PCM_RX;
-		tx_port = PCM_TX;
+		rx_port = AFE_PORT_ID_PRIMARY_PCM_RX;
+		tx_port = AFE_PORT_ID_PRIMARY_PCM_TX;
 	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
 			dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
 		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
index f77ec0f..e6934f6 100644
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -437,7 +437,8 @@
 	if (device == DEVICE_OUT_ALL) {
 		port_id = PRIMARY_I2S_RX | SLIMBUS_0_RX | HDMI_RX |
 				INT_BT_SCO_RX | INT_FM_RX |
-				RT_PROXY_PORT_001_RX | PCM_RX |
+				RT_PROXY_PORT_001_RX |
+				AFE_PORT_ID_PRIMARY_PCM_RX |
 				MI2S_RX | SECONDARY_I2S_RX |
 				SLIMBUS_1_RX | SLIMBUS_4_RX | SLIMBUS_3_RX |
 				AFE_PORT_ID_SECONDARY_MI2S_RX;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 717e63b..9fbf749 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -420,6 +420,12 @@
 	}
 
 	data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size, &idx);
+	if (size < fbytes) {
+		pr_err("%s: size mismatch error size %d fbytes %d\n",
+		__func__ , size , fbytes);
+		ret = -EFAULT;
+		goto fail;
+	}
 	bufptr = data;
 	if (bufptr) {
 		pr_debug("%s:fbytes =%d: xfer=%d size=%d\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index c651ec7..b5f1b6d 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -213,8 +213,8 @@
 	{ INT_FM_TX, 0, 0, 0, 0, 0},
 	{ RT_PROXY_PORT_001_RX, 0, 0, 0, 0, 0},
 	{ RT_PROXY_PORT_001_TX, 0, 0, 0, 0, 0},
-	{ PCM_RX, 0, 0, 0, 0, 0},
-	{ PCM_TX, 0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, 0, 0, 0},
 	{ VOICE_PLAYBACK_TX, 0, 0, 0, 0, 0},
 	{ VOICE_RECORD_RX, 0, 0, 0, 0, 0},
 	{ VOICE_RECORD_TX, 0, 0, 0, 0, 0},
@@ -1406,6 +1406,9 @@
 	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = {
@@ -1421,6 +1424,18 @@
 	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
+static const struct snd_kcontrol_new mi2s_hl_mixer_controls[] = {
+	SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 
 static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = {
@@ -1436,6 +1451,9 @@
 	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PRI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
@@ -1571,6 +1589,9 @@
 	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
+		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+		msm_routing_put_audio_mixer),
 	SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
@@ -1646,6 +1667,9 @@
 	SOC_SINGLE_EXT("SEC_AUX_PCM_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
@@ -2426,15 +2450,21 @@
 			__func__, e->shift_l , e->values[item]);
 		if (e->shift_l < MSM_BACKEND_DAI_MAX &&
 			e->values[item] < MSM_BACKEND_DAI_MAX)
+			/* Enable feedback TX path */
 			ret = afe_spk_prot_feed_back_cfg(
 			   msm_bedais[e->values[item]].port_id,
-			   msm_bedais[e->shift_l].port_id, 1, 0);
+			   msm_bedais[e->shift_l].port_id, 1, 0, 1);
 		else {
-			pr_err("%s values are out of range\n", __func__);
-			ret = -EINVAL;
+			pr_debug("%s values are out of range item %d\n",
+			__func__, e->values[item]);
+			/* Disable feedback TX path */
+			if (e->values[item] == MSM_BACKEND_DAI_MAX)
+				ret = afe_spk_prot_feed_back_cfg(0, 0, 0, 0, 0);
+			else
+				ret = -EINVAL;
 		}
 	} else {
-		pr_err("%s item value is out of range\n", __func__);
+		pr_err("%s item value is out of range item\n", __func__);
 		ret = -EINVAL;
 	}
 	mutex_unlock(&routing_lock);
@@ -2449,11 +2479,11 @@
 }
 
 static const char * const slim0_rx_vi_fb_tx_lch_mux_text[] = {
-	"SLIM4_TX",
+	"ZERO", "SLIM4_TX"
 };
 
 static const int const slim0_rx_vi_fb_tx_lch_value[] = {
-	MSM_BACKEND_DAI_SLIMBUS_4_TX,
+	MSM_BACKEND_DAI_MAX, MSM_BACKEND_DAI_SLIMBUS_4_TX
 };
 static const struct soc_enum slim0_rx_vi_fb_lch_mux_enum =
 	SOC_VALUE_ENUM_DOUBLE(0, MSM_BACKEND_DAI_SLIMBUS_0_RX, 0, 0,
@@ -2510,12 +2540,19 @@
 	SND_SOC_DAPM_AIF_IN("HDMI_DL_HL", "HDMI_HOSTLESS Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SEC_I2S_DL_HL", "SEC_I2S_RX_HOSTLESS Playback",
 		0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SEC_MI2S_DL_HL",
+		"Secondary MI2S_RX Hostless Playback",
+		0, 0, 0, 0),
+
 	SND_SOC_DAPM_AIF_IN("AUXPCM_DL_HL", "AUXPCM_HOSTLESS Playback",
 		0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("AUXPCM_UL_HL", "AUXPCM_HOSTLESS Capture",
 		0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MI2S_UL_HL", "MI2S_TX_HOSTLESS Capture",
 		0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("PRI_MI2S_UL_HL",
+		"Primary MI2S_TX Hostless Capture",
+		0, 0, 0, 0),
 
 	SND_SOC_DAPM_AIF_OUT("MI2S_DL_HL", "MI2S_RX_HOSTLESS Playback",
 		0, 0, 0, 0),
@@ -2543,6 +2580,8 @@
 	SND_SOC_DAPM_AIF_IN("MI2S_TX", "MI2S Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture",
 						0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("PRI_MI2S_TX", "Primary MI2S Capture",
+			    0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture",
 			    0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
@@ -2621,6 +2660,9 @@
 	SND_SOC_DAPM_MIXER("SEC_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 			   secondary_mi2s_rx_mixer_controls,
 			   ARRAY_SIZE(secondary_mi2s_rx_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0,
+			   mi2s_hl_mixer_controls,
+			   ARRAY_SIZE(mi2s_hl_mixer_controls)),
 	SND_SOC_DAPM_MIXER("PRI_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 			   primary_mi2s_rx_mixer_controls,
 			   ARRAY_SIZE(primary_mi2s_rx_mixer_controls)),
@@ -2799,6 +2841,7 @@
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
 	{"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Audio Mixer"},
 
 
@@ -2806,17 +2849,23 @@
 	{"SEC_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"SEC_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"SEC_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"SEC_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
 	{"SEC_MI2S_RX", NULL, "SEC_MI2S_RX Audio Mixer"},
 
+	{"SEC_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+	{"SEC_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"PRI_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
 	{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
 	{"MultiMedia1 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
+	{"MultiMedia5 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia1 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
 	{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
@@ -2825,6 +2874,7 @@
 	{"MultiMedia5 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
 	{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
+	{"MultiMedia1 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -3008,6 +3058,9 @@
 	{"PCM_RX", NULL, "PCM_RX_DL_HL"},
 	{"MI2S_UL_HL", NULL, "MI2S_TX"},
 	{"SEC_I2S_RX", NULL, "SEC_I2S_DL_HL"},
+	{"PRI_MI2S_UL_HL", NULL, "PRI_MI2S_TX"},
+	{"SEC_MI2S_RX", NULL, "SEC_MI2S_DL_HL"},
+
 	{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
@@ -3081,30 +3134,31 @@
 	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
 	{"BE_OUT", NULL, "AUX_PCM_RX"},
 	{"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
+	{"BE_OUT", NULL, "INT_BT_SCO_RX"},
+	{"BE_OUT", NULL, "INT_FM_RX"},
+	{"BE_OUT", NULL, "PCM_RX"},
+	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
+	{"BE_OUT", NULL, "AUX_PCM_RX"},
+	{"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
+	{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"},
 
 	{"PRI_I2S_TX", NULL, "BE_IN"},
 	{"MI2S_TX", NULL, "BE_IN"},
 	{"QUAT_MI2S_TX", NULL, "BE_IN"},
+	{"PRI_MI2S_TX", NULL, "BE_IN"},
 	{"SEC_MI2S_TX", NULL, "BE_IN"},
 	{"SLIMBUS_0_TX", NULL, "BE_IN" },
 	{"SLIMBUS_1_TX", NULL, "BE_IN" },
 	{"SLIMBUS_3_TX", NULL, "BE_IN" },
 	{"SLIMBUS_4_TX", NULL, "BE_IN" },
 	{"SLIMBUS_5_TX", NULL, "BE_IN" },
-	{"BE_OUT", NULL, "INT_BT_SCO_RX"},
 	{"INT_BT_SCO_TX", NULL, "BE_IN"},
-	{"BE_OUT", NULL, "INT_FM_RX"},
 	{"INT_FM_TX", NULL, "BE_IN"},
-	{"BE_OUT", NULL, "PCM_RX"},
 	{"PCM_TX", NULL, "BE_IN"},
-	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
-	{"BE_OUT", NULL, "AUX_PCM_RX"},
 	{"AUX_PCM_TX", NULL, "BE_IN"},
-	{"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
 	{"SEC_AUX_PCM_TX", NULL, "BE_IN"},
 	{"INCALL_RECORD_TX", NULL, "BE_IN"},
 	{"INCALL_RECORD_RX", NULL, "BE_IN"},
-	{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"},
 	{"SLIM0_RX_VI_FB_LCH_MUX", "SLIM4_TX", "SLIMBUS_4_TX"},
 	{"SLIMBUS_0_RX", NULL, "SLIM0_RX_VI_FB_LCH_MUX"},
 };
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 2b0d155..7f4f0ef 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -217,7 +217,7 @@
 
 	switch (port_id) {
 	case PRIMARY_I2S_RX:
-	case PCM_RX:
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
 	case SECONDARY_I2S_RX:
 	case MI2S_RX:
 	case HDMI_RX:
@@ -241,7 +241,7 @@
 		break;
 
 	case PRIMARY_I2S_TX:
-	case PCM_TX:
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
 	case SECONDARY_I2S_TX:
 	case MI2S_TX:
 	case DIGI_MIC_TX:
@@ -307,8 +307,8 @@
 	case RT_PROXY_PORT_001_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_rt_proxy_port_cfg);
 		break;
-	case PCM_RX:
-	case PCM_TX:
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	default:
@@ -899,6 +899,44 @@
 	return ret;
 }
 
+static int afe_send_bank_selection_clip(
+		struct afe_param_id_clip_bank_sel *param)
+{
+	int ret;
+	struct afe_svc_cmd_set_clip_bank_selection config;
+	if (!param) {
+		pr_err("%s: Invalid params", __func__);
+		return -EINVAL;
+	}
+	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	config.hdr.pkt_size = sizeof(config);
+	config.hdr.src_port = 0;
+	config.hdr.dest_port = 0;
+	config.hdr.token = IDX_GLOBAL_CFG;
+	config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
+
+	config.param.payload_size = sizeof(struct afe_port_param_data_v2) +
+				sizeof(struct afe_param_id_clip_bank_sel);
+	config.param.payload_address_lsw = 0x00;
+	config.param.payload_address_msw = 0x00;
+	config.param.mem_map_handle = 0x00;
+
+	config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
+	config.pdata.param_id = AFE_PARAM_ID_CLIP_BANK_SEL_CFG;
+	config.pdata.param_size =
+		sizeof(struct afe_param_id_clip_bank_sel);
+	config.bank_sel = *param;
+	ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
+	if (ret) {
+		pr_err("%s: AFE_PARAM_ID_CLIP_BANK_SEL_CFG failed %d\n",
+		__func__, ret);
+	} else if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+		ret = -EAGAIN;
+	}
+	return ret;
+}
 int afe_send_aanc_version(
 	struct afe_param_id_cdc_aanc_version *version_cfg)
 {
@@ -991,6 +1029,12 @@
 	case AFE_AANC_VERSION:
 		ret = afe_send_aanc_version(config_data);
 		break;
+	case AFE_CLIP_BANK_SEL:
+		ret = afe_send_bank_selection_clip(config_data);
+		break;
+	case AFE_CDC_CLIP_REGISTERS_CONFIG:
+		ret = afe_send_codec_reg_config(config_data);
+		break;
 	default:
 		pr_err("%s: unknown configuration type", __func__);
 		ret = -EINVAL;
@@ -1153,8 +1197,8 @@
 	case PRIMARY_I2S_TX:
 		cfg_type = AFE_PARAM_ID_PCM_CONFIG;
 		break;
-	case PCM_RX:
-	case PCM_TX:
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
 		cfg_type = AFE_PARAM_ID_PCM_CONFIG;
@@ -1250,8 +1294,10 @@
 	switch (port_id) {
 	case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
 	case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
-	case PCM_RX: return IDX_PCM_RX;
-	case PCM_TX: return IDX_PCM_TX;
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+		return IDX_AFE_PORT_ID_PRIMARY_PCM_RX;
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
+		return IDX_AFE_PORT_ID_PRIMARY_PCM_TX;
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 		return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
@@ -1349,8 +1395,8 @@
 	case PRIMARY_I2S_TX:
 		cfg_type = AFE_PARAM_ID_I2S_CONFIG;
 		break;
-	case PCM_RX:
-	case PCM_TX:
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
 		cfg_type = AFE_PARAM_ID_PCM_CONFIG;
@@ -2538,8 +2584,8 @@
 	switch (port_id) {
 	case PRIMARY_I2S_RX:
 	case PRIMARY_I2S_TX:
-	case PCM_RX:
-	case PCM_TX:
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	case SECONDARY_I2S_RX:
@@ -2965,12 +3011,18 @@
 }
 
 int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
-	int l_ch, int r_ch)
+	int l_ch, int r_ch, u32 enable)
 {
 	int ret = -EINVAL;
 	union afe_spkr_prot_config prot_config;
 	int index = 0;
 
+	if (!enable) {
+		pr_debug("%s Disable Feedback tx path", __func__);
+		this_afe.vi_tx_port = -1;
+		return 0;
+	}
+
 	if ((q6audio_validate_port(src_port) < 0) ||
 		(q6audio_validate_port(dst_port) < 0)) {
 		pr_err("%s invalid ports src %d dst %d",
@@ -3011,6 +3063,7 @@
 	this_afe.apr = NULL;
 	this_afe.dtmf_gen_rx_portid = -1;
 	this_afe.mmap_handle = 0;
+	this_afe.vi_tx_port = -1;
 	for (i = 0; i < AFE_MAX_PORTS; i++)
 		init_waitqueue_head(&this_afe.wait[i]);
 
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index faf5f35..3cb7a1f 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -24,8 +24,10 @@
 	switch (port_id) {
 	case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
 	case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
-	case PCM_RX: return IDX_PCM_RX;
-	case PCM_TX: return IDX_PCM_TX;
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+		return IDX_AFE_PORT_ID_PRIMARY_PCM_RX;
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
+		return IDX_AFE_PORT_ID_PRIMARY_PCM_TX;
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 		return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
@@ -76,8 +78,10 @@
 	switch (port_id) {
 	case PRIMARY_I2S_RX: return AFE_PORT_ID_PRIMARY_MI2S_RX;
 	case PRIMARY_I2S_TX: return AFE_PORT_ID_PRIMARY_MI2S_TX;
-	case PCM_RX: return AFE_PORT_ID_PRIMARY_PCM_RX;
-	case PCM_TX: return AFE_PORT_ID_PRIMARY_PCM_TX;
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+			return AFE_PORT_ID_PRIMARY_PCM_RX;
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
+			return AFE_PORT_ID_PRIMARY_PCM_TX;
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 			return AFE_PORT_ID_SECONDARY_PCM_RX;
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
@@ -152,8 +156,8 @@
 	switch (port_id) {
 	case PRIMARY_I2S_RX:
 	case PRIMARY_I2S_TX:
-	case PCM_RX:
-	case PCM_TX:
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	case SECONDARY_I2S_RX:
@@ -179,8 +183,8 @@
 	switch (port_id) {
 	case PRIMARY_I2S_RX:
 	case PRIMARY_I2S_TX:
-	case PCM_RX:
-	case PCM_TX:
+	case AFE_PORT_ID_PRIMARY_PCM_RX:
+	case AFE_PORT_ID_PRIMARY_PCM_TX:
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	case SECONDARY_I2S_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 80bc4f9..e9d0a7e 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -2963,6 +2963,7 @@
 	cvp_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
 	cvp_mute_cmd.cvp_set_mute.direction = VSS_IVOLUME_DIRECTION_RX;
 	cvp_mute_cmd.cvp_set_mute.mute_flag = v->dev_rx.mute;
+	cvp_mute_cmd.cvp_set_mute.ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	ret = apr_send_pkt(common.apr_q6_cvp, (uint32_t *) &cvp_mute_cmd);