Merge "msm: board-8930: Remove HDMI clocks from MDP GDHS data"
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm-stats.txt
new file mode 100644
index 0000000..1b21007
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-stats.txt
@@ -0,0 +1,22 @@
+* RPM Sleep Stats
+
+RPM maintains sleep data in the RPM RAM. A device tree node is added
+that will hold the address of the RPM RAM from where sleep stats are read.
+Additionally a version number is added to distinguish the type of data
+structure being read from the RAM.
+
+The required properties for rpm-stats are:
+
+- compatible: "qcom,rpm-stats"
+- reg: The address on the RPM RAM from where stats are read.
+- reg-names: Name given the register holding address.
+- qcom,sleep-stats-version: Version number.
+
+Example:
+
+qcom,rpm-stats@0xfc19dbd0{
+		compatible = "qcom,rpm-stats";
+		reg = <0xfc19dbd0 0x1000>;
+		reg-names = "phys_addr_base";
+		qcom,sleep-stats-version = <2>;
+};
diff --git a/arch/arm/boot/dts/msm8974-pm.dtsi b/arch/arm/boot/dts/msm8974-pm.dtsi
index 30483bc..52f2a41 100644
--- a/arch/arm/boot/dts/msm8974-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-pm.dtsi
@@ -428,4 +428,11 @@
 		qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
 		qcom,use-sync-timer;
 	};
+
+	qcom,rpm-stats@0xfc19dbd0{
+		compatible = "qcom,rpm-stats";
+		reg = <0xfc19dbd0 0x1000>;
+		reg-names = "phys_addr_base";
+		qcom,sleep-stats-version = <2>;
+	};
 };
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index e1d4ca0..783be1b 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -75,6 +75,25 @@
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_BLOCK=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
 # CONFIG_MTD_MSM_NAND is not set
 CONFIG_MTD_MSM_QPIC_NAND=y
 CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index fd642ee..7a443ec 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -265,6 +265,7 @@
 	select ARM_HAS_SG_CHAIN
 	select MSM_RUN_QUEUE_STATS
 	select MEMORY_HOLE_CARVEOUT
+	select MSM_RPM_STATS_LOG
 
 config ARCH_MPQ8092
 	bool "MPQ8092"
@@ -2097,7 +2098,7 @@
 config MSM_RPM_STATS_LOG
 	tristate "MSM Resource Power Manager Stat Driver"
 	depends on DEBUG_FS
-	depends on MSM_RPM
+	depends on MSM_RPM || MSM_RPM_SMD
 	default n
 	  help
 	  This option enables a driver which reads RPM messages from a shared
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index b9362cf..0b8919b 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -2124,6 +2124,26 @@
 	CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
 
 	CLK_LOOKUP("a5_m_clk", a5_m_clk, ""),
+
+	/* Coresight QDSS clocks */
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc322000.tmc"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc318000.tpiu"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc31c000.replicator"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc307000.tmc"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc31b000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc319000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc31a000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc321000.stm"),
+
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc322000.tmc"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc318000.tpiu"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc31c000.replicator"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc307000.tmc"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc31b000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc319000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc31a000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc321000.stm"),
+
 };
 
 static struct pll_config_regs gpll0_regs __initdata = {
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 2e25076..11d836d 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -32,6 +32,7 @@
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
 #include "ramdump.h"
+#include "sysmon.h"
 
 /* Q6 Register Offsets */
 #define QDSP6SS_RST_EVB			0x010
@@ -74,6 +75,7 @@
 	struct pil_desc desc;
 	struct subsys_device *subsys;
 	struct subsys_desc subsys_desc;
+	void *adsp_state_notifier;
 	u32 img_length;
 	struct q6v5_data *q6;
 	int self_auth;
@@ -489,6 +491,20 @@
 	return ret;
 }
 
+static int adsp_state_notifier_fn(struct notifier_block *this,
+				unsigned long code, void *ss_handle)
+{
+	int ret;
+	ret = sysmon_send_event(SYSMON_SS_MODEM, "adsp", code);
+	if (ret < 0)
+		pr_err("%s: sysmon_send_event failed (%d).", __func__, ret);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+	.notifier_call = adsp_state_notifier_fn,
+};
+
 static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
 {
 	struct mba_data *drv = dev_id;
@@ -658,8 +674,20 @@
 		goto err_irq;
 	}
 
+	drv->adsp_state_notifier = subsys_notif_register_notifier("adsp",
+						&adsp_state_notifier_block);
+	if (IS_ERR(drv->adsp_state_notifier)) {
+		ret = PTR_ERR(drv->adsp_state_notifier);
+		dev_err(&pdev->dev, "%s: Registration with the SSR notification driver failed (%d)",
+			__func__, ret);
+		goto err_smsm;
+	}
+
 	return 0;
 
+err_smsm:
+	smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET, smsm_state_cb,
+					drv);
 err_irq:
 	subsys_unregister(drv->subsys);
 err_subsys:
@@ -676,6 +704,9 @@
 static int __devexit pil_mss_driver_exit(struct platform_device *pdev)
 {
 	struct mba_data *drv = platform_get_drvdata(pdev);
+
+	subsys_notif_unregister_notifier(drv->adsp_state_notifier,
+						&adsp_state_notifier_block);
 	smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
 			smsm_state_cb, drv);
 	subsys_unregister(drv->subsys);
diff --git a/arch/arm/mach-msm/rpm_stats.c b/arch/arm/mach-msm/rpm_stats.c
index 032633c..9a8b8ec 100644
--- a/arch/arm/mach-msm/rpm_stats.c
+++ b/arch/arm/mach-msm/rpm_stats.c
@@ -23,11 +23,13 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/types.h>
+#include <linux/of.h>
 #include <asm/uaccess.h>
-
+#include <asm/arch_timer.h>
 #include <mach/msm_iomap.h>
 #include "rpm_stats.h"
 
+
 enum {
 	ID_COUNTER,
 	ID_ACCUM_TIME_SCLK,
@@ -40,6 +42,8 @@
 };
 
 #define SCLK_HZ 32768
+#define MSM_ARCH_TIMER_FREQ 19200000
+
 struct msm_rpmstats_record{
 	char		name[32];
 	uint32_t	id;
@@ -50,9 +54,99 @@
 	u32 num_records;
 	u32 read_idx;
 	u32 len;
-	char buf[128];
+	char buf[256];
 	struct msm_rpmstats_platform_data *platform_data;
 };
+
+struct msm_rpm_stats_data_v2 {
+	u32 stat_type;
+	u32 count;
+	u64 last_entered_at;
+	u64 last_exited_at;
+};
+
+static inline u64 get_time_in_sec(u64 counter)
+{
+	do_div(counter, MSM_ARCH_TIMER_FREQ);
+	return counter;
+}
+
+static inline u64 get_time_in_msec(u64 counter)
+{
+	do_div(counter, MSM_ARCH_TIMER_FREQ);
+	counter *= MSEC_PER_SEC;
+	return counter;
+}
+
+static inline int msm_rpmstats_append_data_to_buf(char *buf,
+		struct msm_rpm_stats_data_v2 *data, int buflength)
+{
+	char stat_type[5];
+	u64 time_in_last_mode;
+	u64 time_since_last_mode;
+
+	stat_type[4] = 0;
+	memcpy(stat_type, &data->stat_type, sizeof(u32));
+
+	time_in_last_mode = data->last_exited_at - data->last_entered_at;
+	time_in_last_mode = get_time_in_msec(time_in_last_mode);
+	time_since_last_mode = arch_counter_get_cntpct() - data->last_exited_at;
+	time_since_last_mode = get_time_in_sec(time_since_last_mode);
+
+	return  snprintf(buf , buflength,
+		"RPM Mode:%s\n\t count:%d\n time in last mode(msec):%llu\n"
+		"time since last mode(sec):%llu\n",
+		stat_type, data->count, time_in_last_mode,
+		time_since_last_mode);
+}
+
+static inline u32 msm_rpmstats_read_long_register_v2(void __iomem *regbase,
+		int index, int offset)
+{
+	return readl_relaxed(regbase + offset +
+			index * sizeof(struct msm_rpm_stats_data_v2));
+}
+
+static inline u64 msm_rpmstats_read_quad_register_v2(void __iomem *regbase,
+		int index, int offset)
+{
+	u64 dst;
+	memcpy_fromio(&dst,
+		regbase + offset + index * sizeof(struct msm_rpm_stats_data_v2),
+		8);
+	return dst;
+}
+
+static inline int msm_rpmstats_copy_stats_v2(
+			struct msm_rpmstats_private_data *prvdata)
+{
+	void __iomem *reg;
+	struct msm_rpm_stats_data_v2 data;
+	int i, length;
+
+	reg = prvdata->reg_base;
+
+	for (i = 0, length = 0; i < prvdata->num_records; i++) {
+
+		data.stat_type = msm_rpmstats_read_long_register_v2(reg, i,
+				offsetof(struct msm_rpm_stats_data_v2,
+					stat_type));
+		data.count = msm_rpmstats_read_long_register_v2(reg, i,
+				offsetof(struct msm_rpm_stats_data_v2, count));
+		data.last_entered_at = msm_rpmstats_read_quad_register_v2(reg,
+				i, offsetof(struct msm_rpm_stats_data_v2,
+					last_entered_at));
+		data.last_exited_at = msm_rpmstats_read_quad_register_v2(reg,
+				i, offsetof(struct msm_rpm_stats_data_v2,
+					last_exited_at));
+
+		length += msm_rpmstats_append_data_to_buf(prvdata->buf + length,
+				&data, sizeof(prvdata->buf) - length);
+		prvdata->read_idx++;
+	}
+	return length;
+}
+
 static inline unsigned long  msm_rpmstats_read_register(void __iomem *regbase,
 		int index, int offset)
 {
@@ -119,6 +213,7 @@
 			msm_rpmstats_id_labels[record.id],
 			usec);
 }
+
 static int msm_rpmstats_file_read(struct file *file, char __user *bufu,
 				  size_t count, loff_t *ppos)
 {
@@ -140,6 +235,9 @@
 		&& (prvdata->read_idx < prvdata->num_records)) {
 			if (prvdata->platform_data->version == 1)
 				prvdata->len = msm_rpmstats_copy_stats(prvdata);
+			else if (prvdata->platform_data->version == 2)
+				prvdata->len = msm_rpmstats_copy_stats_v2(
+						prvdata);
 			*ppos = 0;
 	}
 
@@ -161,7 +259,8 @@
 		return -ENOMEM;
 	prvdata = file->private_data;
 
-	prvdata->reg_base = ioremap(pdata->phys_addr_base, pdata->phys_size);
+	prvdata->reg_base = ioremap_nocache(pdata->phys_addr_base,
+					pdata->phys_size);
 	if (!prvdata->reg_base) {
 		kfree(file->private_data);
 		prvdata = NULL;
@@ -173,6 +272,9 @@
 
 	prvdata->read_idx = prvdata->num_records =  prvdata->len = 0;
 	prvdata->platform_data = pdata;
+	if (pdata->version == 2)
+		prvdata->num_records = 2;
+
 	return 0;
 }
 
@@ -197,10 +299,12 @@
 
 static  int __devinit msm_rpmstats_probe(struct platform_device *pdev)
 {
-	struct dentry *dent;
+	struct dentry *dent = NULL;
 	struct msm_rpmstats_platform_data *pdata;
 	struct msm_rpmstats_platform_data *pd;
 	struct resource *res = NULL;
+	struct device_node *node = NULL;
+	int ret = 0;
 
 	if (!pdev)
 		return -EINVAL;
@@ -218,19 +322,30 @@
 	pdata->phys_addr_base  = res->start;
 
 	pdata->phys_size = resource_size(res);
-
+	node = pdev->dev.of_node;
 	if (pdev->dev.platform_data) {
 		pd = pdev->dev.platform_data;
-		pdata->version = pd->version ;
-	}
+		pdata->version = pd->version;
 
-	dent = debugfs_create_file("rpm_stats", S_IRUGO, NULL,
-			pdata, &msm_rpmstats_fops);
+	} else if (node)
+		ret = of_property_read_u32(node,
+			"qcom,sleep-stats-version", &pdata->version);
 
-	if (!dent) {
-		pr_err("%s: ERROR debugfs_create_file failed\n", __func__);
+	if (!ret) {
+
+		dent = debugfs_create_file("rpm_stats", S_IRUGO, NULL,
+				pdata, &msm_rpmstats_fops);
+
+		if (!dent) {
+			pr_err("%s: ERROR debugfs_create_file failed\n",
+					__func__);
+			kfree(pdata);
+			return -ENOMEM;
+		}
+
+	} else {
 		kfree(pdata);
-		return -ENOMEM;
+		return -EINVAL;
 	}
 	platform_set_drvdata(pdev, dent);
 	return 0;
@@ -245,12 +360,19 @@
 	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
+
+static struct of_device_id rpm_stats_table[] = {
+	       {.compatible = "qcom,rpm-stats"},
+	       {},
+};
+
 static struct platform_driver msm_rpmstats_driver = {
 	.probe	= msm_rpmstats_probe,
 	.remove = __devexit_p(msm_rpmstats_remove),
 	.driver = {
 		.name = "msm_rpm_stat",
 		.owner = THIS_MODULE,
+		.of_match_table = rpm_stats_table,
 	},
 };
 static int __init msm_rpmstats_init(void)
diff --git a/arch/arm/mach-msm/smd_rpcrouter.c b/arch/arm/mach-msm/smd_rpcrouter.c
index 80a639c..1bea82a 100644
--- a/arch/arm/mach-msm/smd_rpcrouter.c
+++ b/arch/arm/mach-msm/smd_rpcrouter.c
@@ -306,6 +306,10 @@
 	struct msm_rpc_reply *reply, *reply_tmp;
 	unsigned long flags;
 
+	if (!xprt_info) {
+		pr_err("%s: Invalid xprt_info\n", __func__);
+		return;
+	}
 	spin_lock_irqsave(&local_endpoints_lock, flags);
 	/* remove all partial packets received */
 	list_for_each_entry(ept, &local_endpoints, list) {
@@ -2154,6 +2158,7 @@
 	while (!list_empty(&xprt_info_list)) {
 		xprt_info = list_first_entry(&xprt_info_list,
 					struct rpcrouter_xprt_info, list);
+		modem_reset_cleanup(xprt_info);
 		xprt_info->abort_data_read = 1;
 		wake_up(&xprt_info->read_wait);
 		rpcrouter_send_control_msg(xprt_info, &ctl);
@@ -2164,6 +2169,8 @@
 		flush_workqueue(xprt_info->workqueue);
 		destroy_workqueue(xprt_info->workqueue);
 		wake_lock_destroy(&xprt_info->wakelock);
+		/*free memory*/
+		xprt_info->xprt->priv = 0;
 		kfree(xprt_info);
 
 		mutex_lock(&xprt_info_list_lock);
diff --git a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
index f139f4c..4c1aa63 100644
--- a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
+++ b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
@@ -64,7 +64,7 @@
 	pinfo.is_3d_panel = FB_TYPE_3D_PANEL;
 	pinfo.lcd.vsync_enable = TRUE;
 	pinfo.lcd.hw_vsync_mode = TRUE;
-	pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+	pinfo.lcd.refx100 = 6200; /* adjust refx100 to prevent tearing */
 	pinfo.lcd.v_back_porch = 11;
 	pinfo.lcd.v_front_porch = 10;
 	pinfo.lcd.v_pulse_width = 5;
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 73fb995..211327f 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -222,11 +222,9 @@
  * ion_map_kernel - create mapping for the given handle
  * @client:	the client
  * @handle:	handle to map
- * @flags:	flags for this mapping
  *
  * Map the given handle into the kernel and return a kernel address that
- * can be used to access this address. If no flags are specified, this
- * will return a non-secure uncached mapping.
+ * can be used to access this address.
  */
 void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle);
 
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
index 4b7a32c..a1609b8 100644
--- a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
@@ -202,5 +202,7 @@
 #define WCD9XXX_A_MBHC_INSERT_DETECT__POR	(0x00)
 #define WCD9XXX_A_MBHC_INSERT_DET_STATUS	(0x14B) /* TAIKO and later */
 #define WCD9XXX_A_MBHC_INSERT_DET_STATUS__POR	(0x00)
+#define WCD9XXX_A_MAD_ANA_CTRL			(0x150)
+#define WCD9XXX_A_MAD_ANA_CTRL__POR		(0xF1)
 
 #endif
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 1076be8..700d2ae 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1630,7 +1630,7 @@
 	memcpy(&entry->buf, trace_buf, len);
 	entry->buf[len] = '\0';
 	if (!filter_check_discard(call, entry, buffer, event)) {
-		stm_log(OST_ENTITY_TRACE_PRINTK, event, size);
+		stm_log(OST_ENTITY_TRACE_PRINTK, entry->buf, len + 1);
 		ring_buffer_unlock_commit(buffer, event);
 		ftrace_trace_stack(buffer, irq_flags, 6, pc);
 	}
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 95df162..6f2885f 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -2084,7 +2084,6 @@
 		/* Let MBHC module know so micbias switch to be off */
 		wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_pre_on);
 
-		snd_soc_update_bits(codec, w->reg, 0x0E, 0x0A);
 		/* Get cfilt */
 		wcd9xxx_resmgr_cfilt_get(&taiko->resmgr, cfilt_sel_val);
 
@@ -4471,9 +4470,6 @@
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B6_CTL, 0x80),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B6_CTL, 0x80),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
-
-	/* TX VHIGH comparator */
-	TAIKO_REG_VAL(TAIKO_A_TX_SUP_SWITCH_CTRL_2, 0x90),
 };
 
 static const struct taiko_reg_mask_val taiko_1_0_reg_defaults[] = {
@@ -4497,6 +4493,17 @@
 	TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0x76),
 	/* Reduce LINE DAC bias to 70% */
 	TAIKO_REG_VAL(TAIKO_A_RX_LINE_BIAS_PA, 0x78),
+
+	/*
+	 * There is a diode to pull down the micbias while doing
+	 * insertion detection.  This diode can cause leakage.
+	 * Set bit 0 to 1 to prevent leakage.
+	 * Setting this bit of micbias 2 prevents leakage for all other micbias.
+	 */
+	TAIKO_REG_VAL(TAIKO_A_MICB_2_MBHC, 0x41),
+
+	/* Disable TX7 internal biasing path which can cause leakage */
+	TAIKO_REG_VAL(TAIKO_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
 };
 
 static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 653effa..0f2a19c 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -9,6 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/firmware.h>
@@ -566,15 +567,6 @@
 		 ins ? "insert" : "removal");
 	/* Disable detection to avoid glitch */
 	snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT, 1, 0);
-	/* Override mbhc power switch to avoid false IRQs */
-	snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MICB_1_MBHC, 1 << 2,
-			    !ins << 2);
-	snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MICB_2_MBHC, 1 << 2,
-			    !ins << 2);
-	snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MICB_3_MBHC, 1 << 2,
-			    !ins << 2);
-	snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MICB_4_MBHC, 1 << 2,
-			    !ins << 2);
 	snd_soc_write(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT,
 		      (0x68 | (ins ? (1 << 1) : 0)));
 	/* Re-enable detection */
@@ -938,6 +930,23 @@
 	return abs(mic_volt - mic_volt_prev) > threshold;
 }
 
+static void wcd9xxx_onoff_vddio_switch(struct wcd9xxx_mbhc *mbhc, bool on)
+{
+	if (on) {
+		snd_soc_update_bits(mbhc->codec, mbhc->mbhc_bias_regs.mbhc_reg,
+				    1 << 7, 1 << 7);
+		snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MAD_ANA_CTRL,
+				    1 << 4, 0);
+	} else {
+		snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MAD_ANA_CTRL,
+				    1 << 4, 1 << 4);
+		snd_soc_update_bits(mbhc->codec, mbhc->mbhc_bias_regs.mbhc_reg,
+				    1 << 7, 0);
+	}
+	if (on)
+		usleep_range(10000, 10000);
+}
+
 /* called under codec_resource_lock acquisition and mbhc override = 1 */
 static enum wcd9xxx_mbhc_plug_type
 wcd9xxx_codec_get_plug_type(struct wcd9xxx_mbhc *mbhc, bool highhph)
@@ -988,8 +997,7 @@
 			scaled = mic_mv[i];
 		} else {
 			if (vddioswitch)
-				__wcd9xxx_switch_micbias(mbhc, 1,
-							     false, false);
+				wcd9xxx_onoff_vddio_switch(mbhc, true);
 			if (gndswitch)
 				wcd9xxx_codec_hphr_gnd_switch(codec, true);
 			mb_v[i] = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
@@ -1012,8 +1020,7 @@
 			if (gndswitch)
 				wcd9xxx_codec_hphr_gnd_switch(codec, false);
 			if (vddioswitch)
-				__wcd9xxx_switch_micbias(mbhc, 0,
-							     false, false);
+				wcd9xxx_onoff_vddio_switch(mbhc, false);
 			/* claim UNSUPPORTED plug insertion when
 			 * good headset is detected but HPHR GND switch makes
 			 * delta difference */
@@ -1577,7 +1584,7 @@
 	vddio = (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
 		 mbhc->mbhc_micbias_switched);
 	if (vddio)
-		__wcd9xxx_switch_micbias(mbhc, 0, false, true);
+		wcd9xxx_onoff_vddio_switch(mbhc, true);
 
 	if (mbhc->mbhc_cfg->detect_extn_cable &&
 	    !wcd9xxx_swch_level_remove(mbhc))
@@ -1591,7 +1598,7 @@
 	 * switch is off by time now and shouldn't be turn on again from here
 	 */
 	if (vddio && mbhc->current_plug == PLUG_TYPE_HEADSET)
-		__wcd9xxx_switch_micbias(mbhc, 1, true, true);
+		wcd9xxx_onoff_vddio_switch(mbhc, true);
 	WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
 
 	return IRQ_HANDLED;
@@ -2483,7 +2490,7 @@
 
 static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc)
 {
-	u8 cfilt_mode, bg_mode;
+	u8 cfilt_mode;
 	struct snd_soc_codec *codec = mbhc->codec;
 
 	pr_debug("%s: enter\n", __func__);
@@ -2501,8 +2508,6 @@
 	 */
 	cfilt_mode = snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl);
 	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
-	bg_mode = snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL,
-				      0x02, 0x02);
 
 	/*
 	 * Micbias, CFILT, LDOH, MBHC MUX mode settings
@@ -2555,14 +2560,13 @@
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
 	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40,
 			    cfilt_mode);
-	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x02,
-			    bg_mode);
 
 	snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x84);
 	usleep_range(100, 100);
 
 	wcd9xxx_enable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
 	wcd9xxx_turn_onoff_rel_detection(codec, true);
+
 	pr_debug("%s: leave\n", __func__);
 }
 
@@ -3031,7 +3035,7 @@
 		break;
 	/* PA usage change */
 	case WCD9XXX_EVENT_PRE_HPHL_PA_ON:
-		if (!(snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg & 0x80)))
+		if (!(snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg) & 0x80))
 			/* if micbias is enabled, switch to vddio */
 			wcd9xxx_switch_micbias(mbhc, 1);
 		break;
@@ -3187,10 +3191,6 @@
 		return ret;
 	}
 
-	mbhc->mbhc_cfg = kzalloc(sizeof(*mbhc->mbhc_cfg), GFP_KERNEL);
-	if (!mbhc->mbhc_cfg)
-		return -ENOMEM;
-
 	INIT_DELAYED_WORK(&mbhc->mbhc_firmware_dwork, wcd9xxx_mbhc_fw_read);
 	INIT_DELAYED_WORK(&mbhc->mbhc_btn_dwork, wcd9xxx_btn_lpress_fn);
 	INIT_DELAYED_WORK(&mbhc->mbhc_insert_dwork, wcd9xxx_mbhc_insert_work);
@@ -3300,8 +3300,6 @@
 	wcd9xxx_resmgr_unregister_notifier(mbhc->resmgr, &mbhc->nblock);
 
 	wcd9xxx_cleanup_debugfs(mbhc);
-
-	kfree(mbhc->mbhc_cfg);
 }
 EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_deinit);
 
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.c b/sound/soc/codecs/wcd9xxx-resmgr.c
index 5dfa41c..3952dd5 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr.c
@@ -111,7 +111,7 @@
 	blocking_notifier_call_chain(&resmgr->notifier, e, resmgr);
 }
 
-static void wcd9xxx_codec_disable_bg(struct wcd9xxx_resmgr *resmgr)
+static void wcd9xxx_disable_bg(struct wcd9xxx_resmgr *resmgr)
 {
 	/* Notify bg mode change */
 	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_PRE_BG_OFF);
@@ -122,18 +122,28 @@
 	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_POST_BG_OFF);
 }
 
-static void wcd9xxx_codec_enable_bg_audio(struct wcd9xxx_resmgr *resmgr)
+/*
+ * BG enablement should always enable in slow mode.
+ * The fast mode doesn't need to be enabled as fast mode BG is to be driven
+ * by MBHC override.
+ */
+static void wcd9xxx_enable_bg(struct wcd9xxx_resmgr *resmgr)
 {
 	struct snd_soc_codec *codec = resmgr->codec;
 
-	/* Notify bandgap mode change */
-	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_PRE_BG_AUDIO_ON);
-	/* Enable bg */
+	/* Enable BG in slow mode and precharge */
 	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x80, 0x80);
 	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x04, 0x04);
 	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x01, 0x01);
 	usleep_range(1000, 1000);
 	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x80, 0x00);
+}
+
+static void wcd9xxx_enable_bg_audio(struct wcd9xxx_resmgr *resmgr)
+{
+	/* Notify bandgap mode change */
+	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_PRE_BG_AUDIO_ON);
+	wcd9xxx_enable_bg(resmgr);
 	/* Notify bandgap mode change */
 	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_POST_BG_AUDIO_ON);
 }
@@ -146,28 +156,15 @@
 	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_PRE_BG_MBHC_ON);
 
 	/*
-	 * bandgap mode becomes fast,
 	 * mclk should be off or clk buff source souldn't be VBG
 	 * Let's turn off mclk always
 	 */
 	WARN_ON(snd_soc_read(codec, WCD9XXX_A_CLK_BUFF_EN2) & (1 << 2));
-	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x2, 0x2);
-	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x80, 0x80);
-	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x4, 0x4);
-	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x01, 0x01);
-	usleep_range(1000, 1000);
-	snd_soc_update_bits(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x80, 0x00);
-
+	wcd9xxx_enable_bg(resmgr);
 	/* Notify bandgap mode change */
 	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_POST_BG_MBHC_ON);
 }
 
-static void wcd9xxx_disable_bg(struct wcd9xxx_resmgr *resmgr)
-{
-	struct snd_soc_codec *codec = resmgr->codec;
-	snd_soc_write(codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x00);
-}
-
 static void wcd9xxx_disable_clock_block(struct wcd9xxx_resmgr *resmgr)
 {
 	struct snd_soc_codec *codec = resmgr->codec;
@@ -223,14 +220,14 @@
 			/* BG mode can be changed only with clock off */
 			clock_save = wcd9xxx_save_clock(resmgr);
 			/* Swtich BG mode */
-			wcd9xxx_codec_disable_bg(resmgr);
-			wcd9xxx_codec_enable_bg_audio(resmgr);
+			wcd9xxx_disable_bg(resmgr);
+			wcd9xxx_enable_bg_audio(resmgr);
 			/* restore clock */
 			wcd9xxx_restore_clock(resmgr, clock_save);
 		} else if (resmgr->bg_audio_users == 1) {
 			/* currently off, just enable it */
 			WARN_ON(resmgr->bandgap_type != WCD9XXX_BANDGAP_OFF);
-			wcd9xxx_codec_enable_bg_audio(resmgr);
+			wcd9xxx_enable_bg_audio(resmgr);
 		}
 		resmgr->bandgap_type = WCD9XXX_BANDGAP_AUDIO_MODE;
 		break;
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 5b0eb9c..127a2c3 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -143,6 +143,10 @@
 			atomic_set(&prtd->pending_buffer, 0);
 		if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
 			runtime->render_flag |= SNDRV_RENDER_STOPPED;
+			atomic_set(&prtd->pending_buffer, 1);
+			pr_debug("%s:compr driver underrun hw_ptr = %ld appl_ptr = %ld\n",
+				__func__, runtime->status->hw_ptr,
+				runtime->control->appl_ptr);
 			break;
 		}
 		buf = prtd->audio_client->port[IN].buf;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index e8ea058..5f2fb00 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -343,18 +343,20 @@
 		if (!codec_clk) {
 			dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
 				__func__);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto exit;
 		}
 
 		clk_users++;
 		if (clk_users != 1)
-			return ret;
+			goto exit;
 
 		ret = qpnp_clkdiv_enable(codec_clk);
 		if (ret) {
 			dev_err(codec->dev, "%s: Error enabling taiko MCLK\n",
 			       __func__);
-			return -ENODEV;
+			ret = -ENODEV;
+			goto exit;
 		}
 		taiko_mclk_enable(codec, 1, dapm);
 	} else {
@@ -367,8 +369,10 @@
 		} else {
 			pr_err("%s: Error releasing Tabla MCLK\n", __func__);
 			ret = -EINVAL;
+			goto exit;
 		}
 	}
+exit:
 	mutex_unlock(&cdc_mclk_mutex);
 	return ret;
 }
@@ -811,8 +815,8 @@
 	btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg,
 					       MBHC_BTN_DET_V_BTN_HIGH);
 	btn_low[0] = -50;
-	btn_high[0] = 34;
-	btn_low[1] = 35;
+	btn_high[0] = 10;
+	btn_low[1] = 11;
 	btn_high[1] = 52;
 	btn_low[2] = 53;
 	btn_high[2] = 94;