diff options
Diffstat (limited to 'sound/soc/codecs/wcd9335.c')
-rw-r--r-- | sound/soc/codecs/wcd9335.c | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 7ad3aeaa8fb7..2ab787f57b31 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -352,7 +352,6 @@ enum { AUDIO_NOMINAL, CPE_NOMINAL, HPH_PA_DELAY, - SB_CLK_GEAR, ANC_MIC_AMIC1, ANC_MIC_AMIC2, ANC_MIC_AMIC3, @@ -854,7 +853,10 @@ struct tasha_priv { int rx_8_count; bool clk_mode; bool clk_internal; - + /* Lock to prevent multiple functions voting at same time */ + struct mutex sb_clk_gear_lock; + /* Count for functions voting or un-voting */ + u32 ref_count; /* Lock to protect mclk enablement */ struct mutex mclk_lock; }; @@ -2217,6 +2219,32 @@ static void tasha_mbhc_moisture_config(struct wcd_mbhc *mbhc) tasha_mbhc_hph_l_pull_up_control(codec, mbhc->moist_iref); } +static void tasha_update_anc_state(struct snd_soc_codec *codec, bool enable, + int anc_num) +{ + if (enable) + snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CFG0 + + (20 * anc_num), 0x10, 0x10); + else + snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CFG0 + + (20 * anc_num), 0x10, 0x00); +} + +static bool tasha_is_anc_on(struct wcd_mbhc *mbhc) +{ + bool anc_on = false; + u16 ancl, ancr; + + ancl = + (snd_soc_read(mbhc->codec, WCD9335_CDC_RX1_RX_PATH_CFG0)) & 0x10; + ancr = + (snd_soc_read(mbhc->codec, WCD9335_CDC_RX2_RX_PATH_CFG0)) & 0x10; + + anc_on = !!(ancl | ancr); + + return anc_on; +} + static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = tasha_mbhc_request_irq, .irq_control = tasha_mbhc_irq_control, @@ -2239,6 +2267,8 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_gnd_det_ctrl = tasha_mbhc_gnd_det_ctrl, .hph_pull_down_ctrl = tasha_mbhc_hph_pull_down_ctrl, .mbhc_moisture_config = tasha_mbhc_moisture_config, + .update_anc_state = tasha_update_anc_state, + .is_anc_on = tasha_is_anc_on, }; static int tasha_get_anc_slot(struct snd_kcontrol *kcontrol, @@ -3153,10 +3183,7 @@ static int tasha_codec_enable_slimrx(struct snd_soc_dapm_widget *w, &dai->grph); break; case SND_SOC_DAPM_PRE_PMD: - if (!test_bit(SB_CLK_GEAR, &tasha_p->status_mask)) { - tasha_codec_vote_max_bw(codec, true); - set_bit(SB_CLK_GEAR, &tasha_p->status_mask); - } + tasha_codec_vote_max_bw(codec, true); break; case SND_SOC_DAPM_POST_PMD: ret = wcd9xxx_disconnect_port(core, &dai->wcd9xxx_ch_list, @@ -5468,10 +5495,7 @@ static int tasha_codec_enable_interpolator(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - if (!test_bit(SB_CLK_GEAR, &tasha->status_mask)) { - tasha_codec_vote_max_bw(codec, true); - set_bit(SB_CLK_GEAR, &tasha->status_mask); - } + tasha_codec_vote_max_bw(codec, true); /* Reset if needed */ tasha_codec_enable_prim_interpolator(codec, reg, event); break; @@ -5906,8 +5930,6 @@ static int tasha_codec_enable_dec(struct snd_soc_dapm_widget *w, CF_MIN_3DB_150HZ << 5); /* Enable TX PGA Mute */ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10); - /* Enable APC */ - snd_soc_update_bits(codec, dec_cfg_reg, 0x08, 0x08); break; case SND_SOC_DAPM_POST_PMU: snd_soc_update_bits(codec, hpf_gate_reg, 0x01, 0x00); @@ -5934,7 +5956,6 @@ static int tasha_codec_enable_dec(struct snd_soc_dapm_widget *w, hpf_cut_off_freq = tasha->tx_hpf_work[decimator].hpf_cut_off_freq; snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10); - snd_soc_update_bits(codec, dec_cfg_reg, 0x08, 0x00); if (cancel_delayed_work_sync( &tasha->tx_hpf_work[decimator].dwork)) { if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) { @@ -11335,11 +11356,8 @@ static void tasha_shutdown(struct snd_pcm_substream *substream, if (tasha->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) return; - if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) && - test_bit(SB_CLK_GEAR, &tasha->status_mask)) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) tasha_codec_vote_max_bw(dai->codec, false); - clear_bit(SB_CLK_GEAR, &tasha->status_mask); - } } static int tasha_set_decimator_rate(struct snd_soc_dai *dai, @@ -11574,15 +11592,11 @@ prim_rate: static int tasha_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct tasha_priv *tasha = snd_soc_codec_get_drvdata(dai->codec); - pr_debug("%s(): substream = %s stream = %d\n" , __func__, substream->name, substream->stream); - if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) && - test_bit(SB_CLK_GEAR, &tasha->status_mask)) { + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) tasha_codec_vote_max_bw(dai->codec, false); - clear_bit(SB_CLK_GEAR, &tasha->status_mask); - } return 0; } @@ -13290,13 +13304,29 @@ static int tasha_codec_vote_max_bw(struct snd_soc_codec *codec, if (tasha->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) return 0; - if (vote) - bw_ops = SLIM_BW_CLK_GEAR_9; - else - bw_ops = SLIM_BW_UNVOTE; + mutex_lock(&tasha->sb_clk_gear_lock); + if (vote) { + tasha->ref_count++; + if (tasha->ref_count == 1) { + bw_ops = SLIM_BW_CLK_GEAR_9; + tasha_codec_slim_reserve_bw(codec, + bw_ops, true); + } + } else if (!vote && tasha->ref_count > 0) { + tasha->ref_count--; + if (tasha->ref_count == 0) { + bw_ops = SLIM_BW_UNVOTE; + tasha_codec_slim_reserve_bw(codec, + bw_ops, true); + } + }; - return tasha_codec_slim_reserve_bw(codec, - bw_ops, true); + dev_dbg(codec->dev, "%s Value of counter after vote or un-vote is %d\n", + __func__, tasha->ref_count); + + mutex_unlock(&tasha->sb_clk_gear_lock); + + return 0; } static int tasha_cpe_err_irq_control(struct snd_soc_codec *codec, @@ -13479,6 +13509,8 @@ static int tasha_post_reset_cb(struct wcd9xxx *wcd9xxx) if (IS_ERR_VALUE(ret)) dev_err(codec->dev, "%s: invalid pdata\n", __func__); + /* Reset reference counter for voting for max bw */ + tasha->ref_count = 0; /* MBHC Init */ wcd_mbhc_deinit(&tasha->mbhc); tasha->mbhc_started = false; @@ -14265,6 +14297,7 @@ static int tasha_probe(struct platform_device *pdev) mutex_init(&tasha->swr_read_lock); mutex_init(&tasha->swr_write_lock); mutex_init(&tasha->swr_clk_lock); + mutex_init(&tasha->sb_clk_gear_lock); mutex_init(&tasha->mclk_lock); cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region), @@ -14369,6 +14402,7 @@ static int tasha_remove(struct platform_device *pdev) mutex_destroy(&tasha->mclk_lock); devm_kfree(&pdev->dev, tasha); snd_soc_unregister_codec(&pdev->dev); + mutex_destroy(&tasha->sb_clk_gear_lock); return 0; } |