Merge "input: synaptics_i2c_rmi4: Reinitialize list after freeing it"
diff --git a/Documentation/csdio.txt b/Documentation/csdio.txt
deleted file mode 100644
index 22d5e35..0000000
--- a/Documentation/csdio.txt
+++ /dev/null
@@ -1,189 +0,0 @@
-Introduction
-============
-The Char SDIO Device Driver is an interface which exposes an SDIO
-card/function from kernel space as a char device in user space.
-
-The driver doesn't interact with any HW directly. It relies on SDIO
-card/function interface provided as a part of Linux kernel.
-
-Hardware description
-====================
-Each SDIO device/card contains an SDIO client HW block.
-The host interacts with the device by sending byte sequences called
-command (CMD). Some commands can be followed by data blocks. The
-device sends back a byte sequence called response (R) and a data
-block if required. CMD3, CMD5 and CMD7 are used to initialize the
-device. CMD52 and CMD53 are used to access the device. Command
-format and properties are defined by SDIO Specification document
-published by SD Association:
-    http://www.sdcard.org/developers/tech/sdio/.
-
-CMD52 and CMD53 can access up to 8 address spaces called Functions.
-Function 0 contains system information predefined by SD/SDIO
-standard and Functions 1-7 are defined by the SDIO device
-manufacturer.
-
-An SDIO device/card can send an interrupt to SDIO host. This
-interrupt is intercepted and handled by SDIO host.
-
-Software description
-====================
-Linux provides a framework for handling SDIO devices. It implements
-kind of plug-and-play model in which the Linux SDIO Host Driver is
-responsible for initializing an SDIO device upon insertion. It also
-reads device/card identification information and enumerates functions
-provided by the device and then looks up in the list of
-preregistered user SDIO drivers for a suitable one.
-
-During its lifecycle the user SDIO driver interacts with the Linux
-SDIO Host Driver in order to send/receive information to/from SDIO
-device/card. The user SDIO driver doesn't work with CMD52/CMD53
-directly. Instead it uses an abstraction provided by the Linux SDIO
-Host Driver.
-
-The Linux SDIO Host Driver is also in charge of handling SDIO
-interrupts. User SDIO driver can register its own callback in SDIO
-Host Driver and get a notification about interrupt event.
-
-The Char SDIO Device Driver follows the design guidelines mentioned
-above. It provides the following functionality:
-
- - Register itself in the user SDIO drivers list;
- - Handle Probe event upon insertion of supported card/device;
- - Creates and maintains a char device driver for each SDIO Function
-   found in the card/device;
- - Translates read/write/ioctl calls to appropriate SDIO call
-   sequences;
-
-In order to handle general SDIO configuration functionality and
-Function 0 the Char SDIO Device Driver provides additional
-simplified char device driver.
-
-The Manufacturer and Device IDs of handled SDIO device should be
-provided as parameters for kernel module or as configuration
-parameters in case of statically linked driver.
-
-Design
-======
-The main goal of the Char SDIO Device Driver is to expose an SDIO
-card/device from kernel space to user space as a char device driver.
-The driver should be generic and simple as far as possible.
-
-The biggest design tradeoff is maintaining a balance between the
-system call overhead required to initiate an SDIO transaction from
-user space and overall SDIO communication performance. But luckily,
-because of nature of SDIO protocol, this overhead is negligible
-comparing to time required to execute SDIO transaction itself. So,
-each CMD52 (read or write) consists from single ioctl system call.
-And each CMD53 invokes single ioctl system call followed by read or
-write system call.
-
-The Char SDIO Device Driver registers its own class of the devices
-called 'csdio'. This class will serve as a common roof for all SDIO
-devices served by different instances of the Char SDIO Device Driver.
-Additional benefit from maintaining its own class is the driver
-ability to overwrite default permissions of the dev nodes created by
-the driver.
-
-Power Management
-================
-None
-
-SMP/multi-core
-==============
-The driver does not anticipate any issues related to multi-core
-since it is expected to run on one core only.
-
-Security
-========
-None
-
-Performance
-===========
-None
-
-Interface
-=========
-The Char SDIO Device Driver has two char device interfaces:
- - Control Interface;
- - Function Interface.
-
-Char SDIO Device Driver Control Interface consists of:
- - open()   - device node is /dev/csdio0;
- - close()
- - ioctl()  - the following options are available:
-   - CSDIO_IOC_ENABLE_HIGHSPEED_MODE;
-   - CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS;
-   - CSDIO_IOC_ENABLE_ISR;
-   - CSDIO_IOC_DISABLE_ISR.
-
-Char SDIO Device Driver Function Interface consists of:
- - open()  - device node is /dev/csdiofX, where X is Function Id;
- - close()
- - read()  - send CMD53 read;
- - write() - send CMD53 write;
- - ioctl() - the following options are available:
-   - CSDIO_IOC_SET_OP_CODE - 0 fixed adrress, 1 autoincrement.
-   - CSDIO_IOC_FUNCTION_SET_BLOCK_SIZE;
-   - CSDIO_IOC_SET_BLOCK_MODE - 0 byte mode, 1 block mode;
-   - CSDIO_IOC_CMD52 - execute CMD52, receives the
-        following structure as a parameter:
-            struct csdio_cmd52_ctrl_t {
-	            uint32_t    m_write; // 0 - read, 1 -write
-	            uint32_t    m_address;
-	            uint32_t    m_data;  // data to write or read data
-	            uint32_t    m_ret;   // command execution status
-            }__attribute__ ((packed));
-   - CSDIO_IOC_CMD53 - setup CMD53 data transfer, receives the
-        following structure as a parameter:
-            struct csdio_cmd53_ctrl_t {
-	            uint32_t    m_block_mode;
-	            uint32_t    m_op_code;
-	            uint32_t    m_address;
-            }__attribute__ ((packed));
-   - CSDIO_IOC_CONNECT_ISR;
-   - CSDIO_IOC_DISCONNECT_ISR;
-   - CSDIO_IOC_GET_VDD;
-   - CSDIO_IOC_SET_VDD.
-
-Additionally, user space application can use fcntl system call with
-parameters F_SETOWN and F_SETFL in order to set an asynchronous
-callback for SDIO interrupt.
-
-Driver parameters
-=================
-If the driver is compiled as a kernel module, the following
-parameters can be used in order to provide Manufacturer and Device IDs
-upon module download:
- - csdio_vendor_id;
- - csdio_device_id.
-If the driver is intended to work with specific SDIO host the
-host_name parameter should be added followed by the name of the MMC
-host platform device.
-
-Config options
-==============
-These are the kernel configuration options:
- - CONFIG_CSDIO_VENDOR_ID;
- - CONFIG_CSDIO_DEVICE_ID.
-
-Dependencies
-============
-The Char SDIO Device Driver depends on Linux SDIO Host Driver.
-
-User space utilities
-====================
-None
-
-Other
-=====
-None
-
-Known issues
-============
-None
-
-To do
-=====
-Provide mechanism to support a number of SDIO devices simultaneously
-connected to different SDIO hosts.
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 99de826..f724e60 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -198,16 +198,6 @@
 - qti,cpr-uplift-speed-bin:	The speed bin value corresponding to one type of processor which needs to apply the
 				pvs voltage uplift workaround.
 				This is required if cpr-fuse-uplift-disable-sel is present.
-- qti,cpr-quot-adjust-table:	Array of 4-tuples in which each 4-tuple indicates the speed bin
-				of the CPU, the frequency of the CPU, the quotient adjustment and the voltage corner to use.
-				The 4 elements in one 4-tuple are:
-				[0]: => the speed bin of the CPU;
-				[1]: => the frequency in kHz of the CPU;
-				[2]: => the quotient adjustment of the corresponding frequency;
-				[3]: => the voltage corner to use.
-				If the speed bin in a tuple is eqaul to the speed bin of the CPU, then the quotient
-				adjustment would be subtracted from the quotient value of the voltage corner
-				when the CPU is running at that frequency.
 
 Example:
 	apc_vreg_corner: regulator@f9018000 {
@@ -270,9 +260,5 @@
 		qti,cpr-uplift-max-volt = <1350000>;
 		qti,cpr-uplift-speed-bin = <1>;
 		qti,speed-bin-fuse-sel = <22 0 3 0>;
-		qti,cpr-quot-adjust-table = <1 998400 450 3>,
-				<1 1094400 375 3>, <1 1190400 300 3>,
-				<1 1305600 225 3>, <1 1344000 187 3>,
-				<1 1401600 150 3>, <1 1497600 75 3>;
 	};
 
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index a77b5ff..6277054 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -4,23 +4,29 @@
 
 Required properties:
 
- - compatible : "qcom,msm-pcm-dsp"
+ - compatible : "qti,msm-pcm-dsp"
 
- - qcom,msm-pcm-dsp-id : device node id
+ - qti,msm-pcm-dsp-id : device node id
 
 * msm-pcm-low-latency
 
 Required properties:
 
- - compatible : "qcom,msm-pcm-dsp"
+ - compatible : "qti,msm-pcm-dsp"
 
- - qcom,msm-pcm-dsp-id : device node id
+ - qti,msm-pcm-dsp-id : device node id
 
    Optional properties
 
-      - qcom,msm-pcm-low-latency : Flag indicating whether
+      - qti,msm-pcm-low-latency : Flag indicating whether
         the device node is of type low latency.
 
+      - qti,latency-level : Flag indicating whether the device node
+                            is of type regular low latency or ultra
+                            low latency.
+                            regular : regular low latency stream
+                            ultra : ultra low latency stream
+
 * msm-pcm-routing
 
 Required properties:
@@ -226,16 +232,16 @@
 
 Example:
 
-        qcom,msm-pcm {
-		compatible = "qcom,msm-pcm-dsp";
-		qcom,msm-pcm-dsp-id = <0>;
+	qti,msm-pcm {
+		compatible = "qti,msm-pcm-dsp";
+		qti,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;
-        };
+	qti,msm-pcm-low-latency {
+		compatible = "qti,msm-pcm-dsp";
+		qti,msm-pcm-dsp-id = <1>;
+		qti,msm-pcm-low-latency;
+	};
 
         qcom,msm-pcm-routing {
                 compatible = "qcom,msm-pcm-routing";
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 63da606..7db913a 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -91,13 +91,6 @@
 		qti,cpr-uplift-max-volt = <1350000>;
 		qti,cpr-uplift-speed-bin = <1>;
 		qti,speed-bin-fuse-sel = <22 0 3 0>;
-		qti,cpr-quot-adjust-table = <1 300000 0 1>,
-				<1 384000 0 1>, <1 600000 0 2>,
-				<1 787200 0 2>, <1 998400 450 3>,
-				<1 1094400 375 3>, <1 1190400 300 3>,
-				<1 1305600 225 3>, <1 1344000 187 3>,
-				<1 1401600 150 3>, <1 1497600 75 3>,
-				<1 1593600 0 3>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index fc00411..baa81cc 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -429,19 +429,20 @@
 		qcom,tapan-codec-9302;
 	};
 
-	qcom,msm-pcm {
-		compatible = "qcom,msm-pcm-dsp";
-		qcom,msm-pcm-dsp-id = <0>;
+	qti,msm-pcm {
+		compatible = "qti,msm-pcm-dsp";
+		qti,msm-pcm-dsp-id = <0>;
 	};
 
 	qcom,msm-pcm-routing {
 		compatible = "qcom,msm-pcm-routing";
 	};
 
-	qcom,msm-pcm-low-latency {
-		compatible = "qcom,msm-pcm-dsp";
-		qcom,msm-pcm-dsp-id = <1>;
-		qcom,msm-pcm-low-latency;
+	qti,msm-pcm-low-latency {
+		compatible = "qti,msm-pcm-dsp";
+		qti,msm-pcm-dsp-id = <1>;
+		qti,msm-pcm-low-latency;
+		qti,latency-level = "regular";
 	};
 
 	qcom,msm-pcm-lpa {
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 94a9db0..03ef738 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -615,15 +615,16 @@
 		qcom,model = "msm8x10-snd-card";
 	};
 
-	qcom,msm-pcm {
-		compatible = "qcom,msm-pcm-dsp";
-		qcom,msm-pcm-dsp-id = <0>;
+	qti,msm-pcm {
+		compatible = "qti,msm-pcm-dsp";
+		qti,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;
+	qti,msm-pcm-low-latency {
+		compatible = "qti,msm-pcm-dsp";
+		qti,msm-pcm-dsp-id = <1>;
+		qti,msm-pcm-low-latency;
+		qti,latency-level = "ultra";
 	};
 
 	qcom,msm-pcm-routing {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index b4a3e55..a912da8 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1628,15 +1628,16 @@
 		compatible = "qcom,msm-audio-ion";
 	};
 
-	qcom,msm-pcm {
-		compatible = "qcom,msm-pcm-dsp";
-		qcom,msm-pcm-dsp-id = <0>;
+	qti,msm-pcm {
+		compatible = "qti,msm-pcm-dsp";
+		qti,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;
+	qti,msm-pcm-low-latency {
+		compatible = "qti,msm-pcm-dsp";
+		qti,msm-pcm-dsp-id = <1>;
+		qti,msm-pcm-low-latency;
+		qti,latency-level = "regular";
 	};
 
 	qcom,msm-pcm-routing {
diff --git a/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
index fa313bf..6b62391 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
@@ -22,5 +22,5 @@
 };
 
 &sdhc_1 {
-	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
 };
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
index 938a2cc..63cb68b 100644
--- a/arch/arm/boot/dts/msm8974pro-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -214,6 +214,9 @@
 			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 18>,  /* APCx_qgicQTmrSecPhysIrptReq */
+			<0xff 19>,  /* APCx_qgicQTmrSecPhysIrptReq */
+			<0xff 25>,  /* APCx_qgicExtFaultIrptReq */
 			<0xff 33>, /*l2_perf_mon*/
 			<0xff 34>,  /* APCC_qgicL2ErrorIrptReq */
 			<0xff 35>,  /* WDT_barkInt */
@@ -237,7 +240,10 @@
 			<0xff 105>, /* iommu_pmon_nonsecure_irq */
 			<0xff 109>,  /* ocmem_dm_nonsec_irq */
 			<0xff 126>,  /* bam_irq[0] */
+			<0xff 140>,  /* uart_dm_intr */
 			<0xff 155>,  /* sdcc_irq[0] */
+			<0xff 157>,  /* sdcc_irq[0] */
+			<0xff 159>,  /* sdcc_irq[0] */
 			<0xff 163>,  /* usb30_ee1_irq */
 			<0xff 170>,  /* sdcc_pwr_cmd_irq */
 			<0xff 173>, /* o_wcss_apss_smd_hi */
@@ -270,6 +276,8 @@
 			<0xff 207>, /* rpm_ipc(27) */
 			<0xff 211>, /* usb_dwc3_otg */
 			<0xff 240>, /* summary_irq_kpss */
+			<0xff 253>, /* sdcc_pwr_cmd_irq */
+			<0xff 256>, /* sdcc_pwr_cmd_irq */
 			<0xff 268>, /* bam_irq[1] */
 			<0xff 270>, /* bam_irq[0] */
 			<0xff 271>; /* bam_irq[0] */
diff --git a/arch/arm/boot/dts/msm8974pro-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
index 2c06c3c..2783ffd 100644
--- a/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
@@ -60,6 +60,10 @@
 	vdd_cx-supply = <&pm8841_s2_corner>;
 };
 
+&pm8841_s2_corner {
+	qcom,init-smps-mode = <0>;	/* Allow AUTO mode for VDD_CX. */
+};
+
 &krait_regulator_pmic {
 	status = "ok";
 
diff --git a/arch/arm/boot/dts/msm8974pro-pma8084.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084.dtsi
index 71fbeae..c06ebf8 100644
--- a/arch/arm/boot/dts/msm8974pro-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084.dtsi
@@ -191,6 +191,10 @@
 	vdd_cx-supply = <&pma8084_s2_corner>;
 };
 
+&pma8084_s2_corner {
+	qcom,init-smps-mode = <0>;	/* Allow AUTO mode for VDD_CX. */
+};
+
 &krait_regulator_pmic {
 	status = "ok";
 
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 0e7baf1..dee1f68 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -686,9 +686,9 @@
 		qcom,adsp-state = <2>;
 	};
 
-	qcom,msm-pcm {
-		compatible = "qcom,msm-pcm-dsp";
-		qcom,msm-pcm-dsp-id = <0>;
+	qti,msm-pcm {
+		compatible = "qti,msm-pcm-dsp";
+		qti,msm-pcm-dsp-id = <0>;
 	};
 
 	qcom,msm-pcm-routing {
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index 1cf2e41..9ee7333 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -25,7 +25,6 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/cpufreq.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/cpr-regulator.h>
@@ -133,13 +132,6 @@
 
 #define FLAGS_SET_MIN_VOLTAGE		BIT(1)
 #define FLAGS_UPLIFT_QUOT_VOLT		BIT(2)
-#define FLAGS_QUOT_ADJUST_WITH_FREQ	BIT(3)
-
-struct cpufreq_mapping_info {
-	int freq;
-	int quot_adjust;
-	int corner;
-};
 
 enum voltage_change_dir {
 	NO_CHANGE,
@@ -179,7 +171,6 @@
 	bool		cpr_fuse_disable;
 	bool		cpr_fuse_local;
 	int		cpr_fuse_target_quot[CPR_CORNER_MAX];
-	int		cpr_fuse_original_quot[CPR_CORNER_MAX];
 	int		cpr_fuse_ro_sel[CPR_CORNER_MAX];
 	int		gcnt;
 
@@ -214,10 +205,6 @@
 	u32		vdd_apc_step_up_limit;
 	u32		vdd_apc_step_down_limit;
 	u32		flags;
-	struct notifier_block freq_transition;
-	unsigned int	freq;
-	struct cpufreq_mapping_info *cpufreq_mapping;
-	u32		cpufreq_mapping_size;
 };
 
 #define CPR_DEBUG_MASK_IRQ	BIT(0)
@@ -280,28 +267,6 @@
 	return efuse_bits;
 }
 
-static int cpr_get_freq_corner(struct cpr_regulator *cpr_vreg, int freq)
-{
-	int i;
-
-	for (i = 0; i < cpr_vreg->cpufreq_mapping_size; i++) {
-		if (freq == cpr_vreg->cpufreq_mapping[i].freq)
-			return cpr_vreg->cpufreq_mapping[i].corner;
-	}
-
-	return -EINVAL;
-}
-
-static int cpr_get_freq_quot_adjust(struct cpr_regulator *cpr_vreg, int freq)
-{
-	int i;
-
-	for (i = 0; i < cpr_vreg->cpufreq_mapping_size; i++) {
-		if (freq == cpr_vreg->cpufreq_mapping[i].freq)
-			return cpr_vreg->cpufreq_mapping[i].quot_adjust;
-	}
-	return 0;
-}
 
 static bool cpr_is_allowed(struct cpr_regulator *cpr_vreg)
 {
@@ -376,13 +341,6 @@
 	cpr_ctl_modify(cpr_vreg, RBCPR_CTL_LOOP_EN, 0);
 }
 
-static bool cpr_ctl_is_enabled(struct cpr_regulator *cpr_vreg)
-{
-	u32 val;
-	val = cpr_read(cpr_vreg, REG_RBCPR_CTL);
-	return ((val & RBCPR_CTL_LOOP_EN) == RBCPR_CTL_LOOP_EN);
-}
-
 static void cpr_regs_save(struct cpr_regulator *cpr_vreg)
 {
 	int i, offset;
@@ -415,13 +373,6 @@
 static void cpr_corner_restore(struct cpr_regulator *cpr_vreg, int corner)
 {
 	u32 gcnt, ctl, irq, ro_sel;
-	int adjust;
-
-	if (cpr_vreg->flags & FLAGS_QUOT_ADJUST_WITH_FREQ) {
-		adjust = cpr_get_freq_quot_adjust(cpr_vreg, cpr_vreg->freq);
-		cpr_vreg->cpr_fuse_target_quot[corner] =
-		cpr_vreg->cpr_fuse_original_quot[corner] - adjust;
-	}
 
 	ro_sel = cpr_vreg->cpr_fuse_ro_sel[corner];
 	gcnt = cpr_vreg->gcnt | cpr_vreg->cpr_fuse_target_quot[corner];
@@ -1250,78 +1201,6 @@
 	return rc;
 }
 
-static int cpr_get_of_cprfreq_mappings(struct cpr_regulator *cpr_vreg,
-					struct device *dev)
-{
-	int rc = 0;
-	int i, j, size, stripe_size, length;
-	struct property *prop;
-	u32 *tmp;
-
-	prop = of_find_property(dev->of_node, "qti,cpr-quot-adjust-table",
-				NULL);
-	if (prop) {
-		size = prop->length / sizeof(u32);
-		tmp = kzalloc(sizeof(u32) * size, GFP_KERNEL);
-		if (!tmp)
-			return -ENOMEM;
-
-		rc = of_property_read_u32_array(dev->of_node,
-				"qti,cpr-quot-adjust-table", tmp, size);
-		if (rc) {
-			pr_err("qti,cpr-quot-adjust-table missing, rc = %d",
-				rc);
-			kfree(tmp);
-			return rc;
-		}
-
-		length = 0;
-		stripe_size = 1 + sizeof(struct cpufreq_mapping_info) /
-				sizeof(int);
-		for (i = 0; i < size; i += stripe_size) {
-			if (tmp[i] == cpr_vreg->speed_bin)
-				length++;
-		}
-		if (i != size) {
-			pr_err("qti,cpr-quot-adjust-table data is not correct\n");
-			kfree(tmp);
-			return -EINVAL;
-		}
-
-		cpr_vreg->cpufreq_mapping_size = length;
-		if (length) {
-			cpr_vreg->cpufreq_mapping = devm_kzalloc(dev,
-				sizeof(struct cpufreq_mapping_info) * length,
-				GFP_KERNEL);
-
-			if (!cpr_vreg->cpufreq_mapping) {
-				kfree(tmp);
-				return -ENOMEM;
-			}
-
-			cpr_vreg->flags |= FLAGS_QUOT_ADJUST_WITH_FREQ;
-
-			for (i = 0, j = 0; i < size; i += stripe_size) {
-				if (tmp[i] == cpr_vreg->speed_bin) {
-					cpr_vreg->cpufreq_mapping[j].freq =
-						tmp[i+1];
-					cpr_vreg->cpufreq_mapping[j].quot_adjust
-					= tmp[i+2];
-					cpr_vreg->cpufreq_mapping[j].corner =
-						tmp[i+3];
-					++j;
-				}
-
-			}
-
-		}
-
-		kfree(tmp);
-	}
-
-	return rc;
-}
-
 static int __devinit cpr_init_cpr_efuse(struct platform_device *pdev,
 				     struct cpr_regulator *cpr_vreg)
 {
@@ -1451,15 +1330,6 @@
 		}
 	}
 
-	for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
-		cpr_vreg->cpr_fuse_original_quot[i] =
-		cpr_vreg->cpr_fuse_target_quot[i];
-	}
-
-	rc = cpr_get_of_cprfreq_mappings(cpr_vreg, &pdev->dev);
-	if (rc)
-		return rc;
-
 	cpr_vreg->cpr_fuse_bits = fuse_bits;
 	if (!cpr_vreg->cpr_fuse_bits) {
 		cpr_vreg->cpr_fuse_disable = 1;
@@ -1699,8 +1569,6 @@
 		pr_info("[row: %d]: 0x%llx, speed_bits = %d\n",
 				fuse_sel[0], fuse_bits, speed_bits);
 		cpr_vreg->speed_bin = speed_bits;
-	} else {
-		cpr_vreg->speed_bin = UINT_MAX;
 	}
 }
 
@@ -1794,51 +1662,6 @@
 	return 0;
 }
 
-static int cpr_freq_transition(struct notifier_block *nb, unsigned long val,
-					void *data)
-{
-	int old_corner, new_corner;
-	struct cpr_regulator *cpr_vreg = container_of(nb, struct cpr_regulator,
-				freq_transition);
-	struct cpufreq_freqs *freqs = data;
-
-	mutex_lock(&cpr_vreg->cpr_mutex);
-	switch (val) {
-	case CPUFREQ_PRECHANGE:
-		cpr_vreg->freq = freqs->new;
-		if (freqs->new > freqs->old) {
-			old_corner = cpr_get_freq_corner(cpr_vreg, freqs->old);
-			new_corner = cpr_get_freq_corner(cpr_vreg, freqs->new);
-			if (new_corner > 0 && old_corner == new_corner &&
-				cpr_ctl_is_enabled(cpr_vreg)) {
-				cpr_ctl_disable(cpr_vreg);
-				cpr_irq_clr(cpr_vreg);
-				cpr_corner_restore(cpr_vreg, new_corner);
-				cpr_ctl_enable(cpr_vreg, new_corner);
-			}
-		}
-		break;
-	case CPUFREQ_POSTCHANGE:
-		if (freqs->new < freqs->old) {
-			old_corner = cpr_get_freq_corner(cpr_vreg, freqs->old);
-			new_corner = cpr_get_freq_corner(cpr_vreg, freqs->new);
-			if (new_corner > 0 && old_corner == new_corner &&
-				cpr_ctl_is_enabled(cpr_vreg)) {
-				cpr_ctl_disable(cpr_vreg);
-				cpr_irq_clr(cpr_vreg);
-				cpr_corner_restore(cpr_vreg, new_corner);
-				cpr_ctl_enable(cpr_vreg, new_corner);
-			}
-		}
-		break;
-	default:
-		break;
-	}
-	mutex_unlock(&cpr_vreg->cpr_mutex);
-
-	return NOTIFY_OK;
-}
-
 static int __devinit cpr_regulator_probe(struct platform_device *pdev)
 {
 	struct cpr_regulator *cpr_vreg;
@@ -1922,10 +1745,6 @@
 
 	platform_set_drvdata(pdev, cpr_vreg);
 	the_cpr = cpr_vreg;
-	cpr_vreg->freq_transition.notifier_call = cpr_freq_transition;
-	if (cpr_vreg->flags & FLAGS_QUOT_ADJUST_WITH_FREQ)
-		cpufreq_register_notifier(&cpr_vreg->freq_transition,
-						CPUFREQ_TRANSITION_NOTIFIER);
 
 	return 0;
 
@@ -1946,9 +1765,6 @@
 			cpr_irq_set(cpr_vreg, 0);
 		}
 
-		if (cpr_vreg->flags & FLAGS_QUOT_ADJUST_WITH_FREQ)
-			cpufreq_unregister_notifier(&cpr_vreg->freq_transition,
-						CPUFREQ_TRANSITION_NOTIFIER);
 		cpr_apc_exit(cpr_vreg);
 		regulator_unregister(cpr_vreg->rdev);
 	}
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h b/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
index 0a1cdd4..42cf6f9 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
@@ -45,7 +45,7 @@
 };
 
 void rtac_add_adm_device(u32 port_id, u32 copp_id, u32 path_id, u32 popp_id);
-void rtac_remove_adm_device(u32 port_id);
+void rtac_remove_adm_device(u32 port_id, u32 copp_id);
 void rtac_remove_popp_from_adm_devices(u32 popp_id);
 void rtac_add_voice(u32 cvs_handle, u32 cvp_handle, u32 rx_afe_port,
 	u32 tx_afe_port, u32 session_id);
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index ce66531..6bb4011 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -434,7 +434,7 @@
 				       unsigned int len)
 {
 	struct sk_buff *temp;
-	int offset = 0, buf_len = 0, copy_len;
+	unsigned int offset = 0, buf_len = 0, copy_len;
 	void *buf;
 
 	if (!skb_head) {
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
index e6b1324..a18d0f3 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -51,6 +51,11 @@
 #define Y_IND 1
 #define Z_IND 2
 
+/* Shared memory limits */
+/* max_buf_size = (port_size(65535*2) * port_num(8) * group_size(3) */
+#define USF_MAX_BUF_SIZE 3145680
+#define USF_MAX_BUF_NUM  32
+
 /* Place for opreation result, received from QDSP6 */
 #define APR_RESULT_IND 1
 
@@ -482,6 +487,15 @@
 	    (config == NULL))
 		return -EINVAL;
 
+	if ((config->buf_size == 0) ||
+	    (config->buf_size > USF_MAX_BUF_SIZE) ||
+	    (config->buf_num == 0) ||
+	    (config->buf_num > USF_MAX_BUF_NUM)) {
+		pr_err("%s: wrong params: buf_size=%d; buf_num=%d\n",
+		       __func__, config->buf_size, config->buf_num);
+		return -EINVAL;
+	}
+
 	data_map_size = sizeof(usf_xx->encdec_cfg.cfg_common.data_map);
 	min_map_size = min(data_map_size, config->port_cnt);
 
@@ -794,6 +808,7 @@
 {
 	uint32_t timeout = 0;
 	struct us_detect_info_type detect_info;
+	struct usm_session_cmd_detect_info *p_allocated_memory = NULL;
 	struct usm_session_cmd_detect_info usm_detect_info;
 	struct usm_session_cmd_detect_info *p_usm_detect_info =
 						&usm_detect_info;
@@ -820,12 +835,13 @@
 		uint8_t *p_data = NULL;
 
 		detect_info_size += detect_info.params_data_size;
-		p_usm_detect_info = kzalloc(detect_info_size, GFP_KERNEL);
-		if (p_usm_detect_info == NULL) {
+		 p_allocated_memory = kzalloc(detect_info_size, GFP_KERNEL);
+		if (p_allocated_memory == NULL) {
 			pr_err("%s: detect_info[%d] allocation failed\n",
 			       __func__, detect_info_size);
 			return -ENOMEM;
 		}
+		p_usm_detect_info = p_allocated_memory;
 		p_data = (uint8_t *)p_usm_detect_info +
 			sizeof(struct usm_session_cmd_detect_info);
 
@@ -835,7 +851,7 @@
 		if (rc) {
 			pr_err("%s: copy params from user; rc=%d\n",
 				__func__, rc);
-			kfree(p_usm_detect_info);
+			kfree(p_allocated_memory);
 			return -EFAULT;
 		}
 		p_usm_detect_info->algorithm_cfg_size =
@@ -852,9 +868,7 @@
 				    p_usm_detect_info,
 				    detect_info_size);
 	if (rc || (detect_info.detect_timeout == USF_NO_WAIT_TIMEOUT)) {
-		if (detect_info_size >
-		    sizeof(struct usm_session_cmd_detect_info))
-			kfree(p_usm_detect_info);
+		kfree(p_allocated_memory);
 		return rc;
 	}
 
@@ -874,25 +888,24 @@
 					 USF_US_DETECT_UNDEF),
 					timeout);
 	/* In the case of timeout, "no US" is assumed */
-	if (rc < 0) {
+	if (rc < 0)
 		pr_err("%s: Getting US detection failed rc[%d]\n",
 		       __func__, rc);
-		return rc;
+	else {
+		usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type;
+		detect_info.is_us =
+			(usf_xx->us_detect_type == USF_US_DETECT_YES);
+		rc = copy_to_user((void __user *)arg,
+				  &detect_info,
+				  sizeof(detect_info));
+		if (rc) {
+			pr_err("%s: copy detect_info to user; rc=%d\n",
+				__func__, rc);
+			rc = -EFAULT;
+		}
 	}
 
-	usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type;
-	detect_info.is_us = (usf_xx->us_detect_type == USF_US_DETECT_YES);
-	rc = copy_to_user((void __user *)arg,
-			  &detect_info,
-			  sizeof(detect_info));
-	if (rc) {
-		pr_err("%s: copy detect_info to user; rc=%d\n",
-			__func__, rc);
-		rc = -EFAULT;
-	}
-
-	if (detect_info_size > sizeof(struct usm_session_cmd_detect_info))
-		kfree(p_usm_detect_info);
+	kfree(p_allocated_memory);
 
 	return rc;
 } /* usf_set_us_detection */
@@ -993,16 +1006,14 @@
 	if (rc)
 		return rc;
 
-	if (usf_xx->buffer_size && usf_xx->buffer_count) {
-		rc = q6usm_us_client_buf_alloc(
-					IN,
-					usf_xx->usc,
-					usf_xx->buffer_size,
-					usf_xx->buffer_count);
-		if (rc) {
-			(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
-			return rc;
-		}
+	rc = q6usm_us_client_buf_alloc(
+				IN,
+				usf_xx->usc,
+				usf_xx->buffer_size,
+				usf_xx->buffer_count);
+	if (rc) {
+		(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+		return rc;
 	}
 
 	rc = q6usm_dec_cfg_blk(usf_xx->usc,
@@ -1221,10 +1232,15 @@
 		return -EFAULT;
 	}
 
-	/* version_info.buf is pointer to place for the version string */
+	if (version_info.buf_size < sizeof(DRV_VERSION)) {
+		pr_err("%s: buf_size (%d) < version string size (%d)\n",
+			__func__, version_info.buf_size, sizeof(DRV_VERSION));
+		return -EINVAL;
+	}
+
 	rc = copy_to_user(version_info.pbuf,
 			  DRV_VERSION,
-			  version_info.buf_size);
+			  sizeof(DRV_VERSION));
 	if (rc) {
 		pr_err("%s: copy to version_info.pbuf; rc=%d\n",
 			__func__, rc);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 97b1f39..a5748fb 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -658,13 +658,6 @@
 	  applications DSP processor. Say M if you want to enable this
 	  module.
 
-config MMC_GENERIC_CSDIO
-	tristate "Generic sdio driver"
-	default n
-	help
-	  SDIO function driver that extends SDIO card as character device
-	  in user space.
-
 config CSDIO_VENDOR_ID
 	hex "Card VendorId"
 	depends on MMC_GENERIC_CSDIO
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7589946..292cc99 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -65,7 +65,6 @@
 
 obj-$(CONFIG_TILE_SROM)		+= tile-srom.o
 obj-$(CONFIG_MSM_ROTATOR)	+= msm_rotator.o
-obj-$(CONFIG_MMC_GENERIC_CSDIO)	+= csdio.o
 obj-$(CONFIG_DIAG_CHAR)		+= diag/
 obj-$(CONFIG_MSM_ADSPRPC)       += adsprpc.o
 obj-$(CONFIG_MSM_RDBG)       += rdbg.o
diff --git a/drivers/char/csdio.c b/drivers/char/csdio.c
deleted file mode 100644
index 85306d3..0000000
--- a/drivers/char/csdio.c
+++ /dev/null
@@ -1,1074 +0,0 @@
-/*
- * Copyright (c) 2010, 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/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/gfp.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-
-/* Char device */
-#include <linux/cdev.h>
-#include <linux/fs.h>
-
-/* Sdio device */
-#include <linux/mmc/core.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-
-#include <linux/csdio.h>
-
-#define FALSE   0
-#define TRUE    1
-
-#define VERSION                     "0.5"
-#define CSDIO_NUM_OF_SDIO_FUNCTIONS 7
-#define CSDIO_DEV_NAME              "csdio"
-#define TP_DEV_NAME                 CSDIO_DEV_NAME"f"
-#define CSDIO_DEV_PERMISSIONS       0666
-
-#define CSDIO_SDIO_BUFFER_SIZE      (64*512)
-
-int csdio_major;
-int csdio_minor;
-int csdio_transport_nr_devs = CSDIO_NUM_OF_SDIO_FUNCTIONS;
-static uint csdio_vendor_id;
-static uint csdio_device_id;
-static char *host_name;
-
-static struct csdio_func_t {
-	struct sdio_func   *m_func;
-	int                 m_enabled;
-	struct cdev         m_cdev;      /* char device structure */
-	struct device      *m_device;
-	u32                 m_block_size;
-} *g_csdio_func_table[CSDIO_NUM_OF_SDIO_FUNCTIONS] = {0};
-
-struct csdio_t {
-	struct cdev             m_cdev;
-	struct device          *m_device;
-	struct class           *m_driver_class;
-	struct fasync_struct   *m_async_queue;
-	unsigned char           m_current_irq_mask; /* currently enabled irqs */
-	struct mmc_host        *m_host;
-	unsigned int            m_num_of_func;
-} g_csdio;
-
-struct csdio_file_descriptor {
-	struct csdio_func_t    *m_port;
-	u32                     m_block_mode;/* data tran. byte(0)/block(1) */
-	u32                     m_op_code;   /* address auto increment flag */
-	u32                     m_address;
-};
-
-static void *g_sdio_buffer;
-
-/*
- * Open and release
- */
-static int csdio_transport_open(struct inode *inode, struct file *filp)
-{
-	int ret = 0;
-	struct csdio_func_t *port = NULL; /*  device information */
-	struct sdio_func *func = NULL;
-	struct csdio_file_descriptor *descriptor = NULL;
-
-	port = container_of(inode->i_cdev, struct csdio_func_t, m_cdev);
-	func = port->m_func;
-	descriptor = kzalloc(sizeof(struct csdio_file_descriptor), GFP_KERNEL);
-	if (!descriptor) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	pr_info(TP_DEV_NAME"%d: open: func=%p, port=%p\n",
-			func->num, func, port);
-	sdio_claim_host(func);
-	ret = sdio_enable_func(func);
-	if (ret) {
-		pr_err(TP_DEV_NAME"%d:Enable func failed (%d)\n",
-				func->num, ret);
-		ret = -EIO;
-		goto free_descriptor;
-	}
-	descriptor->m_port = port;
-	filp->private_data = descriptor;
-	goto release_host;
-
-free_descriptor:
-	kfree(descriptor);
-release_host:
-	sdio_release_host(func);
-exit:
-	return ret;
-}
-
-static int csdio_transport_release(struct inode *inode, struct file *filp)
-{
-	int ret = 0;
-	struct csdio_file_descriptor *descriptor = filp->private_data;
-	struct csdio_func_t *port = descriptor->m_port;
-	struct sdio_func *func = port->m_func;
-
-	pr_info(TP_DEV_NAME"%d: release\n", func->num);
-	sdio_claim_host(func);
-	ret = sdio_disable_func(func);
-	if (ret) {
-		pr_err(TP_DEV_NAME"%d:Disable func failed(%d)\n",
-				func->num, ret);
-		ret = -EIO;
-	}
-	sdio_release_host(func);
-	kfree(descriptor);
-	return ret;
-}
-
-/*
- * Data management: read and write
- */
-static ssize_t csdio_transport_read(struct file *filp,
-		char __user *buf,
-		size_t count,
-		loff_t *f_pos)
-{
-	ssize_t ret = 0;
-	struct csdio_file_descriptor *descriptor = filp->private_data;
-	struct csdio_func_t *port = descriptor->m_port;
-	struct sdio_func *func = port->m_func;
-	size_t t_count = count;
-
-	if (descriptor->m_block_mode) {
-		pr_info(TP_DEV_NAME "%d: CMD53 read, Md:%d, Addr:0x%04X,"
-				" Un:%d (Bl:%d, BlSz:%d)\n", func->num,
-				descriptor->m_block_mode,
-				descriptor->m_address,
-				count*port->m_block_size,
-				count, port->m_block_size);
-		/* recalculate size */
-		count *= port->m_block_size;
-	}
-	sdio_claim_host(func);
-	if (descriptor->m_op_code) {
-		/* auto increment */
-		ret = sdio_memcpy_fromio(func, g_sdio_buffer,
-				descriptor->m_address, count);
-	} else { /* FIFO */
-		ret = sdio_readsb(func, g_sdio_buffer,
-				descriptor->m_address, count);
-	}
-	sdio_release_host(func);
-	if (!ret) {
-		if (copy_to_user(buf, g_sdio_buffer, count))
-			ret = -EFAULT;
-		else
-			ret = t_count;
-	}
-	if (ret < 0) {
-		pr_err(TP_DEV_NAME "%d: CMD53 read failed (%d)"
-				"(Md:%d, Addr:0x%04X, Sz:%d)\n",
-				func->num, ret,
-				descriptor->m_block_mode,
-				descriptor->m_address, count);
-	}
-	return ret;
-}
-
-static ssize_t csdio_transport_write(struct file *filp,
-		const char __user *buf,
-		size_t count,
-		loff_t *f_pos)
-{
-	ssize_t ret = 0;
-	struct csdio_file_descriptor *descriptor = filp->private_data;
-	struct csdio_func_t *port = descriptor->m_port;
-	struct sdio_func *func = port->m_func;
-	size_t t_count = count;
-
-	if (descriptor->m_block_mode)
-		count *= port->m_block_size;
-
-	if (copy_from_user(g_sdio_buffer, buf, count)) {
-		pr_err(TP_DEV_NAME"%d:copy_from_user failed\n", func->num);
-		ret = -EFAULT;
-	} else {
-		sdio_claim_host(func);
-		if (descriptor->m_op_code) {
-			/* auto increment */
-			ret = sdio_memcpy_toio(func, descriptor->m_address,
-					g_sdio_buffer, count);
-		} else {
-			/* FIFO */
-			ret = sdio_writesb(func, descriptor->m_address,
-					g_sdio_buffer, count);
-		}
-		sdio_release_host(func);
-		if (!ret) {
-			ret = t_count;
-		} else {
-			pr_err(TP_DEV_NAME "%d: CMD53 write failed (%d)"
-				"(Md:%d, Addr:0x%04X, Sz:%d)\n",
-				func->num, ret, descriptor->m_block_mode,
-				descriptor->m_address, count);
-		}
-	}
-	return ret;
-}
-
-/* disable interrupt for sdio client */
-static int disable_sdio_client_isr(struct sdio_func *func)
-{
-	int ret;
-
-	/* disable for all functions, to restore interrupts
-	 * use g_csdio.m_current_irq_mask */
-	sdio_f0_writeb(func, 0, SDIO_CCCR_IENx, &ret);
-	if (ret)
-		pr_err(CSDIO_DEV_NAME" Can't sdio_f0_writeb (%d)\n", ret);
-
-	return ret;
-}
-
-/*
- * This handles the interrupt from SDIO.
- */
-static void csdio_sdio_irq(struct sdio_func *func)
-{
-	int ret;
-
-	pr_info(CSDIO_DEV_NAME" csdio_sdio_irq: func=%d\n", func->num);
-	ret = disable_sdio_client_isr(func);
-	if (ret) {
-		pr_err(CSDIO_DEV_NAME" Can't disable client isr(%d)\n", ret);
-		return;
-	}
-	/*  signal asynchronous readers */
-	if (g_csdio.m_async_queue)
-		kill_fasync(&g_csdio.m_async_queue, SIGIO, POLL_IN);
-}
-
-/*
- * The ioctl() implementation
- */
-static int csdio_transport_ioctl(struct inode *inode,
-		struct file *filp,
-		unsigned int cmd,
-		unsigned long arg)
-{
-	int err = 0;
-	int ret = 0;
-	struct csdio_file_descriptor *descriptor = filp->private_data;
-	struct csdio_func_t *port = descriptor->m_port;
-	struct sdio_func *func = port->m_func;
-
-	/*  extract the type and number bitfields
-	    sanity check: return ENOTTY (inappropriate ioctl) before
-	    access_ok()
-	*/
-	if ((_IOC_TYPE(cmd) != CSDIO_IOC_MAGIC) ||
-			(_IOC_NR(cmd) > CSDIO_IOC_MAXNR)) {
-		pr_err(TP_DEV_NAME "Wrong ioctl command parameters\n");
-		ret = -ENOTTY;
-		goto exit;
-	}
-
-	/*  the direction is a bitmask, and VERIFY_WRITE catches R/W
-	 *  transfers. `Type' is user-oriented, while access_ok is
-	    kernel-oriented, so the concept of "read" and "write" is reversed
-	*/
-	if (_IOC_DIR(cmd) & _IOC_READ) {
-		err = !access_ok(VERIFY_WRITE, (void __user *)arg,
-				_IOC_SIZE(cmd));
-	} else {
-		if (_IOC_DIR(cmd) & _IOC_WRITE) {
-			err =  !access_ok(VERIFY_READ, (void __user *)arg,
-					_IOC_SIZE(cmd));
-		}
-	}
-	if (err) {
-		pr_err(TP_DEV_NAME "Wrong ioctl access direction\n");
-		ret = -EFAULT;
-		goto exit;
-	}
-
-	switch (cmd) {
-	case CSDIO_IOC_SET_OP_CODE:
-		{
-			pr_info(TP_DEV_NAME"%d:SET_OP_CODE=%d\n",
-					func->num, descriptor->m_op_code);
-			ret = get_user(descriptor->m_op_code,
-					(unsigned char __user *)arg);
-			if (ret) {
-				pr_err(TP_DEV_NAME"%d:SET_OP_CODE get data"
-						" from user space failed(%d)\n",
-						func->num, ret);
-				ret = -ENOTTY;
-				break;
-			}
-		}
-		break;
-	case CSDIO_IOC_FUNCTION_SET_BLOCK_SIZE:
-		{
-			unsigned block_size;
-
-			ret = get_user(block_size, (unsigned __user *)arg);
-			if (ret) {
-				pr_err(TP_DEV_NAME"%d:SET_BLOCK_SIZE get data"
-						" from user space failed(%d)\n",
-						func->num, ret);
-				ret = -ENOTTY;
-				break;
-			}
-			pr_info(TP_DEV_NAME"%d:SET_BLOCK_SIZE=%d\n",
-					func->num, block_size);
-			sdio_claim_host(func);
-			ret = sdio_set_block_size(func, block_size);
-			if (!ret) {
-				port->m_block_size = block_size;
-			} else {
-				pr_err(TP_DEV_NAME"%d:SET_BLOCK_SIZE set block"
-						" size to %d failed (%d)\n",
-						func->num, block_size, ret);
-				ret = -ENOTTY;
-				break;
-			}
-			sdio_release_host(func);
-		}
-		break;
-	case CSDIO_IOC_SET_BLOCK_MODE:
-		{
-			pr_info(TP_DEV_NAME"%d:SET_BLOCK_MODE=%d\n",
-					func->num, descriptor->m_block_mode);
-			ret = get_user(descriptor->m_block_mode,
-					(unsigned char __user *)arg);
-			if (ret) {
-				pr_err(TP_DEV_NAME"%d:SET_BLOCK_MODE get data"
-						" from user space failed\n",
-						func->num);
-				ret = -ENOTTY;
-				break;
-			}
-		}
-		break;
-	case CSDIO_IOC_CMD52:
-		{
-			struct csdio_cmd52_ctrl_t cmd52ctrl;
-			int cmd52ret;
-
-			if (copy_from_user(&cmd52ctrl,
-					(const unsigned char __user *)arg,
-					sizeof(cmd52ctrl))) {
-				pr_err(TP_DEV_NAME"%d:IOC_CMD52 get data"
-						" from user space failed\n",
-						func->num);
-				ret = -ENOTTY;
-				break;
-			}
-			sdio_claim_host(func);
-			if (cmd52ctrl.m_write)
-				sdio_writeb(func, cmd52ctrl.m_data,
-						cmd52ctrl.m_address, &cmd52ret);
-			else
-				cmd52ctrl.m_data = sdio_readb(func,
-						cmd52ctrl.m_address, &cmd52ret);
-
-			cmd52ctrl.m_ret = cmd52ret;
-			sdio_release_host(func);
-			if (cmd52ctrl.m_ret)
-				pr_err(TP_DEV_NAME"%d:IOC_CMD52 failed (%d)\n",
-						func->num, cmd52ctrl.m_ret);
-
-			if (copy_to_user((unsigned char __user *)arg,
-						&cmd52ctrl,
-						sizeof(cmd52ctrl))) {
-				pr_err(TP_DEV_NAME"%d:IOC_CMD52 put data"
-						" to user space failed\n",
-						func->num);
-				ret = -ENOTTY;
-				break;
-			}
-		}
-		break;
-	case CSDIO_IOC_CMD53:
-		{
-			struct csdio_cmd53_ctrl_t csdio_cmd53_ctrl;
-
-			if (copy_from_user(&csdio_cmd53_ctrl,
-						(const char __user *)arg,
-						sizeof(csdio_cmd53_ctrl))) {
-				ret = -EPERM;
-				pr_err(TP_DEV_NAME"%d:"
-					"Get data from user space failed\n",
-					func->num);
-				break;
-			}
-			descriptor->m_block_mode =
-				csdio_cmd53_ctrl.m_block_mode;
-			descriptor->m_op_code = csdio_cmd53_ctrl.m_op_code;
-			descriptor->m_address = csdio_cmd53_ctrl.m_address;
-		}
-		break;
-	case CSDIO_IOC_CONNECT_ISR:
-		{
-			pr_info(CSDIO_DEV_NAME" SDIO_CONNECT_ISR"
-				" func=%d, csdio_sdio_irq=%x\n",
-				func->num, (unsigned int)csdio_sdio_irq);
-			sdio_claim_host(func);
-			ret = sdio_claim_irq(func, csdio_sdio_irq);
-			sdio_release_host(func);
-			if (ret) {
-				pr_err(CSDIO_DEV_NAME" SDIO_CONNECT_ISR"
-						" claim irq failed(%d)\n", ret);
-			} else {
-				/* update current irq mask for disable/enable */
-				g_csdio.m_current_irq_mask |= (1 << func->num);
-			}
-		}
-		break;
-	case CSDIO_IOC_DISCONNECT_ISR:
-		{
-			pr_info(CSDIO_DEV_NAME " SDIO_DISCONNECT_ISR func=%d\n",
-					func->num);
-			sdio_claim_host(func);
-			sdio_release_irq(func);
-			sdio_release_host(func);
-			/* update current irq mask for disable/enable */
-			g_csdio.m_current_irq_mask &= ~(1 << func->num);
-		}
-		break;
-	default:  /*  redundant, as cmd was checked against MAXNR */
-		pr_warning(TP_DEV_NAME"%d: Redundant IOCTL\n",
-				func->num);
-		ret = -ENOTTY;
-	}
-exit:
-	return ret;
-}
-
-static const struct file_operations csdio_transport_fops = {
-	.owner =    THIS_MODULE,
-	.read =     csdio_transport_read,
-	.write =    csdio_transport_write,
-	.ioctl =    csdio_transport_ioctl,
-	.open =     csdio_transport_open,
-	.release =  csdio_transport_release,
-};
-
-static void csdio_transport_cleanup(struct csdio_func_t *port)
-{
-	int devno = MKDEV(csdio_major, csdio_minor + port->m_func->num);
-	device_destroy(g_csdio.m_driver_class, devno);
-	port->m_device = NULL;
-	cdev_del(&port->m_cdev);
-}
-
-#if defined(CONFIG_DEVTMPFS)
-static inline int csdio_cdev_update_permissions(
-    const char *devname, int dev_minor)
-{
-	return 0;
-}
-#else
-static int csdio_cdev_update_permissions(
-    const char *devname, int dev_minor)
-{
-	int ret = 0;
-	mm_segment_t fs;
-	struct file *file;
-	struct inode *inode;
-	struct iattr newattrs;
-	int mode = CSDIO_DEV_PERMISSIONS;
-	char dev_file[64];
-
-	fs = get_fs();
-	set_fs(get_ds());
-
-	snprintf(dev_file, sizeof(dev_file), "/dev/%s%d",
-		devname, dev_minor);
-	file = filp_open(dev_file, O_RDWR, 0);
-	if (IS_ERR(file)) {
-		ret = -EFAULT;
-		goto exit;
-	}
-
-	inode = file->f_path.dentry->d_inode;
-
-	mutex_lock(&inode->i_mutex);
-	newattrs.ia_mode =
-		(mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-	ret = notify_change(file->f_path.dentry, &newattrs);
-	mutex_unlock(&inode->i_mutex);
-
-	filp_close(file, NULL);
-
-exit:
-	set_fs(fs);
-	return ret;
-}
-#endif
-
-static struct device *csdio_cdev_init(struct cdev *char_dev,
-		const struct file_operations *file_op, int dev_minor,
-		const char *devname, struct device *parent)
-{
-	int ret = 0;
-	struct device *new_device = NULL;
-	dev_t devno = MKDEV(csdio_major, dev_minor);
-
-	/*  Initialize transport device */
-	cdev_init(char_dev, file_op);
-	char_dev->owner = THIS_MODULE;
-	char_dev->ops = file_op;
-	ret = cdev_add(char_dev, devno, 1);
-
-	/*  Fail gracefully if need be */
-	if (ret) {
-		pr_warning("Error %d adding CSDIO char device '%s%d'",
-				ret, devname, dev_minor);
-		goto exit;
-	}
-	pr_info("'%s%d' char driver registered\n", devname, dev_minor);
-
-	/*  create a /dev entry for transport drivers */
-	new_device = device_create(g_csdio.m_driver_class, parent, devno, NULL,
-			"%s%d", devname, dev_minor);
-	if (!new_device) {
-		pr_err("Can't create device node '/dev/%s%d'\n",
-				devname, dev_minor);
-		goto cleanup;
-	}
-	/* no irq attached */
-	g_csdio.m_current_irq_mask = 0;
-
-	if (csdio_cdev_update_permissions(devname, dev_minor)) {
-		pr_warning("%s%d: Unable to update access permissions of the"
-			" '/dev/%s%d'\n",
-			devname, dev_minor, devname, dev_minor);
-	}
-
-	pr_info("%s%d: Device node '/dev/%s%d' created successfully\n",
-			devname, dev_minor, devname, dev_minor);
-	goto exit;
-cleanup:
-	cdev_del(char_dev);
-exit:
-	return new_device;
-}
-
-/* Looks for first non empty function, returns NULL otherwise */
-static struct sdio_func *get_active_func(void)
-{
-	int i;
-
-	for (i = 0; i < CSDIO_NUM_OF_SDIO_FUNCTIONS; i++) {
-		if (g_csdio_func_table[i])
-			return g_csdio_func_table[i]->m_func;
-	}
-	return NULL;
-}
-
-static ssize_t
-show_vdd(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	if (NULL == g_csdio.m_host)
-		return snprintf(buf, PAGE_SIZE, "N/A\n");
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-		g_csdio.m_host->ios.vdd);
-}
-
-static int
-set_vdd_helper(int value)
-{
-	struct mmc_ios *ios = NULL;
-
-	if (NULL == g_csdio.m_host) {
-		pr_err("%s0: Set VDD, no MMC host assigned\n", CSDIO_DEV_NAME);
-		return -ENXIO;
-	}
-
-	mmc_claim_host(g_csdio.m_host);
-	ios = &g_csdio.m_host->ios;
-	ios->vdd = value;
-	g_csdio.m_host->ops->set_ios(g_csdio.m_host, ios);
-	mmc_release_host(g_csdio.m_host);
-	return 0;
-}
-
-static ssize_t
-set_vdd(struct device *dev, struct device_attribute *att,
-	const char *buf, size_t count)
-{
-	int value = 0;
-
-	sscanf(buf, "%d", &value);
-	if (set_vdd_helper(value))
-		return -ENXIO;
-	return count;
-}
-
-static DEVICE_ATTR(vdd, S_IRUGO | S_IWUSR,
-	show_vdd, set_vdd);
-
-static struct attribute *dev_attrs[] = {
-	&dev_attr_vdd.attr,
-	NULL,
-};
-
-static struct attribute_group dev_attr_grp = {
-	.attrs = dev_attrs,
-};
-
-/*
- * The ioctl() implementation for control device
- */
-static int csdio_ctrl_ioctl(struct inode *inode, struct file *filp,
-		unsigned int cmd, unsigned long arg)
-{
-	int err = 0;
-	int ret = 0;
-
-	pr_info("CSDIO ctrl ioctl.\n");
-
-	/*  extract the type and number bitfields
-	    sanity check: return ENOTTY (inappropriate ioctl) before
-	    access_ok()
-	*/
-	if ((_IOC_TYPE(cmd) != CSDIO_IOC_MAGIC) ||
-			(_IOC_NR(cmd) > CSDIO_IOC_MAXNR)) {
-		pr_err(CSDIO_DEV_NAME "Wrong ioctl command parameters\n");
-		ret = -ENOTTY;
-		goto exit;
-	}
-
-	/*  the direction is a bitmask, and VERIFY_WRITE catches R/W
-	  transfers. `Type' is user-oriented, while access_ok is
-	  kernel-oriented, so the concept of "read" and "write" is reversed
-	  */
-	if (_IOC_DIR(cmd) & _IOC_READ) {
-		err = !access_ok(VERIFY_WRITE, (void __user *)arg,
-				_IOC_SIZE(cmd));
-	} else {
-		if (_IOC_DIR(cmd) & _IOC_WRITE)
-			err =  !access_ok(VERIFY_READ, (void __user *)arg,
-					_IOC_SIZE(cmd));
-	}
-	if (err) {
-		pr_err(CSDIO_DEV_NAME "Wrong ioctl access direction\n");
-		ret = -EFAULT;
-		goto exit;
-	}
-
-	switch (cmd) {
-	case CSDIO_IOC_ENABLE_HIGHSPEED_MODE:
-		pr_info(CSDIO_DEV_NAME" ENABLE_HIGHSPEED_MODE\n");
-		break;
-	case CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS:
-		{
-			struct mmc_host *host = g_csdio.m_host;
-			struct mmc_ios *ios = NULL;
-
-			if (NULL == host) {
-				pr_err("%s0: "
-					"CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS,"
-					" no MMC host assigned\n",
-					CSDIO_DEV_NAME);
-				ret = -EFAULT;
-				goto exit;
-			}
-			ios = &host->ios;
-
-			mmc_claim_host(host);
-			ret = get_user(host->ios.clock,
-					(unsigned int __user *)arg);
-			if (ret) {
-				pr_err(CSDIO_DEV_NAME
-					" get data from user space failed\n");
-			} else {
-				pr_err(CSDIO_DEV_NAME
-					"SET_DATA_TRANSFER_CLOCKS(%d-%d)(%d)\n",
-					host->f_min, host->f_max,
-					host->ios.clock);
-				host->ops->set_ios(host, ios);
-			}
-			mmc_release_host(host);
-		}
-		break;
-	case CSDIO_IOC_ENABLE_ISR:
-		{
-			int ret;
-			unsigned char reg;
-			struct sdio_func *func = get_active_func();
-
-			if (!func) {
-				pr_err(CSDIO_DEV_NAME " CSDIO_IOC_ENABLE_ISR"
-						" no active sdio function\n");
-				ret = -EFAULT;
-				goto exit;
-			}
-			pr_info(CSDIO_DEV_NAME
-					" CSDIO_IOC_ENABLE_ISR func=%d\n",
-					func->num);
-			reg = g_csdio.m_current_irq_mask | 1;
-
-			sdio_claim_host(func);
-			sdio_f0_writeb(func, reg, SDIO_CCCR_IENx, &ret);
-			sdio_release_host(func);
-			if (ret) {
-				pr_err(CSDIO_DEV_NAME
-						" Can't sdio_f0_writeb (%d)\n",
-						ret);
-				goto exit;
-			}
-		}
-		break;
-	case CSDIO_IOC_DISABLE_ISR:
-		{
-			int ret;
-			struct sdio_func *func = get_active_func();
-			if (!func) {
-				pr_err(CSDIO_DEV_NAME " CSDIO_IOC_ENABLE_ISR"
-						" no active sdio function\n");
-				ret = -EFAULT;
-				goto exit;
-			}
-			pr_info(CSDIO_DEV_NAME
-					" CSDIO_IOC_DISABLE_ISR func=%p\n",
-					func);
-
-			sdio_claim_host(func);
-			ret = disable_sdio_client_isr(func);
-			sdio_release_host(func);
-			if (ret) {
-				pr_err("%s0: Can't disable client isr (%d)\n",
-					CSDIO_DEV_NAME, ret);
-				goto exit;
-			}
-		}
-	break;
-	case CSDIO_IOC_SET_VDD:
-		{
-			unsigned int vdd = 0;
-
-			ret = get_user(vdd, (unsigned int __user *)arg);
-			if (ret) {
-				pr_err("%s0: CSDIO_IOC_SET_VDD,"
-					" get data from user space failed\n",
-					CSDIO_DEV_NAME);
-				goto exit;
-			}
-			pr_info(CSDIO_DEV_NAME" CSDIO_IOC_SET_VDD - %d\n", vdd);
-
-			ret = set_vdd_helper(vdd);
-			if (ret)
-				goto exit;
-		}
-	break;
-	case CSDIO_IOC_GET_VDD:
-		{
-			if (NULL == g_csdio.m_host) {
-				pr_err("%s0: CSDIO_IOC_GET_VDD,"
-					" no MMC host assigned\n",
-					CSDIO_DEV_NAME);
-				ret = -EFAULT;
-				goto exit;
-			}
-			ret = put_user(g_csdio.m_host->ios.vdd,
-				(unsigned short __user *)arg);
-			if (ret) {
-				pr_err("%s0: CSDIO_IOC_GET_VDD, put data"
-					" to user space failed\n",
-					CSDIO_DEV_NAME);
-				goto exit;
-			}
-		}
-	break;
-	default:  /*  redundant, as cmd was checked against MAXNR */
-		pr_warning(CSDIO_DEV_NAME" Redundant IOCTL\n");
-		ret = -ENOTTY;
-	}
-exit:
-	return ret;
-}
-
-static int csdio_ctrl_fasync(int fd, struct file *filp, int mode)
-{
-	pr_info(CSDIO_DEV_NAME
-			" csdio_ctrl_fasync: fd=%d, filp=%p, mode=%d\n",
-			fd, filp, mode);
-	return fasync_helper(fd, filp, mode, &g_csdio.m_async_queue);
-}
-
-/*
- * Open and close
- */
-static int csdio_ctrl_open(struct inode *inode, struct file *filp)
-{
-	int ret = 0;
-	struct csdio_t *csdio_ctrl_drv = NULL; /*  device information */
-
-	pr_info("CSDIO ctrl open.\n");
-	csdio_ctrl_drv = container_of(inode->i_cdev, struct csdio_t, m_cdev);
-	filp->private_data = csdio_ctrl_drv; /*  for other methods */
-	return ret;
-}
-
-static int csdio_ctrl_release(struct inode *inode, struct file *filp)
-{
-	pr_info("CSDIO ctrl release.\n");
-	/*  remove this filp from the asynchronously notified filp's */
-	csdio_ctrl_fasync(-1, filp, 0);
-	return 0;
-}
-
-static const struct file_operations csdio_ctrl_fops = {
-	.owner =	THIS_MODULE,
-	.ioctl =	csdio_ctrl_ioctl,
-	.open  =	csdio_ctrl_open,
-	.release =	csdio_ctrl_release,
-	.fasync =	csdio_ctrl_fasync,
-};
-
-static int csdio_probe(struct sdio_func *func,
-		const struct sdio_device_id *id)
-{
-	struct csdio_func_t *port;
-	int ret = 0;
-	struct mmc_host *host = func->card->host;
-
-	if (NULL != g_csdio.m_host && g_csdio.m_host != host) {
-		pr_info("%s: Device is on unexpected host\n",
-			CSDIO_DEV_NAME);
-		ret = -ENODEV;
-		goto exit;
-	}
-
-	/* enforce single instance policy */
-	if (g_csdio_func_table[func->num-1]) {
-		pr_err("%s - only single SDIO device supported",
-				sdio_func_id(func));
-		ret = -EEXIST;
-		goto exit;
-	}
-
-	port = kzalloc(sizeof(struct csdio_func_t), GFP_KERNEL);
-	if (!port) {
-		pr_err("Can't allocate memory\n");
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	/* initialize SDIO side */
-	port->m_func = func;
-	sdio_set_drvdata(func, port);
-
-	pr_info("%s - SDIO device found. Function %d\n",
-			sdio_func_id(func), func->num);
-
-	port->m_device = csdio_cdev_init(&port->m_cdev, &csdio_transport_fops,
-			csdio_minor + port->m_func->num,
-			TP_DEV_NAME, &port->m_func->dev);
-
-	/* create appropriate char device */
-	if (!port->m_device)
-		goto free;
-
-	if (0 == g_csdio.m_num_of_func && NULL == host_name)
-		g_csdio.m_host = host;
-	g_csdio.m_num_of_func++;
-	g_csdio_func_table[func->num-1] = port;
-	port->m_enabled = TRUE;
-	goto exit;
-free:
-	kfree(port);
-exit:
-	return ret;
-}
-
-static void csdio_remove(struct sdio_func *func)
-{
-	struct csdio_func_t *port = sdio_get_drvdata(func);
-
-	csdio_transport_cleanup(port);
-	sdio_claim_host(func);
-	sdio_release_irq(func);
-	sdio_disable_func(func);
-	sdio_release_host(func);
-	kfree(port);
-	g_csdio_func_table[func->num-1] = NULL;
-	g_csdio.m_num_of_func--;
-	if (0 == g_csdio.m_num_of_func && NULL == host_name)
-		g_csdio.m_host = NULL;
-	pr_info("%s%d: Device removed (%s). Function %d\n",
-		CSDIO_DEV_NAME, func->num, sdio_func_id(func), func->num);
-}
-
-/* CONFIG_CSDIO_VENDOR_ID and CONFIG_CSDIO_DEVICE_ID are defined in Kconfig.
- * Use kernel configuration to change the values or overwrite them through
- * module parameters */
-static struct sdio_device_id csdio_ids[] = {
-	{ SDIO_DEVICE(CONFIG_CSDIO_VENDOR_ID, CONFIG_CSDIO_DEVICE_ID) },
-	{ /* end: all zeroes */},
-};
-
-MODULE_DEVICE_TABLE(sdio, csdio_ids);
-
-static struct sdio_driver csdio_driver = {
-	.probe      = csdio_probe,
-	.remove     = csdio_remove,
-	.name       = "csdio",
-	.id_table   = csdio_ids,
-};
-
-static void __exit csdio_exit(void)
-{
-	dev_t devno = MKDEV(csdio_major, csdio_minor);
-
-	sdio_unregister_driver(&csdio_driver);
-	sysfs_remove_group(&g_csdio.m_device->kobj, &dev_attr_grp);
-	kfree(g_sdio_buffer);
-	device_destroy(g_csdio.m_driver_class, devno);
-	cdev_del(&g_csdio.m_cdev);
-	class_destroy(g_csdio.m_driver_class);
-	unregister_chrdev_region(devno, csdio_transport_nr_devs);
-	pr_info("%s: Exit driver module\n", CSDIO_DEV_NAME);
-}
-
-static char *csdio_devnode(struct device *dev, mode_t *mode)
-{
-	*mode = CSDIO_DEV_PERMISSIONS;
-	return NULL;
-}
-
-static int __init csdio_init(void)
-{
-	int ret = 0;
-	dev_t devno = 0;
-
-	pr_info("Init CSDIO driver module.\n");
-
-	/*  Get a range of minor numbers to work with, asking for a dynamic */
-	/*  major unless directed otherwise at load time. */
-	if (csdio_major) {
-		devno = MKDEV(csdio_major, csdio_minor);
-		ret = register_chrdev_region(devno, csdio_transport_nr_devs,
-				CSDIO_DEV_NAME);
-	} else {
-		ret = alloc_chrdev_region(&devno, csdio_minor,
-				csdio_transport_nr_devs, CSDIO_DEV_NAME);
-		csdio_major = MAJOR(devno);
-	}
-	if (ret < 0) {
-		pr_err("CSDIO: can't get major %d\n", csdio_major);
-		goto exit;
-	}
-	pr_info("CSDIO char driver major number is %d\n", csdio_major);
-
-	/* kernel module got parameters: overwrite vendor and device id's */
-	if ((csdio_vendor_id != 0) && (csdio_device_id != 0)) {
-		csdio_ids[0].vendor = (u16)csdio_vendor_id;
-		csdio_ids[0].device = (u16)csdio_device_id;
-	}
-
-	/*  prepare create /dev/... instance */
-	g_csdio.m_driver_class = class_create(THIS_MODULE, CSDIO_DEV_NAME);
-	if (IS_ERR(g_csdio.m_driver_class)) {
-		ret = -ENOMEM;
-		pr_err(CSDIO_DEV_NAME " class_create failed\n");
-		goto unregister_region;
-	}
-	g_csdio.m_driver_class->devnode = csdio_devnode;
-
-	/*  create CSDIO ctrl driver */
-	g_csdio.m_device = csdio_cdev_init(&g_csdio.m_cdev,
-		&csdio_ctrl_fops, csdio_minor, CSDIO_DEV_NAME, NULL);
-	if (!g_csdio.m_device) {
-		pr_err("%s: Unable to create ctrl driver\n",
-			CSDIO_DEV_NAME);
-		goto destroy_class;
-	}
-
-	g_sdio_buffer = kmalloc(CSDIO_SDIO_BUFFER_SIZE, GFP_KERNEL);
-	if (!g_sdio_buffer) {
-		pr_err("Unable to allocate %d bytes\n", CSDIO_SDIO_BUFFER_SIZE);
-		ret = -ENOMEM;
-		goto destroy_cdev;
-	}
-
-	ret = sysfs_create_group(&g_csdio.m_device->kobj, &dev_attr_grp);
-	if (ret) {
-		pr_err("%s: Unable to create device attribute\n",
-			CSDIO_DEV_NAME);
-		goto free_sdio_buff;
-	}
-
-	g_csdio.m_num_of_func = 0;
-	g_csdio.m_host = NULL;
-
-	if (NULL != host_name) {
-		struct device *dev = bus_find_device_by_name(&platform_bus_type,
-			NULL, host_name);
-		if (NULL != dev) {
-			g_csdio.m_host = dev_get_drvdata(dev);
-		} else {
-			pr_err("%s: Host '%s' doesn't exist!\n", CSDIO_DEV_NAME,
-				host_name);
-		}
-	}
-
-	pr_info("%s: Match with VendorId=0x%X, DeviceId=0x%X, Host = %s\n",
-		CSDIO_DEV_NAME, csdio_device_id, csdio_vendor_id,
-		(NULL == host_name) ? "Any" : host_name);
-
-	/* register sdio driver */
-	ret = sdio_register_driver(&csdio_driver);
-	if (ret) {
-		pr_err("%s: Unable to register as SDIO driver\n",
-			CSDIO_DEV_NAME);
-		goto remove_group;
-	}
-
-	goto exit;
-
-remove_group:
-	sysfs_remove_group(&g_csdio.m_device->kobj, &dev_attr_grp);
-free_sdio_buff:
-	kfree(g_sdio_buffer);
-destroy_cdev:
-	cdev_del(&g_csdio.m_cdev);
-destroy_class:
-	class_destroy(g_csdio.m_driver_class);
-unregister_region:
-	unregister_chrdev_region(devno, csdio_transport_nr_devs);
-exit:
-	return ret;
-}
-module_param(csdio_vendor_id, uint, S_IRUGO);
-module_param(csdio_device_id, uint, S_IRUGO);
-module_param(host_name, charp, S_IRUGO);
-
-module_init(csdio_init);
-module_exit(csdio_exit);
-
-MODULE_AUTHOR("The Linux Foundation");
-MODULE_DESCRIPTION("CSDIO device driver version " VERSION);
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 070b5ac..eba60ea 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2051,6 +2051,8 @@
 
 	device->reset_counter++;
 
+	set_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv);
+
 	return 0;
 
 error_rb_stop:
@@ -2088,7 +2090,25 @@
 	set_user_nice(current, _wake_nice);
 
 	mutex_lock(&device->mutex);
-	_status = _adreno_start(adreno_dev);
+	/*
+	 *  If adreno start is already called, no need to call it again
+	 *  it can lead to unpredictable behavior if we try to start
+	 *  the device that is already started.
+	 *  Below is the sequence of events that can go bad without the check
+	 *  1) thread 1 calls adreno_start to be scheduled on high priority wq
+	 *  2) thread 2 calls adreno_start with normal priority
+	 *  3) thread 1 after checking the device to be in slumber state gives
+	 *     up mutex to be scheduled on high priority wq
+	 *  4) thread 2 after checking the device to be in slumber state gets
+	 *     the mutex and finishes adreno_start before thread 1 is scheduled
+	 *     on high priority wq.
+	 *  5) thread 1 gets scheduled on high priority wq and executes
+	 *     adreno_start again. This leads to unpredictable behavior.
+	 */
+	if (!test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
+		_status = _adreno_start(adreno_dev);
+	else
+		_status = 0;
 	mutex_unlock(&device->mutex);
 }
 
@@ -2149,6 +2169,8 @@
 
 	kgsl_cffdump_close(device);
 
+	clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 1b538a7..800caf1 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -216,6 +216,7 @@
 	ADRENO_DEVICE_PWRON = 0,
 	ADRENO_DEVICE_PWRON_FIXUP = 1,
 	ADRENO_DEVICE_INITIALIZED = 2,
+	ADRENO_DEVICE_STARTED = 3,
 };
 
 #define PERFCOUNTER_FLAG_NONE 0x0
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 505be69..f0114ad 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -141,7 +141,7 @@
 
 static inline void *kgsl_sg_alloc(unsigned int sglen)
 {
-	if (sglen >= ULONG_MAX / sizeof(struct scatterlist))
+	if ((sglen == 0) || (sglen >= ULONG_MAX / sizeof(struct scatterlist)))
 		return NULL;
 
 	if ((sglen * sizeof(struct scatterlist)) <  PAGE_SIZE)
diff --git a/drivers/input/misc/cm36283.c b/drivers/input/misc/cm36283.c
index ceeb67b..5c89c0c 100644
--- a/drivers/input/misc/cm36283.c
+++ b/drivers/input/misc/cm36283.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/delay.h>
-#include <linux/earlysuspend.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/sensors.h>
@@ -118,7 +117,6 @@
 	struct input_dev *ls_input_dev;
 	struct input_dev *ps_input_dev;
 
-	struct early_suspend early_suspend;
 	struct i2c_client *i2c_client;
 	struct workqueue_struct *lp_wq;
 
@@ -1426,29 +1424,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void cm36283_early_suspend(struct early_suspend *h)
-{
-	struct cm36283_info *lpi = lp_info;
-
-	D("[LS][CM36283] %s\n", __func__);
-
-	if (lpi->als_enable)
-		lightsensor_disable(lpi);
-
-}
-
-static void cm36283_late_resume(struct early_suspend *h)
-{
-	struct cm36283_info *lpi = lp_info;
-
-	D("[LS][CM36283] %s\n", __func__);
-
-	if (!lpi->als_enable)
-		lightsensor_enable(lpi);
-}
-#endif
-
 static int cm36283_parse_dt(struct device *dev,
 				struct cm36283_platform_data *pdata)
 {
@@ -1744,13 +1719,6 @@
 	if (ret)
 		goto err_create_ps_device_file;
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	lpi->early_suspend.level =
-			EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
-	lpi->early_suspend.suspend = cm36283_early_suspend;
-	lpi->early_suspend.resume = cm36283_late_resume;
-	register_early_suspend(&lpi->early_suspend);
-#endif
 	ret = sensors_classdev_register(&client->dev, &sensors_light_cdev);
 	if (ret)
 		goto err_create_ps_device_file;
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 3b7bf5a..fab209e 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -325,32 +325,32 @@
 {
 	struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
 	unsigned long val;
+	u32 enable;
 
 	if (kstrtoul(buf, 10, &val))
 		return -EINVAL;
-	sensor->enable = (u32)val == 0 ? 0 : 1;
-	if (sensor->enable) {
+	enable = (u32)val == 0 ? 0 : 1;
+	if (enable && (!sensor->enable)) {
+		sensor->enable = enable;
 		pm_runtime_get_sync(sensor->dev);
-		gpio_set_value(sensor->enable_gpio, 1);
 		if (sensor->use_poll)
 			schedule_delayed_work(&sensor->input_work,
 				msecs_to_jiffies(sensor->poll_interval));
-		else {
-			i2c_smbus_write_byte_data(sensor->client,
-					MPU3050_INT_CFG,
-					MPU3050_ACTIVE_LOW |
-					MPU3050_OPEN_DRAIN |
-					MPU3050_RAW_RDY_EN);
+		else
 			enable_irq(sensor->client->irq);
-		}
-	} else {
+	} else if (!enable && sensor->enable) {
 		if (sensor->use_poll)
 			cancel_delayed_work_sync(&sensor->input_work);
 		else
 			disable_irq(sensor->client->irq);
-		gpio_set_value(sensor->enable_gpio, 0);
-		pm_runtime_put(sensor->dev);
+		pm_runtime_put_sync(sensor->dev);
+		sensor->enable = enable;
+	} else {
+		dev_warn(&sensor->client->dev,
+				"ignore enable state change from %d to %d\n",
+				sensor->enable, enable);
 	}
+
 	return count;
 }
 
@@ -485,54 +485,6 @@
 }
 
 /**
- *	mpu3050_input_open	-	called on input event open
- *	@input: input dev of opened device
- *
- *	The input layer calls this function when input event is opened. The
- *	function will push the device to resume. Then, the device is ready
- *	to provide data.
- */
-static int mpu3050_input_open(struct input_dev *input)
-{
-	struct mpu3050_sensor *sensor = input_get_drvdata(input);
-	int error;
-
-	pm_runtime_get_sync(sensor->dev);
-
-	/* Enable interrupts */
-	error = i2c_smbus_write_byte_data(sensor->client, MPU3050_INT_CFG,
-					MPU3050_ACTIVE_LOW |
-					MPU3050_OPEN_DRAIN |
-					MPU3050_RAW_RDY_EN);
-	if (error < 0) {
-		pm_runtime_put(sensor->dev);
-		return error;
-	}
-	if (sensor->use_poll)
-		schedule_delayed_work(&sensor->input_work,
-			msecs_to_jiffies(sensor->poll_interval));
-
-	return 0;
-}
-
-/**
- *	mpu3050_input_close	-	called on input event close
- *	@input: input dev of closed device
- *
- *	The input layer calls this function when input event is closed. The
- *	function will push the device to suspend.
- */
-static void mpu3050_input_close(struct input_dev *input)
-{
-	struct mpu3050_sensor *sensor = input_get_drvdata(input);
-
-	if (sensor->use_poll)
-		cancel_delayed_work_sync(&sensor->input_work);
-
-	pm_runtime_put(sensor->dev);
-}
-
-/**
  *	mpu3050_interrupt_thread	-	handle an IRQ
  *	@irq: interrupt numner
  *	@data: the sensor
@@ -588,18 +540,12 @@
  *
  *	Called during device probe; configures the sampling method.
  */
-static int __devinit mpu3050_hw_init(struct mpu3050_sensor *sensor)
+static int mpu3050_hw_init(struct mpu3050_sensor *sensor)
 {
 	struct i2c_client *client = sensor->client;
 	int ret;
 	u8 reg;
 
-	/* Reset */
-	ret = i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM,
-					MPU3050_PWR_MGM_RESET);
-	if (ret < 0)
-		return ret;
-
 	ret = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
 	if (ret < 0)
 		return ret;
@@ -624,6 +570,16 @@
 	if (ret < 0)
 		return ret;
 
+	/* Enable interrupts */
+	if (!sensor->use_poll) {
+		reg = MPU3050_ACTIVE_LOW;
+		reg |= MPU3050_OPEN_DRAIN;
+		reg |= MPU3050_RAW_RDY_EN;
+		ret = i2c_smbus_write_byte_data(client, MPU3050_INT_CFG, reg);
+		if (ret < 0)
+			return ret;
+	}
+
 	return 0;
 }
 #ifdef CONFIG_OF
@@ -750,9 +706,6 @@
 	idev->name = "MPU3050";
 	idev->id.bustype = BUS_I2C;
 
-	idev->open = mpu3050_input_open;
-	idev->close = mpu3050_input_close;
-
 	input_set_capability(idev, EV_ABS, ABS_MISC);
 	input_set_abs_params(idev, ABS_X,
 			     MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
@@ -813,6 +766,9 @@
 		disable_irq(client->irq);
 	}
 
+	sensor->enable = 0;
+	mpu3050_set_power_mode(client, 0);
+
 	error = input_register_device(idev);
 	if (error) {
 		dev_err(&client->dev, "failed to register input device\n");
@@ -893,10 +849,11 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
 
-	if (!sensor->use_poll)
-		disable_irq(client->irq);
-
-	mpu3050_set_power_mode(client, 0);
+	if (sensor->enable) {
+		if (!sensor->use_poll)
+			disable_irq(client->irq);
+		mpu3050_set_power_mode(client, 0);
+	}
 
 	return 0;
 }
@@ -912,16 +869,64 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
 
-	mpu3050_set_power_mode(client, 1);
+	if (sensor->enable) {
+		mpu3050_set_power_mode(client, 1);
+		mpu3050_hw_init(sensor);
+		if (!sensor->use_poll)
+			enable_irq(client->irq);
+	}
 
-	if (!sensor->use_poll)
-		enable_irq(client->irq);
+	return 0;
+}
+
+/**
+ *	mpu3050_runtime_suspend		-	called on device enters runtime suspend
+ *	@dev: device being suspended
+ *
+ *	Put the device into sleep mode.
+ */
+static int mpu3050_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
+
+	if (sensor->enable)
+		mpu3050_set_power_mode(client, 0);
+
+	return 0;
+}
+
+/**
+ *	mpu3050_runtime_resume		-	called on device enters runtime resume
+ *	@dev: device being resumed
+ *
+ *	Put the device into powered mode.
+ */
+static int mpu3050_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
+
+	if (sensor->enable) {
+		mpu3050_set_power_mode(client, 1);
+		mpu3050_hw_init(sensor);
+	}
 
 	return 0;
 }
 #endif
 
-static UNIVERSAL_DEV_PM_OPS(mpu3050_pm, mpu3050_suspend, mpu3050_resume, NULL);
+static const struct dev_pm_ops mpu3050_pm = {
+	.runtime_suspend = mpu3050_runtime_suspend,
+	.runtime_resume = mpu3050_runtime_resume,
+	.runtime_idle = NULL,
+	.suspend = mpu3050_suspend,
+	.resume = mpu3050_resume,
+	.freeze = mpu3050_suspend,
+	.thaw = mpu3050_resume,
+	.poweroff = mpu3050_suspend,
+	.restore = mpu3050_resume,
+};
 
 static const struct i2c_device_id mpu3050_ids[] = {
 	{ "mpu3050", 0 },
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 7954296..e776dbb 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -713,7 +713,7 @@
 			duty_us = (led->mpp_cfg->pwm_cfg->pwm_period_us *
 					led->cdev.brightness) / LED_FULL;
 			/*config pwm for brightness scaling*/
-			rc = pwm_config(led->mpp_cfg->pwm_cfg->pwm_dev,
+			rc = pwm_config_us(led->mpp_cfg->pwm_cfg->pwm_dev,
 					duty_us,
 					led->mpp_cfg->pwm_cfg->pwm_period_us);
 			if (rc < 0) {
@@ -1239,7 +1239,7 @@
 		if (led->kpdbl_cfg->pwm_cfg->mode == PWM_MODE) {
 			duty_us = (led->kpdbl_cfg->pwm_cfg->pwm_period_us *
 				led->cdev.brightness) / KPDBL_MAX_LEVEL;
-			rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev,
+			rc = pwm_config_us(led->kpdbl_cfg->pwm_cfg->pwm_dev,
 					duty_us,
 					led->kpdbl_cfg->pwm_cfg->pwm_period_us);
 			if (rc < 0) {
@@ -1261,7 +1261,7 @@
 			led->kpdbl_cfg->pwm_cfg->default_mode;
 
 		if (led->kpdbl_cfg->always_on) {
-			rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev, 0,
+			rc = pwm_config_us(led->kpdbl_cfg->pwm_cfg->pwm_dev, 0,
 					led->kpdbl_cfg->pwm_cfg->pwm_period_us);
 			if (rc < 0) {
 				dev_err(&led->spmi_dev->dev,
@@ -1310,7 +1310,8 @@
 		if (led->rgb_cfg->pwm_cfg->mode == PWM_MODE) {
 			duty_us = (led->rgb_cfg->pwm_cfg->pwm_period_us *
 				led->cdev.brightness) / LED_FULL;
-			rc = pwm_config(led->rgb_cfg->pwm_cfg->pwm_dev, duty_us,
+			rc = pwm_config_us(led->rgb_cfg->pwm_cfg->pwm_dev,
+					duty_us,
 					led->rgb_cfg->pwm_cfg->pwm_period_us);
 			if (rc < 0) {
 				dev_err(&led->spmi_dev->dev,
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 7d26bef..588afc6 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -208,6 +208,12 @@
 #define QPNP_PWM_SIZE_8_BIT		8
 #define QPNP_PWM_SIZE_9_BIT		9
 
+/* Supported time levels */
+enum time_level {
+	LVL_NSEC,
+	LVL_USEC,
+};
+
 /* LPG revisions */
 enum qpnp_lpg_revision {
 	QPNP_LPG_REVISION_0 = 0x0,
@@ -305,8 +311,8 @@
 	bool				in_use;
 	const char			*lable;
 	int				pwm_value;
-	int				pwm_period;
-	int				pwm_duty;
+	int				pwm_period;	/* in microseconds */
+	int				pwm_duty;	/* in microseconds */
 	struct pwm_period_config	period;
 	int				force_pwm_size;
 };
@@ -425,8 +431,9 @@
  * This is the formula to figure out m for the best pre-divide and clock:
  * (PWM Period / N) = (Pre-divide * Clock Period) * 2^m
  */
-static void qpnp_lpg_calc_period(unsigned int period_us,
-				   struct pwm_device *pwm)
+static void qpnp_lpg_calc_period(enum time_level tm_lvl,
+				unsigned int period_value,
+				struct pwm_device *pwm)
 {
 	int		n, m, clk, div;
 	int		best_m, best_div, best_clk;
@@ -443,14 +450,18 @@
 	else
 		n = 6;
 
-	if (period_us < ((unsigned)(-1) / NSEC_PER_USEC)) {
-		period_n = (period_us * NSEC_PER_USEC) >> n;
+	if (tm_lvl == LVL_USEC) {
+		if (period_value < ((unsigned)(-1) / NSEC_PER_USEC)) {
+			period_n = (period_value * NSEC_PER_USEC) >> n;
+		} else {
+			if (qpnp_check_gpled_lpg_channel(id))
+				n = 8;
+			else
+				n = 9;
+			period_n = (period_value >> n) * NSEC_PER_USEC;
+		}
 	} else {
-		if (qpnp_check_gpled_lpg_channel(id))
-			n = 8;
-		else
-			n = 9;
-		period_n = (period_us >> n) * NSEC_PER_USEC;
+		period_n = period_value >> n;
 	}
 
 	if (force_pwm_size != 0) {
@@ -520,20 +531,20 @@
 }
 
 static void qpnp_lpg_calc_pwm_value(struct pwm_device *pwm,
-				      unsigned int period_us,
-				      unsigned int duty_us)
+				      unsigned int period_value,
+				      unsigned int duty_value)
 {
 	unsigned int		max_pwm_value, tmp;
 	struct qpnp_pwm_config	*pwm_config = &pwm->pwm_config;
 
 	/* Figure out pwm_value with overflow handling */
 	tmp = 1 << (sizeof(tmp) * 8 - pwm_config->period.pwm_size);
-	if (duty_us < tmp) {
-		tmp = duty_us << pwm_config->period.pwm_size;
-		pwm_config->pwm_value = tmp / period_us;
+	if (duty_value < tmp) {
+		tmp = duty_value << pwm_config->period.pwm_size;
+		pwm_config->pwm_value = tmp / period_value;
 	} else {
-		tmp = period_us >> pwm_config->period.pwm_size;
-		pwm_config->pwm_value = duty_us / tmp;
+		tmp = period_value >> pwm_config->period.pwm_size;
+		pwm_config->pwm_value = duty_value / tmp;
 	}
 	max_pwm_value = (1 << pwm_config->period.pwm_size) - 1;
 	if (pwm_config->pwm_value > max_pwm_value)
@@ -1083,25 +1094,36 @@
 	return rc;
 }
 
-static int _pwm_config(struct pwm_device *pwm, int duty_us, int period_us)
+static int _pwm_config(struct pwm_device *pwm,
+				enum time_level tm_lvl,
+				int duty_value, int period_value)
 {
 	struct qpnp_pwm_config		*pwm_config;
 	struct qpnp_lpg_chip		*chip;
 	struct pwm_period_config	*period;
-	int				rc;
+	int period_us, duty_us;
+	int	rc;
 
 	chip = pwm->chip;
 	pwm_config = &pwm->pwm_config;
 	period = &pwm_config->period;
 
+	if (tm_lvl == LVL_USEC) {
+		period_us = period_value;
+		duty_us = duty_value;
+	} else {
+		period_us = period_value / NSEC_PER_USEC;
+		duty_us = duty_value / NSEC_PER_USEC;
+	}
+
 	if (pwm_config->pwm_period != period_us) {
-		qpnp_lpg_calc_period(period_us, pwm);
+		qpnp_lpg_calc_period(tm_lvl, period_value, pwm);
 		qpnp_lpg_save_period(pwm);
 		pwm_config->pwm_period = period_us;
 	}
 
 	pwm_config->pwm_duty = duty_us;
-	qpnp_lpg_calc_pwm_value(pwm, period_us, duty_us);
+	qpnp_lpg_calc_pwm_value(pwm, period_value, duty_value);
 	rc = qpnp_lpg_save_pwm_value(pwm);
 
 	if (rc) {
@@ -1124,8 +1146,9 @@
 		return rc;
 	}
 
-	pr_debug("duty/period=%u/%u usec: pwm_value=%d (of %d)\n",
+	pr_debug("duty/period=%u/%u %s: pwm_value=%d (of %d)\n",
 		 (unsigned)duty_us, (unsigned)period_us,
+		 (tm_lvl == LVL_USEC) ? "usec" : "nsec",
 		 pwm_config->pwm_value, 1 << period->pwm_size);
 
 	return 0;
@@ -1151,7 +1174,7 @@
 	period = &pwm_config->period;
 
 	if (pwm_config->pwm_period != period_us) {
-		qpnp_lpg_calc_period(period_us, pwm);
+		qpnp_lpg_calc_period(LVL_USEC, period_us, pwm);
 		qpnp_lpg_save_period(pwm);
 		pwm_config->pwm_period = period_us;
 	}
@@ -1302,10 +1325,41 @@
 /**
  * pwm_config - change a PWM device configuration
  * @pwm: the PWM device
+ * @period_ns: period in nanoseconds
+ * @duty_ns: duty cycle in nanoseconds
+ */
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	int rc;
+	unsigned long flags;
+
+	if (pwm == NULL || IS_ERR(pwm) || duty_ns > period_ns ||
+		(unsigned)period_ns < PM_PWM_PERIOD_MIN * NSEC_PER_USEC) {
+		pr_err("Invalid pwm handle or parameters\n");
+		return -EINVAL;
+	}
+
+	if (!pwm->pwm_config.in_use)
+		return -EINVAL;
+
+	spin_lock_irqsave(&pwm->chip->lpg_lock, flags);
+	rc = _pwm_config(pwm, LVL_NSEC, duty_ns, period_ns);
+	spin_unlock_irqrestore(&pwm->chip->lpg_lock, flags);
+
+	if (rc)
+		pr_err("Failed to configure PWM mode\n");
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(pwm_config);
+
+/**
+ * pwm_config_us - change a PWM device configuration
+ * @pwm: the PWM device
  * @period_us: period in microseconds
  * @duty_us: duty cycle in microseconds
  */
-int pwm_config(struct pwm_device *pwm, int duty_us, int period_us)
+int pwm_config_us(struct pwm_device *pwm, int duty_us, int period_us)
 {
 	int rc;
 	unsigned long flags;
@@ -1322,7 +1376,7 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&pwm->chip->lpg_lock, flags);
-	rc = _pwm_config(pwm, duty_us, period_us);
+	rc = _pwm_config(pwm, LVL_USEC, duty_us, period_us);
 	spin_unlock_irqrestore(&pwm->chip->lpg_lock, flags);
 
 	if (rc)
@@ -1330,7 +1384,7 @@
 
 	return rc;
 }
-EXPORT_SYMBOL_GPL(pwm_config);
+EXPORT_SYMBOL_GPL(pwm_config_us);
 
 /**
  * pwm_enable - start a PWM output toggling
@@ -1627,7 +1681,8 @@
 		return rc;
 	}
 
-	rc = _pwm_config(pwm_dev, pwm_dev->pwm_config.pwm_duty, period);
+	rc = _pwm_config(pwm_dev, LVL_USEC,
+					pwm_dev->pwm_config.pwm_duty, period);
 
 	return rc;
 }
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index cf1801b..efb87a9 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1339,7 +1339,7 @@
 {
 	u8 status_low = 0, status_high = 0, qpnp_adc_tm_meas_en = 0;
 	u8 adc_tm_low_enable = 0, adc_tm_high_enable = 0;
-	u8 sensor_mask = 0;
+	u8 sensor_mask = 0, adc_tm_low_thr_set = 0, adc_tm_high_thr_set = 0;
 	int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
 	uint32_t btm_chan_num = 0;
 	struct qpnp_adc_thr_client_info *client_info = NULL;
@@ -1368,6 +1368,20 @@
 		goto fail;
 	}
 
+	rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
+						&adc_tm_low_thr_set);
+	if (rc) {
+		pr_err("adc-tm-tm read low thr failed with %d\n", rc);
+		goto fail;
+	}
+
+	rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
+						&adc_tm_high_thr_set);
+	if (rc) {
+		pr_err("adc-tm-tm read high thr failed with %d\n", rc);
+		goto fail;
+	}
+
 	/* Check which interrupt threshold is lower and measure against the
 	 * enabled channel */
 	rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
@@ -1378,7 +1392,9 @@
 	}
 
 	adc_tm_low_enable = qpnp_adc_tm_meas_en & status_low;
+	adc_tm_low_enable &= adc_tm_low_thr_set;
 	adc_tm_high_enable = qpnp_adc_tm_meas_en & status_high;
+	adc_tm_high_enable &= adc_tm_high_thr_set;
 
 	if (adc_tm_high_enable) {
 		sensor_notify_num = adc_tm_high_enable;
@@ -1886,7 +1902,7 @@
 			pr_debug("thermal node%x\n", btm_channel_num);
 			chip->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
 			chip->sensor[sen_idx].thermal_node = true;
-			snprintf(name, sizeof(name),
+			snprintf(name, sizeof(name), "%s",
 				chip->adc->adc_channels[sen_idx].name);
 			chip->sensor[sen_idx].meas_interval =
 				QPNP_ADC_TM_MEAS_INTERVAL;
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 28997ec..f1f0455 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -26,6 +26,7 @@
 #include "mdss_fb.h"
 
 #define MDP_VSYNC_CLK_RATE	19200000
+#define KOFF_TIMEOUT msecs_to_jiffies(84)
 
 enum  {
 	MDP3_CLK_AHB,
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index a6fc20d..6fc6195 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -91,6 +91,36 @@
 	return bufq->count;
 }
 
+void mdp3_ctrl_notifier_register(struct mdp3_session_data *ses,
+	struct notifier_block *notifier)
+{
+	blocking_notifier_chain_register(&ses->notifier_head, notifier);
+}
+
+void mdp3_ctrl_notifier_unregister(struct mdp3_session_data *ses,
+	struct notifier_block *notifier)
+{
+	blocking_notifier_chain_unregister(&ses->notifier_head, notifier);
+}
+
+int mdp3_ctrl_notify(struct mdp3_session_data *ses, int event)
+{
+	return blocking_notifier_call_chain(&ses->notifier_head, event, ses);
+}
+
+static void mdp3_dispatch_dma_done(struct work_struct *work)
+{
+	struct mdp3_session_data *session;
+
+	pr_debug("%s\n", __func__);
+	session = container_of(work, struct mdp3_session_data,
+				dma_done_work);
+	if (!session)
+		return;
+
+	mdp3_ctrl_notify(session, MDP_NOTIFY_FRAME_DONE);
+}
+
 static void mdp3_dispatch_clk_off(struct work_struct *work)
 {
 	struct mdp3_session_data *session;
@@ -121,6 +151,12 @@
 	sysfs_notify_dirent(session->vsync_event_sd);
 }
 
+void dma_done_notify_handler(void *arg)
+{
+	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
+	schedule_work(&session->dma_done_work);
+}
+
 void vsync_count_down(void *arg)
 {
 	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
@@ -140,8 +176,8 @@
 static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
 {
 	struct mdp3_session_data *mdp3_session;
-	struct mdp3_vsync_notification vsync_client;
-	struct mdp3_vsync_notification *arg = NULL;
+	struct mdp3_notification vsync_client;
+	struct mdp3_notification *arg = NULL;
 
 	pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -464,6 +500,7 @@
 	int frame_rate = mfd->panel_info->mipi.frame_rate;
 	int vbp, vfp, vspw;
 	int vtotal, vporch;
+	struct mdp3_notification dma_done_callback;
 
 	vbp = panel_info->lcdc.v_back_porch;
 	vfp = panel_info->lcdc.v_front_porch;
@@ -499,6 +536,13 @@
 		rc = dma->dma_config(dma, &sourceConfig, &outputConfig);
 	else
 		rc = -EINVAL;
+
+	if (outputConfig.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		dma_done_callback.handler = dma_done_notify_handler;
+		dma_done_callback.arg = mfd->mdp.private1;
+		dma->dma_done_notifier(dma, &dma_done_callback);
+	}
+
 	return rc;
 }
 
@@ -527,6 +571,8 @@
 	}
 
 	mdp3_batfet_ctrl(true);
+	mdp3_ctrl_notifier_register(mdp3_session,
+		&mdp3_session->mfd->mdp_sync_pt_data.notifier);
 
 	rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
 	if (rc) {
@@ -658,6 +704,8 @@
 	if (rc)
 		pr_err("fail to dettach MDP DMA SMMU\n");
 
+	mdp3_ctrl_notifier_unregister(mdp3_session,
+		&mdp3_session->mfd->mdp_sync_pt_data.notifier);
 	mdp3_batfet_ctrl(false);
 	mdp3_session->vsync_enabled = 0;
 	atomic_set(&mdp3_session->vsync_countdown, 0);
@@ -677,7 +725,7 @@
 	struct mdp3_session_data *mdp3_session;
 	struct mdp3_dma *mdp3_dma;
 	struct mdss_panel_data *panel;
-	struct mdp3_vsync_notification vsync_client;
+	struct mdp3_notification vsync_client;
 
 	pr_debug("mdp3_ctrl_reset_cmd\n");
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -727,7 +775,7 @@
 	struct mdp3_session_data *mdp3_session;
 	struct mdp3_dma *mdp3_dma;
 	struct mdss_panel_data *panel;
-	struct mdp3_vsync_notification vsync_client;
+	struct mdp3_notification vsync_client;
 
 	pr_debug("mdp3_ctrl_reset\n");
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -969,13 +1017,27 @@
 		return -EPERM;
 	}
 
+	mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN);
 	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
 	if (data) {
 		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
 		mdp3_ctrl_clk_enable(mfd, 1);
-		mdp3_session->dma->update(mdp3_session->dma,
+		rc = mdp3_session->dma->update(mdp3_session->dma,
 			(void *)data->addr,
 			mdp3_session->intf);
+		/* This is for the previous frame */
+		if (rc < 0) {
+			mdp3_ctrl_notify(mdp3_session,
+				MDP_NOTIFY_FRAME_TIMEOUT);
+		} else {
+			if (mdp3_ctrl_get_intf_type(mfd) ==
+						MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
+				mdp3_ctrl_notify(mdp3_session,
+					MDP_NOTIFY_FRAME_DONE);
+			}
+		}
+
+		mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_FLUSHED);
 		mdp3_bufq_push(&mdp3_session->bufq_out, data);
 	}
 
@@ -998,7 +1060,7 @@
 
 	mdss_fb_update_notify_update(mfd);
 
-	return rc;
+	return 0;
 }
 
 static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
@@ -1008,6 +1070,7 @@
 	u32 offset;
 	int bpp;
 	struct mdss_panel_info *panel_info = mfd->panel_info;
+	int rc;
 
 	pr_debug("mdp3_ctrl_pan_display\n");
 	if (!mfd || !mfd->mdp.private1)
@@ -1044,10 +1107,23 @@
 
 	if (mfd->fbi->screen_base) {
 		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
+		mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN);
 		mdp3_ctrl_clk_enable(mfd, 1);
-		mdp3_session->dma->update(mdp3_session->dma,
-				(void *)mfd->iova + offset,
+		rc = mdp3_session->dma->update(mdp3_session->dma,
+				(void *)(mfd->iova + offset),
 				mdp3_session->intf);
+		/* This is for the previous frame */
+		if (rc < 0) {
+			mdp3_ctrl_notify(mdp3_session,
+				MDP_NOTIFY_FRAME_TIMEOUT);
+		} else {
+			if (mdp3_ctrl_get_intf_type(mfd) ==
+						MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
+				mdp3_ctrl_notify(mdp3_session,
+					MDP_NOTIFY_FRAME_DONE);
+			}
+		}
+		mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_FLUSHED);
 	} else {
 		pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
 		mdp3_clk_enable(1, 0);
@@ -1658,6 +1734,7 @@
 	memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
 	mutex_init(&mdp3_session->lock);
 	INIT_WORK(&mdp3_session->clk_off_work, mdp3_dispatch_clk_off);
+	INIT_WORK(&mdp3_session->dma_done_work, mdp3_dispatch_dma_done);
 	atomic_set(&mdp3_session->vsync_countdown, 0);
 	mutex_init(&mdp3_session->histo_lock);
 	mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
@@ -1693,6 +1770,7 @@
 	mdp3_bufq_init(&mdp3_session->bufq_out);
 	mdp3_session->histo_status = 0;
 	mdp3_session->lut_sel = 0;
+	BLOCKING_INIT_NOTIFIER_HEAD(&mdp3_session->notifier_head);
 
 	init_timer(&mdp3_session->vsync_timer);
 	mdp3_session->vsync_timer.function = mdp3_vsync_timer_func;
@@ -1721,8 +1799,11 @@
 	kobject_uevent(&dev->kobj, KOBJ_ADD);
 	pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
 
-	if (mdp3_get_cont_spash_en())
+	if (mdp3_get_cont_spash_en()) {
 		mdp3_session->clk_on = 1;
+		mdp3_ctrl_notifier_register(mdp3_session,
+			&mdp3_session->mfd->mdp_sync_pt_data.notifier);
+	}
 
 	if (splash_mismatch) {
 		pr_err("splash memory mismatch, stop splash\n");
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index f2484ef..cfad1d3 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -49,6 +49,7 @@
 	struct mdp3_buffer_queue bufq_in;
 	struct mdp3_buffer_queue bufq_out;
 	struct work_struct clk_off_work;
+	struct work_struct dma_done_work;
 	int histo_status;
 	struct mutex histo_lock;
 	int lut_sel;
@@ -56,6 +57,7 @@
 	bool vsync_before_commit;
 	bool first_commit;
 	int clk_on;
+	struct blocking_notifier_head notifier_head;
 
 	int vsync_enabled;
 	atomic_t vsync_countdown; /* Used to count down  */
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index ae7598f..5cae2de 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -27,7 +27,7 @@
 static void mdp3_vsync_intr_handler(int type, void *arg)
 {
 	struct mdp3_dma *dma = (struct mdp3_dma *)arg;
-	struct mdp3_vsync_notification vsync_client;
+	struct mdp3_notification vsync_client;
 	unsigned int wait_for_next_vs;
 
 	pr_debug("mdp3_vsync_intr_handler\n");
@@ -49,10 +49,16 @@
 static void mdp3_dma_done_intr_handler(int type, void *arg)
 {
 	struct mdp3_dma *dma = (struct mdp3_dma *)arg;
+	struct mdp3_notification dma_client;
 
 	pr_debug("mdp3_dma_done_intr_handler\n");
+	spin_lock(&dma->dma_lock);
+	dma_client = dma->dma_notifier_client;
 	complete(&dma->dma_comp);
+	spin_unlock(&dma->dma_lock);
 	mdp3_irq_disable_nosync(type);
+	if (dma_client.handler)
+		dma_client.handler(dma_client.arg);
 }
 
 static void mdp3_hist_done_intr_handler(int type, void *arg)
@@ -195,7 +201,7 @@
 }
 
 static void mdp3_dma_vsync_enable(struct mdp3_dma *dma,
-				struct mdp3_vsync_notification *vsync_client)
+				struct mdp3_notification *vsync_client)
 {
 	unsigned long flag;
 	int updated = 0;
@@ -226,6 +232,21 @@
 	}
 }
 
+static void mdp3_dma_done_notifier(struct mdp3_dma *dma,
+				struct mdp3_notification *dma_client)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&dma->dma_lock, flag);
+	if (dma_client) {
+		dma->dma_notifier_client = *dma_client;
+	} else {
+		dma->dma_notifier_client.handler = NULL;
+		dma->dma_notifier_client.arg = NULL;
+	}
+	spin_unlock_irqrestore(&dma->dma_lock, flag);
+}
+
 static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
 {
 	u32 cgc;
@@ -552,13 +573,20 @@
 {
 	unsigned long flag;
 	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+	int rc = 0;
 
 	pr_debug("mdp3_dmap_update\n");
 
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
 		cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
-		if (intf->active)
-			wait_for_completion_killable(&dma->dma_comp);
+		if (intf->active) {
+			rc = wait_for_completion_timeout(&dma->dma_comp,
+				KOFF_TIMEOUT);
+			if (rc <= 0) {
+				WARN(1, "cmd kickoff timed out (%d)\n", rc);
+				rc = -1;
+			}
+		}
 	}
 	spin_lock_irqsave(&dma->dma_lock, flag);
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
@@ -581,10 +609,14 @@
 
 	mdp3_dma_callback_enable(dma, cb_type);
 	pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
-	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
-		wait_for_completion_killable(&dma->vsync_comp);
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
+		rc = wait_for_completion_timeout(&dma->vsync_comp,
+			KOFF_TIMEOUT);
+		if (rc <= 0)
+			rc = -1;
+	}
 	pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
-	return 0;
+	return rc;
 }
 
 static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf,
@@ -878,6 +910,7 @@
 		dma->get_histo = mdp3_dmap_histo_get;
 		dma->histo_op = mdp3_dmap_histo_op;
 		dma->vsync_enable = mdp3_dma_vsync_enable;
+		dma->dma_done_notifier = mdp3_dma_done_notifier;
 		dma->start = mdp3_dma_start;
 		dma->stop = mdp3_dma_stop;
 		dma->config_stride = mdp3_dma_stride_config;
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 6ad4c79..04955d4 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -14,6 +14,7 @@
 #ifndef MDP3_DMA_H
 #define MDP3_DMA_H
 
+#include <linux/notifier.h>
 #include <linux/sched.h>
 
 #define MDP_HISTOGRAM_BL_SCALE_MAX 1024
@@ -227,7 +228,7 @@
 	u32 extra[2];
 };
 
-struct mdp3_vsync_notification {
+struct mdp3_notification {
 	void (*handler)(void *arg);
 	void *arg;
 };
@@ -245,7 +246,8 @@
 	struct completion vsync_comp;
 	struct completion dma_comp;
 	struct completion histo_comp;
-	struct mdp3_vsync_notification vsync_client;
+	struct mdp3_notification vsync_client;
+	struct mdp3_notification dma_notifier_client;
 
 	struct mdp3_dma_output_config output_config;
 	struct mdp3_dma_source source_config;
@@ -291,7 +293,10 @@
 	void (*config_stride)(struct mdp3_dma *dma, int stride);
 
 	void (*vsync_enable)(struct mdp3_dma *dma,
-			struct mdp3_vsync_notification *vsync_client);
+			struct mdp3_notification *vsync_client);
+
+	void (*dma_done_notifier)(struct mdp3_dma *dma,
+			struct mdp3_notification *dma_client);
 };
 
 struct mdp3_video_intf_cfg {
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index f6256e7..3c7d17c 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -19,7 +19,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/leds.h>
-#include <linux/pwm.h>
+#include <linux/qpnp/pwm.h>
 #include <linux/err.h>
 
 #include "mdss_dsi.h"
@@ -69,9 +69,9 @@
 		ctrl->pwm_enabled = 0;
 	}
 
-	ret = pwm_config(ctrl->pwm_bl, duty, ctrl->pwm_period);
+	ret = pwm_config_us(ctrl->pwm_bl, duty, ctrl->pwm_period);
 	if (ret) {
-		pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
+		pr_err("%s: pwm_config_us() failed err=%d.\n", __func__, ret);
 		return;
 	}
 
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index bb27e6b..6dbca10 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -23,7 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
-#include <linux/pwm.h>
+#include <linux/qpnp/pwm.h>
 #include <linux/clk.h>
 #include <linux/spinlock_types.h>
 #include <linux/kthread.h>
@@ -210,11 +210,11 @@
 		if (bl_level > bl_max)
 			bl_level = bl_max;
 
-		ret = pwm_config(edp_drv->bl_pwm,
+		ret = pwm_config_us(edp_drv->bl_pwm,
 				bl_level * edp_drv->pwm_period / bl_max,
 				edp_drv->pwm_period);
 		if (ret) {
-			pr_err("%s: pwm_config() failed err=%d.\n", __func__,
+			pr_err("%s: pwm_config_us() failed err=%d.\n", __func__,
 					ret);
 			return;
 		}
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 94b2cbd..54e3bc8 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1836,11 +1836,11 @@
 
 int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
 {
-	int ret = -EINVAL;
+	int ret = 0;
 
 	if (req_state == mfd->dcm_state) {
-		pr_warn("Already in correct DCM state");
-		ret = 0;
+		pr_warn("Already in correct DCM/DTM state");
+		return ret;
 	}
 
 	switch (req_state) {
@@ -1856,11 +1856,12 @@
 		break;
 	case DCM_ENTER:
 		if (mfd->dcm_state == DCM_UNBLANK) {
-			/* Keep unblank path available for only
-			DCM operation */
+			/*
+			 * Keep unblank path available for only
+			 * DCM operation
+			 */
 			mfd->panel_power_on = false;
 			mfd->dcm_state = DCM_ENTER;
-			ret = 0;
 		}
 		break;
 	case DCM_EXIT:
@@ -1868,7 +1869,6 @@
 			/* Release the unblank path for exit */
 			mfd->panel_power_on = true;
 			mfd->dcm_state = DCM_EXIT;
-			ret = 0;
 		}
 		break;
 	case DCM_BLANK:
@@ -1882,7 +1882,16 @@
 			}
 		}
 		break;
+	case DTM_ENTER:
+		if (mfd->dcm_state == DCM_UNINIT)
+			mfd->dcm_state = DTM_ENTER;
+		break;
+	case DTM_EXIT:
+		if (mfd->dcm_state == DTM_ENTER)
+			mfd->dcm_state = DCM_UNINIT;
+		break;
 	}
+
 	return ret;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index f73b583..d57e4fb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1913,8 +1913,10 @@
 	if (ctl->wait_pingpong)
 		ctl->wait_pingpong(ctl, NULL);
 
-	/* postprocessing setup, including dspp */
-	mdss_mdp_pp_setup_locked(ctl);
+	if (ctl->mfd && ctl->mfd->dcm_state != DTM_ENTER)
+		/* postprocessing setup, including dspp */
+		mdss_mdp_pp_setup_locked(ctl);
+
 	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
 	if (sctl) {
 		mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH,
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index b6f94d0..bcd3cf4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -108,7 +108,9 @@
 	MDSS_MDP_MAX_CTL
 };
 
-#define MDSS_MDP_REG_CTL_OFFSET(ctl) (0x00600 + ((ctl) * 0x100))
+#define MDSS_MDP_CTL_ADDRESS_OFFSET			0x100
+#define MDSS_MDP_REG_CTL_OFFSET(ctl) (0x00600 + ((ctl) * \
+					 MDSS_MDP_CTL_ADDRESS_OFFSET))
 
 #define MDSS_MDP_REG_CTL_LAYER(lm)			((lm) * 0x004)
 #define MDSS_MDP_REG_CTL_TOP				0x014
@@ -159,7 +161,10 @@
 	MDSS_MDP_CHROMA_420
 };
 
-#define MDSS_MDP_REG_SSPP_OFFSET(pipe) (0x01200 + ((pipe) * 0x400))
+
+#define MDSS_MDP_SSPP_ADDRESS_OFFSET			0x400
+#define MDSS_MDP_REG_SSPP_OFFSET(pipe) (0x01200 + ((pipe) * \
+					MDSS_MDP_SSPP_ADDRESS_OFFSET))
 
 #define MDSS_MDP_REG_SSPP_SRC_SIZE			0x000
 #define MDSS_MDP_REG_SSPP_SRC_IMG_SIZE			0x004
@@ -175,6 +180,7 @@
 #define MDSS_MDP_REG_SSPP_STILE_FRAME_SIZE		0x02C
 #define MDSS_MDP_REG_SSPP_SRC_FORMAT			0x030
 #define MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN		0x034
+#define MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR		0x03C
 #define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_0		0x050
 #define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_1		0x054
 #define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_2		0x058
@@ -280,8 +286,9 @@
 	MDSS_MDP_MAX_STAGE
 };
 
-#define MDSS_MDP_REG_LM_OFFSET(lm) (0x03200 + ((lm) * 0x400))
-
+#define MDSS_MDP_LM_ADDRESS_OFFSET			0x400
+#define MDSS_MDP_REG_LM_OFFSET(lm) (0x03200 + ((lm) * \
+					MDSS_MDP_LM_ADDRESS_OFFSET))
 #define MDSS_MDP_REG_LM_OP_MODE				0x000
 #define MDSS_MDP_REG_LM_OUT_SIZE			0x004
 #define MDSS_MDP_REG_LM_BORDER_COLOR_0			0x008
@@ -423,7 +430,9 @@
 	MDSS_MDP_MAX_DSPP
 };
 
-#define MDSS_MDP_REG_DSPP_OFFSET(pipe)	(0x4600 + ((pipe) * 0x400))
+#define MDSS_MDP_DSPP_ADDRESS_OFFSET			0x400
+#define MDSS_MDP_REG_DSPP_OFFSET(pipe)	(0x4600 + ((pipe) * \
+					MDSS_MDP_DSPP_ADDRESS_OFFSET))
 #define MDSS_MDP_REG_DSPP_OP_MODE			0x000
 #define MDSS_MDP_REG_DSPP_PCC_BASE			0x030
 #define MDSS_MDP_REG_DSPP_DITHER_DEPTH			0x150
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index d0d2157..555974b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -173,6 +173,13 @@
 	GAMUT_T2_SIZE + GAMUT_T3_SIZE + GAMUT_T4_SIZE + \
 	GAMUT_T5_SIZE + GAMUT_T6_SIZE + GAMUT_T7_SIZE)
 
+#define MDSS_MDP_PA_SIZE		0xC
+#define MDSS_MDP_GC_SIZE		0x28
+#define MDSS_MDP_PCC_SIZE		0xB8
+#define MDSS_MDP_GAMUT_SIZE		0x5C
+#define MDSS_MDP_IGC_DSPP_COLORS	0x3
+#define TOTAL_BLEND_STAGES		0x4
+
 #define PP_FLAGS_DIRTY_PA	0x1
 #define PP_FLAGS_DIRTY_PCC	0x2
 #define PP_FLAGS_DIRTY_IGC	0x4
@@ -1727,11 +1734,13 @@
 		if (mdss_pp_res == NULL) {
 			pr_err("%s mdss_pp_res allocation failed!", __func__);
 			ret = -ENOMEM;
-		}
-
-		for (i = 0; i < MDSS_MDP_MAX_DSPP; i++) {
-			mutex_init(&mdss_pp_res->dspp_hist[i].hist_mutex);
-			spin_lock_init(&mdss_pp_res->dspp_hist[i].hist_lock);
+		} else {
+			for (i = 0; i < MDSS_MDP_MAX_DSPP; i++) {
+				mutex_init(
+					&mdss_pp_res->dspp_hist[i].hist_mutex);
+				spin_lock_init(
+					&mdss_pp_res->dspp_hist[i].hist_lock);
+			}
 		}
 	}
 	if (mdata) {
@@ -4434,71 +4443,271 @@
 	return rc;
 }
 
-static int is_valid_calib_addr(void *addr)
+static int is_valid_calib_ctrl_addr(char __iomem *ptr)
+{
+	char __iomem *base;
+	int ret = 0, counter = 0;
+	int stage = 0;
+	struct mdss_mdp_ctl *ctl;
+
+	/* Controller */
+	for (counter = 0; counter < mdss_res->nctl; counter++) {
+		ctl = mdss_res->ctl_off + counter;
+		base = ctl->base;
+
+		if (ptr == base + MDSS_MDP_REG_CTL_TOP) {
+			ret = MDP_PP_OPS_READ;
+			break;
+		} else if (ptr == base + MDSS_MDP_REG_CTL_FLUSH) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		}
+
+		for (stage = 0; stage < mdss_res->nmixers_intf; stage++)
+			if (ptr == base + MDSS_MDP_REG_CTL_LAYER(stage)) {
+				ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+				goto End;
+			}
+	}
+
+End:
+	return ret;
+}
+
+static int is_valid_calib_dspp_addr(char __iomem *ptr)
+{
+	char __iomem *base;
+	int ret = 0, counter = 0;
+	struct mdss_mdp_mixer *mixer;
+
+	for (counter = 0; counter < mdss_res->nmixers_intf; counter++) {
+		mixer = mdss_res->mixer_intf + counter;
+		base = mixer->dspp_base;
+
+		if (ptr == base) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* PA range */
+		} else if ((ptr >= base + MDSS_MDP_REG_DSPP_PA_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_DSPP_PA_BASE +
+						MDSS_MDP_PA_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* PCC range */
+		} else if ((ptr >= base + MDSS_MDP_REG_DSPP_PCC_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_DSPP_PCC_BASE +
+						MDSS_MDP_PCC_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* Gamut range */
+		} else if ((ptr >= base + MDSS_MDP_REG_DSPP_GAMUT_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_DSPP_GAMUT_BASE +
+						MDSS_MDP_GAMUT_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* GC range */
+		} else if ((ptr >= base + MDSS_MDP_REG_DSPP_GC_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_DSPP_GC_BASE +
+						MDSS_MDP_GC_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* Dither enable/disable */
+		} else if ((ptr == base + MDSS_MDP_REG_DSPP_DITHER_DEPTH)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int is_valid_calib_vig_addr(char __iomem *ptr)
+{
+	char __iomem *base;
+	int ret = 0, counter = 0;
+	struct mdss_mdp_pipe *pipe;
+
+	for (counter = 0; counter < mdss_res->nvig_pipes; counter++) {
+		pipe = mdss_res->vig_pipes + counter;
+		base = pipe->base;
+
+		if (ptr == base + MDSS_MDP_REG_SSPP_SRC_FORMAT) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		} else if ((ptr == base + MDSS_MDP_REG_VIG_QSEED2_SHARP)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* PA range */
+		} else if ((ptr >= base + MDSS_MDP_REG_VIG_PA_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_VIG_PA_BASE +
+						MDSS_MDP_PA_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* IGC range */
+		} else if ((ptr >= base + MDSS_MDP_REG_IGC_VIG_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_IGC_VIG_BASE +
+						MDSS_MDP_GC_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int is_valid_calib_rgb_addr(char __iomem *ptr)
+{
+	char __iomem *base;
+	int ret = 0, counter = 0;
+	struct mdss_mdp_pipe *pipe;
+
+	for (counter = 0; counter < mdss_res->nrgb_pipes; counter++) {
+		pipe = mdss_res->rgb_pipes + counter;
+		base = pipe->base;
+
+		if (ptr == base + MDSS_MDP_REG_SSPP_SRC_FORMAT) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* IGC range */
+		} else if ((ptr >= base + MDSS_MDP_REG_IGC_RGB_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_IGC_RGB_BASE +
+						MDSS_MDP_GC_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int is_valid_calib_dma_addr(char __iomem *ptr)
+{
+	char __iomem *base;
+	int ret = 0, counter = 0;
+	struct mdss_mdp_pipe *pipe;
+
+	for (counter = 0; counter < mdss_res->ndma_pipes; counter++) {
+		pipe = mdss_res->dma_pipes + counter;
+		base = pipe->base;
+
+		if (ptr == base + MDSS_MDP_REG_SSPP_SRC_FORMAT) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* IGC range */
+		} else if ((ptr >= base + MDSS_MDP_REG_IGC_DMA_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_IGC_DMA_BASE +
+						MDSS_MDP_GC_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int is_valid_calib_mixer_addr(char __iomem *ptr)
+{
+	char __iomem *base;
+	int ret = 0, counter = 0;
+	int stage = 0;
+	struct mdss_mdp_mixer *mixer;
+
+	for (counter = 0; counter < mdss_res->nmixers_intf; counter++) {
+		mixer = mdss_res->mixer_intf + counter;
+		base = mixer->base;
+
+		if (ptr == base + MDSS_MDP_REG_LM_OP_MODE) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		/* GC range */
+		} else if ((ptr >= base + MDSS_MDP_REG_LM_GC_LUT_BASE) &&
+			(ptr <= base + MDSS_MDP_REG_LM_GC_LUT_BASE +
+						MDSS_MDP_GC_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		}
+
+		for (stage = 0; stage < TOTAL_BLEND_STAGES; stage++)
+			if (ptr == base + MDSS_MDP_REG_LM_BLEND_OFFSET(stage) +
+						 MDSS_MDP_REG_LM_BLEND_OP) {
+				ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+				goto End;
+			} else if (ptr == base +
+					MDSS_MDP_REG_LM_BLEND_OFFSET(stage) +
+					MDSS_MDP_REG_LM_BLEND_FG_ALPHA) {
+				ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+				goto End;
+			} else if (ptr == base +
+					 MDSS_MDP_REG_LM_BLEND_OFFSET(stage) +
+					 MDSS_MDP_REG_LM_BLEND_BG_ALPHA) {
+				ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+				goto End;
+			}
+	}
+
+End:
+	return ret;
+}
+
+static int is_valid_calib_addr(void *addr, u32 operation)
 {
 	int ret = 0;
-	unsigned int ptr;
-	ptr = (unsigned int) addr;
-	/* if request is outside the MDP reg-map or is not aligned 4 */
-	if (ptr > 0x5138 || ptr % 0x4)
-		goto end;
-	if (ptr >= 0x100 && ptr <= 0x5138) {
-		/* if ptr is in dspp range */
-		if (ptr >= 0x4600 && ptr <= 0x5138) {
-			/* if ptr is in dspp0 range*/
-			if (ptr >= 0x4600 && ptr <= 0x4938)
-				ptr -= 0x4600;
-			/* if ptr is in dspp1 range */
-			else if (ptr >= 0x4a00 && ptr <= 0x4d38)
-				ptr -= 0x4a00;
-			/* if ptr is in dspp2 range */
-			else if (ptr >= 0x4e00 && ptr <= 0x5138)
-				ptr -= 0x4e00;
-			/* if ptr is in pcc plane rgb coeff.range */
-			if (ptr >= 0x30 && ptr <= 0xe8)
-				ret = 1;
-			/* if ptr is in ARLUT red range */
-			else if (ptr >= 0x2b0 && ptr <= 0x2b8)
-				ret = 1;
-			/* if ptr is in PA range */
-			else if (ptr >= 0x238 && ptr <= 0x244)
-				ret = 1;
-			 /* if ptr is in ARLUT green range */
-			else if (ptr >= 0x2c0 && ptr <= 0x2c8)
-				ret = 1;
-			/* if ptr is in ARLUT blue range or
-			    gamut map table range */
-			else if (ptr >= 0x2d0 && ptr <= 0x338)
-				ret = 1;
-			/* if ptr is dspp0,dspp1,dspp2 op mode
-						register */
-			else if (ptr == 0)
-				ret = 1;
-		} else if (ptr >= 0x600 && ptr <= 0x608)
-				ret = 1;
-		else if (ptr >= 0x400 && ptr <= 0x408)
-				ret = 1;
-		else if ((ptr == 0x1830) || (ptr == 0x1c30) ||
-				(ptr == 0x1430) || (ptr == 0x1e38))
-				ret = 1;
-		else if ((ptr == 0x1e3c) || (ptr == 0x1e30))
-				ret = 1;
-		else if (ptr >= 0x3220 && ptr <= 0x3228)
-				ret = 1;
-		else if (ptr == 0x3200 || ptr == 0x100)
-				ret = 1;
-		else if (ptr == 0x104 || ptr == 0x614 || ptr == 0x714 ||
-			ptr == 0x814 || ptr == 0x914 || ptr == 0xa14)
-				ret = 1;
-		else if (ptr == 0x618 || ptr == 0x718 || ptr == 0x818 ||
-				 ptr == 0x918 || ptr == 0xa18)
-				ret = 1;
-		else if (ptr == 0x2234 || ptr == 0x1e34 || ptr == 0x2634)
-				ret = 1;
-	} else if (ptr == 0x0)
-		ret = 1;
-end:
-	return ret;
+	char __iomem *ptr = addr;
+	char __iomem *mixer_base = mdss_res->mixer_intf->base;
+	char __iomem *rgb_base   = mdss_res->rgb_pipes->base;
+	char __iomem *dma_base   = mdss_res->dma_pipes->base;
+	char __iomem *vig_base   = mdss_res->vig_pipes->base;
+	char __iomem *ctl_base   = mdss_res->ctl_off->base;
+	char __iomem *dspp_base  = mdss_res->mixer_intf->dspp_base;
+
+	if ((unsigned int)addr % 4) {
+		ret = 0;
+	} else if (ptr == (mdss_res->mdp_base + MDSS_MDP_REG_HW_VERSION) ||
+	    ptr == (mdss_res->mdp_base + MDSS_MDP_REG_DISP_INTF_SEL)) {
+		ret = MDP_PP_OPS_READ;
+	} else if (ptr >= (mdss_res->mdp_base + MDSS_MDP_REG_IGC_DSPP_BASE) &&
+		    ptr < (mdss_res->mdp_base + MDSS_MDP_REG_IGC_DSPP_BASE +
+						MDSS_MDP_IGC_DSPP_COLORS)) {
+		ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+	} else if (ptr >= dspp_base && ptr < (dspp_base +
+		(mdss_res->nmixers_intf * MDSS_MDP_DSPP_ADDRESS_OFFSET))) {
+		ret = is_valid_calib_dspp_addr(ptr);
+	} else if (ptr >= ctl_base && ptr < (ctl_base + (mdss_res->nctl
+					* MDSS_MDP_CTL_ADDRESS_OFFSET))) {
+		ret = is_valid_calib_ctrl_addr(ptr);
+	} else if (ptr >= vig_base && ptr < (vig_base + (mdss_res->nvig_pipes
+					* MDSS_MDP_SSPP_ADDRESS_OFFSET))) {
+		ret = is_valid_calib_vig_addr(ptr);
+	} else if (ptr >= rgb_base && ptr < (rgb_base + (mdss_res->nrgb_pipes
+					* MDSS_MDP_SSPP_ADDRESS_OFFSET))) {
+		ret = is_valid_calib_rgb_addr(ptr);
+	} else if (ptr >= dma_base && ptr < (dma_base + (mdss_res->ndma_pipes
+					* MDSS_MDP_SSPP_ADDRESS_OFFSET))) {
+		ret = is_valid_calib_dma_addr(ptr);
+	} else if (ptr >= mixer_base && ptr < (mixer_base +
+		(mdss_res->nmixers_intf * MDSS_MDP_LM_ADDRESS_OFFSET))) {
+		ret = is_valid_calib_mixer_addr(ptr);
+	}
+
+	return ret & operation;
 }
 
 int mdss_mdp_calib_config(struct mdp_calib_config_data *cfg, u32 *copyback)
@@ -4506,11 +4715,12 @@
 	int ret = -1;
 	void *ptr = (void *) cfg->addr;
 
-	if (is_valid_calib_addr(ptr))
+	ptr = (void *)(((unsigned int) ptr) + (mdss_res->mdp_base));
+	if (is_valid_calib_addr(ptr, cfg->ops))
 		ret = 0;
 	else
 		return ret;
-	ptr = (void *)(((unsigned int) ptr) + (mdss_res->mdp_base));
+
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 
 	if (cfg->ops & MDP_PP_OPS_READ) {
@@ -4545,65 +4755,50 @@
 	int i = 0;
 
 	if (!cfg) {
-		pr_err("Invalid buffer pointer");
+		pr_err("Invalid buffer pointer\n");
 		return ret;
 	}
 
-	if (cfg->size == 0 || cfg->size > PAGE_SIZE) {
-		pr_err("Invalid buffer size %d", cfg->size);
+	if (cfg->size == 0) {
+		pr_err("Invalid buffer size\n");
 		return ret;
 	}
 
 	counter = cfg->size / (sizeof(uint32_t) * 2);
 	buff_org = buff = kzalloc(cfg->size, GFP_KERNEL);
 	if (buff == NULL) {
-		pr_err("Allocation failed");
+		pr_err("Config buffer allocation failed\n");
 		return ret;
 	}
 
 	if (copy_from_user(buff, cfg->buffer, cfg->size)) {
 		kfree(buff);
-		pr_err("Copy failed");
+		pr_err("config buffer copy failed\n");
 		return ret;
 	}
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 
-	if (cfg->ops & MDP_PP_OPS_READ) {
-		for (i = 0 ; i < counter ; i++) {
-			if (is_valid_calib_addr((void *) *buff)) {
-				ret = 0;
-			} else {
-				ret = -1;
-				pr_err("Address validation failed");
-				break;
-			}
+	for (i = 0; i < counter; i++) {
+		ptr = (void *) (((unsigned int) *buff) + mdss_res->mdp_base);
 
-			ptr = (void *)(((unsigned int) *buff) +
-					 (mdss_res->mdp_base));
-			buff++;
+		if (!is_valid_calib_addr(ptr, cfg->ops)) {
+			ret = -1;
+			pr_err("Address validation failed or access not permitted\n");
+			break;
+		}
+
+		buff++;
+		if (cfg->ops & MDP_PP_OPS_READ)
 			*buff = readl_relaxed(ptr);
-			buff++;
-		}
-		if (!ret)
-			ret = copy_to_user(cfg->buffer, buff_org, cfg->size);
-		*copyback = 1;
-	} else if (cfg->ops & MDP_PP_OPS_WRITE) {
-		for (i = 0 ; i < counter ; i++) {
-			if (is_valid_calib_addr((void *) *buff)) {
-				ret = 0;
-			} else {
-				ret = -1;
-				pr_err("Address validation failed");
-				break;
-			}
-
-			ptr = (void *)(((unsigned int) *buff) +
-					 (mdss_res->mdp_base));
-			buff++;
+		else if (cfg->ops & MDP_PP_OPS_WRITE)
 			writel_relaxed(*buff, ptr);
-			buff++;
-		}
+		buff++;
+	}
+
+	if (ret & MDP_PP_OPS_READ) {
+		ret = copy_to_user(cfg->buffer, buff_org, cfg->size);
+		*copyback = 1;
 	}
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 329b58e..4640d3b 100755
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -99,7 +99,6 @@
 header-y += connector.h
 header-y += const.h
 header-y += cramfs_fs.h
-header-y += csdio.h
 header-y += cuda.h
 header-y += cyclades.h
 header-y += cycx_cfm.h
diff --git a/include/linux/csdio.h b/include/linux/csdio.h
deleted file mode 100644
index 260c49d..0000000
--- a/include/linux/csdio.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef CSDIO_H
-#define CSDIO_H
-
-#include <linux/ioctl.h>
-
-#define CSDIO_IOC_MAGIC  'm'
-
-#define CSDIO_IOC_ENABLE_HIGHSPEED_MODE      _IO(CSDIO_IOC_MAGIC, 0)
-#define CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS   _IO(CSDIO_IOC_MAGIC, 1)
-#define CSDIO_IOC_SET_OP_CODE                _IO(CSDIO_IOC_MAGIC, 2)
-#define CSDIO_IOC_FUNCTION_SET_BLOCK_SIZE    _IO(CSDIO_IOC_MAGIC, 3)
-#define CSDIO_IOC_SET_BLOCK_MODE             _IO(CSDIO_IOC_MAGIC, 4)
-#define CSDIO_IOC_CONNECT_ISR                _IO(CSDIO_IOC_MAGIC, 5)
-#define CSDIO_IOC_DISCONNECT_ISR             _IO(CSDIO_IOC_MAGIC, 6)
-#define CSDIO_IOC_CMD52                      _IO(CSDIO_IOC_MAGIC, 7)
-#define CSDIO_IOC_CMD53                      _IO(CSDIO_IOC_MAGIC, 8)
-#define CSDIO_IOC_ENABLE_ISR                 _IO(CSDIO_IOC_MAGIC, 9)
-#define CSDIO_IOC_DISABLE_ISR                _IO(CSDIO_IOC_MAGIC, 10)
-#define CSDIO_IOC_SET_VDD                    _IO(CSDIO_IOC_MAGIC, 11)
-#define CSDIO_IOC_GET_VDD                    _IO(CSDIO_IOC_MAGIC, 12)
-
-#define CSDIO_IOC_MAXNR   12
-
-struct csdio_cmd53_ctrl_t {
-	uint32_t    m_block_mode;   /* data tran. byte(0)/block(1) mode */
-	uint32_t    m_op_code;      /* address auto increment flag */
-	uint32_t    m_address;
-} __attribute__ ((packed));
-
-struct csdio_cmd52_ctrl_t {
-	uint32_t    m_write;
-	uint32_t    m_address;
-	uint32_t    m_data;
-	uint32_t    m_ret;
-} __attribute__ ((packed));
-
-#endif
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 4903939..0791545 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -800,6 +800,8 @@
 	DCM_ENTER,
 	DCM_EXIT,
 	DCM_BLANK,
+	DTM_ENTER,
+	DTM_EXIT,
 };
 
 #define MDSS_PP_SPLIT_LEFT_ONLY		0x10000000
diff --git a/include/linux/qpnp/pwm.h b/include/linux/qpnp/pwm.h
index bf7908b..50fb2e5 100644
--- a/include/linux/qpnp/pwm.h
+++ b/include/linux/qpnp/pwm.h
@@ -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
@@ -146,6 +146,12 @@
 int pwm_lut_config(struct pwm_device *pwm, int period_us,
 		int duty_pct[], struct lut_params lut_params);
 
+/*
+ * support microsecond level configuration
+ */
+int pwm_config_us(struct pwm_device *pwm,
+		int duty_us, int period_us);
+
 /* Standard APIs supported */
 /*
  * pwm_request - request a PWM device
@@ -161,8 +167,8 @@
 /*
  * pwm_config - change a PWM device configuration
  * @pwm: the PWM device
- * @period_us: period in microsecond
- * @duty_us: duty cycle in microsecond
+ * @period_ns: period in nanosecond
+ * @duty_ns: duty cycle in nanosecond
  */
 
 /*
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 6f121b3..5941f71 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -31,7 +31,7 @@
 int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params);
 
 int adm_open(int port, int path, int rate, int mode, int topology,
-				bool perf_mode, uint16_t bits_per_sample);
+				int perf_mode, uint16_t bits_per_sample);
 
 int adm_get_params(int port_id, uint32_t module_id, uint32_t param_id,
 			uint32_t params_length, char *params);
@@ -40,7 +40,7 @@
 				 uint32_t params_length);
 
 int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
-			int topology, bool perf_mode, uint16_t bits_per_sample);
+			int topology, int perf_mode, uint16_t bits_per_sample);
 
 int adm_unmap_cal_blocks(void);
 
@@ -53,10 +53,10 @@
 
 int adm_memory_unmap_regions(int port_id);
 
-int adm_close(int port, bool perf_mode);
+int adm_close(int port, int perf_mode);
 
 int adm_matrix_map(int session_id, int path, int num_copps,
-		unsigned int *port_id, int copp_id, bool perf_mode);
+		unsigned int *port_id, int copp_id, int perf_mode);
 
 int adm_connect_afe_port(int mode, int session_id, int port_id);
 
@@ -64,6 +64,8 @@
 
 int adm_get_copp_id(int port_id);
 
+int adm_get_lowlatency_copp_id(int port_id);
+
 void adm_set_multi_ch_map(char *channel_map);
 
 void adm_get_multi_ch_map(char *channel_map);
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index b00cfc9..a78c333 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -175,7 +175,7 @@
 	struct audio_port_data port[2];
 	wait_queue_head_t      cmd_wait;
 	wait_queue_head_t      time_wait;
-	bool                   perf_mode;
+	int                    perf_mode;
 	int					   stream_id;
 	/* audio cache operations fptr*/
 	int (*fptr_cache_ops)(struct audio_buffer *abuff, int cache_op);
diff --git a/include/sound/q6audio-v2.h b/include/sound/q6audio-v2.h
index fd6a490..8ac835c 100644
--- a/include/sound/q6audio-v2.h
+++ b/include/sound/q6audio-v2.h
@@ -15,6 +15,13 @@
 
 #include <mach/qdsp6v2/apr.h>
 
+enum {
+	LEGACY_PCM_MODE = 0,
+	LOW_LATENCY_PCM_MODE,
+	ULTRA_LOW_LATENCY_PCM_MODE,
+};
+
+
 int q6audio_get_port_index(u16 port_id);
 
 int q6audio_convert_virtual_to_portid(u16 port_id);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index fa8a793..e174693 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -184,6 +184,36 @@
 	return ret;
 }
 
+#ifdef ENABLE_VMALLOC_SAVING
+int is_vmalloc_addr(const void *x)
+{
+	struct rb_node *n;
+	struct vmap_area *va;
+	int ret = 0;
+
+	spin_lock(&vmap_area_lock);
+
+	for (n = rb_first(vmap_area_root); n; rb_next(n)) {
+		va = rb_entry(n, struct vmap_area, rb_node);
+		if (x >= va->va_start && x < va->va_end) {
+			ret = 1;
+			break;
+		}
+	}
+
+	spin_unlock(&vmap_area_lock);
+	return ret;
+}
+#else
+int is_vmalloc_addr(const void *x)
+{
+	unsigned long addr = (unsigned long)x;
+
+	return addr >= VMALLOC_START && addr < VMALLOC_END;
+}
+#endif
+EXPORT_SYMBOL(is_vmalloc_addr);
+
 int is_vmalloc_or_module_addr(const void *x)
 {
 	/*
@@ -272,47 +302,6 @@
 
 static unsigned long vmap_area_pcpu_hole;
 
-#ifdef CONFIG_ENABLE_VMALLOC_SAVING
-int is_vmalloc_addr(const void *x)
-{
-	struct vmap_area *va;
-	int ret = 0;
-
-	spin_lock(&vmap_area_lock);
-	list_for_each_entry(va, &vmap_area_list, list) {
-		if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING))
-			continue;
-
-		if (!(va->flags & VM_VM_AREA))
-			continue;
-
-		if (va->vm == NULL)
-			continue;
-
-		if (va->vm->flags & VM_LOWMEM)
-			continue;
-
-		if ((unsigned long)x >= va->va_start &&
-		    (unsigned long)x < va->va_end) {
-			ret = 1;
-			break;
-		}
-	}
-	spin_unlock(&vmap_area_lock);
-	return ret;
-}
-#else
-int is_vmalloc_addr(const void *x)
-{
-	unsigned long addr = (unsigned long)x;
-
-	return addr >= VMALLOC_START && addr < VMALLOC_END;
-}
-#endif
-EXPORT_SYMBOL(is_vmalloc_addr);
-
-
-
 static struct vmap_area *__find_vmap_area(unsigned long addr)
 {
 	struct rb_node *n = vmap_area_root.rb_node;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index bddb720..b094741 100755
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1510,8 +1510,8 @@
 	if (wiphy_idx_valid(reg_request->wiphy_idx))
 		wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
 
-	if (reg_initiator == NL80211_REGDOM_SET_BY_DRIVER &&
-	    !wiphy) {
+	if ((reg_initiator == NL80211_REGDOM_SET_BY_DRIVER ||
+	     reg_initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) && !wiphy) {
 		kfree(reg_request);
 		return;
 	}
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index c62f875..f874c43 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -3404,6 +3404,7 @@
 					TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
 			ret |= taiko_codec_enable_anc(w, kcontrol, event);
 		}
+		break;
 	case SND_SOC_DAPM_POST_PMD:
 		ret = taiko_hph_pa_event(w, kcontrol, event);
 		break;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 69a6671..4c3a72e 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -2203,6 +2203,22 @@
 		.codec_name = "snd-soc-dummy",
 	},
 	{
+		.name = "Voice2",
+		.stream_name = "Voice2",
+		.cpu_dai_name   = "Voice2",
+		.platform_name  = "msm-pcm-voice",
+		.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",
+		.be_id = MSM_FRONTEND_DAI_VOICE2,
+	},
+	{
 		.name = "INT_HFP_BT Hostless",
 		.stream_name = "INT_HFP_BT Hostless",
 		.cpu_dai_name   = "INT_HFP_BT_HOSTLESS",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index f25f746..3ddc3e0 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -25,6 +25,7 @@
 #include <sound/pcm.h>
 #include <sound/initval.h>
 #include <sound/control.h>
+#include <sound/q6audio-v2.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <linux/msm_audio_ion.h>
@@ -916,11 +917,12 @@
 	int rc;
 	int id;
 	struct msm_plat_data *pdata;
+	const char *latency_level;
 
 	rc = of_property_read_u32(pdev->dev.of_node,
-				"qcom,msm-pcm-dsp-id", &id);
+				"qti,msm-pcm-dsp-id", &id);
 	if (rc) {
-		dev_err(&pdev->dev, "%s: qcom,msm-pcm-dsp-id missing in DT node\n",
+		dev_err(&pdev->dev, "%s: qti,msm-pcm-dsp-id missing in DT node\n",
 					__func__);
 		return rc;
 	}
@@ -932,10 +934,17 @@
 	}
 
 	if (of_property_read_bool(pdev->dev.of_node,
-				"qcom,msm-pcm-low-latency"))
-		pdata->perf_mode = 1;
-	else
-		pdata->perf_mode = 0;
+				"qti,msm-pcm-low-latency")) {
+
+		pdata->perf_mode = LOW_LATENCY_PCM_MODE;
+		rc = of_property_read_string(pdev->dev.of_node,
+			"qti,latency-level", &latency_level);
+		if (!rc) {
+			if (!strcmp(latency_level, "ultra"))
+				pdata->perf_mode = ULTRA_LOW_LATENCY_PCM_MODE;
+		}
+	} else
+		pdata->perf_mode = LEGACY_PCM_MODE;
 
 	dev_set_drvdata(&pdev->dev, pdata);
 
@@ -957,7 +966,7 @@
 	return 0;
 }
 static const struct of_device_id msm_pcm_dt_match[] = {
-	{.compatible = "qcom,msm-pcm-dsp"},
+	{.compatible = "qti,msm-pcm-dsp"},
 	{}
 };
 MODULE_DEVICE_TABLE(of, msm_pcm_dt_match);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 711291da..91c0744 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -290,7 +290,7 @@
 /* Track performance mode of all front-end multimedia sessions.
  * Performance mode is only valid when session is valid.
  */
-static bool fe_dai_perf_mode[MSM_FRONTEND_DAI_MM_SIZE][2];
+static int fe_dai_perf_mode[MSM_FRONTEND_DAI_MM_SIZE][2];
 
 static uint8_t is_be_dai_extproc(int be_dai)
 {
@@ -303,7 +303,7 @@
 }
 
 static void msm_pcm_routing_build_matrix(int fedai_id, int dspst_id,
-	int path_type, bool perf_mode)
+	int path_type, int perf_mode)
 {
 	int i, port_type;
 	struct route_payload payload;
@@ -365,7 +365,7 @@
 	mutex_unlock(&routing_lock);
 }
 
-void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
+void msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
 					int dspst_id, int stream_type)
 {
 	int i, session_type, path_type, port_type, port_id, topology;
@@ -437,7 +437,7 @@
 			port_id = srs_port_id = msm_bedais[i].port_id;
 			srs_send_params(srs_port_id, 1, 0);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (!perf_mode))
+			    (perf_mode == LEGACY_PCM_MODE))
 				if (dolby_dap_init(port_id,
 						msm_bedais[i].channel) < 0)
 					pr_err("%s: Err init dolby dap\n",
@@ -494,7 +494,8 @@
 			adm_close(msm_bedais[i].port_id,
 				  fe_dai_perf_mode[fedai_id][session_type]);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (fe_dai_perf_mode[fedai_id][session_type] == false))
+			    (fe_dai_perf_mode[fedai_id][session_type] ==
+							LEGACY_PCM_MODE))
 				dolby_dap_deinit(msm_bedais[i].port_id);
 		}
 	}
@@ -604,7 +605,8 @@
 			port_id = srs_port_id = msm_bedais[reg].port_id;
 			srs_send_params(srs_port_id, 1, 0);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (fe_dai_perf_mode[val][session_type] == false))
+			    (fe_dai_perf_mode[val][session_type] ==
+							LEGACY_PCM_MODE))
 				if (dolby_dap_init(port_id, channels) < 0)
 					pr_err("%s: Err init dolby dap\n",
 						__func__);
@@ -621,7 +623,8 @@
 			adm_close(msm_bedais[reg].port_id,
 				  fe_dai_perf_mode[val][session_type]);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (fe_dai_perf_mode[val][session_type] == false))
+			    (fe_dai_perf_mode[val][session_type] ==
+							LEGACY_PCM_MODE))
 				dolby_dap_deinit(msm_bedais[reg].port_id);
 			msm_pcm_routing_build_matrix(val,
 				fdai->strm_id, path_type,
@@ -3960,7 +3963,8 @@
 				  fe_dai_perf_mode[i][session_type]);
 			srs_port_id = -1;
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (fe_dai_perf_mode[i][session_type] == false))
+			    (fe_dai_perf_mode[i][session_type] ==
+							LEGACY_PCM_MODE))
 				dolby_dap_deinit(bedai->port_id);
 		}
 	}
@@ -4060,7 +4064,8 @@
 			port_id = srs_port_id = bedai->port_id;
 			srs_send_params(srs_port_id, 1, 0);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (fe_dai_perf_mode[i][session_type] == false))
+			    (fe_dai_perf_mode[i][session_type] ==
+							LEGACY_PCM_MODE))
 				if (dolby_dap_init(port_id, channels) < 0)
 					pr_err("%s: Err init dolby dap\n",
 						__func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 4f7c4e3..54f5e4a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -143,7 +143,7 @@
  * dspst_id:  DSP audio stream ID
  * stream_type: playback or capture
  */
-void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode, int dspst_id,
+void msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, int dspst_id,
 	int stream_type);
 void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
 		int stream_type);
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 6cb7ce1..54b1263 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -702,7 +702,8 @@
 	return;
 }
 
-static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
+static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal,
+			      int perf_mode)
 {
 	s32				result = 0;
 	struct adm_cmd_set_pp_params_v5	adm_params;
@@ -731,7 +732,14 @@
 	adm_params.hdr.src_port = port_id;
 	adm_params.hdr.dest_svc = APR_SVC_ADM;
 	adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
-	adm_params.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+
+	if (perf_mode == LEGACY_PCM_MODE)
+		adm_params.hdr.dest_port =
+			atomic_read(&this_adm.copp_id[index]);
+	else
+		adm_params.hdr.dest_port =
+			atomic_read(&this_adm.copp_low_latency_id[index]);
+
 	adm_params.hdr.token = port_id;
 	adm_params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
 	adm_params.payload_addr_lsw = aud_cal->cal_paddr;
@@ -767,7 +775,7 @@
 	return result;
 }
 
-static void send_adm_cal(int port_id, int path)
+static void send_adm_cal(int port_id, int path, int perf_mode)
 {
 	int			result = 0;
 	s32			acdb_path;
@@ -808,7 +816,7 @@
 		}
 	}
 
-	if (!send_adm_cal_block(port_id, &aud_cal))
+	if (!send_adm_cal_block(port_id, &aud_cal, perf_mode))
 		pr_debug("%s: Audproc cal sent for port id: %#x, path %d\n",
 			__func__, port_id, acdb_path);
 	else
@@ -842,7 +850,7 @@
 		}
 	}
 
-	if (!send_adm_cal_block(port_id, &aud_cal))
+	if (!send_adm_cal_block(port_id, &aud_cal, perf_mode))
 		pr_debug("%s: Audvol cal sent for port id: %#x, path %d\n",
 			__func__, port_id, acdb_path);
 	else
@@ -1048,7 +1056,7 @@
 }
 
 int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
-			bool perf_mode, uint16_t bits_per_sample)
+			int perf_mode, uint16_t bits_per_sample)
 {
 	struct adm_cmd_device_open_v5	open;
 	int ret = 0;
@@ -1079,7 +1087,7 @@
 		rtac_set_adm_handle(this_adm.apr);
 	}
 
-	if (!perf_mode) {
+	if (perf_mode == LEGACY_PCM_MODE) {
 		atomic_set(&this_adm.copp_perf_mode[index], 0);
 		send_adm_custom_topology(port_id);
 	} else {
@@ -1087,8 +1095,9 @@
 	}
 
 	/* Create a COPP if port id are not enabled */
-	if ((!perf_mode && (atomic_read(&this_adm.copp_cnt[index]) == 0)) ||
-		(perf_mode &&
+	if ((perf_mode == LEGACY_PCM_MODE &&
+		(atomic_read(&this_adm.copp_cnt[index]) == 0)) ||
+		(perf_mode != LEGACY_PCM_MODE &&
 		(atomic_read(&this_adm.copp_low_latency_cnt[index]) == 0))) {
 		pr_debug("%s:opening ADM: perf_mode: %d\n", __func__,
 			perf_mode);
@@ -1103,12 +1112,12 @@
 		open.hdr.dest_port = tmp_port;
 		open.hdr.token = port_id;
 		open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
-		open.flags = 0x00;
-		if (perf_mode) {
-			open.flags |= ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
-		} else {
-			open.flags |= ADM_LEGACY_DEVICE_SESSION;
-		}
+		if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
+			open.flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
+		else if (perf_mode == LOW_LATENCY_PCM_MODE)
+			open.flags = ADM_LOW_LATENCY_DEVICE_SESSION;
+		else
+			open.flags = ADM_LEGACY_DEVICE_SESSION;
 
 		open.mode_of_operation = path;
 		open.endpoint_id_1 = tmp_port;
@@ -1125,7 +1134,7 @@
 			(open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
 				rate = 16000;
 
-		if (perf_mode) {
+		if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
 			open.topology_id = NULL_COPP_TOPOLOGY;
 			rate = ULL_SUPPORTED_SAMPLE_RATE;
 			if(channel_mode > ULL_MAX_SUPPORTED_CHANNEL)
@@ -1133,7 +1142,8 @@
 		}
 		open.dev_num_channel = channel_mode & 0x00FF;
 		open.bit_width = bits_per_sample;
-		WARN_ON(perf_mode && (rate != 48000));
+		WARN_ON(perf_mode == ULTRA_LOW_LATENCY_PCM_MODE &&
+							(rate != 48000));
 		open.sample_rate  = rate;
 		memset(open.dev_channel_mapping, 0, 8);
 
@@ -1208,7 +1218,8 @@
 			goto fail_cmd;
 		}
 	}
-	if (perf_mode) {
+	if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+			perf_mode == LOW_LATENCY_PCM_MODE) {
 		atomic_inc(&this_adm.copp_low_latency_cnt[index]);
 		pr_debug("%s: index: %d coppid: %d", __func__, index,
 			atomic_read(&this_adm.copp_low_latency_id[index]));
@@ -1225,7 +1236,7 @@
 }
 
 int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
-			int topology, bool perf_mode, uint16_t bits_per_sample)
+			int topology, int perf_mode, uint16_t bits_per_sample)
 {
 	int ret = 0;
 
@@ -1236,7 +1247,7 @@
 }
 
 int adm_matrix_map(int session_id, int path, int num_copps,
-			unsigned int *port_id, int copp_id, bool perf_mode)
+			unsigned int *port_id, int copp_id, int perf_mode)
 {
 	struct adm_cmd_matrix_map_routings_v5	*route;
 	struct adm_session_map_node_v5 *node;
@@ -1275,7 +1286,8 @@
 	route->hdr.src_port = copp_id;
 	route->hdr.dest_svc = APR_SVC_ADM;
 	route->hdr.dest_domain = APR_DOMAIN_ADSP;
-	if (perf_mode) {
+	if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+			perf_mode == LOW_LATENCY_PCM_MODE) {
 		route->hdr.dest_port =
 			atomic_read(&this_adm.copp_low_latency_id[index]);
 	} else {
@@ -1313,7 +1325,8 @@
 
 
 		if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
-			if (perf_mode)
+			if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+					perf_mode == LOW_LATENCY_PCM_MODE)
 				copps_list[i] =
 				atomic_read(&this_adm.copp_low_latency_id[tmp]);
 			else
@@ -1323,8 +1336,7 @@
 		else
 			continue;
 		pr_debug("%s: port_id[%#x]: %d, index: %d act coppid[0x%x]\n",
-			__func__, i, port_id[i], tmp,
-			atomic_read(&this_adm.copp_id[tmp]));
+			__func__, i, port_id[i], tmp, copps_list[i]);
 	}
 	atomic_set(&this_adm.copp_stat[index], 0);
 
@@ -1344,25 +1356,31 @@
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
-	if (!perf_mode) {
+
+	if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
 		for (i = 0; i < num_copps; i++)
-			send_adm_cal(port_id[i], path);
+			send_adm_cal(port_id[i], path, perf_mode);
 
 		for (i = 0; i < num_copps; i++) {
-			int tmp;
+			int tmp, copp_id;
 			tmp = afe_get_port_index(port_id[i]);
 			if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
+				if (perf_mode == LEGACY_PCM_MODE)
+					copp_id = atomic_read(
+					&this_adm.copp_id[tmp]);
+				else
+					copp_id = atomic_read(
+					&this_adm.copp_low_latency_id[tmp]);
 				rtac_add_adm_device(port_id[i],
-					atomic_read(&this_adm.copp_id[tmp]),
-					path, session_id);
-				pr_debug("%s, copp_id: %d\n", __func__,
-					atomic_read(&this_adm.copp_id[tmp]));
-			} else {
+						copp_id, path, session_id);
+				pr_debug("%s, copp_id: %d\n",
+							__func__, copp_id);
+			} else
 				pr_debug("%s: Invalid port index %d",
-					__func__, tmp);
-			}
+							__func__, tmp);
 		}
 	}
+
 fail_cmd:
 	kfree(matrix_map);
 	return ret;
@@ -1514,8 +1532,26 @@
 	return ret;
 }
 
+#ifdef CONFIG_RTAC
 int adm_get_copp_id(int port_index)
 {
+	int copp_id;
+	pr_debug("%s\n", __func__);
+
+	if (port_index < 0) {
+		pr_err("%s: invalid port_id = %d\n", __func__, port_index);
+		return -EINVAL;
+	}
+
+	copp_id = atomic_read(&this_adm.copp_id[port_index]);
+	if (copp_id == RESET_COPP_ID)
+		copp_id = atomic_read(
+			&this_adm.copp_low_latency_id[port_index]);
+	return copp_id;
+}
+
+int adm_get_lowlatency_copp_id(int port_index)
+{
 	pr_debug("%s\n", __func__);
 
 	if (port_index < 0) {
@@ -1523,8 +1559,19 @@
 		return -EINVAL;
 	}
 
-	return atomic_read(&this_adm.copp_id[port_index]);
+	return atomic_read(&this_adm.copp_low_latency_id[port_index]);
 }
+#else
+int adm_get_copp_id(int port_index)
+{
+	return -EINVAL;
+}
+
+int adm_get_lowlatency_copp_id(int port_index)
+{
+	return -EINVAL;
+}
+#endif /* #ifdef CONFIG_RTAC */
 
 void adm_ec_ref_rx_id(int port_id)
 {
@@ -1532,12 +1579,13 @@
 	pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
 }
 
-int adm_close(int port_id, bool perf_mode)
+int adm_close(int port_id, int perf_mode)
 {
 	struct apr_hdr close;
 
 	int ret = 0;
 	int index = 0;
+	int copp_id = RESET_COPP_ID;
 
 	port_id = q6audio_convert_virtual_to_portid(port_id);
 
@@ -1548,7 +1596,8 @@
 	pr_debug("%s port_id=%#x index %d perf_mode: %d\n", __func__, port_id,
 		index, perf_mode);
 
-	if (perf_mode) {
+	if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+				perf_mode == LOW_LATENCY_PCM_MODE) {
 		if (!(atomic_read(&this_adm.copp_low_latency_cnt[index]))) {
 			pr_err("%s: copp count for port[%#x]is 0\n", __func__,
 				port_id);
@@ -1563,8 +1612,9 @@
 		}
 		atomic_dec(&this_adm.copp_cnt[index]);
 	}
-	if ((!perf_mode && !(atomic_read(&this_adm.copp_cnt[index]))) ||
-		(perf_mode &&
+	if ((perf_mode == LEGACY_PCM_MODE &&
+		!(atomic_read(&this_adm.copp_cnt[index]))) ||
+		((perf_mode != LEGACY_PCM_MODE) &&
 		!(atomic_read(&this_adm.copp_low_latency_cnt[index])))) {
 
 		pr_debug("%s:Closing ADM: perf_mode: %d\n", __func__,
@@ -1577,7 +1627,8 @@
 		close.src_port = port_id;
 		close.dest_svc = APR_SVC_ADM;
 		close.dest_domain = APR_DOMAIN_ADSP;
-		if (perf_mode)
+		if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+				perf_mode == LOW_LATENCY_PCM_MODE)
 			close.dest_port =
 			     atomic_read(&this_adm.copp_low_latency_id[index]);
 		else
@@ -1587,18 +1638,23 @@
 
 		atomic_set(&this_adm.copp_stat[index], 0);
 
-		if (perf_mode) {
+		if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+				perf_mode == LOW_LATENCY_PCM_MODE) {
+			copp_id = atomic_read(
+				&this_adm.copp_low_latency_id[index]);
 			pr_debug("%s:coppid %d portid=%#x index=%d coppcnt=%d\n",
-			    __func__,
-			    atomic_read(&this_adm.copp_low_latency_id[index]),
-			    port_id, index,
-			    atomic_read(&this_adm.copp_low_latency_cnt[index]));
+				__func__,
+				copp_id,
+				port_id, index,
+				atomic_read(
+					&this_adm.copp_low_latency_cnt[index]));
 			atomic_set(&this_adm.copp_low_latency_id[index],
 				RESET_COPP_ID);
 		} else {
+			copp_id = atomic_read(&this_adm.copp_id[index]);
 			pr_debug("%s:coppid %d portid=%#x index=%d coppcnt=%d\n",
 				__func__,
-				atomic_read(&this_adm.copp_id[index]),
+				copp_id,
 				port_id, index,
 				atomic_read(&this_adm.copp_cnt[index]));
 			atomic_set(&this_adm.copp_id[index],
@@ -1623,9 +1679,9 @@
 		}
 	}
 
-	if (!perf_mode) {
+	if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
 		pr_debug("%s: remove adm device from rtac\n", __func__);
-		rtac_remove_adm_device(port_id);
+		rtac_remove_adm_device(port_id, copp_id);
 	}
 
 fail_cmd:
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 631e9bd..24f5f3b 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -39,6 +39,7 @@
 
 #include <sound/apr_audio-v2.h>
 #include <sound/q6asm-v2.h>
+#include <sound/q6audio-v2.h>
 
 #include "audio_acdb.h"
 
@@ -354,7 +355,7 @@
 	session[ac->session] = 0;
 	mutex_unlock(&session_lock);
 	ac->session = 0;
-	ac->perf_mode = 0;
+	ac->perf_mode = LEGACY_PCM_MODE;
 	ac->fptr_cache_ops = NULL;
 	return;
 }
@@ -810,7 +811,7 @@
 	ac->cb = cb;
 	ac->priv = priv;
 	ac->io_mode = SYNC_IO_MODE;
-	ac->perf_mode = false;
+	ac->perf_mode = LEGACY_PCM_MODE;
 	ac->fptr_cache_ops = NULL;
 	ac->apr = apr_register("ADSP", "ASM", \
 				(apr_fn)q6asm_callback,\
@@ -1695,7 +1696,7 @@
 	open.bits_per_sample = bits_per_sample;
 	open.mode_flags = 0x0;
 
-	if (ac->perf_mode) {
+	if (ac->perf_mode == LOW_LATENCY_PCM_MODE) {
 		open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION <<
 				ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ;
 	} else {
@@ -1781,8 +1782,10 @@
 
 	open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;
 	open.mode_flags = 0x00;
-	if (ac->perf_mode)
+	if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
 		open.mode_flags |= ASM_ULTRA_LOW_LATENCY_STREAM_SESSION;
+	else if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
+		open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
 	else {
 		open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
 		if (is_gapless_mode)
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index f74dbe2..701dfef 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -556,7 +556,8 @@
 	/* Check if device already added */
 	if (rtac_adm_data.num_of_dev != 0) {
 		for (; i < rtac_adm_data.num_of_dev; i++) {
-			if (rtac_adm_data.device[i].afe_port == port_id) {
+			if (rtac_adm_data.device[i].afe_port == port_id &&
+			    rtac_adm_data.device[i].copp == copp_id) {
 				add_popp(i, port_id, popp_id);
 				goto done;
 			}
@@ -609,7 +610,7 @@
 	}
 }
 
-void rtac_remove_adm_device(u32 port_id)
+void rtac_remove_adm_device(u32 port_id, u32 copp_id)
 {
 	s32 i;
 	pr_debug("%s: port_id = %d\n", __func__, port_id);
@@ -619,7 +620,8 @@
 
 	/* look for device */
 	for (i = 0; i < rtac_adm_data.num_of_dev; i++) {
-		if (rtac_adm_data.device[i].afe_port == port_id) {
+		if (rtac_adm_data.device[i].afe_port == port_id &&
+		    rtac_adm_data.device[i].copp == copp_id) {
 			memset(&rtac_adm_data.device[i], 0,
 				   sizeof(rtac_adm_data.device[i]));
 			rtac_adm_data.num_of_dev--;
@@ -870,6 +872,8 @@
 	for (port_index = 0; port_index < AFE_MAX_PORTS; port_index++) {
 		if (adm_get_copp_id(port_index) == copp_id)
 			break;
+		if (adm_get_lowlatency_copp_id(port_index) == copp_id)
+			break;
 	}
 	if (port_index >= AFE_MAX_PORTS) {
 		pr_err("%s: Could not find port index for copp = %d\n",