From 13faf538b32ed00ee6bde18831a72973ff4a3d2c Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Wed, 13 Feb 2019 12:55:30 +0530 Subject: [PATCH] ASoC: wcd937x: Fix playback stop issue after SSR/PDR on special hs If we start playback on special hs after record is done and perform SSR/PDR then playback gets paused. This happens because ANA_TX_DIV2_CLK which needs to be enabled for special hs gets disabled after record is stopped. Maintain a count for ANA_DIV2_CLK to enable/disable it as required. Change-Id: Ic73475c83cb16e3c014f35b8d46ee22d2e7a2efd Signed-off-by: Vatsal Bucha --- asoc/codecs/wcd937x/internal.h | 2 ++ asoc/codecs/wcd937x/wcd937x.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/wcd937x/internal.h b/asoc/codecs/wcd937x/internal.h index 110425a892..b7bdfa22dd 100644 --- a/asoc/codecs/wcd937x/internal.h +++ b/asoc/codecs/wcd937x/internal.h @@ -83,6 +83,8 @@ struct wcd937x_priv { struct snd_info_entry *entry; struct snd_info_entry *version_entry; int ear_rx_path; + int ana_clk_count; + struct mutex ana_tx_clk_lock; }; struct wcd937x_micbias_setting { diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c index beb4b177fd..29c2774d29 100644 --- a/asoc/codecs/wcd937x/wcd937x.c +++ b/asoc/codecs/wcd937x/wcd937x.c @@ -1267,12 +1267,17 @@ static int wcd937x_codec_enable_adc(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct wcd937x_priv *wcd937x = + snd_soc_component_get_drvdata(component); dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, w->name, event); switch (event) { case SND_SOC_DAPM_PRE_PMU: + mutex_lock(&wcd937x->ana_tx_clk_lock); + wcd937x->ana_clk_count++; + mutex_unlock(&wcd937x->ana_tx_clk_lock); snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80); snd_soc_component_update_bits(component, @@ -1296,6 +1301,8 @@ static int wcd937x_enable_req(struct snd_soc_dapm_widget *w, { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct wcd937x_priv *wcd937x = + snd_soc_component_get_drvdata(component); dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, w->name, event); @@ -1324,8 +1331,15 @@ static int wcd937x_enable_req(struct snd_soc_dapm_widget *w, WCD937X_ANA_TX_CH2, 0x80, 0x00); snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x10, 0x00); - snd_soc_component_update_bits(component, + mutex_lock(&wcd937x->ana_tx_clk_lock); + wcd937x->ana_clk_count--; + if (wcd937x->ana_clk_count <= 0) { + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00); + wcd937x->ana_clk_count = 0; + } + + mutex_unlock(&wcd937x->ana_tx_clk_lock); snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x00); break; @@ -1389,6 +1403,9 @@ int wcd937x_micbias_control(struct snd_soc_component *component, break; case MICB_ENABLE: wcd937x->micb_ref[micb_index]++; + mutex_lock(&wcd937x->ana_tx_clk_lock); + wcd937x->ana_clk_count++; + mutex_unlock(&wcd937x->ana_tx_clk_lock); if (wcd937x->micb_ref[micb_index] == 1) { snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0xE0, 0xE0); @@ -1413,6 +1430,9 @@ int wcd937x_micbias_control(struct snd_soc_component *component, &wcd937x->mbhc->wcd_mbhc); break; case MICB_DISABLE: + mutex_lock(&wcd937x->ana_tx_clk_lock); + wcd937x->ana_clk_count--; + mutex_unlock(&wcd937x->ana_tx_clk_lock); if (wcd937x->micb_ref[micb_index] > 0) wcd937x->micb_ref[micb_index]--; if ((wcd937x->micb_ref[micb_index] == 0) && @@ -1433,6 +1453,14 @@ int wcd937x_micbias_control(struct snd_soc_component *component, post_off_event, &wcd937x->mbhc->wcd_mbhc); } + mutex_lock(&wcd937x->ana_tx_clk_lock); + if (wcd937x->ana_clk_count <= 0) { + snd_soc_component_update_bits(component, + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, + 0x10, 0x00); + wcd937x->ana_clk_count = 0; + } + mutex_unlock(&wcd937x->ana_tx_clk_lock); if (is_dapm && post_dapm_off && wcd937x->mbhc) blocking_notifier_call_chain( &wcd937x->mbhc->notifier, post_dapm_off, @@ -2757,6 +2785,7 @@ static int wcd937x_bind(struct device *dev) } mutex_init(&wcd937x->micb_lock); + mutex_init(&wcd937x->ana_tx_clk_lock); /* Request for watchdog interrupt */ wcd_request_irq(&wcd937x->irq_info, WCD937X_IRQ_HPHR_PDM_WD_INT, "HPHR PDM WD INT", wcd937x_wd_handle_irq, NULL); @@ -2793,6 +2822,7 @@ static void wcd937x_unbind(struct device *dev) snd_soc_unregister_component(dev); component_unbind_all(dev, wcd937x); mutex_destroy(&wcd937x->micb_lock); + mutex_destroy(&wcd937x->ana_tx_clk_lock); } static const struct of_device_id wcd937x_dt_match[] = {