Merge "arm/dt: pm8941: Add additional VADC channel nodes" into msm-3.4
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 2131d49..f9efec5 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -228,6 +228,53 @@
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
 		qcom,min-clk-gear = <10>;
 		qcom,rxreg-access;
+
+		taiko_codec {
+			compatible = "qcom,taiko-slim-pgd";
+			elemental-addr = [00 01 A0 00 17 02];
+
+			qcom,cdc-reset-gpio = <&msmgpio 63 0>;
+
+			cdc-vdd-buck-supply = <&pm8941_s2>;
+			qcom,cdc-vdd-buck-voltage = <2150000 2150000>;
+			qcom,cdc-vdd-buck-current = <650000>;
+
+			cdc-vdd-tx-h-supply = <&pm8941_s3>;
+			qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-tx-h-current = <25000>;
+
+			cdc-vdd-rx-h-supply = <&pm8941_s3>;
+			qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-rx-h-current = <25000>;
+
+			cdc-vddpx-1-supply = <&pm8941_s3>;
+			qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+			qcom,cdc-vddpx-1-current = <10000>;
+
+			cdc-vdd-a-1p2v-supply = <&pm8941_l1>;
+			qcom,cdc-vdd-a-1p2v-voltage = <1225000 1225000>;
+			qcom,cdc-vdd-a-1p2v-current = <10000>;
+
+			cdc-vddcx-1-supply = <&pm8941_l1>;
+			qcom,cdc-vddcx-1-voltage = <1225000 1225000>;
+			qcom,cdc-vddcx-1-current = <10000>;
+
+			cdc-vddcx-2-supply = <&pm8941_l1>;
+			qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
+			qcom,cdc-vddcx-2-current = <10000>;
+
+			qcom,cdc-micbias-ldoh-v = <0x3>;
+			qcom,cdc-micbias-cfilt1-mv = <1800>;
+			qcom,cdc-micbias-cfilt2-mv = <2700>;
+			qcom,cdc-micbias-cfilt3-mv = <1800>;
+			qcom,cdc-micbias1-cfilt-sel = <0x0>;
+			qcom,cdc-micbias2-cfilt-sel = <0x1>;
+			qcom,cdc-micbias3-cfilt-sel = <0x2>;
+			qcom,cdc-micbias4-cfilt-sel = <0x2>;
+
+			qcom,cdc-slim-ifd = "taiko-slim-ifd";
+			qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+		};
 	};
 
 	spmi_bus: qcom,spmi@fc4c0000 {
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index d3a4960..d4bd18f 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -99,6 +99,9 @@
 	REGULATOR_SUPPLY("cam_vdig",		"4-0048"),
 	REGULATOR_SUPPLY("cam_vdig",            "4-0020"),
 };
+VREG_CONSUMERS(L13) = {
+	REGULATOR_SUPPLY("8038_l13",		NULL),
+};
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8038_l14",		NULL),
 	REGULATOR_SUPPLY("pa_therm",		"pm8xxx-adc"),
@@ -148,6 +151,9 @@
 	REGULATOR_SUPPLY("8038_l24",		NULL),
 	REGULATOR_SUPPLY("riva_vddmx",		"wcnss_wlan.0"),
 };
+VREG_CONSUMERS(L25) = {
+	REGULATOR_SUPPLY("8038_l25",		NULL),
+};
 VREG_CONSUMERS(L26) = {
 	REGULATOR_SUPPLY("8038_l26",		NULL),
 };
@@ -492,6 +498,7 @@
 	RPM_LDO(L10,	 0, 1, 0, 2900000, 2900000, NULL,      0, 0),
 	RPM_LDO(L11,	 1, 1, 0, 1800000, 1800000, "8038_s4", 10000, 10000),
 	RPM_LDO(L12,	 0, 1, 0, 1200000, 1200000, "8038_s2", 0, 0),
+	RPM_LDO(L13,	 0, 0, 0, 2220000, 2220000, NULL,      0, 0),
 	RPM_LDO(L14,	 0, 1, 0, 1800000, 1800000, NULL,      0, 0),
 	RPM_LDO(L15,	 0, 1, 0, 1800000, 2950000, NULL,      0, 0),
 	RPM_LDO(L17,	 0, 1, 0, 1800000, 2950000, NULL,      0, 0),
@@ -501,6 +508,7 @@
 	RPM_LDO(L22,	 1, 1, 0, 1850000, 2950000, NULL,      10000, 10000),
 	RPM_LDO(L23,	 1, 1, 1, 1800000, 1800000, "8038_s4", 0, 0),
 	RPM_LDO(L24,	 0, 1, 1,  500000, 1150000, "8038_s2", 10000, 10000),
+	RPM_LDO(L25,	 0, 0, 0, 1740000, 1740000, "8038_l13", 0, 0),
 	RPM_LDO(L26,     1, 1, 0, 1050000, 1050000, "8038_s2", 10000, 10000),
 
 	/*	ID     a_on pd ss		    supply */
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 0db82e9..9c5e436 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -385,6 +385,7 @@
 #define GP2_CBCR                                 0x1940
 #define GP3_CBCR                                 0x1980
 #define AUDIO_CORE_GDSCR			 0x7000
+#define AUDIO_CORE_IXFABRIC_CBCR		 0x1B000
 #define AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR     0xA014
 #define AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR    0xA018
 #define AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR    0xA01C
@@ -492,6 +493,8 @@
 #define MSS_BUS_Q6_CBCR                          0x10A4
 #define MSS_CFG_AHB_CBCR                         0x0280
 
+#define GCC_USB_BOOT_CLOCK_CTL	   0x1A00
+#define GCC_KPSS_BOOT_CLOCK_CTL	   0x19C0
 #define APCS_CLOCK_BRANCH_ENA_VOTE 0x1484
 #define APCS_CLOCK_SLEEP_ENA_VOTE  0x1488
 
@@ -759,6 +762,7 @@
 static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(bimc_acpu_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_gfx3d_clk, &ocmemgx_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ocmemgx_msmbus_clk, &ocmemgx_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
 
@@ -3870,7 +3874,7 @@
 
 static struct branch_clk oxili_gfx3d_clk = {
 	.cbcr_reg = OXILI_GFX3D_CBCR,
-	.has_sibling = 1,
+	.parent = &ocmemgx_gfx3d_clk.c,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "oxili_gfx3d_clk",
@@ -3936,7 +3940,7 @@
 	F_LPASS(  512000, lpapll0, 16, 1, 60),
 	F_LPASS(  768000, lpapll0, 16, 1, 40),
 	F_LPASS( 1024000, lpapll0, 16, 1, 30),
-	F_LPASS( 1536000, lpapll0, 16, 1, 10),
+	F_LPASS( 1536000, lpapll0, 16, 1, 20),
 	F_LPASS( 2048000, lpapll0, 16, 1, 15),
 	F_LPASS( 3072000, lpapll0, 16, 1, 10),
 	F_LPASS( 4096000, lpapll0, 15, 1,  8),
@@ -4307,6 +4311,17 @@
 	},
 };
 
+static struct branch_clk audio_core_ixfabric_clk = {
+	.cbcr_reg = AUDIO_CORE_IXFABRIC_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_ixfabric_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_ixfabric_clk.c),
+	},
+};
+
 static struct branch_clk q6ss_xo_clk = {
 	.cbcr_reg = LPASS_Q6SS_XO_CBCR,
 	.bcr_reg = LPASS_Q6SS_BCR,
@@ -4521,6 +4536,7 @@
 	{&q6ss_xo_clk.c,			LPASS_BASE, 0x002b},
 	{&q6ss_ahb_lfabif_clk.c,		LPASS_BASE, 0x001e},
 	{&q6ss_ahbm_clk.c,			LPASS_BASE, 0x001d},
+	{&audio_core_ixfabric_clk.c,		LPASS_BASE, 0x0059},
 	{&mss_bus_q6_clk.c,			MSS_BASE, 0x003c},
 	{&mss_xo_q6_clk.c,			MSS_BASE, 0x0007},
 
@@ -4579,12 +4595,12 @@
 		break;
 
 	case LPASS_BASE:
-		clk_sel = 0x169;
+		clk_sel = 0x161;
 		regval = BVAL(11, 0, measure_mux[i].debug_mux);
 		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
 
 		/* Activate debug clock output */
-		regval |= BIT(16);
+		regval |= BIT(20);
 		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
 		break;
 
@@ -4966,6 +4982,7 @@
 
 
 	/* LPASS clocks */
+	CLK_LOOKUP("bus_clk", audio_core_ixfabric_clk.c, ""),
 	CLK_LOOKUP("core_clk", audio_core_slimbus_core_clk.c, "fe12f000.slim"),
 	CLK_LOOKUP("iface_clk", audio_core_slimbus_lfabif_clk.c,
 			"fe12f000.slim"),
@@ -5286,6 +5303,10 @@
 	 */
 	writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
 
+	/* Clear a bit that forces-on certain USB HS and Krait clocks */
+	writel_relaxed(0x0, GCC_REG_BASE(GCC_USB_BOOT_CLOCK_CTL));
+	writel_relaxed(0x0, GCC_REG_BASE(GCC_KPSS_BOOT_CLOCK_CTL));
+
 	/*
 	 * TODO: The following sequence enables the LPASS audio core GDSC.
 	 * Remove when this becomes unnecessary.
@@ -5330,6 +5351,11 @@
 	 */
 	clk_prepare_enable(&cxo_a_clk_src.c);
 
+	/* TODO: Temporarily enable a clock to allow access to LPASS core
+	 * registers.
+	 */
+	clk_prepare_enable(&audio_core_ixfabric_clk.c);
+
 	/*
 	 * TODO: Temporarily enable NOC configuration AHB clocks. Remove when
 	 * the bus driver is ready.
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 207dbef..be69827 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -54,6 +54,23 @@
 	return (rc < 0) ? rc : iv.value * r->factor;
 }
 
+static int clk_rpmrs_handoff(struct rpm_clk *r)
+{
+	struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
+	int rc = msm_rpm_get_status(&iv, 1);
+
+	if (rc < 0)
+		return rc;
+
+	if (!r->branch) {
+		r->last_set_khz = iv.value;
+		r->last_set_sleep_khz = iv.value;
+		r->c.rate = iv.value * r->factor;
+	}
+
+	return 0;
+}
+
 static int clk_rpmrs_set_rate_smd(struct rpm_clk *r, uint32_t value,
 				uint32_t context, int noirq)
 {
@@ -71,10 +88,16 @@
 						r->rpm_clk_id, &kvp, 1);
 }
 
+static int clk_rpmrs_handoff_smd(struct rpm_clk *r)
+{
+	return 0;
+}
+
 struct clk_rpmrs_data {
 	int (*set_rate_fn)(struct rpm_clk *r, uint32_t value,
 				uint32_t context, int noirq);
 	int (*get_rate_fn)(struct rpm_clk *r);
+	int (*handoff_fn)(struct rpm_clk *r);
 	int ctx_active_id;
 	int ctx_sleep_id;
 };
@@ -82,12 +105,14 @@
 struct clk_rpmrs_data clk_rpmrs_data = {
 	.set_rate_fn = clk_rpmrs_set_rate,
 	.get_rate_fn = clk_rpmrs_get_rate,
+	.handoff_fn = clk_rpmrs_handoff,
 	.ctx_active_id = MSM_RPM_CTX_SET_0,
 	.ctx_sleep_id = MSM_RPM_CTX_SET_SLEEP,
 };
 
 struct clk_rpmrs_data clk_rpmrs_data_smd = {
 	.set_rate_fn = clk_rpmrs_set_rate_smd,
+	.handoff_fn = clk_rpmrs_handoff_smd,
 	.ctx_active_id = MSM_RPM_CTX_ACTIVE_SET,
 	.ctx_sleep_id = MSM_RPM_CTX_SLEEP_SET,
 };
@@ -257,7 +282,6 @@
 static enum handoff rpm_clk_handoff(struct clk *clk)
 {
 	struct rpm_clk *r = to_rpm_clk(clk);
-	struct msm_rpm_iv_pair iv = { r->rpm_status_id };
 	int rc;
 
 	/*
@@ -266,16 +290,10 @@
 	 * assume these clocks are enabled (unless the RPM call fails) so
 	 * child clocks of these RPM clocks can still be handed off.
 	 */
-	rc  = msm_rpm_get_status(&iv, 1);
+	rc  = r->rpmrs_data->handoff_fn(r);
 	if (rc < 0)
 		return HANDOFF_DISABLED_CLK;
 
-	if (!r->branch) {
-		r->last_set_khz = iv.value;
-		r->last_set_sleep_khz = iv.value;
-		clk->rate = iv.value * r->factor;
-	}
-
 	return HANDOFF_ENABLED_CLK;
 }
 
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
index 684f9d3..47056a8 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
@@ -100,6 +100,7 @@
 	RPM_VREG_ID_PM8038_L10,
 	RPM_VREG_ID_PM8038_L11,
 	RPM_VREG_ID_PM8038_L12,
+	RPM_VREG_ID_PM8038_L13,
 	RPM_VREG_ID_PM8038_L14,
 	RPM_VREG_ID_PM8038_L15,
 	RPM_VREG_ID_PM8038_L16,
@@ -111,6 +112,7 @@
 	RPM_VREG_ID_PM8038_L22,
 	RPM_VREG_ID_PM8038_L23,
 	RPM_VREG_ID_PM8038_L24,
+	RPM_VREG_ID_PM8038_L25,
 	RPM_VREG_ID_PM8038_L26,
 	RPM_VREG_ID_PM8038_L27,
 	RPM_VREG_ID_PM8038_S1,
@@ -154,6 +156,7 @@
 };
 
 /* Minimum high power mode loads in uA. */
+#define RPM_VREG_8930_LDO_5_HPM_MIN_LOAD		0
 #define RPM_VREG_8930_LDO_50_HPM_MIN_LOAD		5000
 #define RPM_VREG_8930_LDO_150_HPM_MIN_LOAD		10000
 #define RPM_VREG_8930_LDO_300_HPM_MIN_LOAD		10000
diff --git a/arch/arm/mach-msm/pil-mba.c b/arch/arm/mach-msm/pil-mba.c
index d0ba7d0..2176b26 100644
--- a/arch/arm/mach-msm/pil-mba.c
+++ b/arch/arm/mach-msm/pil-mba.c
@@ -37,7 +37,6 @@
 
 #define STATUS_META_DATA_AUTH_SUCCESS	0x3
 #define STATUS_AUTH_COMPLETE		0x4
-#define STATUS_ERROR_MASK		BIT(31)
 
 #define AUTH_TIMEOUT_US			10000000
 #define PROXY_TIMEOUT_MS		10000
@@ -75,7 +74,7 @@
 			      const u8 *metadata, size_t size)
 {
 	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	u32 status;
+	s32 status;
 	int ret;
 
 	/* Copy metadata to assigned shared buffer location */
@@ -89,10 +88,14 @@
 	writel_relaxed(drv->metadata_phys, drv->reg_base + RMB_PMI_META_DATA);
 	writel_relaxed(CMD_META_DATA_READY, drv->reg_base + RMB_MBA_COMMAND);
 	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
-		status == STATUS_META_DATA_AUTH_SUCCESS,
+		status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
 		POLL_INTERVAL_US, AUTH_TIMEOUT_US);
-	if (ret)
+	if (ret) {
 		dev_err(pil->dev, "MBA authentication timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		ret = -EINVAL;
+	}
 
 	return ret;
 }
@@ -101,6 +104,7 @@
 			       size_t size)
 {
 	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	s32 status;
 
 	/* Begin image authentication */
 	if (drv->img_length == 0) {
@@ -111,28 +115,33 @@
 	drv->img_length += size;
 	writel_relaxed(drv->img_length, drv->reg_base + RMB_PMI_CODE_LENGTH);
 
-	return readl_relaxed(drv->reg_base + RMB_MBA_STATUS)
-			& STATUS_ERROR_MASK;
+	status = readl_relaxed(drv->reg_base + RMB_MBA_STATUS);
+	if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static int pil_mba_auth(struct pil_desc *pil)
 {
 	struct mba_data *drv = dev_get_drvdata(pil->dev);
 	int ret;
-	u32 status;
+	s32 status;
 
 	/* Wait for all segments to be authenticated or an error to occur */
 	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
-			status == STATUS_AUTH_COMPLETE ||
-			status & STATUS_ERROR_MASK,
+			status == STATUS_AUTH_COMPLETE || status < 0,
 			50, AUTH_TIMEOUT_US);
-	if (ret)
-		return ret;
+	if (ret) {
+		dev_err(pil->dev, "MBA authentication timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		ret = -EINVAL;
+	}
 
-	if (status & STATUS_ERROR_MASK)
-		return -EINVAL;
-
-	return 0;
+	return ret;
 }
 
 static int pil_mba_shutdown(struct pil_desc *pil)
diff --git a/arch/arm/mach-msm/rpm-regulator-8930.c b/arch/arm/mach-msm/rpm-regulator-8930.c
index 0de67b1..3878e22 100644
--- a/arch/arm/mach-msm/rpm-regulator-8930.c
+++ b/arch/arm/mach-msm/rpm-regulator-8930.c
@@ -71,6 +71,11 @@
 	VOLTAGE_RANGE( 750000, 1537500, 12500),
 };
 
+static struct vreg_range ln_ldo_ranges[] = {
+	VOLTAGE_RANGE( 690000, 1110000,  60000),
+	VOLTAGE_RANGE(1380000, 2220000, 120000),
+};
+
 static struct vreg_range smps_ranges[] = {
 	VOLTAGE_RANGE( 375000,  737500, 12500),
 	VOLTAGE_RANGE( 750000, 1487500, 12500),
@@ -90,6 +95,7 @@
 static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
 static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
 static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges);
+static struct vreg_set_points ln_ldo_set_points = SET_POINTS(ln_ldo_ranges);
 static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges);
 static struct vreg_set_points ftsmps_set_points = SET_POINTS(ftsmps_ranges);
 static struct vreg_set_points corner_set_points = SET_POINTS(corner_ranges);
@@ -98,6 +104,7 @@
 	&pldo_set_points,
 	&nldo_set_points,
 	&nldo1200_set_points,
+	&ln_ldo_set_points,
 	&smps_set_points,
 	&ftsmps_set_points,
 	&corner_set_points,
@@ -173,6 +180,7 @@
 	LDO(L10,  "8038_l10",  "8038_l10_pc", pldo,     LDO_600,  0),
 	LDO(L11,  "8038_l11",  "8038_l11_pc", pldo,     LDO_600,  0),
 	LDO(L12,  "8038_l12",  "8038_l12_pc", nldo,     LDO_300,  1),
+	LDO(L13,  "8038_l13",  NULL,          ln_ldo,   LDO_5,    0),
 	LDO(L14,  "8038_l14",  "8038_l14_pc", pldo,     LDO_50,   0),
 	LDO(L15,  "8038_l15",  "8038_l15_pc", pldo,     LDO_150,  0),
 	LDO(L16,  "8038_l16",  NULL,          nldo1200, LDO_1200, 1),
@@ -184,6 +192,7 @@
 	LDO(L22,  "8038_l22",  "8038_l22_pc", pldo,     LDO_50,   0),
 	LDO(L23,  "8038_l23",  "8038_l23_pc", pldo,     LDO_50,   0),
 	LDO(L24,  "8038_l24",  NULL,          nldo1200, LDO_1200, 1),
+	LDO(L25,  "8038_l25",  NULL,          ln_ldo,   LDO_5,    0),
 	LDO(L26,  "8038_l26",  "8038_l26_pc", nldo,     LDO_150,  1),
 	LDO(L27,  "8038_l27",  NULL,          nldo1200, LDO_1200, 1),
 
@@ -237,8 +246,12 @@
 {
 	int real_id = 0;
 
-	if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L15_PC)
+	if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L12_PC)
 		real_id = id - RPM_VREG_ID_PM8038_L2_PC;
+	else if (id >= RPM_VREG_ID_PM8038_L14_PC
+			&& id <= RPM_VREG_ID_PM8038_L15_PC)
+		real_id = id - RPM_VREG_ID_PM8038_L14_PC
+				+ RPM_VREG_ID_PM8038_L14;
 	else if (id >= RPM_VREG_ID_PM8038_L17_PC
 			&& id <= RPM_VREG_ID_PM8038_L18_PC)
 		real_id = id - RPM_VREG_ID_PM8038_L17_PC
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 59cb45b..4758829 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -35,6 +35,10 @@
 #include <linux/gpio.h>
 #include "wcd9310.h"
 
+static int cfilt_adjust_ms = 10;
+module_param(cfilt_adjust_ms, int, 0644);
+MODULE_PARM_DESC(cfilt_adjust_ms, "delay after adjusting cfilt voltage in ms");
+
 #define WCD9310_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
@@ -2240,26 +2244,26 @@
 	}
 	snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
 
-	if (!tabla->no_mic_headset_override) {
-		if (mbhc_state == MBHC_STATE_POTENTIAL) {
-			pr_debug("%s recovering MBHC state macine\n", __func__);
-			tabla->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
-			/* set to max button press threshold */
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
-				      0x7F);
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
-				      0xFF);
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
-				      (TABLA_IS_1_X(tabla_core->version) ?
-				       0x07 : 0x7F));
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL,
-				      0xFF);
-			/* set to max */
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL,
-				      0x7F);
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL,
-				      0xFF);
-		}
+	if (tabla->no_mic_headset_override) {
+		pr_debug("%s setting button threshold to min", __func__);
+		/* set to min */
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x80);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0x00);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL, 0x80);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL, 0x00);
+	} else if (unlikely(mbhc_state == MBHC_STATE_POTENTIAL)) {
+		pr_debug("%s recovering MBHC state machine\n", __func__);
+		tabla->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
+		/* set to max button press threshold */
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL, 0x7F);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL, 0xFF);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
+			      (TABLA_IS_1_X(tabla_core->version) ?
+			       0x07 : 0x7F));
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0xFF);
+		/* set to max */
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL, 0x7F);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL, 0xFF);
 	}
 
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
@@ -2479,11 +2483,11 @@
 			cfilt_k_val = tabla_find_k_value(
 						   tabla->pdata->micbias.ldoh_v,
 						   VDDIO_MICBIAS_MV);
-			usleep_range(10000, 10000);
 			snd_soc_update_bits(codec,
 					    tabla->mbhc_bias_regs.cfilt_val,
 					    0xFC, (cfilt_k_val << 2));
-			usleep_range(10000, 10000);
+			usleep_range(cfilt_adjust_ms * 1000,
+				     cfilt_adjust_ms * 1000);
 			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
 				      tabla->mbhc_data.adj_v_ins_hu & 0xFF);
 			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
@@ -2517,7 +2521,8 @@
 			snd_soc_update_bits(codec,
 					    tabla->mbhc_bias_regs.cfilt_val,
 					    0xFC, (cfilt_k_val << 2));
-			usleep_range(10000, 10000);
+			usleep_range(cfilt_adjust_ms * 1000,
+				     cfilt_adjust_ms * 1000);
 			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
 				      tabla->mbhc_data.v_ins_hu & 0xFF);
 			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
@@ -7777,9 +7782,15 @@
 
 	lbuf[cnt] = '\0';
 	buf = (char *)lbuf;
-	tabla->no_mic_headset_override = (*strsep(&buf, " ") == '0') ?
-					     false : true;
-	return rc;
+	TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
+	tabla->no_mic_headset_override =
+	    (*strsep(&buf, " ") == '0') ? false : true;
+	if (tabla->no_mic_headset_override && tabla->mbhc_polling_active) {
+		tabla_codec_pause_hs_polling(tabla->codec);
+		tabla_codec_start_hs_polling(tabla->codec);
+	}
+	TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+	return cnt;
 }
 
 static ssize_t codec_mbhc_debug_read(struct file *file, char __user *buf,