From d06525fa6853fe6faff8e4bf9b8355b80abccdd4 Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Mon, 14 Oct 2019 23:14:12 +0530 Subject: [PATCH] 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 --- asoc/codecs/bolero/bolero-cdc.c | 6 ++++++ asoc/codecs/bolero/bolero-cdc.h | 3 ++- asoc/codecs/bolero/internal.h | 1 + asoc/codecs/bolero/tx-macro.c | 19 +++++++++++++++++-- asoc/codecs/wcd-mbhc-adc.c | 11 +++++++++++ asoc/codecs/wcd938x/internal.h | 4 ++++ asoc/codecs/wcd938x/wcd938x-mbhc.c | 10 ++++++++++ asoc/codecs/wcd938x/wcd938x.c | 15 +++++++++++++++ include/asoc/wcd-mbhc-v2.h | 2 ++ 9 files changed, 68 insertions(+), 3 deletions(-) diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index feb0082eea..e56127ce4f 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -214,6 +214,12 @@ static int bolero_cdc_update_wcd_event(void *handle, u16 event, u32 data) 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 f104f88a34..fe02ad0d4c 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -40,7 +40,8 @@ enum { 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 d3f6894674..ba89832e86 100644 --- a/asoc/codecs/bolero/internal.h +++ b/asoc/codecs/bolero/internal.h @@ -31,6 +31,7 @@ enum { 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 ca88bfa158..73ce9d254a 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -172,6 +172,8 @@ struct tx_macro_priv { 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 @@ static int tx_macro_event_handler(struct snd_soc_component *component, 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 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, 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 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, 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 4de19de467..9652d11dea 100644 --- a/asoc/codecs/wcd-mbhc-adc.c +++ b/asoc/codecs/wcd-mbhc-adc.c @@ -689,6 +689,13 @@ static void wcd_correct_swch_plug(struct work_struct *work) } 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 @@ correct_plug_type: 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 098a60dac8..46d61a00db 100644 --- a/asoc/codecs/wcd938x/internal.h +++ b/asoc/codecs/wcd938x/internal.h @@ -149,6 +149,7 @@ enum { 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 @@ enum { 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 27566ee85b..0687de6475 100644 --- a/asoc/codecs/wcd938x/wcd938x-mbhc.c +++ b/asoc/codecs/wcd938x/wcd938x-mbhc.c @@ -803,6 +803,15 @@ static void wcd938x_mbhc_moisture_polling_ctrl(struct wcd_mbhc *mbhc, 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 @@ static const struct wcd_mbhc_cb mbhc_cb = { .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 04954d9f9d..0355ea6f34 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -1523,6 +1523,21 @@ static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w, 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 1f9d64e3ba..f3ee728243 100644 --- a/include/asoc/wcd-mbhc-v2.h +++ b/include/asoc/wcd-mbhc-v2.h @@ -451,6 +451,8 @@ struct wcd_mbhc_register { }; 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,