ASoC: Fix audio distortion issue during headset record
Audio is distorted during first 3 secs on headset record
while doing device switch from dmic to headset mic.
Disable BCS before slow insertion detection and enable it
afterwards to resolve the issue.
Change-Id: Ie5bc4b5292e5f69066760cab44d78989a74f13f4
Signed-off-by: Vatsal Bucha <vbucha@codeaurora.org>
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index feb0082..e56127c 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -214,6 +214,12 @@
priv->component,
BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST, data);
break;
+ case WCD_BOLERO_EVT_BCS_CLK_OFF:
+ if (priv->macro_params[TX_MACRO].event_handler)
+ priv->macro_params[TX_MACRO].event_handler(
+ priv->component,
+ BOLERO_MACRO_EVT_BCS_CLK_OFF, data);
+ break;
default:
dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n",
__func__, event);
diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h
index f104f88..fe02ad0 100644
--- a/asoc/codecs/bolero/bolero-cdc.h
+++ b/asoc/codecs/bolero/bolero-cdc.h
@@ -40,7 +40,8 @@
BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET,
BOLERO_MACRO_EVT_CLK_RESET,
BOLERO_MACRO_EVT_REG_WAKE_IRQ,
- BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST
+ BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST,
+ BOLERO_MACRO_EVT_BCS_CLK_OFF
};
struct macro_ops {
diff --git a/asoc/codecs/bolero/internal.h b/asoc/codecs/bolero/internal.h
index d3f6894..ba89832 100644
--- a/asoc/codecs/bolero/internal.h
+++ b/asoc/codecs/bolero/internal.h
@@ -31,6 +31,7 @@
WCD_BOLERO_EVT_IMPED_TRUE, /* for imped true */
WCD_BOLERO_EVT_IMPED_FALSE, /* for imped false */
WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
+ WCD_BOLERO_EVT_BCS_CLK_OFF,
};
struct wcd_ctrl_platform_data {
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index ca88bfa..73ce9d2 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -172,6 +172,8 @@
int tx_clk_status;
bool bcs_enable;
int dec_mode[NUM_DECIMATORS];
+ bool bcs_clk_en;
+ bool hs_slow_insert_complete;
};
static bool tx_macro_get_data(struct snd_soc_component *component,
@@ -387,6 +389,15 @@
case BOLERO_MACRO_EVT_CLK_RESET:
bolero_rsc_clk_reset(tx_dev, TX_CORE_CLK);
break;
+ case BOLERO_MACRO_EVT_BCS_CLK_OFF:
+ if (tx_priv->bcs_clk_en)
+ snd_soc_component_update_bits(component,
+ BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, data << 6);
+ if (data)
+ tx_priv->hs_slow_insert_complete = true;
+ else
+ tx_priv->hs_slow_insert_complete = false;
+ break;
}
return 0;
}
@@ -902,8 +913,11 @@
if (tx_priv->bcs_enable) {
snd_soc_component_update_bits(component, dec_cfg_reg,
0x01, 0x01);
- snd_soc_component_update_bits(component,
- BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x40);
+ tx_priv->bcs_clk_en = true;
+ if (tx_priv->hs_slow_insert_complete)
+ snd_soc_component_update_bits(component,
+ BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40,
+ 0x40);
}
break;
case SND_SOC_DAPM_PRE_PMD:
@@ -946,6 +960,7 @@
0x01, 0x00);
snd_soc_component_update_bits(component,
BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x00);
+ tx_priv->bcs_clk_en = false;
}
break;
}
diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c
index 4de19de..9652d11 100644
--- a/asoc/codecs/wcd-mbhc-adc.c
+++ b/asoc/codecs/wcd-mbhc-adc.c
@@ -689,6 +689,13 @@
}
correct_plug_type:
+ /*
+ * Callback to disable BCS slow insertion detection
+ */
+ if (plug_type == MBHC_PLUG_TYPE_HEADSET ||
+ plug_type == MBHC_PLUG_TYPE_HEADPHONE)
+ mbhc->mbhc_cb->bcs_enable(mbhc, false);
+
timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
while (!time_after(jiffies, timeout)) {
if (mbhc->hs_detect_work_stop) {
@@ -833,6 +840,10 @@
wrk_complete = false;
}
}
+ if ((plug_type == MBHC_PLUG_TYPE_HEADSET ||
+ plug_type == MBHC_PLUG_TYPE_HEADPHONE))
+ mbhc->mbhc_cb->bcs_enable(mbhc, true);
+
if (!wrk_complete) {
/*
* If plug_tye is headset, we might have already reported either
diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h
index 098a60d..46d61a0 100644
--- a/asoc/codecs/wcd938x/internal.h
+++ b/asoc/codecs/wcd938x/internal.h
@@ -149,6 +149,7 @@
WCD_BOLERO_EVT_IMPED_TRUE, /* for imped true */
WCD_BOLERO_EVT_IMPED_FALSE, /* for imped false */
WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
+ WCD_BOLERO_EVT_BCS_CLK_OFF,
};
enum {
@@ -182,6 +183,9 @@
extern struct wcd938x_mbhc *wcd938x_soc_get_mbhc(
struct snd_soc_component *component);
+extern void wcd938x_disable_bcs_before_slow_insert(
+ struct snd_soc_component *component,
+ bool bcs_disable);
extern int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
int volt, int micb_num);
extern int wcd938x_get_micb_vout_ctl_val(u32 micb_mv);
diff --git a/asoc/codecs/wcd938x/wcd938x-mbhc.c b/asoc/codecs/wcd938x/wcd938x-mbhc.c
index 27566ee..0687de6 100644
--- a/asoc/codecs/wcd938x/wcd938x-mbhc.c
+++ b/asoc/codecs/wcd938x/wcd938x-mbhc.c
@@ -803,6 +803,15 @@
0x04, (enable << 2));
}
+static void wcd938x_mbhc_bcs_enable(struct wcd_mbhc *mbhc,
+ bool bcs_enable)
+{
+ if (bcs_enable)
+ wcd938x_disable_bcs_before_slow_insert(mbhc->component, false);
+ else
+ wcd938x_disable_bcs_before_slow_insert(mbhc->component, true);
+}
+
static const struct wcd_mbhc_cb mbhc_cb = {
.request_irq = wcd938x_mbhc_request_irq,
.irq_control = wcd938x_mbhc_irq_control,
@@ -827,6 +836,7 @@
.mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status,
.mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl,
.mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en,
+ .bcs_enable = wcd938x_mbhc_bcs_enable,
};
static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol,
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index 04954d9..0355ea6 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -1523,6 +1523,21 @@
return 0;
}
+void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
+ bool bcs_disable)
+{
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+ if (wcd938x->update_wcd_event) {
+ if (bcs_disable)
+ wcd938x->update_wcd_event(wcd938x->handle,
+ WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
+ else
+ wcd938x->update_wcd_event(wcd938x->handle,
+ WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
+ }
+}
+
int wcd938x_tx_channel_config(struct snd_soc_component *component,
int channel, int mode)
{
diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h
index 1f9d64e..f3ee728 100644
--- a/include/asoc/wcd-mbhc-v2.h
+++ b/include/asoc/wcd-mbhc-v2.h
@@ -451,6 +451,8 @@
};
struct wcd_mbhc_cb {
+ void (*bcs_enable)
+ (struct wcd_mbhc *mbhc, bool bcs_enable);
int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on);
void (*trim_btn_reg)(struct snd_soc_component *component);
void (*compute_impedance)(struct wcd_mbhc *mbhc,