Merge "asoc: bolero: Update rx dc droop register setting"
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index 2ab2e8a..1bc8f9d 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -241,6 +241,7 @@
 	struct wsa_macro_bcl_pmic_params bcl_pmic_params;
 	char __iomem *mclk_mode_muxsel;
 	u16 default_clk_id;
+	u32 pcm_rate_vi;
 	int wsa_digital_mute_status[WSA_MACRO_RX_MAX];
 };
 
@@ -747,6 +748,15 @@
 {
 	struct snd_soc_component *component = dai->component;
 	int ret;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv = dev_get_drvdata(wsa_dev);
+	if (!wsa_priv)
+		return -EINVAL;
 
 	dev_dbg(component->dev,
 		"%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
@@ -764,6 +774,8 @@
 		}
 		break;
 	case SNDRV_PCM_STREAM_CAPTURE:
+		if (dai->id == WSA_MACRO_AIF_VI)
+			wsa_priv->pcm_rate_vi = params_rate(params);
 	default:
 		break;
 	}
@@ -1046,10 +1058,24 @@
 			snd_soc_dapm_to_component(w->dapm);
 	struct device *wsa_dev = NULL;
 	struct wsa_macro_priv *wsa_priv = NULL;
+	u8 val = 0x0;
 
 	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
 		return -EINVAL;
 
+	switch (wsa_priv->pcm_rate_vi) {
+		case 48000:
+			val = 0x04;
+			break;
+		case 24000:
+			val = 0x02;
+			break;
+		case 8000:
+		default:
+			val = 0x00;
+			break;
+	}
+
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		if (test_bit(WSA_MACRO_TX0,
@@ -1064,10 +1090,10 @@
 				0x20, 0x20);
 			snd_soc_component_update_bits(component,
 				BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
-				0x0F, 0x00);
+				0x0F, val);
 			snd_soc_component_update_bits(component,
 				BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CTL,
-				0x0F, 0x00);
+				0x0F, val);
 			snd_soc_component_update_bits(component,
 				BOLERO_CDC_WSA_TX0_SPKR_PROT_PATH_CTL,
 				0x10, 0x10);
@@ -1093,10 +1119,10 @@
 				0x20, 0x20);
 			snd_soc_component_update_bits(component,
 				BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
-				0x0F, 0x00);
+				0x0F, val);
 			snd_soc_component_update_bits(component,
 				BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CTL,
-				0x0F, 0x00);
+				0x0F, val);
 			snd_soc_component_update_bits(component,
 				BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CTL,
 				0x10, 0x10);
diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c
index 78bef6a..2f8e954 100644
--- a/asoc/codecs/rouleur/rouleur-mbhc.c
+++ b/asoc/codecs/rouleur/rouleur-mbhc.c
@@ -37,6 +37,10 @@
 #define ROULEUR_MBHC_ZDET_CONST         (86 * 16384)
 #define ROULEUR_MBHC_MOISTURE_RREF      R_24_KOHM
 
+/* Cross connection thresholds in mV */
+#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 200
+#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 200
+
 static struct wcd_mbhc_register
 	wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {
 	WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN",
@@ -320,11 +324,11 @@
 					0x1C, 0x0C);
 		snd_soc_component_update_bits(component,
 					ROULEUR_ANA_MBHC_MICB2_RAMP,
-					0xA0, 0x80);
+					0x80, 0x80);
 	} else {
 		snd_soc_component_update_bits(component,
 					ROULEUR_ANA_MBHC_MICB2_RAMP,
-					0xA0, 0x00);
+					0x80, 0x00);
 		snd_soc_component_update_bits(component,
 					ROULEUR_ANA_MBHC_MICB2_RAMP,
 					0x1C, 0x00);
@@ -820,15 +824,6 @@
 		rouleur_disable_bcs_before_slow_insert(mbhc->component, true);
 }
 
-static void rouleur_mbhc_hs_vref_max_update(struct wcd_mbhc *mbhc)
-{
-	struct snd_soc_component *component = mbhc->component;
-
-	/* Update the HS Vref max voltage to 1.7V */
-	snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
-				      0x03, 0x03);
-}
-
 static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb)
 {
 	u8 vout_ctl = 0;
@@ -843,19 +838,40 @@
 	pr_debug("%s: vout_ctl: %d, micbias: %d\n", __func__, vout_ctl, *mb);
 }
 
-static void rouleur_mbhc_micb_pullup_control(
-				struct snd_soc_component *component,
-				bool pullup_enable)
+static void rouleur_mbhc_comp_autozero_control(struct wcd_mbhc *mbhc,
+						bool az_enable)
 {
-	if (pullup_enable)
-		rouleur_micbias_control(component, MIC_BIAS_2,
-					MICB_PULLUP_ENABLE, false);
+	if (az_enable)
+		snd_soc_component_update_bits(mbhc->component,
+				ROULEUR_ANA_MBHC_MCLK, 0x08, 0x08);
 	else
-		rouleur_micbias_control(component, MIC_BIAS_2,
-					MICB_PULLUP_DISABLE, false);
+		snd_soc_component_update_bits(mbhc->component,
+				ROULEUR_ANA_MBHC_MCLK, 0x08, 0x00);
 
 }
 
+static void rouleur_mbhc_surge_control(struct wcd_mbhc *mbhc,
+						bool surge_enable)
+{
+	if (surge_enable)
+		snd_soc_component_update_bits(mbhc->component,
+				ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0);
+	else
+		snd_soc_component_update_bits(mbhc->component,
+				ROULEUR_ANA_SURGE_EN, 0xC0, 0x00);
+
+}
+
+static void rouleur_mbhc_update_cross_conn_thr(struct wcd_mbhc *mbhc)
+{
+	mbhc->hphl_cross_conn_thr = ROULEUR_HPHL_CROSS_CONN_THRESHOLD;
+	mbhc->hphr_cross_conn_thr = ROULEUR_HPHR_CROSS_CONN_THRESHOLD;
+
+	pr_debug("%s: Cross connection threshold for hphl: %d, hphr: %d\n",
+			__func__, mbhc->hphl_cross_conn_thr,
+			mbhc->hphr_cross_conn_thr);
+}
+
 static const struct wcd_mbhc_cb mbhc_cb = {
 	.request_irq = rouleur_mbhc_request_irq,
 	.irq_control = rouleur_mbhc_irq_control,
@@ -880,9 +896,10 @@
 	.mbhc_get_moisture_status = rouleur_mbhc_get_moisture_status,
 	.mbhc_moisture_detect_en = rouleur_mbhc_moisture_detect_en,
 	.bcs_enable = rouleur_mbhc_bcs_enable,
-	.hs_vref_max_update = rouleur_mbhc_hs_vref_max_update,
 	.get_micbias_val = rouleur_mbhc_get_micbias_val,
-	.mbhc_micb_pullup_control = rouleur_mbhc_micb_pullup_control,
+	.mbhc_comp_autozero_control = rouleur_mbhc_comp_autozero_control,
+	.mbhc_surge_ctl = rouleur_mbhc_surge_control,
+	.update_cross_conn_thr = rouleur_mbhc_update_cross_conn_thr,
 };
 
 static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol,
diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c
index cdb1de2..e1ecdba 100644
--- a/asoc/codecs/rouleur/rouleur.c
+++ b/asoc/codecs/rouleur/rouleur.c
@@ -107,6 +107,9 @@
 
 static int rouleur_init_reg(struct snd_soc_component *component)
 {
+	/* Disable HPH OCP */
+	snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2,
+					0x03, 0x00);
 	/* Enable surge protection */
 	snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN,
 					0xC0, 0xC0);
@@ -354,7 +357,7 @@
 		usleep_range(5000, 5100);
 		rouleur_global_mbias_enable(component);
 		snd_soc_component_update_bits(component,
-				ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x11);
+				ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x11);
 		snd_soc_component_update_bits(component,
 				ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x80);
 		snd_soc_component_update_bits(component,
@@ -382,14 +385,14 @@
 		snd_soc_component_update_bits(component,
 				ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x00);
 		snd_soc_component_update_bits(component,
-				ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x00);
+				ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x00);
 		snd_soc_component_update_bits(component,
 				ROULEUR_ANA_NCP_EN, 0x01, 0x00);
-		rouleur_global_mbias_disable(component);
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x20, 0x00);
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x10, 0x00);
+		rouleur_global_mbias_disable(component);
 
 	}
 	mutex_unlock(&rouleur->rx_clk_lock);
@@ -478,8 +481,15 @@
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_component_update_bits(component,
-			ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
-			0x01, 0x00);
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
+				0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x04, 0x00);
+		if (rouleur->comp1_enable)
+			snd_soc_component_update_bits(component,
+					ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+					0x02, 0x00);
 		break;
 	}
 
@@ -544,6 +554,13 @@
 	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_component_update_bits(component,
 			ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x08, 0x00);
+		if (rouleur->comp2_enable)
+			snd_soc_component_update_bits(component,
+					ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
+					0x01, 0x00);
 		break;
 
 	}
@@ -568,17 +585,20 @@
 				ROULEUR_DIG_SWR_CDC_RX0_CTL,
 				0x7C, 0x7C);
 		snd_soc_component_update_bits(component,
-				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
-				0x01, 0x01);
-		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
 				0x04, 0x04);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
+				0x01, 0x01);
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
 				0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x04, 0x00);
 
 		break;
 	};
diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c
index 52585ac..bfb32d1 100644
--- a/asoc/codecs/wcd-mbhc-adc.c
+++ b/asoc/codecs/wcd-mbhc-adc.c
@@ -80,8 +80,22 @@
 	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
 	/* Set the MUX selection to IN2P */
 	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_IN2P);
+
+	/*
+	 * Current source mode requires Auto zeroing to be enabled
+	 * automatically. If HW doesn't do it, SW has to take care of this
+	 * for button interrupts to work fine and to avoid
+	 * fake electrical removal interrupts by enabling autozero before FSM
+	 * enable and disable it after FSM enable
+	 */
+	if (mbhc->mbhc_cb->mbhc_comp_autozero_control)
+		mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc,
+							true);
 	/* Enable MBHC FSM */
 	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
+	if (mbhc->mbhc_cb->mbhc_comp_autozero_control)
+		mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc,
+							false);
 	/* Enable ADC_ENABLE bit */
 	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 1);
 
@@ -294,6 +308,10 @@
 	WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
 	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00);
 
+	/* Disable surge detection before ADC measurement */
+	if (mbhc->mbhc_cb->mbhc_surge_ctl)
+		mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, false);
+
 	/* Read and set ADC to single measurement */
 	WCD_MBHC_REG_READ(WCD_MBHC_ADC_MODE, adc_mode);
 	/* Read ADC Enable bit to restore after adc measurement */
@@ -317,7 +335,12 @@
 		goto done;
 	}
 
-	if (hphl_adc_res > 100 || hphr_adc_res > 100) {
+	/* Update cross connection threshold voltages if needed */
+	if (mbhc->mbhc_cb->update_cross_conn_thr)
+		mbhc->mbhc_cb->update_cross_conn_thr(mbhc);
+
+	if (hphl_adc_res > mbhc->hphl_cross_conn_thr ||
+	    hphr_adc_res > mbhc->hphr_cross_conn_thr) {
 		plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
 		pr_debug("%s: Cross connection identified\n", __func__);
 	} else {
@@ -339,6 +362,10 @@
 	/* Restore FSM state */
 	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, fsm_en);
 
+	/* Restore surge detection */
+	if (mbhc->mbhc_cb->mbhc_surge_ctl)
+		mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, true);
+
 	/* Restore electrical detection */
 	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
 
diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c
index 9a2178a..ee24ea6 100644
--- a/asoc/codecs/wcd-mbhc-v2.c
+++ b/asoc/codecs/wcd-mbhc-v2.c
@@ -77,17 +77,13 @@
 	struct snd_soc_component *component = mbhc->component;
 	u32 reg_val;
 
-	if (mbhc->mbhc_cb->hs_vref_max_update) {
-		mbhc->mbhc_cb->hs_vref_max_update(mbhc);
-	} else {
-		plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR(
-					mbhc->mbhc_cfg->calibration);
-		reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);
+	plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR(
+				mbhc->mbhc_cfg->calibration);
+	reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);
 
-		dev_dbg(component->dev, "%s: reg_val  = %x\n",
-				__func__, reg_val);
-		WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val);
-	}
+	dev_dbg(component->dev, "%s: reg_val  = %x\n",
+		__func__, reg_val);
+	WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val);
 }
 
 static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias)
@@ -973,14 +969,6 @@
 			mbhc->mbhc_cb->enable_mb_source(mbhc, true);
 		mbhc->btn_press_intr = false;
 		mbhc->is_btn_press = false;
-		/*
-		 * When current source mode doesn't work properly
-		 * use mic bias pull up mode for button interrupts
-		 * to function properly
-		 */
-		if (mbhc->mbhc_cb->mbhc_micb_pullup_control)
-			mbhc->mbhc_cb->mbhc_micb_pullup_control(component,
-								true);
 		if (mbhc->mbhc_fn)
 			mbhc->mbhc_fn->wcd_mbhc_detect_plug_type(mbhc);
 	} else if ((mbhc->current_plug != MBHC_PLUG_TYPE_NONE)
@@ -1055,10 +1043,6 @@
 									false);
 		}
 
-		if (mbhc->mbhc_cb->mbhc_micb_pullup_control)
-			mbhc->mbhc_cb->mbhc_micb_pullup_control(component,
-								false);
-
 	} else if (!detection_type) {
 		/* Disable external voltage source to micbias if present */
 		if (mbhc->mbhc_cb->enable_mb_source)
@@ -1815,6 +1799,8 @@
 	mbhc->hph_type = WCD_MBHC_HPH_NONE;
 	mbhc->wcd_mbhc_regs = wcd_mbhc_regs;
 	mbhc->swap_thr = GND_MIC_SWAP_THRESHOLD;
+	mbhc->hphl_cross_conn_thr = HPHL_CROSS_CONN_THRESHOLD;
+	mbhc->hphr_cross_conn_thr = HPHR_CROSS_CONN_THRESHOLD;
 
 	if (mbhc->intr_ids == NULL) {
 		pr_err("%s: Interrupt mapping not provided\n", __func__);
diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h
index 774542a..1934141 100644
--- a/include/asoc/wcd-mbhc-v2.h
+++ b/include/asoc/wcd-mbhc-v2.h
@@ -140,6 +140,8 @@
 #define FW_READ_ATTEMPTS 15
 #define FW_READ_TIMEOUT 4000000
 #define FAKE_REM_RETRY_ATTEMPTS 3
+#define HPHL_CROSS_CONN_THRESHOLD 100
+#define HPHR_CROSS_CONN_THRESHOLD 100
 
 #define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS  50
 #define ANC_DETECT_RETRY_CNT 7
@@ -451,12 +453,14 @@
 };
 
 struct wcd_mbhc_cb {
-	void (*mbhc_micb_pullup_control)
-		(struct snd_soc_component *component, bool enable);
+	void (*update_cross_conn_thr)
+		(struct wcd_mbhc *mbhc);
+	void (*mbhc_surge_ctl)
+		(struct wcd_mbhc *mbhc, bool surge_en);
+	void (*mbhc_comp_autozero_control)
+		(struct wcd_mbhc *mbhc, bool az_enable);
 	void (*get_micbias_val)
 		(struct wcd_mbhc *mbhc, int *mb);
-	void (*hs_vref_max_update)
-		(struct wcd_mbhc *mbhc);
 	void (*bcs_enable)
 		(struct wcd_mbhc *mbhc, bool bcs_enable);
 	int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on);
@@ -552,6 +556,8 @@
 	u32 moist_vref;
 	u32 moist_iref;
 	u32 moist_rref;
+	u32 hphl_cross_conn_thr;
+	u32 hphr_cross_conn_thr;
 	u8 micbias1_cap_mode; /* track ext cap setting */
 	u8 micbias2_cap_mode; /* track ext cap setting */
 	bool hs_detect_work_stop;