summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/wcd9335.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wcd9335.c')
-rw-r--r--sound/soc/codecs/wcd9335.c92
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;
}