Merge "arm/dt: zinc: Add initial device tree for MSMZINC"
diff --git a/Documentation/cgroups/cpuacct.txt b/Documentation/cgroups/cpuacct.txt
index e21a932..9d73cc0 100644
--- a/Documentation/cgroups/cpuacct.txt
+++ b/Documentation/cgroups/cpuacct.txt
@@ -39,13 +39,6 @@
 
 user and system are in USER_HZ unit.
 
-cpuacct.cpufreq file gives CPU time (in nanoseconds) spent at each CPU
-frequency. Platform hooks must be implemented inorder to properly track
-time at each CPU frequency.
-
-cpuacct.power file gives CPU power consumed (in milliWatt seconds). Platform
-must provide and implement power callback functions.
-
 cpuacct controller uses percpu_counter interface to collect user and
 system times. This has two side effects:
 
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index 6d22003..195a98d 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -8,17 +8,24 @@
 lpm-level. The units for voltage are dependent on the PMIC used on the target
 and are in uV.
 
-The optional properties are:
-
-- qcom,use-qtimer: Indicates whether the target uses the synchronized QTimer.
-
 The required nodes for lpm-levels are:
 
 - compatible: "qcom,lpm-levels"
 - reg: The numeric level id
-- qcom,mode: The sleep mode of the processor
-- qcom,xo: The state of XO clock.
-- qcom,l2: The state of L2 cache.
+- qcom,mode: The sleep mode of the processor, values for the property are:
+		"wfi" - Wait for Interrupt
+		"ramp_down_and_wfi" - Ramp down and wait for interrupt
+		"standalone_pc" - Standalone power collapse
+		"pc" - Power Collapse
+		"retention" - Retention
+		"pc_suspend" - Suspended Power Collapse
+		"pc_no_xo_shutdown" - Power Collapse with no XO shutdown
+- qcom,xo: The state of XO clock. Values are "xo_on" and "xo_off"
+- qcom,l2: The state of L2 cache. Values are:
+		"l2_cache_pc" - L2 cache in power collapse
+		"l2_cache_retenetion" - L2 cache in retention
+		"l2_cache_gdhs" - L2 cache in GDHS
+		"l2_cache_active" - L2 cache in active mode
 - qcom,vdd-mem-upper-bound: The upper bound value of mem voltage in uV
 - qcom,vdd-mem-lower-bound: The lower bound value of mem voltage in uV
 - qcom,vdd-dig-upper-bound: The upper bound value of dig voltage in uV
@@ -41,6 +48,7 @@
 - qcom,gpio-detectable: The field indicates whether the GPIOs can be detected
 			by the GPIO interrupt controller during a given low
 			power mode.
+- qcom,use-qtimer: Indicates whether the target uses the synchronized QTimer.
 
 Example:
 
@@ -48,9 +56,9 @@
 	qcom,use-qtimer;
 	qcom,lpm-level@0 {
 		reg = <0>;
-		qcom,mode = <0>;        /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
-		qcom,xo = <1>;          /* ON */
-		qcom,l2 = <3>;          /* ACTIVE */
+		qcom,mode = "wfi";
+		qcom,xo = "xo_on";
+		qcom,l2 = "l2_cache_active";
 		qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 		qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 		qcom,vdd-dig-upper-bound = <5>; /* MAX */
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
index ccb3465..7b5fda3 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
@@ -20,10 +20,9 @@
 - reg: The numeric level id
 - qcom,name: The name of the low power resource represented
              as a string.
-- qcom,resource-type: The type of the LPM resource.
-   MSM_LPM_RPM_RS_TYPE    = 0
-   MSM_LPM_LOCAL_RS_TYPE  = 1
-- qcom,init-value: Initialization value of the LPM resource.
+- qcom,init-value: Initialization value of the LPM resource represented as
+			decimal value for vdd-dig and vdd-mem resources and
+			as string for pxo and l2 resources.
 
 
 Optional Nodes:
@@ -33,12 +32,13 @@
 - qcom,id: The id representing a device within a resource type.
 - qcom,key: The key is the specific attribute of the resource being
             monitored represented as a hex value.
+- qcom,local-resource-type: The property exists only for locally managed
+				resource and is represented as a bool.
 
 Example:
             qcom,lpm-resources@0 {
                         reg = <0x0>;
                         qcom,name = "vdd-dig";
-                        qcom,resource-type = <0>;
                         qcom,type = <0x62706d73>;   /* "smpb" */
                         qcom,id = <0x02>;
                         qcom,key = <0x6e726f63>;   /* "corn" */
diff --git a/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
index a372912..c741514 100644
--- a/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
+++ b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
@@ -18,10 +18,10 @@
 - reg: physical IMEM address reserved for PC counters and the size
 - qcom,use-sync-timer: Indicates whether the target uses the synchronized QTimer.
 - qcom,pc-mode: Indicates the type of power collapse used by the target. The
-	valid values for this are:
-	0  (Power collapse terminates in TZ; integrated L2 cache controller)
-	1, (Power collapse doesn't terminate in TZ; external L2 cache controller)
-	2  (Power collapse terminates in TZ; external L2 cache controller)
+           valid values for this are:
+	"tz_l2_int"  (Power collapse terminates in TZ; integrated L2 cache controller)
+	"no_tz_l2_ext", (Power collapse doesn't terminate in TZ; external L2 cache controller)
+	"tz_l2_ext"  (Power collapse terminates in TZ; external L2 cache controller)
 - qcom,saw-turns-off-pll: Version of SAW2.1 or can turn off the HFPLL, when
 	doing power collapse and so the core need to switch to Global PLL before
 	PC.
@@ -31,6 +31,6 @@
 qcom,pm-8x60@fe800664 {
 		compatible = "qcom,pm-8x60";
 		reg = <0xfe800664 0x40>;
-		qcom,pc-mode = <0>;
+		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
 	};
diff --git a/Documentation/devicetree/bindings/arm/msm/pm-boot.txt b/Documentation/devicetree/bindings/arm/msm/pm-boot.txt
index cce9d0e..7ba8a6d 100644
--- a/Documentation/devicetree/bindings/arm/msm/pm-boot.txt
+++ b/Documentation/devicetree/bindings/arm/msm/pm-boot.txt
@@ -16,10 +16,10 @@
 
 - compatible: Must be "qcom,pm-boot"
 - qcom,mode: The mode that the target will use for booting
-	MSM_PM_BOOT_CONFIG_TZ                = 0,
-	MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS = 1,
-	MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT = 2,
-	MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR   = 3,
+	"tz" = MSM_PM_BOOT_CONFIG_TZ,
+	"reset_vector_phys" = MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS,
+	"reset_vector_virt" = MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT,
+	"remap_boot_addr" = MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR,
 
 Optional parameters (based on the mode chosen):
 
@@ -36,5 +36,5 @@
 
 	qcom,pm-boot {
 		compatible = "qcom,pm-boot";
-		qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+		qcom,mode = "tz"; /* MSM_PM_BOOT_CONFIG_TZ */
 	};
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 1885e8a..9f8bbd9 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -15,7 +15,10 @@
 	"wakeup" : Wakeup interrupt from HSIC during suspend (or XO shutdown).
 - hsic,<gpio-name>-gpio : handle to the GPIO node, see "gpios property"
   in Documentation/devicetree/bindings/gpio/gpio.txt.
-  Optional "gpio-name" can be "strobe" and "data".
+  Optional "gpio-name" can be "strobe", "data" and "resume".
+- hsic,resume-gpio : if present then periperal connected to hsic controller
+  cannot wakeup from XO shutdown using in-band hsic resume. Use resume
+  gpio to wakeup peripheral
 - hsic,ignore-cal-pad-config : If present then HSIC CAL PAD configuration
   using TLMM is not performed.
 - hsic,strobe-pad-offset : Offset of TLMM register for configuring HSIC
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6839263..17a44b3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1830,13 +1830,6 @@
 	  Enable hardware performance counter support for perf events. If
 	  disabled, perf events will use software events only.
 
-config VMALLOC_RESERVE
-	hex "Reserved vmalloc space"
-	default 0x08000000
-	depends on MMU
-	help
-	  Reserved vmalloc space if not specified on the kernel commandline.
-
 source "mm/Kconfig"
 
 config ARCH_MEMORY_PROBE
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 6348f5a..2351d9c 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -22,7 +22,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 2b 06 26 30 0f];
@@ -39,7 +39,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 2b 06 26 30 0f];
@@ -56,7 +56,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 2b 06 26 30 0f];
@@ -73,7 +73,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 2b 06 26 30 0f];
@@ -90,7 +90,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x14>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-pmic-data0 = <0x0400009c>;
 		qcom,saw2-pmic-data1 = <0x0000001c>;
 		qcom,vctl-timeout-us = <50>;
@@ -114,7 +114,6 @@
 		qcom,lpm-resources@0 {
 			reg = <0x0>;
 			qcom,name = "vdd-dig";
-			qcom,resource-type = <0>;
 			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x02>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
@@ -124,7 +123,6 @@
 		qcom,lpm-resources@1 {
 			reg = <0x1>;
 			qcom,name = "vdd-mem";
-			qcom,resource-type = <0>;
 			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x01>;
 			qcom,key = <0x7675>;		/* "uv" */
@@ -134,18 +132,17 @@
 		qcom,lpm-resources@2 {
 			reg = <0x2>;
 			qcom,name = "pxo";
-			qcom,resource-type = <0>;
 			qcom,type = <0x306b6c63>;	/* "clk0" */
 			qcom,id = <0x00>;
 			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = <1>;		/* On */
+			qcom,init-value = "xo_on";
 		};
 
 		qcom,lpm-resources@3 {
 			reg = <0x3>;
 			qcom,name = "l2";
-			qcom,resource-type = <1>;
-			qcom,init-value = <2>;		/* Retention */
+			qcom,local-resource-type;
+			qcom,init-value = "l2_cache_retention";
 		};
 	};
 
@@ -156,9 +153,9 @@
 
 		qcom,lpm-level@0 {
 			reg = <0x0>;
-			qcom,mode = <0>;        /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "wfi";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -171,9 +168,9 @@
 
 		qcom,lpm-level@1 {
 			reg = <0x1>;
-			qcom,mode = <4>;        /* MSM_PM_SLEEP_MODE_RETENTION*/
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "retention";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -187,9 +184,9 @@
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
-			qcom,mode = <2>;        /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "standalone_pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -202,9 +199,9 @@
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -217,9 +214,9 @@
 
 		qcom,lpm-level@4 {
 			reg = <0x4>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
 			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
@@ -232,9 +229,9 @@
 
 		qcom,lpm-level@5 {
 			reg = <0x5>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -247,9 +244,9 @@
 
 		qcom,lpm-level@6 {
 			reg = <0x6>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -262,9 +259,9 @@
 
 		qcom,lpm-level@7 {
 			reg = <0x7>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
 			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
@@ -277,9 +274,9 @@
 
 		qcom,lpm-level@8 {
 			reg = <0x8>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
 			qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
 			qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
@@ -293,7 +290,7 @@
 
 	qcom,pm-boot {
 		compatible = "qcom,pm-boot";
-		qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+		qcom,mode = "tz";
 	};
 
 	qcom,mpm@fc4281d0 {
@@ -392,7 +389,7 @@
 	qcom,pm-8x60@fe805664 {
 		compatible = "qcom,pm-8x60";
 		reg = <0xfe805664 0x40>;
-		qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
 	};
 
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 223675d..17de157 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -201,16 +201,14 @@
 			"DMIC3", "MIC BIAS3 External",
 			"MIC BIAS3 External", "Digital Mic3",
 			"DMIC4", "MIC BIAS3 External",
-			"MIC BIAS3 External", "Digital Mic4",
-			"DMIC5", "MIC BIAS4 External",
-			"MIC BIAS4 External", "Digital Mic5",
-			"DMIC6", "MIC BIAS4 External",
-			"MIC BIAS4 External", "Digital Mic6";
+			"MIC BIAS3 External", "Digital Mic4";
+
 		qcom,tapan-mclk-clk-freq = <9600000>;
 	};
 
 	qcom,msm-pcm {
 		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <0>;
 	};
 
 	qcom,msm-pcm-routing {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index feb3087..d6e143c 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -114,7 +114,6 @@
 		qcom,lpm-resources@0 {
 			reg = <0x0>;
 			qcom,name = "vdd-dig";
-			qcom,resource-type = <0>;
 			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x02>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
@@ -124,7 +123,6 @@
 		qcom,lpm-resources@1 {
 			reg = <0x1>;
 			qcom,name = "vdd-mem";
-			qcom,resource-type = <0>;
 			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x01>;
 			qcom,key = <0x7675>;		/* "uv" */
@@ -134,18 +132,17 @@
 		qcom,lpm-resources@2 {
 			reg = <0x2>;
 			qcom,name = "pxo";
-			qcom,resource-type = <0>;
 			qcom,type = <0x306b6c63>;	/* "clk0" */
 			qcom,id = <0x00>;
 			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = <1>;		/* On */
+			qcom,init-value = "xo_on";
 		};
 
 		qcom,lpm-resources@3 {
 			reg = <0x3>;
 			qcom,name = "l2";
-			qcom,resource-type = <1>;
-			qcom,init-value = <2>;		/* Retention */
+			qcom,local-resource-type;
+			qcom,init-value = "l2_cache_retention";
 		};
 	};
 
@@ -156,9 +153,9 @@
 
 		qcom,lpm-level@0 {
 			reg = <0x0>;
-			qcom,mode = <0>;        /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "wfi";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -171,9 +168,9 @@
 
 		qcom,lpm-level@1 {
 			reg = <0x1>;
-			qcom,mode = <4>;        /* MSM_PM_SLEEP_MODE_RETENTION*/
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "retention";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -187,9 +184,9 @@
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
-			qcom,mode = <2>;        /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "standalone_pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -202,9 +199,9 @@
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -217,9 +214,9 @@
 
 		qcom,lpm-level@4 {
 			reg = <0x4>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
 			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
@@ -232,9 +229,9 @@
 
 		qcom,lpm-level@5 {
 			reg = <0x5>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -247,9 +244,9 @@
 
 		qcom,lpm-level@6 {
 			reg = <0x6>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -262,9 +259,9 @@
 
 		qcom,lpm-level@7 {
 			reg = <0x7>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
 			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
@@ -277,9 +274,9 @@
 
 		qcom,lpm-level@8 {
 			reg = <0x8>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
 			qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
 			qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
@@ -293,7 +290,7 @@
 
 	qcom,pm-boot {
 		compatible = "qcom,pm-boot";
-		qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+		qcom,mode = "tz";
 	};
 
 	qcom,mpm@fc4281d0 {
@@ -385,7 +382,7 @@
 	qcom,pm-8x60@fe805664 {
 		compatible = "qcom,pm-8x60";
 		reg = <0xfe805664 0x40>;
-		qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 2b1cbb5..45cbc89 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -213,6 +213,7 @@
                 HSIC_GDSC-supply = <&gdsc_usb_hsic>;
                 hsic,strobe-gpio = <&msmgpio 144 0x00>;
                 hsic,data-gpio = <&msmgpio 145 0x00>;
+                hsic,resume-gpio = <&msmgpio 80 0x00>;
                 hsic,ignore-cal-pad-config;
                 hsic,strobe-pad-offset = <0x2050>;
                 hsic,data-pad-offset = <0x2054>;
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index 0b6fa8c..d8a1444 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -139,7 +139,6 @@
 		qcom,lpm-resources@0 {
 			reg = <0x0>;
 			qcom,name = "vdd-dig";
-			qcom,resource-type = <0>;
 			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x02>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
@@ -149,7 +148,6 @@
 		qcom,lpm-resources@1 {
 			reg = <0x1>;
 			qcom,name = "vdd-mem";
-			qcom,resource-type = <0>;
 			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x01>;
 			qcom,key = <0x7675>;		/* "uv" */
@@ -159,18 +157,17 @@
 		qcom,lpm-resources@2 {
 			reg = <0x2>;
 			qcom,name = "pxo";
-			qcom,resource-type = <0>;
 			qcom,type = <0x306b6c63>;	/* "clk0" */
 			qcom,id = <0x00>;
 			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = <1>;		/* On */
+			qcom,init-value = "xo_on";
 		};
 
 		qcom,lpm-resources@3 {
 			reg = <0x3>;
 			qcom,name = "l2";
-			qcom,resource-type = <1>;
-			qcom,init-value = <2>;		/* Retention */
+			qcom,local-resource-type;
+			qcom,init-value = "l2_cache_retention";
 		};
 	};
 
@@ -183,9 +180,9 @@
 
 		qcom,lpm-level@0 {
 			reg = <0x0>;
-			qcom,mode = <0>;        /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "wfi";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -200,9 +197,9 @@
 
 		qcom,lpm-level@1 {
 			reg = <0x1>;
-			qcom,mode = <4>;        /* MSM_PM_SLEEP_MODE_RETENTION*/
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "retention";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -218,9 +215,9 @@
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
-			qcom,mode = <2>;        /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "standalone_pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -235,9 +232,9 @@
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -252,9 +249,9 @@
 
 		qcom,lpm-level@4 {
 			reg = <0x4>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO  */
@@ -269,9 +266,9 @@
 
 		qcom,lpm-level@5 {
 			reg = <0x5>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -284,9 +281,9 @@
 
 		qcom,lpm-level@6 {
 			reg = <0x6>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -299,9 +296,9 @@
 
 		qcom,lpm-level@7 {
 			reg = <0x7>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode= "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
 			qcom,vdd-mem-lower-bound = <950000>;  /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
@@ -314,9 +311,9 @@
 
 		qcom,lpm-level@8 {
 			reg = <0x8>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode= "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
 			qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
 			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
@@ -330,7 +327,7 @@
 
 	qcom,pm-boot {
 		compatible = "qcom,pm-boot";
-		qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+		qcom,mode = "tz";
 	};
 
 	qcom,mpm@fc4281d0 {
@@ -343,7 +340,8 @@
 		qcom,ipc-bit-offset = <1>;
 
 		qcom,gic-parent = <&intc>;
-		qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
+		qcom,gic-map = <47 165>, /* usb30_hs_phy_irq */
+			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
@@ -423,7 +421,7 @@
 	qcom,pm-8x60@fe805664 {
 		compatible = "qcom,pm-8x60";
 		reg = <0xfe805664 0x40>;
-		qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 8cc497b..e020fa4 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -15,8 +15,8 @@
 / {
 	qcom,spm@f9089000 {
 		compatible = "qcom,spm-v2";
-		#address-cells = <1>;
-		#size-cells = <1>;
+	#address-cells = <1>;
+	#size-cells = <1>;
 		reg = <0xf9089000 0x1000>;
 		qcom,core-id = <0>;
 		qcom,saw2-ver-reg = <0xfd0>;
@@ -29,10 +29,10 @@
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
 		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+			30 06 26 30 0F];
 		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+			E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
 	};
 
 	qcom,spm@f9099000 {
@@ -51,8 +51,8 @@
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
 		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+			30 06 26 30 0F];
 		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
 				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
 	};
@@ -73,8 +73,8 @@
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
 		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+			30 06 26 30 0F];
 		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
 				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
 	};
@@ -95,8 +95,8 @@
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
 		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+			30 06 26 30 0F];
 		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
 				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
 	};
@@ -136,7 +136,6 @@
 		qcom,lpm-resources@0 {
 			reg = <0x0>;
 			qcom,name = "vdd-dig";
-			qcom,resource-type = <0>;
 			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x02>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
@@ -146,7 +145,6 @@
 		qcom,lpm-resources@1 {
 			reg = <0x1>;
 			qcom,name = "vdd-mem";
-			qcom,resource-type = <0>;
 			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x01>;
 			qcom,key = <0x7675>;		/* "uv" */
@@ -156,18 +154,17 @@
 		qcom,lpm-resources@2 {
 			reg = <0x2>;
 			qcom,name = "pxo";
-			qcom,resource-type = <0>;
 			qcom,type = <0x306b6c63>;	/* "clk0" */
 			qcom,id = <0x00>;
 			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = <1>;		/* On */
+			qcom,init-value = "xo_on";
 		};
 
 		qcom,lpm-resources@3 {
 			reg = <0x3>;
 			qcom,name = "l2";
-			qcom,resource-type = <1>;
-			qcom,init-value = <2>;		/* Retention */
+			qcom,local-resource-type;
+			qcom,init-value = "l2_cache_retention";
 		};
 	};
 
@@ -180,9 +177,9 @@
 
 		qcom,lpm-level@0 {
 			reg = <0x0>;
-			qcom,mode = <0>;        /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "wfi";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -197,9 +194,9 @@
 
 		qcom,lpm-level@1 {
 			reg = <0x1>;
-			qcom,mode = <4>;        /* MSM_PM_SLEEP_MODE_RETENTION*/
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "retention";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -215,9 +212,9 @@
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
-			qcom,mode = <2>;        /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "standalone_pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -232,9 +229,9 @@
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -249,9 +246,9 @@
 
 		qcom,lpm-level@4 {
 			reg = <0x4>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO  */
@@ -266,9 +263,9 @@
 
 		qcom,lpm-level@5 {
 			reg = <0x5>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -281,9 +278,9 @@
 
 		qcom,lpm-level@6 {
 			reg = <0x6>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -296,9 +293,9 @@
 
 		qcom,lpm-level@7 {
 			reg = <0x7>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode= "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
 			qcom,vdd-mem-lower-bound = <950000>;  /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
@@ -311,9 +308,9 @@
 
 		qcom,lpm-level@8 {
 			reg = <0x8>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode= "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
 			qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
 			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
@@ -327,7 +324,7 @@
 
 	qcom,pm-boot {
 		compatible = "qcom,pm-boot";
-		qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+		qcom,mode = "tz";
 	};
 
 	qcom,mpm@fc4281d0 {
@@ -340,7 +337,8 @@
 		qcom,ipc-bit-offset = <1>;
 
 		qcom,gic-parent = <&intc>;
-		qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
+		qcom,gic-map = <47 165>, /* usb30_hs_phy_irq */
+			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
@@ -420,7 +418,7 @@
 	qcom,pm-8x60@fe805664 {
 		compatible = "qcom,pm-8x60";
 		reg = <0xfe805664 0x40>;
-		qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
 		qcom,saw-turns-off-pll;
 	};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 3ebdbb6..2a5347e 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1374,8 +1374,8 @@
 
 	sfpb_spinlock: qcom,ipc-spinlock@fd484000 {
 		compatible = "qcom,ipc-spinlock-sfpb";
-		reg = <0xfd484000 0x1000>;
-		qcom,num-locks = <32>;
+		reg = <0xfd484000 0x400>;
+		qcom,num-locks = <8>;
 	};
 
 	ldrex_spinlock: qcom,ipc-spinlock@fa00000 {
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index e881977..51a3faa 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -38,7 +38,6 @@
 		qcom,lpm-resources@0 {
 			reg = <0x0>;
 			qcom,name = "vdd-dig";
-			qcom,resource-type = <0>;
 			qcom,type = <0x616F646C>;       /* "ldoa" */
 			qcom,id = <0x0A>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
@@ -48,7 +47,6 @@
 		qcom,lpm-resources@1 {
 			reg = <0x1>;
 			qcom,name = "vdd-mem";
-			qcom,resource-type = <0>;
 			qcom,type = <0x616F646C>;       /* "ldoa" */
 			qcom,id = <0x0C>;
 			qcom,key =  <0x7675>;		/* "uv" */
@@ -58,11 +56,10 @@
 		qcom,lpm-resources@2 {
 			reg = <0x2>;
 			qcom,name = "pxo";
-			qcom,resource-type = <0>;
 			qcom,type = <0x306b6c63>;	/* "clk0" */
 			qcom,id = <0x00>;
 			qcom,key = <0x62616e45>;	/* "Enab" */
-			qcom,init-value = <1>;		/* On */
+			qcom,init-value = "xo_on";
 		};
 	};
 
@@ -75,9 +72,9 @@
 
 		qcom,lpm-level@0 {
 			reg = <0x0>;
-			qcom,mode = <0>;        /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "wfi";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -92,9 +89,9 @@
 
 		qcom,lpm-level@1 {
 			reg = <0x1>;
-			qcom,mode = <2>;        /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
+			qcom,mode = "standalone_pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_active";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -109,9 +106,9 @@
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <1>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_gdhs";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -126,9 +123,9 @@
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <0>;          /* GDHS */
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
@@ -143,9 +140,9 @@
 
 		qcom,lpm-level@4 {
 			reg = <0x4>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -159,9 +156,9 @@
 
 		qcom,lpm-level@5 {
 			reg = <0x5>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -175,9 +172,9 @@
 
 		qcom,lpm-level@6 {
 			reg = <0x6>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
+			qcom,mode = "pc";
+			qcom,xo = "xo_off";
+			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
 			qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
 			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
@@ -191,7 +188,7 @@
 
 	qcom,pm-boot {
 		compatible = "qcom,pm-boot";
-		qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+		qcom,mode = "tz";
 	};
 
 	qcom,mpm@fc4281d0 {
@@ -277,7 +274,7 @@
 
 	qcom,pm-8x60 {
 		compatible = "qcom,pm-8x60";
-		qcom,pc-mode = <2>; /*MSM_PC_TZ_L2_EXT */
+		qcom,pc-mode = "tz_l2_ext";
 		qcom,use-sync-timer;
 	};
 
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index b163a5d..216fe99 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -105,6 +105,74 @@
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
 CONFIG_BRIDGE_NF_EBTABLES=y
 CONFIG_BRIDGE_EBT_BROUTE=y
 CONFIG_BRIDGE=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index ea10007..224df83 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -474,3 +474,4 @@
 CONFIG_PM_WAKELOCKS_LIMIT=0
 CONFIG_PM_AUTOSLEEP=y
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 077c7a6..e42aa77 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -499,3 +499,4 @@
 CONFIG_PM_WAKELOCKS_LIMIT=0
 CONFIG_PM_AUTOSLEEP=y
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index f525eee..6e8fe3e 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -323,7 +323,6 @@
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
 CONFIG_PM_AUTOSLEEP=y
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index f3a7b5c..9a32239 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -324,7 +324,6 @@
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
 CONFIG_PM_AUTOSLEEP=y
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index dfcdb9f..c355aeb 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -110,6 +110,7 @@
 	unsigned long reboot_code_buffer_phys;
 	void *reboot_code_buffer;
 
+	arch_kexec();
 
 	page_list = image->head & PAGE_MASK;
 
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index c8bdb5d..48abd35 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2388,12 +2388,6 @@
 	}
 }
 
-static void __init fsm8064_ep_pcie_init(void)
-{
-	msm_device_pcie.dev.platform_data = &ep_pcie_platform_data;
-	platform_device_register(&msm_device_pcie);
-}
-
 static struct platform_device mpq8064_device_ext_3p3v_vreg = {
 	.name			= "reg-fixed-voltage",
 	.dev			= {
@@ -2401,6 +2395,12 @@
 	},
 };
 
+static void __init fsm8064_ep_pcie_init(void)
+{
+	msm_device_pcie.dev.platform_data = &ep_pcie_platform_data;
+	platform_device_register(&msm_device_pcie);
+}
+
 static struct platform_device apq8064_device_ext_5v_vreg __devinitdata = {
 	.name	= GPIO_REGULATOR_DEV_NAME,
 	.id	= PM8921_MPP_PM_TO_SYS(7),
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index b4f202d..2723e20 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -36,6 +36,7 @@
 #ifdef CONFIG_ION_MSM
 #include <mach/ion.h>
 #endif
+#include <linux/regulator/qpnp-regulator.h>
 #include <mach/msm_memtypes.h>
 #include <mach/socinfo.h>
 #include <mach/board.h>
@@ -96,6 +97,7 @@
 	msm_rpm_driver_init();
 	msm_lpmrs_module_init();
 	msm_spm_device_init();
+	qpnp_regulator_init();
 	msm_thermal_device_init();
 
 	if (machine_is_msm8610_rumi())
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index d8a9c3e..688c6f7 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -203,7 +203,6 @@
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
-	.dir = GPIOMUX_OUT_LOW,
 };
 
 static struct gpiomux_setting hsic_act_cfg = {
@@ -219,6 +218,19 @@
 	.dir = GPIOMUX_IN,
 };
 
+static struct gpiomux_setting hsic_resume_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting hsic_resume_susp_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct msm_gpiomux_config msm_hsic_configs[] = {
 	{
 		.gpio = 144,               /*HSIC_STROBE */
@@ -234,6 +246,13 @@
 			[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
 		},
 	},
+	{
+		.gpio = 80,
+		.settings = {
+			[GPIOMUX_ACTIVE] = &hsic_resume_act_cfg,
+			[GPIOMUX_SUSPENDED] = &hsic_resume_susp_cfg,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_hsic_hub_configs[] = {
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 46af77d..d02ab66 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -32,6 +32,17 @@
 
 #include "acpuclock.h"
 
+struct cpufreq_work_struct {
+	struct work_struct work;
+	struct cpufreq_policy *policy;
+	struct completion complete;
+	int frequency;
+	int status;
+};
+
+static DEFINE_PER_CPU(struct cpufreq_work_struct, cpufreq_work);
+static struct workqueue_struct *msm_cpufreq_wq;
+
 struct cpufreq_suspend_t {
 	struct mutex suspend_mutex;
 	int device_suspended;
@@ -99,6 +110,15 @@
 	return ret;
 }
 
+static void set_cpu_work(struct work_struct *work)
+{
+	struct cpufreq_work_struct *cpu_work =
+		container_of(work, struct cpufreq_work_struct, work);
+
+	cpu_work->status = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
+	complete(&cpu_work->complete);
+}
+
 static int msm_cpufreq_target(struct cpufreq_policy *policy,
 				unsigned int target_freq,
 				unsigned int relation)
@@ -107,11 +127,17 @@
 	int index;
 	struct cpufreq_frequency_table *table;
 
+	struct cpufreq_work_struct *cpu_work = NULL;
+	cpumask_var_t mask;
+
 	if (!cpu_active(policy->cpu)) {
 		pr_info("cpufreq: cpu %d is not active.\n", policy->cpu);
 		return -ENODEV;
 	}
 
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+
 	mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 
 	if (per_cpu(cpufreq_suspend, policy->cpu).device_suspended) {
@@ -133,9 +159,27 @@
 		policy->cpu, target_freq, relation,
 		policy->min, policy->max, table[index].frequency);
 
-	ret = set_cpu_freq(policy, table[index].frequency);
+	cpu_work = &per_cpu(cpufreq_work, policy->cpu);
+	cpu_work->policy = policy;
+	cpu_work->frequency = table[index].frequency;
+	cpu_work->status = -ENODEV;
+
+	cpumask_clear(mask);
+	cpumask_set_cpu(policy->cpu, mask);
+	if (cpumask_equal(mask, &current->cpus_allowed)) {
+		ret = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
+		goto done;
+	} else {
+		cancel_work_sync(&cpu_work->work);
+		INIT_COMPLETION(cpu_work->complete);
+		queue_work_on(policy->cpu, msm_cpufreq_wq, &cpu_work->work);
+		wait_for_completion(&cpu_work->complete);
+	}
+
+	ret = cpu_work->status;
 
 done:
+	free_cpumask_var(mask);
 	mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 	return ret;
 }
@@ -218,6 +262,7 @@
 	int cur_freq;
 	int index;
 	struct cpufreq_frequency_table *table;
+	struct cpufreq_work_struct *cpu_work = NULL;
 
 	table = cpufreq_frequency_get_table(policy->cpu);
 	if (table == NULL)
@@ -247,7 +292,7 @@
 	    CPUFREQ_RELATION_H, &index) &&
 	    cpufreq_frequency_table_target(policy, table, cur_freq,
 	    CPUFREQ_RELATION_L, &index)) {
-		pr_info("%s: cpu%d at invalid freq: %d\n", __func__,
+		pr_info("cpufreq: cpu%d at invalid freq: %d\n",
 				policy->cpu, cur_freq);
 		return -EINVAL;
 	}
@@ -268,6 +313,10 @@
 	policy->cpuinfo.transition_latency =
 		acpuclk_get_switch_time() * NSEC_PER_USEC;
 
+	cpu_work = &per_cpu(cpufreq_work, policy->cpu);
+	INIT_WORK(&cpu_work->work, set_cpu_work);
+	init_completion(&cpu_work->complete);
+
 	return 0;
 }
 
@@ -355,6 +404,7 @@
 		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
 	}
 
+	msm_cpufreq_wq = create_workqueue("msm-cpufreq");
 	register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
 
 	return cpufreq_register_driver(&msm_cpufreq_driver);
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index a104a42..d908a65 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -94,7 +94,7 @@
 
 extern int msm_iommu_map_extra(struct iommu_domain *domain,
 						unsigned long start_iova,
-						unsigned long phys_addr,
+						phys_addr_t phys_addr,
 						unsigned long size,
 						unsigned long page_size,
 						int cached);
@@ -104,7 +104,7 @@
 						unsigned long size,
 						unsigned long page_size);
 
-extern int msm_iommu_map_contig_buffer(unsigned long phys,
+extern int msm_iommu_map_contig_buffer(phys_addr_t phys,
 				unsigned int domain_no,
 				unsigned int partition_no,
 				unsigned long size,
@@ -148,7 +148,7 @@
 
 static inline int msm_iommu_map_extra(struct iommu_domain *domain,
 						unsigned long start_iova,
-						unsigned long phys_addr,
+						phys_addr_t phys_addr,
 						unsigned long size,
 						unsigned long page_size,
 						int cached)
@@ -163,7 +163,7 @@
 {
 }
 
-static inline int msm_iommu_map_contig_buffer(unsigned long phys,
+static inline int msm_iommu_map_contig_buffer(phys_addr_t phys,
 				unsigned int domain_no,
 				unsigned int partition_no,
 				unsigned long size,
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index f24dc87..5228abc 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -55,7 +55,7 @@
 
 int msm_iommu_map_extra(struct iommu_domain *domain,
 				unsigned long start_iova,
-				unsigned long phy_addr,
+				phys_addr_t phy_addr,
 				unsigned long size,
 				unsigned long page_size,
 				int prot)
@@ -135,7 +135,7 @@
 
 static int msm_iommu_map_iova_phys(struct iommu_domain *domain,
 				unsigned long iova,
-				unsigned long phys,
+				phys_addr_t phys,
 				unsigned long size,
 				int cached)
 {
@@ -167,7 +167,7 @@
 
 }
 
-int msm_iommu_map_contig_buffer(unsigned long phys,
+int msm_iommu_map_contig_buffer(phys_addr_t phys,
 				unsigned int domain_no,
 				unsigned int partition_no,
 				unsigned long size,
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 8fe69d9..953f941d 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -28,6 +28,7 @@
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/krait-regulator.h>
 #include <linux/debugfs.h>
+#include <linux/syscore_ops.h>
 #include <mach/msm_iomap.h>
 
 #include "spm.h"
@@ -292,27 +293,6 @@
 	return 0;
 }
 
-int krait_power_mdd_enable(int cpu_num, bool on)
-{
-	/*
-	 * Expected to be called when the cpu goes to retention mode as a part
-	 * of idle power collapse. IT is guaranteed that cpu won't be put in
-	 * retention while being hotplugged out
-	 */
-	struct krait_power_vreg *kvreg = per_cpu(krait_vregs, cpu_num);
-
-	if (!on && kvreg->mode == LDO_MODE) {
-		pr_debug("%s using LDO - cannot turn off MDD\n", kvreg->name);
-		return -EINVAL;
-	}
-
-	if (on && kvreg->mode == LDO_MODE)
-		return 0;
-
-	__krait_power_mdd_enable(kvreg, on);
-	return 0;
-}
-
 static int switch_to_using_hs(struct krait_power_vreg *kvreg)
 {
 	if (kvreg->mode == HS_MODE)
@@ -342,8 +322,6 @@
 	krait_masked_write(kvreg, APC_PWR_GATE_CTL,
 				LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
 
-	/* turn off MDD since LDO is not used */
-	__krait_power_mdd_enable(kvreg, false);
 	kvreg->mode = HS_MODE;
 	pr_debug("%s using BHS\n", kvreg->name);
 	return 0;
@@ -362,9 +340,6 @@
 	if (kvreg->mode == LDO_MODE)
 		switch_to_using_hs(kvreg);
 
-	/* turn on MDD since LDO is being turned on */
-	__krait_power_mdd_enable(kvreg, true);
-
 	set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
 
 	/*
@@ -792,8 +767,7 @@
 	int rc;
 
 	mutex_lock(&pvreg->krait_power_vregs_lock);
-	if (kvreg->mode == LDO_MODE)
-		__krait_power_mdd_enable(kvreg, true);
+	__krait_power_mdd_enable(kvreg, true);
 	kvreg->online = true;
 	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
 	if (rc < 0)
@@ -823,8 +797,7 @@
 		goto dis_err;
 
 	rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
-	if (kvreg->mode == LDO_MODE)
-		__krait_power_mdd_enable(kvreg, false);
+	__krait_power_mdd_enable(kvreg, false);
 dis_err:
 	mutex_unlock(&pvreg->krait_power_vregs_lock);
 	return rc;
@@ -889,6 +862,8 @@
 
 	/* setup the bandgap that configures the reference to the LDO */
 	writel_relaxed(0x00000190, kvreg->mdd_base + MDD_CONFIG_CTL);
+	/* Enable MDD */
+	writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
 	mb();
 }
 
@@ -1112,6 +1087,26 @@
 	{}
 };
 
+static int boot_cpu_mdd_off(void)
+{
+	struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
+
+	__krait_power_mdd_enable(kvreg, false);
+	return 0;
+}
+
+static void boot_cpu_mdd_on(void)
+{
+	struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
+
+	__krait_power_mdd_enable(kvreg, true);
+}
+
+static struct syscore_ops boot_cpu_mdd_ops = {
+	.suspend	= boot_cpu_mdd_off,
+	.resume		= boot_cpu_mdd_on,
+};
+
 static int __devinit krait_pdn_probe(struct platform_device *pdev)
 {
 	int rc;
@@ -1172,6 +1167,7 @@
 	dent = debugfs_create_dir(KRAIT_REGULATOR_DRIVER_NAME, NULL);
 	debugfs_create_file("retention_uV",
 			0644, dent, the_gang, &retention_fops);
+	register_syscore_ops(&boot_cpu_mdd_ops);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 8194721..aa33f2c 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -28,6 +28,8 @@
 	MSM_LPM_LVL_DBG_IDLE_LIMITS = BIT(1),
 };
 
+#define MAX_STR_LEN 30
+
 static int msm_lpm_lvl_dbg_msk;
 
 module_param_named(
@@ -41,6 +43,48 @@
 static DEFINE_PER_CPU(int , lpm_permitted_level);
 static DEFINE_PER_CPU(struct atomic_notifier_head, lpm_notify_head);
 
+static int msm_pm_get_sleep_mode_value(struct device_node *node,
+			const char *key, uint32_t *sleep_mode_val)
+{
+	int i;
+	struct lpm_lookup_table {
+		uint32_t modes;
+		const char *mode_name;
+	};
+	struct lpm_lookup_table pm_sm_lookup[] = {
+		{MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
+			"wfi"},
+		{MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT,
+			"ramp_down_and_wfi"},
+		{MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
+			"standalone_pc"},
+		{MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+			"pc"},
+		{MSM_PM_SLEEP_MODE_RETENTION,
+			"retention"},
+		{MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND,
+			"pc_suspend"},
+		{MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN,
+			"pc_no_xo_shutdown"}
+	};
+	int ret;
+	const char *mode_name;
+
+	ret = of_property_read_string(node, key, &mode_name);
+	if (!ret) {
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(pm_sm_lookup); i++) {
+			if (!strncmp(mode_name, pm_sm_lookup[i].mode_name,
+				MAX_STR_LEN)) {
+				*sleep_mode_val = pm_sm_lookup[i].modes;
+				ret = 0;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
 static void msm_lpm_level_update(void)
 {
 	unsigned int lpm_level;
@@ -343,19 +387,19 @@
 		level->available = false;
 
 		key = "qcom,mode";
-		ret = of_property_read_u32(node, key, &val);
+		ret = msm_pm_get_sleep_mode_value(node, key, &val);
 		if (ret)
 			goto fail;
 		level->sleep_mode = val;
 
 		key = "qcom,xo";
-		ret = of_property_read_u32(node, key, &val);
+		ret = msm_lpm_get_xo_value(node, key, &val);
 		if (ret)
 			goto fail;
 		level->rs_limits.pxo = val;
 
 		key = "qcom,l2";
-		ret = of_property_read_u32(node, key, &val);
+		ret = msm_lpm_get_l2_cache_value(node, key, &val);
 		if (ret)
 			goto fail;
 		level->rs_limits.l2_cache = val;
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 60184b4..f0e5ebd 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -51,29 +51,39 @@
 #define MAX_RS_SIZE		(4)
 #define IS_RPM_CTL(rs) \
 	(!strncmp(rs->name, "rpm_ctl", MAX_RS_NAME))
+#define MAX_STR_LEN		30
 
 static bool msm_lpm_beyond_limits_vdd_dig(struct msm_rpmrs_limits *limits);
 static void msm_lpm_aggregate_vdd_dig(struct msm_rpmrs_limits *limits);
 static void msm_lpm_flush_vdd_dig(int notify_rpm);
 static void msm_lpm_notify_vdd_dig(struct msm_rpm_notifier_data
 					*rpm_notifier_cb);
+static int msm_lpm_init_value_vdd_dig(struct device_node *node,
+					char *key, uint32_t *default_value);
 
 static bool msm_lpm_beyond_limits_vdd_mem(struct msm_rpmrs_limits *limits);
 static void msm_lpm_aggregate_vdd_mem(struct msm_rpmrs_limits *limits);
 static void msm_lpm_flush_vdd_mem(int notify_rpm);
 static void msm_lpm_notify_vdd_mem(struct msm_rpm_notifier_data
 					*rpm_notifier_cb);
+static int msm_lpm_init_value_vdd_mem(struct device_node *node,
+					char *key, uint32_t *default_value);
+
 
 static bool msm_lpm_beyond_limits_pxo(struct msm_rpmrs_limits *limits);
 static void msm_lpm_aggregate_pxo(struct msm_rpmrs_limits *limits);
 static void msm_lpm_flush_pxo(int notify_rpm);
 static void msm_lpm_notify_pxo(struct msm_rpm_notifier_data
 					*rpm_notifier_cb);
+static int msm_lpm_init_value_pxo(struct device_node *node,
+				char *key, uint32_t *default_value);
 
 
 static bool msm_lpm_beyond_limits_l2(struct msm_rpmrs_limits *limits);
 static void msm_lpm_flush_l2(int notify_rpm);
 static void msm_lpm_aggregate_l2(struct msm_rpmrs_limits *limits);
+static int msm_lpm_init_value_l2(struct device_node *node,
+				char *key, uint32_t *default_value);
 
 static void msm_lpm_flush_rpm_ctl(int notify_rpm);
 
@@ -127,8 +137,14 @@
 	void (*flush)(int notify_rpm);
 	void (*notify)(struct msm_rpm_notifier_data *rpm_notifier_cb);
 	struct kobj_attribute ko_attr;
+	int (*init_value)(struct device_node *node,
+			char *key, uint32_t *default_value);
 };
 
+struct lpm_lookup_table {
+	uint32_t modes;
+	const char *mode_name;
+};
 
 static struct msm_lpm_resource msm_lpm_l2 = {
 	.name = "l2",
@@ -138,6 +154,7 @@
 	.notify = NULL,
 	.valid = false,
 	.ko_attr = RPMRS_ATTR(l2),
+	.init_value = msm_lpm_init_value_l2,
 };
 
 static struct msm_lpm_resource msm_lpm_vdd_dig = {
@@ -148,6 +165,7 @@
 	.notify = msm_lpm_notify_vdd_dig,
 	.valid = false,
 	.ko_attr = RPMRS_ATTR(vdd_dig),
+	.init_value = msm_lpm_init_value_vdd_dig,
 };
 
 static struct msm_lpm_resource msm_lpm_vdd_mem = {
@@ -158,6 +176,7 @@
 	.notify = msm_lpm_notify_vdd_mem,
 	.valid = false,
 	.ko_attr = RPMRS_ATTR(vdd_mem),
+	.init_value = msm_lpm_init_value_vdd_mem,
 };
 
 static struct msm_lpm_resource msm_lpm_pxo = {
@@ -168,6 +187,7 @@
 	.notify = msm_lpm_notify_pxo,
 	.valid = false,
 	.ko_attr = RPMRS_ATTR(pxo),
+	.init_value = msm_lpm_init_value_pxo,
 };
 
 static struct msm_lpm_resource *msm_lpm_resources[] = {
@@ -444,6 +464,12 @@
 				__func__, lpm);
 }
 
+static int msm_lpm_init_value_l2(struct device_node *node,
+					char *key, uint32_t *default_value)
+{
+	return msm_lpm_get_l2_cache_value(node, key, default_value);
+}
+
 static void msm_lpm_flush_l2(int notify_rpm)
 {
 	struct msm_lpm_resource *rs = &msm_lpm_l2;
@@ -451,6 +477,34 @@
 	msm_lpm_set_l2_mode(rs->sleep_value, notify_rpm);
 }
 
+int msm_lpm_get_l2_cache_value(struct device_node *node,
+			char *key, uint32_t *l2_val)
+{
+	int i;
+	struct lpm_lookup_table l2_mode_lookup[] = {
+		{MSM_LPM_L2_CACHE_HSFS_OPEN, "l2_cache_pc"},
+		{MSM_LPM_L2_CACHE_GDHS, "l2_cache_gdhs"},
+		{MSM_LPM_L2_CACHE_RETENTION, "l2_cache_retention"},
+		{MSM_LPM_L2_CACHE_ACTIVE, "l2_cache_active"}
+	};
+	const char *l2_str;
+	int ret;
+
+	ret = of_property_read_string(node, key, &l2_str);
+	if (!ret) {
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(l2_mode_lookup); i++) {
+			if (!strncmp(l2_str, l2_mode_lookup[i].mode_name,
+				MAX_STR_LEN)) {
+				*l2_val = l2_mode_lookup[i].modes;
+				ret = 0;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
 /* RPM CTL */
 static void msm_lpm_flush_rpm_ctl(int notify_rpm)
 {
@@ -484,6 +538,12 @@
 	return ret;
 }
 
+static int msm_lpm_init_value_vdd_dig(struct device_node *node,
+					char *key, uint32_t *default_value)
+{
+	return of_property_read_u32(node, key, default_value);
+}
+
 static void msm_lpm_aggregate_vdd_dig(struct msm_rpmrs_limits *limits)
 {
 	struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
@@ -570,6 +630,12 @@
 	msm_lpm_notify_common(rpm_notifier_cb, rs);
 }
 
+static int msm_lpm_init_value_vdd_mem(struct device_node *node,
+					char *key, uint32_t *default_value)
+{
+	return of_property_read_u32(node, key, default_value);
+}
+
 /*PXO*/
 static bool msm_lpm_beyond_limits_pxo(struct msm_rpmrs_limits *limits)
 {
@@ -628,11 +694,43 @@
 	msm_lpm_notify_common(rpm_notifier_cb, rs);
 }
 
+static int msm_lpm_init_value_pxo(struct device_node *node,
+				char *key, uint32_t *default_value)
+{
+	return msm_lpm_get_xo_value(node, key, default_value);
+}
+
 static inline bool msm_lpm_use_mpm(struct msm_rpmrs_limits *limits)
 {
 	return (limits->pxo == MSM_LPM_PXO_OFF);
 }
 
+int msm_lpm_get_xo_value(struct device_node *node,
+			char *key, uint32_t *xo_val)
+{
+	int  i;
+	struct lpm_lookup_table pxo_mode_lookup[] = {
+		{MSM_LPM_PXO_OFF, "xo_off"},
+		{MSM_LPM_PXO_ON, "xo_on"}
+	};
+	const char *xo_str;
+	int ret;
+
+	ret = of_property_read_string(node, key, &xo_str);
+	if (!ret) {
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(pxo_mode_lookup); i++) {
+			if (!strncmp(xo_str, pxo_mode_lookup[i].mode_name,
+				MAX_STR_LEN)) {
+				*xo_val = pxo_mode_lookup[i].modes;
+				ret = 0;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
 /* LPM levels interface */
 bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits)
 {
@@ -797,7 +895,7 @@
 		struct msm_lpm_resource *rs = NULL;
 		const char *val;
 		int i;
-		uint32_t resource_type;
+		bool local_resource;
 
 		key = "qcom,name";
 		ret = of_property_read_string(node, key, &val);
@@ -822,8 +920,7 @@
 		}
 
 		key = "qcom,init-value";
-		ret = of_property_read_u32(node, key,
-				&rs->rs_data.default_value);
+		ret = rs->init_value(node, key, &rs->rs_data.default_value);
 		if (ret) {
 			pr_err("%s():Failed to read %s\n", __func__, key);
 			goto fail;
@@ -831,18 +928,13 @@
 
 		rs->rs_data.value = rs->rs_data.default_value;
 
-		key = "qcom,resource-type";
-		ret = of_property_read_u32(node, key, &resource_type);
-		if (ret) {
-			pr_err("Failed to read resource-type\n");
-			goto fail;
-		}
+		key = "qcom,local-resource-type";
+		local_resource = of_property_read_bool(node, key);
 
-		switch (resource_type) {
-		case MSM_LPM_RPM_RS_TYPE:
+		if (!local_resource) {
 			key = "qcom,type";
 			ret = of_property_read_u32(node, key,
-						&rs->rs_data.type);
+					&rs->rs_data.type);
 			if (ret) {
 				pr_err("Failed to read type\n");
 				goto fail;
@@ -873,15 +965,9 @@
 				goto fail;
 			}
 			/* fall through */
-
-		case MSM_LPM_LOCAL_RS_TYPE:
-			rs->valid = true;
-			break;
-		default:
-			pr_err("%s: Invalid resource type %d", __func__,
-					resource_type);
-			goto fail;
 		}
+
+		rs->valid = true;
 	}
 	msm_rpm_register_notifier(&msm_lpm_rpm_nblk);
 	msm_lpm_init_rpm_ctl();
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
index 1a2d72d..105cfe6 100644
--- a/arch/arm/mach-msm/lpm_resources.h
+++ b/arch/arm/mach-msm/lpm_resources.h
@@ -17,15 +17,15 @@
 #include "test-lpm.h"
 
 enum {
-	MSM_LPM_PXO_OFF = 0,
-	MSM_LPM_PXO_ON = 1,
+	MSM_LPM_PXO_OFF,
+	MSM_LPM_PXO_ON
 };
 
 enum {
-	MSM_LPM_L2_CACHE_HSFS_OPEN = 0,
-	MSM_LPM_L2_CACHE_GDHS = 1,
-	MSM_LPM_L2_CACHE_RETENTION = 2,
-	MSM_LPM_L2_CACHE_ACTIVE = 3,
+	MSM_LPM_L2_CACHE_HSFS_OPEN,
+	MSM_LPM_L2_CACHE_GDHS,
+	MSM_LPM_L2_CACHE_RETENTION,
+	MSM_LPM_L2_CACHE_ACTIVE,
 };
 
 struct msm_rpmrs_limits {
@@ -99,6 +99,24 @@
 uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits);
 
 /**
+ * msm_lpm_get_xo_value() - get the enum value for xo
+ * @node		pointer to the device node
+ * @key			pxo property key
+ * @xo_val		xo enum value
+ */
+int msm_lpm_get_xo_value(struct device_node *node,
+			char *key, uint32_t *xo_val);
+
+/**
+ * msm_lpm_get_l2_cache_value() - get the enum value for l2 cache
+ * @node                pointer to the device node
+ * @key                 l2 cache property key
+ * @l2_val              l2 mode enum value
+ */
+int msm_lpm_get_l2_cache_value(struct device_node *node,
+				char *key, uint32_t *l2_val);
+
+/**
  * struct msm_lpm_sleep_data - abstraction to get sleep data
  * @limits:	pointer to the msm_rpmrs_limits structure
  * @kernel_sleep:	kernel sleep time as decided by the power calculation
diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c
index d1538dd..1589623 100644
--- a/arch/arm/mach-msm/msm_rq_stats.c
+++ b/arch/arm/mach-msm/msm_rq_stats.c
@@ -31,6 +31,7 @@
 #include <linux/tick.h>
 #include <asm/smp_plat.h>
 #include "acpuclock.h"
+#include <linux/suspend.h>
 
 #define MAX_LONG_SIZE 24
 #define DEFAULT_RQ_POLL_JIFFIES 1
@@ -206,6 +207,34 @@
 	return NOTIFY_OK;
 }
 
+static int system_suspend_handler(struct notifier_block *nb,
+				unsigned long val, void *data)
+{
+	switch (val) {
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		rq_info.hotplug_disabled = 0;
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		rq_info.hotplug_disabled = 1;
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+	return NOTIFY_OK;
+}
+
+
+static ssize_t hotplug_disable_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	unsigned int val = 0;
+	val = rq_info.hotplug_disabled;
+	return snprintf(buf, MAX_LONG_SIZE, "%d\n", val);
+}
+
+static struct kobj_attribute hotplug_disabled_attr = __ATTR_RO(hotplug_disable);
+
 static void def_work_fn(struct work_struct *work)
 {
 	int64_t diff;
@@ -310,6 +339,7 @@
 	&def_timer_ms_attr.attr,
 	&run_queue_avg_attr.attr,
 	&run_queue_poll_ms_attr.attr,
+	&hotplug_disabled_attr.attr,
 	NULL,
 };
 
@@ -358,6 +388,7 @@
 	rq_info.def_timer_jiffies = DEFAULT_DEF_TIMER_JIFFIES;
 	rq_info.rq_poll_last_jiffy = 0;
 	rq_info.def_timer_last_jiffy = 0;
+	rq_info.hotplug_disabled = 0;
 	ret = init_rq_attribs();
 
 	rq_info.init = 1;
@@ -380,3 +411,16 @@
 	return ret;
 }
 late_initcall(msm_rq_stats_init);
+
+static int __init msm_rq_stats_early_init(void)
+{
+	/* Bail out if this is not an SMP Target */
+	if (!is_smp()) {
+		rq_info.init = 0;
+		return -ENOSYS;
+	}
+
+	pm_notifier(system_suspend_handler, 0);
+	return 0;
+}
+core_initcall(msm_rq_stats_early_init);
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index fc9a0fa..958edaf 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -208,16 +208,24 @@
 	return ret;
 }
 
-static void pil_proxy_unvote(struct pil_desc *desc, unsigned long timeout)
+static void pil_proxy_unvote(struct pil_desc *desc, int immediate)
 {
 	struct pil_priv *priv = desc->priv;
+	unsigned long timeout;
 
-	if (proxy_timeout_ms >= 0)
+	if (proxy_timeout_ms == 0 && !immediate)
+		return;
+	else if (proxy_timeout_ms > 0)
 		timeout = proxy_timeout_ms;
+	else
+		timeout = desc->proxy_timeout;
 
-	if (timeout && desc->ops->proxy_unvote) {
+	if (desc->ops->proxy_unvote) {
 		if (WARN_ON(!try_module_get(desc->owner)))
 			return;
+
+		if (immediate)
+			timeout = 0;
 		schedule_delayed_work(&priv->proxy, msecs_to_jiffies(timeout));
 	}
 }
@@ -558,7 +566,6 @@
 	const struct elf32_hdr *ehdr;
 	struct pil_seg *seg;
 	const struct firmware *fw;
-	unsigned long proxy_timeout = desc->proxy_timeout;
 	struct pil_priv *priv = desc->priv;
 
 	/* Reinitialize for new image */
@@ -633,12 +640,11 @@
 	ret = desc->ops->auth_and_reset(desc);
 	if (ret) {
 		pil_err(desc, "Failed to bring out of reset\n");
-		proxy_timeout = 0; /* Remove proxy vote immediately on error */
 		goto err_boot;
 	}
 	pil_info(desc, "Brought out of reset\n");
 err_boot:
-	pil_proxy_unvote(desc, proxy_timeout);
+	pil_proxy_unvote(desc, ret);
 release_fw:
 	release_firmware(fw);
 out:
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index b52d284..7fbbf2c 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -128,6 +128,40 @@
 static uint32_t msm_pm_max_sleep_time;
 static bool msm_no_ramp_down_pc;
 
+static int msm_pm_get_pc_mode(struct device_node *node,
+		const char *key, uint32_t *pc_mode_val)
+{
+	struct pc_mode_of {
+		uint32_t mode;
+		char *mode_name;
+	};
+	int i;
+	struct pc_mode_of pc_modes[] = {
+				{MSM_PM_PC_TZ_L2_INT, "tz_l2_int"},
+				{MSM_PM_PC_NOTZ_L2_EXT, "no_tz_l2_ext"},
+				{MSM_PM_PC_TZ_L2_EXT , "tz_l2_ext"} };
+	int ret;
+	const char *pc_mode_str;
+
+	ret = of_property_read_string(node, key, &pc_mode_str);
+	if (ret) {
+		pr_debug("%s: Cannot read %s,defaulting to 0", __func__, key);
+		pc_mode_val = MSM_PM_PC_TZ_L2_INT;
+		ret = 0;
+	} else {
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(pc_modes); i++) {
+			if (!strncmp(pc_mode_str, pc_modes[i].mode_name,
+				strlen(pc_modes[i].mode_name))) {
+				*pc_mode_val = pc_modes[i].mode;
+				ret = 0;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
 /*
  * Write out the attribute.
  */
@@ -360,12 +394,10 @@
 
 	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
 	WARN_ON(ret);
-	krait_power_mdd_enable(smp_processor_id(), false);
 }
 
 static void msm_pm_config_hw_before_retention(void)
 {
-	krait_power_mdd_enable(smp_processor_id(), true);
 	return;
 }
 
@@ -619,7 +651,7 @@
 	int64_t time = 0;
 
 	if (msm_pm_use_sync_timer)
-		return ktime_to_ns(ktime_get());
+		return sched_clock();
 
 	time = msm_timer_get_sclk_time(period);
 	if (!time)
@@ -631,7 +663,7 @@
 static int64_t msm_pm_timer_exit_suspend(int64_t time, int64_t period)
 {
 	if (msm_pm_use_sync_timer)
-		return ktime_to_ns(ktime_get()) - time;
+		return sched_clock() - time;
 
 	if (time != 0) {
 		int64_t end_time = msm_timer_get_sclk_time(NULL);
@@ -1257,7 +1289,6 @@
 {
 	char *key = NULL;
 	struct dentry *dent = NULL;
-	uint32_t val = 0;
 	struct resource *res = NULL;
 	int i ;
 	struct msm_pm_init_data_type pdata_local;
@@ -1299,14 +1330,14 @@
 
 	} else {
 		key = "qcom,pc-mode";
-		ret = of_property_read_u32(pdev->dev.of_node, key, &val);
+		ret = msm_pm_get_pc_mode(pdev->dev.of_node,
+				key,
+				&pdata_local.pc_mode);
 		if (ret) {
-			pr_debug("%s: Cannot read %s,defaulting to 0",
+			pr_debug("%s: Error reading key %s",
 					__func__, key);
-			val = MSM_PM_PC_TZ_L2_INT;
-			ret = 0;
+			return -EINVAL;
 		}
-		pdata_local.pc_mode = val;
 
 		key = "qcom,use-sync-timer";
 		pdata_local.use_sync_timer =
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index c77b19c..3559510 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,42 @@
 static void (*msm_pm_boot_before_pc)(unsigned int cpu, unsigned long entry);
 static void (*msm_pm_boot_after_pc)(unsigned int cpu);
 
+
+static int msm_pm_get_boot_config_mode(struct device_node *dev,
+		const char *key, uint32_t *boot_config_mode)
+{
+	struct pm_lookup_table {
+		uint32_t boot_config_mode;
+		const char *boot_config_name;
+	};
+	const char *boot_config_str;
+	struct pm_lookup_table boot_config_lookup[] = {
+		{MSM_PM_BOOT_CONFIG_TZ, "tz"},
+		{MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS, "reset_vector_phys"},
+		{MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT, "reset_vector_virt"},
+		{MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR, "remap_boot_addr"}
+	};
+	int ret;
+	int i;
+
+	ret = of_property_read_string(dev, key, &boot_config_str);
+	if (!ret) {
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(boot_config_lookup); i++) {
+			if (!strncmp(boot_config_str,
+				boot_config_lookup[i].boot_config_name,
+				strlen(boot_config_lookup[i].boot_config_name))
+			) {
+				*boot_config_mode =
+					boot_config_lookup[i].boot_config_mode;
+				ret = 0;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
 static void msm_pm_write_boot_vector(unsigned int cpu, unsigned long address)
 {
 	msm_pm_boot_vector[cpu] = address;
@@ -235,11 +271,9 @@
 	vaddr_val = 0;
 
 	key = "qcom,mode";
-	ret = of_property_read_u32(pdev->dev.of_node, key, &val);
-	if (ret) {
-		pr_err("Unable to read boot mode Err(%d).\n", ret);
-		return -ENODEV;
-	}
+	ret = msm_pm_get_boot_config_mode(pdev->dev.of_node, key, &val);
+	if (ret)
+		goto fail;
 	pdata.mode = val;
 
 	key = "qcom,phy-addr";
diff --git a/arch/arm/mach-msm/pm-boot.h b/arch/arm/mach-msm/pm-boot.h
index 8ca3bb5..2d5110d 100644
--- a/arch/arm/mach-msm/pm-boot.h
+++ b/arch/arm/mach-msm/pm-boot.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,10 +18,10 @@
 /* end */
 
 enum {
-	MSM_PM_BOOT_CONFIG_TZ		     = 0,
-	MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS = 1,
-	MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT = 2,
-	MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR   = 3,
+	MSM_PM_BOOT_CONFIG_TZ		    ,
+	MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS,
+	MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT,
+	MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR  ,
 };
 
 struct msm_pm_boot_platform_data {
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index c77304d..793b778 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -95,11 +95,11 @@
 };
 
 enum msm_pm_pc_mode_type {
-	MSM_PM_PC_TZ_L2_INT = 0,   /*Power collapse terminates in TZ;
+	MSM_PM_PC_TZ_L2_INT,   /*Power collapse terminates in TZ;
 					integrated L2 cache controller */
-	MSM_PM_PC_NOTZ_L2_EXT = 1, /* Power collapse doesn't terminate in
+	MSM_PM_PC_NOTZ_L2_EXT, /* Power collapse doesn't terminate in
 					TZ; external L2 cache controller */
-	MSM_PM_PC_TZ_L2_EXT = 2,   /* Power collapse terminates in TZ;
+	MSM_PM_PC_TZ_L2_EXT,   /* Power collapse terminates in TZ;
 					external L2 cache controller */
 };
 
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 2ec87b8..892b007 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -425,9 +425,9 @@
 		writel_relaxed(1, l2x0_base + L2X0_CTRL);
 	}
 
-		outer_cache.inv_range = l2x0_inv_range;
-		outer_cache.clean_range = l2x0_clean_range;
-		outer_cache.flush_range = l2x0_flush_range;
+	outer_cache.inv_range = l2x0_inv_range;
+	outer_cache.clean_range = l2x0_clean_range;
+	outer_cache.flush_range = l2x0_flush_range;
 	outer_cache.sync = l2x0_cache_sync;
 	outer_cache.flush_all = l2x0_flush_all;
 	outer_cache.inv_all = l2x0_inv_all;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 6ae5d03..6d28042 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -37,6 +37,7 @@
 unsigned char dci_cumulative_event_mask[DCI_EVENT_MASK_SIZE];
 struct mutex dci_log_mask_mutex;
 struct mutex dci_event_mask_mutex;
+struct mutex dci_health_mutex;
 
 #define DCI_CHK_CAPACITY(entry, new_data_len)				\
 ((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0)	\
@@ -211,6 +212,7 @@
 				entry = &(driver->dci_client_tbl[i]);
 				event_mask_ptr = entry->dci_event_mask +
 								 byte_index;
+				mutex_lock(&dci_health_mutex);
 				if (*event_mask_ptr & byte_mask) {
 					/* copy to client buffer */
 					if (DCI_CHK_CAPACITY(entry,
@@ -218,7 +220,9 @@
 						pr_err("diag: DCI event drop\n");
 						driver->dci_client_tbl[i].
 							dropped_events++;
-						return;
+						mutex_unlock(
+							&dci_health_mutex);
+						break;
 					}
 					driver->dci_client_tbl[i].
 							received_events++;
@@ -230,6 +234,7 @@
 						, total_event_len);
 					entry->data_len += 4 + total_event_len;
 				}
+				mutex_unlock(&dci_health_mutex);
 			}
 		}
 		temp_len += 2 + timestamp_len + payload_len_field + payload_len;
@@ -264,6 +269,7 @@
 			if (!log_mask_ptr)
 				return;
 			log_mask_ptr = log_mask_ptr + byte_offset;
+			mutex_lock(&dci_health_mutex);
 			if (*log_mask_ptr & byte_mask) {
 				pr_debug("\t log code %x needed by client %d",
 					 log_code, entry->client->tgid);
@@ -273,6 +279,8 @@
 						pr_err("diag: DCI log drop\n");
 						driver->dci_client_tbl[i].
 								dropped_logs++;
+						mutex_unlock(
+							&dci_health_mutex);
 						return;
 				}
 				driver->dci_client_tbl[i].received_logs++;
@@ -282,6 +290,7 @@
 					    buf + 4, *(uint16_t *)(buf + 2));
 				entry->data_len += 4 + *(uint16_t *)(buf + 2);
 			}
+			mutex_unlock(&dci_health_mutex);
 		}
 	}
 }
@@ -1028,6 +1037,8 @@
 	mutex_init(&driver->dci_mutex);
 	mutex_init(&dci_log_mask_mutex);
 	mutex_init(&dci_event_mask_mutex);
+	mutex_init(&dci_health_mutex);
+
 	for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
 		success = diag_smd_constructor(&driver->smd_dci[i],
 					i, SMD_DCI_TYPE);
@@ -1082,5 +1093,118 @@
 	kfree(driver->req_tracking_tbl);
 	kfree(driver->dci_client_tbl);
 	kfree(driver->apps_dci_buf);
+	mutex_destroy(&driver->dci_mutex);
+	mutex_destroy(&dci_log_mask_mutex);
+	mutex_destroy(&dci_event_mask_mutex);
+	mutex_destroy(&dci_health_mutex);
 	destroy_workqueue(driver->diag_dci_wq);
 }
+
+int diag_dci_clear_log_mask()
+{
+	int i, j, k, err = DIAG_DCI_NO_ERROR;
+	uint8_t *log_mask_ptr, *update_ptr;
+
+	i = diag_dci_find_client_index(current->tgid);
+	if (i == DCI_CLIENT_INDEX_INVALID)
+		return DIAG_DCI_TABLE_ERR;
+
+	mutex_lock(&dci_log_mask_mutex);
+	create_dci_log_mask_tbl(
+			driver->dci_client_tbl[i].dci_log_mask);
+	memset(dci_cumulative_log_mask,
+				0x0, DCI_LOG_MASK_SIZE);
+	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		update_ptr = dci_cumulative_log_mask;
+		if (driver->dci_client_tbl[i].client) {
+			log_mask_ptr =
+				driver->dci_client_tbl[i].dci_log_mask;
+			for (j = 0; j < 16; j++) {
+				*update_ptr = j;
+				*(update_ptr + 1) = 1;
+				update_ptr += 2;
+				log_mask_ptr += 2;
+				for (k = 0; k < 513; k++) {
+					*update_ptr |= *log_mask_ptr;
+					update_ptr++;
+					log_mask_ptr++;
+				}
+			}
+		}
+	}
+	mutex_unlock(&dci_log_mask_mutex);
+	err = diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
+	return err;
+}
+
+int diag_dci_clear_event_mask()
+{
+	int i, j, err = DIAG_DCI_NO_ERROR;
+	uint8_t *event_mask_ptr, *update_ptr;
+
+	i = diag_dci_find_client_index(current->tgid);
+	if (i == DCI_CLIENT_INDEX_INVALID)
+		return DIAG_DCI_TABLE_ERR;
+
+	mutex_lock(&dci_event_mask_mutex);
+	memset(driver->dci_client_tbl[i].dci_event_mask,
+			0x0, DCI_EVENT_MASK_SIZE);
+	memset(dci_cumulative_event_mask,
+			0x0, DCI_EVENT_MASK_SIZE);
+	update_ptr = dci_cumulative_event_mask;
+	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		event_mask_ptr =
+			driver->dci_client_tbl[i].dci_event_mask;
+		for (j = 0; j < DCI_EVENT_MASK_SIZE; j++)
+			*(update_ptr + j) |= *(event_mask_ptr + j);
+	}
+	mutex_unlock(&dci_event_mask_mutex);
+	err = diag_send_dci_event_mask(driver->smd_cntl[MODEM_DATA].ch);
+	return err;
+}
+
+int diag_dci_query_log_mask(uint16_t log_code)
+{
+	uint16_t item_num;
+	uint8_t equip_id, *log_mask_ptr, byte_mask;
+	int i, byte_index, offset;
+
+	equip_id = LOG_GET_EQUIP_ID(log_code);
+	item_num = LOG_GET_ITEM_NUM(log_code);
+	byte_index = item_num/8 + 2;
+	byte_mask = 0x01 << (item_num % 8);
+	offset = equip_id * 514;
+
+	i = diag_dci_find_client_index(current->tgid);
+	if (i != DCI_CLIENT_INDEX_INVALID) {
+		log_mask_ptr = driver->dci_client_tbl[i].dci_log_mask;
+		log_mask_ptr = log_mask_ptr + offset + byte_index;
+		return ((*log_mask_ptr & byte_mask) == byte_mask) ?
+								1 : 0;
+	}
+	return 0;
+}
+
+
+int diag_dci_query_event_mask(uint16_t event_id)
+{
+	uint8_t *event_mask_ptr, byte_mask;
+	int i, byte_index, bit_index;
+	byte_index = event_id/8;
+	bit_index = event_id % 8;
+	byte_mask = 0x1 << bit_index;
+
+	i = diag_dci_find_client_index(current->tgid);
+	if (i != DCI_CLIENT_INDEX_INVALID) {
+		event_mask_ptr =
+		driver->dci_client_tbl[i].dci_event_mask;
+		event_mask_ptr = event_mask_ptr + byte_index;
+		if ((*event_mask_ptr & byte_mask) == byte_mask)
+			return 1;
+		else
+			return 0;
+	}
+	return 0;
+}
+
+
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 9187516..260cdf3 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -37,6 +37,7 @@
 
 extern unsigned int dci_max_reg;
 extern unsigned int dci_max_clients;
+extern struct mutex dci_health_mutex;
 
 struct dci_pkt_req_tracking_tbl {
 	int pid;
@@ -68,6 +69,13 @@
 	int reset_status;
 };
 
+/* This is used for querying DCI Log
+   or Event Mask */
+struct diag_log_event_stats {
+	uint16_t code;
+	int is_set;
+};
+
 enum {
 	DIAG_DCI_NO_ERROR = 1001,	/* No error */
 	DIAG_DCI_NO_REG,		/* Could not register */
@@ -96,10 +104,14 @@
 void clear_client_dci_cumulative_log_mask(int client_index);
 int diag_send_dci_log_mask(smd_channel_t *ch);
 void extract_dci_log(unsigned char *buf);
+int diag_dci_clear_log_mask(void);
+int diag_dci_query_log_mask(uint16_t log_code);
 /* DCI event streaming functions */
 void update_dci_cumulative_event_mask(int offset, uint8_t byte_mask);
 void clear_client_dci_cumulative_event_mask(int client_index);
 int diag_send_dci_event_mask(smd_channel_t *ch);
 void extract_dci_events(unsigned char *buf);
 void create_dci_event_mask_tbl(unsigned char *tbl_buf);
+int diag_dci_clear_event_mask(void);
+int diag_dci_query_event_mask(uint16_t event_id);
 #endif
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index df28dab..532df09 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -30,7 +30,6 @@
 #define IN_BUF_SIZE		16384
 #define MAX_IN_BUF_SIZE	32768
 #define MAX_SYNC_OBJ_NAME_SIZE	32
-#define UINT32_MAX	UINT_MAX
 /* Size of the buffer used for deframing a packet
   reveived from the PC tool*/
 #define HDLC_MAX 4096
@@ -86,8 +85,8 @@
 #define SMD_DCI_TYPE 2
 
 /* Maximum number of pkt reg supported at initialization*/
-extern unsigned int diag_max_reg;
-extern unsigned int diag_threshold_reg;
+extern int diag_max_reg;
+extern int diag_threshold_reg;
 
 #define APPEND_DEBUG(ch) \
 do {							\
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 3e3d8fd..c523457 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -66,8 +66,8 @@
 static unsigned int max_clients = 15;
 static unsigned int threshold_client_limit = 30;
 /* This is the maximum number of pkt registrations supported at initialization*/
-unsigned int diag_max_reg = 600;
-unsigned int diag_threshold_reg = 750;
+int diag_max_reg = 600;
+int diag_threshold_reg = 750;
 
 /* Timer variables */
 static struct timer_list drain_timer;
@@ -522,143 +522,324 @@
 			    int *pnum_data) { return 0; }
 #endif
 
-long diagchar_ioctl(struct file *filp,
-			   unsigned int iocmd, unsigned long ioarg)
+int diag_command_reg(unsigned long ioarg)
 {
-	int i, j, temp, success = -1, status, index = -1;
-	unsigned int count_entries = 0, interim_count = 0;
+	int i = 0, success = -EINVAL, j;
 	void *temp_buf;
-	uint16_t support_list = 0;
-	struct diag_dci_client_tbl *dci_params;
-	struct diag_dci_health_stats stats;
-
-	if (iocmd == DIAG_IOCTL_COMMAND_REG) {
-		struct bindpkt_params_per_process pkt_params;
-		struct bindpkt_params *params;
-		struct bindpkt_params *head_params;
-		if (copy_from_user(&pkt_params, (void *)ioarg,
-			   sizeof(struct bindpkt_params_per_process))) {
-			return -EFAULT;
-		}
-		if ((UINT32_MAX/sizeof(struct bindpkt_params)) <
-							 pkt_params.count) {
-			pr_warning("diag: integer overflow while multiply\n");
-			return -EFAULT;
-		}
-		params = kzalloc(pkt_params.count*sizeof(
-			struct bindpkt_params), GFP_KERNEL);
-		if (!params) {
-			pr_err("diag: unable to alloc memory\n");
-			return -ENOMEM;
-		} else
-			head_params = params;
-
-		if (copy_from_user(params, pkt_params.params,
-			   pkt_params.count*sizeof(struct bindpkt_params))) {
-			kfree(head_params);
-			return -EFAULT;
-		}
-		mutex_lock(&driver->diagchar_mutex);
-		for (i = 0; i < diag_max_reg; i++) {
-			if (driver->table[i].process_id == 0) {
-				diag_add_reg(i, params, &success,
-							 &count_entries);
-				if (pkt_params.count > count_entries) {
-					params++;
-				} else {
-					mutex_unlock(&driver->diagchar_mutex);
-					kfree(head_params);
-					return success;
-				}
+	unsigned int count_entries = 0, interim_count = 0;
+	struct bindpkt_params_per_process pkt_params;
+	struct bindpkt_params *params;
+	struct bindpkt_params *head_params;
+	if (copy_from_user(&pkt_params, (void *)ioarg,
+		   sizeof(struct bindpkt_params_per_process))) {
+		return -EFAULT;
+	}
+	if ((UINT_MAX/sizeof(struct bindpkt_params)) <
+						 pkt_params.count) {
+		pr_warn("diag: integer overflow while multiply\n");
+		return -EFAULT;
+	}
+	head_params = kzalloc(pkt_params.count*sizeof(
+		struct bindpkt_params), GFP_KERNEL);
+	if (!head_params) {
+		pr_err("diag: unable to alloc memory\n");
+		return -ENOMEM;
+	} else
+		params = head_params;
+	if (copy_from_user(params, pkt_params.params,
+		   pkt_params.count*sizeof(struct bindpkt_params))) {
+		kfree(head_params);
+		return -EFAULT;
+	}
+	mutex_lock(&driver->diagchar_mutex);
+	for (i = 0; i < diag_max_reg; i++) {
+		if (driver->table[i].process_id == 0) {
+			diag_add_reg(i, params, &success,
+						 &count_entries);
+			if (pkt_params.count > count_entries) {
+				params++;
+			} else {
+				kfree(head_params);
+				mutex_unlock(&driver->diagchar_mutex);
+				return success;
 			}
 		}
-		if (i < diag_threshold_reg) {
-			/* Increase table size by amount required */
+	}
+	if (i < diag_threshold_reg) {
+		/* Increase table size by amount required */
+		if (pkt_params.count >= count_entries) {
+			interim_count = pkt_params.count -
+						 count_entries;
+		} else {
+			pr_warn("diag: error in params count\n");
+			kfree(head_params);
+			mutex_unlock(&driver->diagchar_mutex);
+			return -EFAULT;
+		}
+		if (UINT_MAX - diag_max_reg >=
+						interim_count) {
+			diag_max_reg += interim_count;
+		} else {
+			pr_warn("diag: Integer overflow\n");
+			kfree(head_params);
+			mutex_unlock(&driver->diagchar_mutex);
+			return -EFAULT;
+		}
+		/* Make sure size doesnt go beyond threshold */
+		if (diag_max_reg > diag_threshold_reg) {
+			diag_max_reg = diag_threshold_reg;
+			pr_err("diag: best case memory allocation\n");
+		}
+		if (UINT_MAX/sizeof(struct diag_master_table) <
+							 diag_max_reg) {
+			pr_warn("diag: integer overflow\n");
+			kfree(head_params);
+			mutex_unlock(&driver->diagchar_mutex);
+			return -EFAULT;
+		}
+		temp_buf = krealloc(driver->table,
+				 diag_max_reg*sizeof(struct
+				 diag_master_table), GFP_KERNEL);
+		if (!temp_buf) {
+			pr_err("diag: Insufficient memory for reg.\n");
+
 			if (pkt_params.count >= count_entries) {
 				interim_count = pkt_params.count -
 							 count_entries;
 			} else {
-				pr_warning("diag: error in params count\n");
+				pr_warn("diag: params count error\n");
 				kfree(head_params);
 				mutex_unlock(&driver->diagchar_mutex);
 				return -EFAULT;
 			}
-			if (UINT32_MAX - diag_max_reg >=
-							interim_count) {
-				diag_max_reg += interim_count;
+			if (diag_max_reg >= interim_count) {
+				diag_max_reg -= interim_count;
 			} else {
-				pr_warning("diag: Integer overflow\n");
+				pr_warn("diag: Integer underflow\n");
 				kfree(head_params);
 				mutex_unlock(&driver->diagchar_mutex);
 				return -EFAULT;
 			}
-			/* Make sure size doesnt go beyond threshold */
-			if (diag_max_reg > diag_threshold_reg) {
-				diag_max_reg = diag_threshold_reg;
-				pr_info("diag: best case memory allocation\n");
-			}
-			if (UINT32_MAX/sizeof(struct diag_master_table) <
-								 diag_max_reg) {
-				pr_warning("diag: integer overflow\n");
-				kfree(head_params);
-				mutex_unlock(&driver->diagchar_mutex);
-				return -EFAULT;
-			}
-			temp_buf = krealloc(driver->table,
-					 diag_max_reg*sizeof(struct
-					 diag_master_table), GFP_KERNEL);
-			if (!temp_buf) {
-				pr_alert("diag: Insufficient memory for reg.\n");
-				mutex_unlock(&driver->diagchar_mutex);
-
-				if (pkt_params.count >= count_entries) {
-					interim_count = pkt_params.count -
-								 count_entries;
-				} else {
-					pr_warning("diag: params count error\n");
-					mutex_unlock(&driver->diagchar_mutex);
-					kfree(head_params);
-					return -EFAULT;
-				}
-				if (diag_max_reg >= interim_count) {
-					diag_max_reg -= interim_count;
-				} else {
-					pr_warning("diag: Integer underflow\n");
-					mutex_unlock(&driver->diagchar_mutex);
-					kfree(head_params);
-					return -EFAULT;
-				}
-				kfree(head_params);
-				return 0;
-			} else {
-				driver->table = temp_buf;
-			}
-			for (j = i; j < diag_max_reg; j++) {
-				diag_add_reg(j, params, &success,
-							 &count_entries);
-				if (pkt_params.count > count_entries) {
-					params++;
-				} else {
-					mutex_unlock(&driver->diagchar_mutex);
-					kfree(head_params);
-					return success;
-				}
-			}
 			kfree(head_params);
 			mutex_unlock(&driver->diagchar_mutex);
+			return 0;
 		} else {
-			mutex_unlock(&driver->diagchar_mutex);
-			kfree(head_params);
-			pr_err("Max size reached, Pkt Registration failed for"
-						" Process %d", current->tgid);
+			driver->table = temp_buf;
 		}
-		success = 0;
-	} else if (iocmd == DIAG_IOCTL_GET_DELAYED_RSP_ID) {
-		struct diagpkt_delay_params delay_params;
-		uint16_t interim_rsp_id;
-		int interim_size;
+		for (j = i; j < diag_max_reg; j++) {
+			diag_add_reg(j, params, &success,
+						 &count_entries);
+			if (pkt_params.count > count_entries) {
+				params++;
+			} else {
+				kfree(head_params);
+				mutex_unlock(&driver->diagchar_mutex);
+				return success;
+			}
+		}
+		kfree(head_params);
+		mutex_unlock(&driver->diagchar_mutex);
+	} else {
+		kfree(head_params);
+		mutex_unlock(&driver->diagchar_mutex);
+		pr_err("Max size reached, Pkt Registration failed for Process %d",
+					current->tgid);
+	}
+	success = 0;
+	return success;
+}
+
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode)
+{
+	if (old_mode == MEMORY_DEVICE_MODE && new_mode
+					== NO_LOGGING_MODE) {
+		diagfwd_disconnect_bridge(0);
+		diag_clear_hsic_tbl();
+	} else if (old_mode == NO_LOGGING_MODE && new_mode
+					== MEMORY_DEVICE_MODE) {
+		diagfwd_connect_bridge(0);
+	} else if (old_mode == USB_MODE && new_mode
+					 == NO_LOGGING_MODE) {
+		diagfwd_disconnect_bridge(0);
+	} else if (old_mode == NO_LOGGING_MODE && new_mode
+					== USB_MODE) {
+		diagfwd_connect_bridge(0);
+	} else if (old_mode == USB_MODE && new_mode
+					== MEMORY_DEVICE_MODE) {
+		diagfwd_cancel_hsic();
+		diagfwd_connect_bridge(0);
+	} else if (old_mode == MEMORY_DEVICE_MODE && new_mode
+					== USB_MODE) {
+		diag_clear_hsic_tbl();
+		diagfwd_cancel_hsic();
+		diagfwd_connect_bridge(0);
+	}
+}
+#else
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode)
+{
+
+}
+#endif
+
+#ifdef CONFIG_DIAG_SDIO_PIPE
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode)
+{
+	if (old_mode == MEMORY_DEVICE_MODE && new_mode
+					== NO_LOGGING_MODE) {
+		mutex_lock(&driver->diagchar_mutex);
+		driver->in_busy_sdio = 1;
+		mutex_unlock(&driver->diagchar_mutex);
+	} else if (old_mode == NO_LOGGING_MODE && new_mode
+					== MEMORY_DEVICE_MODE) {
+		mutex_lock(&driver->diagchar_mutex);
+		driver->in_busy_sdio = 0;
+		mutex_unlock(&driver->diagchar_mutex);
+		/* Poll SDIO channel to check for data */
+		if (driver->sdio_ch)
+			queue_work(driver->diag_sdio_wq,
+				&(driver->diag_read_sdio_work));
+	} else if (old_mode == USB_MODE && new_mode
+					== MEMORY_DEVICE_MODE) {
+		mutex_lock(&driver->diagchar_mutex);
+		driver->in_busy_sdio = 0;
+		mutex_unlock(&driver->diagchar_mutex);
+		/* Poll SDIO channel to check for data */
+		if (driver->sdio_ch)
+			queue_work(driver->diag_sdio_wq,
+				&(driver->diag_read_sdio_work));
+	}
+}
+#else
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode)
+{
+
+}
+#endif
+
+int diag_switch_logging(unsigned long ioarg)
+{
+	int i, temp, success = -EINVAL, status;
+	mutex_lock(&driver->diagchar_mutex);
+	temp = driver->logging_mode;
+	driver->logging_mode = (int)ioarg;
+	if (temp == driver->logging_mode) {
+		mutex_unlock(&driver->diagchar_mutex);
+		pr_err("diag: forbidden logging change requested\n");
+		return 0;
+	}
+
+	if (driver->logging_mode == MEMORY_DEVICE_MODE) {
+		diag_clear_hsic_tbl();
+		driver->mask_check = 1;
+		if (driver->socket_process) {
+			/*
+			 * Notify the socket logging process that we
+			 * are switching to MEMORY_DEVICE_MODE
+			 */
+			status = send_sig(SIGCONT,
+				 driver->socket_process, 0);
+			if (status) {
+				pr_err("diag: %s, Error notifying ",
+					__func__);
+				pr_err("socket process, status: %d\n",
+					status);
+			}
+		}
+	} else if (driver->logging_mode == SOCKET_MODE) {
+		driver->socket_process = current;
+	} else if (driver->logging_mode == CALLBACK_MODE) {
+		driver->callback_process = current;
+	}
+
+	if (driver->logging_mode == UART_MODE ||
+				driver->logging_mode == SOCKET_MODE ||
+				driver->logging_mode == CALLBACK_MODE) {
+		diag_clear_hsic_tbl();
+		driver->mask_check = 0;
+		driver->logging_mode = MEMORY_DEVICE_MODE;
+	}
+
+	driver->logging_process_id = current->tgid;
+	mutex_unlock(&driver->diagchar_mutex);
+
+	if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
+						== NO_LOGGING_MODE) {
+		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+			driver->smd_data[i].in_busy_1 = 0;
+			driver->smd_data[i].in_busy_2 = 0;
+		}
+		diag_cmp_logging_modes_sdio_pipe(temp, driver->logging_mode);
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+							driver->logging_mode);
+	} else if (temp == NO_LOGGING_MODE && driver->logging_mode
+						== MEMORY_DEVICE_MODE) {
+		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+			driver->smd_data[i].in_busy_1 = 0;
+			driver->smd_data[i].in_busy_2 = 0;
+			/* Poll SMD channels to check for data*/
+			if (driver->smd_data[i].ch)
+				queue_work(driver->diag_wq,
+					&(driver->smd_data[i].
+						diag_read_smd_work));
+		}
+		diag_cmp_logging_modes_sdio_pipe(temp,
+						driver->logging_mode);
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	} else if (temp == USB_MODE && driver->logging_mode
+						 == NO_LOGGING_MODE) {
+		diagfwd_disconnect();
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	} else if (temp == NO_LOGGING_MODE && driver->logging_mode
+							== USB_MODE) {
+		diagfwd_connect();
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	} else if (temp == USB_MODE && driver->logging_mode
+						== MEMORY_DEVICE_MODE) {
+		diagfwd_disconnect();
+		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+			driver->smd_data[i].in_busy_1 = 0;
+			driver->smd_data[i].in_busy_2 = 0;
+			/* Poll SMD channels to check for data*/
+			if (driver->smd_data[i].ch)
+				queue_work(driver->diag_wq,
+					&(driver->smd_data[i].
+						diag_read_smd_work));
+		}
+		diag_cmp_logging_modes_sdio_pipe(temp, driver->logging_mode);
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	} else if (temp == MEMORY_DEVICE_MODE &&
+			 driver->logging_mode == USB_MODE) {
+		diagfwd_connect();
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	}
+	success = 1;
+	return success;
+}
+
+long diagchar_ioctl(struct file *filp,
+			   unsigned int iocmd, unsigned long ioarg)
+{
+	int i, result = -EINVAL, interim_size = 0, client_id = 0;
+	uint16_t support_list = 0, interim_rsp_id, remote_dev;
+	struct diag_dci_client_tbl *dci_params;
+	struct diag_dci_health_stats stats;
+	struct diag_log_event_stats le_stats;
+	struct diagpkt_delay_params delay_params;
+
+	switch (iocmd) {
+	case DIAG_IOCTL_COMMAND_REG:
+		result = diag_command_reg(ioarg);
+		break;
+	case DIAG_IOCTL_GET_DELAYED_RSP_ID:
 		if (copy_from_user(&delay_params, (void *)ioarg,
-					   sizeof(struct diagpkt_delay_params)))
+					sizeof(struct diagpkt_delay_params)))
 			return -EFAULT;
 		if ((delay_params.rsp_ptr) &&
 		 (delay_params.size == sizeof(delayed_rsp_id)) &&
@@ -672,9 +853,10 @@
 			if (copy_to_user((void *)delay_params.num_bytes_ptr,
 						 &interim_size, sizeof(int)))
 				return -EFAULT;
-			success = 0;
+			result = 0;
 		}
-	} else if (iocmd == DIAG_IOCTL_DCI_REG) {
+		break;
+	case DIAG_IOCTL_DCI_REG:
 		if (driver->dci_state == DIAG_DCI_NO_REG)
 			return DIAG_DCI_NO_REG;
 		if (driver->num_dci_client >= MAX_DCI_CLIENTS)
@@ -723,49 +905,47 @@
 		}
 		kfree(dci_params);
 		mutex_unlock(&driver->dci_mutex);
-		return driver->dci_client_id;
-	} else if (iocmd == DIAG_IOCTL_DCI_DEINIT) {
-		success = -1;
-		/*
-		* Clear log/event masks and send updated
-		* masks to peripherals
-		*/
+		result = driver->dci_client_id;
+		break;
+	case DIAG_IOCTL_DCI_DEINIT:
+		result = -EIO;
+		/* Delete this process from DCI table */
 		mutex_lock(&driver->dci_mutex);
-		index = diag_dci_find_client_index(current->tgid);
-		if (index != DCI_CLIENT_INDEX_INVALID) {
+		i = diag_dci_find_client_index(current->tgid);
+		if (i == DCI_CLIENT_INDEX_INVALID) {
+			result = DIAG_DCI_NOT_SUPPORTED;
+		} else {
 			/* clear respective cumulative log masks */
-			clear_client_dci_cumulative_log_mask(index);
+			clear_client_dci_cumulative_log_mask(i);
 			/* send updated log mask to peripherals */
-			success =
+			result =
 			diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
-			if (success != DIAG_DCI_NO_ERROR) {
+			if (result != DIAG_DCI_NO_ERROR) {
 				mutex_unlock(&driver->dci_mutex);
-				return success;
+				return result;
 			}
 			/* clear respective cumulative event masks */
-			clear_client_dci_cumulative_event_mask(index);
+			clear_client_dci_cumulative_event_mask(i);
 			/* send updated event mask to peripherals */
-			success =
+			result =
 			diag_send_dci_event_mask(
 				driver->smd_cntl[MODEM_DATA].ch);
-			if (success != DIAG_DCI_NO_ERROR) {
+			if (result != DIAG_DCI_NO_ERROR) {
 				mutex_unlock(&driver->dci_mutex);
-				return success;
+				return result;
 			}
-		}
-		/* Delete this process from DCI table */
-		for (i = 0; i < dci_max_reg; i++)
-			if (driver->req_tracking_tbl[i].pid == current->tgid)
-				driver->req_tracking_tbl[i].pid = 0;
-		if (index != DCI_CLIENT_INDEX_INVALID) {
-			driver->dci_client_tbl[index].client = NULL;
-			success = index;
-		}
-		if (success >= 0)
+			result = i;
+			/* Delete this process from DCI table */
+			for (i = 0; i < dci_max_reg; i++)
+				if (driver->req_tracking_tbl[i].pid ==
+					 current->tgid)
+					driver->req_tracking_tbl[i].pid = 0;
+			driver->dci_client_tbl[result].client = NULL;
 			driver->num_dci_client--;
+		}
 		mutex_unlock(&driver->dci_mutex);
-		return success;
-	} else if (iocmd == DIAG_IOCTL_DCI_SUPPORT) {
+		break;
+	case DIAG_IOCTL_DCI_SUPPORT:
 		for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
 			if (driver->smd_dci[i].ch)
 				support_list |=
@@ -774,35 +954,69 @@
 		if (copy_to_user((void *)ioarg, &support_list,
 							 sizeof(uint16_t)))
 			return -EFAULT;
-		return DIAG_DCI_NO_ERROR;
-	} else if (iocmd == DIAG_IOCTL_DCI_HEALTH_STATS) {
+		result = DIAG_DCI_NO_ERROR;
+		break;
+	case DIAG_IOCTL_DCI_HEALTH_STATS:
 		if (copy_from_user(&stats, (void *)ioarg,
 				 sizeof(struct diag_dci_health_stats)))
 			return -EFAULT;
-		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		mutex_lock(&dci_health_mutex);
+		i = diag_dci_find_client_index(current->tgid);
+		if (i != DCI_CLIENT_INDEX_INVALID) {
 			dci_params = &(driver->dci_client_tbl[i]);
-			if (dci_params->client &&
-				dci_params->client->tgid == current->tgid) {
-				stats.dropped_logs = dci_params->dropped_logs;
-				stats.dropped_events =
-						 dci_params->dropped_events;
-				stats.received_logs = dci_params->received_logs;
-				stats.received_events =
-						 dci_params->received_events;
-				if (stats.reset_status) {
-					dci_params->dropped_logs = 0;
-					dci_params->dropped_events = 0;
-					dci_params->received_logs = 0;
-					dci_params->received_events = 0;
-				}
-				break;
+			stats.dropped_logs = dci_params->dropped_logs;
+			stats.dropped_events =
+					dci_params->dropped_events;
+			stats.received_logs =
+					dci_params->received_logs;
+			stats.received_events =
+					dci_params->received_events;
+			if (stats.reset_status) {
+				dci_params->dropped_logs = 0;
+				dci_params->dropped_events = 0;
+				dci_params->received_logs = 0;
+				dci_params->received_events = 0;
 			}
 		}
+		mutex_unlock(&dci_health_mutex);
 		if (copy_to_user((void *)ioarg, &stats,
 				   sizeof(struct diag_dci_health_stats)))
 			return -EFAULT;
-		return DIAG_DCI_NO_ERROR;
-	} else if (iocmd == DIAG_IOCTL_LSM_DEINIT) {
+		result = DIAG_DCI_NO_ERROR;
+		break;
+	case DIAG_IOCTL_DCI_LOG_STATUS:
+		if (copy_from_user(&le_stats, (void *)ioarg,
+				sizeof(struct diag_log_event_stats)))
+			return -EFAULT;
+		le_stats.is_set = diag_dci_query_log_mask(le_stats.code);
+		if (copy_to_user((void *)ioarg, &le_stats,
+				sizeof(struct diag_log_event_stats)))
+			return -EFAULT;
+		result = DIAG_DCI_NO_ERROR;
+		break;
+	case DIAG_IOCTL_DCI_EVENT_STATUS:
+		if (copy_from_user(&le_stats, (void *)ioarg,
+					sizeof(struct diag_log_event_stats)))
+			return -EFAULT;
+		le_stats.is_set = diag_dci_query_event_mask(le_stats.code);
+		if (copy_to_user((void *)ioarg, &le_stats,
+				sizeof(struct diag_log_event_stats)))
+			return -EFAULT;
+		result = DIAG_DCI_NO_ERROR;
+		break;
+	case DIAG_IOCTL_DCI_CLEAR_LOGS:
+		if (copy_from_user((void *)&client_id, (void *)ioarg,
+				sizeof(int)))
+			return -EFAULT;
+		result = diag_dci_clear_log_mask();
+		break;
+	case DIAG_IOCTL_DCI_CLEAR_EVENTS:
+		if (copy_from_user(&client_id, (void *)ioarg,
+				sizeof(int)))
+			return -EFAULT;
+		result = diag_dci_clear_event_mask();
+		break;
+	case DIAG_IOCTL_LSM_DEINIT:
 		for (i = 0; i < driver->num_clients; i++)
 			if (driver->client_map[i].pid == current->tgid)
 				break;
@@ -810,138 +1024,20 @@
 			return -EINVAL;
 		driver->data_ready[i] |= DEINIT_TYPE;
 		wake_up_interruptible(&driver->wait_q);
-		success = 1;
-	} else if (iocmd == DIAG_IOCTL_SWITCH_LOGGING) {
-		mutex_lock(&driver->diagchar_mutex);
-		temp = driver->logging_mode;
-		driver->logging_mode = (int)ioarg;
-		if (temp == driver->logging_mode) {
-			mutex_unlock(&driver->diagchar_mutex);
-			pr_alert("diag: forbidden logging change requested\n");
-			return 0;
-		}
-		if (driver->logging_mode == MEMORY_DEVICE_MODE) {
-			diag_clear_hsic_tbl();
-			driver->mask_check = 1;
-			if (driver->socket_process) {
-				/*
-				 * Notify the socket logging process that we
-				 * are switching to MEMORY_DEVICE_MODE
-				 */
-				status = send_sig(SIGCONT,
-					 driver->socket_process, 0);
-				if (status) {
-					pr_err("diag: %s, Error notifying ",
-						__func__);
-					pr_err("socket process, status: %d\n",
-						status);
-				}
-			}
-		}
-		if (driver->logging_mode == SOCKET_MODE)
-			driver->socket_process = current;
-		if (driver->logging_mode == CALLBACK_MODE)
-			driver->callback_process = current;
-		if (driver->logging_mode == UART_MODE ||
-			driver->logging_mode == SOCKET_MODE ||
-			driver->logging_mode == CALLBACK_MODE) {
-			diag_clear_hsic_tbl();
-			driver->mask_check = 0;
-			driver->logging_mode = MEMORY_DEVICE_MODE;
-		}
-		driver->logging_process_id = current->tgid;
-		mutex_unlock(&driver->diagchar_mutex);
-		if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
-							== NO_LOGGING_MODE) {
-			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
-				driver->smd_data[i].in_busy_1 = 0;
-				driver->smd_data[i].in_busy_2 = 0;
-			}
-#ifdef CONFIG_DIAG_SDIO_PIPE
-			driver->in_busy_sdio = 1;
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_disconnect_bridge(0);
-			diag_clear_hsic_tbl();
-#endif
-		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
-							== MEMORY_DEVICE_MODE) {
-			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
-				driver->smd_data[i].in_busy_1 = 0;
-				driver->smd_data[i].in_busy_2 = 0;
-				/* Poll SMD channels to check for data*/
-				if (driver->smd_data[i].ch)
-					queue_work(driver->diag_wq,
-						&(driver->smd_data[i].
-							diag_read_smd_work));
-			}
-#ifdef CONFIG_DIAG_SDIO_PIPE
-			driver->in_busy_sdio = 0;
-			/* Poll SDIO channel to check for data */
-			if (driver->sdio_ch)
-				queue_work(driver->diag_sdio_wq,
-					&(driver->diag_read_sdio_work));
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_connect_bridge(0);
-#endif
-		}
-#ifdef CONFIG_DIAG_OVER_USB
-		else if (temp == USB_MODE && driver->logging_mode
-							 == NO_LOGGING_MODE) {
-			diagfwd_disconnect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_disconnect_bridge(0);
-#endif
-		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
-								== USB_MODE) {
-			diagfwd_connect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_connect_bridge(0);
-#endif
-		} else if (temp == USB_MODE && driver->logging_mode
-							== MEMORY_DEVICE_MODE) {
-			diagfwd_disconnect();
-			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
-				driver->smd_data[i].in_busy_1 = 0;
-				driver->smd_data[i].in_busy_2 = 0;
-				/* Poll SMD channels to check for data*/
-				if (driver->smd_data[i].ch)
-					queue_work(driver->diag_wq,
-						&(driver->smd_data[i].
-							diag_read_smd_work));
-			}
-#ifdef CONFIG_DIAG_SDIO_PIPE
-			driver->in_busy_sdio = 0;
-			/* Poll SDIO channel to check for data */
-			if (driver->sdio_ch)
-				queue_work(driver->diag_sdio_wq,
-					&(driver->diag_read_sdio_work));
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_cancel_hsic();
-			diagfwd_connect_bridge(0);
-#endif
-		} else if (temp == MEMORY_DEVICE_MODE &&
-				 driver->logging_mode == USB_MODE) {
-			diagfwd_connect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diag_clear_hsic_tbl();
-			diagfwd_cancel_hsic();
-			diagfwd_connect_bridge(0);
-#endif
-		}
-#endif /* DIAG over USB */
-		success = 1;
-	} else if (iocmd == DIAG_IOCTL_REMOTE_DEV) {
-		uint16_t remote_dev = diag_get_remote_device_mask();
+		result = 1;
+		break;
+	case DIAG_IOCTL_SWITCH_LOGGING:
+		result = diag_switch_logging(ioarg);
+		break;
+	case DIAG_IOCTL_REMOTE_DEV:
+		remote_dev = diag_get_remote_device_mask();
 		if (copy_to_user((void *)ioarg, &remote_dev, sizeof(uint16_t)))
-			success = -EFAULT;
+			result = -EFAULT;
 		else
-			success = 1;
+			result = 1;
+		break;
 	}
-
-	return success;
+	return result;
 }
 
 static int diagchar_read(struct file *file, char __user *buf, size_t count,
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 5a67b0c..afbe4be 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -39,6 +39,10 @@
 int diag_smd_constructor(struct diag_smd_info *smd_info, int peripheral,
 			 int type);
 void diag_smd_destructor(struct diag_smd_info *smd_info);
+int diag_switch_logging(unsigned long);
+int diag_command_reg(unsigned long);
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode);
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode);
 /* State for diag forwarding */
 #ifdef CONFIG_DIAG_OVER_USB
 int diagfwd_connect(void);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 522136d..2cfafc3 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -59,7 +59,7 @@
 /*
  * Assigned numbers, used for dynamic minors
  */
-#define DYNAMIC_MINORS 64 /* like dynamic majors */
+#define DYNAMIC_MINORS 96 /* like dynamic majors */
 static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);
 
 #ifdef CONFIG_PROC_FS
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index c113cf1..f5ca5b6 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -1,6 +1,7 @@
 #
 # Makefile for the kernel tpm device drivers.
 #
+
 obj-$(CONFIG_TCG_TPM) += tpm.o
 ifdef CONFIG_ACPI
 	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
deleted file mode 100644
index 94bb440..0000000
--- a/drivers/char/tty_io.c
+++ /dev/null
@@ -1,3154 +0,0 @@
-/*
- *  linux/drivers/char/tty_io.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/*
- * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
- * or rs-channels. It also implements echoing, cooked mode etc.
- *
- * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
- *
- * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
- * tty_struct and tty_queue structures.  Previously there was an array
- * of 256 tty_struct's which was statically allocated, and the
- * tty_queue structures were allocated at boot time.  Both are now
- * dynamically allocated only when the tty is open.
- *
- * Also restructured routines so that there is more of a separation
- * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
- * the low-level tty routines (serial.c, pty.c, console.c).  This
- * makes for cleaner and more compact code.  -TYT, 9/17/92
- *
- * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
- * which can be dynamically activated and de-activated by the line
- * discipline handling modules (like SLIP).
- *
- * NOTE: pay no attention to the line discipline code (yet); its
- * interface is still subject to change in this version...
- * -- TYT, 1/31/92
- *
- * Added functionality to the OPOST tty handling.  No delays, but all
- * other bits should be there.
- *	-- Nick Holloway <alfie@dcs.warwick.ac.uk>, 27th May 1993.
- *
- * Rewrote canonical mode and added more termios flags.
- * 	-- julian@uhunix.uhcc.hawaii.edu (J. Cowley), 13Jan94
- *
- * Reorganized FASYNC support so mouse code can share it.
- *	-- ctm@ardi.com, 9Sep95
- *
- * New TIOCLINUX variants added.
- *	-- mj@k332.feld.cvut.cz, 19-Nov-95
- *
- * Restrict vt switching via ioctl()
- *      -- grif@cs.ucr.edu, 5-Dec-95
- *
- * Move console and virtual terminal code to more appropriate files,
- * implement CONFIG_VT and generalize console device interface.
- *	-- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97
- *
- * Rewrote tty_init_dev and tty_release_dev to eliminate races.
- *	-- Bill Hawes <whawes@star.net>, June 97
- *
- * Added devfs support.
- *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 13-Jan-1998
- *
- * Added support for a Unix98-style ptmx device.
- *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
- *
- * Reduced memory usage for older ARM systems
- *      -- Russell King <rmk@arm.linux.org.uk>
- *
- * Move do_SAK() into process context.  Less stack use in devfs functions.
- * alloc_tty_struct() always uses kmalloc()
- *			 -- Andrew Morton <andrewm@uow.edu.eu> 17Mar01
- */
-
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/devpts_fs.h>
-#include <linux/file.h>
-#include <linux/fdtable.h>
-#include <linux/console.h>
-#include <linux/timer.h>
-#include <linux/ctype.h>
-#include <linux/kd.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/smp_lock.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-
-#include <linux/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/kbd_kern.h>
-#include <linux/vt_kern.h>
-#include <linux/selection.h>
-
-#include <linux/kmod.h>
-#include <linux/nsproxy.h>
-
-#undef TTY_DEBUG_HANGUP
-
-#define TTY_PARANOIA_CHECK 1
-#define CHECK_TTY_COUNT 1
-
-struct ktermios tty_std_termios = {	/* for the benefit of tty drivers  */
-	.c_iflag = ICRNL | IXON,
-	.c_oflag = OPOST | ONLCR,
-	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
-	.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
-		   ECHOCTL | ECHOKE | IEXTEN,
-	.c_cc = INIT_C_CC,
-	.c_ispeed = 38400,
-	.c_ospeed = 38400
-};
-
-EXPORT_SYMBOL(tty_std_termios);
-
-/* This list gets poked at by procfs and various bits of boot up code. This
-   could do with some rationalisation such as pulling the tty proc function
-   into this file */
-
-LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
-
-/* Mutex to protect creating and releasing a tty. This is shared with
-   vt.c for deeply disgusting hack reasons */
-DEFINE_MUTEX(tty_mutex);
-EXPORT_SYMBOL(tty_mutex);
-
-static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
-ssize_t redirected_tty_write(struct file *, const char __user *,
-							size_t, loff_t *);
-static unsigned int tty_poll(struct file *, poll_table *);
-static int tty_open(struct inode *, struct file *);
-long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-#ifdef CONFIG_COMPAT
-static long tty_compat_ioctl(struct file *file, unsigned int cmd,
-				unsigned long arg);
-#else
-#define tty_compat_ioctl NULL
-#endif
-static int tty_fasync(int fd, struct file *filp, int on);
-static void release_tty(struct tty_struct *tty, int idx);
-static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
-static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
-
-/**
- *	alloc_tty_struct	-	allocate a tty object
- *
- *	Return a new empty tty structure. The data fields have not
- *	been initialized in any way but has been zeroed
- *
- *	Locking: none
- */
-
-struct tty_struct *alloc_tty_struct(void)
-{
-	return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
-}
-
-/**
- *	free_tty_struct		-	free a disused tty
- *	@tty: tty struct to free
- *
- *	Free the write buffers, tty queue and tty memory itself.
- *
- *	Locking: none. Must be called after tty is definitely unused
- */
-
-void free_tty_struct(struct tty_struct *tty)
-{
-	kfree(tty->write_buf);
-	tty_buffer_free_all(tty);
-	kfree(tty);
-}
-
-#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
-
-/**
- *	tty_name	-	return tty naming
- *	@tty: tty structure
- *	@buf: buffer for output
- *
- *	Convert a tty structure into a name. The name reflects the kernel
- *	naming policy and if udev is in use may not reflect user space
- *
- *	Locking: none
- */
-
-char *tty_name(struct tty_struct *tty, char *buf)
-{
-	if (!tty) /* Hmm.  NULL pointer.  That's fun. */
-		strcpy(buf, "NULL tty");
-	else
-		strcpy(buf, tty->name);
-	return buf;
-}
-
-EXPORT_SYMBOL(tty_name);
-
-int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
-			      const char *routine)
-{
-#ifdef TTY_PARANOIA_CHECK
-	if (!tty) {
-		printk(KERN_WARNING
-			"null TTY for (%d:%d) in %s\n",
-			imajor(inode), iminor(inode), routine);
-		return 1;
-	}
-	if (tty->magic != TTY_MAGIC) {
-		printk(KERN_WARNING
-			"bad magic number for tty struct (%d:%d) in %s\n",
-			imajor(inode), iminor(inode), routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-static int check_tty_count(struct tty_struct *tty, const char *routine)
-{
-#ifdef CHECK_TTY_COUNT
-	struct list_head *p;
-	int count = 0;
-
-	file_list_lock();
-	list_for_each(p, &tty->tty_files) {
-		count++;
-	}
-	file_list_unlock();
-	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
-	    tty->driver->subtype == PTY_TYPE_SLAVE &&
-	    tty->link && tty->link->count)
-		count++;
-	if (tty->count != count) {
-		printk(KERN_WARNING "Warning: dev (%s) tty->count(%d) "
-				    "!= #fd's(%d) in %s\n",
-		       tty->name, tty->count, count, routine);
-		return count;
-	}
-#endif
-	return 0;
-}
-
-/**
- *	get_tty_driver		-	find device of a tty
- *	@dev_t: device identifier
- *	@index: returns the index of the tty
- *
- *	This routine returns a tty driver structure, given a device number
- *	and also passes back the index number.
- *
- *	Locking: caller must hold tty_mutex
- */
-
-static struct tty_driver *get_tty_driver(dev_t device, int *index)
-{
-	struct tty_driver *p;
-
-	list_for_each_entry(p, &tty_drivers, tty_drivers) {
-		dev_t base = MKDEV(p->major, p->minor_start);
-		if (device < base || device >= base + p->num)
-			continue;
-		*index = device - base;
-		return tty_driver_kref_get(p);
-	}
-	return NULL;
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-
-/**
- *	tty_find_polling_driver	-	find device of a polled tty
- *	@name: name string to match
- *	@line: pointer to resulting tty line nr
- *
- *	This routine returns a tty driver structure, given a name
- *	and the condition that the tty driver is capable of polled
- *	operation.
- */
-struct tty_driver *tty_find_polling_driver(char *name, int *line)
-{
-	struct tty_driver *p, *res = NULL;
-	int tty_line = 0;
-	int len;
-	char *str, *stp;
-
-	for (str = name; *str; str++)
-		if ((*str >= '0' && *str <= '9') || *str == ',')
-			break;
-	if (!*str)
-		return NULL;
-
-	len = str - name;
-	tty_line = simple_strtoul(str, &str, 10);
-
-	mutex_lock(&tty_mutex);
-	/* Search through the tty devices to look for a match */
-	list_for_each_entry(p, &tty_drivers, tty_drivers) {
-		if (strncmp(name, p->name, len) != 0)
-			continue;
-		stp = str;
-		if (*stp == ',')
-			stp++;
-		if (*stp == '\0')
-			stp = NULL;
-
-		if (tty_line >= 0 && tty_line <= p->num && p->ops &&
-		    p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) {
-			res = tty_driver_kref_get(p);
-			*line = tty_line;
-			break;
-		}
-	}
-	mutex_unlock(&tty_mutex);
-
-	return res;
-}
-EXPORT_SYMBOL_GPL(tty_find_polling_driver);
-#endif
-
-/**
- *	tty_check_change	-	check for POSIX terminal changes
- *	@tty: tty to check
- *
- *	If we try to write to, or set the state of, a terminal and we're
- *	not in the foreground, send a SIGTTOU.  If the signal is blocked or
- *	ignored, go ahead and perform the operation.  (POSIX 7.2)
- *
- *	Locking: ctrl_lock
- */
-
-int tty_check_change(struct tty_struct *tty)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	if (current->signal->tty != tty)
-		return 0;
-
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
-
-	if (!tty->pgrp) {
-		printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
-		goto out_unlock;
-	}
-	if (task_pgrp(current) == tty->pgrp)
-		goto out_unlock;
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-	if (is_ignored(SIGTTOU))
-		goto out;
-	if (is_current_pgrp_orphaned()) {
-		ret = -EIO;
-		goto out;
-	}
-	kill_pgrp(task_pgrp(current), SIGTTOU, 1);
-	set_thread_flag(TIF_SIGPENDING);
-	ret = -ERESTARTSYS;
-out:
-	return ret;
-out_unlock:
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-	return ret;
-}
-
-EXPORT_SYMBOL(tty_check_change);
-
-static ssize_t hung_up_tty_read(struct file *file, char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	return 0;
-}
-
-static ssize_t hung_up_tty_write(struct file *file, const char __user *buf,
-				 size_t count, loff_t *ppos)
-{
-	return -EIO;
-}
-
-/* No kernel lock held - none needed ;) */
-static unsigned int hung_up_tty_poll(struct file *filp, poll_table *wait)
-{
-	return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
-}
-
-static long hung_up_tty_ioctl(struct file *file, unsigned int cmd,
-		unsigned long arg)
-{
-	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
-}
-
-static long hung_up_tty_compat_ioctl(struct file *file,
-				     unsigned int cmd, unsigned long arg)
-{
-	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
-}
-
-static const struct file_operations tty_fops = {
-	.llseek		= no_llseek,
-	.read		= tty_read,
-	.write		= tty_write,
-	.poll		= tty_poll,
-	.unlocked_ioctl	= tty_ioctl,
-	.compat_ioctl	= tty_compat_ioctl,
-	.open		= tty_open,
-	.release	= tty_release,
-	.fasync		= tty_fasync,
-};
-
-static const struct file_operations console_fops = {
-	.llseek		= no_llseek,
-	.read		= tty_read,
-	.write		= redirected_tty_write,
-	.poll		= tty_poll,
-	.unlocked_ioctl	= tty_ioctl,
-	.compat_ioctl	= tty_compat_ioctl,
-	.open		= tty_open,
-	.release	= tty_release,
-	.fasync		= tty_fasync,
-};
-
-static const struct file_operations hung_up_tty_fops = {
-	.llseek		= no_llseek,
-	.read		= hung_up_tty_read,
-	.write		= hung_up_tty_write,
-	.poll		= hung_up_tty_poll,
-	.unlocked_ioctl	= hung_up_tty_ioctl,
-	.compat_ioctl	= hung_up_tty_compat_ioctl,
-	.release	= tty_release,
-};
-
-static DEFINE_SPINLOCK(redirect_lock);
-static struct file *redirect;
-
-/**
- *	tty_wakeup	-	request more data
- *	@tty: terminal
- *
- *	Internal and external helper for wakeups of tty. This function
- *	informs the line discipline if present that the driver is ready
- *	to receive more output data.
- */
-
-void tty_wakeup(struct tty_struct *tty)
-{
-	struct tty_ldisc *ld;
-
-	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) {
-		ld = tty_ldisc_ref(tty);
-		if (ld) {
-			if (ld->ops->write_wakeup)
-				ld->ops->write_wakeup(tty);
-			tty_ldisc_deref(ld);
-		}
-	}
-	wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
-}
-
-EXPORT_SYMBOL_GPL(tty_wakeup);
-
-/**
- *	do_tty_hangup		-	actual handler for hangup events
- *	@work: tty device
- *
- *	This can be called by the "eventd" kernel thread.  That is process
- *	synchronous but doesn't hold any locks, so we need to make sure we
- *	have the appropriate locks for what we're doing.
- *
- *	The hangup event clears any pending redirections onto the hung up
- *	device. It ensures future writes will error and it does the needed
- *	line discipline hangup and signal delivery. The tty object itself
- *	remains intact.
- *
- *	Locking:
- *		BKL
- *		  redirect lock for undoing redirection
- *		  file list lock for manipulating list of ttys
- *		  tty_ldisc_lock from called functions
- *		  termios_mutex resetting termios data
- *		  tasklist_lock to walk task list for hangup event
- *		    ->siglock to protect ->signal/->sighand
- */
-static void do_tty_hangup(struct work_struct *work)
-{
-	struct tty_struct *tty =
-		container_of(work, struct tty_struct, hangup_work);
-	struct file *cons_filp = NULL;
-	struct file *filp, *f = NULL;
-	struct task_struct *p;
-	int    closecount = 0, n;
-	unsigned long flags;
-	int refs = 0;
-
-	if (!tty)
-		return;
-
-
-	spin_lock(&redirect_lock);
-	if (redirect && redirect->private_data == tty) {
-		f = redirect;
-		redirect = NULL;
-	}
-	spin_unlock(&redirect_lock);
-
-	/* inuse_filps is protected by the single kernel lock */
-	lock_kernel();
-	check_tty_count(tty, "do_tty_hangup");
-
-	file_list_lock();
-	/* This breaks for file handles being sent over AF_UNIX sockets ? */
-	list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
-		if (filp->f_op->write == redirected_tty_write)
-			cons_filp = filp;
-		if (filp->f_op->write != tty_write)
-			continue;
-		closecount++;
-		tty_fasync(-1, filp, 0);	/* can't block */
-		filp->f_op = &hung_up_tty_fops;
-	}
-	file_list_unlock();
-
-	tty_ldisc_hangup(tty);
-
-	read_lock(&tasklist_lock);
-	if (tty->session) {
-		do_each_pid_task(tty->session, PIDTYPE_SID, p) {
-			spin_lock_irq(&p->sighand->siglock);
-			if (p->signal->tty == tty) {
-				p->signal->tty = NULL;
-				/* We defer the dereferences outside fo
-				   the tasklist lock */
-				refs++;
-			}
-			if (!p->signal->leader) {
-				spin_unlock_irq(&p->sighand->siglock);
-				continue;
-			}
-			__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
-			__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
-			put_pid(p->signal->tty_old_pgrp);  /* A noop */
-			spin_lock_irqsave(&tty->ctrl_lock, flags);
-			if (tty->pgrp)
-				p->signal->tty_old_pgrp = get_pid(tty->pgrp);
-			spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-			spin_unlock_irq(&p->sighand->siglock);
-		} while_each_pid_task(tty->session, PIDTYPE_SID, p);
-	}
-	read_unlock(&tasklist_lock);
-
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
-	clear_bit(TTY_THROTTLED, &tty->flags);
-	clear_bit(TTY_PUSH, &tty->flags);
-	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-	put_pid(tty->session);
-	put_pid(tty->pgrp);
-	tty->session = NULL;
-	tty->pgrp = NULL;
-	tty->ctrl_status = 0;
-	set_bit(TTY_HUPPED, &tty->flags);
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
-	/* Account for the p->signal references we killed */
-	while (refs--)
-		tty_kref_put(tty);
-
-	/*
-	 * If one of the devices matches a console pointer, we
-	 * cannot just call hangup() because that will cause
-	 * tty->count and state->count to go out of sync.
-	 * So we just call close() the right number of times.
-	 */
-	if (cons_filp) {
-		if (tty->ops->close)
-			for (n = 0; n < closecount; n++)
-				tty->ops->close(tty, cons_filp);
-	} else if (tty->ops->hangup)
-		(tty->ops->hangup)(tty);
-	/*
-	 * We don't want to have driver/ldisc interactions beyond
-	 * the ones we did here. The driver layer expects no
-	 * calls after ->hangup() from the ldisc side. However we
-	 * can't yet guarantee all that.
-	 */
-	set_bit(TTY_HUPPED, &tty->flags);
-	tty_ldisc_enable(tty);
-	unlock_kernel();
-	if (f)
-		fput(f);
-}
-
-/**
- *	tty_hangup		-	trigger a hangup event
- *	@tty: tty to hangup
- *
- *	A carrier loss (virtual or otherwise) has occurred on this like
- *	schedule a hangup sequence to run after this event.
- */
-
-void tty_hangup(struct tty_struct *tty)
-{
-#ifdef TTY_DEBUG_HANGUP
-	char	buf[64];
-	printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
-#endif
-	schedule_work(&tty->hangup_work);
-}
-
-EXPORT_SYMBOL(tty_hangup);
-
-/**
- *	tty_vhangup		-	process vhangup
- *	@tty: tty to hangup
- *
- *	The user has asked via system call for the terminal to be hung up.
- *	We do this synchronously so that when the syscall returns the process
- *	is complete. That guarantee is necessary for security reasons.
- */
-
-void tty_vhangup(struct tty_struct *tty)
-{
-#ifdef TTY_DEBUG_HANGUP
-	char	buf[64];
-
-	printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
-#endif
-	do_tty_hangup(&tty->hangup_work);
-}
-
-EXPORT_SYMBOL(tty_vhangup);
-
-/**
- *	tty_vhangup_self	-	process vhangup for own ctty
- *
- *	Perform a vhangup on the current controlling tty
- */
-
-void tty_vhangup_self(void)
-{
-	struct tty_struct *tty;
-
-	tty = get_current_tty();
-	if (tty) {
-		tty_vhangup(tty);
-		tty_kref_put(tty);
-	}
-}
-
-/**
- *	tty_hung_up_p		-	was tty hung up
- *	@filp: file pointer of tty
- *
- *	Return true if the tty has been subject to a vhangup or a carrier
- *	loss
- */
-
-int tty_hung_up_p(struct file *filp)
-{
-	return (filp->f_op == &hung_up_tty_fops);
-}
-
-EXPORT_SYMBOL(tty_hung_up_p);
-
-static void session_clear_tty(struct pid *session)
-{
-	struct task_struct *p;
-	do_each_pid_task(session, PIDTYPE_SID, p) {
-		proc_clear_tty(p);
-	} while_each_pid_task(session, PIDTYPE_SID, p);
-}
-
-/**
- *	disassociate_ctty	-	disconnect controlling tty
- *	@on_exit: true if exiting so need to "hang up" the session
- *
- *	This function is typically called only by the session leader, when
- *	it wants to disassociate itself from its controlling tty.
- *
- *	It performs the following functions:
- * 	(1)  Sends a SIGHUP and SIGCONT to the foreground process group
- * 	(2)  Clears the tty from being controlling the session
- * 	(3)  Clears the controlling tty for all processes in the
- * 		session group.
- *
- *	The argument on_exit is set to 1 if called when a process is
- *	exiting; it is 0 if called by the ioctl TIOCNOTTY.
- *
- *	Locking:
- *		BKL is taken for hysterical raisins
- *		  tty_mutex is taken to protect tty
- *		  ->siglock is taken to protect ->signal/->sighand
- *		  tasklist_lock is taken to walk process list for sessions
- *		    ->siglock is taken to protect ->signal/->sighand
- */
-
-void disassociate_ctty(int on_exit)
-{
-	struct tty_struct *tty;
-	struct pid *tty_pgrp = NULL;
-
-	if (!current->signal->leader)
-		return;
-
-	tty = get_current_tty();
-	if (tty) {
-		tty_pgrp = get_pid(tty->pgrp);
-		lock_kernel();
-		if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
-			tty_vhangup(tty);
-		unlock_kernel();
-		tty_kref_put(tty);
-	} else if (on_exit) {
-		struct pid *old_pgrp;
-		spin_lock_irq(&current->sighand->siglock);
-		old_pgrp = current->signal->tty_old_pgrp;
-		current->signal->tty_old_pgrp = NULL;
-		spin_unlock_irq(&current->sighand->siglock);
-		if (old_pgrp) {
-			kill_pgrp(old_pgrp, SIGHUP, on_exit);
-			kill_pgrp(old_pgrp, SIGCONT, on_exit);
-			put_pid(old_pgrp);
-		}
-		return;
-	}
-	if (tty_pgrp) {
-		kill_pgrp(tty_pgrp, SIGHUP, on_exit);
-		if (!on_exit)
-			kill_pgrp(tty_pgrp, SIGCONT, on_exit);
-		put_pid(tty_pgrp);
-	}
-
-	spin_lock_irq(&current->sighand->siglock);
-	put_pid(current->signal->tty_old_pgrp);
-	current->signal->tty_old_pgrp = NULL;
-	spin_unlock_irq(&current->sighand->siglock);
-
-	tty = get_current_tty();
-	if (tty) {
-		unsigned long flags;
-		spin_lock_irqsave(&tty->ctrl_lock, flags);
-		put_pid(tty->session);
-		put_pid(tty->pgrp);
-		tty->session = NULL;
-		tty->pgrp = NULL;
-		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-		tty_kref_put(tty);
-	} else {
-#ifdef TTY_DEBUG_HANGUP
-		printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
-		       " = NULL", tty);
-#endif
-	}
-
-	/* Now clear signal->tty under the lock */
-	read_lock(&tasklist_lock);
-	session_clear_tty(task_session(current));
-	read_unlock(&tasklist_lock);
-}
-
-/**
- *
- *	no_tty	- Ensure the current process does not have a controlling tty
- */
-void no_tty(void)
-{
-	struct task_struct *tsk = current;
-	lock_kernel();
-	disassociate_ctty(0);
-	unlock_kernel();
-	proc_clear_tty(tsk);
-}
-
-
-/**
- *	stop_tty	-	propagate flow control
- *	@tty: tty to stop
- *
- *	Perform flow control to the driver. For PTY/TTY pairs we
- *	must also propagate the TIOCKPKT status. May be called
- *	on an already stopped device and will not re-call the driver
- *	method.
- *
- *	This functionality is used by both the line disciplines for
- *	halting incoming flow and by the driver. It may therefore be
- *	called from any context, may be under the tty atomic_write_lock
- *	but not always.
- *
- *	Locking:
- *		Uses the tty control lock internally
- */
-
-void stop_tty(struct tty_struct *tty)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
-	if (tty->stopped) {
-		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-		return;
-	}
-	tty->stopped = 1;
-	if (tty->link && tty->link->packet) {
-		tty->ctrl_status &= ~TIOCPKT_START;
-		tty->ctrl_status |= TIOCPKT_STOP;
-		wake_up_interruptible_poll(&tty->link->read_wait, POLLIN);
-	}
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-	if (tty->ops->stop)
-		(tty->ops->stop)(tty);
-}
-
-EXPORT_SYMBOL(stop_tty);
-
-/**
- *	start_tty	-	propagate flow control
- *	@tty: tty to start
- *
- *	Start a tty that has been stopped if at all possible. Perform
- *	any necessary wakeups and propagate the TIOCPKT status. If this
- *	is the tty was previous stopped and is being started then the
- *	driver start method is invoked and the line discipline woken.
- *
- *	Locking:
- *		ctrl_lock
- */
-
-void start_tty(struct tty_struct *tty)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
-	if (!tty->stopped || tty->flow_stopped) {
-		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-		return;
-	}
-	tty->stopped = 0;
-	if (tty->link && tty->link->packet) {
-		tty->ctrl_status &= ~TIOCPKT_STOP;
-		tty->ctrl_status |= TIOCPKT_START;
-		wake_up_interruptible_poll(&tty->link->read_wait, POLLIN);
-	}
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-	if (tty->ops->start)
-		(tty->ops->start)(tty);
-	/* If we have a running line discipline it may need kicking */
-	tty_wakeup(tty);
-}
-
-EXPORT_SYMBOL(start_tty);
-
-/**
- *	tty_read	-	read method for tty device files
- *	@file: pointer to tty file
- *	@buf: user buffer
- *	@count: size of user buffer
- *	@ppos: unused
- *
- *	Perform the read system call function on this terminal device. Checks
- *	for hung up devices before calling the line discipline method.
- *
- *	Locking:
- *		Locks the line discipline internally while needed. Multiple
- *	read calls may be outstanding in parallel.
- */
-
-static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
-			loff_t *ppos)
-{
-	int i;
-	struct tty_struct *tty;
-	struct inode *inode;
-	struct tty_ldisc *ld;
-
-	tty = (struct tty_struct *)file->private_data;
-	inode = file->f_path.dentry->d_inode;
-	if (tty_paranoia_check(tty, inode, "tty_read"))
-		return -EIO;
-	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
-		return -EIO;
-
-	/* We want to wait for the line discipline to sort out in this
-	   situation */
-	ld = tty_ldisc_ref_wait(tty);
-	if (ld->ops->read)
-		i = (ld->ops->read)(tty, file, buf, count);
-	else
-		i = -EIO;
-	tty_ldisc_deref(ld);
-	if (i > 0)
-		inode->i_atime = current_fs_time(inode->i_sb);
-	return i;
-}
-
-void tty_write_unlock(struct tty_struct *tty)
-{
-	mutex_unlock(&tty->atomic_write_lock);
-	wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
-}
-
-int tty_write_lock(struct tty_struct *tty, int ndelay)
-{
-	if (!mutex_trylock(&tty->atomic_write_lock)) {
-		if (ndelay)
-			return -EAGAIN;
-		if (mutex_lock_interruptible(&tty->atomic_write_lock))
-			return -ERESTARTSYS;
-	}
-	return 0;
-}
-
-/*
- * Split writes up in sane blocksizes to avoid
- * denial-of-service type attacks
- */
-static inline ssize_t do_tty_write(
-	ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
-	struct tty_struct *tty,
-	struct file *file,
-	const char __user *buf,
-	size_t count)
-{
-	ssize_t ret, written = 0;
-	unsigned int chunk;
-
-	ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * We chunk up writes into a temporary buffer. This
-	 * simplifies low-level drivers immensely, since they
-	 * don't have locking issues and user mode accesses.
-	 *
-	 * But if TTY_NO_WRITE_SPLIT is set, we should use a
-	 * big chunk-size..
-	 *
-	 * The default chunk-size is 2kB, because the NTTY
-	 * layer has problems with bigger chunks. It will
-	 * claim to be able to handle more characters than
-	 * it actually does.
-	 *
-	 * FIXME: This can probably go away now except that 64K chunks
-	 * are too likely to fail unless switched to vmalloc...
-	 */
-	chunk = 2048;
-	if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
-		chunk = 65536;
-	if (count < chunk)
-		chunk = count;
-
-	/* write_buf/write_cnt is protected by the atomic_write_lock mutex */
-	if (tty->write_cnt < chunk) {
-		unsigned char *buf_chunk;
-
-		if (chunk < 1024)
-			chunk = 1024;
-
-		buf_chunk = kmalloc(chunk, GFP_KERNEL);
-		if (!buf_chunk) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		kfree(tty->write_buf);
-		tty->write_cnt = chunk;
-		tty->write_buf = buf_chunk;
-	}
-
-	/* Do the write .. */
-	for (;;) {
-		size_t size = count;
-		if (size > chunk)
-			size = chunk;
-		ret = -EFAULT;
-		if (copy_from_user(tty->write_buf, buf, size))
-			break;
-		ret = write(tty, file, tty->write_buf, size);
-		if (ret <= 0)
-			break;
-		written += ret;
-		buf += ret;
-		count -= ret;
-		if (!count)
-			break;
-		ret = -ERESTARTSYS;
-		if (signal_pending(current))
-			break;
-		cond_resched();
-	}
-	if (written) {
-		struct inode *inode = file->f_path.dentry->d_inode;
-		inode->i_mtime = current_fs_time(inode->i_sb);
-		ret = written;
-	}
-out:
-	tty_write_unlock(tty);
-	return ret;
-}
-
-/**
- * tty_write_message - write a message to a certain tty, not just the console.
- * @tty: the destination tty_struct
- * @msg: the message to write
- *
- * This is used for messages that need to be redirected to a specific tty.
- * We don't put it into the syslog queue right now maybe in the future if
- * really needed.
- *
- * We must still hold the BKL and test the CLOSING flag for the moment.
- */
-
-void tty_write_message(struct tty_struct *tty, char *msg)
-{
-	if (tty) {
-		mutex_lock(&tty->atomic_write_lock);
-		lock_kernel();
-		if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
-			unlock_kernel();
-			tty->ops->write(tty, msg, strlen(msg));
-		} else
-			unlock_kernel();
-		tty_write_unlock(tty);
-	}
-	return;
-}
-
-
-/**
- *	tty_write		-	write method for tty device file
- *	@file: tty file pointer
- *	@buf: user data to write
- *	@count: bytes to write
- *	@ppos: unused
- *
- *	Write data to a tty device via the line discipline.
- *
- *	Locking:
- *		Locks the line discipline as required
- *		Writes to the tty driver are serialized by the atomic_write_lock
- *	and are then processed in chunks to the device. The line discipline
- *	write method will not be invoked in parallel for each device.
- */
-
-static ssize_t tty_write(struct file *file, const char __user *buf,
-						size_t count, loff_t *ppos)
-{
-	struct tty_struct *tty;
-	struct inode *inode = file->f_path.dentry->d_inode;
-	ssize_t ret;
-	struct tty_ldisc *ld;
-
-	tty = (struct tty_struct *)file->private_data;
-	if (tty_paranoia_check(tty, inode, "tty_write"))
-		return -EIO;
-	if (!tty || !tty->ops->write ||
-		(test_bit(TTY_IO_ERROR, &tty->flags)))
-			return -EIO;
-	/* Short term debug to catch buggy drivers */
-	if (tty->ops->write_room == NULL)
-		printk(KERN_ERR "tty driver %s lacks a write_room method.\n",
-			tty->driver->name);
-	ld = tty_ldisc_ref_wait(tty);
-	if (!ld->ops->write)
-		ret = -EIO;
-	else
-		ret = do_tty_write(ld->ops->write, tty, file, buf, count);
-	tty_ldisc_deref(ld);
-	return ret;
-}
-
-ssize_t redirected_tty_write(struct file *file, const char __user *buf,
-						size_t count, loff_t *ppos)
-{
-	struct file *p = NULL;
-
-	spin_lock(&redirect_lock);
-	if (redirect) {
-		get_file(redirect);
-		p = redirect;
-	}
-	spin_unlock(&redirect_lock);
-
-	if (p) {
-		ssize_t res;
-		res = vfs_write(p, buf, count, &p->f_pos);
-		fput(p);
-		return res;
-	}
-	return tty_write(file, buf, count, ppos);
-}
-
-static char ptychar[] = "pqrstuvwxyzabcde";
-
-/**
- *	pty_line_name	-	generate name for a pty
- *	@driver: the tty driver in use
- *	@index: the minor number
- *	@p: output buffer of at least 6 bytes
- *
- *	Generate a name from a driver reference and write it to the output
- *	buffer.
- *
- *	Locking: None
- */
-static void pty_line_name(struct tty_driver *driver, int index, char *p)
-{
-	int i = index + driver->name_base;
-	/* ->name is initialized to "ttyp", but "tty" is expected */
-	sprintf(p, "%s%c%x",
-		driver->subtype == PTY_TYPE_SLAVE ? "tty" : driver->name,
-		ptychar[i >> 4 & 0xf], i & 0xf);
-}
-
-/**
- *	tty_line_name	-	generate name for a tty
- *	@driver: the tty driver in use
- *	@index: the minor number
- *	@p: output buffer of at least 7 bytes
- *
- *	Generate a name from a driver reference and write it to the output
- *	buffer.
- *
- *	Locking: None
- */
-static void tty_line_name(struct tty_driver *driver, int index, char *p)
-{
-	sprintf(p, "%s%d", driver->name, index + driver->name_base);
-}
-
-/**
- *	tty_driver_lookup_tty() - find an existing tty, if any
- *	@driver: the driver for the tty
- *	@idx:	 the minor number
- *
- *	Return the tty, if found or ERR_PTR() otherwise.
- *
- *	Locking: tty_mutex must be held. If tty is found, the mutex must
- *	be held until the 'fast-open' is also done. Will change once we
- *	have refcounting in the driver and per driver locking
- */
-static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
-		struct inode *inode, int idx)
-{
-	struct tty_struct *tty;
-
-	if (driver->ops->lookup)
-		return driver->ops->lookup(driver, inode, idx);
-
-	tty = driver->ttys[idx];
-	return tty;
-}
-
-/**
- *	tty_init_termios	-  helper for termios setup
- *	@tty: the tty to set up
- *
- *	Initialise the termios structures for this tty. Thus runs under
- *	the tty_mutex currently so we can be relaxed about ordering.
- */
-
-int tty_init_termios(struct tty_struct *tty)
-{
-	struct ktermios *tp;
-	int idx = tty->index;
-
-	tp = tty->driver->termios[idx];
-	if (tp == NULL) {
-		tp = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
-		if (tp == NULL)
-			return -ENOMEM;
-		memcpy(tp, &tty->driver->init_termios,
-						sizeof(struct ktermios));
-		tty->driver->termios[idx] = tp;
-	}
-	tty->termios = tp;
-	tty->termios_locked = tp + 1;
-
-	/* Compatibility until drivers always set this */
-	tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
-	tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(tty_init_termios);
-
-/**
- *	tty_driver_install_tty() - install a tty entry in the driver
- *	@driver: the driver for the tty
- *	@tty: the tty
- *
- *	Install a tty object into the driver tables. The tty->index field
- *	will be set by the time this is called. This method is responsible
- *	for ensuring any need additional structures are allocated and
- *	configured.
- *
- *	Locking: tty_mutex for now
- */
-static int tty_driver_install_tty(struct tty_driver *driver,
-						struct tty_struct *tty)
-{
-	int idx = tty->index;
-	int ret;
-
-	if (driver->ops->install) {
-		lock_kernel();
-		ret = driver->ops->install(driver, tty);
-		unlock_kernel();
-		return ret;
-	}
-
-	if (tty_init_termios(tty) == 0) {
-		lock_kernel();
-		tty_driver_kref_get(driver);
-		tty->count++;
-		driver->ttys[idx] = tty;
-		unlock_kernel();
-		return 0;
-	}
-	return -ENOMEM;
-}
-
-/**
- *	tty_driver_remove_tty() - remove a tty from the driver tables
- *	@driver: the driver for the tty
- *	@idx:	 the minor number
- *
- *	Remvoe a tty object from the driver tables. The tty->index field
- *	will be set by the time this is called.
- *
- *	Locking: tty_mutex for now
- */
-static void tty_driver_remove_tty(struct tty_driver *driver,
-						struct tty_struct *tty)
-{
-	if (driver->ops->remove)
-		driver->ops->remove(driver, tty);
-	else
-		driver->ttys[tty->index] = NULL;
-}
-
-/*
- * 	tty_reopen()	- fast re-open of an open tty
- * 	@tty	- the tty to open
- *
- *	Return 0 on success, -errno on error.
- *
- *	Locking: tty_mutex must be held from the time the tty was found
- *		 till this open completes.
- */
-static int tty_reopen(struct tty_struct *tty)
-{
-	struct tty_driver *driver = tty->driver;
-
-	if (test_bit(TTY_CLOSING, &tty->flags))
-		return -EIO;
-
-	if (driver->type == TTY_DRIVER_TYPE_PTY &&
-	    driver->subtype == PTY_TYPE_MASTER) {
-		/*
-		 * special case for PTY masters: only one open permitted,
-		 * and the slave side open count is incremented as well.
-		 */
-		if (tty->count)
-			return -EIO;
-
-		tty->link->count++;
-	}
-	tty->count++;
-	tty->driver = driver; /* N.B. why do this every time?? */
-
-	mutex_lock(&tty->ldisc_mutex);
-	WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
-	mutex_unlock(&tty->ldisc_mutex);
-
-	return 0;
-}
-
-/**
- *	tty_init_dev		-	initialise a tty device
- *	@driver: tty driver we are opening a device on
- *	@idx: device index
- *	@ret_tty: returned tty structure
- *	@first_ok: ok to open a new device (used by ptmx)
- *
- *	Prepare a tty device. This may not be a "new" clean device but
- *	could also be an active device. The pty drivers require special
- *	handling because of this.
- *
- *	Locking:
- *		The function is called under the tty_mutex, which
- *	protects us from the tty struct or driver itself going away.
- *
- *	On exit the tty device has the line discipline attached and
- *	a reference count of 1. If a pair was created for pty/tty use
- *	and the other was a pty master then it too has a reference count of 1.
- *
- * WSH 06/09/97: Rewritten to remove races and properly clean up after a
- * failed open.  The new code protects the open with a mutex, so it's
- * really quite straightforward.  The mutex locking can probably be
- * relaxed for the (most common) case of reopening a tty.
- */
-
-struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
-								int first_ok)
-{
-	struct tty_struct *tty;
-	int retval;
-
-	lock_kernel();
-	/* Check if pty master is being opened multiple times */
-	if (driver->subtype == PTY_TYPE_MASTER &&
-		(driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
-		unlock_kernel();
-		return ERR_PTR(-EIO);
-	}
-	unlock_kernel();
-
-	/*
-	 * First time open is complex, especially for PTY devices.
-	 * This code guarantees that either everything succeeds and the
-	 * TTY is ready for operation, or else the table slots are vacated
-	 * and the allocated memory released.  (Except that the termios
-	 * and locked termios may be retained.)
-	 */
-
-	if (!try_module_get(driver->owner))
-		return ERR_PTR(-ENODEV);
-
-	tty = alloc_tty_struct();
-	if (!tty)
-		goto fail_no_mem;
-	initialize_tty_struct(tty, driver, idx);
-
-	retval = tty_driver_install_tty(driver, tty);
-	if (retval < 0) {
-		free_tty_struct(tty);
-		module_put(driver->owner);
-		return ERR_PTR(retval);
-	}
-
-	/*
-	 * Structures all installed ... call the ldisc open routines.
-	 * If we fail here just call release_tty to clean up.  No need
-	 * to decrement the use counts, as release_tty doesn't care.
-	 */
-	retval = tty_ldisc_setup(tty, tty->link);
-	if (retval)
-		goto release_mem_out;
-	return tty;
-
-fail_no_mem:
-	module_put(driver->owner);
-	return ERR_PTR(-ENOMEM);
-
-	/* call the tty release_tty routine to clean out this slot */
-release_mem_out:
-	if (printk_ratelimit())
-		printk(KERN_INFO "tty_init_dev: ldisc open failed, "
-				 "clearing slot %d\n", idx);
-	lock_kernel();
-	release_tty(tty, idx);
-	unlock_kernel();
-	return ERR_PTR(retval);
-}
-
-void tty_free_termios(struct tty_struct *tty)
-{
-	struct ktermios *tp;
-	int idx = tty->index;
-	/* Kill this flag and push into drivers for locking etc */
-	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-		/* FIXME: Locking on ->termios array */
-		tp = tty->termios;
-		tty->driver->termios[idx] = NULL;
-		kfree(tp);
-	}
-}
-EXPORT_SYMBOL(tty_free_termios);
-
-void tty_shutdown(struct tty_struct *tty)
-{
-	tty_driver_remove_tty(tty->driver, tty);
-	tty_free_termios(tty);
-}
-EXPORT_SYMBOL(tty_shutdown);
-
-/**
- *	release_one_tty		-	release tty structure memory
- *	@kref: kref of tty we are obliterating
- *
- *	Releases memory associated with a tty structure, and clears out the
- *	driver table slots. This function is called when a device is no longer
- *	in use. It also gets called when setup of a device fails.
- *
- *	Locking:
- *		tty_mutex - sometimes only
- *		takes the file list lock internally when working on the list
- *	of ttys that the driver keeps.
- *
- *	This method gets called from a work queue so that the driver private
- *	cleanup ops can sleep (needed for USB at least)
- */
-static void release_one_tty(struct work_struct *work)
-{
-	struct tty_struct *tty =
-		container_of(work, struct tty_struct, hangup_work);
-	struct tty_driver *driver = tty->driver;
-
-	if (tty->ops->cleanup)
-		tty->ops->cleanup(tty);
-
-	tty->magic = 0;
-	tty_driver_kref_put(driver);
-	module_put(driver->owner);
-
-	file_list_lock();
-	list_del_init(&tty->tty_files);
-	file_list_unlock();
-
-	put_pid(tty->pgrp);
-	put_pid(tty->session);
-	free_tty_struct(tty);
-}
-
-static void queue_release_one_tty(struct kref *kref)
-{
-	struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
-
-	if (tty->ops->shutdown)
-		tty->ops->shutdown(tty);
-	else
-		tty_shutdown(tty);
-
-	/* The hangup queue is now free so we can reuse it rather than
-	   waste a chunk of memory for each port */
-	INIT_WORK(&tty->hangup_work, release_one_tty);
-	schedule_work(&tty->hangup_work);
-}
-
-/**
- *	tty_kref_put		-	release a tty kref
- *	@tty: tty device
- *
- *	Release a reference to a tty device and if need be let the kref
- *	layer destruct the object for us
- */
-
-void tty_kref_put(struct tty_struct *tty)
-{
-	if (tty)
-		kref_put(&tty->kref, queue_release_one_tty);
-}
-EXPORT_SYMBOL(tty_kref_put);
-
-/**
- *	release_tty		-	release tty structure memory
- *
- *	Release both @tty and a possible linked partner (think pty pair),
- *	and decrement the refcount of the backing module.
- *
- *	Locking:
- *		tty_mutex - sometimes only
- *		takes the file list lock internally when working on the list
- *	of ttys that the driver keeps.
- *		FIXME: should we require tty_mutex is held here ??
- *
- */
-static void release_tty(struct tty_struct *tty, int idx)
-{
-	/* This should always be true but check for the moment */
-	WARN_ON(tty->index != idx);
-
-	if (tty->link)
-		tty_kref_put(tty->link);
-	tty_kref_put(tty);
-}
-
-/**
- *	tty_release		-	vfs callback for close
- *	@inode: inode of tty
- *	@filp: file pointer for handle to tty
- *
- *	Called the last time each file handle is closed that references
- *	this tty. There may however be several such references.
- *
- *	Locking:
- *		Takes bkl. See tty_release_dev
- *
- * Even releasing the tty structures is a tricky business.. We have
- * to be very careful that the structures are all released at the
- * same time, as interrupts might otherwise get the wrong pointers.
- *
- * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
- * lead to double frees or releasing memory still in use.
- */
-
-int tty_release(struct inode *inode, struct file *filp)
-{
-	struct tty_struct *tty, *o_tty;
-	int	pty_master, tty_closing, o_tty_closing, do_sleep;
-	int	devpts;
-	int	idx;
-	char	buf[64];
-
-	tty = (struct tty_struct *)filp->private_data;
-	if (tty_paranoia_check(tty, inode, "tty_release_dev"))
-		return 0;
-
-	lock_kernel();
-	check_tty_count(tty, "tty_release_dev");
-
-	tty_fasync(-1, filp, 0);
-
-	idx = tty->index;
-	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
-		      tty->driver->subtype == PTY_TYPE_MASTER);
-	devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
-	o_tty = tty->link;
-
-#ifdef TTY_PARANOIA_CHECK
-	if (idx < 0 || idx >= tty->driver->num) {
-		printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
-				  "free (%s)\n", tty->name);
-		unlock_kernel();
-		return 0;
-	}
-	if (!devpts) {
-		if (tty != tty->driver->ttys[idx]) {
-			unlock_kernel();
-			printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
-			       "for (%s)\n", idx, tty->name);
-			return 0;
-		}
-		if (tty->termios != tty->driver->termios[idx]) {
-			unlock_kernel();
-			printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
-			       "for (%s)\n",
-			       idx, tty->name);
-			return 0;
-		}
-	}
-#endif
-
-#ifdef TTY_DEBUG_HANGUP
-	printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...",
-	       tty_name(tty, buf), tty->count);
-#endif
-
-#ifdef TTY_PARANOIA_CHECK
-	if (tty->driver->other &&
-	     !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
-		if (o_tty != tty->driver->other->ttys[idx]) {
-			unlock_kernel();
-			printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
-					  "not o_tty for (%s)\n",
-			       idx, tty->name);
-			return 0 ;
-		}
-		if (o_tty->termios != tty->driver->other->termios[idx]) {
-			unlock_kernel();
-			printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
-					  "not o_termios for (%s)\n",
-			       idx, tty->name);
-			return 0;
-		}
-		if (o_tty->link != tty) {
-			unlock_kernel();
-			printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
-			return 0;
-		}
-	}
-#endif
-	if (tty->ops->close)
-		tty->ops->close(tty, filp);
-
-	unlock_kernel();
-	/*
-	 * Sanity check: if tty->count is going to zero, there shouldn't be
-	 * any waiters on tty->read_wait or tty->write_wait.  We test the
-	 * wait queues and kick everyone out _before_ actually starting to
-	 * close.  This ensures that we won't block while releasing the tty
-	 * structure.
-	 *
-	 * The test for the o_tty closing is necessary, since the master and
-	 * slave sides may close in any order.  If the slave side closes out
-	 * first, its count will be one, since the master side holds an open.
-	 * Thus this test wouldn't be triggered at the time the slave closes,
-	 * so we do it now.
-	 *
-	 * Note that it's possible for the tty to be opened again while we're
-	 * flushing out waiters.  By recalculating the closing flags before
-	 * each iteration we avoid any problems.
-	 */
-	while (1) {
-		/* Guard against races with tty->count changes elsewhere and
-		   opens on /dev/tty */
-
-		mutex_lock(&tty_mutex);
-		lock_kernel();
-		tty_closing = tty->count <= 1;
-		o_tty_closing = o_tty &&
-			(o_tty->count <= (pty_master ? 1 : 0));
-		do_sleep = 0;
-
-		if (tty_closing) {
-			if (waitqueue_active(&tty->read_wait)) {
-				wake_up_poll(&tty->read_wait, POLLIN);
-				do_sleep++;
-			}
-			if (waitqueue_active(&tty->write_wait)) {
-				wake_up_poll(&tty->write_wait, POLLOUT);
-				do_sleep++;
-			}
-		}
-		if (o_tty_closing) {
-			if (waitqueue_active(&o_tty->read_wait)) {
-				wake_up_poll(&o_tty->read_wait, POLLIN);
-				do_sleep++;
-			}
-			if (waitqueue_active(&o_tty->write_wait)) {
-				wake_up_poll(&o_tty->write_wait, POLLOUT);
-				do_sleep++;
-			}
-		}
-		if (!do_sleep)
-			break;
-
-		printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
-				    "active!\n", tty_name(tty, buf));
-		unlock_kernel();
-		mutex_unlock(&tty_mutex);
-		schedule();
-	}
-
-	/*
-	 * The closing flags are now consistent with the open counts on
-	 * both sides, and we've completed the last operation that could
-	 * block, so it's safe to proceed with closing.
-	 */
-	if (pty_master) {
-		if (--o_tty->count < 0) {
-			printk(KERN_WARNING "tty_release_dev: bad pty slave count "
-					    "(%d) for %s\n",
-			       o_tty->count, tty_name(o_tty, buf));
-			o_tty->count = 0;
-		}
-	}
-	if (--tty->count < 0) {
-		printk(KERN_WARNING "tty_release_dev: bad tty->count (%d) for %s\n",
-		       tty->count, tty_name(tty, buf));
-		tty->count = 0;
-	}
-
-	/*
-	 * We've decremented tty->count, so we need to remove this file
-	 * descriptor off the tty->tty_files list; this serves two
-	 * purposes:
-	 *  - check_tty_count sees the correct number of file descriptors
-	 *    associated with this tty.
-	 *  - do_tty_hangup no longer sees this file descriptor as
-	 *    something that needs to be handled for hangups.
-	 */
-	file_kill(filp);
-	filp->private_data = NULL;
-
-	/*
-	 * Perform some housekeeping before deciding whether to return.
-	 *
-	 * Set the TTY_CLOSING flag if this was the last open.  In the
-	 * case of a pty we may have to wait around for the other side
-	 * to close, and TTY_CLOSING makes sure we can't be reopened.
-	 */
-	if (tty_closing)
-		set_bit(TTY_CLOSING, &tty->flags);
-	if (o_tty_closing)
-		set_bit(TTY_CLOSING, &o_tty->flags);
-
-	/*
-	 * If _either_ side is closing, make sure there aren't any
-	 * processes that still think tty or o_tty is their controlling
-	 * tty.
-	 */
-	if (tty_closing || o_tty_closing) {
-		read_lock(&tasklist_lock);
-		session_clear_tty(tty->session);
-		if (o_tty)
-			session_clear_tty(o_tty->session);
-		read_unlock(&tasklist_lock);
-	}
-
-	mutex_unlock(&tty_mutex);
-
-	/* check whether both sides are closing ... */
-	if (!tty_closing || (o_tty && !o_tty_closing)) {
-		unlock_kernel();
-		return 0;
-	}
-
-#ifdef TTY_DEBUG_HANGUP
-	printk(KERN_DEBUG "freeing tty structure...");
-#endif
-	/*
-	 * Ask the line discipline code to release its structures
-	 */
-	tty_ldisc_release(tty, o_tty);
-	/*
-	 * The release_tty function takes care of the details of clearing
-	 * the slots and preserving the termios structure.
-	 */
-	release_tty(tty, idx);
-
-	/* Make this pty number available for reallocation */
-	if (devpts)
-		devpts_kill_index(inode, idx);
-	unlock_kernel();
-	return 0;
-}
-
-/**
- *	tty_open		-	open a tty device
- *	@inode: inode of device file
- *	@filp: file pointer to tty
- *
- *	tty_open and tty_release keep up the tty count that contains the
- *	number of opens done on a tty. We cannot use the inode-count, as
- *	different inodes might point to the same tty.
- *
- *	Open-counting is needed for pty masters, as well as for keeping
- *	track of serial lines: DTR is dropped when the last close happens.
- *	(This is not done solely through tty->count, now.  - Ted 1/27/92)
- *
- *	The termios state of a pty is reset on first open so that
- *	settings don't persist across reuse.
- *
- *	Locking: tty_mutex protects tty, get_tty_driver and tty_init_dev work.
- *		 tty->count should protect the rest.
- *		 ->siglock protects ->signal/->sighand
- */
-
-static int tty_open(struct inode *inode, struct file *filp)
-{
-	struct tty_struct *tty = NULL;
-	int noctty, retval;
-	struct tty_driver *driver;
-	int index;
-	dev_t device = inode->i_rdev;
-	unsigned saved_flags = filp->f_flags;
-
-	nonseekable_open(inode, filp);
-
-retry_open:
-	noctty = filp->f_flags & O_NOCTTY;
-	index  = -1;
-	retval = 0;
-
-	mutex_lock(&tty_mutex);
-	lock_kernel();
-
-	if (device == MKDEV(TTYAUX_MAJOR, 0)) {
-		tty = get_current_tty();
-		if (!tty) {
-			unlock_kernel();
-			mutex_unlock(&tty_mutex);
-			return -ENXIO;
-		}
-		driver = tty_driver_kref_get(tty->driver);
-		index = tty->index;
-		filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
-		/* noctty = 1; */
-		/* FIXME: Should we take a driver reference ? */
-		tty_kref_put(tty);
-		goto got_driver;
-	}
-#ifdef CONFIG_VT
-	if (device == MKDEV(TTY_MAJOR, 0)) {
-		extern struct tty_driver *console_driver;
-		driver = tty_driver_kref_get(console_driver);
-		index = fg_console;
-		noctty = 1;
-		goto got_driver;
-	}
-#endif
-	if (device == MKDEV(TTYAUX_MAJOR, 1)) {
-		struct tty_driver *console_driver = console_device(&index);
-		if (console_driver) {
-			driver = tty_driver_kref_get(console_driver);
-			if (driver) {
-				/* Don't let /dev/console block */
-				filp->f_flags |= O_NONBLOCK;
-				noctty = 1;
-				goto got_driver;
-			}
-		}
-		unlock_kernel();
-		mutex_unlock(&tty_mutex);
-		return -ENODEV;
-	}
-
-	driver = get_tty_driver(device, &index);
-	if (!driver) {
-		unlock_kernel();
-		mutex_unlock(&tty_mutex);
-		return -ENODEV;
-	}
-got_driver:
-	if (!tty) {
-		/* check whether we're reopening an existing tty */
-		tty = tty_driver_lookup_tty(driver, inode, index);
-
-		if (IS_ERR(tty)) {
-			unlock_kernel();
-			mutex_unlock(&tty_mutex);
-			return PTR_ERR(tty);
-		}
-	}
-
-	if (tty) {
-		retval = tty_reopen(tty);
-		if (retval)
-			tty = ERR_PTR(retval);
-	} else
-		tty = tty_init_dev(driver, index, 0);
-
-	mutex_unlock(&tty_mutex);
-	tty_driver_kref_put(driver);
-	if (IS_ERR(tty)) {
-		unlock_kernel();
-		return PTR_ERR(tty);
-	}
-
-	filp->private_data = tty;
-	file_move(filp, &tty->tty_files);
-	check_tty_count(tty, "tty_open");
-	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
-	    tty->driver->subtype == PTY_TYPE_MASTER)
-		noctty = 1;
-#ifdef TTY_DEBUG_HANGUP
-	printk(KERN_DEBUG "opening %s...", tty->name);
-#endif
-	if (!retval) {
-		if (tty->ops->open)
-			retval = tty->ops->open(tty, filp);
-		else
-			retval = -ENODEV;
-	}
-	filp->f_flags = saved_flags;
-
-	if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) &&
-						!capable(CAP_SYS_ADMIN))
-		retval = -EBUSY;
-
-	if (retval) {
-#ifdef TTY_DEBUG_HANGUP
-		printk(KERN_DEBUG "error %d in opening %s...", retval,
-		       tty->name);
-#endif
-		tty_release(inode, filp);
-		if (retval != -ERESTARTSYS) {
-			unlock_kernel();
-			return retval;
-		}
-		if (signal_pending(current)) {
-			unlock_kernel();
-			return retval;
-		}
-		schedule();
-		/*
-		 * Need to reset f_op in case a hangup happened.
-		 */
-		if (filp->f_op == &hung_up_tty_fops)
-			filp->f_op = &tty_fops;
-		unlock_kernel();
-		goto retry_open;
-	}
-	unlock_kernel();
-
-
-	mutex_lock(&tty_mutex);
-	lock_kernel();
-	spin_lock_irq(&current->sighand->siglock);
-	if (!noctty &&
-	    current->signal->leader &&
-	    !current->signal->tty &&
-	    tty->session == NULL)
-		__proc_set_tty(current, tty);
-	spin_unlock_irq(&current->sighand->siglock);
-	unlock_kernel();
-	mutex_unlock(&tty_mutex);
-	return 0;
-}
-
-
-
-/**
- *	tty_poll	-	check tty status
- *	@filp: file being polled
- *	@wait: poll wait structures to update
- *
- *	Call the line discipline polling method to obtain the poll
- *	status of the device.
- *
- *	Locking: locks called line discipline but ldisc poll method
- *	may be re-entered freely by other callers.
- */
-
-static unsigned int tty_poll(struct file *filp, poll_table *wait)
-{
-	struct tty_struct *tty;
-	struct tty_ldisc *ld;
-	int ret = 0;
-
-	tty = (struct tty_struct *)filp->private_data;
-	if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
-		return 0;
-
-	ld = tty_ldisc_ref_wait(tty);
-	if (ld->ops->poll)
-		ret = (ld->ops->poll)(tty, filp, wait);
-	tty_ldisc_deref(ld);
-	return ret;
-}
-
-static int tty_fasync(int fd, struct file *filp, int on)
-{
-	struct tty_struct *tty;
-	unsigned long flags;
-	int retval = 0;
-
-	lock_kernel();
-	tty = (struct tty_struct *)filp->private_data;
-	if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
-		goto out;
-
-	retval = fasync_helper(fd, filp, on, &tty->fasync);
-	if (retval <= 0)
-		goto out;
-
-	if (on) {
-		enum pid_type type;
-		struct pid *pid;
-		if (!waitqueue_active(&tty->read_wait))
-			tty->minimum_to_wake = 1;
-		spin_lock_irqsave(&tty->ctrl_lock, flags);
-		if (tty->pgrp) {
-			pid = tty->pgrp;
-			type = PIDTYPE_PGID;
-		} else {
-			pid = task_pid(current);
-			type = PIDTYPE_PID;
-		}
-		get_pid(pid);
-		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-		retval = __f_setown(filp, pid, type, 0);
-		put_pid(pid);
-		if (retval)
-			goto out;
-	} else {
-		if (!tty->fasync && !waitqueue_active(&tty->read_wait))
-			tty->minimum_to_wake = N_TTY_BUF_SIZE;
-	}
-	retval = 0;
-out:
-	unlock_kernel();
-	return retval;
-}
-
-/**
- *	tiocsti			-	fake input character
- *	@tty: tty to fake input into
- *	@p: pointer to character
- *
- *	Fake input to a tty device. Does the necessary locking and
- *	input management.
- *
- *	FIXME: does not honour flow control ??
- *
- *	Locking:
- *		Called functions take tty_ldisc_lock
- *		current->signal->tty check is safe without locks
- *
- *	FIXME: may race normal receive processing
- */
-
-static int tiocsti(struct tty_struct *tty, char __user *p)
-{
-	char ch, mbz = 0;
-	struct tty_ldisc *ld;
-
-	if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	if (get_user(ch, p))
-		return -EFAULT;
-	tty_audit_tiocsti(tty, ch);
-	ld = tty_ldisc_ref_wait(tty);
-	ld->ops->receive_buf(tty, &ch, &mbz, 1);
-	tty_ldisc_deref(ld);
-	return 0;
-}
-
-/**
- *	tiocgwinsz		-	implement window query ioctl
- *	@tty; tty
- *	@arg: user buffer for result
- *
- *	Copies the kernel idea of the window size into the user buffer.
- *
- *	Locking: tty->termios_mutex is taken to ensure the winsize data
- *		is consistent.
- */
-
-static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
-{
-	int err;
-
-	mutex_lock(&tty->termios_mutex);
-	err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
-	mutex_unlock(&tty->termios_mutex);
-
-	return err ? -EFAULT: 0;
-}
-
-/**
- *	tty_do_resize		-	resize event
- *	@tty: tty being resized
- *	@rows: rows (character)
- *	@cols: cols (character)
- *
- *	Update the termios variables and send the necessary signals to
- *	peform a terminal resize correctly
- */
-
-int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
-{
-	struct pid *pgrp;
-	unsigned long flags;
-
-	/* Lock the tty */
-	mutex_lock(&tty->termios_mutex);
-	if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
-		goto done;
-	/* Get the PID values and reference them so we can
-	   avoid holding the tty ctrl lock while sending signals */
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
-	pgrp = get_pid(tty->pgrp);
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
-	if (pgrp)
-		kill_pgrp(pgrp, SIGWINCH, 1);
-	put_pid(pgrp);
-
-	tty->winsize = *ws;
-done:
-	mutex_unlock(&tty->termios_mutex);
-	return 0;
-}
-
-/**
- *	tiocswinsz		-	implement window size set ioctl
- *	@tty; tty side of tty
- *	@arg: user buffer for result
- *
- *	Copies the user idea of the window size to the kernel. Traditionally
- *	this is just advisory information but for the Linux console it
- *	actually has driver level meaning and triggers a VC resize.
- *
- *	Locking:
- *		Driver dependant. The default do_resize method takes the
- *	tty termios mutex and ctrl_lock. The console takes its own lock
- *	then calls into the default method.
- */
-
-static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg)
-{
-	struct winsize tmp_ws;
-	if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
-		return -EFAULT;
-
-	if (tty->ops->resize)
-		return tty->ops->resize(tty, &tmp_ws);
-	else
-		return tty_do_resize(tty, &tmp_ws);
-}
-
-/**
- *	tioccons	-	allow admin to move logical console
- *	@file: the file to become console
- *
- *	Allow the adminstrator to move the redirected console device
- *
- *	Locking: uses redirect_lock to guard the redirect information
- */
-
-static int tioccons(struct file *file)
-{
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	if (file->f_op->write == redirected_tty_write) {
-		struct file *f;
-		spin_lock(&redirect_lock);
-		f = redirect;
-		redirect = NULL;
-		spin_unlock(&redirect_lock);
-		if (f)
-			fput(f);
-		return 0;
-	}
-	spin_lock(&redirect_lock);
-	if (redirect) {
-		spin_unlock(&redirect_lock);
-		return -EBUSY;
-	}
-	get_file(file);
-	redirect = file;
-	spin_unlock(&redirect_lock);
-	return 0;
-}
-
-/**
- *	fionbio		-	non blocking ioctl
- *	@file: file to set blocking value
- *	@p: user parameter
- *
- *	Historical tty interfaces had a blocking control ioctl before
- *	the generic functionality existed. This piece of history is preserved
- *	in the expected tty API of posix OS's.
- *
- *	Locking: none, the open file handle ensures it won't go away.
- */
-
-static int fionbio(struct file *file, int __user *p)
-{
-	int nonblock;
-
-	if (get_user(nonblock, p))
-		return -EFAULT;
-
-	spin_lock(&file->f_lock);
-	if (nonblock)
-		file->f_flags |= O_NONBLOCK;
-	else
-		file->f_flags &= ~O_NONBLOCK;
-	spin_unlock(&file->f_lock);
-	return 0;
-}
-
-/**
- *	tiocsctty	-	set controlling tty
- *	@tty: tty structure
- *	@arg: user argument
- *
- *	This ioctl is used to manage job control. It permits a session
- *	leader to set this tty as the controlling tty for the session.
- *
- *	Locking:
- *		Takes tty_mutex() to protect tty instance
- *		Takes tasklist_lock internally to walk sessions
- *		Takes ->siglock() when updating signal->tty
- */
-
-static int tiocsctty(struct tty_struct *tty, int arg)
-{
-	int ret = 0;
-	if (current->signal->leader && (task_session(current) == tty->session))
-		return ret;
-
-	mutex_lock(&tty_mutex);
-	/*
-	 * The process must be a session leader and
-	 * not have a controlling tty already.
-	 */
-	if (!current->signal->leader || current->signal->tty) {
-		ret = -EPERM;
-		goto unlock;
-	}
-
-	if (tty->session) {
-		/*
-		 * This tty is already the controlling
-		 * tty for another session group!
-		 */
-		if (arg == 1 && capable(CAP_SYS_ADMIN)) {
-			/*
-			 * Steal it away
-			 */
-			read_lock(&tasklist_lock);
-			session_clear_tty(tty->session);
-			read_unlock(&tasklist_lock);
-		} else {
-			ret = -EPERM;
-			goto unlock;
-		}
-	}
-	proc_set_tty(current, tty);
-unlock:
-	mutex_unlock(&tty_mutex);
-	return ret;
-}
-
-/**
- *	tty_get_pgrp	-	return a ref counted pgrp pid
- *	@tty: tty to read
- *
- *	Returns a refcounted instance of the pid struct for the process
- *	group controlling the tty.
- */
-
-struct pid *tty_get_pgrp(struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct pid *pgrp;
-
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
-	pgrp = get_pid(tty->pgrp);
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
-	return pgrp;
-}
-EXPORT_SYMBOL_GPL(tty_get_pgrp);
-
-/**
- *	tiocgpgrp		-	get process group
- *	@tty: tty passed by user
- *	@real_tty: tty side of the tty pased by the user if a pty else the tty
- *	@p: returned pid
- *
- *	Obtain the process group of the tty. If there is no process group
- *	return an error.
- *
- *	Locking: none. Reference to current->signal->tty is safe.
- */
-
-static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
-	struct pid *pid;
-	int ret;
-	/*
-	 * (tty == real_tty) is a cheap way of
-	 * testing if the tty is NOT a master pty.
-	 */
-	if (tty == real_tty && current->signal->tty != real_tty)
-		return -ENOTTY;
-	pid = tty_get_pgrp(real_tty);
-	ret =  put_user(pid_vnr(pid), p);
-	put_pid(pid);
-	return ret;
-}
-
-/**
- *	tiocspgrp		-	attempt to set process group
- *	@tty: tty passed by user
- *	@real_tty: tty side device matching tty passed by user
- *	@p: pid pointer
- *
- *	Set the process group of the tty to the session passed. Only
- *	permitted where the tty session is our session.
- *
- *	Locking: RCU, ctrl lock
- */
-
-static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
-	struct pid *pgrp;
-	pid_t pgrp_nr;
-	int retval = tty_check_change(real_tty);
-	unsigned long flags;
-
-	if (retval == -EIO)
-		return -ENOTTY;
-	if (retval)
-		return retval;
-	if (!current->signal->tty ||
-	    (current->signal->tty != real_tty) ||
-	    (real_tty->session != task_session(current)))
-		return -ENOTTY;
-	if (get_user(pgrp_nr, p))
-		return -EFAULT;
-	if (pgrp_nr < 0)
-		return -EINVAL;
-	rcu_read_lock();
-	pgrp = find_vpid(pgrp_nr);
-	retval = -ESRCH;
-	if (!pgrp)
-		goto out_unlock;
-	retval = -EPERM;
-	if (session_of_pgrp(pgrp) != task_session(current))
-		goto out_unlock;
-	retval = 0;
-	spin_lock_irqsave(&tty->ctrl_lock, flags);
-	put_pid(real_tty->pgrp);
-	real_tty->pgrp = get_pid(pgrp);
-	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-out_unlock:
-	rcu_read_unlock();
-	return retval;
-}
-
-/**
- *	tiocgsid		-	get session id
- *	@tty: tty passed by user
- *	@real_tty: tty side of the tty pased by the user if a pty else the tty
- *	@p: pointer to returned session id
- *
- *	Obtain the session id of the tty. If there is no session
- *	return an error.
- *
- *	Locking: none. Reference to current->signal->tty is safe.
- */
-
-static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
-	/*
-	 * (tty == real_tty) is a cheap way of
-	 * testing if the tty is NOT a master pty.
-	*/
-	if (tty == real_tty && current->signal->tty != real_tty)
-		return -ENOTTY;
-	if (!real_tty->session)
-		return -ENOTTY;
-	return put_user(pid_vnr(real_tty->session), p);
-}
-
-/**
- *	tiocsetd	-	set line discipline
- *	@tty: tty device
- *	@p: pointer to user data
- *
- *	Set the line discipline according to user request.
- *
- *	Locking: see tty_set_ldisc, this function is just a helper
- */
-
-static int tiocsetd(struct tty_struct *tty, int __user *p)
-{
-	int ldisc;
-	int ret;
-
-	if (get_user(ldisc, p))
-		return -EFAULT;
-
-	ret = tty_set_ldisc(tty, ldisc);
-
-	return ret;
-}
-
-/**
- *	send_break	-	performed time break
- *	@tty: device to break on
- *	@duration: timeout in mS
- *
- *	Perform a timed break on hardware that lacks its own driver level
- *	timed break functionality.
- *
- *	Locking:
- *		atomic_write_lock serializes
- *
- */
-
-static int send_break(struct tty_struct *tty, unsigned int duration)
-{
-	int retval;
-
-	if (tty->ops->break_ctl == NULL)
-		return 0;
-
-	if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
-		retval = tty->ops->break_ctl(tty, duration);
-	else {
-		/* Do the work ourselves */
-		if (tty_write_lock(tty, 0) < 0)
-			return -EINTR;
-		retval = tty->ops->break_ctl(tty, -1);
-		if (retval)
-			goto out;
-		if (!signal_pending(current))
-			msleep_interruptible(duration);
-		retval = tty->ops->break_ctl(tty, 0);
-out:
-		tty_write_unlock(tty);
-		if (signal_pending(current))
-			retval = -EINTR;
-	}
-	return retval;
-}
-
-/**
- *	tty_tiocmget		-	get modem status
- *	@tty: tty device
- *	@file: user file pointer
- *	@p: pointer to result
- *
- *	Obtain the modem status bits from the tty driver if the feature
- *	is supported. Return -EINVAL if it is not available.
- *
- *	Locking: none (up to the driver)
- */
-
-static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
-{
-	int retval = -EINVAL;
-
-	if (tty->ops->tiocmget) {
-		retval = tty->ops->tiocmget(tty, file);
-
-		if (retval >= 0)
-			retval = put_user(retval, p);
-	}
-	return retval;
-}
-
-/**
- *	tty_tiocmset		-	set modem status
- *	@tty: tty device
- *	@file: user file pointer
- *	@cmd: command - clear bits, set bits or set all
- *	@p: pointer to desired bits
- *
- *	Set the modem status bits from the tty driver if the feature
- *	is supported. Return -EINVAL if it is not available.
- *
- *	Locking: none (up to the driver)
- */
-
-static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
-	     unsigned __user *p)
-{
-	int retval;
-	unsigned int set, clear, val;
-
-	if (tty->ops->tiocmset == NULL)
-		return -EINVAL;
-
-	retval = get_user(val, p);
-	if (retval)
-		return retval;
-	set = clear = 0;
-	switch (cmd) {
-	case TIOCMBIS:
-		set = val;
-		break;
-	case TIOCMBIC:
-		clear = val;
-		break;
-	case TIOCMSET:
-		set = val;
-		clear = ~val;
-		break;
-	}
-	set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP|TIOCM_CD|
-		TIOCM_RI|TIOCM_DSR|TIOCM_CTS;
-	clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP|TIOCM_CD|
-		TIOCM_RI|TIOCM_DSR|TIOCM_CTS;
-	return tty->ops->tiocmset(tty, file, set, clear);
-}
-
-struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
-{
-	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
-	    tty->driver->subtype == PTY_TYPE_MASTER)
-		tty = tty->link;
-	return tty;
-}
-EXPORT_SYMBOL(tty_pair_get_tty);
-
-struct tty_struct *tty_pair_get_pty(struct tty_struct *tty)
-{
-	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
-	    tty->driver->subtype == PTY_TYPE_MASTER)
-	    return tty;
-	return tty->link;
-}
-EXPORT_SYMBOL(tty_pair_get_pty);
-
-/*
- * Split this up, as gcc can choke on it otherwise..
- */
-long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct tty_struct *tty, *real_tty;
-	void __user *p = (void __user *)arg;
-	int retval;
-	struct tty_ldisc *ld;
-	struct inode *inode = file->f_dentry->d_inode;
-
-	tty = (struct tty_struct *)file->private_data;
-	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
-		return -EINVAL;
-
-	real_tty = tty_pair_get_tty(tty);
-
-	/*
-	 * Factor out some common prep work
-	 */
-	switch (cmd) {
-	case TIOCSETD:
-	case TIOCSBRK:
-	case TIOCCBRK:
-	case TCSBRK:
-	case TCSBRKP:
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		if (cmd != TIOCCBRK) {
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-		}
-		break;
-	}
-
-	/*
-	 *	Now do the stuff.
-	 */
-	switch (cmd) {
-	case TIOCSTI:
-		return tiocsti(tty, p);
-	case TIOCGWINSZ:
-		return tiocgwinsz(real_tty, p);
-	case TIOCSWINSZ:
-		return tiocswinsz(real_tty, p);
-	case TIOCCONS:
-		return real_tty != tty ? -EINVAL : tioccons(file);
-	case FIONBIO:
-		return fionbio(file, p);
-	case TIOCEXCL:
-		set_bit(TTY_EXCLUSIVE, &tty->flags);
-		return 0;
-	case TIOCNXCL:
-		clear_bit(TTY_EXCLUSIVE, &tty->flags);
-		return 0;
-	case TIOCNOTTY:
-		if (current->signal->tty != tty)
-			return -ENOTTY;
-		no_tty();
-		return 0;
-	case TIOCSCTTY:
-		return tiocsctty(tty, arg);
-	case TIOCGPGRP:
-		return tiocgpgrp(tty, real_tty, p);
-	case TIOCSPGRP:
-		return tiocspgrp(tty, real_tty, p);
-	case TIOCGSID:
-		return tiocgsid(tty, real_tty, p);
-	case TIOCGETD:
-		return put_user(tty->ldisc->ops->num, (int __user *)p);
-	case TIOCSETD:
-		return tiocsetd(tty, p);
-	/*
-	 * Break handling
-	 */
-	case TIOCSBRK:	/* Turn break on, unconditionally */
-		if (tty->ops->break_ctl)
-			return tty->ops->break_ctl(tty, -1);
-		return 0;
-	case TIOCCBRK:	/* Turn break off, unconditionally */
-		if (tty->ops->break_ctl)
-			return tty->ops->break_ctl(tty, 0);
-		return 0;
-	case TCSBRK:   /* SVID version: non-zero arg --> no break */
-		/* non-zero arg means wait for all output data
-		 * to be sent (performed above) but don't send break.
-		 * This is used by the tcdrain() termios function.
-		 */
-		if (!arg)
-			return send_break(tty, 250);
-		return 0;
-	case TCSBRKP:	/* support for POSIX tcsendbreak() */
-		return send_break(tty, arg ? arg*100 : 250);
-
-	case TIOCMGET:
-		return tty_tiocmget(tty, file, p);
-	case TIOCMSET:
-	case TIOCMBIC:
-	case TIOCMBIS:
-		return tty_tiocmset(tty, file, cmd, p);
-	case TCFLSH:
-		switch (arg) {
-		case TCIFLUSH:
-		case TCIOFLUSH:
-		/* flush tty buffer and allow ldisc to process ioctl */
-			tty_buffer_flush(tty);
-			break;
-		}
-		break;
-	}
-	if (tty->ops->ioctl) {
-		retval = (tty->ops->ioctl)(tty, file, cmd, arg);
-		if (retval != -ENOIOCTLCMD)
-			return retval;
-	}
-	ld = tty_ldisc_ref_wait(tty);
-	retval = -EINVAL;
-	if (ld->ops->ioctl) {
-		retval = ld->ops->ioctl(tty, file, cmd, arg);
-		if (retval == -ENOIOCTLCMD)
-			retval = -EINVAL;
-	}
-	tty_ldisc_deref(ld);
-	return retval;
-}
-
-#ifdef CONFIG_COMPAT
-static long tty_compat_ioctl(struct file *file, unsigned int cmd,
-				unsigned long arg)
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	struct tty_struct *tty = file->private_data;
-	struct tty_ldisc *ld;
-	int retval = -ENOIOCTLCMD;
-
-	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
-		return -EINVAL;
-
-	if (tty->ops->compat_ioctl) {
-		retval = (tty->ops->compat_ioctl)(tty, file, cmd, arg);
-		if (retval != -ENOIOCTLCMD)
-			return retval;
-	}
-
-	ld = tty_ldisc_ref_wait(tty);
-	if (ld->ops->compat_ioctl)
-		retval = ld->ops->compat_ioctl(tty, file, cmd, arg);
-	tty_ldisc_deref(ld);
-
-	return retval;
-}
-#endif
-
-/*
- * This implements the "Secure Attention Key" ---  the idea is to
- * prevent trojan horses by killing all processes associated with this
- * tty when the user hits the "Secure Attention Key".  Required for
- * super-paranoid applications --- see the Orange Book for more details.
- *
- * This code could be nicer; ideally it should send a HUP, wait a few
- * seconds, then send a INT, and then a KILL signal.  But you then
- * have to coordinate with the init process, since all processes associated
- * with the current tty must be dead before the new getty is allowed
- * to spawn.
- *
- * Now, if it would be correct ;-/ The current code has a nasty hole -
- * it doesn't catch files in flight. We may send the descriptor to ourselves
- * via AF_UNIX socket, close it and later fetch from socket. FIXME.
- *
- * Nasty bug: do_SAK is being called in interrupt context.  This can
- * deadlock.  We punt it up to process context.  AKPM - 16Mar2001
- */
-void __do_SAK(struct tty_struct *tty)
-{
-#ifdef TTY_SOFT_SAK
-	tty_hangup(tty);
-#else
-	struct task_struct *g, *p;
-	struct pid *session;
-	int		i;
-	struct file	*filp;
-	struct fdtable *fdt;
-
-	if (!tty)
-		return;
-	session = tty->session;
-
-	tty_ldisc_flush(tty);
-
-	tty_driver_flush_buffer(tty);
-
-	read_lock(&tasklist_lock);
-	/* Kill the entire session */
-	do_each_pid_task(session, PIDTYPE_SID, p) {
-		printk(KERN_NOTICE "SAK: killed process %d"
-			" (%s): task_session(p)==tty->session\n",
-			task_pid_nr(p), p->comm);
-		send_sig(SIGKILL, p, 1);
-	} while_each_pid_task(session, PIDTYPE_SID, p);
-	/* Now kill any processes that happen to have the
-	 * tty open.
-	 */
-	do_each_thread(g, p) {
-		if (p->signal->tty == tty) {
-			printk(KERN_NOTICE "SAK: killed process %d"
-			    " (%s): task_session(p)==tty->session\n",
-			    task_pid_nr(p), p->comm);
-			send_sig(SIGKILL, p, 1);
-			continue;
-		}
-		task_lock(p);
-		if (p->files) {
-			/*
-			 * We don't take a ref to the file, so we must
-			 * hold ->file_lock instead.
-			 */
-			spin_lock(&p->files->file_lock);
-			fdt = files_fdtable(p->files);
-			for (i = 0; i < fdt->max_fds; i++) {
-				filp = fcheck_files(p->files, i);
-				if (!filp)
-					continue;
-				if (filp->f_op->read == tty_read &&
-				    filp->private_data == tty) {
-					printk(KERN_NOTICE "SAK: killed process %d"
-					    " (%s): fd#%d opened to the tty\n",
-					    task_pid_nr(p), p->comm, i);
-					force_sig(SIGKILL, p);
-					break;
-				}
-			}
-			spin_unlock(&p->files->file_lock);
-		}
-		task_unlock(p);
-	} while_each_thread(g, p);
-	read_unlock(&tasklist_lock);
-#endif
-}
-
-static void do_SAK_work(struct work_struct *work)
-{
-	struct tty_struct *tty =
-		container_of(work, struct tty_struct, SAK_work);
-	__do_SAK(tty);
-}
-
-/*
- * The tq handling here is a little racy - tty->SAK_work may already be queued.
- * Fortunately we don't need to worry, because if ->SAK_work is already queued,
- * the values which we write to it will be identical to the values which it
- * already has. --akpm
- */
-void do_SAK(struct tty_struct *tty)
-{
-	if (!tty)
-		return;
-	schedule_work(&tty->SAK_work);
-}
-
-EXPORT_SYMBOL(do_SAK);
-
-/**
- *	initialize_tty_struct
- *	@tty: tty to initialize
- *
- *	This subroutine initializes a tty structure that has been newly
- *	allocated.
- *
- *	Locking: none - tty in question must not be exposed at this point
- */
-
-void initialize_tty_struct(struct tty_struct *tty,
-		struct tty_driver *driver, int idx)
-{
-	memset(tty, 0, sizeof(struct tty_struct));
-	kref_init(&tty->kref);
-	tty->magic = TTY_MAGIC;
-	tty_ldisc_init(tty);
-	tty->session = NULL;
-	tty->pgrp = NULL;
-	tty->overrun_time = jiffies;
-	tty->buf.head = tty->buf.tail = NULL;
-	tty_buffer_init(tty);
-	mutex_init(&tty->termios_mutex);
-	mutex_init(&tty->ldisc_mutex);
-	init_waitqueue_head(&tty->write_wait);
-	init_waitqueue_head(&tty->read_wait);
-	INIT_WORK(&tty->hangup_work, do_tty_hangup);
-	mutex_init(&tty->atomic_read_lock);
-	mutex_init(&tty->atomic_write_lock);
-	mutex_init(&tty->output_lock);
-	mutex_init(&tty->echo_lock);
-	spin_lock_init(&tty->read_lock);
-	spin_lock_init(&tty->ctrl_lock);
-	INIT_LIST_HEAD(&tty->tty_files);
-	INIT_WORK(&tty->SAK_work, do_SAK_work);
-
-	tty->driver = driver;
-	tty->ops = driver->ops;
-	tty->index = idx;
-	tty_line_name(driver, idx, tty->name);
-}
-
-/**
- *	tty_put_char	-	write one character to a tty
- *	@tty: tty
- *	@ch: character
- *
- *	Write one byte to the tty using the provided put_char method
- *	if present. Returns the number of characters successfully output.
- *
- *	Note: the specific put_char operation in the driver layer may go
- *	away soon. Don't call it directly, use this method
- */
-
-int tty_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	if (tty->ops->put_char)
-		return tty->ops->put_char(tty, ch);
-	return tty->ops->write(tty, &ch, 1);
-}
-EXPORT_SYMBOL_GPL(tty_put_char);
-
-struct class *tty_class;
-
-/**
- *	tty_register_device - register a tty device
- *	@driver: the tty driver that describes the tty device
- *	@index: the index in the tty driver for this tty device
- *	@device: a struct device that is associated with this tty device.
- *		This field is optional, if there is no known struct device
- *		for this tty device it can be set to NULL safely.
- *
- *	Returns a pointer to the struct device for this tty device
- *	(or ERR_PTR(-EFOO) on error).
- *
- *	This call is required to be made to register an individual tty device
- *	if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set.  If
- *	that bit is not set, this function should not be called by a tty
- *	driver.
- *
- *	Locking: ??
- */
-
-struct device *tty_register_device(struct tty_driver *driver, unsigned index,
-				   struct device *device)
-{
-	char name[64];
-	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
-
-	if (index >= driver->num) {
-		printk(KERN_ERR "Attempt to register invalid tty line number "
-		       " (%d).\n", index);
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (driver->type == TTY_DRIVER_TYPE_PTY)
-		pty_line_name(driver, index, name);
-	else
-		tty_line_name(driver, index, name);
-
-	return device_create(tty_class, device, dev, NULL, name);
-}
-EXPORT_SYMBOL(tty_register_device);
-
-/**
- * 	tty_unregister_device - unregister a tty device
- * 	@driver: the tty driver that describes the tty device
- * 	@index: the index in the tty driver for this tty device
- *
- * 	If a tty device is registered with a call to tty_register_device() then
- *	this function must be called when the tty device is gone.
- *
- *	Locking: ??
- */
-
-void tty_unregister_device(struct tty_driver *driver, unsigned index)
-{
-	device_destroy(tty_class,
-		MKDEV(driver->major, driver->minor_start) + index);
-}
-EXPORT_SYMBOL(tty_unregister_device);
-
-struct tty_driver *alloc_tty_driver(int lines)
-{
-	struct tty_driver *driver;
-
-	driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
-	if (driver) {
-		kref_init(&driver->kref);
-		driver->magic = TTY_DRIVER_MAGIC;
-		driver->num = lines;
-		/* later we'll move allocation of tables here */
-	}
-	return driver;
-}
-EXPORT_SYMBOL(alloc_tty_driver);
-
-static void destruct_tty_driver(struct kref *kref)
-{
-	struct tty_driver *driver = container_of(kref, struct tty_driver, kref);
-	int i;
-	struct ktermios *tp;
-	void *p;
-
-	if (driver->flags & TTY_DRIVER_INSTALLED) {
-		/*
-		 * Free the termios and termios_locked structures because
-		 * we don't want to get memory leaks when modular tty
-		 * drivers are removed from the kernel.
-		 */
-		for (i = 0; i < driver->num; i++) {
-			tp = driver->termios[i];
-			if (tp) {
-				driver->termios[i] = NULL;
-				kfree(tp);
-			}
-			if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
-				tty_unregister_device(driver, i);
-		}
-		p = driver->ttys;
-		proc_tty_unregister_driver(driver);
-		driver->ttys = NULL;
-		driver->termios = NULL;
-		kfree(p);
-		cdev_del(&driver->cdev);
-	}
-	kfree(driver);
-}
-
-void tty_driver_kref_put(struct tty_driver *driver)
-{
-	kref_put(&driver->kref, destruct_tty_driver);
-}
-EXPORT_SYMBOL(tty_driver_kref_put);
-
-void tty_set_operations(struct tty_driver *driver,
-			const struct tty_operations *op)
-{
-	driver->ops = op;
-};
-EXPORT_SYMBOL(tty_set_operations);
-
-void put_tty_driver(struct tty_driver *d)
-{
-	tty_driver_kref_put(d);
-}
-EXPORT_SYMBOL(put_tty_driver);
-
-/*
- * Called by a tty driver to register itself.
- */
-int tty_register_driver(struct tty_driver *driver)
-{
-	int error;
-	int i;
-	dev_t dev;
-	void **p = NULL;
-
-	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
-		p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
-		if (!p)
-			return -ENOMEM;
-	}
-
-	if (!driver->major) {
-		error = alloc_chrdev_region(&dev, driver->minor_start,
-						driver->num, driver->name);
-		if (!error) {
-			driver->major = MAJOR(dev);
-			driver->minor_start = MINOR(dev);
-		}
-	} else {
-		dev = MKDEV(driver->major, driver->minor_start);
-		error = register_chrdev_region(dev, driver->num, driver->name);
-	}
-	if (error < 0) {
-		kfree(p);
-		return error;
-	}
-
-	if (p) {
-		driver->ttys = (struct tty_struct **)p;
-		driver->termios = (struct ktermios **)(p + driver->num);
-	} else {
-		driver->ttys = NULL;
-		driver->termios = NULL;
-	}
-
-	cdev_init(&driver->cdev, &tty_fops);
-	driver->cdev.owner = driver->owner;
-	error = cdev_add(&driver->cdev, dev, driver->num);
-	if (error) {
-		unregister_chrdev_region(dev, driver->num);
-		driver->ttys = NULL;
-		driver->termios = NULL;
-		kfree(p);
-		return error;
-	}
-
-	mutex_lock(&tty_mutex);
-	list_add(&driver->tty_drivers, &tty_drivers);
-	mutex_unlock(&tty_mutex);
-
-	if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
-		for (i = 0; i < driver->num; i++)
-		    tty_register_device(driver, i, NULL);
-	}
-	proc_tty_register_driver(driver);
-	driver->flags |= TTY_DRIVER_INSTALLED;
-	return 0;
-}
-
-EXPORT_SYMBOL(tty_register_driver);
-
-/*
- * Called by a tty driver to unregister itself.
- */
-int tty_unregister_driver(struct tty_driver *driver)
-{
-#if 0
-	/* FIXME */
-	if (driver->refcount)
-		return -EBUSY;
-#endif
-	unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
-				driver->num);
-	mutex_lock(&tty_mutex);
-	list_del(&driver->tty_drivers);
-	mutex_unlock(&tty_mutex);
-	return 0;
-}
-
-EXPORT_SYMBOL(tty_unregister_driver);
-
-dev_t tty_devnum(struct tty_struct *tty)
-{
-	return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
-}
-EXPORT_SYMBOL(tty_devnum);
-
-void proc_clear_tty(struct task_struct *p)
-{
-	unsigned long flags;
-	struct tty_struct *tty;
-	spin_lock_irqsave(&p->sighand->siglock, flags);
-	tty = p->signal->tty;
-	p->signal->tty = NULL;
-	spin_unlock_irqrestore(&p->sighand->siglock, flags);
-	tty_kref_put(tty);
-}
-
-/* Called under the sighand lock */
-
-static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
-{
-	if (tty) {
-		unsigned long flags;
-		/* We should not have a session or pgrp to put here but.... */
-		spin_lock_irqsave(&tty->ctrl_lock, flags);
-		put_pid(tty->session);
-		put_pid(tty->pgrp);
-		tty->pgrp = get_pid(task_pgrp(tsk));
-		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-		tty->session = get_pid(task_session(tsk));
-		if (tsk->signal->tty) {
-			printk(KERN_DEBUG "tty not NULL!!\n");
-			tty_kref_put(tsk->signal->tty);
-		}
-	}
-	put_pid(tsk->signal->tty_old_pgrp);
-	tsk->signal->tty = tty_kref_get(tty);
-	tsk->signal->tty_old_pgrp = NULL;
-}
-
-static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
-{
-	spin_lock_irq(&tsk->sighand->siglock);
-	__proc_set_tty(tsk, tty);
-	spin_unlock_irq(&tsk->sighand->siglock);
-}
-
-struct tty_struct *get_current_tty(void)
-{
-	struct tty_struct *tty;
-	unsigned long flags;
-
-	spin_lock_irqsave(&current->sighand->siglock, flags);
-	tty = tty_kref_get(current->signal->tty);
-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
-	return tty;
-}
-EXPORT_SYMBOL_GPL(get_current_tty);
-
-void tty_default_fops(struct file_operations *fops)
-{
-	*fops = tty_fops;
-}
-
-/*
- * Initialize the console device. This is called *early*, so
- * we can't necessarily depend on lots of kernel help here.
- * Just do some early initializations, and do the complex setup
- * later.
- */
-void __init console_init(void)
-{
-	initcall_t *call;
-
-	/* Setup the default TTY line discipline. */
-	tty_ldisc_begin();
-
-	/*
-	 * set up the console device so that later boot sequences can
-	 * inform about problems etc..
-	 */
-	call = __con_initcall_start;
-	while (call < __con_initcall_end) {
-		(*call)();
-		call++;
-	}
-}
-
-static char *tty_devnode(struct device *dev, mode_t *mode)
-{
-	if (!mode)
-		return NULL;
-	if (dev->devt == MKDEV(TTYAUX_MAJOR, 0) ||
-	    dev->devt == MKDEV(TTYAUX_MAJOR, 2))
-		*mode = 0666;
-	return NULL;
-}
-
-static int __init tty_class_init(void)
-{
-	tty_class = class_create(THIS_MODULE, "tty");
-	if (IS_ERR(tty_class))
-		return PTR_ERR(tty_class);
-	tty_class->devnode = tty_devnode;
-	return 0;
-}
-
-postcore_initcall(tty_class_init);
-
-/* 3/2004 jmc: why do these devices exist? */
-
-static struct cdev tty_cdev, console_cdev;
-
-/*
- * Ok, now we can initialize the rest of the tty devices and can count
- * on memory allocations, interrupts etc..
- */
-int __init tty_init(void)
-{
-	cdev_init(&tty_cdev, &tty_fops);
-	if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
-	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
-		panic("Couldn't register /dev/tty driver\n");
-	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
-			      "tty");
-
-	cdev_init(&console_cdev, &console_fops);
-	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
-	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
-		panic("Couldn't register /dev/console driver\n");
-	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
-			      "console");
-
-#ifdef CONFIG_VT
-	vty_init(&console_fops);
-#endif
-	return 0;
-}
-
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 3157a86..ec38843 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -163,15 +163,6 @@
 {
 	int mult = 1;
 
-	/* for higher loadavg, we are more reluctant */
-
-	/*
-	 * this doesn't work as intended - it is almost always 0, but can
-	 * sometimes, depending on workload, spike very high into the hundreds
-	 * even when the average cpu load is under 10%.
-	 */
-	/* mult += 2 * get_loadavg(); */
-
 	/* for IO wait tasks (per cpu!) we add 5x each */
 	mult += 10 * nr_iowait_cpu(smp_processor_id());
 
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 1facf24..9d8e825 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -353,6 +353,9 @@
 	pce = cmdlistinfo->auth_seg_size;
 	pce->data = sreq->size;
 
+	pce = cmdlistinfo->encr_seg_cfg;
+	pce->data = 0;
+
 	/* write auth seg size start*/
 	pce = cmdlistinfo->auth_seg_start;
 	pce->data = 0;
@@ -521,8 +524,12 @@
 			pce->data = totallen_in - creq->authsize;
 		pce = cmdlistinfo->auth_seg_start;
 		pce->data = 0;
+	} else {
+		if (creq->op != QCE_REQ_AEAD) {
+			pce = cmdlistinfo->auth_seg_cfg;
+			pce->data = 0;
+		}
 	}
-
 	switch (creq->mode) {
 	case QCE_MODE_ECB:
 		encr_cfg |= (CRYPTO_ENCR_MODE_ECB << CRYPTO_ENCR_MODE);
@@ -1289,7 +1296,7 @@
 					CRYPTO_RESULT_DUMP_SIZE,
 					  &pce_dev->ce_sps.out_transfer);
 		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
-				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+				SPS_IOVEC_FLAG_INT);
 		rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
 					  &pce_dev->ce_sps.out_transfer);
 		if (rc) {
@@ -1364,7 +1371,7 @@
 					CRYPTO_RESULT_DUMP_SIZE,
 					  &pce_dev->ce_sps.out_transfer);
 		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
-				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+				SPS_IOVEC_FLAG_INT);
 		rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
 					  &pce_dev->ce_sps.out_transfer);
 		if (rc) {
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 0904f9fe..9ab2343 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -914,7 +914,7 @@
 		if (type == ION_HEAP_TYPE_SYSTEM_CONTIG ||
 			type == ION_HEAP_TYPE_CARVEOUT ||
 			type == (enum ion_heap_type) ION_HEAP_TYPE_CP)
-			seq_printf(s, " : %12lx", handle->buffer->priv_phys);
+			seq_printf(s, " : %12pa", &handle->buffer->priv_phys);
 		else
 			seq_printf(s, " : %12s", "N/A");
 
@@ -1988,8 +1988,8 @@
 		ret = memblock_reserve(data->heaps[i].base,
 				       data->heaps[i].size);
 		if (ret)
-			pr_err("memblock reserve of %x@%lx failed\n",
+			pr_err("memblock reserve of %x@%pa failed\n",
 			       data->heaps[i].size,
-			       data->heaps[i].base);
+			       &data->heaps[i].base);
 	}
 }
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 3e55a57..b51fa6a 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -297,8 +297,11 @@
 			const char *client_name = "(null)";
 
 			if (last_end < data->addr) {
-				seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-					   "FREE", last_end, data->addr-1,
+				phys_addr_t da;
+
+				da = data->addr-1;
+				seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+					   "FREE", &last_end, &da,
 					   data->addr-last_end,
 					   data->addr-last_end);
 			}
@@ -306,9 +309,9 @@
 			if (data->client_name)
 				client_name = data->client_name;
 
-			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-				   client_name, data->addr,
-				   data->addr_end,
+			seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+				   client_name, &data->addr,
+				   &data->addr_end,
 				   data->size, data->size);
 			last_end = data->addr_end+1;
 		}
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c
index 4f5ac75..8063138 100644
--- a/drivers/gpu/ion/ion_cma_heap.c
+++ b/drivers/gpu/ion/ion_cma_heap.c
@@ -325,9 +325,9 @@
 			if (data->client_name)
 				client_name = data->client_name;
 
-			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-				   client_name, data->addr,
-				   data->addr_end,
+			seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+				   client_name, &data->addr,
+				   &data->addr_end,
 				   data->size, data->size);
 		}
 	}
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index 2c0e5ae..496e5b4 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -359,9 +359,9 @@
 			if (data->client_name)
 				client_name = data->client_name;
 
-			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-				   client_name, data->addr,
-				   data->addr_end,
+			seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+				   client_name, &data->addr,
+				   &data->addr_end,
 				   data->size, data->size);
 		}
 	}
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 56ccc8f..a7473e2 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -256,8 +256,8 @@
 			atomic_dec(&cp_heap->protect_cnt);
 		} else {
 			cp_heap->heap_protected = HEAP_PROTECTED;
-			pr_debug("Protected heap %s @ 0x%lx\n",
-				heap->name, cp_heap->base);
+			pr_debug("Protected heap %s @ 0x%pa\n",
+				heap->name, &cp_heap->base);
 		}
 	}
 out:
@@ -804,8 +804,11 @@
 			const char *client_name = "(null)";
 
 			if (last_end < data->addr) {
-				seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-					   "FREE", last_end, data->addr-1,
+				phys_addr_t da;
+
+				da = data->addr-1;
+				seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+					   "FREE", &last_end, &da,
 					   data->addr-last_end,
 					   data->addr-last_end);
 			}
@@ -813,9 +816,9 @@
 			if (data->client_name)
 				client_name = data->client_name;
 
-			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-				   client_name, data->addr,
-				   data->addr_end,
+			seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+				   client_name, &data->addr,
+				   &data->addr_end,
 				   data->size, data->size);
 			last_end = data->addr_end+1;
 		}
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index ff2b8dd..46fefb5 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -56,9 +56,9 @@
 	}
 
 	if (IS_ERR_OR_NULL(heap)) {
-		pr_err("%s: error creating heap %s type %d base %lu size %u\n",
+		pr_err("%s: error creating heap %s type %d base %pa size %u\n",
 		       __func__, heap_data->name, heap_data->type,
-		       heap_data->base, heap_data->size);
+		       &heap_data->base, heap_data->size);
 		return ERR_PTR(-EINVAL);
 	}
 
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 9d1e90e..2ab2ed6 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -189,8 +189,8 @@
  */
 struct mem_map_data {
 	struct rb_node node;
-	unsigned long addr;
-	unsigned long addr_end;
+	ion_phys_addr_t addr;
+	ion_phys_addr_t addr_end;
 	unsigned long size;
 	const char *client_name;
 };
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 7840d87..bd27385 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -172,7 +172,7 @@
 }
 EXPORT_SYMBOL(msm_ion_do_cache_op);
 
-static unsigned long msm_ion_get_base(unsigned long size, int memory_type,
+static ion_phys_addr_t msm_ion_get_base(unsigned long size, int memory_type,
 				    unsigned int align)
 {
 	switch (memory_type) {
@@ -340,10 +340,10 @@
 static int is_heap_overlapping(const struct ion_platform_heap *heap1,
 				const struct ion_platform_heap *heap2)
 {
-	unsigned long heap1_base = heap1->base;
-	unsigned long heap2_base = heap2->base;
-	unsigned long heap1_end = heap1->base + heap1->size - 1;
-	unsigned long heap2_end = heap2->base + heap2->size - 1;
+	ion_phys_addr_t heap1_base = heap1->base;
+	ion_phys_addr_t heap2_base = heap2->base;
+	ion_phys_addr_t heap1_end = heap1->base + heap1->size - 1;
+	ion_phys_addr_t heap2_end = heap2->base + heap2->size - 1;
 
 	if (heap1_base == heap2_base)
 		return 1;
@@ -792,9 +792,9 @@
 			continue;
 		} else {
 			if (heap_data->size)
-				pr_info("ION heap %s created at %lx "
+				pr_info("ION heap %s created at %pa "
 					"with size %x\n", heap_data->name,
-							  heap_data->base,
+							  &heap_data->base,
 							  heap_data->size);
 			else
 				pr_info("ION heap %s created\n",
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index c2b5f38..51ffd21 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -586,12 +586,16 @@
 	return 0;
 }
 
-static int epm_psoc_scale_result(uint32_t result, uint32_t index)
+static int epm_psoc_scale_result(int16_t result, uint32_t index)
 {
 	struct epm_adc_drv *epm_adc = epm_adc_drv;
-	int32_t result_cur;
+	int32_t result_cur, neg = 0;
 
 	if ((1 << index) & epm_adc->channel_mask) {
+		if (result & 0x800) {
+			neg = 1;
+			result = result & 0x7ff;
+		}
 		/* result = (2.048V * code)/(4096 * gain * rsense) */
 		result_cur = ((EPM_PSOC_VREF_VOLTAGE * result)/
 				EPM_PSOC_MAX_ADC_CODE_12_BIT);
@@ -599,14 +603,22 @@
 		result_cur = (result_cur/
 			(epm_adc->epm_psoc_ch_prop[index].gain *
 			epm_adc->epm_psoc_ch_prop[index].resistorvalue));
+		if (neg)
+			result_cur -= result_cur;
 	} else {
+		if (result & 0x8000) {
+			neg = 1;
+			result = result & 0x7fff;
+		}
 		/* result = (2.048V * code)/(32767 * gain * rsense) */
-		result_cur = (((EPM_PSOC_VREF_VOLTAGE * result)/
+		result_cur = (((EPM_PSOC_VREF_VOLTAGE * (int) result)/
 				EPM_PSOC_MAX_ADC_CODE_15_BIT) * 1000);
 
 		result_cur = (result_cur/
 		(epm_adc->epm_psoc_ch_prop[index].gain *
 			epm_adc->epm_psoc_ch_prop[index].resistorvalue));
+		if (neg)
+			result_cur -= result_cur;
 	}
 
 	return result_cur;
@@ -869,10 +881,8 @@
 	psoc_get_meas->timestamp_resp_value = (rx_buf[3] << 24) |
 			(rx_buf[4] << 16) | (rx_buf[5] << 8) |
 			rx_buf[6];
-	psoc_get_meas->reading_value = (rx_buf[7] << 8) | rx_buf[8];
+	psoc_get_meas->reading_raw = (rx_buf[7] << 8) | rx_buf[8];
 
-	pr_debug("dev_num:%d, chan_num:%d\n", rx_buf[1], rx_buf[2]);
-	pr_debug("data %d\n", psoc_get_meas->reading_value);
 	return rc;
 }
 
@@ -1336,7 +1346,7 @@
 			}
 
 			psoc_get_data.reading_value = epm_psoc_scale_result(
-				psoc_get_data.reading_value,
+				psoc_get_data.reading_raw,
 				psoc_get_data.chan_num);
 
 			if (copy_to_user((void __user *)arg, &psoc_get_data,
@@ -1753,8 +1763,6 @@
 	conv.device_idx = attr->index / pdata->chan_per_adc;
 	conv.channel_idx = attr->index % pdata->chan_per_adc;
 	conv.physical = 0;
-	pr_info("%s: device_idx=%d channel_idx=%d", __func__, conv.device_idx,
-			conv.channel_idx);
 
 	if (!epm_adc_expander_register) {
 		rc = epm_adc_i2c_expander_register();
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4c72b65..bfa48de 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -411,13 +411,6 @@
 	  To compile this driver as a module, choose M here; the
 	  module will be called opencores-kbd.
 
-config KEYBOARD_PM8058
-	bool "Qualcomm PM8058 Matrix Keypad support"
-	depends on PM8058
-	help
-	  Say Y here to enable the driver for the keypad matrix interface
-	  on the Qualcomm PM8058 power management I/C device.
-
 config KEYBOARD_PXA27x
 	tristate "PXA27x/PXA3xx keypad support"
 	depends on PXA27x || PXA3xx || ARCH_MMP
@@ -623,5 +616,3 @@
 	  module will be called w90p910_keypad.
 
 endif
-
-
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 833904a..85f1d86 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -54,4 +54,3 @@
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_QCIKBD)       += qci_kbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
-obj-$(CONFIG_KEYBOARD_PMIC8058)		+= pmic8058-keypad.o
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index ad43bbf..1f309d8 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -17,7 +17,6 @@
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR)	+= auo-pixcir-ts.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
-obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CYPRESS_TMG)	+= cy8c_tmg_ts.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)	+= bu21013_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)	+= cy8ctmg110_ts.o
@@ -29,7 +28,6 @@
 obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)	+= hampshire.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunze.o
 obj-$(CONFIG_TOUCHSCREEN_EETI)		+= eeti_ts.o
-obj-$(CONFIG_TOUCHSCREEN_ELAN_I2C_8232) += elan8232_i2c.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX)	+= egalax_ts.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 26e8496..f13e55a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -195,23 +195,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called leds-msm-tricolor.
 
-config LEDS_GPIO_PLATFORM
-	bool "Platform device bindings for GPIO LEDs"
-	depends on LEDS_GPIO
-	default y
-	help
-	  Let the leds-gpio driver drive LEDs which have been defined as
-	  platform devices.  If you don't know what this means, say yes.
-
-config LEDS_GPIO_OF
-	bool "OpenFirmware platform device bindings for GPIO LEDs"
-	depends on LEDS_GPIO && OF_DEVICE
-	default y
-	help
-	  Let the leds-gpio driver drive LEDs which have been defined as
-	  of_platform devices.  For instance, LEDs which are listed in a "dts"
-	  file.
-
 config LEDS_LP3944
 	tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
 	depends on LEDS_CLASS
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index da5db8b..d749d92 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -42,7 +42,7 @@
 	unsigned int idx_in;
 	unsigned int idx_out;
 	sector_t sector;
-	atomic_t cc_pending;
+	atomic_t pending;
 	struct ablkcipher_request *req;
 };
 
@@ -56,7 +56,7 @@
 
 	struct convert_context ctx;
 
-	atomic_t io_pending;
+	atomic_t pending;
 	int error;
 	sector_t sector;
 	struct dm_crypt_io *base_io;
@@ -740,14 +740,14 @@
 {
 	int r;
 
-	atomic_set(&ctx->cc_pending, 1);
+	atomic_set(&ctx->pending, 1);
 
 	while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
 	      ctx->idx_out < ctx->bio_out->bi_vcnt) {
 
 		crypt_alloc_req(cc, ctx);
 
-		atomic_inc(&ctx->cc_pending);
+		atomic_inc(&ctx->pending);
 
 		r = crypt_convert_block(cc, ctx, ctx->req);
 
@@ -764,14 +764,14 @@
 
 		/* sync */
 		case 0:
-			atomic_dec(&ctx->cc_pending);
+			atomic_dec(&ctx->pending);
 			ctx->sector++;
 			cond_resched();
 			continue;
 
 		/* error */
 		default:
-			atomic_dec(&ctx->cc_pending);
+			atomic_dec(&ctx->pending);
 			return r;
 		}
 	}
@@ -868,14 +868,14 @@
 	io->error = 0;
 	io->base_io = NULL;
 	io->ctx.req = NULL;
-	atomic_set(&io->io_pending, 0);
+	atomic_set(&io->pending, 0);
 
 	return io;
 }
 
 static void crypt_inc_pending(struct dm_crypt_io *io)
 {
-	atomic_inc(&io->io_pending);
+	atomic_inc(&io->pending);
 }
 
 /*
@@ -890,7 +890,7 @@
 	struct dm_crypt_io *base_io = io->base_io;
 	int error = io->error;
 
-	if (!atomic_dec_and_test(&io->io_pending))
+	if (!atomic_dec_and_test(&io->pending))
 		return;
 
 	if (io->ctx.req)
@@ -1080,7 +1080,8 @@
 		r = crypt_convert(cc, &io->ctx);
 		if (r < 0)
 			io->error = -EIO;
-		crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending);
+
+		crypt_finished = atomic_dec_and_test(&io->ctx.pending);
 
 		/* Encryption was already finished, submit io now */
 		if (crypt_finished) {
@@ -1151,11 +1152,10 @@
 			   io->sector);
 
 	r = crypt_convert(cc, &io->ctx);
-
 	if (r < 0)
 		io->error = -EIO;
 
-	if (atomic_dec_and_test(&io->ctx.cc_pending))
+	if (atomic_dec_and_test(&io->ctx.pending))
 		kcryptd_crypt_read_done(io);
 
 	crypt_dec_pending(io);
@@ -1182,7 +1182,7 @@
 
 	mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
 
-	if (!atomic_dec_and_test(&ctx->cc_pending))
+	if (!atomic_dec_and_test(&ctx->pending))
 		return;
 
 	if (bio_data_dir(io->base_bio) == READ)
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 5a61c5f..754f38f 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -770,11 +770,6 @@
 	if (!argc)
 		return 0;
 
-	if (argc > as->argc) {
-		ti->error = "not enough arguments for features";
-		return -EINVAL;
-	}
-
 	do {
 		arg_name = dm_shift_arg(as);
 		argc--;
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index ce65e3f..c99bed1 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -58,11 +58,8 @@
 
 obj-$(CONFIG_TIMPANI_CODEC)	+= timpani-codec.o
 
-ifdef CONFIG_TIMPANI_CODEC
 obj-$(CONFIG_TIMPANI_CODEC) += msm-adie-codec.o
-else ifdef CONFIG_MARIMBA_CODEC
 obj-$(CONFIG_MARIMBA_CODEC) += msm-adie-codec.o
-endif
 
 obj-$(CONFIG_TWL6030_PWM)	+= twl6030-pwm.o
 obj-$(CONFIG_TWL6040_CORE)	+= twl6040-core.o twl6040-irq.o
@@ -127,6 +124,10 @@
 obj-$(CONFIG_MFD_WL1273_CORE)	+= wl1273-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o
+obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o
+obj-$(CONFIG_MFD_PM8821_CORE) 	+= pm8821-core.o
+obj-$(CONFIG_MFD_PM8018_CORE) 	+= pm8018-core.o
+obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090)	+= tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE)	+= aat2870-core.o
@@ -135,11 +136,7 @@
 obj-$(CONFIG_MFD_S5M_CORE)	+= s5m-core.o s5m-irq.o
 obj-$(CONFIG_PMIC8058)		+= pmic8058.o
 obj-$(CONFIG_PMIC8901)		+= pmic8901.o
-obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o
-obj-$(CONFIG_MFD_PM8821_CORE) 	+= pm8821-core.o
-obj-$(CONFIG_MFD_PM8018_CORE) 	+= pm8018-core.o
 obj-$(CONFIG_MFD_PM8038_CORE) 	+= pm8038-core.o
-obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
 obj-$(CONFIG_MFD_PM8821_IRQ) 	+= pm8821-irq.o
 obj-$(CONFIG_MFD_PM8XXX_DEBUG) 	+= pm8xxx-debug.o
 obj-$(CONFIG_MFD_PM8XXX_PWM) 	+= pm8xxx-pwm.o
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b0222ec..f80f3f2 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,8 +54,6 @@
 obj-$(CONFIG_MAX8997_MUIC)	+= max8997-muic.o
 obj-$(CONFIG_WL127X_RFKILL)	+= wl127x-rfkill.o
 obj-$(CONFIG_SENSORS_AK8975)	+= akm8975.o
-obj-$(CONFIG_WL127X_RFKILL)	+= wl127x-rfkill.o
-obj-$(CONFIG_SENSORS_AK8975)	+= akm8975.o
 obj-$(CONFIG_TSIF) += msm_tsif.o
 msm_tsif-objs := tsif.o
 obj-$(CONFIG_TSIF_CHRDEV) += tsif_chrdev.o
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 07702b4..bea8428 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1023,7 +1023,7 @@
 	if (host->areq)
 		mmc_post_req(host, host->areq->mrq, 0);
 
-	/* Cancel a prepared request if it was not started. */
+	 /* Cancel a prepared request if it was not started. */
 	if ((err || start_err) && areq)
 		mmc_post_req(host, areq->mrq, -EINVAL);
 
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index fca3274..3d8ceb4 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -215,14 +215,14 @@
 
 	card->sdio_single_irq = NULL;
 	if ((card->host->caps & MMC_CAP_SDIO_IRQ) &&
-			card->host->sdio_irqs == 1)
+	    card->host->sdio_irqs == 1)
 		for (i = 0; i < card->sdio_funcs; i++) {
-			func = card->sdio_func[i];
-			if (func && func->irq_handler) {
-				card->sdio_single_irq = func;
-				break;
-			}
-		}
+		       func = card->sdio_func[i];
+		       if (func && func->irq_handler) {
+			       card->sdio_single_irq = func;
+			       break;
+		       }
+	       }
 }
 
 /**
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 315efbb..47b19c0 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3219,44 +3219,6 @@
 }
 EXPORT_SYMBOL(nand_scan_ident);
 
-static void nand_panic_wait(struct mtd_info *mtd)
-{
-	struct nand_chip *chip = mtd->priv;
-	int i;
-
-	if (chip->state != FL_READY)
-		for (i = 0; i < 40; i++) {
-			if (chip->dev_ready(mtd))
-				break;
-			mdelay(10);
-		}
-	chip->state = FL_READY;
-}
-
-static int nand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
-			    size_t *retlen, const u_char *buf)
-{
-	struct nand_chip *chip = mtd->priv;
-	int ret;
-
-	/* Do not allow reads past end of device */
-	if ((to + len) > mtd->size)
-		return -EINVAL;
-	if (!len)
-		return 0;
-
-	nand_panic_wait(mtd);
-
-	chip->ops.len = len;
-	chip->ops.datbuf = (uint8_t *)buf;
-	chip->ops.oobbuf = NULL;
-
-	ret = nand_do_write_ops(mtd, to, &chip->ops);
-
-	*retlen = chip->ops.retlen;
-	return ret;
-}
-
 
 /**
  * nand_scan_tail - [NAND Interface] Scan for the NAND device
diff --git a/drivers/net/pppolac.c b/drivers/net/pppolac.c
deleted file mode 100644
index a5d3d63..0000000
--- a/drivers/net/pppolac.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/* drivers/net/pppolac.c
- *
- * Driver for PPP on L2TP Access Concentrator / PPPoLAC Socket (RFC 2661)
- *
- * Copyright (C) 2009 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-/* This driver handles L2TP data packets between a UDP socket and a PPP channel.
- * The socket must keep connected, and only one session per socket is permitted.
- * Sequencing of outgoing packets is controlled by LNS. Incoming packets with
- * sequences are reordered within a sliding window of one second. Currently
- * reordering only happens when a packet is received. It is done for simplicity
- * since no additional locks or threads are required. This driver only works on
- * IPv4 due to the lack of UDP encapsulation support in IPv6. */
-
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/workqueue.h>
-#include <linux/skbuff.h>
-#include <linux/file.h>
-#include <linux/netdevice.h>
-#include <linux/net.h>
-#include <linux/udp.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_ppp.h>
-#include <linux/if_pppox.h>
-#include <linux/ppp_channel.h>
-#include <net/tcp_states.h>
-#include <asm/uaccess.h>
-
-#define L2TP_CONTROL_BIT	0x80
-#define L2TP_LENGTH_BIT		0x40
-#define L2TP_SEQUENCE_BIT	0x08
-#define L2TP_OFFSET_BIT		0x02
-#define L2TP_VERSION		0x02
-#define L2TP_VERSION_MASK	0x0F
-
-#define PPP_ADDR	0xFF
-#define PPP_CTRL	0x03
-
-union unaligned {
-	__u32 u32;
-} __attribute__((packed));
-
-static inline union unaligned *unaligned(void *ptr)
-{
-	return (union unaligned *)ptr;
-}
-
-struct meta {
-	__u32 sequence;
-	__u32 timestamp;
-};
-
-static inline struct meta *skb_meta(struct sk_buff *skb)
-{
-	return (struct meta *)skb->cb;
-}
-
-/******************************************************************************/
-
-static int pppolac_recv_core(struct sock *sk_udp, struct sk_buff *skb)
-{
-	struct sock *sk = (struct sock *)sk_udp->sk_user_data;
-	struct pppolac_opt *opt = &pppox_sk(sk)->proto.lac;
-	struct meta *meta = skb_meta(skb);
-	__u32 now = jiffies;
-	__u8 bits;
-	__u8 *ptr;
-
-	/* Drop the packet if L2TP header is missing. */
-	if (skb->len < sizeof(struct udphdr) + 6)
-		goto drop;
-
-	/* Put it back if it is a control packet. */
-	if (skb->data[sizeof(struct udphdr)] & L2TP_CONTROL_BIT)
-		return opt->backlog_rcv(sk_udp, skb);
-
-	/* Skip UDP header. */
-	skb_pull(skb, sizeof(struct udphdr));
-
-	/* Check the version. */
-	if ((skb->data[1] & L2TP_VERSION_MASK) != L2TP_VERSION)
-		goto drop;
-	bits = skb->data[0];
-	ptr = &skb->data[2];
-
-	/* Check the length if it is present. */
-	if (bits & L2TP_LENGTH_BIT) {
-		if ((ptr[0] << 8 | ptr[1]) != skb->len)
-			goto drop;
-		ptr += 2;
-	}
-
-	/* Skip all fields including optional ones. */
-	if (!skb_pull(skb, 6 + (bits & L2TP_SEQUENCE_BIT ? 4 : 0) +
-			(bits & L2TP_LENGTH_BIT ? 2 : 0) +
-			(bits & L2TP_OFFSET_BIT ? 2 : 0)))
-		goto drop;
-
-	/* Skip the offset padding if it is present. */
-	if (bits & L2TP_OFFSET_BIT &&
-			!skb_pull(skb, skb->data[-2] << 8 | skb->data[-1]))
-		goto drop;
-
-	/* Check the tunnel and the session. */
-	if (unaligned(ptr)->u32 != opt->local)
-		goto drop;
-
-	/* Check the sequence if it is present. */
-	if (bits & L2TP_SEQUENCE_BIT) {
-		meta->sequence = ptr[4] << 8 | ptr[5];
-		if ((__s16)(meta->sequence - opt->recv_sequence) < 0)
-			goto drop;
-	}
-
-	/* Skip PPP address and control if they are present. */
-	if (skb->len >= 2 && skb->data[0] == PPP_ADDR &&
-			skb->data[1] == PPP_CTRL)
-		skb_pull(skb, 2);
-
-	/* Fix PPP protocol if it is compressed. */
-	if (skb->len >= 1 && skb->data[0] & 1)
-		skb_push(skb, 1)[0] = 0;
-
-	/* Drop the packet if PPP protocol is missing. */
-	if (skb->len < 2)
-		goto drop;
-
-	/* Perform reordering if sequencing is enabled. */
-	atomic_set(&opt->sequencing, bits & L2TP_SEQUENCE_BIT);
-	if (bits & L2TP_SEQUENCE_BIT) {
-		struct sk_buff *skb1;
-
-		/* Insert the packet into receive queue in order. */
-		skb_set_owner_r(skb, sk);
-		skb_queue_walk(&sk->sk_receive_queue, skb1) {
-			struct meta *meta1 = skb_meta(skb1);
-			__s16 order = meta->sequence - meta1->sequence;
-			if (order == 0)
-				goto drop;
-			if (order < 0) {
-				meta->timestamp = meta1->timestamp;
-				skb_insert(skb1, skb, &sk->sk_receive_queue);
-				skb = NULL;
-				break;
-			}
-		}
-		if (skb) {
-			meta->timestamp = now;
-			skb_queue_tail(&sk->sk_receive_queue, skb);
-		}
-
-		/* Remove packets from receive queue as long as
-		 * 1. the receive buffer is full,
-		 * 2. they are queued longer than one second, or
-		 * 3. there are no missing packets before them. */
-		skb_queue_walk_safe(&sk->sk_receive_queue, skb, skb1) {
-			meta = skb_meta(skb);
-			if (atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
-					now - meta->timestamp < HZ &&
-					meta->sequence != opt->recv_sequence)
-				break;
-			skb_unlink(skb, &sk->sk_receive_queue);
-			opt->recv_sequence = (__u16)(meta->sequence + 1);
-			skb_orphan(skb);
-			ppp_input(&pppox_sk(sk)->chan, skb);
-		}
-		return NET_RX_SUCCESS;
-	}
-
-	/* Flush receive queue if sequencing is disabled. */
-	skb_queue_purge(&sk->sk_receive_queue);
-	skb_orphan(skb);
-	ppp_input(&pppox_sk(sk)->chan, skb);
-	return NET_RX_SUCCESS;
-drop:
-	kfree_skb(skb);
-	return NET_RX_DROP;
-}
-
-static int pppolac_recv(struct sock *sk_udp, struct sk_buff *skb)
-{
-	sock_hold(sk_udp);
-	sk_receive_skb(sk_udp, skb, 0);
-	return 0;
-}
-
-static struct sk_buff_head delivery_queue;
-
-static void pppolac_xmit_core(struct work_struct *delivery_work)
-{
-	mm_segment_t old_fs = get_fs();
-	struct sk_buff *skb;
-
-	set_fs(KERNEL_DS);
-	while ((skb = skb_dequeue(&delivery_queue))) {
-		struct sock *sk_udp = skb->sk;
-		struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
-		struct msghdr msg = {
-			.msg_iov = (struct iovec *)&iov,
-			.msg_iovlen = 1,
-			.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
-		};
-		sk_udp->sk_prot->sendmsg(NULL, sk_udp, &msg, skb->len);
-		kfree_skb(skb);
-	}
-	set_fs(old_fs);
-}
-
-static DECLARE_WORK(delivery_work, pppolac_xmit_core);
-
-static int pppolac_xmit(struct ppp_channel *chan, struct sk_buff *skb)
-{
-	struct sock *sk_udp = (struct sock *)chan->private;
-	struct pppolac_opt *opt = &pppox_sk(sk_udp->sk_user_data)->proto.lac;
-
-	/* Install PPP address and control. */
-	skb_push(skb, 2);
-	skb->data[0] = PPP_ADDR;
-	skb->data[1] = PPP_CTRL;
-
-	/* Install L2TP header. */
-	if (atomic_read(&opt->sequencing)) {
-		skb_push(skb, 10);
-		skb->data[0] = L2TP_SEQUENCE_BIT;
-		skb->data[6] = opt->xmit_sequence >> 8;
-		skb->data[7] = opt->xmit_sequence;
-		skb->data[8] = 0;
-		skb->data[9] = 0;
-		opt->xmit_sequence++;
-	} else {
-		skb_push(skb, 6);
-		skb->data[0] = 0;
-	}
-	skb->data[1] = L2TP_VERSION;
-	unaligned(&skb->data[2])->u32 = opt->remote;
-
-	/* Now send the packet via the delivery queue. */
-	skb_set_owner_w(skb, sk_udp);
-	skb_queue_tail(&delivery_queue, skb);
-	schedule_work(&delivery_work);
-	return 1;
-}
-
-/******************************************************************************/
-
-static struct ppp_channel_ops pppolac_channel_ops = {
-	.start_xmit = pppolac_xmit,
-};
-
-static int pppolac_connect(struct socket *sock, struct sockaddr *useraddr,
-	int addrlen, int flags)
-{
-	struct sock *sk = sock->sk;
-	struct pppox_sock *po = pppox_sk(sk);
-	struct sockaddr_pppolac *addr = (struct sockaddr_pppolac *)useraddr;
-	struct socket *sock_udp = NULL;
-	struct sock *sk_udp;
-	int error;
-
-	if (addrlen != sizeof(struct sockaddr_pppolac) ||
-			!addr->local.tunnel || !addr->local.session ||
-			!addr->remote.tunnel || !addr->remote.session) {
-		return -EINVAL;
-	}
-
-	lock_sock(sk);
-	error = -EALREADY;
-	if (sk->sk_state != PPPOX_NONE)
-		goto out;
-
-	sock_udp = sockfd_lookup(addr->udp_socket, &error);
-	if (!sock_udp)
-		goto out;
-	sk_udp = sock_udp->sk;
-	lock_sock(sk_udp);
-
-	/* Remove this check when IPv6 supports UDP encapsulation. */
-	error = -EAFNOSUPPORT;
-	if (sk_udp->sk_family != AF_INET)
-		goto out;
-	error = -EPROTONOSUPPORT;
-	if (sk_udp->sk_protocol != IPPROTO_UDP)
-		goto out;
-	error = -EDESTADDRREQ;
-	if (sk_udp->sk_state != TCP_ESTABLISHED)
-		goto out;
-	error = -EBUSY;
-	if (udp_sk(sk_udp)->encap_type || sk_udp->sk_user_data)
-		goto out;
-	if (!sk_udp->sk_bound_dev_if) {
-		struct dst_entry *dst = sk_dst_get(sk_udp);
-		error = -ENODEV;
-		if (!dst)
-			goto out;
-		sk_udp->sk_bound_dev_if = dst->dev->ifindex;
-		dst_release(dst);
-	}
-
-	po->chan.hdrlen = 12;
-	po->chan.private = sk_udp;
-	po->chan.ops = &pppolac_channel_ops;
-	po->chan.mtu = PPP_MRU - 80;
-	po->proto.lac.local = unaligned(&addr->local)->u32;
-	po->proto.lac.remote = unaligned(&addr->remote)->u32;
-	atomic_set(&po->proto.lac.sequencing, 1);
-	po->proto.lac.backlog_rcv = sk_udp->sk_backlog_rcv;
-
-	error = ppp_register_channel(&po->chan);
-	if (error)
-		goto out;
-
-	sk->sk_state = PPPOX_CONNECTED;
-	udp_sk(sk_udp)->encap_type = UDP_ENCAP_L2TPINUDP;
-	udp_sk(sk_udp)->encap_rcv = pppolac_recv;
-	sk_udp->sk_backlog_rcv = pppolac_recv_core;
-	sk_udp->sk_user_data = sk;
-out:
-	if (sock_udp) {
-		release_sock(sk_udp);
-		if (error)
-			sockfd_put(sock_udp);
-	}
-	release_sock(sk);
-	return error;
-}
-
-static int pppolac_release(struct socket *sock)
-{
-	struct sock *sk = sock->sk;
-
-	if (!sk)
-		return 0;
-
-	lock_sock(sk);
-	if (sock_flag(sk, SOCK_DEAD)) {
-		release_sock(sk);
-		return -EBADF;
-	}
-
-	if (sk->sk_state != PPPOX_NONE) {
-		struct sock *sk_udp = (struct sock *)pppox_sk(sk)->chan.private;
-		lock_sock(sk_udp);
-		skb_queue_purge(&sk->sk_receive_queue);
-		pppox_unbind_sock(sk);
-		udp_sk(sk_udp)->encap_type = 0;
-		udp_sk(sk_udp)->encap_rcv = NULL;
-		sk_udp->sk_backlog_rcv = pppox_sk(sk)->proto.lac.backlog_rcv;
-		sk_udp->sk_user_data = NULL;
-		release_sock(sk_udp);
-		sockfd_put(sk_udp->sk_socket);
-	}
-
-	sock_orphan(sk);
-	sock->sk = NULL;
-	release_sock(sk);
-	sock_put(sk);
-	return 0;
-}
-
-/******************************************************************************/
-
-static struct proto pppolac_proto = {
-	.name = "PPPOLAC",
-	.owner = THIS_MODULE,
-	.obj_size = sizeof(struct pppox_sock),
-};
-
-static struct proto_ops pppolac_proto_ops = {
-	.family = PF_PPPOX,
-	.owner = THIS_MODULE,
-	.release = pppolac_release,
-	.bind = sock_no_bind,
-	.connect = pppolac_connect,
-	.socketpair = sock_no_socketpair,
-	.accept = sock_no_accept,
-	.getname = sock_no_getname,
-	.poll = sock_no_poll,
-	.ioctl = pppox_ioctl,
-	.listen = sock_no_listen,
-	.shutdown = sock_no_shutdown,
-	.setsockopt = sock_no_setsockopt,
-	.getsockopt = sock_no_getsockopt,
-	.sendmsg = sock_no_sendmsg,
-	.recvmsg = sock_no_recvmsg,
-	.mmap = sock_no_mmap,
-};
-
-static int pppolac_create(struct net *net, struct socket *sock)
-{
-	struct sock *sk;
-
-	sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppolac_proto);
-	if (!sk)
-		return -ENOMEM;
-
-	sock_init_data(sock, sk);
-	sock->state = SS_UNCONNECTED;
-	sock->ops = &pppolac_proto_ops;
-	sk->sk_protocol = PX_PROTO_OLAC;
-	sk->sk_state = PPPOX_NONE;
-	return 0;
-}
-
-/******************************************************************************/
-
-static struct pppox_proto pppolac_pppox_proto = {
-	.create = pppolac_create,
-	.owner = THIS_MODULE,
-};
-
-static int __init pppolac_init(void)
-{
-	int error;
-
-	error = proto_register(&pppolac_proto, 0);
-	if (error)
-		return error;
-
-	error = register_pppox_proto(PX_PROTO_OLAC, &pppolac_pppox_proto);
-	if (error)
-		proto_unregister(&pppolac_proto);
-	else
-		skb_queue_head_init(&delivery_queue);
-	return error;
-}
-
-static void __exit pppolac_exit(void)
-{
-	unregister_pppox_proto(PX_PROTO_OLAC);
-	proto_unregister(&pppolac_proto);
-}
-
-module_init(pppolac_init);
-module_exit(pppolac_exit);
-
-MODULE_DESCRIPTION("PPP on L2TP Access Concentrator (PPPoLAC)");
-MODULE_AUTHOR("Chia-chi Yeh <chiachi@android.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/pppopns.c b/drivers/net/pppopns.c
deleted file mode 100644
index 6016d29..0000000
--- a/drivers/net/pppopns.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/* drivers/net/pppopns.c
- *
- * Driver for PPP on PPTP Network Server / PPPoPNS Socket (RFC 2637)
- *
- * Copyright (C) 2009 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-/* This driver handles PPTP data packets between a RAW socket and a PPP channel.
- * The socket is created in the kernel space and connected to the same address
- * of the control socket. Outgoing packets are always sent with sequences but
- * without acknowledgements. Incoming packets with sequences are reordered
- * within a sliding window of one second. Currently reordering only happens when
- * a packet is received. It is done for simplicity since no additional locks or
- * threads are required. This driver should work on both IPv4 and IPv6. */
-
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/workqueue.h>
-#include <linux/skbuff.h>
-#include <linux/file.h>
-#include <linux/netdevice.h>
-#include <linux/net.h>
-#include <linux/ppp_defs.h>
-#include <linux/if.h>
-#include <linux/if_ppp.h>
-#include <linux/if_pppox.h>
-#include <linux/ppp_channel.h>
-#include <asm/uaccess.h>
-
-#define GRE_HEADER_SIZE		8
-
-#define PPTP_GRE_BITS		htons(0x2001)
-#define PPTP_GRE_BITS_MASK	htons(0xEF7F)
-#define PPTP_GRE_SEQ_BIT	htons(0x1000)
-#define PPTP_GRE_ACK_BIT	htons(0x0080)
-#define PPTP_GRE_TYPE		htons(0x880B)
-
-#define PPP_ADDR	0xFF
-#define PPP_CTRL	0x03
-
-struct header {
-	__u16	bits;
-	__u16	type;
-	__u16	length;
-	__u16	call;
-	__u32	sequence;
-} __attribute__((packed));
-
-struct meta {
-	__u32 sequence;
-	__u32 timestamp;
-};
-
-static inline struct meta *skb_meta(struct sk_buff *skb)
-{
-	return (struct meta *)skb->cb;
-}
-
-/******************************************************************************/
-
-static int pppopns_recv_core(struct sock *sk_raw, struct sk_buff *skb)
-{
-	struct sock *sk = (struct sock *)sk_raw->sk_user_data;
-	struct pppopns_opt *opt = &pppox_sk(sk)->proto.pns;
-	struct meta *meta = skb_meta(skb);
-	__u32 now = jiffies;
-	struct header *hdr;
-
-	/* Skip transport header */
-	skb_pull(skb, skb_transport_header(skb) - skb->data);
-
-	/* Drop the packet if GRE header is missing. */
-	if (skb->len < GRE_HEADER_SIZE)
-		goto drop;
-	hdr = (struct header *)skb->data;
-
-	/* Check the header. */
-	if (hdr->type != PPTP_GRE_TYPE || hdr->call != opt->local ||
-			(hdr->bits & PPTP_GRE_BITS_MASK) != PPTP_GRE_BITS)
-		goto drop;
-
-	/* Skip all fields including optional ones. */
-	if (!skb_pull(skb, GRE_HEADER_SIZE +
-			(hdr->bits & PPTP_GRE_SEQ_BIT ? 4 : 0) +
-			(hdr->bits & PPTP_GRE_ACK_BIT ? 4 : 0)))
-		goto drop;
-
-	/* Check the length. */
-	if (skb->len != ntohs(hdr->length))
-		goto drop;
-
-	/* Check the sequence if it is present. */
-	if (hdr->bits & PPTP_GRE_SEQ_BIT) {
-		meta->sequence = ntohl(hdr->sequence);
-		if ((__s32)(meta->sequence - opt->recv_sequence) < 0)
-			goto drop;
-	}
-
-	/* Skip PPP address and control if they are present. */
-	if (skb->len >= 2 && skb->data[0] == PPP_ADDR &&
-			skb->data[1] == PPP_CTRL)
-		skb_pull(skb, 2);
-
-	/* Fix PPP protocol if it is compressed. */
-	if (skb->len >= 1 && skb->data[0] & 1)
-		skb_push(skb, 1)[0] = 0;
-
-	/* Drop the packet if PPP protocol is missing. */
-	if (skb->len < 2)
-		goto drop;
-
-	/* Perform reordering if sequencing is enabled. */
-	if (hdr->bits & PPTP_GRE_SEQ_BIT) {
-		struct sk_buff *skb1;
-
-		/* Insert the packet into receive queue in order. */
-		skb_set_owner_r(skb, sk);
-		skb_queue_walk(&sk->sk_receive_queue, skb1) {
-			struct meta *meta1 = skb_meta(skb1);
-			__s32 order = meta->sequence - meta1->sequence;
-			if (order == 0)
-				goto drop;
-			if (order < 0) {
-				meta->timestamp = meta1->timestamp;
-				skb_insert(skb1, skb, &sk->sk_receive_queue);
-				skb = NULL;
-				break;
-			}
-		}
-		if (skb) {
-			meta->timestamp = now;
-			skb_queue_tail(&sk->sk_receive_queue, skb);
-		}
-
-		/* Remove packets from receive queue as long as
-		 * 1. the receive buffer is full,
-		 * 2. they are queued longer than one second, or
-		 * 3. there are no missing packets before them. */
-		skb_queue_walk_safe(&sk->sk_receive_queue, skb, skb1) {
-			meta = skb_meta(skb);
-			if (atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
-					now - meta->timestamp < HZ &&
-					meta->sequence != opt->recv_sequence)
-				break;
-			skb_unlink(skb, &sk->sk_receive_queue);
-			opt->recv_sequence = meta->sequence + 1;
-			skb_orphan(skb);
-			ppp_input(&pppox_sk(sk)->chan, skb);
-		}
-		return NET_RX_SUCCESS;
-	}
-
-	/* Flush receive queue if sequencing is disabled. */
-	skb_queue_purge(&sk->sk_receive_queue);
-	skb_orphan(skb);
-	ppp_input(&pppox_sk(sk)->chan, skb);
-	return NET_RX_SUCCESS;
-drop:
-	kfree_skb(skb);
-	return NET_RX_DROP;
-}
-
-static void pppopns_recv(struct sock *sk_raw, int length)
-{
-	struct sk_buff *skb;
-	while ((skb = skb_dequeue(&sk_raw->sk_receive_queue))) {
-		sock_hold(sk_raw);
-		sk_receive_skb(sk_raw, skb, 0);
-	}
-}
-
-static struct sk_buff_head delivery_queue;
-
-static void pppopns_xmit_core(struct work_struct *delivery_work)
-{
-	mm_segment_t old_fs = get_fs();
-	struct sk_buff *skb;
-
-	set_fs(KERNEL_DS);
-	while ((skb = skb_dequeue(&delivery_queue))) {
-		struct sock *sk_raw = skb->sk;
-		struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
-		struct msghdr msg = {
-			.msg_iov = (struct iovec *)&iov,
-			.msg_iovlen = 1,
-			.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
-		};
-		sk_raw->sk_prot->sendmsg(NULL, sk_raw, &msg, skb->len);
-		kfree_skb(skb);
-	}
-	set_fs(old_fs);
-}
-
-static DECLARE_WORK(delivery_work, pppopns_xmit_core);
-
-static int pppopns_xmit(struct ppp_channel *chan, struct sk_buff *skb)
-{
-	struct sock *sk_raw = (struct sock *)chan->private;
-	struct pppopns_opt *opt = &pppox_sk(sk_raw->sk_user_data)->proto.pns;
-	struct header *hdr;
-	__u16 length;
-
-	/* Install PPP address and control. */
-	skb_push(skb, 2);
-	skb->data[0] = PPP_ADDR;
-	skb->data[1] = PPP_CTRL;
-	length = skb->len;
-
-	/* Install PPTP GRE header. */
-	hdr = (struct header *)skb_push(skb, 12);
-	hdr->bits = PPTP_GRE_BITS | PPTP_GRE_SEQ_BIT;
-	hdr->type = PPTP_GRE_TYPE;
-	hdr->length = htons(length);
-	hdr->call = opt->remote;
-	hdr->sequence = htonl(opt->xmit_sequence);
-	opt->xmit_sequence++;
-
-	/* Now send the packet via the delivery queue. */
-	skb_set_owner_w(skb, sk_raw);
-	skb_queue_tail(&delivery_queue, skb);
-	schedule_work(&delivery_work);
-	return 1;
-}
-
-/******************************************************************************/
-
-static struct ppp_channel_ops pppopns_channel_ops = {
-	.start_xmit = pppopns_xmit,
-};
-
-static int pppopns_connect(struct socket *sock, struct sockaddr *useraddr,
-	int addrlen, int flags)
-{
-	struct sock *sk = sock->sk;
-	struct pppox_sock *po = pppox_sk(sk);
-	struct sockaddr_pppopns *addr = (struct sockaddr_pppopns *)useraddr;
-	struct sockaddr_storage ss;
-	struct socket *sock_tcp = NULL;
-	struct socket *sock_raw = NULL;
-	struct sock *sk_tcp;
-	struct sock *sk_raw;
-	int error;
-
-	if (addrlen != sizeof(struct sockaddr_pppopns))
-		return -EINVAL;
-
-	lock_sock(sk);
-	error = -EALREADY;
-	if (sk->sk_state != PPPOX_NONE)
-		goto out;
-
-	sock_tcp = sockfd_lookup(addr->tcp_socket, &error);
-	if (!sock_tcp)
-		goto out;
-	sk_tcp = sock_tcp->sk;
-	error = -EPROTONOSUPPORT;
-	if (sk_tcp->sk_protocol != IPPROTO_TCP)
-		goto out;
-	addrlen = sizeof(struct sockaddr_storage);
-	error = kernel_getpeername(sock_tcp, (struct sockaddr *)&ss, &addrlen);
-	if (error)
-		goto out;
-	if (!sk_tcp->sk_bound_dev_if) {
-		struct dst_entry *dst = sk_dst_get(sk_tcp);
-		error = -ENODEV;
-		if (!dst)
-			goto out;
-		sk_tcp->sk_bound_dev_if = dst->dev->ifindex;
-		dst_release(dst);
-	}
-
-	error = sock_create(ss.ss_family, SOCK_RAW, IPPROTO_GRE, &sock_raw);
-	if (error)
-		goto out;
-	sk_raw = sock_raw->sk;
-	sk_raw->sk_bound_dev_if = sk_tcp->sk_bound_dev_if;
-	error = kernel_connect(sock_raw, (struct sockaddr *)&ss, addrlen, 0);
-	if (error)
-		goto out;
-
-	po->chan.hdrlen = 14;
-	po->chan.private = sk_raw;
-	po->chan.ops = &pppopns_channel_ops;
-	po->chan.mtu = PPP_MRU - 80;
-	po->proto.pns.local = addr->local;
-	po->proto.pns.remote = addr->remote;
-	po->proto.pns.data_ready = sk_raw->sk_data_ready;
-	po->proto.pns.backlog_rcv = sk_raw->sk_backlog_rcv;
-
-	error = ppp_register_channel(&po->chan);
-	if (error)
-		goto out;
-
-	sk->sk_state = PPPOX_CONNECTED;
-	lock_sock(sk_raw);
-	sk_raw->sk_data_ready = pppopns_recv;
-	sk_raw->sk_backlog_rcv = pppopns_recv_core;
-	sk_raw->sk_user_data = sk;
-	release_sock(sk_raw);
-out:
-	if (sock_tcp)
-		sockfd_put(sock_tcp);
-	if (error && sock_raw)
-		sock_release(sock_raw);
-	release_sock(sk);
-	return error;
-}
-
-static int pppopns_release(struct socket *sock)
-{
-	struct sock *sk = sock->sk;
-
-	if (!sk)
-		return 0;
-
-	lock_sock(sk);
-	if (sock_flag(sk, SOCK_DEAD)) {
-		release_sock(sk);
-		return -EBADF;
-	}
-
-	if (sk->sk_state != PPPOX_NONE) {
-		struct sock *sk_raw = (struct sock *)pppox_sk(sk)->chan.private;
-		lock_sock(sk_raw);
-		skb_queue_purge(&sk->sk_receive_queue);
-		pppox_unbind_sock(sk);
-		sk_raw->sk_data_ready = pppox_sk(sk)->proto.pns.data_ready;
-		sk_raw->sk_backlog_rcv = pppox_sk(sk)->proto.pns.backlog_rcv;
-		sk_raw->sk_user_data = NULL;
-		release_sock(sk_raw);
-		sock_release(sk_raw->sk_socket);
-	}
-
-	sock_orphan(sk);
-	sock->sk = NULL;
-	release_sock(sk);
-	sock_put(sk);
-	return 0;
-}
-
-/******************************************************************************/
-
-static struct proto pppopns_proto = {
-	.name = "PPPOPNS",
-	.owner = THIS_MODULE,
-	.obj_size = sizeof(struct pppox_sock),
-};
-
-static struct proto_ops pppopns_proto_ops = {
-	.family = PF_PPPOX,
-	.owner = THIS_MODULE,
-	.release = pppopns_release,
-	.bind = sock_no_bind,
-	.connect = pppopns_connect,
-	.socketpair = sock_no_socketpair,
-	.accept = sock_no_accept,
-	.getname = sock_no_getname,
-	.poll = sock_no_poll,
-	.ioctl = pppox_ioctl,
-	.listen = sock_no_listen,
-	.shutdown = sock_no_shutdown,
-	.setsockopt = sock_no_setsockopt,
-	.getsockopt = sock_no_getsockopt,
-	.sendmsg = sock_no_sendmsg,
-	.recvmsg = sock_no_recvmsg,
-	.mmap = sock_no_mmap,
-};
-
-static int pppopns_create(struct net *net, struct socket *sock)
-{
-	struct sock *sk;
-
-	sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppopns_proto);
-	if (!sk)
-		return -ENOMEM;
-
-	sock_init_data(sock, sk);
-	sock->state = SS_UNCONNECTED;
-	sock->ops = &pppopns_proto_ops;
-	sk->sk_protocol = PX_PROTO_OPNS;
-	sk->sk_state = PPPOX_NONE;
-	return 0;
-}
-
-/******************************************************************************/
-
-static struct pppox_proto pppopns_pppox_proto = {
-	.create = pppopns_create,
-	.owner = THIS_MODULE,
-};
-
-static int __init pppopns_init(void)
-{
-	int error;
-
-	error = proto_register(&pppopns_proto, 0);
-	if (error)
-		return error;
-
-	error = register_pppox_proto(PX_PROTO_OPNS, &pppopns_pppox_proto);
-	if (error)
-		proto_unregister(&pppopns_proto);
-	else
-		skb_queue_head_init(&delivery_queue);
-	return error;
-}
-
-static void __exit pppopns_exit(void)
-{
-	unregister_pppox_proto(PX_PROTO_OPNS);
-	proto_unregister(&pppopns_proto);
-}
-
-module_init(pppopns_init);
-module_exit(pppopns_exit);
-
-MODULE_DESCRIPTION("PPP on PPTP Network Server (PPPoPNS)");
-MODULE_AUTHOR("Chia-chi Yeh <chiachi@android.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 0d161b7..e42337f 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -294,6 +294,13 @@
 	help
 	  Say Y to enable support for the battery in Qualcomm MSM.
 
+config BATTERY_MSM_FAKE
+	tristate "Fake MSM battery"
+	depends on ARCH_MSM && BATTERY_MSM
+	default n
+	help
+	  Say Y to bypass actual battery queries.
+
 config BATTERY_MSM8X60
 	tristate "MSM8X60 battery"
 	select PMIC8XXX_BATTALARM
@@ -365,13 +372,6 @@
 	  The driver reports the charger status via the power supply framework.
 	  A charger status change triggers an IRQ via the device STAT pin.
 
-config BATTERY_MSM_FAKE
-	tristate "Fake MSM battery"
-	depends on ARCH_MSM && BATTERY_MSM
-	default n
-	help
-	  Say Y to bypass actual battery queries.
-
 config PM8058_FIX_USB
 	tristate "pmic8058 software workaround for usb removal"
 	depends on PMIC8058
@@ -396,13 +396,6 @@
 	help
 	  Say Y here to enable support for batteries with BQ27520 (I2C) chips.
 
-config BATTERY_BQ27541
-	tristate "BQ27541 battery driver"
-	depends on I2C
-	default n
-	help
-	  Say Y here to enable support for batteries with BQ27541 (I2C) chips.
-
 config BQ27520_TEST_ENABLE
 	bool "Enable BQ27520 Fuel Gauge Chip Test"
 	depends on BATTERY_BQ27520
@@ -410,6 +403,13 @@
 	help
 	  Say Y here to enable Test sysfs Interface for BQ27520 Drivers.
 
+config BATTERY_BQ27541
+	tristate "BQ27541 battery driver"
+	depends on I2C
+	default n
+	help
+	  Say Y here to enable support for batteries with BQ27541 (I2C) chips.
+
 config BATTERY_BQ28400
 	tristate "BQ28400 battery driver"
 	depends on I2C
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8f924d6..fe5af3a 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -436,4 +436,6 @@
 	  comply with QPNP.  QPNP is a SPMI based PMIC implementation.  These
 	  chips provide several different varieties of LDO and switching
 	  regulators.  They also provide voltage switches and boost regulators.
+
 endif
+
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 054ce42..eb07c97 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -45,7 +45,6 @@
 obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
-obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
 obj-$(CONFIG_REGULATOR_PMIC8058) += pmic8058-regulator.o
 obj-$(CONFIG_REGULATOR_PMIC8901) += pmic8901-regulator.o
 obj-$(CONFIG_REGULATOR_MSM_GPIO) += msm-gpio-regulator.o
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 1849118..7a559a6 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -123,24 +123,6 @@
 	  clock several times per second, please enable this option
 	  only if you know that you really need it.
 
-config RTC_INTF_ALARM
-	bool "Android alarm driver"
-	depends on RTC_CLASS
-	default y
-	help
-	  Provides non-wakeup and rtc backed wakeup alarms based on rtc or
-	  elapsed realtime, and a non-wakeup alarm on the monotonic clock.
-	  Also provides an interface to set the wall time which must be used
-	  for elapsed realtime to work.
-
-config RTC_INTF_ALARM_DEV
-	bool "Android alarm device"
-	depends on RTC_INTF_ALARM
-	default y
-	help
-	  Exports the alarm interface to user-space.
-
-
 config RTC_DRV_TEST
 	tristate "Test driver/device"
 	help
@@ -804,13 +786,6 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-davinci.
 
-config RTC_DRV_MSM7X00A
-	tristate "MSM7X00A"
-	depends on ARCH_MSM
-	default y
-	help
-	  RTC driver for Qualcomm MSM7K chipsets
-
 config RTC_DRV_OMAP
 	tristate "TI OMAP1"
 	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
@@ -1150,15 +1125,6 @@
 	  This drive can also be built as a module. If so, the module
 	  will be called rtc-puv3.
 
-config RTC_DRV_PM8XXX
-	tristate "Qualcomm PMIC8XXX RTC"
-	depends on MFD_PM8XXX
-	help
-	  Say Y here if you want to support the Qualcomm PMIC8XXX RTC.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called rtc-pm8xxx.
-
 config RTC_DRV_LOONGSON1
 	tristate "loongson1 RTC support"
 	depends on MACH_LOONGSON1
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 295f927..c6a0362 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -81,7 +81,6 @@
 obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_PCF2123)	+= rtc-pcf2123.o
 obj-$(CONFIG_RTC_DRV_PCF50633)	+= rtc-pcf50633.o
-obj-$(CONFIG_RTC_DRV_PM8XXX)    += rtc-pm8xxx.o
 obj-$(CONFIG_RTC_DRV_PL030)	+= rtc-pl030.o
 obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_PM8XXX)	+= rtc-pm8xxx.o
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index bec0399..e9f056e 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2568,11 +2568,12 @@
 					struct slim_pending_ch, pending);
 		struct slim_ich *slc = &ctrl->chans[pch->chan];
 		u32 sl = slc->seglen << slc->rootexp;
-		if (revert) {
+		if (revert || slc->def > 0) {
 			if (slc->coeff == SLIM_COEFF_3)
 				sl *= 3;
 			ctrl->sched.usedslots += sl;
-			slc->def = 1;
+			if (revert)
+				slc->def++;
 			slc->state = SLIM_CH_ACTIVE;
 		} else
 			slim_remove_ch(ctrl, slc);
@@ -2635,7 +2636,11 @@
 			/* Disconnect source port to free it up */
 			if (SLIM_HDL_TO_LA(slc->srch) == sb->laddr)
 				slc->srch = 0;
-			if (slc->def != 0) {
+			/*
+			 * If controller overrides BW allocation,
+			 * delete this in remove channel itself
+			 */
+			if (slc->def != 0 && !ctrl->allocbw) {
 				list_del(&pch->pending);
 				kfree(pch);
 			}
diff --git a/drivers/staging/ath6kl/os/linux/include/athendpack_linux.h b/drivers/staging/ath6kl/os/linux/include/athendpack_linux.h
deleted file mode 100644
index e69de29..0000000
--- a/drivers/staging/ath6kl/os/linux/include/athendpack_linux.h
+++ /dev/null
diff --git a/drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h b/drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h
deleted file mode 100644
index e69de29..0000000
--- a/drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h
+++ /dev/null
diff --git a/drivers/staging/dream/Kconfig b/drivers/staging/dream/Kconfig
deleted file mode 100644
index 0c30b19..0000000
--- a/drivers/staging/dream/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-config DREAM
-	tristate "HTC Dream support"
-	depends on MACH_TROUT
-
-if DREAM
-
-source "drivers/staging/dream/camera/Kconfig"
-
-config INPUT_GPIO
-	tristate "GPIO driver support"
-	help
-	  Say Y here if you want to support gpio based keys, wheels etc...
-endif
diff --git a/drivers/staging/dream/Makefile b/drivers/staging/dream/Makefile
deleted file mode 100644
index fbea0ab..0000000
--- a/drivers/staging/dream/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-EXTRA_CFLAGS=-Idrivers/staging/dream/include
-obj-$(CONFIG_MSM_ADSP)		+= qdsp5/
-obj-$(CONFIG_MSM_CAMERA)	+= camera/
-obj-$(CONFIG_INPUT_GPIO)	+= gpio_axis.o gpio_event.o gpio_input.o gpio_matrix.o gpio_output.o
-
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 9274c17..5c8645a 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -988,14 +988,6 @@
 	  Choose M here to compile it as a module. The module will be
 	  called msm_serial_hs.
 
-config SERIAL_MSM_CLOCK_CONTROL
-	bool "Allow tty clients to make clock requests to msm uarts."
-	depends on SERIAL_MSM=y
-	default y
-	help
-	 Provides an interface for tty clients to request the msm uart clock
-	 to be turned on or off for power savings.
-
 config SERIAL_MSM_RX_WAKEUP
 	bool "Wakeup the msm uart clock on GPIO activity."
 	depends on SERIAL_MSM_CLOCK_CONTROL
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 3e15ea7..fddb4fe 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -134,6 +134,8 @@
 
 source "drivers/usb/musb/Kconfig"
 
+source "drivers/usb/renesas_usbhs/Kconfig"
+
 source "drivers/usb/class/Kconfig"
 
 source "drivers/usb/storage/Kconfig"
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 87a0078..5b97148 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2093,6 +2093,7 @@
 	bool audio_enabled = false;
 	static DEFINE_RATELIMIT_STATE(rl, 10*HZ, 1);
 
+
 	if (!cdev)
 		return -ENODEV;
 
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index ccede0c..569f200 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -3,12 +3,6 @@
  * 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>
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 81fc1cc..e0255ce 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3280,6 +3280,7 @@
 static int ci13xxx_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *));
 static int ci13xxx_stop(struct usb_gadget_driver *driver);
+
 /**
  * Device operations part of the API to the USB controller hardware,
  * which don't involve endpoints (or i/o)
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 76028b2..3145418 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -137,10 +137,10 @@
 #define CI13XXX_CONTROLLER_RESET_EVENT			0
 #define CI13XXX_CONTROLLER_CONNECT_EVENT		1
 #define CI13XXX_CONTROLLER_SUSPEND_EVENT		2
-#define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT	3
-#define CI13XXX_CONTROLLER_RESUME_EVENT	        4
-#define CI13XXX_CONTROLLER_DISCONNECT_EVENT	    5
-#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT	    6
+#define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT		3
+#define CI13XXX_CONTROLLER_RESUME_EVENT		4
+#define CI13XXX_CONTROLLER_DISCONNECT_EVENT		5
+#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT		6
 
 	void	(*notify_event) (struct ci13xxx *udc, unsigned event);
 };
diff --git a/drivers/usb/gadget/qcom_maemo.c b/drivers/usb/gadget/qcom_maemo.c
deleted file mode 100644
index 2fb8be0..0000000
--- a/drivers/usb/gadget/qcom_maemo.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Qualcomm Maemo Composite driver
- *
- * Copyright (C) 2008 David Brownell
- * Copyright (C) 2008 Nokia Corporation
- * Copyright (C) 2009 Samsung Electronics
- * Copyright (c) 2010, The Linux Foundation. All rights reserved.
- *
- * This program from The Linux Foundation is free software; you can
- * redistribute it and/or modify it under the GNU General Public License
- * version 2 and only version 2 as published by the Free Software Foundation.
- * The original work available from [git.kernel.org ] is subject to the
- * notice below.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/utsname.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-
-
-#define DRIVER_DESC		"Qcom Maemo Composite Gadget"
-#define VENDOR_ID		0x05c6
-#define PRODUCT_ID		0x902E
-
-/*
- * kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-
-#include "composite.c"
-#include "usbstring.c"
-#include "config.c"
-#include "epautoconf.c"
-
-#define USB_ETH
-
-#define USB_ETH_RNDIS
-#ifdef USB_ETH_RNDIS
-#  include "f_rndis.c"
-#  include "rndis.c"
-#endif
-
-
-#include "u_serial.c"
-#include "f_serial.c"
-
-#include "u_ether.c"
-
-#undef DBG     /* u_ether.c has broken idea about macros */
-#undef VDBG    /* so clean up after it */
-#undef ERROR
-#undef INFO
-
-#include "f_mass_storage.c"
-#include "f_diag.c"
-#include "f_rmnet.c"
-
-/*-------------------------------------------------------------------------*/
-/* string IDs are assigned dynamically */
-
-#define STRING_MANUFACTURER_IDX         0
-#define STRING_PRODUCT_IDX              1
-#define STRING_SERIAL_IDX               2
-
-/* String Table */
-static struct usb_string strings_dev[] = {
-	/* These dummy values should be overridden by platform data */
-	[STRING_MANUFACTURER_IDX].s = "Qualcomm Incorporated",
-	[STRING_PRODUCT_IDX].s = "Usb composition",
-	[STRING_SERIAL_IDX].s = "0123456789ABCDEF",
-	{  }                    /* end of list */
-};
-
-static struct usb_gadget_strings stringtab_dev = {
-	.language       = 0x0409,       /* en-us */
-	.strings        = strings_dev,
-};
-
-static struct usb_gadget_strings *dev_strings[] = {
-	&stringtab_dev,
-	NULL,
-};
-
-static struct usb_device_descriptor device_desc = {
-	.bLength              = sizeof(device_desc),
-	.bDescriptorType      = USB_DT_DEVICE,
-	.bcdUSB               = __constant_cpu_to_le16(0x0200),
-	.bDeviceClass         = USB_CLASS_PER_INTERFACE,
-	.bDeviceSubClass      =      0,
-	.bDeviceProtocol      =      0,
-	.idVendor             = __constant_cpu_to_le16(VENDOR_ID),
-	.idProduct            = __constant_cpu_to_le16(PRODUCT_ID),
-	.bcdDevice            = __constant_cpu_to_le16(0xffff),
-	.bNumConfigurations   = 1,
-};
-
-static u8 hostaddr[ETH_ALEN];
-static struct usb_diag_ch *diag_ch;
-static struct usb_diag_platform_data usb_diag_pdata = {
-	.ch_name = DIAG_LEGACY,
-};
-
-/****************************** Configurations ******************************/
-static struct fsg_module_parameters mod_data = {
-	.stall = 0
-};
-FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
-
-static struct fsg_common *fsg_common;
-static int maemo_setup_config(struct usb_configuration *c,
-			const struct usb_ctrlrequest *ctrl);
-
-static int maemo_do_config(struct usb_configuration *c)
-{
-	int ret;
-
-	ret = rndis_bind_config(c, hostaddr);
-	if (ret < 0)
-		return ret;
-
-	ret = diag_function_add(c);
-	if (ret < 0)
-		return ret;
-
-	ret = gser_bind_config(c, 0);
-	if (ret < 0)
-		return ret;
-
-	ret = gser_bind_config(c, 1);
-	if (ret < 0)
-		return ret;
-
-	ret = rmnet_function_add(c);
-	if (ret < 0)
-		return ret;
-
-	ret = fsg_add(c->cdev, c, fsg_common);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static struct usb_configuration maemo_config_driver = {
-	.label			= "Qcom Maemo Gadget",
-	.bind			= maemo_do_config,
-	.setup			= maemo_setup_config,
-	.bConfigurationValue	= 1,
-	.bMaxPower		= 0xFA,
-};
-static int maemo_setup_config(struct usb_configuration *c,
-		const struct usb_ctrlrequest *ctrl)
-{
-	int i;
-	int ret = -EOPNOTSUPP;
-
-	for (i = 0; i < maemo_config_driver.next_interface_id; i++) {
-		if (maemo_config_driver.interface[i]->setup) {
-			ret = maemo_config_driver.interface[i]->setup(
-				maemo_config_driver.interface[i], ctrl);
-			if (ret >= 0)
-				return ret;
-		}
-	}
-
-	return ret;
-}
-
-static int maemo_bind(struct usb_composite_dev *cdev)
-{
-	struct usb_gadget *gadget = cdev->gadget;
-	int status, gcnum;
-
-	/* set up diag channel */
-	diag_ch = diag_setup(&usb_diag_pdata);
-	if (IS_ERR(diag_ch))
-		return PTR_ERR(diag_ch);
-
-	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		goto diag_clean;
-
-	/* set up serial link layer */
-	status = gserial_setup(cdev->gadget, 2);
-	if (status < 0)
-		goto fail0;
-
-	/* set up mass storage function */
-	fsg_common = fsg_common_from_params(0, cdev, &mod_data);
-	if (IS_ERR(fsg_common)) {
-		status = PTR_ERR(fsg_common);
-		goto fail1;
-	}
-
-	gcnum = usb_gadget_controller_number(gadget);
-	if (gcnum >= 0)
-		device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
-	else {
-		/* gadget zero is so simple (for now, no altsettings) that
-		 * it SHOULD NOT have problems with bulk-capable hardware.
-		 * so just warn about unrcognized controllers -- don't panic.
-		 *
-		 * things like configuration and altsetting numbering
-		 * can need hardware-specific attention though.
-		 */
-		WARNING(cdev, "controller '%s' not recognized\n",
-			gadget->name);
-		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
-	}
-
-	/* Allocate string descriptor numbers ... note that string
-	 * contents can be overridden by the composite_dev glue.
-	*/
-
-	status = usb_string_id(cdev);
-	if (status < 0)
-		goto fail2;
-	strings_dev[STRING_MANUFACTURER_IDX].id = status;
-	device_desc.iManufacturer = status;
-
-	status = usb_string_id(cdev);
-	if (status < 0)
-		goto fail2;
-	strings_dev[STRING_PRODUCT_IDX].id = status;
-	device_desc.iProduct = status;
-
-	if (!usb_gadget_set_selfpowered(gadget))
-		maemo_config_driver.bmAttributes |= USB_CONFIG_ATT_SELFPOWER;
-
-	if (gadget->ops->wakeup)
-		maemo_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-
-	/* register our first configuration */
-	status = usb_add_config(cdev, &maemo_config_driver);
-	if (status < 0)
-		goto fail2;
-
-	usb_gadget_set_selfpowered(gadget);
-	dev_info(&gadget->dev, DRIVER_DESC "\n");
-	fsg_common_put(fsg_common);
-	return 0;
-
-fail2:
-	fsg_common_put(fsg_common);
-fail1:
-	gserial_cleanup();
-fail0:
-	gether_cleanup();
-diag_clean:
-	diag_cleanup(diag_ch);
-
-	return status;
-}
-
-static int __exit maemo_unbind(struct usb_composite_dev *cdev)
-{
-	gserial_cleanup();
-	gether_cleanup();
-	diag_cleanup(diag_ch);
-	return 0;
-}
-
-static struct usb_composite_driver qcom_maemo_driver = {
-	.name		= "Qcom Maemo Gadget",
-	.dev		= &device_desc,
-	.strings	= dev_strings,
-	.bind		= maemo_bind,
-	.unbind		= __exit_p(maemo_unbind),
-};
-
-static int __init qcom_maemo_usb_init(void)
-{
-	return usb_composite_register(&qcom_maemo_driver);
-}
-module_init(qcom_maemo_usb_init);
-
-static void __exit qcom_maemo_usb_cleanup(void)
-{
-	usb_composite_unregister(&qcom_maemo_driver);
-}
-module_exit(qcom_maemo_usb_cleanup);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION("1.0");
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 502c33a..350e723 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1048,6 +1048,13 @@
 	struct gs_port		*port = tty->driver_data;
 	unsigned long		flags;
 
+	/*
+	 * tty's driver data is set to NULL during port close.  Nothing
+	 * to do here.
+	 */
+	if (!port)
+		return;
+
 	spin_lock_irqsave(&port->port_lock, flags);
 	if (port->port_usb) {
 		/* Kickstart read queue processing.  We don't do xon/xoff,
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 8c0894c..ca4b01a 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -624,6 +624,15 @@
 	int ret;
 	void __iomem *reg;
 
+	if (pdata && pdata->resume_gpio) {
+		ret = gpio_request(pdata->resume_gpio, "HSIC_RESUME_GPIO");
+		if (ret < 0) {
+			dev_err(mehci->dev,
+				"gpio req failed for hsic resume:%d\n", ret);
+			pdata->resume_gpio = 0;
+		}
+	}
+
 	/* HSIC init sequence when HSIC signals (Strobe/Data) are
 	routed via GPIOs */
 	if (pdata && pdata->strobe && pdata->data) {
@@ -645,7 +654,7 @@
 		ret = msm_hsic_config_gpios(mehci, 1);
 		if (ret) {
 			dev_err(mehci->dev, " gpio configuarion failed\n");
-			return ret;
+			goto free_resume_gpio;
 		}
 		if (pdata->strobe_pad_offset) {
 			/* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
@@ -694,6 +703,12 @@
 	ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
 
 	return 0;
+
+free_resume_gpio:
+	if (pdata && pdata->resume_gpio)
+		gpio_free(pdata->resume_gpio);
+
+	return ret;
 }
 
 #define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
@@ -1312,6 +1327,10 @@
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	u32			temp;
 	struct task_struct	*resume_thread = NULL;
+	struct msm_hsic_host_platform_data *pdata =  mehci->dev->platform_data;
+
+	if (pdata->resume_gpio)
+		gpio_direction_output(pdata->resume_gpio, 1);
 
 	mehci->resume_status = 0;
 	resume_thread = kthread_run(msm_hsic_resume_thread,
@@ -1351,6 +1370,9 @@
 
 	spin_unlock_irq(&ehci->lock);
 
+	if (pdata->resume_gpio)
+		gpio_direction_output(pdata->resume_gpio, 0);
+
 	return 0;
 }
 
@@ -1781,6 +1803,11 @@
 		res_gpio = 0;
 	pdata->data = res_gpio;
 
+	res_gpio = of_get_named_gpio(node, "hsic,resume-gpio", 0);
+	if (res_gpio < 0)
+		res_gpio = 0;
+	pdata->resume_gpio = res_gpio;
+
 	pdata->ignore_cal_pad_config = of_property_read_bool(node,
 					"hsic,ignore-cal-pad-config");
 	of_property_read_u32(node, "hsic,strobe-pad-offset",
@@ -2099,6 +2126,10 @@
 	destroy_workqueue(ehci_wq);
 
 	msm_hsic_config_gpios(mehci, 0);
+
+	if (pdata && pdata->resume_gpio)
+		gpio_free(pdata->resume_gpio);
+
 	msm_hsic_init_vddcx(mehci, 0);
 	msm_hsic_init_gdsc(mehci, 0);
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index cd17421..edf2a73 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -754,23 +754,6 @@
 
 #endif
 
-/*
- * Writing to dma coherent memory on ARM may be delayed via L2
- * writing buffer, so introduce the helper which can flush L2 writing
- * buffer into memory immediately, especially used to flush ehci
- * descriptor to memory.
- * */
-#ifdef	CONFIG_ARM_DMA_MEM_BUFFERABLE
-static inline void ehci_sync_mem(void)
-{
-	mb();
-}
-#else
-static inline void ehci_sync_mem(void)
-{
-}
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 #ifdef CONFIG_PCI
diff --git a/drivers/usb/otg/otg_id.c b/drivers/usb/otg/otg_id.c
deleted file mode 100644
index 7c38390..0000000
--- a/drivers/usb/otg/otg_id.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2011 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/notifier.h>
-#include <linux/usb/otg_id.h>
-
-static DEFINE_MUTEX(otg_id_lock);
-static struct plist_head otg_id_plist =
-	PLIST_HEAD_INIT(otg_id_plist);
-static struct otg_id_notifier_block *otg_id_active;
-static bool otg_id_cancelling;
-static bool otg_id_inited;
-static int otg_id_suspended;
-static bool otg_id_pending;
-
-static void otg_id_cancel(void)
-{
-	if (otg_id_active) {
-		otg_id_cancelling = true;
-		mutex_unlock(&otg_id_lock);
-
-		otg_id_active->cancel(otg_id_active);
-
-		mutex_lock(&otg_id_lock);
-		otg_id_cancelling = false;
-	}
-}
-
-static void __otg_id_notify(void)
-{
-	int ret = 0;
-	struct otg_id_notifier_block *otg_id_nb;
-	bool proxy_wait = false;
-	if (plist_head_empty(&otg_id_plist))
-		return;
-
-	plist_for_each_entry(otg_id_nb, &otg_id_plist, p) {
-		if (proxy_wait) {
-			if (otg_id_nb->proxy_wait)
-				ret = otg_id_nb->proxy_wait(otg_id_nb);
-		} else {
-			ret = otg_id_nb->detect(otg_id_nb);
-		}
-		if (ret == OTG_ID_HANDLED) {
-			otg_id_active = otg_id_nb;
-			return;
-		}
-		if (ret == OTG_ID_PROXY_WAIT)
-			proxy_wait = true;
-
-	}
-
-	WARN(1, "otg id event not handled");
-	otg_id_active = NULL;
-}
-
-int otg_id_init(void)
-{
-	mutex_lock(&otg_id_lock);
-
-	otg_id_inited = true;
-	__otg_id_notify();
-
-	mutex_unlock(&otg_id_lock);
-	return 0;
-}
-late_initcall(otg_id_init);
-
-/**
- * otg_id_register_notifier
- * @otg_id_nb: notifier block containing priority and callback function
- *
- * Register a notifier that will be called on any USB cable state change.
- * The priority determines the order the callback will be called in, a higher
- * number will be called first.  A callback function needs to determine the
- * type of USB cable that is connected.  If it can determine the type, it
- * should notify the appropriate drivers (for example, call an otg notifier
- * with USB_EVENT_VBUS), and return OTG_ID_HANDLED.  Once a callback has
- * returned OTG_ID_HANDLED, it is responsible for calling otg_id_notify() when
- * the detected USB cable is disconnected.
- */
-int otg_id_register_notifier(struct otg_id_notifier_block *otg_id_nb)
-{
-	plist_node_init(&otg_id_nb->p, otg_id_nb->priority);
-
-	mutex_lock(&otg_id_lock);
-	plist_add(&otg_id_nb->p, &otg_id_plist);
-
-	if (otg_id_inited) {
-		otg_id_cancel();
-		__otg_id_notify();
-	}
-
-	mutex_unlock(&otg_id_lock);
-
-	return 0;
-}
-
-void otg_id_unregister_notifier(struct otg_id_notifier_block *otg_id_nb)
-{
-	mutex_lock(&otg_id_lock);
-
-	plist_del(&otg_id_nb->p, &otg_id_plist);
-
-	if (otg_id_inited && (otg_id_active == otg_id_nb)) {
-		otg_id_cancel();
-		__otg_id_notify();
-	}
-
-	mutex_unlock(&otg_id_lock);
-}
-
-/**
- * otg_id_notify
- *
- * Notify listeners on any USB cable state change.
- *
- * A driver may only call otg_id_notify if it returned OTG_ID_HANDLED the last
- * time it's notifier was called, and it's cancel function has not been called.
- */
-void otg_id_notify(void)
-{
-	mutex_lock(&otg_id_lock);
-
-	if (otg_id_cancelling)
-		goto out;
-
-	if (otg_id_suspended != 0) {
-		otg_id_pending = true;
-		goto out;
-	}
-
-	__otg_id_notify();
-out:
-	mutex_unlock(&otg_id_lock);
-}
-
-/**
- * otg_id_suspend
- *
- * Mark the otg_id subsystem as going into suspend. From here on out,
- * any notifications will be deferred until the last otg_id client resumes.
- * If there is a pending notification when calling this function, it will
- * return a negative errno and expects that the caller will abort suspend.
- * Returs 0 on success.
- */
-int otg_id_suspend(void)
-{
-	int ret = 0;
-
-	mutex_lock(&otg_id_lock);
-
-	/*
-	 * if there's a pending notification, tell the caller to abort suspend
-	 */
-	if (otg_id_suspended != 0 && otg_id_pending) {
-		pr_info("otg_id: pending notification, should abort suspend\n");
-		ret = -EBUSY;
-		goto out;
-	}
-
-	otg_id_suspended++;
-out:
-	mutex_unlock(&otg_id_lock);
-	return ret;
-}
-
-/**
- * otg_id_resume
- *
- * Inform the otg_id subsystem that a client is resuming. If this is the
- * last client to be resumed and there's a pending notification,
- * otg_id_notify() is called.
- */
-void otg_id_resume(void)
-{
-	mutex_lock(&otg_id_lock);
-	if (WARN(!otg_id_suspended, "unbalanced otg_id_resume\n"))
-		goto out;
-	if (--otg_id_suspended == 0) {
-		if (otg_id_pending) {
-			pr_info("otg_id: had pending notification\n");
-			otg_id_pending = false;
-			__otg_id_notify();
-		}
-	}
-out:
-	mutex_unlock(&otg_id_lock);
-}
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index bfd8238..e50055f 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -3682,6 +3682,8 @@
 
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 
+	msm_fb_wait_for_fence(mfd);
+
 	switch (mfd->panel.type) {
 	case MIPI_CMD_PANEL:
 		mdp4_dsi_cmd_pipe_commit(0, 1);
@@ -3703,6 +3705,7 @@
 		ret = -EINVAL;
 		break;
 	}
+	msm_fb_signal_timeline(mfd);
 
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 4f95aee..6c7a1195 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -1774,6 +1774,12 @@
 		return -ENODEV;
 	}
 
+	if (!hdmi_ctrl->audio_sdev.state) {
+		DEV_ERR("%s: failed. HDMI is not connected/ready for audio\n",
+			__func__);
+		return -EPERM;
+	}
+
 	return hdmi_edid_get_audio_blk(
 		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], blk);
 } /* hdmi_tx_get_audio_edid_blk */
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index dcefc09..005a420 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -539,9 +539,9 @@
 	virt = ion_map_kernel(iclient, ihdl);
 	ion_phys(iclient, ihdl, &phys, &size);
 
-	pr_debug("%s %d Allocating %u bytes at 0x%lx (%lx phys)\n",
+	pr_debug("%s %d Allocating %u bytes at 0x%lx (%pa phys)\n",
 			__func__, __LINE__, size,
-			(unsigned long int)virt, phys);
+			(unsigned long int)virt, &phys);
 
 	bl_fb_addr_va = (unsigned long *)ioremap(bl_fb_addr, size);
 
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index e5f8a69..57bf9f2 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -118,6 +118,8 @@
 static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
 						struct mdp_bl_scale_data *data);
 static void msm_fb_scale_bl(__u32 *bl_lvl);
+static void msm_fb_commit_wq_handler(struct work_struct *work);
+static int msm_fb_pan_idle(struct msm_fb_data_type *mfd);
 
 #ifdef MSM_FB_ENABLE_DBGFS
 
@@ -879,6 +881,17 @@
 			if (ret)
 				mfd->panel_power_on = curr_pwr_state;
 
+			if (mfd->timeline) {
+				/* Adding 1 is enough when pan_display is still
+				 * a blocking call and with mutex protection.
+				 * But if it is an async call, we will still
+				 * need to add 2. Adding 2 can be safer in
+				 * order to signal all existing fences, and it
+				 * is harmless. */
+				sw_sync_timeline_inc(mfd->timeline, 2);
+				mfd->timeline_value += 2;
+			}
+
 			mfd->op_enable = TRUE;
 		}
 		break;
@@ -921,7 +934,7 @@
 			    const struct fb_fillrect *rect)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
+	msm_fb_pan_idle(mfd);
 	cfb_fillrect(info, rect);
 	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
 		!mfd->sw_currently_refreshing) {
@@ -942,6 +955,7 @@
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 
+	msm_fb_pan_idle(mfd);
 	cfb_copyarea(info, area);
 	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
 		!mfd->sw_currently_refreshing) {
@@ -961,6 +975,7 @@
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 
+	msm_fb_pan_idle(mfd);
 	cfb_imageblit(info, image);
 	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
 		!mfd->sw_currently_refreshing) {
@@ -979,6 +994,7 @@
 static int msm_fb_blank(int blank_mode, struct fb_info *info)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	msm_fb_pan_idle(mfd);
 	return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
 }
 
@@ -1005,6 +1021,7 @@
 	u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
 	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	msm_fb_pan_idle(mfd);
 	if (off >= len) {
 		/* memory mapped io */
 		off -= len;
@@ -1359,7 +1376,15 @@
 	mfd->msmfb_no_update_notify_timer.data = (unsigned long)mfd;
 	init_completion(&mfd->msmfb_update_notify);
 	init_completion(&mfd->msmfb_no_update_notify);
-
+	init_completion(&mfd->commit_comp);
+	mutex_init(&mfd->sync_mutex);
+	INIT_WORK(&mfd->commit_work, msm_fb_commit_wq_handler);
+	mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type),
+		GFP_KERNEL);
+	if (mfd->msm_fb_backup == 0) {
+		pr_err("error: not enough memory!\n");
+		return -ENOMEM;
+	}
 	fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
 	fbram += fbram_offset;
 	fbram_phys += fbram_offset;
@@ -1669,7 +1694,34 @@
 	return ret;
 }
 
-DEFINE_SEMAPHORE(msm_fb_pan_sem);
+int msm_fb_wait_for_fence(struct msm_fb_data_type *mfd)
+{
+	int i, ret = 0;
+	/* buf sync */
+	for (i = 0; i < mfd->acq_fen_cnt; i++) {
+		ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
+		sync_fence_put(mfd->acq_fen[i]);
+		if (ret < 0) {
+			pr_err("%s: sync_fence_wait failed! ret = %x\n",
+				__func__, ret);
+			break;
+		}
+	}
+	mfd->acq_fen_cnt = 0;
+	return ret;
+}
+int msm_fb_signal_timeline(struct msm_fb_data_type *mfd)
+{
+	mutex_lock(&mfd->sync_mutex);
+	if (mfd->timeline) {
+		sw_sync_timeline_inc(mfd->timeline, 1);
+		mfd->timeline_value++;
+	}
+	mfd->last_rel_fence = mfd->cur_rel_fence;
+	mfd->cur_rel_fence = 0;
+	mutex_unlock(&mfd->sync_mutex);
+	return 0;
+}
 
 static void bl_workqueue_handler(struct work_struct *work)
 {
@@ -1687,13 +1739,84 @@
 	}
 }
 
+DEFINE_SEMAPHORE(msm_fb_pan_sem);
+static int msm_fb_pan_idle(struct msm_fb_data_type *mfd)
+{
+	int ret = 0;
+
+	mutex_lock(&mfd->sync_mutex);
+	if (mfd->is_committing) {
+		mutex_unlock(&mfd->sync_mutex);
+		ret = wait_for_completion_timeout(&mfd->commit_comp,
+			msecs_to_jiffies(WAIT_FENCE_TIMEOUT));
+		if (ret <= 0)
+			pr_err("%s wait for commit_comp timeout %d %d",
+				__func__, ret, mfd->is_committing);
+	} else {
+		mutex_unlock(&mfd->sync_mutex);
+	}
+	return ret;
+}
+static int msm_fb_pan_display_ex(struct fb_var_screeninfo *var,
+			      struct fb_info *info, u32 wait_for_finish)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct msm_fb_backup_type *fb_backup;
+	int ret = 0;
+	/*
+	 * If framebuffer is 2, io pen display is not allowed.
+	 */
+	if (bf_supported && info->node == 2) {
+		pr_err("%s: no pan display for fb%d!",
+		       __func__, info->node);
+		return -EPERM;
+	}
+
+	if (info->node != 0 || mfd->cont_splash_done)	/* primary */
+		if ((!mfd->op_enable) || (!mfd->panel_power_on))
+			return -EPERM;
+
+	if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+		return -EINVAL;
+
+	if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+		return -EINVAL;
+	msm_fb_pan_idle(mfd);
+
+	mutex_lock(&mfd->sync_mutex);
+
+	if (info->fix.xpanstep)
+		info->var.xoffset =
+		    (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+	if (info->fix.ypanstep)
+		info->var.yoffset =
+		    (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+	fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
+	memcpy(&fb_backup->info, info, sizeof(struct fb_info));
+	memcpy(&fb_backup->var, var, sizeof(struct fb_var_screeninfo));
+	mfd->is_committing = 1;
+	INIT_COMPLETION(mfd->commit_comp);
+	schedule_work(&mfd->commit_work);
+	mutex_unlock(&mfd->sync_mutex);
+	if (wait_for_finish)
+		msm_fb_pan_idle(mfd);
+	return ret;
+}
+
 static int msm_fb_pan_display(struct fb_var_screeninfo *var,
 			      struct fb_info *info)
 {
+	return msm_fb_pan_display_ex(var, info, TRUE);
+}
+
+static int msm_fb_pan_display_sub(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
 	struct mdp_dirty_region dirty;
 	struct mdp_dirty_region *dirtyPtr = NULL;
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	int i, ret;
 
 	/*
 	 * If framebuffer is 2, io pen display is not allowed.
@@ -1765,17 +1888,7 @@
 	mutex_unlock(&msm_fb_notify_update_sem);
 
 	down(&msm_fb_pan_sem);
-	/* buf sync */
-	for (i = 0; i < mfd->acq_fen_cnt; i++) {
-		ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
-		sync_fence_put(mfd->acq_fen[i]);
-		if (ret < 0) {
-			pr_err("%s: sync_fence_wait failed! ret = %x\n",
-				__func__, ret);
-			break;
-		}
-	}
-	mfd->acq_fen_cnt = 0;
+	msm_fb_wait_for_fence(mfd);
 	if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
 		mdp_set_dma_pan_info(info, NULL, TRUE);
 		if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
@@ -1790,13 +1903,9 @@
 
 	mdp_set_dma_pan_info(info, dirtyPtr,
 			     (var->activate & FB_ACTIVATE_VBL));
+	/* async call */
 	mdp_dma_pan_update(info);
-	if (mfd->timeline) {
-		sw_sync_timeline_inc(mfd->timeline, 1);
-		mfd->timeline_value++;
-	}
-	mfd->last_rel_fence = mfd->cur_rel_fence;
-	mfd->cur_rel_fence = 0;
+	msm_fb_signal_timeline(mfd);
 	up(&msm_fb_pan_sem);
 
 	if (unset_bl_level && !bl_updated)
@@ -1810,8 +1919,30 @@
 	return 0;
 }
 
+static void msm_fb_commit_wq_handler(struct work_struct *work)
+{
+	struct msm_fb_data_type *mfd;
+	struct fb_var_screeninfo *var;
+	struct fb_info *info;
+	struct msm_fb_backup_type *fb_backup;
+
+	mfd = container_of(work, struct msm_fb_data_type, commit_work);
+	fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
+	var = &fb_backup->var;
+	info = &fb_backup->info;
+	msm_fb_pan_display_sub(var, info);
+	mutex_lock(&mfd->sync_mutex);
+	mfd->is_committing = 0;
+	complete_all(&mfd->commit_comp);
+	mutex_unlock(&mfd->sync_mutex);
+
+}
+
 static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	msm_fb_pan_idle(mfd);
 	if (var->rotate != FB_ROTATE_UR)
 		return -EINVAL;
 	if (var->grayscale != info->var.grayscale)
@@ -1936,7 +2067,7 @@
 	struct fb_var_screeninfo *var = &info->var;
 	int old_imgType;
 	int blank = 0;
-
+	msm_fb_pan_idle(mfd);
 	old_imgType = mfd->fb_imgType;
 	switch (var->bits_per_pixel) {
 	case 16:
@@ -3386,6 +3517,7 @@
 		pr_err("%s:copy_from_user failed", __func__);
 		return ret;
 	}
+	mutex_lock(&mfd->sync_mutex);
 	for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
 		fence = sync_fence_fdget(acq_fen_fd[i]);
 		if (fence == NULL) {
@@ -3426,6 +3558,7 @@
 		goto buf_sync_err_2;
 	}
 	mfd->acq_fen_cnt = buf_sync->acq_fen_fd_cnt;
+	mutex_unlock(&mfd->sync_mutex);
 	return ret;
 buf_sync_err_2:
 	sync_fence_put(mfd->cur_rel_fence);
@@ -3436,6 +3569,97 @@
 	for (i = 0; i < fence_cnt; i++)
 		sync_fence_put(mfd->acq_fen[i]);
 	mfd->acq_fen_cnt = 0;
+	mutex_unlock(&mfd->sync_mutex);
+	return ret;
+}
+
+static int buf_fence_process(struct msm_fb_data_type *mfd,
+						struct mdp_buf_fence *buf_fence)
+{
+	int i, fence_cnt = 0, ret;
+	struct sync_fence *fence;
+
+	if ((buf_fence->acq_fen_fd_cnt == 0) ||
+		(buf_fence->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
+		(mfd->timeline == NULL))
+		return -EINVAL;
+
+	mutex_lock(&mfd->sync_mutex);
+	for (i = 0; i < buf_fence->acq_fen_fd_cnt; i++) {
+		fence = sync_fence_fdget(buf_fence->acq_fen_fd[i]);
+		if (fence == NULL) {
+			pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
+				buf_fence->acq_fen_fd[i]);
+			ret = -EINVAL;
+			break;
+		}
+		mfd->acq_fen[i] = fence;
+	}
+	fence_cnt = i;
+	if (ret)
+		goto buf_fence_err_1;
+	mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
+			mfd->timeline_value + 2);
+	if (mfd->cur_rel_sync_pt == NULL) {
+		pr_err("%s: cannot create sync point", __func__);
+		ret = -ENOMEM;
+		goto buf_fence_err_1;
+	}
+	/* create fence */
+	mfd->cur_rel_fence = sync_fence_create("mdp-fence",
+			mfd->cur_rel_sync_pt);
+	if (mfd->cur_rel_fence == NULL) {
+		sync_pt_free(mfd->cur_rel_sync_pt);
+		mfd->cur_rel_sync_pt = NULL;
+		pr_err("%s: cannot create fence", __func__);
+		ret = -ENOMEM;
+		goto buf_fence_err_1;
+	}
+	/* create fd */
+	mfd->cur_rel_fen_fd = get_unused_fd_flags(0);
+	sync_fence_install(mfd->cur_rel_fence, mfd->cur_rel_fen_fd);
+	buf_fence->rel_fen_fd[0] = mfd->cur_rel_fen_fd;
+	/* Only one released fd for now, -1 indicates an end */
+	buf_fence->rel_fen_fd[1] = -1;
+	mfd->acq_fen_cnt = buf_fence->acq_fen_fd_cnt;
+	mutex_unlock(&mfd->sync_mutex);
+	return ret;
+buf_fence_err_1:
+	for (i = 0; i < fence_cnt; i++)
+		sync_fence_put(mfd->acq_fen[i]);
+	mfd->acq_fen_cnt = 0;
+	mutex_unlock(&mfd->sync_mutex);
+	return ret;
+}
+static int msmfb_display_commit(struct fb_info *info,
+						unsigned long *argp)
+{
+	int ret;
+	u32 copy_back = FALSE;
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct mdp_display_commit disp_commit;
+	struct mdp_buf_fence *buf_fence;
+	ret = copy_from_user(&disp_commit, argp,
+			sizeof(disp_commit));
+	if (ret) {
+		pr_err("%s:copy_from_user failed", __func__);
+		return ret;
+	}
+	buf_fence = &disp_commit.buf_fence;
+	if (buf_fence->acq_fen_fd_cnt > 0)
+		ret = buf_fence_process(mfd, buf_fence);
+	if ((!ret) && (buf_fence->rel_fen_fd[0] > 0))
+		copy_back = TRUE;
+
+	ret = msm_fb_pan_display_ex(&disp_commit.var,
+			      info, disp_commit.wait_for_finish);
+
+	if (copy_back) {
+		ret = copy_to_user(argp,
+			&disp_commit, sizeof(disp_commit));
+		if (ret)
+			pr_err("%s:copy_to_user failed", __func__);
+	}
 	return ret;
 }
 static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
@@ -3458,6 +3682,7 @@
 	struct msmfb_metadata mdp_metadata;
 	struct mdp_buf_sync buf_sync;
 	int ret = 0;
+	msm_fb_pan_idle(mfd);
 
 	switch (cmd) {
 #ifdef CONFIG_FB_MSM_OVERLAY
@@ -3760,6 +3985,8 @@
 		if (ret)
 			return ret;
 		ret = msmfb_handle_metadata_ioctl(mfd, &mdp_metadata);
+	case MSMFB_DISPLAY_COMMIT:
+		ret = msmfb_display_commit(info, argp);
 		break;
 
 	case MSMFB_METADATA_GET:
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 7e1716a..7519ac7 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -205,6 +205,18 @@
 	struct sync_fence *last_rel_fence;
 	struct sw_sync_timeline *timeline;
 	int timeline_value;
+	u32 last_acq_fen_cnt;
+	struct sync_fence *last_acq_fen[MDP_MAX_FENCE_FD];
+	struct mutex sync_mutex;
+	struct completion commit_comp;
+	u32 is_committing;
+	struct work_struct commit_work;
+	void *msm_fb_backup;
+};
+struct msm_fb_backup_type {
+	struct fb_info info;
+	struct fb_var_screeninfo var;
+	struct msm_fb_data_type mfd;
 };
 
 struct dentry *msm_fb_get_debugfs_root(void);
@@ -224,7 +236,8 @@
 int msm_fb_writeback_terminate(struct fb_info *info);
 int msm_fb_detect_client(const char *name);
 int calc_fb_offset(struct msm_fb_data_type *mfd, struct fb_info *fbi, int bpp);
-
+int msm_fb_wait_for_fence(struct msm_fb_data_type *mfd);
+int msm_fb_signal_timeline(struct msm_fb_data_type *mfd);
 #ifdef CONFIG_FB_BACKLIGHT
 void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
 #endif
diff --git a/fs/fat/Makefile b/fs/fat/Makefile
index 3f3e535..e061903 100644
--- a/fs/fat/Makefile
+++ b/fs/fat/Makefile
@@ -2,7 +2,6 @@
 # Makefile for the Linux fat filesystem support.
 #
 
-
 obj-$(CONFIG_FAT_FS) += fat.o
 obj-$(CONFIG_VFAT_FS) += vfat.o
 obj-$(CONFIG_MSDOS_FS) += msdos.o
diff --git a/include/linux/cpuacct.h b/include/linux/cpuacct.h
deleted file mode 100644
index 8f68e73..0000000
--- a/include/linux/cpuacct.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* include/linux/cpuacct.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _CPUACCT_H_
-#define _CPUACCT_H_
-
-#include <linux/cgroup.h>
-
-#ifdef CONFIG_CGROUP_CPUACCT
-
-/*
- * Platform specific CPU frequency hooks for cpuacct. These functions are
- * called from the scheduler.
- */
-struct cpuacct_charge_calls {
-	/*
-	 * Platforms can take advantage of this data and use
-	 * per-cpu allocations if necessary.
-	 */
-	void (*init) (void **cpuacct_data);
-	void (*charge) (void *cpuacct_data,  u64 cputime, unsigned int cpu);
-	void (*cpufreq_show) (void *cpuacct_data, struct cgroup_map_cb *cb);
-	/* Returns power consumed in milliWatt seconds */
-	u64 (*power_usage) (void *cpuacct_data);
-};
-
-int cpuacct_charge_register(struct cpuacct_charge_calls *fn);
-
-#endif /* CONFIG_CGROUP_CPUACCT */
-
-#endif // _CPUACCT_H_
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 7a5ab0d..d208f1e 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -43,6 +43,10 @@
 #define DIAG_IOCTL_DCI_REG		23
 #define DIAG_IOCTL_DCI_STREAM_INIT	24
 #define DIAG_IOCTL_DCI_HEALTH_STATS	25
+#define DIAG_IOCTL_DCI_LOG_STATUS	26
+#define DIAG_IOCTL_DCI_EVENT_STATUS	27
+#define DIAG_IOCTL_DCI_CLEAR_LOGS	28
+#define DIAG_IOCTL_DCI_CLEAR_EVENTS	29
 #define DIAG_IOCTL_REMOTE_DEV		32
 
 /* PC Tools IDs */
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 14cb148..4fa41b5 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -39,7 +39,8 @@
 	uint8_t		dev_num;
 	uint8_t		chan_num;
 	uint32_t	timestamp_resp_value;
-	uint32_t	reading_value;
+	int16_t		reading_raw;
+	int32_t		reading_value;
 };
 
 struct epm_psoc_get_buffered_data {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 03fc44b..093f0b8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -17,8 +17,8 @@
  * nr_file rlimit, so it's safe to set up a ridiculously high absolute
  * upper limit on files-per-process.
  *
- * Some programs (notably those using select()) may have to be
- * recompiled to take full advantage of the new limits..
+ * Some programs (notably those using select()) may have to be 
+ * recompiled to take full advantage of the new limits..  
  */
 
 /* Fixed constants first: */
@@ -178,7 +178,7 @@
 #define SEL_EX		4
 
 /* public flags for file_system_type */
-#define FS_REQUIRES_DEV 1
+#define FS_REQUIRES_DEV 1 
 #define FS_BINARY_MOUNTDATA 2
 #define FS_HAS_SUBTYPE 4
 #define FS_REVAL_DOT	16384	/* Check the paths ".", ".." for staleness */
@@ -490,7 +490,7 @@
  */
 #include <linux/quota.h>
 
-/**
+/** 
  * enum positive_aop_returns - aop return codes with specific semantics
  *
  * @AOP_WRITEPAGE_ACTIVATE: Informs the caller that page writeback has
@@ -500,7 +500,7 @@
  * 			    be a candidate for writeback again in the near
  * 			    future.  Other callers must be careful to unlock
  * 			    the page if they get this return.  Returned by
- * 			    writepage();
+ * 			    writepage(); 
  *
  * @AOP_TRUNCATED_PAGE: The AOP method that was handed a locked page has
  *  			unlocked it and the page might have been truncated.
@@ -1078,10 +1078,10 @@
 
 #define	MAX_NON_LFS	((1UL<<31) - 1)
 
-/* Page cache limit. The filesystems should put that into their s_maxbytes
-   limits, otherwise bad things can happen in VM. */
+/* Page cache limit. The filesystems should put that into their s_maxbytes 
+   limits, otherwise bad things can happen in VM. */ 
 #if BITS_PER_LONG==32
-#define MAX_LFS_FILESIZE	(((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
+#define MAX_LFS_FILESIZE	(((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) 
 #elif BITS_PER_LONG==64
 #define MAX_LFS_FILESIZE 	0x7fffffffffffffffUL
 #endif
@@ -2282,7 +2282,7 @@
 
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
 extern struct file * open_exec(const char *);
-
+ 
 /* fs/dcache.c -- generic fs support functions */
 extern int is_subdir(struct dentry *, struct dentry *);
 extern int path_is_under(struct path *, struct path *);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 37b1fdc..fb0c7af 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -710,7 +710,4 @@
 
 #endif /* __KERNEL__ */
 
-/* To identify board information in panic logs, set this */
-extern char *mach_panic_string;
-
 #endif
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index fc7d1a4..4473d69 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -243,10 +243,6 @@
 extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
 					  unsigned long pnum);
 
-extern void reserve_hotplug_pages(unsigned long start_pfn,
-				unsigned long nr_pages);
-extern void unreserve_hotplug_pages(unsigned long start_pfn,
-				unsigned long nr_pages);
 #endif /* __LINUX_MEMORY_HOTPLUG_H */
 extern int physical_remove_memory(u64 start, u64 size);
 extern int arch_physical_remove_memory(u64 start, u64 size);
diff --git a/include/linux/mfd/wcd9xxx/wcd9306_registers.h b/include/linux/mfd/wcd9xxx/wcd9306_registers.h
index 1254fac..564e5b3 100644
--- a/include/linux/mfd/wcd9xxx/wcd9306_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9306_registers.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
@@ -15,20 +15,20 @@
 
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 
-#define TAPAN_A_CHIP_CTL				WCD9XXX_A_CHIP_CTL
-#define TAPAN_A_CHIP_CTL__POR			WCD9XXX_A_CHIP_CTL__POR
-#define TAPAN_A_CHIP_STATUS				WCD9XXX_A_CHIP_STATUS
-#define TAPAN_A_CHIP_STATUS__POR		WCD9XXX_A_CHIP_STATUS__POR
-#define TAPAN_A_CHIP_ID_BYTE_0			WCD9XXX_A_CHIP_ID_BYTE_0
-#define TAPAN_A_CHIP_ID_BYTE_0__POR		WCD9XXX_A_CHIP_ID_BYTE_0__POR
-#define TAPAN_A_CHIP_ID_BYTE_1			WCD9XXX_A_CHIP_ID_BYTE_1
-#define TAPAN_A_CHIP_ID_BYTE_1__POR		WCD9XXX_A_CHIP_ID_BYTE_1__POR
-#define TAPAN_A_CHIP_ID_BYTE_2			WCD9XXX_A_CHIP_ID_BYTE_2
-#define TAPAN_A_CHIP_ID_BYTE_2__POR		WCD9XXX_A_CHIP_ID_BYTE_2__POR
-#define TAPAN_A_CHIP_ID_BYTE_3			WCD9XXX_A_CHIP_ID_BYTE_3
-#define TAPAN_A_CHIP_ID_BYTE_3__POR		WCD9XXX_A_CHIP_ID_BYTE_3__POR
-#define TAPAN_A_CHIP_VERSION			WCD9XXX_A_CHIP_VERSION
-#define TAPAN_A_CHIP_VERSION__POR		WCD9XXX_A_CHIP_VERSION__POR
+#define TAPAN_A_CHIP_CTL			(0x000)
+#define TAPAN_A_CHIP_CTL__POR				(0x00)
+#define TAPAN_A_CHIP_STATUS			(0x001)
+#define TAPAN_A_CHIP_STATUS__POR				(0x00)
+#define TAPAN_A_CHIP_ID_BYTE_0			(0x004)
+#define TAPAN_A_CHIP_ID_BYTE_0__POR				(0x00)
+#define TAPAN_A_CHIP_ID_BYTE_1			(0x005)
+#define TAPAN_A_CHIP_ID_BYTE_1__POR				(0x00)
+#define TAPAN_A_CHIP_ID_BYTE_2			(0x006)
+#define TAPAN_A_CHIP_ID_BYTE_2__POR				(0x03)
+#define TAPAN_A_CHIP_ID_BYTE_3			(0x007)
+#define TAPAN_A_CHIP_ID_BYTE_3__POR				(0x01)
+#define TAPAN_A_CHIP_VERSION			(0x008)
+#define TAPAN_A_CHIP_VERSION__POR				(0x20)
 #define TAPAN_A_CHIP_DEBUG_CTL			(0x009)
 #define TAPAN_A_CHIP_DEBUG_CTL__POR				(0x00)
 #define TAPAN_A_SLAVE_ID_1			(0x00C)
@@ -566,21 +566,21 @@
 #define TAPAN_A_CDC_TX4_VOL_CTL_CFG			(0x23A)
 #define TAPAN_A_CDC_TX4_VOL_CTL_CFG__POR				(0x00)
 #define TAPAN_A_CDC_TX1_MUX_CTL			(0x223)
-#define TAPAN_A_CDC_TX1_MUX_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX1_MUX_CTL__POR				(0x08)
 #define TAPAN_A_CDC_TX2_MUX_CTL			(0x22B)
-#define TAPAN_A_CDC_TX2_MUX_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX2_MUX_CTL__POR				(0x08)
 #define TAPAN_A_CDC_TX3_MUX_CTL			(0x233)
-#define TAPAN_A_CDC_TX3_MUX_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX3_MUX_CTL__POR				(0x08)
 #define TAPAN_A_CDC_TX4_MUX_CTL			(0x23B)
-#define TAPAN_A_CDC_TX4_MUX_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX4_MUX_CTL__POR				(0x08)
 #define TAPAN_A_CDC_TX1_CLK_FS_CTL			(0x224)
-#define TAPAN_A_CDC_TX1_CLK_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX1_CLK_FS_CTL__POR				(0x03)
 #define TAPAN_A_CDC_TX2_CLK_FS_CTL			(0x22C)
-#define TAPAN_A_CDC_TX2_CLK_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX2_CLK_FS_CTL__POR				(0x03)
 #define TAPAN_A_CDC_TX3_CLK_FS_CTL			(0x234)
-#define TAPAN_A_CDC_TX3_CLK_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX3_CLK_FS_CTL__POR				(0x03)
 #define TAPAN_A_CDC_TX4_CLK_FS_CTL			(0x23C)
-#define TAPAN_A_CDC_TX4_CLK_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX4_CLK_FS_CTL__POR				(0x03)
 #define TAPAN_A_CDC_TX1_DMIC_CTL			(0x225)
 #define TAPAN_A_CDC_TX1_DMIC_CTL__POR				(0x00)
 #define TAPAN_A_CDC_TX2_DMIC_CTL			(0x22D)
@@ -608,9 +608,9 @@
 #define TAPAN_A_CDC_SRC2_PDA_CFG			(0x2A8)
 #define TAPAN_A_CDC_SRC2_PDA_CFG__POR				(0x00)
 #define TAPAN_A_CDC_SRC1_FS_CTL			(0x2A1)
-#define TAPAN_A_CDC_SRC1_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_SRC1_FS_CTL__POR				(0x1B)
 #define TAPAN_A_CDC_SRC2_FS_CTL			(0x2A9)
-#define TAPAN_A_CDC_SRC2_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_SRC2_FS_CTL__POR				(0x1B)
 #define TAPAN_A_CDC_RX1_B1_CTL			(0x2B0)
 #define TAPAN_A_CDC_RX1_B1_CTL__POR				(0x00)
 #define TAPAN_A_CDC_RX2_B1_CTL			(0x2B8)
@@ -644,21 +644,21 @@
 #define TAPAN_A_CDC_RX4_B4_CTL			(0x2CB)
 #define TAPAN_A_CDC_RX4_B4_CTL__POR				(0x00)
 #define TAPAN_A_CDC_RX1_B5_CTL			(0x2B4)
-#define TAPAN_A_CDC_RX1_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_B5_CTL__POR				(0x78)
 #define TAPAN_A_CDC_RX2_B5_CTL			(0x2BC)
-#define TAPAN_A_CDC_RX2_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_B5_CTL__POR				(0x78)
 #define TAPAN_A_CDC_RX3_B5_CTL			(0x2C4)
-#define TAPAN_A_CDC_RX3_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_B5_CTL__POR				(0x78)
 #define TAPAN_A_CDC_RX4_B5_CTL			(0x2CC)
-#define TAPAN_A_CDC_RX4_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_B5_CTL__POR				(0x78)
 #define TAPAN_A_CDC_RX1_B6_CTL			(0x2B5)
-#define TAPAN_A_CDC_RX1_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_B6_CTL__POR				(0x80)
 #define TAPAN_A_CDC_RX2_B6_CTL			(0x2BD)
-#define TAPAN_A_CDC_RX2_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_B6_CTL__POR				(0x80)
 #define TAPAN_A_CDC_RX3_B6_CTL			(0x2C5)
-#define TAPAN_A_CDC_RX3_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_B6_CTL__POR				(0x80)
 #define TAPAN_A_CDC_RX4_B6_CTL			(0x2CD)
-#define TAPAN_A_CDC_RX4_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_B6_CTL__POR				(0x80)
 #define TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL			(0x2B6)
 #define TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL__POR				(0x00)
 #define TAPAN_A_CDC_RX2_VOL_CTL_B1_CTL			(0x2BE)
@@ -784,9 +784,9 @@
 #define TAPAN_A_CDC_IIR2_GAIN_B8_CTL			(0x357)
 #define TAPAN_A_CDC_IIR2_GAIN_B8_CTL__POR				(0x00)
 #define TAPAN_A_CDC_IIR1_CTL			(0x348)
-#define TAPAN_A_CDC_IIR1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_CTL__POR				(0x40)
 #define TAPAN_A_CDC_IIR2_CTL			(0x358)
-#define TAPAN_A_CDC_IIR2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_CTL__POR				(0x40)
 #define TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL			(0x349)
 #define TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL__POR				(0x00)
 #define TAPAN_A_CDC_IIR2_GAIN_TIMER_CTL			(0x359)
@@ -802,35 +802,35 @@
 #define TAPAN_A_CDC_TOP_GAIN_UPDATE			(0x360)
 #define TAPAN_A_CDC_TOP_GAIN_UPDATE__POR				(0x00)
 #define TAPAN_A_CDC_COMP0_B1_CTL			(0x368)
-#define TAPAN_A_CDC_COMP0_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B1_CTL__POR				(0x30)
 #define TAPAN_A_CDC_COMP1_B1_CTL			(0x370)
-#define TAPAN_A_CDC_COMP1_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B1_CTL__POR				(0x30)
 #define TAPAN_A_CDC_COMP2_B1_CTL			(0x378)
-#define TAPAN_A_CDC_COMP2_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B1_CTL__POR				(0x30)
 #define TAPAN_A_CDC_COMP0_B2_CTL			(0x369)
-#define TAPAN_A_CDC_COMP0_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B2_CTL__POR				(0xB5)
 #define TAPAN_A_CDC_COMP1_B2_CTL			(0x371)
-#define TAPAN_A_CDC_COMP1_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B2_CTL__POR				(0xB5)
 #define TAPAN_A_CDC_COMP2_B2_CTL			(0x379)
-#define TAPAN_A_CDC_COMP2_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B2_CTL__POR				(0xB5)
 #define TAPAN_A_CDC_COMP0_B3_CTL			(0x36A)
-#define TAPAN_A_CDC_COMP0_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B3_CTL__POR				(0x28)
 #define TAPAN_A_CDC_COMP1_B3_CTL			(0x372)
-#define TAPAN_A_CDC_COMP1_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B3_CTL__POR				(0x28)
 #define TAPAN_A_CDC_COMP2_B3_CTL			(0x37A)
-#define TAPAN_A_CDC_COMP2_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B3_CTL__POR				(0x28)
 #define TAPAN_A_CDC_COMP0_B4_CTL			(0x36B)
-#define TAPAN_A_CDC_COMP0_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B4_CTL__POR				(0x37)
 #define TAPAN_A_CDC_COMP1_B4_CTL			(0x373)
-#define TAPAN_A_CDC_COMP1_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B4_CTL__POR				(0x37)
 #define TAPAN_A_CDC_COMP2_B4_CTL			(0x37B)
-#define TAPAN_A_CDC_COMP2_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B4_CTL__POR				(0x37)
 #define TAPAN_A_CDC_COMP0_B5_CTL			(0x36C)
-#define TAPAN_A_CDC_COMP0_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B5_CTL__POR				(0x7F)
 #define TAPAN_A_CDC_COMP1_B5_CTL			(0x374)
-#define TAPAN_A_CDC_COMP1_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B5_CTL__POR				(0x7F)
 #define TAPAN_A_CDC_COMP2_B5_CTL			(0x37C)
-#define TAPAN_A_CDC_COMP2_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B5_CTL__POR				(0x7F)
 #define TAPAN_A_CDC_COMP0_B6_CTL			(0x36D)
 #define TAPAN_A_CDC_COMP0_B6_CTL__POR				(0x00)
 #define TAPAN_A_CDC_COMP1_B6_CTL			(0x375)
@@ -838,17 +838,17 @@
 #define TAPAN_A_CDC_COMP2_B6_CTL			(0x37D)
 #define TAPAN_A_CDC_COMP2_B6_CTL__POR				(0x00)
 #define TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS			(0x36E)
-#define TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS__POR				(0x03)
 #define TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS			(0x376)
-#define TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS__POR				(0x03)
 #define TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS			(0x37E)
-#define TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS__POR				(0x03)
 #define TAPAN_A_CDC_COMP0_FS_CFG			(0x36F)
-#define TAPAN_A_CDC_COMP0_FS_CFG__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_FS_CFG__POR				(0x03)
 #define TAPAN_A_CDC_COMP1_FS_CFG			(0x377)
-#define TAPAN_A_CDC_COMP1_FS_CFG__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_FS_CFG__POR				(0x03)
 #define TAPAN_A_CDC_COMP2_FS_CFG			(0x37F)
-#define TAPAN_A_CDC_COMP2_FS_CFG__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_FS_CFG__POR				(0x03)
 #define TAPAN_A_CDC_CONN_RX1_B1_CTL			(0x380)
 #define TAPAN_A_CDC_CONN_RX1_B1_CTL__POR				(0x00)
 #define TAPAN_A_CDC_CONN_RX1_B2_CTL			(0x381)
@@ -992,12 +992,18 @@
 #define TAPAN_A_CDC_MBHC_SPARE			(0x3DF)
 #define TAPAN_A_CDC_MBHC_SPARE__POR				(0x00)
 
-
 /* SLIMBUS Slave Registers */
-#define TAPAN_SLIM_PGD_PORT_INT_EN0 (0x30)
-#define TAPAN_SLIM_PGD_PORT_INT_STATUS0 (0x34)
-#define TAPAN_SLIM_PGD_PORT_INT_CLR0 (0x38)
-#define TAPAN_SLIM_PGD_PORT_INT_SOURCE0 (0x60)
+#define TAPAN_SLIM_PGD_PORT_INT_EN0                     (0x30)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS_RX_0             (0x34)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS_RX_1             (0x35)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS_TX_0             (0x36)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS_TX_1             (0x37)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR_RX_0                (0x38)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR_RX_1                (0x39)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR_TX_0                (0x3A)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR_TX_1                (0x3B)
+#define TAPAN_SLIM_PGD_PORT_INT_RX_SOURCE0		(0x60)
+#define TAPAN_SLIM_PGD_PORT_INT_TX_SOURCE0		(0x70)
 
 /* Macros for Packing Register Writes into a U32 */
 #define TAPAN_PACKED_REG_SIZE sizeof(u32)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 6e12694..ca7a586 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -529,12 +529,6 @@
 	return test_bit(ZONE_OOM_LOCKED, &zone->flags);
 }
 
-#ifdef CONFIG_SMP
-unsigned long zone_nr_free_pages(struct zone *zone);
-#else
-#define zone_nr_free_pages(zone) zone_page_state(zone, NR_FREE_PAGES)
-#endif /* CONFIG_SMP */
-
 /*
  * The "priority" of VM scanning is how much of the queues we will scan in one
  * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 45bc0ea..4149552 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -629,11 +629,19 @@
 };
 
 #define MDP_DISPLAY_COMMIT_OVERLAY	1
+struct mdp_buf_fence {
+	uint32_t flags;
+	uint32_t acq_fen_fd_cnt;
+	int acq_fen_fd[MDP_MAX_FENCE_FD];
+	int rel_fen_fd[MDP_MAX_FENCE_FD];
+};
+
 
 struct mdp_display_commit {
 	uint32_t flags;
 	uint32_t wait_for_finish;
 	struct fb_var_screeninfo var;
+	struct mdp_buf_fence buf_fence;
 };
 
 struct mdp_page_protection {
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 6e4b7a6..ce5ddf3 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1135,55 +1135,6 @@
  *	%NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into
  *	(Re)Association Response frames when the driver (or firmware) replies to
  *	(Re)Association Request frames.
- * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
- *      of the station, see &enum nl80211_sta_wme_attr.
- * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working
- *      as AP.
- *
- * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of
- *      roaming to another AP in the same ESS if the signal lever is low.
- *
- * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching
- *      candidate information, see &enum nl80211_pmksa_candidate_attr.
- *
- * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not
- *      for management frames transmission. In order to avoid p2p probe/action
- *      frames are being transmitted at CCK rate in 2GHz band, the user space
- *      applications use this attribute.
- *      This attribute is used with %NL80211_CMD_TRIGGER_SCAN and
- *      %NL80211_CMD_FRAME commands.
- *
- * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
- *      request, link setup confirm, link teardown, etc.). Values are
- *      described in the TDLS (802.11z) specification.
- * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
- *      TDLS conversation between two devices.
- * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
- *      &enum nl80211_tdls_operation, represented as a u8.
- * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
- *      as a TDLS peer sta.
- * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
- *      procedures should be performed by sending TDLS packets via
- *      %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
- *      used for asking the driver to perform a TDLS operation.
- *
- * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
- *      that have AP support to indicate that they have the AP SME integrated
- *      with support for the features listed in this attribute, see
- *      &enum nl80211_ap_sme_features.
- *
- * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
- *      the driver to not wait for an acknowledgement. Note that due to this,
- *      it will also not give a status callback nor return a cookie. This is
- *      mostly useful for probe responses to save airtime.
- *
- * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
- *      &enum nl80211_feature_flags and is advertised in wiphy information.
- * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe
- *
- *      requests while operating in AP-mode.
- *      This attribute holds a bitmap of the supported protocols for
- *      offloading (see &enum nl80211_probe_resp_offload_support_attr).
  *
  * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
  *	of the station, see &enum nl80211_sta_wme_attr.
diff --git a/include/linux/platform_data/ram_console.h b/include/linux/platform_data/ram_console.h
deleted file mode 100644
index 9f1125c..0000000
--- a/include/linux/platform_data/ram_console.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_
-#define _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_
-
-struct ram_console_platform_data {
-	const char *bootinfo;
-};
-
-#endif /* _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_ */
diff --git a/include/linux/regulator/krait-regulator.h b/include/linux/regulator/krait-regulator.h
index b784531..2683fd7 100644
--- a/include/linux/regulator/krait-regulator.h
+++ b/include/linux/regulator/krait-regulator.h
@@ -27,22 +27,6 @@
 #ifdef CONFIG_ARCH_MSM8974
 int __init krait_power_init(void);
 void secondary_cpu_hs_init(void *base_ptr);
-
-/**
- * krait_power_mdd_enable - function to turn on/off MDD. Turning off MDD
- *				turns off badngap reference for LDO. If
- *				a core is running on a LDO, requests to
- *				turn off MDD will not be honoured
- * @on:	boolean to indicate whether to turn MDD on/off
- *
- * CONTEXT: Can be called in interrupt context, only when the core
- *		is about to go to idle, this guarantees that there are no
- *		frequency changes on that cpu happening. Note if going from off
- *		to on mode there will be settling delays
- *
- * RETURNS: -EINVAL if MDD cannot be turned off
- */
-int krait_power_mdd_enable(int cpu_num, bool on);
 #else
 static inline int __init krait_power_init(void)
 {
@@ -50,10 +34,6 @@
 }
 
 static inline void secondary_cpu_hs_init(void *base_ptr) {}
-static inline int krait_power_mdd_enable(int cpu_num, bool on)
-{
-	return -EINVAL;
-}
 #endif
 
 #endif
diff --git a/include/linux/rq_stats.h b/include/linux/rq_stats.h
index 65d8e8f..0accf38 100644
--- a/include/linux/rq_stats.h
+++ b/include/linux/rq_stats.h
@@ -19,6 +19,7 @@
 	unsigned long rq_poll_total_jiffies;
 	unsigned long def_timer_last_jiffy;
 	unsigned int def_interval;
+	unsigned int hotplug_disabled;
 	int64_t def_start_time;
 	struct attribute_group *attr_group;
 	struct kobject *kobj;
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index f9547f4..3b5e910 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -27,8 +27,6 @@
 	struct cpu_stop_done	*done;
 };
 
-extern struct mutex stop_cpus_mutex;
-
 int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
 void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 			 struct cpu_stop_work *work_buf);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index c5943c9..ea45a8c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -406,6 +406,9 @@
 	struct msm_bus_scale_pdata *bus_scale_table;
 	unsigned log2_irq_thresh;
 
+	/* gpio used to resume peripheral */
+	unsigned resume_gpio;
+
 	/*swfi latency is required while driving resume on to the bus */
 	u32 swfi_latency;
 
diff --git a/include/linux/usb/otg_id.h b/include/linux/usb/otg_id.h
deleted file mode 100644
index f9f5189..0000000
--- a/include/linux/usb/otg_id.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2011 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __LINUX_USB_OTG_ID_H
-#define __LINUX_USB_OTG_ID_H
-
-#include <linux/notifier.h>
-#include <linux/plist.h>
-
-/**
- * otg_id_notifier_block
- *
- * @priority: Order the notifications will be called in.  Higher numbers
- *    get called first.
- * @detect: Called during otg_id_notify.  Return OTG_ID_HANDLED if the USB cable
- *    has been identified
- * @proxy_wait: Called during otg_id_notify if a previous handler returns
- *    OTG_ID_PROXY_WAIT.  This should wait on ID change then call otg_id_notify.
- *    This is used when a handler knows what's connected but can't detect
- *    the change itself.
- * @cancel: Called after detect has returned OTG_ID_HANDLED to ask it to
- *    release detection resources to allow a new identification to occur.
- */
-
-struct otg_id_notifier_block {
-	int priority;
-	int (*detect)(struct otg_id_notifier_block *otg_id_nb);
-	int (*proxy_wait)(struct otg_id_notifier_block *otg_id_nb);
-	void (*cancel)(struct otg_id_notifier_block *otg_id_nb);
-	struct plist_node p;
-};
-
-#define OTG_ID_PROXY_WAIT 2
-#define OTG_ID_HANDLED 1
-#define OTG_ID_UNHANDLED 0
-
-int otg_id_register_notifier(struct otg_id_notifier_block *otg_id_nb);
-void otg_id_unregister_notifier(struct otg_id_notifier_block *otg_id_nb);
-
-void otg_id_notify(void);
-int otg_id_suspend(void);
-void otg_id_resume(void);
-
-#endif /* __LINUX_USB_OTG_ID_H */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 2972dc0..a1d0445 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1491,6 +1491,7 @@
 	V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE			= 0,
 	V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME	= 1,
 	V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME		= 2,
+
 };
 #define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC			(V4L2_CID_MPEG_BASE+217)
 #define V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE		(V4L2_CID_MPEG_BASE+218)
@@ -1602,7 +1603,6 @@
 #define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP	(V4L2_CID_MPEG_BASE+403)
 #define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP	(V4L2_CID_MPEG_BASE+404)
 #define V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL		(V4L2_CID_MPEG_BASE+405)
-
 enum v4l2_mpeg_video_mpeg4_level {
 	V4L2_MPEG_VIDEO_MPEG4_LEVEL_0	= 0,
 	V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B	= 1,
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index a51f84c..5b4ad6d 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -152,8 +152,8 @@
 #define RC_MAP_TREKSTOR                  "rc-trekstor"
 #define RC_MAP_TT_1500                   "rc-tt-1500"
 #define RC_MAP_TWINHAN_VP1027_DVBS       "rc-twinhan1027"
-#define RC_MAP_VIDEOMATE_K100            "rc-videomate-k100"
 #define RC_MAP_UE_RF4CE			 "rc-ue-rf4ce"
+#define RC_MAP_VIDEOMATE_K100            "rc-videomate-k100"
 #define RC_MAP_VIDEOMATE_S350            "rc-videomate-s350"
 #define RC_MAP_VIDEOMATE_TV_PVR          "rc-videomate-tv-pvr"
 #define RC_MAP_WINFAST                   "rc-winfast"
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index efc11bb..c68d427 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -26,7 +26,6 @@
 #define __HCI_CORE_H
 
 #include <net/bluetooth/hci.h>
-#include <linux/wakelock.h>
 /* HCI upper protocols */
 #define HCI_PROTO_L2CAP	0
 #define HCI_PROTO_SCO	1
@@ -327,7 +326,6 @@
 
 	struct work_struct work_add;
 	struct work_struct work_del;
-	struct wake_lock idle_lock;
 	struct device	dev;
 	atomic_t	devref;
 
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3a7edf3..1645608 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -669,7 +669,9 @@
 
 	const u8 *assoc_req_ies;
 	size_t assoc_req_ies_len;
+
 	u32 beacon_loss_count;
+
 	/*
 	 * Note: Add a new enum station_info_flags value for each new field and
 	 * use it to check which fields are initialized.
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 6f1470f..498433d 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -14,8 +14,6 @@
 
 struct flowi6;
 
-extern void initialize_hashidentrnd(void);
-
 /* extension headers */
 extern int				ipv6_exthdrs_init(void);
 extern void				ipv6_exthdrs_exit(void);
diff --git a/init/Kconfig b/init/Kconfig
index b2126bc..e4b67a1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1132,15 +1132,6 @@
 	  option replaces shmem and tmpfs with the much simpler ramfs code,
 	  which may be appropriate on small systems without swap.
 
-config ASHMEM
-	bool "Enable the Anonymous Shared Memory Subsystem"
-	default n
-	depends on SHMEM || TINY_SHMEM
-	help
-	  The ashmem subsystem is a new shared memory allocator, similar to
-	  POSIX SHM but with different behavior and sporting a simpler
-	  file-based API.
-
 config AIO
 	bool "Enable AIO support" if EXPERT
 	default y
diff --git a/kernel/power/main.c b/kernel/power/main.c
index b54da02..7aac5f6 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -666,7 +666,6 @@
 	tc_ev_timer.function = &tc_ev_stop;
 	tc_ev_processed = 1;
 
-
 	power_kobj = kobject_create_and_add("power", NULL);
 	if (!power_kobj)
 		return -ENOMEM;
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index b0f118e..2f194e9 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -133,8 +133,8 @@
 	cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf);
 }
 
-DEFINE_MUTEX(stop_cpus_mutex);
 /* static data for stop_cpus */
+static DEFINE_MUTEX(stop_cpus_mutex);
 static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work);
 
 static void queue_stop_cpus_work(const struct cpumask *cpumask,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 50f73be..7ffcc1b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -543,7 +543,6 @@
 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
 	conn->conn_valid = true;
 	spin_lock_init(&conn->lock);
-	wake_lock_init(&conn->idle_lock, WAKE_LOCK_SUSPEND, "bt_idle");
 
 	switch (type) {
 	case ACL_LINK:
@@ -621,7 +620,6 @@
 
 	/* Make sure no timers are running */
 	del_timer(&conn->idle_timer);
-	wake_lock_destroy(&conn->idle_lock);
 	del_timer(&conn->disc_timer);
 	del_timer(&conn->smp_timer);
 	__cancel_delayed_work(&conn->rssi_update_work);
@@ -1082,7 +1080,6 @@
 		if (conn->conn_valid) {
 			mod_timer(&conn->idle_timer,
 				jiffies + msecs_to_jiffies(hdev->idle_timeout));
-			wake_lock(&conn->idle_lock);
 		}
 		spin_unlock_bh(&conn->lock);
 	}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 198773c..d243646 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2596,9 +2596,6 @@
 			else
 				conn->power_save = 0;
 		}
-		if (conn->mode == HCI_CM_SNIFF)
-			if (wake_lock_active(&conn->idle_lock))
-				wake_unlock(&conn->idle_lock);
 
 		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
 			hci_sco_setup(conn, ev->status);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index d778ae3..83087d1 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -201,7 +201,7 @@
 		l2cap_pi(sk)->mode, sk->sk_state);
 
 	if (!addr || alen < sizeof(addr->sa_family) ||
-	    addr->sa_family != AF_BLUETOOTH)
+		addr->sa_family != AF_BLUETOOTH)
 		return -EINVAL;
 
 	memset(&la, 0, sizeof(la));
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 291934b..a00a904 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -69,3 +69,4 @@
 obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o
 
 obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
+
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index ab7bd2c..0cb86ce 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1991,49 +1991,6 @@
 }
 EXPORT_SYMBOL(tcp_v4_destroy_sock);
 
-/*
- * tcp_v4_nuke_addr - destroy all sockets on the given local address
- */
-void tcp_v4_nuke_addr(__u32 saddr)
-{
-	unsigned int bucket;
-
-	for (bucket = 0; bucket < tcp_hashinfo.ehash_mask; bucket++) {
-		struct hlist_nulls_node *node;
-		struct sock *sk;
-		spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
-
-restart:
-		spin_lock_bh(lock);
-		sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
-			struct inet_sock *inet = inet_sk(sk);
-
-			if (inet->inet_rcv_saddr != saddr)
-				continue;
-			if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
-				continue;
-			if (sock_flag(sk, SOCK_DEAD))
-				continue;
-
-			sock_hold(sk);
-			spin_unlock_bh(lock);
-
-			local_bh_disable();
-			bh_lock_sock(sk);
-			sk->sk_err = ETIMEDOUT;
-			sk->sk_error_report(sk);
-
-			tcp_done(sk);
-			bh_unlock_sock(sk);
-			local_bh_enable();
-			sock_put(sk);
-
-			goto restart;
-		}
-		spin_unlock_bh(lock);
-	}
-}
-
 #ifdef CONFIG_PROC_FS
 /* Proc filesystem TCP sock list dumping. */
 
diff --git a/net/wireless/util.c b/net/wireless/util.c
index a448b80..017d4fc 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1038,6 +1038,7 @@
 		if (!found)
 			return -EINVAL;
 	}
+
 	/*
 	 * mask must have at least one bit set here since we
 	 * didn't accept a 0-length rates array nor allowed
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index a09dab3..f0cd026 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -52,7 +52,7 @@
 snd-soc-wcd9310-objs := wcd9310.o wcd9310-tables.o
 snd-soc-cs8427-objs := cs8427.o
 snd-soc-wcd9320-objs := wcd9xxx-resmgr.o wcd9320.o wcd9320-tables.o wcd9xxx-mbhc.o wcd9xxx-common.o
-snd-soc-wcd9306-objs := wcd9306.o wcd9306-tables.o
+snd-soc-wcd9306-objs := wcd9306.o wcd9306-tables.o wcd9xxx-common.o
 snd-soc-msm8x10-wcd-objs := msm8x10-wcd.o msm8x10-wcd-tables.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 25d3f56..634493b 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -18,6 +18,8 @@
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
 #include <linux/debugfs.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
 #include <linux/mfd/wcd9xxx/core.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
 #include <linux/mfd/wcd9xxx/wcd9306_registers.h>
@@ -34,6 +36,20 @@
 #include <linux/gpio.h>
 #include "wcd9306.h"
 #include "wcd9xxx-resmgr.h"
+#include "wcd9xxx-common.h"
+
+static atomic_t kp_tapan_priv;
+static int spkr_drv_wrnd_param_set(const char *val,
+				   const struct kernel_param *kp);
+static int spkr_drv_wrnd = 1;
+
+static struct kernel_param_ops spkr_drv_wrnd_param_ops = {
+	.set = spkr_drv_wrnd_param_set,
+	.get = param_get_int,
+};
+module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
+MODULE_PARM_DESC(spkr_drv_wrnd,
+	       "Run software workaround to avoid leakage on the speaker drive");
 
 #define WCD9306_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
@@ -42,10 +58,22 @@
 #define NUM_DECIMATORS 4
 #define NUM_INTERPOLATORS 4
 #define BITS_PER_REG 8
+/* This actual number of TX ports supported in slimbus slave */
 #define TAPAN_TX_PORT_NUMBER	16
 
-#define TAPAN_I2S_MASTER_MODE_MASK 0x08
+/* Nummer of TX ports actually connected from Slimbus slave to codec Digital */
+#define TAPAN_SLIM_CODEC_TX_PORTS 5
 
+#define TAPAN_I2S_MASTER_MODE_MASK 0x08
+#define TAPAN_MCLK_CLK_12P288MHZ 12288000
+#define TAPAN_MCLK_CLK_9P6HZ 9600000
+
+#define TAPAN_SLIM_CLOSE_TIMEOUT 1000
+#define TAPAN_SLIM_IRQ_OVERFLOW (1 << 0)
+#define TAPAN_SLIM_IRQ_UNDERFLOW (1 << 1)
+#define TAPAN_SLIM_IRQ_PORT_CLOSED (1 << 2)
+#define TAPAN_MCLK_CLK_12P288MHZ 12288000
+#define TAPAN_MCLK_CLK_9P6HZ 9600000
 enum {
 	AIF1_PB = 0,
 	AIF1_CAP,
@@ -67,8 +95,6 @@
 	RX_MIX1_INP_SEL_RX3,
 	RX_MIX1_INP_SEL_RX4,
 	RX_MIX1_INP_SEL_RX5,
-	RX_MIX1_INP_SEL_RX6,
-	RX_MIX1_INP_SEL_RX7,
 	RX_MIX1_INP_SEL_AUXRX,
 };
 
@@ -97,7 +123,8 @@
 };
 
 enum {
-	COMPANDER_1 = 0,
+	COMPANDER_0,
+	COMPANDER_1,
 	COMPANDER_2,
 	COMPANDER_MAX,
 };
@@ -152,6 +179,11 @@
 	(1 << AIF1_CAP) | (1 << AIF2_CAP),	/* AIF2_CAP */
 };
 
+static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
+	0,	/* AIF1_PB */
+	0,	/* AIF1_CAP */
+};
+
 struct tapan_priv {
 	struct snd_soc_codec *codec;
 	u32 adc_count;
@@ -168,22 +200,82 @@
 	/* num of slim ports required */
 	struct wcd9xxx_codec_dai_data  dai[NUM_CODEC_DAIS];
 
+	/*compander*/
+	int comp_enabled[COMPANDER_MAX];
+	u32 comp_fs[COMPANDER_MAX];
+
 	/* Maintain the status of AUX PGA */
 	int aux_pga_cnt;
 	u8 aux_l_gain;
 	u8 aux_r_gain;
 
+	bool spkr_pa_widget_on;
+
 	/* resmgr module */
 	struct wcd9xxx_resmgr resmgr;
 	/* mbhc module */
 	struct wcd9xxx_mbhc mbhc;
+
+	/* class h specific data */
+	struct wcd9xxx_clsh_cdc_data clsh_d;
 };
 
 static const u32 comp_shift[] = {
+	4, /* Compander 0's clock source is on interpolator 7 */
 	0,
 	2,
 };
 
+static const int comp_rx_path[] = {
+	COMPANDER_1,
+	COMPANDER_1,
+	COMPANDER_2,
+	COMPANDER_2,
+	COMPANDER_2,
+	COMPANDER_2,
+	COMPANDER_0,
+	COMPANDER_MAX,
+};
+
+static const struct comp_sample_dependent_params comp_samp_params[] = {
+	{
+		/* 8 Khz */
+		.peak_det_timeout = 0x02,
+		.rms_meter_div_fact = 0x09,
+		.rms_meter_resamp_fact = 0x06,
+	},
+	{
+		/* 16 Khz */
+		.peak_det_timeout = 0x03,
+		.rms_meter_div_fact = 0x0A,
+		.rms_meter_resamp_fact = 0x0C,
+	},
+	{
+		/* 32 Khz */
+		.peak_det_timeout = 0x05,
+		.rms_meter_div_fact = 0x0B,
+		.rms_meter_resamp_fact = 0x1E,
+	},
+	{
+		/* 48 Khz */
+		.peak_det_timeout = 0x05,
+		.rms_meter_div_fact = 0x0B,
+		.rms_meter_resamp_fact = 0x28,
+	},
+	{
+		/* 96 Khz */
+		.peak_det_timeout = 0x06,
+		.rms_meter_div_fact = 0x0C,
+		.rms_meter_resamp_fact = 0x50,
+	},
+	{
+		/* 192 Khz */
+		.peak_det_timeout = 0x07,
+		.rms_meter_div_fact = 0xD,
+		.rms_meter_resamp_fact = 0xA0,
+	},
+};
+
 static unsigned short rx_digital_gain_reg[] = {
 	TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
 	TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL,
@@ -198,71 +290,61 @@
 	TAPAN_A_CDC_TX4_VOL_CTL_GAIN,
 };
 
-static int tapan_codec_enable_class_h_clk(struct snd_soc_dapm_widget *w,
-		struct snd_kcontrol *kcontrol, int event)
+static int spkr_drv_wrnd_param_set(const char *val,
+				   const struct kernel_param *kp)
 {
-	struct snd_soc_codec *codec = w->codec;
+	struct snd_soc_codec *codec;
+	int ret, old;
+	struct tapan_priv *priv;
 
-	dev_dbg(codec->dev, "%s %s  %d\n", __func__, w->name, event);
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, TAPAN_A_CDC_CLSH_B1_CTL, 0x01, 0x01);
-		break;
-	case SND_SOC_DAPM_PRE_PMD:
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x80, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_CDC_CLSH_B1_CTL, 0x01, 0x00);
-		break;
+	priv = (struct tapan_priv *)atomic_read(&kp_tapan_priv);
+	if (!priv) {
+		pr_debug("%s: codec isn't yet registered\n", __func__);
+		return 0;
 	}
+
+	WCD9XXX_BCL_LOCK(&priv->resmgr);
+	old = spkr_drv_wrnd;
+	ret = param_set_int(val, kp);
+	if (ret) {
+		WCD9XXX_BCL_UNLOCK(&priv->resmgr);
+		return ret;
+	}
+
+	codec = priv->codec;
+	dev_dbg(codec->dev, "%s: spkr_drv_wrnd %d -> %d\n",
+			__func__, old, spkr_drv_wrnd);
+	if (old == 0 && spkr_drv_wrnd == 1) {
+		wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x80);
+	} else if (old == 1 && spkr_drv_wrnd == 0) {
+		wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		if (!priv->spkr_pa_widget_on)
+			snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80,
+					    0x00);
+	}
+
+	WCD9XXX_BCL_UNLOCK(&priv->resmgr);
 	return 0;
 }
 
-static int tapan_codec_enable_class_h(struct snd_soc_dapm_widget *w,
-		struct snd_kcontrol *kcontrol, int event)
+static int tapan_get_anc_slot(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = w->codec;
-
-	dev_dbg(codec->dev, "%s %s  %d\n", __func__, w->name, event);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x02);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_4, 0xFF, 0xFF);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x04, 0x04);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x04, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x80, 0x80);
-		usleep_range(1000, 1000);
-		break;
-	}
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	ucontrol->value.integer.value[0] = tapan->anc_slot;
 	return 0;
 }
 
-static int tapan_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
-		struct snd_kcontrol *kcontrol, int event)
+static int tapan_put_anc_slot(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = w->codec;
-
-	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, w->reg, 0x01, 0x01);
-		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x0f, 0x01);
-		break;
-
-	case SND_SOC_DAPM_POST_PMU:
-		usleep_range(1000, 1000);
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-	    snd_soc_update_bits(codec, w->reg, 0x01, 0x00);
-		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
-		snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x0f, 0x08);
-		break;
-	}
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	tapan->anc_slot = ucontrol->value.integer.value[0];
 	return 0;
 }
 
@@ -464,6 +546,168 @@
 	return 0;
 }
 
+static int tapan_get_compander(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int comp = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = tapan->comp_enabled[comp];
+	return 0;
+}
+
+static int tapan_set_compander(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	int comp = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
+		 __func__, comp, tapan->comp_enabled[comp], value);
+	tapan->comp_enabled[comp] = value;
+	return 0;
+}
+
+static int tapan_config_gain_compander(struct snd_soc_codec *codec,
+				       int comp, bool enable)
+{
+	int ret = 0;
+
+	switch (comp) {
+	case COMPANDER_0:
+		snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_GAIN,
+				    1 << 2, !enable << 2);
+		break;
+	case COMPANDER_1:
+		snd_soc_update_bits(codec, TAPAN_A_RX_HPH_L_GAIN,
+				    1 << 5, !enable << 5);
+		snd_soc_update_bits(codec, TAPAN_A_RX_HPH_R_GAIN,
+				    1 << 5, !enable << 5);
+		break;
+	case COMPANDER_2:
+		snd_soc_update_bits(codec, TAPAN_A_RX_LINE_1_GAIN,
+				    1 << 5, !enable << 5);
+		snd_soc_update_bits(codec, TAPAN_A_RX_LINE_2_GAIN,
+				    1 << 5, !enable << 5);
+		break;
+	default:
+		WARN_ON(1);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void tapan_discharge_comp(struct snd_soc_codec *codec, int comp)
+{
+	/* Update RSM to 1, DIVF to 5 */
+	snd_soc_write(codec, TAPAN_A_CDC_COMP0_B3_CTL + (comp * 8), 1);
+	snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8), 0xF0,
+			    1 << 5);
+	/* Wait for 1ms */
+	usleep_range(1000, 1000);
+}
+
+static int tapan_config_compander(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol, int event)
+{
+	int mask, emask;
+	bool timedout;
+	unsigned long timeout;
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	const int comp = w->shift;
+	const u32 rate = tapan->comp_fs[comp];
+	const struct comp_sample_dependent_params *comp_params =
+	    &comp_samp_params[rate];
+
+	dev_dbg(codec->dev, "%s: %s event %d compander %d, enabled %d",
+		__func__, w->name, event, comp, tapan->comp_enabled[comp]);
+
+	if (!tapan->comp_enabled[comp])
+		return 0;
+
+	/* Compander 0 has single channel */
+	mask = (comp == COMPANDER_0 ? 0x01 : 0x03);
+	emask = (comp == COMPANDER_0 ? 0x02 : 0x03);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Set gain source to compander */
+		tapan_config_gain_compander(codec, comp, true);
+		/* Enable RX interpolation path clocks */
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_B2_CTL,
+				    mask << comp_shift[comp],
+				    mask << comp_shift[comp]);
+
+		tapan_discharge_comp(codec, comp);
+
+		/* Clear compander halt */
+		snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B1_CTL +
+					   (comp * 8),
+				    1 << 2, 0);
+		/* Toggle compander reset bits */
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL,
+				    mask << comp_shift[comp],
+				    mask << comp_shift[comp]);
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL,
+				    mask << comp_shift[comp], 0);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* Set sample rate dependent paramater */
+		snd_soc_update_bits(codec,
+				    TAPAN_A_CDC_COMP0_FS_CFG + (comp * 8),
+				    0x07, rate);
+		snd_soc_write(codec, TAPAN_A_CDC_COMP0_B3_CTL + (comp * 8),
+			      comp_params->rms_meter_resamp_fact);
+		snd_soc_update_bits(codec,
+				    TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8),
+				    0x0F, comp_params->peak_det_timeout);
+		snd_soc_update_bits(codec,
+				    TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8),
+				    0xF0, comp_params->rms_meter_div_fact << 4);
+		/* Compander enable */
+		snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B1_CTL +
+				    (comp * 8), emask, emask);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		/* Halt compander */
+		snd_soc_update_bits(codec,
+				    TAPAN_A_CDC_COMP0_B1_CTL + (comp * 8),
+				    1 << 2, 1 << 2);
+		/* Wait up to a second for shutdown complete */
+		timeout = jiffies + HZ;
+		do {
+			if ((snd_soc_read(codec,
+					  TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS +
+					  (comp * 8)) & mask) == mask)
+				break;
+		} while (!(timedout = time_after(jiffies, timeout)));
+		dev_dbg(codec->dev, "%s: Compander %d shutdown %s in %dms\n",
+			 __func__, comp, timedout ? "timedout" : "completed",
+			 jiffies_to_msecs(timeout - HZ - jiffies));
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Disable compander */
+		snd_soc_update_bits(codec,
+				    TAPAN_A_CDC_COMP0_B1_CTL + (comp * 8),
+				    emask, 0x00);
+		/* Turn off the clock for compander in pair */
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_B2_CTL,
+				    mask << comp_shift[comp], 0);
+		/* Set gain source to register */
+		tapan_config_gain_compander(codec, comp, false);
+		break;
+	}
+	return 0;
+}
+
 static const char * const tapan_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
 static const struct soc_enum tapan_ear_pa_gain_enum[] = {
 		SOC_ENUM_SINGLE_EXT(2, tapan_ear_pa_gain_text),
@@ -498,21 +742,40 @@
 static const struct soc_enum cf_rxmix4_enum =
 	SOC_ENUM_SINGLE(TAPAN_A_CDC_RX4_B4_CTL, 0, 3, cf_text);
 
+static const char * const class_h_dsm_text[] = {
+	"ZERO", "RX_HPHL", "RX_SPKR"
+};
+
+static const struct soc_enum class_h_dsm_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_CLSH_CTL, 2, 3, class_h_dsm_text);
+
+static const struct snd_kcontrol_new class_h_dsm_mux =
+	SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
+
 static const struct snd_kcontrol_new tapan_snd_controls[] = {
 
 	SOC_ENUM_EXT("EAR PA Gain", tapan_ear_pa_gain_enum[0],
 		tapan_pa_gain_get, tapan_pa_gain_put),
 
-	SOC_SINGLE_TLV("LINEOUT1 Volume", TAPAN_A_RX_LINE_1_GAIN, 0, 12, 1,
+	SOC_SINGLE_TLV("HPHL Volume", TAPAN_A_RX_HPH_L_GAIN, 0, 14, 1,
 		line_gain),
-	SOC_SINGLE_TLV("LINEOUT2 Volume", TAPAN_A_RX_LINE_2_GAIN, 0, 12, 1,
+	SOC_SINGLE_TLV("HPHR Volume", TAPAN_A_RX_HPH_R_GAIN, 0, 14, 1,
 		line_gain),
 
-	SOC_SINGLE_TLV("HPHL Volume", TAPAN_A_RX_HPH_L_GAIN, 0, 12, 1,
+	SOC_SINGLE_TLV("LINEOUT1 Volume", TAPAN_A_RX_LINE_1_GAIN, 0, 14, 1,
 		line_gain),
-	SOC_SINGLE_TLV("HPHR Volume", TAPAN_A_RX_HPH_R_GAIN, 0, 12, 1,
+	SOC_SINGLE_TLV("LINEOUT2 Volume", TAPAN_A_RX_LINE_2_GAIN, 0, 14, 1,
 		line_gain),
 
+	SOC_SINGLE_TLV("SPK DRV Volume", TAPAN_A_SPKR_DRV_GAIN, 3, 7, 1,
+		line_gain),
+
+	SOC_SINGLE_TLV("ADC1 Volume", TAPAN_A_TX_1_EN, 2, 13, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC2 Volume", TAPAN_A_TX_2_EN, 2, 13, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC3 Volume", TAPAN_A_TX_3_EN, 2, 13, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC4 Volume", TAPAN_A_TX_4_EN, 2, 13, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC5 Volume", TAPAN_A_TX_5_EN, 2, 13, 0, analog_gain),
+
 	SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
 		-84, 40, digital_gain),
 	SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL,
@@ -540,9 +803,8 @@
 	SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAPAN_A_CDC_IIR1_GAIN_B4_CTL, -84,
 		40, digital_gain),
 
-	SOC_SINGLE("MICBIAS1 CAPLESS Switch", TAPAN_A_MICB_1_CTL, 4, 1, 1),
-	SOC_SINGLE("MICBIAS2 CAPLESS Switch", TAPAN_A_MICB_2_CTL, 4, 1, 1),
-	SOC_SINGLE("MICBIAS3 CAPLESS Switch", TAPAN_A_MICB_3_CTL, 4, 1, 1),
+	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, tapan_get_anc_slot,
+		tapan_put_anc_slot),
 
 	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
 	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
@@ -606,11 +868,23 @@
 	SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
 	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
 
+	SOC_SINGLE_EXT("COMP0 Switch", SND_SOC_NOPM, COMPANDER_0, 1, 0,
+		       tapan_get_compander, tapan_set_compander),
+	SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
+		       tapan_get_compander, tapan_set_compander),
+	SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
+		       tapan_get_compander, tapan_set_compander),
+
 };
 
-static const char * const rx_mix1_text[] = {
+static const char * const rx_1_2_mix1_text[] = {
 	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
-		"RX5", "RX6", "RX7"
+		"RX5", "AUXRX", "AUXTX1"
+};
+
+static const char * const rx_3_4_mix1_text[] = {
+	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
+		"RX5", "AUXRX", "AUXTX1", "AUXTX2"
 };
 
 static const char * const rx_mix2_text[] = {
@@ -621,86 +895,85 @@
 	"DEM4", "DEM3_INV"
 };
 
-static const char * const rx_rdac7_text[] = {
-	"DEM6", "DEM5_INV"
-};
-
-static const char * const sb_tx1_mux_text[] = {
-	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
-		"DEC1"
-};
-
-static const char * const sb_tx2_mux_text[] = {
-	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
-		"DEC2"
+static const char * const sb_tx_1_2_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4",
+	"RSVD", "RSVD", "RSVD",
+	"DEC1", "DEC2", "DEC3", "DEC4"
 };
 
 static const char * const sb_tx3_mux_text[] = {
-	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
-		"DEC3"
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4",
+	"RSVD", "RSVD", "RSVD", "RSVD", "RSVD",
+	"DEC3"
 };
 
 static const char * const sb_tx4_mux_text[] = {
-	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
-		"DEC4"
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4",
+	"RSVD", "RSVD", "RSVD", "RSVD", "RSVD", "RSVD",
+	"DEC4"
 };
 
-static const char * const dec1_mux_text[] = {
-	"ZERO", "DMIC1", "ADC6",
+static const char * const sb_tx5_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4",
+	"RSVD", "RSVD", "RSVD",
+	"DEC1"
 };
 
-static const char * const dec2_mux_text[] = {
-	"ZERO", "DMIC2", "ADC5",
+static const char * const dec_1_2_mux_text[] = {
+	"ZERO", "ADC1", "ADC2", "ADC3", "ADC4",  "ADCMB",
+	"DMIC1", "DMIC2", "DMIC3", "DMIC4"
 };
 
 static const char * const dec3_mux_text[] = {
-	"ZERO", "DMIC3", "ADC4",
+	"ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADCMB",
+	"DMIC1", "DMIC2", "DMIC3", "DMIC4",
+	"ANCFBTUNE1"
 };
 
 static const char * const dec4_mux_text[] = {
-	"ZERO", "DMIC4", "ADC3",
+	"ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADCMB",
+	"DMIC1", "DMIC2", "DMIC3", "DMIC4",
+	"ANCFBTUNE2"
 };
 
 static const char * const anc_mux_text[] = {
-	"ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
-		"RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
-};
-
-static const char * const anc1_fb_mux_text[] = {
-	"ZERO", "EAR_HPH_L", "EAR_LINE_1",
+	"ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5",
+	"RSVD", "RSVD", "RSVD",
+	"DMIC1", "DMIC2", "DMIC3", "DMIC4",
+	"RSVD", "RSVD"
 };
 
 static const char * const iir1_inp1_text[] = {
-	"ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
-	"DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
+	"ZERO", "DEC1", "DEC2", "DEC3", "DEC4",
+	"RX1", "RX2", "RX3", "RX4", "RX5"
 };
 
 static const struct soc_enum rx_mix1_inp1_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_1_2_mix1_text);
 
 static const struct soc_enum rx_mix1_inp2_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_1_2_mix1_text);
 
 static const struct soc_enum rx_mix1_inp3_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_1_2_mix1_text);
 
 static const struct soc_enum rx2_mix1_inp1_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_1_2_mix1_text);
 
 static const struct soc_enum rx2_mix1_inp2_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_1_2_mix1_text);
 
 static const struct soc_enum rx3_mix1_inp1_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 0, 13, rx_3_4_mix1_text);
 
 static const struct soc_enum rx3_mix1_inp2_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 4, 13, rx_3_4_mix1_text);
 
 static const struct soc_enum rx4_mix1_inp1_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 0, 13, rx_3_4_mix1_text);
 
 static const struct soc_enum rx4_mix1_inp2_chain_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 4, 13, rx_3_4_mix1_text);
 
 static const struct soc_enum rx1_mix2_inp1_chain_enum =
 	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
@@ -714,38 +987,52 @@
 static const struct soc_enum rx2_mix2_inp2_chain_enum =
 	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
 
+static const struct soc_enum rx4_mix2_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx4_mix2_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B3_CTL, 3, 5, rx_mix2_text);
+
 static const struct soc_enum rx_rdac5_enum =
 	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
 
-static const struct soc_enum rx_rdac7_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_MISC, 1, 2, rx_rdac7_text);
-
 static const struct soc_enum sb_tx1_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B1_CTL, 0, 12,
+					sb_tx_1_2_mux_text);
 
 static const struct soc_enum sb_tx2_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B2_CTL, 0, 12,
+					sb_tx_1_2_mux_text);
 
 static const struct soc_enum sb_tx3_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B3_CTL, 0, 11, sb_tx3_mux_text);
 
 static const struct soc_enum sb_tx4_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B4_CTL, 0, 12, sb_tx4_mux_text);
+
+static const struct soc_enum sb_tx5_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
 
 static const struct soc_enum dec1_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 0, 10, dec_1_2_mux_text);
 
 static const struct soc_enum dec2_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 4, 10, dec_1_2_mux_text);
 
 static const struct soc_enum dec3_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B2_CTL, 0, 12, dec3_mux_text);
 
 static const struct soc_enum dec4_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B2_CTL, 4, 12, dec4_mux_text);
+
+static const struct soc_enum anc1_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_ANC_B1_CTL, 0, 15, anc_mux_text);
+
+static const struct soc_enum anc2_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_ANC_B1_CTL, 4, 15, anc_mux_text);
 
 static const struct soc_enum iir1_inp1_mux_enum =
-	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_EQ1_B1_CTL, 0, 10, iir1_inp1_text);
 
 static const struct snd_kcontrol_new rx_mix1_inp1_mux =
 	SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
@@ -786,6 +1073,12 @@
 static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
 	SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
 
+static const struct snd_kcontrol_new rx4_mix2_inp1_mux =
+	SOC_DAPM_ENUM("RX4 MIX2 INP1 Mux", rx4_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx4_mix2_inp2_mux =
+	SOC_DAPM_ENUM("RX4 MIX2 INP2 Mux", rx4_mix2_inp2_chain_enum);
+
 static const struct snd_kcontrol_new rx_dac5_mux =
 	SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
 
@@ -801,9 +1094,8 @@
 static const struct snd_kcontrol_new sb_tx4_mux =
 	SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
 
-/*static const struct snd_kcontrol_new sb_tx5_mux =
+static const struct snd_kcontrol_new sb_tx5_mux =
 	SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
-*/
 
 static int wcd9306_put_dec_enum(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
@@ -851,23 +1143,17 @@
 	switch (decimator) {
 	case 1:
 	case 2:
+		if ((dec_mux >= 1) && (dec_mux <= 5))
+			adc_dmic_sel = 0x0;
+		else if ((dec_mux >= 6) && (dec_mux <= 9))
+			adc_dmic_sel = 0x1;
+		break;
 	case 3:
 	case 4:
-	case 5:
-	case 6:
-		if (dec_mux == 1)
-			adc_dmic_sel = 0x1;
-		else
+		if ((dec_mux >= 1) && (dec_mux <= 6))
 			adc_dmic_sel = 0x0;
-		break;
-	case 7:
-	case 8:
-	case 9:
-	case 10:
-		if ((dec_mux == 1) || (dec_mux == 2))
+		else if ((dec_mux >= 7) && (dec_mux <= 10))
 			adc_dmic_sel = 0x1;
-		else
-			adc_dmic_sel = 0x0;
 		break;
 	default:
 		pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
@@ -908,6 +1194,12 @@
 static const struct snd_kcontrol_new iir1_inp1_mux =
 	SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
 
+static const struct snd_kcontrol_new anc1_mux =
+	SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
+
+static const struct snd_kcontrol_new anc2_mux =
+	SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
+
 static const struct snd_kcontrol_new dac1_switch[] = {
 	SOC_DAPM_SINGLE("Switch", TAPAN_A_RX_EAR_EN, 5, 1, 0)
 };
@@ -915,6 +1207,10 @@
 	SOC_DAPM_SINGLE("Switch", TAPAN_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
 };
 
+static const struct snd_kcontrol_new spk_dac_switch[] = {
+	SOC_DAPM_SINGLE("Switch", TAPAN_A_SPKR_DRV_DAC_CTL, 2, 1, 0)
+};
+
 static const struct snd_kcontrol_new hphl_pa_mix[] = {
 	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
 					7, 1, 0),
@@ -939,15 +1235,6 @@
 					3, 1, 0),
 };
 
-static const struct snd_kcontrol_new lineout3_pa_mix[] = {
-	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
-					2, 1, 0),
-};
-
-static const struct snd_kcontrol_new lineout4_pa_mix[] = {
-	SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
-					1, 1, 0),
-};
 
 /* virtual port entries */
 static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
@@ -973,6 +1260,7 @@
 	u32 dai_id = widget->shift;
 	u32 port_id = mixer->shift;
 	u32 enable = ucontrol->value.integer.value[0];
+	u32 vtable = vport_check_table[dai_id];
 
 	dev_dbg(codec->dev, "%s: wname %s cname %s\n",
 		__func__, widget->name,	ucontrol->id.name);
@@ -997,8 +1285,15 @@
 		/* only add to the list if value not set
 		 */
 		if (enable && !(widget->value & 1 << port_id)) {
+			if (tapan_p->intf_type ==
+					WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+				vtable = vport_check_table[dai_id];
+			if (tapan_p->intf_type ==
+					WCD9XXX_INTERFACE_TYPE_I2C)
+				vtable = vport_i2s_check_table[dai_id];
+
 			if (wcd9xxx_tx_vport_validation(
-						vport_check_table[dai_id],
+						vtable,
 						port_id,
 						tapan_p->dai)) {
 				dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
@@ -1009,27 +1304,29 @@
 			widget->value |= 1 << port_id;
 			list_add_tail(&core->tx_chs[port_id].list,
 				      &tapan_p->dai[dai_id].wcd9xxx_ch_list
-				      );
+					      );
 		} else if (!enable && (widget->value & 1 << port_id)) {
 			widget->value &= ~(1 << port_id);
 			list_del_init(&core->tx_chs[port_id].list);
 		} else {
 			if (enable)
-				dev_dbg(codec->dev, "%s: TX%u port is used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is used by\n"
+					"this virtual port\n",
 					__func__, port_id + 1);
 			else
-				dev_dbg(codec->dev, "%s: TX%u port is not used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
+					"this virtual port\n",
 					__func__, port_id + 1);
 			/* avoid update power function */
 			mutex_unlock(&codec->mutex);
 			return 0;
 		}
 		break;
-	default:
-		pr_err("Unknown AIF %d\n", dai_id);
-		mutex_unlock(&codec->mutex);
-		return -EINVAL;
-	}
+		default:
+			dev_err(codec->dev, "Unknown AIF %d\n", dai_id);
+			mutex_unlock(&codec->mutex);
+			return -EINVAL;
+		}
 	dev_dbg(codec->dev, "%s: name %s sname %s updated value %u shift %d\n",
 		 __func__, widget->name, widget->sname,
 		 widget->value, widget->shift);
@@ -1153,6 +1450,49 @@
 			slim_tx_mixer_get, slim_tx_mixer_put),
 };
 
+static int tapan_codec_enable_adc(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	u16 adc_reg;
+	u8 init_bit_shift;
+
+	dev_dbg(codec->dev, "%s(): %s %d\n", __func__, w->name, event);
+
+	if (w->reg == TAPAN_A_TX_1_EN) {
+		init_bit_shift = 7;
+		adc_reg = TAPAN_A_TX_1_2_TEST_CTL;
+	} else if (w->reg == TAPAN_A_TX_2_EN) {
+		init_bit_shift = 6;
+		adc_reg = TAPAN_A_TX_1_2_TEST_CTL;
+	} else if (w->reg == TAPAN_A_TX_3_EN) {
+		init_bit_shift = 6;
+		adc_reg = TAPAN_A_TX_1_2_TEST_CTL;
+	} else if (w->reg == TAPAN_A_TX_4_EN) {
+		init_bit_shift = 7;
+		adc_reg = TAPAN_A_TX_4_5_TEST_CTL;
+	} else if (w->reg == TAPAN_A_TX_5_EN) {
+		init_bit_shift = 6;
+		adc_reg = TAPAN_A_TX_4_5_TEST_CTL;
+	} else {
+		pr_err("%s: Error, invalid adc register\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
+				1 << init_bit_shift);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+
+		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+
+		break;
+	}
+	return 0;
+}
+
 static int tapan_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -1188,6 +1528,7 @@
 		struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
 	u16 lineout_gain_reg;
 
 	dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
@@ -1207,15 +1548,21 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
-		dev_dbg(codec->dev, "%s: sleeping 16 ms after %s PA turn on\n",
+		wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+						 WCD9XXX_CLSH_STATE_LO,
+						 WCD9XXX_CLSH_REQ_ENABLE,
+						 WCD9XXX_CLSH_EVENT_POST_PA);
+		dev_dbg(codec->dev, "%s: sleeping 3 ms after %s PA turn on\n",
 				__func__, w->name);
-		usleep_range(16000, 16000);
+		usleep_range(3000, 3010);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
+		wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+						 WCD9XXX_CLSH_STATE_LO,
+						 WCD9XXX_CLSH_REQ_DISABLE,
+						 WCD9XXX_CLSH_EVENT_POST_PA);
 		break;
 	}
 	return 0;
@@ -1224,7 +1571,22 @@
 static int tapan_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
 				     struct snd_kcontrol *kcontrol, int event)
 {
-	dev_dbg(w->codec->dev, "%s %d %s\n", __func__, event, w->name);
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s: %s %d\n", __func__, w->name, event);
+	WCD9XXX_BCL_LOCK(&tapan->resmgr);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		tapan->spkr_pa_widget_on = true;
+		snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x80);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		tapan->spkr_pa_widget_on = false;
+		snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x00);
+		break;
+	}
+	WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
 	return 0;
 }
 
@@ -1239,7 +1601,7 @@
 	unsigned int dmic;
 	int ret;
 
-	ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
+	ret = kstrtouint(strpbrk(w->name, "1234"), 10, &dmic);
 	if (ret < 0) {
 		pr_err("%s: Invalid DMIC line on the codec\n", __func__);
 		return -EINVAL;
@@ -1266,17 +1628,6 @@
 			__func__, event,  dmic, *dmic_clk_cnt);
 		break;
 
-	case 5:
-	case 6:
-		dmic_clk_en = 0x01;
-		dmic_clk_cnt = &(tapan->dmic_5_6_clk_cnt);
-		dmic_clk_reg = TAPAN_A_CDC_CLK_DMIC_B2_CTL;
-
-		dev_dbg(codec->dev, "%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
-			__func__, event,  dmic, *dmic_clk_cnt);
-
-		break;
-
 	default:
 		pr_err("%s: Invalid DMIC Selection\n", __func__);
 		return -EINVAL;
@@ -1600,7 +1951,7 @@
 					msecs_to_jiffies(300));
 		}
 		/* apply the digital gain after the decimator is enabled*/
-		if ((w->shift) < ARRAY_SIZE(tx_digital_gain_reg))
+		if ((w->shift + offset) < ARRAY_SIZE(tx_digital_gain_reg))
 			snd_soc_write(codec,
 				  tx_digital_gain_reg[w->shift + offset],
 				  snd_soc_read(codec,
@@ -1628,6 +1979,42 @@
 	return ret;
 }
 
+static int tapan_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
+				       struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+
+	dev_dbg(codec->dev, "%s: %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+
+		if (spkr_drv_wrnd > 0) {
+			WARN_ON(!(snd_soc_read(codec, TAPAN_A_SPKR_DRV_EN) &
+				  0x80));
+			snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80,
+					    0x00);
+		}
+		if (TAPAN_IS_1_0(core->version))
+			snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_DBG_PWRSTG,
+					    0x24, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (TAPAN_IS_1_0(core->version))
+			snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_DBG_PWRSTG,
+					    0x24, 0x24);
+		if (spkr_drv_wrnd > 0) {
+			WARN_ON(!!(snd_soc_read(codec, TAPAN_A_SPKR_DRV_EN) &
+				   0x80));
+			snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80,
+					    0x80);
+		}
+		break;
+	}
+	return 0;
+}
+
 static int tapan_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -1685,18 +2072,53 @@
 	}
 	return 0;
 }
-static int tapan_hphr_dac_event(struct snd_soc_dapm_widget *w,
+
+
+static int tapan_hphl_dac_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
 
 	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL,
+							0x02, 0x02);
+		wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+						 WCD9XXX_CLSH_STATE_HPHL,
+						 WCD9XXX_CLSH_REQ_ENABLE,
+						 WCD9XXX_CLSH_EVENT_PRE_DAC);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL,
+							0x02, 0x00);
+	}
+	return 0;
+}
+
+static int tapan_hphr_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL,
+							0x04, 0x04);
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+		wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+						 WCD9XXX_CLSH_STATE_HPHR,
+						 WCD9XXX_CLSH_REQ_ENABLE,
+						 WCD9XXX_CLSH_EVENT_PRE_DAC);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL,
+							0x04, 0x00);
 		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
 		break;
 	}
@@ -1709,14 +2131,17 @@
 	struct snd_soc_codec *codec = w->codec;
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
 	enum wcd9xxx_notify_event e_pre_on, e_post_off;
+	u8 req_clsh_state;
 
 	dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
 	if (w->shift == 5) {
 		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
 		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
+		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
 	} else if (w->shift == 4) {
 		e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
 		e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+		req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
 	} else {
 		pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
 		return -EINVAL;
@@ -1729,43 +2154,51 @@
 		break;
 
 	case SND_SOC_DAPM_POST_PMU:
-		usleep_range(10000, 10000);
+		wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+						 req_clsh_state,
+						 WCD9XXX_CLSH_REQ_ENABLE,
+						 WCD9XXX_CLSH_EVENT_POST_PA);
 
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x20, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x04);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
 
-		usleep_range(10, 10);
+		usleep_range(5000, 5010);
 		break;
 
 	case SND_SOC_DAPM_POST_PMD:
 		/* Let MBHC module know PA turned off */
 		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off);
 
-		/*
-		 * schedule work is required because at the time HPH PA DAPM
-		 * event callback is called by DAPM framework, CODEC dapm mutex
-		 * would have been locked while snd_soc_jack_report also
-		 * attempts to acquire same lock.
-		 */
+		wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+						 req_clsh_state,
+						 WCD9XXX_CLSH_REQ_DISABLE,
+						 WCD9XXX_CLSH_EVENT_POST_PA);
+
 		dev_dbg(codec->dev, "%s: sleep 10 ms after %s PA disable.\n",
 			 __func__, w->name);
-		usleep_range(5000, 5000);
+		usleep_range(5000, 5010);
 		break;
 	}
 	return 0;
 }
 
+static const struct snd_soc_dapm_widget tapan_dapm_i2s_widgets[] = {
+	SND_SOC_DAPM_SUPPLY("I2S_CLK", TAPAN_A_CDC_CLK_I2S_CTL,
+	4, 0, NULL, 0),
+};
+
 static int tapan_lineout_dac_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
 
 	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
+		wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+						 WCD9XXX_CLSH_STATE_LO,
+						 WCD9XXX_CLSH_REQ_ENABLE,
+						 WCD9XXX_CLSH_EVENT_PRE_DAC);
 		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
 		break;
 
@@ -1786,12 +2219,12 @@
 }
 
 static const struct snd_soc_dapm_route audio_i2s_map[] = {
-	{"RX_I2S_CLK", NULL, "CDC_CONN"},
-	{"SLIM RX1", NULL, "RX_I2S_CLK"},
-	{"SLIM RX2", NULL, "RX_I2S_CLK"},
+	{"I2S_CLK", NULL, "CDC_CONN"},
+	{"SLIM RX1", NULL, "I2S_CLK"},
+	{"SLIM RX2", NULL, "I2S_CLK"},
 
-	{"SLIM TX1 MUX", NULL, "TX_I2S_CLK"},
-	{"SLIM TX2 MUX", NULL, "TX_I2S_CLK"},
+	{"SLIM TX1 MUX", NULL, "I2S_CLK"},
+	{"SLIM TX2 MUX", NULL, "I2S_CLK"},
 };
 
 static const struct snd_soc_dapm_route audio_map[] = {
@@ -1806,122 +2239,60 @@
 	{"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
 	{"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
 	{"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
-	{"AIF1_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
-	{"AIF1_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
-	{"AIF1_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
-	{"AIF1_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
-	{"AIF1_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
 	/* SLIM_MIXER("AIF2_CAP Mixer"),*/
 	{"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
 	{"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
 	{"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
 	{"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
 	{"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
-	{"AIF2_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
-	{"AIF2_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
-	{"AIF2_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
-	{"AIF2_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
-	{"AIF2_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
 	/* SLIM_MIXER("AIF3_CAP Mixer"),*/
 	{"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
 	{"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
 	{"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
 	{"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
 	{"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
-	{"AIF3_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
-	{"AIF3_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
-	{"AIF3_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
-	{"AIF3_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
-	{"AIF3_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
 
 	{"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX1 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX1 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX1 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX1 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX1 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX1 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX1 MUX", "RMIX4", "RX4 MIX1"},
 
+	{"SLIM TX2 MUX", "DEC1", "DEC1 MUX"},
 	{"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX2 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX2 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX2 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX2 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX2 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX2 MUX", "RMIX4", "RX4 MIX1"},
 
 	{"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
 	{"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
 	{"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
 	{"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
 	{"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
-	{"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
-	{"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
-	{"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
 
 	{"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX4 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX4 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX4 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX4 MUX", "RMIX4", "RX4 MIX1"},
 
-	{"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX5 MUX", "DEC1", "DEC1 MUX"},
 	{"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
 	{"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
 	{"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
 	{"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
-	{"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
-	{"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
-	{"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
-
-	{"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
-
-	{"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
-	{"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
-	{"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
-	{"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
-	{"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
-	{"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
-	{"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
-	{"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
-	{"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
-	{"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
-	{"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
-	{"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
-	{"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
-	{"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
-	{"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
-	{"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
-	{"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
-
-	{"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
-	{"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
-	{"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
-	{"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
-	{"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
-	{"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
-	{"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
-	{"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
-	{"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
-	{"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
-
-	{"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
-	{"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
-	{"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
-	{"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
-	{"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
-	{"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
-	{"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
-	{"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
-	{"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
-	{"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
-
-	{"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
-	{"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
-	{"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
-	{"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
-	{"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
-	{"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
-	{"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
-	{"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
-	{"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
-	{"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
 
 	/* Earpiece (RX MIX1) */
 	{"EAR", NULL, "EAR PA"},
 	{"EAR PA", NULL, "EAR_PA_MIXER"},
 	{"EAR_PA_MIXER", NULL, "DAC1"},
-	{"DAC1", NULL, "CP"},
-	{"CP", NULL, "CLASS_H_EAR"},
-	{"CLASS_H_EAR", NULL, "CLASS_H_CLK"},
-
-	{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
-	{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
-	{"ANC", NULL, "ANC1 FB MUX"},
+	{"DAC1", NULL, "RX_BIAS"},
 
 	/* Headset (RX MIX1 and RX MIX2) */
 	{"HEADPHONE", NULL, "HPHL"},
@@ -1929,93 +2300,47 @@
 
 	{"HPHL", NULL, "HPHL_PA_MIXER"},
 	{"HPHL_PA_MIXER", NULL, "HPHL DAC"},
+	{"HPHL DAC", NULL, "RX_BIAS"},
 
 	{"HPHR", NULL, "HPHR_PA_MIXER"},
 	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
+	{"HPHR DAC", NULL, "RX_BIAS"},
 
-	{"HPHL DAC", NULL, "CP"},
-	{"CP", NULL, "CLASS_H_HPH_L"},
-	{"CLASS_H_HPH_L", NULL, "CLASS_H_CLK"},
-
-	{"HPHR DAC", NULL, "CP"},
-	{"CP", NULL, "CLASS_H_HPH_R"},
-	{"CLASS_H_HPH_R", NULL, "CLASS_H_CLK"},
-
-	{"ANC", NULL, "ANC1 MUX"},
-	{"ANC", NULL, "ANC2 MUX"},
-	{"ANC1 MUX", "ADC1", "ADC1"},
-	{"ANC1 MUX", "ADC2", "ADC2"},
-	{"ANC1 MUX", "ADC3", "ADC3"},
-	{"ANC1 MUX", "ADC4", "ADC4"},
-	{"ANC2 MUX", "ADC1", "ADC1"},
-	{"ANC2 MUX", "ADC2", "ADC2"},
-	{"ANC2 MUX", "ADC3", "ADC3"},
-	{"ANC2 MUX", "ADC4", "ADC4"},
-
-	{"ANC", NULL, "CDC_CONN"},
-
-	{"DAC1", "Switch", "RX1 CHAIN"},
-	{"HPHL DAC", "Switch", "RX1 CHAIN"},
+	{"DAC1", "Switch", "CLASS_H_DSM MUX"},
+	{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
 	{"HPHR DAC", NULL, "RX2 CHAIN"},
 
 	{"LINEOUT1", NULL, "LINEOUT1 PA"},
 	{"LINEOUT2", NULL, "LINEOUT2 PA"},
-	{"LINEOUT3", NULL, "LINEOUT3 PA"},
-	{"LINEOUT4", NULL, "LINEOUT4 PA"},
 	{"SPK_OUT", NULL, "SPK PA"},
 
-	{"LINEOUT1 PA", NULL, "CP"},
 	{"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
 	{"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
 
-	{"LINEOUT2 PA", NULL, "CP"},
 	{"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
 	{"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
 
-	{"LINEOUT3 PA", NULL, "CP"},
-	{"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
-	{"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
-
-	{"LINEOUT4 PA", NULL, "CP"},
-	{"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
-	{"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
-
-	{"CP", NULL, "CLASS_H_LINEOUTS_PA"},
-	{"CLASS_H_LINEOUTS_PA", NULL, "CLASS_H_CLK"},
-
 	{"LINEOUT1 DAC", NULL, "RX3 MIX1"},
 
 	{"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
-	{"RDAC5 MUX", "DEM4", "RX4 MIX1"},
+	{"RDAC5 MUX", "DEM4", "RX4 MIX2"},
 
-	{"LINEOUT3 DAC", NULL, "RDAC5 MUX"},
-
-	{"LINEOUT2 DAC", NULL, "RX5 MIX1"},
-
-	{"RDAC7 MUX", "DEM5_INV", "RX5 MIX1"},
-	{"RDAC7 MUX", "DEM6", "RX6 MIX1"},
-
-	{"LINEOUT4 DAC", NULL, "RDAC7 MUX"},
+	{"LINEOUT2 DAC", NULL, "RDAC5 MUX"},
 
 	{"SPK PA", NULL, "SPK DAC"},
-	{"SPK DAC", NULL, "RX7 MIX2"},
+	{"SPK DAC", "Switch", "RX4 MIX2"},
+	{"SPK DAC", NULL, "VDD_SPKDRV"},
 
 	{"RX1 CHAIN", NULL, "RX1 MIX2"},
 	{"RX2 CHAIN", NULL, "RX2 MIX2"},
-	{"RX1 CHAIN", NULL, "ANC"},
-	{"RX2 CHAIN", NULL, "ANC"},
+	{"CLASS_H_DSM MUX", "RX_HPHL", "RX1 CHAIN"},
 
-	{"CLASS_H_CLK", NULL, "RX_BIAS"},
 	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
 	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
-	{"LINEOUT3 DAC", NULL, "RX_BIAS"},
-	{"LINEOUT4 DAC", NULL, "RX_BIAS"},
-	{"SPK DAC", NULL, "RX_BIAS"},
 
 	{"RX1 MIX1", NULL, "COMP1_CLK"},
 	{"RX2 MIX1", NULL, "COMP1_CLK"},
 	{"RX3 MIX1", NULL, "COMP2_CLK"},
-	{"RX5 MIX1", NULL, "COMP2_CLK"},
 
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
@@ -2026,21 +2351,15 @@
 	{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
 	{"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
 	{"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
-	{"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
-	{"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
-	{"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
-	{"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
-	{"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
-	{"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
 	{"RX1 MIX2", NULL, "RX1 MIX1"},
 	{"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
 	{"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
 	{"RX2 MIX2", NULL, "RX2 MIX1"},
 	{"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
 	{"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
-	{"RX7 MIX2", NULL, "RX7 MIX1"},
-	{"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
-	{"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
+	{"RX4 MIX2", NULL, "RX4 MIX1"},
+	{"RX4 MIX2", NULL, "RX4 MIX2 INP1"},
+	{"RX4 MIX2", NULL, "RX4 MIX2 INP2"},
 
 	/* SLIM_MUX("AIF1_PB", "AIF1 PB"),*/
 	{"SLIM RX1 MUX", "AIF1_PB", "AIF1 PB"},
@@ -2048,198 +2367,128 @@
 	{"SLIM RX3 MUX", "AIF1_PB", "AIF1 PB"},
 	{"SLIM RX4 MUX", "AIF1_PB", "AIF1 PB"},
 	{"SLIM RX5 MUX", "AIF1_PB", "AIF1 PB"},
-	{"SLIM RX6 MUX", "AIF1_PB", "AIF1 PB"},
-	{"SLIM RX7 MUX", "AIF1_PB", "AIF1 PB"},
 	/* SLIM_MUX("AIF2_PB", "AIF2 PB"),*/
 	{"SLIM RX1 MUX", "AIF2_PB", "AIF2 PB"},
 	{"SLIM RX2 MUX", "AIF2_PB", "AIF2 PB"},
 	{"SLIM RX3 MUX", "AIF2_PB", "AIF2 PB"},
 	{"SLIM RX4 MUX", "AIF2_PB", "AIF2 PB"},
 	{"SLIM RX5 MUX", "AIF2_PB", "AIF2 PB"},
-	{"SLIM RX6 MUX", "AIF2_PB", "AIF2 PB"},
-	{"SLIM RX7 MUX", "AIF2_PB", "AIF2 PB"},
 	/* SLIM_MUX("AIF3_PB", "AIF3 PB"),*/
 	{"SLIM RX1 MUX", "AIF3_PB", "AIF3 PB"},
 	{"SLIM RX2 MUX", "AIF3_PB", "AIF3 PB"},
 	{"SLIM RX3 MUX", "AIF3_PB", "AIF3 PB"},
 	{"SLIM RX4 MUX", "AIF3_PB", "AIF3 PB"},
 	{"SLIM RX5 MUX", "AIF3_PB", "AIF3 PB"},
-	{"SLIM RX6 MUX", "AIF3_PB", "AIF3 PB"},
-	{"SLIM RX7 MUX", "AIF3_PB", "AIF3 PB"},
 
 	{"SLIM RX1", NULL, "SLIM RX1 MUX"},
 	{"SLIM RX2", NULL, "SLIM RX2 MUX"},
 	{"SLIM RX3", NULL, "SLIM RX3 MUX"},
 	{"SLIM RX4", NULL, "SLIM RX4 MUX"},
 	{"SLIM RX5", NULL, "SLIM RX5 MUX"},
-	{"SLIM RX6", NULL, "SLIM RX6 MUX"},
-	{"SLIM RX7", NULL, "SLIM RX7 MUX"},
 
 	{"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
-	{"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
-	{"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX1 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
-	{"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
-	{"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX1 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
 	{"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
 	{"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
-	{"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
-	{"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
-	{"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
-	{"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
-	{"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
-	{"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
-	{"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
-	{"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX3 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
 	{"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
-	{"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
-	{"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX3 MIX1 INP2", "IIR1", "IIR1"},
 	{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
 	{"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
 	{"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
-	{"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
-	{"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX4 MIX1 INP1", "IIR1", "IIR1"},
 	{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
 	{"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
 	{"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
-	{"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
-	{"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX4 MIX1 INP2", "IIR1", "IIR1"},
-	{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
-	{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
-	{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
-	{"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
-	{"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
-	{"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
-	{"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
-	{"RX5 MIX1 INP1", "IIR1", "IIR1"},
-	{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
-	{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
-	{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
-	{"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
-	{"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
-	{"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
-	{"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
-	{"RX5 MIX1 INP2", "IIR1", "IIR1"},
-	{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
-	{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
-	{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
-	{"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
-	{"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
-	{"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
-	{"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
-	{"RX6 MIX1 INP1", "IIR1", "IIR1"},
-	{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
-	{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
-	{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
-	{"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
-	{"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
-	{"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
-	{"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
-	{"RX6 MIX1 INP2", "IIR1", "IIR1"},
-	{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
-	{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
-	{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
-	{"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
-	{"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
-	{"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
-	{"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
-	{"RX7 MIX1 INP1", "IIR1", "IIR1"},
-	{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
-	{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
-	{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
-	{"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
-	{"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
-	{"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
-	{"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
-	{"RX7 MIX1 INP2", "IIR1", "IIR1"},
+
 	{"RX1 MIX2 INP1", "IIR1", "IIR1"},
 	{"RX1 MIX2 INP2", "IIR1", "IIR1"},
 	{"RX2 MIX2 INP1", "IIR1", "IIR1"},
 	{"RX2 MIX2 INP2", "IIR1", "IIR1"},
-	{"RX7 MIX2 INP1", "IIR1", "IIR1"},
-	{"RX7 MIX2 INP2", "IIR1", "IIR1"},
+	{"RX4 MIX2 INP1", "IIR1", "IIR1"},
+	{"RX4 MIX2 INP2", "IIR1", "IIR1"},
 
 	/* Decimator Inputs */
+	{"DEC1 MUX", "ADC1", "ADC1"},
+	{"DEC1 MUX", "ADC2", "ADC2"},
+	{"DEC1 MUX", "ADC3", "ADC3"},
+	{"DEC1 MUX", "ADC4", "ADC4"},
 	{"DEC1 MUX", "DMIC1", "DMIC1"},
-	{"DEC1 MUX", "ADC6", "ADC6"},
+	{"DEC1 MUX", "DMIC2", "DMIC2"},
+	{"DEC1 MUX", "DMIC3", "DMIC3"},
+	{"DEC1 MUX", "DMIC4", "DMIC4"},
 	{"DEC1 MUX", NULL, "CDC_CONN"},
+
+	{"DEC2 MUX", "ADC1", "ADC1"},
+	{"DEC2 MUX", "ADC2", "ADC2"},
+	{"DEC2 MUX", "ADC3", "ADC3"},
+	{"DEC2 MUX", "ADC4", "ADC4"},
+	{"DEC2 MUX", "DMIC1", "DMIC1"},
 	{"DEC2 MUX", "DMIC2", "DMIC2"},
-	{"DEC2 MUX", "ADC5", "ADC5"},
+	{"DEC2 MUX", "DMIC3", "DMIC3"},
+	{"DEC2 MUX", "DMIC4", "DMIC4"},
 	{"DEC2 MUX", NULL, "CDC_CONN"},
-	{"DEC3 MUX", "DMIC3", "DMIC3"},
+
+	{"DEC3 MUX", "ADC1", "ADC1"},
+	{"DEC3 MUX", "ADC2", "ADC2"},
+	{"DEC3 MUX", "ADC3", "ADC3"},
 	{"DEC3 MUX", "ADC4", "ADC4"},
+	{"DEC3 MUX", "ADC5", "ADC5"},
+	{"DEC3 MUX", "DMIC1", "DMIC1"},
+	{"DEC3 MUX", "DMIC2", "DMIC2"},
+	{"DEC3 MUX", "DMIC3", "DMIC3"},
+	{"DEC3 MUX", "DMIC4", "DMIC4"},
 	{"DEC3 MUX", NULL, "CDC_CONN"},
-	{"DEC4 MUX", "DMIC4", "DMIC4"},
+
+	{"DEC4 MUX", "ADC1", "ADC1"},
+	{"DEC4 MUX", "ADC2", "ADC2"},
 	{"DEC4 MUX", "ADC3", "ADC3"},
+	{"DEC4 MUX", "ADC4", "ADC4"},
+	{"DEC4 MUX", "ADC5", "ADC5"},
+	{"DEC4 MUX", "DMIC1", "DMIC1"},
+	{"DEC4 MUX", "DMIC2", "DMIC2"},
+	{"DEC4 MUX", "DMIC3", "DMIC3"},
+	{"DEC4 MUX", "DMIC4", "DMIC4"},
 	{"DEC4 MUX", NULL, "CDC_CONN"},
-	{"DEC5 MUX", "DMIC5", "DMIC5"},
-	{"DEC5 MUX", "ADC2", "ADC2"},
-	{"DEC5 MUX", NULL, "CDC_CONN"},
-	{"DEC6 MUX", "DMIC6", "DMIC6"},
-	{"DEC6 MUX", "ADC1", "ADC1"},
-	{"DEC6 MUX", NULL, "CDC_CONN"},
-	{"DEC7 MUX", "DMIC1", "DMIC1"},
-	{"DEC7 MUX", "DMIC6", "DMIC6"},
-	{"DEC7 MUX", "ADC1", "ADC1"},
-	{"DEC7 MUX", "ADC6", "ADC6"},
-	{"DEC7 MUX", NULL, "CDC_CONN"},
-	{"DEC8 MUX", "DMIC2", "DMIC2"},
-	{"DEC8 MUX", "DMIC5", "DMIC5"},
-	{"DEC8 MUX", "ADC2", "ADC2"},
-	{"DEC8 MUX", "ADC5", "ADC5"},
-	{"DEC8 MUX", NULL, "CDC_CONN"},
-	{"DEC9 MUX", "DMIC4", "DMIC4"},
-	{"DEC9 MUX", "DMIC5", "DMIC5"},
-	{"DEC9 MUX", "ADC2", "ADC2"},
-	{"DEC9 MUX", "ADC3", "ADC3"},
-	{"DEC9 MUX", NULL, "CDC_CONN"},
-	{"DEC10 MUX", "DMIC3", "DMIC3"},
-	{"DEC10 MUX", "DMIC6", "DMIC6"},
-	{"DEC10 MUX", "ADC1", "ADC1"},
-	{"DEC10 MUX", "ADC4", "ADC4"},
-	{"DEC10 MUX", NULL, "CDC_CONN"},
 
 	/* ADC Connections */
 	{"ADC1", NULL, "AMIC1"},
@@ -2247,7 +2496,6 @@
 	{"ADC3", NULL, "AMIC3"},
 	{"ADC4", NULL, "AMIC4"},
 	{"ADC5", NULL, "AMIC5"},
-	{"ADC6", NULL, "AMIC6"},
 
 	/* AUX PGA Connections */
 	{"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
@@ -2255,22 +2503,13 @@
 	{"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
 	{"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
 	{"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
-	{"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
-	{"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
 	{"AUX_PGA_Left", NULL, "AMIC5"},
-	{"AUX_PGA_Right", NULL, "AMIC6"},
 
 	{"IIR1", NULL, "IIR1 INP1 MUX"},
 	{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
 	{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
 	{"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
 	{"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
-	{"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
-	{"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
-	{"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
-	{"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
-	{"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
-	{"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
 
 	{"MIC BIAS1 Internal1", NULL, "LDO_H"},
 	{"MIC BIAS1 Internal2", NULL, "LDO_H"},
@@ -2282,7 +2521,6 @@
 	{"MIC BIAS3 Internal1", NULL, "LDO_H"},
 	{"MIC BIAS3 Internal2", NULL, "LDO_H"},
 	{"MIC BIAS3 External", NULL, "LDO_H"},
-	{"MIC BIAS4 External", NULL, "LDO_H"},
 };
 
 static int tapan_readable(struct snd_soc_codec *ssc, unsigned int reg)
@@ -2313,7 +2551,7 @@
 static int tapan_volatile(struct snd_soc_codec *ssc, unsigned int reg)
 {
 	/* Registers lower than 0x100 are top level registers which can be
-	 * written by the Taiko core driver.
+	 * written by the Tapan core driver.
 	 */
 
 	if ((reg >= TAPAN_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
@@ -2445,6 +2683,40 @@
 
 static int tapan_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
+	u8 val = 0;
+	struct snd_soc_codec *codec = dai->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s\n", __func__);
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		/* CPU is master */
+		if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			if (dai->id == AIF1_CAP)
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CLK_I2S_CTL,
+					TAPAN_I2S_MASTER_MODE_MASK, 0);
+			else if (dai->id == AIF1_PB)
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CLK_I2S_CTL,
+					TAPAN_I2S_MASTER_MODE_MASK, 0);
+		}
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+	/* CPU is slave */
+		if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			val = TAPAN_I2S_MASTER_MODE_MASK;
+			if (dai->id == AIF1_CAP)
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CLK_I2S_CTL, val, val);
+			else if (dai->id == AIF1_PB)
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CLK_I2S_CTL, val, val);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
 	return 0;
 }
 
@@ -2490,7 +2762,7 @@
 		}
 		list_for_each_entry(ch, &tapan_p->dai[dai->id].wcd9xxx_ch_list,
 				    list) {
-			dev_dbg(dai->codec->dev, "%s: rx_slot[%d] %d ch->ch_num %d\n",
+			dev_dbg(dai->codec->dev, "%s: rx_slot[%d] %d, ch->ch_num %d\n",
 				 __func__, i, rx_slot[i], ch->ch_num);
 			rx_slot[i++] = ch->ch_num;
 		}
@@ -2524,7 +2796,7 @@
 }
 
 static int tapan_set_interpolator_rate(struct snd_soc_dai *dai,
-	u8 rx_fs_rate_reg_val, u32 sample_rate)
+	u8 rx_fs_rate_reg_val, u32 compander_fs, u32 sample_rate)
 {
 	u32 j;
 	u8 rx_mix1_inp;
@@ -2540,7 +2812,7 @@
 		rx_mix1_inp = ch->port + RX_MIX1_INP_SEL_RX1 -
 			      TAPAN_TX_PORT_NUMBER;
 		if ((rx_mix1_inp < RX_MIX1_INP_SEL_RX1) ||
-			(rx_mix1_inp > RX_MIX1_INP_SEL_RX7)) {
+			(rx_mix1_inp > RX_MIX1_INP_SEL_RX5)) {
 			pr_err("%s: Invalid TAPAN_RX%u port. Dai ID is %d\n",
 				__func__,  rx_mix1_inp - 5 , dai->id);
 			return -EINVAL;
@@ -2572,6 +2844,9 @@
 				snd_soc_update_bits(codec, rx_fs_reg,
 						0xE0, rx_fs_rate_reg_val);
 
+				if (comp_rx_path[j] < COMPANDER_MAX)
+					tapan->comp_fs[comp_rx_path[j]]
+					= compander_fs;
 			}
 			if (j <= 2)
 				rx_mix_1_reg_1 += 3;
@@ -2599,7 +2874,7 @@
 		dev_dbg(codec->dev, "%s: dai->id = %d, tx_port = %d",
 			__func__, dai->id, tx_port);
 
-		if ((tx_port < 1) || (tx_port > NUM_DECIMATORS)) {
+		if ((tx_port < 1) || (tx_port > TAPAN_SLIM_CODEC_TX_PORTS)) {
 			pr_err("%s: Invalid SLIM TX%u port. DAI ID is %d\n",
 				__func__, tx_port, dai->id);
 			return -EINVAL;
@@ -2610,23 +2885,15 @@
 
 		decimator = 0;
 
-		if ((tx_port >= 1) && (tx_port <= 6)) {
+		tx_port_reg_val =  tx_port_reg_val & 0x0F;
 
-			tx_port_reg_val =  tx_port_reg_val & 0x0F;
-			if (tx_port_reg_val == 0x8)
-				decimator = tx_port;
-
-		} else if ((tx_port >= 7) && (tx_port <= NUM_DECIMATORS)) {
-
-			tx_port_reg_val =  tx_port_reg_val & 0x1F;
-
-			if ((tx_port_reg_val >= 0x8) &&
+		if ((tx_port_reg_val >= 0x8) &&
 			    (tx_port_reg_val <= 0x11)) {
 
 				decimator = (tx_port_reg_val - 0x8) + 1;
-			}
 		}
 
+
 		if (decimator) { /* SLIM_TX port has a DEC as input */
 
 			tx_fs_reg = TAPAN_A_CDC_TX1_CLK_FS_CTL +
@@ -2640,7 +2907,7 @@
 
 		} else {
 			if ((tx_port_reg_val >= 0x1) &&
-			    (tx_port_reg_val <= 0x7)) {
+			    (tx_port_reg_val <= 0x4)) {
 
 				dev_dbg(codec->dev, "%s: RMIX%u going to SLIM TX%u\n",
 					__func__, tx_port_reg_val, tx_port);
@@ -2673,8 +2940,10 @@
 			    struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
 {
+	struct snd_soc_codec *codec = dai->codec;
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(dai->codec);
 	u8 tx_fs_rate, rx_fs_rate;
+	u32 compander_fs;
 	int ret;
 
 	dev_dbg(dai->codec->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
@@ -2685,26 +2954,32 @@
 	case 8000:
 		tx_fs_rate = 0x00;
 		rx_fs_rate = 0x00;
+		compander_fs = COMPANDER_FS_8KHZ;
 		break;
 	case 16000:
 		tx_fs_rate = 0x01;
 		rx_fs_rate = 0x20;
+		compander_fs = COMPANDER_FS_16KHZ;
 		break;
 	case 32000:
 		tx_fs_rate = 0x02;
 		rx_fs_rate = 0x40;
+		compander_fs = COMPANDER_FS_32KHZ;
 		break;
 	case 48000:
 		tx_fs_rate = 0x03;
 		rx_fs_rate = 0x60;
+		compander_fs = COMPANDER_FS_48KHZ;
 		break;
 	case 96000:
 		tx_fs_rate = 0x04;
 		rx_fs_rate = 0x80;
+		compander_fs = COMPANDER_FS_96KHZ;
 		break;
 	case 192000:
 		tx_fs_rate = 0x05;
 		rx_fs_rate = 0xA0;
+		compander_fs = COMPANDER_FS_192KHZ;
 		break;
 	default:
 		pr_err("%s: Invalid sampling rate %d\n", __func__,
@@ -2722,31 +2997,85 @@
 			return ret;
 		}
 
-		if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
-			pr_err("%s: I2C interface not yet supported\n",
-				   __func__);
-		else
-			tapan->dai[dai->id].rate = params_rate(params);
-
+		if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CLK_I2S_CTL,
+					0x20, 0x20);
+				break;
+			case SNDRV_PCM_FORMAT_S32_LE:
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CLK_I2S_CTL,
+					0x20, 0x00);
+				break;
+			default:
+				pr_err("invalid format\n");
+				break;
+			}
+			snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_I2S_CTL,
+					    0x07, tx_fs_rate);
+		} else {
+			tapan->dai[dai->id].rate   = params_rate(params);
+		}
 		break;
 
 	case SNDRV_PCM_STREAM_PLAYBACK:
 		ret = tapan_set_interpolator_rate(dai, rx_fs_rate,
+						  compander_fs,
 						  params_rate(params));
 		if (ret < 0) {
-			pr_err("%s: set decimator rate failed %d\n", __func__,
-				ret);
+			dev_err(codec->dev, "%s: set decimator rate failed %d\n",
+				__func__, ret);
 			return ret;
 		}
-		if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
-			pr_err("%s: I2C interface not yet supported\n",
-				   __func__);
-		else
+		if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CLK_I2S_CTL,
+					0x20, 0x20);
+				break;
+			case SNDRV_PCM_FORMAT_S32_LE:
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CLK_I2S_CTL,
+					0x20, 0x00);
+				break;
+			default:
+				dev_err(codec->dev, "invalid format\n");
+				break;
+			}
+			snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_I2S_CTL,
+					    0x03, (rx_fs_rate >> 0x05));
+		} else {
+			switch (params_format(params)) {
+			case SNDRV_PCM_FORMAT_S16_LE:
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CONN_RX_SB_B1_CTL,
+					0xFF, 0xAA);
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CONN_RX_SB_B2_CTL,
+					0xFF, 0x2A);
+				tapan->dai[dai->id].bit_width = 16;
+				break;
+			case SNDRV_PCM_FORMAT_S24_LE:
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CONN_RX_SB_B1_CTL,
+					0xFF, 0x00);
+				snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CONN_RX_SB_B2_CTL,
+					0xFF, 0x00);
+				tapan->dai[dai->id].bit_width = 24;
+				break;
+			default:
+				dev_err(codec->dev, "Invalid format\n");
+				break;
+			}
 			tapan->dai[dai->id].rate   = params_rate(params);
-
+		}
 		break;
 	default:
-		pr_err("%s: Invalid stream type %d\n", __func__,
+		dev_err(codec->dev, "%s: Invalid stream type %d\n", __func__,
 			substream->stream);
 		return -EINVAL;
 	}
@@ -2882,6 +3211,38 @@
 	},
 };
 
+static int tapan_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
+					  bool up)
+{
+	int ret = 0;
+	struct wcd9xxx_ch *ch;
+
+	if (up) {
+		list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
+			ret = wcd9xxx_get_slave_port(ch->ch_num);
+			if (ret < 0) {
+				pr_debug("%s: Invalid slave port ID: %d\n",
+				       __func__, ret);
+				ret = -EINVAL;
+			} else {
+				set_bit(ret, &dai->ch_mask);
+			}
+		}
+	} else {
+		ret = wait_event_timeout(dai->dai_wait, (dai->ch_mask == 0),
+					 msecs_to_jiffies(
+						     TAPAN_SLIM_CLOSE_TIMEOUT));
+		if (!ret) {
+			pr_debug("%s: Slim close tx/rx wait timeout\n",
+					 __func__);
+			ret = -ETIMEDOUT;
+		} else {
+			ret = 0;
+		}
+	}
+	return ret;
+}
+
 static int tapan_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
 				     struct snd_kcontrol *kcontrol,
 				     int event)
@@ -2889,7 +3250,7 @@
 	struct wcd9xxx *core;
 	struct snd_soc_codec *codec = w->codec;
 	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
-	u32  ret = 0;
+	int ret = 0;
 	struct wcd9xxx_codec_dai_data *dai;
 
 	core = dev_get_drvdata(codec->dev->parent);
@@ -2909,6 +3270,7 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
+		(void) tapan_codec_enable_slim_chmask(dai, true);
 		ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
 					      dai->rate, dai->bit_width,
 					      &dai->grph);
@@ -2916,7 +3278,14 @@
 	case SND_SOC_DAPM_POST_PMD:
 		ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
 						dai->grph);
-		usleep_range(15000, 15000);
+		ret = tapan_codec_enable_slim_chmask(dai, false);
+		if (ret < 0) {
+			ret = wcd9xxx_disconnect_port(core,
+						      &dai->wcd9xxx_ch_list,
+						      dai->grph);
+			dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
+				 __func__, ret);
+		}
 		break;
 	}
 	return ret;
@@ -2938,7 +3307,6 @@
 		__func__, w->codec->name);
 	dev_dbg(codec->dev, "%s: num_dai %d stream name %s\n",
 		__func__, w->codec->num_dai, w->sname);
-
 	/* Execute the callback only if interface type is slimbus */
 	if (tapan_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
 		return 0;
@@ -2949,6 +3317,7 @@
 	dai = &tapan_p->dai[w->shift];
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
+		(void) tapan_codec_enable_slim_chmask(dai, true);
 		ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
 					      dai->rate, dai->bit_width,
 					      &dai->grph);
@@ -2956,45 +3325,103 @@
 	case SND_SOC_DAPM_POST_PMD:
 		ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
 						dai->grph);
+		ret = tapan_codec_enable_slim_chmask(dai, false);
+		if (ret < 0) {
+			ret = wcd9xxx_disconnect_port(core,
+						      &dai->wcd9xxx_ch_list,
+						      dai->grph);
+			dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
+				 __func__, ret);
+		}
 		break;
 	}
 	return ret;
 }
 
+
 static int tapan_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
 
 	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
 
 	switch (event) {
-
 	case SND_SOC_DAPM_POST_PMU:
+		wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+						 WCD9XXX_CLSH_STATE_EAR,
+						 WCD9XXX_CLSH_REQ_ENABLE,
+						 WCD9XXX_CLSH_EVENT_POST_PA);
 
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x20, 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x04);
-		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
+		usleep_range(5000, 5010);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+						 WCD9XXX_CLSH_STATE_EAR,
+						 WCD9XXX_CLSH_REQ_DISABLE,
+						 WCD9XXX_CLSH_EVENT_POST_PA);
+		usleep_range(5000, 5010);
+	}
+	return 0;
+}
 
-		usleep_range(5000, 5000);
+static int tapan_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+						 WCD9XXX_CLSH_STATE_EAR,
+						 WCD9XXX_CLSH_REQ_ENABLE,
+						 WCD9XXX_CLSH_EVENT_PRE_DAC);
+		break;
+	}
+
+	return 0;
+}
+
+static int tapan_codec_dsm_mux_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	u8 reg_val, zoh_mux_val = 0x00;
+
+	dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		reg_val = snd_soc_read(codec, TAPAN_A_CDC_CONN_CLSH_CTL);
+
+		if ((reg_val & 0x30) == 0x10)
+			zoh_mux_val = 0x04;
+		else if ((reg_val & 0x30) == 0x20)
+			zoh_mux_val = 0x08;
+
+		if (zoh_mux_val != 0x00)
+			snd_soc_update_bits(codec,
+					TAPAN_A_CDC_CONN_CLSH_CTL,
+					0x0C, zoh_mux_val);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CONN_CLSH_CTL,
+							0x0C, 0x00);
 		break;
 	}
 	return 0;
 }
 
+
 /* Todo: Have seperate dapm widgets for I2S and Slimbus.
  * Might Need to have callbacks registered only for slimbus
  */
 static const struct snd_soc_dapm_widget tapan_dapm_widgets[] = {
-	/*RX stuff */
-	SND_SOC_DAPM_OUTPUT("EAR"),
-
-	SND_SOC_DAPM_PGA_E("EAR PA", TAPAN_A_RX_EAR_EN, 4, 0, NULL, 0,
-			tapan_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_MIXER("DAC1", TAPAN_A_RX_EAR_EN, 6, 0, dac1_switch,
-		ARRAY_SIZE(dac1_switch)),
 
 	SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
 				AIF1_PB, 0, tapan_codec_enable_slimrx,
@@ -3023,51 +3450,61 @@
 	SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
 
-	/* Headphone */
-	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
-	SND_SOC_DAPM_PGA_E("HPHL", TAPAN_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
-		tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER("HPHL DAC", TAPAN_A_RX_HPH_L_DAC_CTL, 7, 0,
-		hphl_switch, ARRAY_SIZE(hphl_switch)),
 
-	SND_SOC_DAPM_PGA_E("HPHR", TAPAN_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
-		tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
+	/* RX1 MIX1 mux inputs */
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp3_mux),
 
-	SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAPAN_A_RX_HPH_R_DAC_CTL, 7, 0,
-		tapan_hphr_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	/* RX2 MIX1 mux inputs */
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp2_mux),
 
-	/* Speaker */
-	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
-	SND_SOC_DAPM_OUTPUT("LINEOUT2"),
-	SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+	/* RX3 MIX1 mux inputs */
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp2_mux),
 
-	SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAPAN_A_RX_LINE_CNP_EN, 0, 0, NULL,
-			0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAPAN_A_RX_LINE_CNP_EN, 1, 0, NULL,
-			0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	/* RX4 MIX1 mux inputs */
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp2_mux),
 
-	SND_SOC_DAPM_PGA_E("SPK PA", TAPAN_A_SPKR_DRV_EN, 7, 0 , NULL,
-			   0, tapan_codec_enable_spk_pa, SND_SOC_DAPM_PRE_PMU |
-			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	/* RX1 MIX2 mux inputs */
+	SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+		&rx1_mix2_inp1_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+		&rx1_mix2_inp2_mux),
 
-	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAPAN_A_RX_LINE_1_DAC_CTL, 7, 0
-		, tapan_lineout_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAPAN_A_RX_LINE_2_DAC_CTL, 7, 0
-		, tapan_lineout_dac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	/* RX2 MIX2 mux inputs */
+	SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+		&rx2_mix2_inp1_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+		&rx2_mix2_inp2_mux),
 
-	SND_SOC_DAPM_DAC_E("SPK DAC", NULL, SND_SOC_NOPM, 0, 0,
-			   tapan_spk_dac_event,
-			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	/* RX4 MIX2 mux inputs */
+	SND_SOC_DAPM_MUX("RX4 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+		&rx4_mix2_inp1_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+		&rx4_mix2_inp2_mux),
+
 
 	SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX4 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 
 	SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
 		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
@@ -3078,94 +3515,116 @@
 	SND_SOC_DAPM_MIXER_E("RX3 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
 		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
-		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU),
-	SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
+	SND_SOC_DAPM_MIXER_E("RX4 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
 		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 
-	SND_SOC_DAPM_MIXER("RX1 CHAIN", TAPAN_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("RX2 CHAIN", TAPAN_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX1 CHAIN", TAPAN_A_CDC_RX1_B6_CTL, 5, 0,
+						NULL, 0),
+	SND_SOC_DAPM_MIXER("RX2 CHAIN", TAPAN_A_CDC_RX2_B6_CTL, 5, 0,
+						NULL, 0),
 
-	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
-		&rx_mix1_inp3_mux),
-	SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx2_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx2_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx3_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx3_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
-		&rx4_mix1_inp1_mux),
-	SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
-		&rx4_mix1_inp2_mux),
-	SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
-		&rx1_mix2_inp1_mux),
-	SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
-		&rx1_mix2_inp2_mux),
-	SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
-		&rx2_mix2_inp1_mux),
-	SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
-		&rx2_mix2_inp2_mux),
+	SND_SOC_DAPM_MUX_E("CLASS_H_DSM MUX", SND_SOC_NOPM, 0, 0,
+		&class_h_dsm_mux, tapan_codec_dsm_mux_event,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
-		&rx_dac5_mux),
-
-	SND_SOC_DAPM_SUPPLY("CLASS_H_CLK", TAPAN_A_CDC_CLK_OTHR_CTL, 0, 0,
-		tapan_codec_enable_class_h_clk, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_PRE_PMD),
-
-	SND_SOC_DAPM_SUPPLY("CLASS_H_EAR", TAPAN_A_CDC_CLSH_B1_CTL, 4, 0,
-		tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_L", TAPAN_A_CDC_CLSH_B1_CTL, 3, 0,
-		tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_R", TAPAN_A_CDC_CLSH_B1_CTL, 2, 0,
-		tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_SUPPLY("CLASS_H_LINEOUTS_PA", SND_SOC_NOPM, 0, 0,
-		tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_SUPPLY("CP", TAPAN_A_NCP_EN, 0, 0,
-		tapan_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-
+	/* RX Bias */
 	SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
 		tapan_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
 
-	/* TX */
+	/*EAR */
+	SND_SOC_DAPM_PGA_E("EAR PA", TAPAN_A_RX_EAR_EN, 4, 0, NULL, 0,
+			tapan_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
+			SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_SUPPLY("CDC_CONN", TAPAN_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+	SND_SOC_DAPM_MIXER_E("DAC1", TAPAN_A_RX_EAR_EN, 6, 0, dac1_switch,
+		ARRAY_SIZE(dac1_switch), tapan_codec_ear_dac_event,
+		SND_SOC_DAPM_PRE_PMU),
+
+	/* Headphone Left */
+	SND_SOC_DAPM_PGA_E("HPHL", TAPAN_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+		tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("HPHL DAC", TAPAN_A_RX_HPH_L_DAC_CTL, 7, 0,
+		hphl_switch, ARRAY_SIZE(hphl_switch), tapan_hphl_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Headphone Right */
+	SND_SOC_DAPM_PGA_E("HPHR", TAPAN_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+		tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAPAN_A_RX_HPH_R_DAC_CTL, 7, 0,
+		tapan_hphr_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* LINEOUT1*/
+	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAPAN_A_RX_LINE_1_DAC_CTL, 7, 0
+		, tapan_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAPAN_A_RX_LINE_CNP_EN, 0, 0, NULL,
+			0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* LINEOUT2*/
+	SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac5_mux),
+
+	SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAPAN_A_RX_LINE_2_DAC_CTL, 7, 0
+		, tapan_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAPAN_A_RX_LINE_CNP_EN, 1, 0, NULL,
+			0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* CLASS-D SPK */
+	SND_SOC_DAPM_MIXER_E("SPK DAC", SND_SOC_NOPM, 0, 0,
+		spk_dac_switch, ARRAY_SIZE(spk_dac_switch), tapan_spk_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0 , NULL,
+			   0, tapan_codec_enable_spk_pa,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
+			    tapan_codec_enable_vdd_spkr,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_OUTPUT("EAR"),
+	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+	SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+
+	/* TX Path*/
+	SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
+		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
+		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
+		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+	SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TAPAN_TX1, 0,
+		&sb_tx1_mux),
+	SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TAPAN_TX2, 0,
+		&sb_tx2_mux),
+	SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TAPAN_TX3, 0,
+		&sb_tx3_mux),
+	SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TAPAN_TX4, 0,
+		&sb_tx4_mux),
+	SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, TAPAN_TX5, 0,
+		&sb_tx5_mux),
+
+	SND_SOC_DAPM_SUPPLY("CDC_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
 		0),
 
-	SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0,
-		tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
-
-	SND_SOC_DAPM_INPUT("AMIC1"),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
-		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0,
-		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0,
-		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_INPUT("AMIC3"),
-
-	SND_SOC_DAPM_INPUT("AMIC4"),
-
-	SND_SOC_DAPM_INPUT("AMIC5"),
-
+	/* Decimator MUX */
 	SND_SOC_DAPM_MUX_E("DEC1 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
 		&dec1_mux, tapan_codec_enable_dec,
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
@@ -3186,6 +3645,54 @@
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0,
+		tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
+		tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
+		tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
+		tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC1"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("ADC1", NULL, TAPAN_A_TX_1_EN, 7, 0,
+		tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC2", NULL, TAPAN_A_TX_2_EN, 7, 0,
+		tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC3"),
+	SND_SOC_DAPM_ADC_E("ADC3", NULL, TAPAN_A_TX_3_EN, 7, 0,
+		tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC4"),
+	SND_SOC_DAPM_ADC_E("ADC4", NULL, TAPAN_A_TX_4_EN, 7, 0,
+		tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC5"),
+	SND_SOC_DAPM_ADC_E("ADC5", NULL, TAPAN_A_TX_5_EN, 7, 0,
+		tapan_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
+	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
+
 	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
 		tapan_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
@@ -3225,25 +3732,7 @@
 		AIF3_CAP, 0, tapan_codec_enable_slimtx,
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
-		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
-
-	SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
-		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
-
-	SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
-		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
-
-	SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TAPAN_TX1, 0,
-		&sb_tx1_mux),
-	SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TAPAN_TX2, 0,
-		&sb_tx2_mux),
-	SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TAPAN_TX3, 0,
-		&sb_tx3_mux),
-	SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TAPAN_TX4, 0,
-		&sb_tx4_mux),
-
-	/* Digital Mic Inputs */
+		/* Digital Mic Inputs */
 	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
 		tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
@@ -3289,142 +3778,98 @@
 
 	SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
 		lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
-
 };
 
-static unsigned long slimbus_value;
-
 static irqreturn_t tapan_slimbus_irq(int irq, void *data)
 {
 	struct tapan_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
-	int i, j;
+	unsigned long status = 0;
+	int i, j, port_id, k;
+	u32 bit;
 	u8 val;
+	bool tx, cleared;
 
-	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
-		slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
-			TAPAN_SLIM_PGD_PORT_INT_STATUS0 + i);
-		for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
-			val = wcd9xxx_interface_reg_read(codec->control_data,
-				TAPAN_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
-			if (val & 0x1)
-				pr_err_ratelimited(
-				"overflow error on port %x, value %x\n",
-				i*8 + j, val);
-			if (val & 0x2)
-				pr_err_ratelimited(
-				"underflow error on port %x, value %x\n",
-				i*8 + j, val);
+	for (i = TAPAN_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
+	     i <= TAPAN_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
+		val = wcd9xxx_interface_reg_read(codec->control_data, i);
+		status |= ((u32)val << (8 * j));
+	}
+
+	for_each_set_bit(j, &status, 32) {
+		tx = (j >= 16 ? true : false);
+		port_id = (tx ? j - 16 : j);
+		val = wcd9xxx_interface_reg_read(codec->control_data,
+					TAPAN_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
+		if (val & TAPAN_SLIM_IRQ_OVERFLOW)
+			pr_err_ratelimited(
+			    "%s: overflow error on %s port %d, value %x\n",
+			    __func__, (tx ? "TX" : "RX"), port_id, val);
+		if (val & TAPAN_SLIM_IRQ_UNDERFLOW)
+			pr_err_ratelimited(
+			    "%s: underflow error on %s port %d, value %x\n",
+			    __func__, (tx ? "TX" : "RX"), port_id, val);
+		if (val & TAPAN_SLIM_IRQ_PORT_CLOSED) {
+			/*
+			 * INT SOURCE register starts from RX to TX
+			 * but port number in the ch_mask is in opposite way
+			 */
+			bit = (tx ? j - 16 : j + 16);
+			dev_dbg(codec->dev, "%s: %s port %d closed value %x, bit %u\n",
+				 __func__, (tx ? "TX" : "RX"), port_id, val,
+				 bit);
+			for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
+				dev_dbg(codec->dev, "%s: priv->dai[%d].ch_mask = 0x%lx\n",
+					 __func__, k, priv->dai[k].ch_mask);
+				if (test_and_clear_bit(bit,
+						       &priv->dai[k].ch_mask)) {
+					cleared = true;
+					if (!priv->dai[k].ch_mask)
+						wake_up(&priv->dai[k].dai_wait);
+					/*
+					 * There are cases when multiple DAIs
+					 * might be using the same slimbus
+					 * channel. Hence don't break here.
+					 */
+				}
+			}
+			WARN(!cleared,
+			     "Couldn't find slimbus %s port %d for closing\n",
+			     (tx ? "TX" : "RX"), port_id);
 		}
 		wcd9xxx_interface_reg_write(codec->control_data,
-			TAPAN_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
-
+					    TAPAN_SLIM_PGD_PORT_INT_CLR_RX_0 +
+					    (j / 8),
+					    1 << (j % 8));
 	}
+
 	return IRQ_HANDLED;
 }
 
-static const struct tapan_reg_mask_val tapan_1_0_class_h_ear[] = {
-
-	/* CLASS-H EAR  IDLE_THRESHOLD Table */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_IDLE_EAR_THSD, 0x26),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_FCLKONLY_EAR_THSD, 0x2C),
-
-	/* CLASS-H EAR I_PA_FACT Table. */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_L,	0xA9),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_U, 0x07),
-
-	/* CLASS-H EAR Voltage Headroom , Voltage Min. */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_EAR, 0x0D),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_EAR, 0x3A),
-
-	/* CLASS-H EAR K values --chnages from load. */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_ADDR, 0x08),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x1B),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x2D),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x36),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x37),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
-	/** end of Ear PA load 32 */
-};
-
-static const struct tapan_reg_mask_val tapan_1_0_class_h_hph[] = {
-
-	/* CLASS-H HPH  IDLE_THRESHOLD Table */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_IDLE_HPH_THSD, 0x13),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0x19),
-
-	/* CLASS-H HPH I_PA_FACT Table */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_L, 0x9A),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_U, 0x06),
-
-	/* CLASS-H HPH Voltage Headroom , Voltage Min */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_HPH, 0x0D),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_HPH, 0x1D),
-
-	/* CLASS-H HPH K values --chnages from load .*/
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_ADDR, 0x00),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0xAE),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x01),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x1C),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x25),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x27),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
-};
-
-static int tapan_config_ear_class_h(struct snd_soc_codec *codec, u32 ear_load)
-{
-	u32 i;
-
-	if (ear_load  != 32)
-		return -EINVAL;
-
-	for (i = 0; i < ARRAY_SIZE(tapan_1_0_class_h_ear); i++)
-		snd_soc_write(codec, tapan_1_0_class_h_ear[i].reg,
-				tapan_1_0_class_h_ear[i].val);
-	return 0;
-}
-
-static int tapan_config_hph_class_h(struct snd_soc_codec *codec, u32 hph_load)
-{
-	u32 i;
-	if (hph_load  != 16)
-		return -EINVAL;
-
-	for (i = 0; i < ARRAY_SIZE(tapan_1_0_class_h_hph); i++)
-		snd_soc_write(codec, tapan_1_0_class_h_hph[i].reg,
-				tapan_1_0_class_h_hph[i].val);
-	return 0;
-}
-
 static int tapan_handle_pdata(struct tapan_priv *tapan)
 {
 	struct snd_soc_codec *codec = tapan->codec;
 	struct wcd9xxx_pdata *pdata = tapan->resmgr.pdata;
 	int k1, k2, k3, rc = 0;
-	u8 leg_mode, txfe_bypass, txfe_buff, flag;
-	u8 value = 0;
+	u8 txfe_bypass = pdata->amic_settings.txfe_enable;
+	u8 txfe_buff = pdata->amic_settings.txfe_buff;
+	u8 flag = pdata->amic_settings.use_pdata;
+	u8 i = 0, j = 0;
+	u8 val_txfe = 0, value = 0;
 
 	if (!pdata) {
-		pr_err("%s: NULL pdata\n", __func__);
+		dev_err(codec->dev, "%s: NULL pdata\n", __func__);
 		rc = -ENODEV;
 		goto done;
 	}
 
-	leg_mode = pdata->amic_settings.legacy_mode;
-	txfe_bypass = pdata->amic_settings.txfe_enable;
-	txfe_buff = pdata->amic_settings.txfe_buff;
-	flag = pdata->amic_settings.use_pdata;
-
 	/* Make sure settings are correct */
 	if ((pdata->micbias.ldoh_v > WCD9XXX_LDOH_3P0_V) ||
 	    (pdata->micbias.bias1_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
 	    (pdata->micbias.bias2_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
 	    (pdata->micbias.bias3_cfilt_sel > WCD9XXX_CFILT3_SEL)) {
+		dev_err(codec->dev, "%s: Invalid ldoh voltage or bias cfilt\n",
+				__func__);
 		rc = -EINVAL;
 		goto done;
 	}
@@ -3434,6 +3879,9 @@
 	k3 = wcd9xxx_resmgr_get_k_val(&tapan->resmgr, pdata->micbias.cfilt3_mv);
 
 	if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
+		dev_err(codec->dev,
+			"%s: could not get K value. k1 = %d k2 = %d k3 = %d\n",
+			__func__, k1, k2, k3);
 		rc = -EINVAL;
 		goto done;
 	}
@@ -3445,19 +3893,34 @@
 	snd_soc_update_bits(codec, TAPAN_A_MICB_CFILT_2_VAL, 0xFC, (k2 << 2));
 	snd_soc_update_bits(codec, TAPAN_A_MICB_CFILT_3_VAL, 0xFC, (k3 << 2));
 
-	snd_soc_update_bits(codec, TAPAN_A_MICB_1_CTL, 0x60,
-			    (pdata->micbias.bias1_cfilt_sel << 5));
-	snd_soc_update_bits(codec, TAPAN_A_MICB_2_CTL, 0x60,
-			    (pdata->micbias.bias2_cfilt_sel << 5));
-	snd_soc_update_bits(codec, TAPAN_A_MICB_3_CTL, 0x60,
-			    (pdata->micbias.bias3_cfilt_sel << 5));
+	i = 0;
+	while (i < 5) {
+		if (flag & (0x01 << i)) {
+			val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
+			val_txfe = val_txfe |
+				((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
+			snd_soc_update_bits(codec,
+				TAPAN_A_TX_1_2_TEST_EN + j * 10,
+				0x30, val_txfe);
+		}
+		if (flag & (0x01 << (i + 1))) {
+			val_txfe = (txfe_bypass &
+					(0x01 << (i + 1))) ? 0x02 : 0x00;
+			val_txfe |= (txfe_buff &
+					(0x01 << (i + 1))) ? 0x01 : 0x00;
+			snd_soc_update_bits(codec,
+				TAPAN_A_TX_1_2_TEST_EN + j * 10,
+				0x03, val_txfe);
+		}
+		/* Tapan only has TAPAN_A_TX_1_2_TEST_EN  and
+		   TAPAN_A_TX_4_5_TEST_EN  reg */
 
-	if (flag & 0x40) {
-		value = (leg_mode & 0x40) ? 0x10 : 0x00;
-		value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
-		value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
-		snd_soc_update_bits(codec, TAPAN_A_TX_7_MBHC_EN,
-			0x13, value);
+		if (i == 0) {
+			i = 3;
+			continue;
+		} else if (i == 3) {
+			break;
+		}
 	}
 
 	if (pdata->ocp.use_pdata) {
@@ -3475,8 +3938,16 @@
 			0xE0, (pdata->ocp.hph_ocp_limit << 5));
 	}
 
-	tapan_config_ear_class_h(codec, 32);
-	tapan_config_hph_class_h(codec, 16);
+	/* Set micbias capless mode with tail current */
+	value = (pdata->micbias.bias1_cap_mode == MICBIAS_EXT_BYP_CAP ?
+		 0x00 : 0x10);
+	snd_soc_update_bits(codec, TAPAN_A_MICB_1_CTL, 0x10, value);
+	value = (pdata->micbias.bias2_cap_mode == MICBIAS_EXT_BYP_CAP ?
+		 0x00 : 0x10);
+	snd_soc_update_bits(codec, TAPAN_A_MICB_2_CTL, 0x10, value);
+	value = (pdata->micbias.bias3_cap_mode == MICBIAS_EXT_BYP_CAP ?
+		 0x00 : 0x10);
+	snd_soc_update_bits(codec, TAPAN_A_MICB_3_CTL, 0x10, value);
 
 done:
 	return rc;
@@ -3484,60 +3955,54 @@
 
 static const struct tapan_reg_mask_val tapan_reg_defaults[] = {
 
-	/* set MCLk to 9.6 */
-	TAPAN_REG_VAL(TAPAN_A_CHIP_CTL, 0x0A),
+	/* enable QFUSE for wcd9306 */
+	TAPAN_REG_VAL(TAPAN_A_QFUSE_CTL, 0x03),
+
+	/* PROGRAM_THE_0P85V_VBG_REFERENCE = V_0P858V */
+	TAPAN_REG_VAL(TAPAN_A_BIAS_CURR_CTL_2, 0x04),
+
 	TAPAN_REG_VAL(TAPAN_A_CDC_CLK_POWER_CTL, 0x03),
 
 	/* EAR PA deafults  */
 	TAPAN_REG_VAL(TAPAN_A_RX_EAR_CMBUFF, 0x05),
 
-	/** BUCK and NCP defaults for EAR and HS */
-	TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_CCL_4, 0x50),
-	TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_CCL_1, 0x5B),
-
-	/* CLASS-H defaults for EAR and HS */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_BUCK_NCP_VARS, 0x00),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_BUCK_NCP_VARS, 0x04),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x01),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x05),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x35),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B3_CTL, 0x30),
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B3_CTL, 0x3B),
-
-	/*
-	 * For CLASS-H, Enable ANC delay buffer,
-	 * set HPHL and EAR PA ref gain to 0 DB.
-	 */
-	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B1_CTL, 0x26),
-
-	/* RX deafults */
-	TAPAN_REG_VAL(TAPAN_A_CDC_RX1_B5_CTL, 0x78),
-	TAPAN_REG_VAL(TAPAN_A_CDC_RX2_B5_CTL, 0x78),
-	TAPAN_REG_VAL(TAPAN_A_CDC_RX3_B5_CTL, 0x78),
-	TAPAN_REG_VAL(TAPAN_A_CDC_RX4_B5_CTL, 0x78),
-
 	/* RX1 and RX2 defaults */
 	TAPAN_REG_VAL(TAPAN_A_CDC_RX1_B6_CTL, 0xA0),
 	TAPAN_REG_VAL(TAPAN_A_CDC_RX2_B6_CTL, 0xA0),
 
-	/* RX3 to RX7 defaults */
-	TAPAN_REG_VAL(TAPAN_A_CDC_RX3_B6_CTL, 0x80),
-	TAPAN_REG_VAL(TAPAN_A_CDC_RX4_B6_CTL, 0x80),
+	/* Heaset set Right from RX2 */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CONN_RX2_B2_CTL, 0x10),
+
 
 	/*
-	 * The following only need to be written for Taiko 1.0 parts.
-	 * Taiko 2.0 will have appropriate defaults for these registers.
+	 * The following only need to be written for Tapan 1.0 parts.
+	 * Tapan 2.0 will have appropriate defaults for these registers.
 	 */
+
+	/* Required defaults for class H operation */
+	/* borrowed from Taiko class-h */
+	TAPAN_REG_VAL(TAPAN_A_RX_HPH_CHOP_CTL, 0xF4),
+	TAPAN_REG_VAL(TAPAN_A_BIAS_CURR_CTL_2, 0x08),
+	TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
+	TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
+
+	/* TODO: Check below reg writes conflict with above */
+	/* PROGRAM_THE_0P85V_VBG_REFERENCE = V_0P858V */
+	TAPAN_REG_VAL(TAPAN_A_BIAS_CURR_CTL_2, 0x04),
+	TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x54),
+	TAPAN_REG_VAL(TAPAN_A_RX_HPH_CHOP_CTL, 0x74),
+	TAPAN_REG_VAL(TAPAN_A_RX_BUCK_BIAS1, 0x62),
+
 	/* Choose max non-overlap time for NCP */
 	TAPAN_REG_VAL(TAPAN_A_NCP_CLK, 0xFC),
 	/* Use 25mV/50mV for deltap/m to reduce ripple */
-	TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_VCL_1, 0x08),
+	TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x08),
 	/*
 	 * Set DISABLE_MODE_SEL<1:0> to 0b10 (disable PWM in auto mode).
 	 * Note that the other bits of this register will be changed during
 	 * Rx PA bring up.
 	 */
-	TAPAN_REG_VAL(TAPAN_A_BUCK_MODE_3, 0xCE),
+	TAPAN_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
 	/* Reduce HPH DAC bias to 70% */
 	TAPAN_REG_VAL(TAPAN_A_RX_HPH_BIAS_PA, 0x7A),
 	/*Reduce EAR DAC bias to 70% */
@@ -3553,17 +4018,64 @@
 	 */
 	TAPAN_REG_VAL(TAPAN_A_MICB_2_MBHC, 0x41),
 
+	/* not needed if MBHC is not needed */
 	/* Disable TX7 internal biasing path which can cause leakage */
 	TAPAN_REG_VAL(TAPAN_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
 };
 
+static const struct tapan_reg_mask_val tapan_2_x_reg_reset_values[] = {
+
+	TAPAN_REG_VAL(TAPAN_A_TX_7_MBHC_EN, 0x6C),
+	TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_CCL_4, 0x51),
+	TAPAN_REG_VAL(TAPAN_A_RX_HPH_CNP_WG_CTL, 0xDA),
+	TAPAN_REG_VAL(TAPAN_A_RX_EAR_CNP, 0xC0),
+	TAPAN_REG_VAL(TAPAN_A_RX_LINE_1_TEST, 0x02),
+	TAPAN_REG_VAL(TAPAN_A_RX_LINE_2_TEST, 0x02),
+	TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_OCP_CTL, 0x97),
+	TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_CLIP_DET, 0x01),
+	TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_IEC, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B1_CTL, 0xE4),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B3_CTL, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_BUCK_NCP_VARS, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_EAR, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_HPH, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_EAR, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_HPH, 0x00),
+};
+
+static const struct tapan_reg_mask_val tapan_1_0_reg_defaults[] = {
+	/* Close leakage on the spkdrv */
+	TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_DBG_PWRSTG, 0x24),
+	TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_DBG_DAC, 0xE5),
+
+};
+
 static void tapan_update_reg_defaults(struct snd_soc_codec *codec)
 {
 	u32 i;
+	struct wcd9xxx *tapan_core = dev_get_drvdata(codec->dev->parent);
+
+	if (!TAPAN_IS_1_0(tapan_core->version)) {
+		for (i = 0; i < ARRAY_SIZE(tapan_2_x_reg_reset_values); i++)
+			snd_soc_write(codec, tapan_2_x_reg_reset_values[i].reg,
+				tapan_2_x_reg_reset_values[i].val);
+	}
 
 	for (i = 0; i < ARRAY_SIZE(tapan_reg_defaults); i++)
 		snd_soc_write(codec, tapan_reg_defaults[i].reg,
 				tapan_reg_defaults[i].val);
+
+	if (TAPAN_IS_1_0(tapan_core->version)) {
+		for (i = 0; i < ARRAY_SIZE(tapan_1_0_reg_defaults); i++)
+			snd_soc_write(codec, tapan_1_0_reg_defaults[i].reg,
+				tapan_1_0_reg_defaults[i].val);
+	}
+
+	if (!TAPAN_IS_1_0(tapan_core->version))
+		spkr_drv_wrnd = -1;
+	else if (spkr_drv_wrnd == 1)
+		snd_soc_write(codec, TAPAN_A_SPKR_DRV_EN, 0xEF);
 }
 
 static const struct tapan_reg_mask_val tapan_codec_reg_init_val[] = {
@@ -3578,17 +4090,27 @@
 	{TAPAN_A_RX_HPH_R_GAIN, 0x20, 0x20},
 	{TAPAN_A_RX_LINE_1_GAIN, 0x20, 0x20},
 	{TAPAN_A_RX_LINE_2_GAIN, 0x20, 0x20},
+	{TAPAN_A_SPKR_DRV_GAIN, 0x04, 0x04},
+
+	/*  Set RDAC5 MUX to take input from DEM3_INV.
+	 *  This sets LO2 DAC to get input from DEM3_INV
+	 *  for LO1 and LO2 to work as differential outputs.
+	 */
+	{TAPAN_A_CDC_CONN_MISC, 0x04, 0x04},
 
 	/* CLASS H config */
 	{TAPAN_A_CDC_CONN_CLSH_CTL, 0x3C, 0x14},
 
-	/* Use 16 bit sample size for TX1 to TX6 */
+	/* Use 16 bit sample size for TX1 to TX5 */
 	{TAPAN_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
 	{TAPAN_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
 	{TAPAN_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
 	{TAPAN_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
 	{TAPAN_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
 
+	/* Disable SPK SWITCH */
+	{TAPAN_A_SPKR_DRV_DAC_CTL, 0x04, 0x00},
+
 	/* Use 16 bit sample size for RX */
 	{TAPAN_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
 	{TAPAN_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0x2A},
@@ -3607,8 +4129,14 @@
 
 	/* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
 	{TAPAN_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
-	{TAPAN_A_CDC_CLK_DMIC_B2_CTL, 0x0E, 0x02},
 
+	/* Compander zone selection */
+	{TAPAN_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
+	{TAPAN_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
+	{TAPAN_A_CDC_COMP2_B4_CTL, 0x3F, 0x37},
+	{TAPAN_A_CDC_COMP0_B5_CTL, 0x7F, 0x7F},
+	{TAPAN_A_CDC_COMP1_B5_CTL, 0x7F, 0x7F},
+	{TAPAN_A_CDC_COMP2_B5_CTL, 0x7F, 0x7F},
 };
 
 static void tapan_codec_init_reg(struct snd_soc_codec *codec)
@@ -3684,6 +4212,10 @@
 
 	snd_soc_codec_set_drvdata(codec, tapan);
 
+	/* TODO: Read buck voltage from DT property */
+	tapan->clsh_d.buck_mv = WCD9XXX_CDC_BUCK_MV_1P8;
+	wcd9xxx_clsh_init(&tapan->clsh_d, &tapan->resmgr);
+
 	/* codec resmgr module init */
 	wcd9xxx = codec->control_data;
 	pdata = dev_get_platdata(codec->dev->parent);
@@ -3691,28 +4223,44 @@
 				  &tapan_reg_address);
 	if (ret) {
 		pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
-		goto err_codec;
+		return ret;
 	}
 
-	/* init and start mbhc */
-	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec);
-	if (ret) {
-		pr_err("%s: mbhc init failed %d\n", __func__, ret);
-		goto err_codec;
-	}
+	/* TODO: wcd9xxx_mbhc_init to enable mbhc */
 
 	tapan->codec = codec;
-
+	for (i = 0; i < COMPANDER_MAX; i++) {
+		tapan->comp_enabled[i] = 0;
+		tapan->comp_fs[i] = COMPANDER_FS_48KHZ;
+	}
 	tapan->intf_type = wcd9xxx_get_intf_type();
 	tapan->aux_pga_cnt = 0;
 	tapan->aux_l_gain = 0x1F;
 	tapan->aux_r_gain = 0x1F;
 	tapan_update_reg_defaults(codec);
+
+	dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
+			__func__, wcd9xxx->mclk_rate);
+
+	if (wcd9xxx->mclk_rate == TAPAN_MCLK_CLK_12P288MHZ) {
+		snd_soc_update_bits(codec, TAPAN_A_CHIP_CTL, 0x06, 0x0);
+		snd_soc_update_bits(codec, TAPAN_A_RX_COM_TIMER_DIV, 0x01,
+				0x01);
+	} else if (wcd9xxx->mclk_rate == TAPAN_MCLK_CLK_9P6HZ) {
+		snd_soc_update_bits(codec, TAPAN_A_CHIP_CTL, 0x06, 0x2);
+	}
 	tapan_codec_init_reg(codec);
 	ret = tapan_handle_pdata(tapan);
 	if (IS_ERR_VALUE(ret)) {
-		pr_err("%s: bad pdata\n", __func__);
-		goto err_codec;
+		dev_err(codec->dev, "%s: bad pdata\n", __func__);
+		goto err_pdata;
+	}
+
+	if (spkr_drv_wrnd > 0) {
+		WCD9XXX_BCL_LOCK(&tapan->resmgr);
+		wcd9xxx_resmgr_get_bandgap(&tapan->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
 	}
 
 	ptr = kmalloc((sizeof(tapan_rx_chs) +
@@ -3724,8 +4272,12 @@
 	}
 
 	if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
-		pr_err("%s: I2C interface not supported yet\n",
-			   __func__);
+		snd_soc_dapm_new_controls(dapm, tapan_dapm_i2s_widgets,
+			ARRAY_SIZE(tapan_dapm_i2s_widgets));
+		snd_soc_dapm_add_routes(dapm, audio_i2s_map,
+			ARRAY_SIZE(audio_i2s_map));
+		for (i = 0; i < ARRAY_SIZE(tapan_i2s_dai); i++)
+			INIT_LIST_HEAD(&tapan->dai[i].wcd9xxx_ch_list);
 	} else if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
 		for (i = 0; i < NUM_CODEC_DAIS; i++) {
 			INIT_LIST_HEAD(&tapan->dai[i].wcd9xxx_ch_list);
@@ -3744,12 +4296,14 @@
 
 	(void) tapan_setup_irqs(tapan);
 
+	atomic_set(&kp_tapan_priv, (unsigned long)tapan);
+
 	codec->ignore_pmdown_time = 1;
 	return ret;
 
-err_nomem_slimch:
+err_pdata:
 	kfree(ptr);
-err_codec:
+err_nomem_slimch:
 	kfree(tapan);
 	return ret;
 }
@@ -3758,6 +4312,13 @@
 {
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
 
+	WCD9XXX_BCL_LOCK(&tapan->resmgr);
+	atomic_set(&kp_tapan_priv, 0);
+
+	if (spkr_drv_wrnd > 0)
+		wcd9xxx_resmgr_put_bandgap(&tapan->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+	WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
 	/* cleanup MBHC */
 	wcd9xxx_mbhc_deinit(&tapan->mbhc);
 	/* cleanup resmgr */
@@ -3801,6 +4362,7 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct tapan_priv *tapan = platform_get_drvdata(pdev);
 	dev_dbg(dev, "%s: system resume\n", __func__);
+	/* Notify */
 	wcd9xxx_resmgr_notifier_call(&tapan->resmgr, WCD9XXX_EVENT_POST_RESUME);
 	return 0;
 }
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 328c380..7766b60 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -84,7 +84,6 @@
 static int msm_btsco_ch = 1;
 
 static struct mutex cdc_mclk_mutex;
-static struct q_clkdiv *codec_clk;
 static int clk_users;
 
 static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
@@ -96,24 +95,18 @@
 
 	mutex_lock(&cdc_mclk_mutex);
 	if (enable) {
-		if (!codec_clk) {
-			dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
-				__func__);
-			ret = -EINVAL;
-			goto exit;
-		}
 
 		clk_users++;
 		if (clk_users != 1)
 			goto exit;
-		/* TODO: qpnp_clkdiv_enable */
+		/* TODO: clk_disable */
 		tapan_mclk_enable(codec, 1, dapm);
 	} else {
 		if (clk_users > 0) {
 			clk_users--;
 			if (clk_users == 0) {
 				tapan_mclk_enable(codec, 0, dapm);
-				/* TODO: qpnp_clkdiv_disable */
+				/* TODO: clk_enable */
 			}
 		} else {
 			pr_err("%s: Error releasing Tabla MCLK\n", __func__);
@@ -268,23 +261,6 @@
 	return 0;
 }
 
-static int msm8226_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
-
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
-			channels->min, channels->max);
-
-	rate->min = rate->max = 48000;
-
-	return 0;
-}
-
 static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					    struct snd_pcm_hw_params *params)
 {
@@ -335,9 +311,9 @@
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
-	SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[1],
+	SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[0],
 		     msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
-	SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[2],
+	SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[1],
 		     msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
 };
 
@@ -378,8 +354,11 @@
 
 	/* start mbhc */
 	mbhc_cfg.calibration = def_tapan_mbhc_cal();
-	if (mbhc_cfg.calibration)
-		err = tapan_hs_detect(codec, &mbhc_cfg);
+	if (mbhc_cfg.calibration) {
+		pr_info("%s: WCD9306: Headset detection disabled\n",
+				__func__);
+	}
+
 	else
 		err = -ENOMEM;
 
@@ -550,7 +529,7 @@
 		.name = "MSM8226 Media1",
 		.stream_name = "MultiMedia1",
 		.cpu_dai_name	= "MultiMedia1",
-		.platform_name  = "msm-pcm-dsp",
+		.platform_name  = "msm-pcm-dsp.0",
 		.dynamic = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 			SND_SOC_DPCM_TRIGGER_POST},
@@ -565,7 +544,7 @@
 		.name = "MSM8226 Media2",
 		.stream_name = "MultiMedia2",
 		.cpu_dai_name   = "MultiMedia2",
-		.platform_name  = "msm-pcm-dsp",
+		.platform_name  = "msm-pcm-dsp.0",
 		.dynamic = 1,
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
@@ -744,6 +723,22 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 	},
+	{
+		.name = "VoLTE",
+		.stream_name = "VoLTE",
+		.cpu_dai_name   = "VoLTE",
+		.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_VOLTE,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
@@ -757,6 +752,7 @@
 		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_INT_BT_SCO_TX,
@@ -768,6 +764,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
 		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_INT_FM_RX,
@@ -781,6 +778,7 @@
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_INT_FM_TX,
@@ -792,6 +790,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_INT_FM_TX,
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
 	},
 	/* Backend AFE DAI Links */
 	{
@@ -806,6 +805,7 @@
 		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_AFE_PCM_TX,
@@ -817,6 +817,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
 		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		.ignore_suspend = 1,
 	},
 	/* HDMI Hostless */
 	{
@@ -833,19 +834,6 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 	},
-	/* HDMI BACK END DAI Link */
-	{
-		.name = LPASS_BE_HDMI,
-		.stream_name = "HDMI Playback",
-		.cpu_dai_name = "msm-dai-q6-hdmi.8",
-		.platform_name = "msm-pcm-routing",
-		.codec_name     = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-rx",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_HDMI_RX,
-		.be_hw_params_fixup = msm8226_hdmi_be_hw_params_fixup,
-		.ignore_pmdown_time = 1,
-	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
@@ -860,6 +848,7 @@
 		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
 		.ops = &msm8226_be_ops,
 		.ignore_pmdown_time = 1, /* dai link has playback support */
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_0_TX,
@@ -872,6 +861,7 @@
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8226_be_ops,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_1_RX,
@@ -886,6 +876,7 @@
 		.ops = &msm8226_be_ops,
 		/* dai link has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_1_TX,
@@ -898,6 +889,7 @@
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8226_be_ops,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_3_RX,
@@ -912,6 +904,7 @@
 		.ops = &msm8226_be_ops,
 		/* dai link has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_3_TX,
@@ -924,6 +917,7 @@
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8226_be_ops,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_4_RX,
@@ -938,6 +932,7 @@
 		.ops = &msm8226_be_ops,
 		/* dai link has playback support */
 		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
 	},
 	{
 		.name = LPASS_BE_SLIMBUS_4_TX,
@@ -950,6 +945,7 @@
 		.be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm8226_be_ops,
+		.ignore_suspend = 1,
 	},
 };
 
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index ccaf39d..259f3ed 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -839,7 +839,7 @@
 {
 	int			result;
 	int			i;
-	unsigned long		paddr;
+	ion_phys_addr_t		paddr;
 	void                    *kvptr;
 	unsigned long		kvaddr;
 	unsigned long		mem_len;