diff options
author | Cristian Ciocaltea <cristian.ciocaltea@collabora.com> | 2023-09-07 20:10:03 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2023-09-11 13:34:36 +0100 |
commit | 77bf613f0bf08c021309cdb5f84b5f630b829261 (patch) | |
tree | 6a2824bbc214f5694ac6b7f830892f79359b896e /sound/soc/codecs/cs35l41.c | |
parent | 5ad668a9ce83d819701fb7abc1c2236049ec15c2 (diff) |
ASoC: cs35l41: Fix broken shared boost activation
Enabling the active/passive shared boosts requires setting SYNC_EN, but
*not* before receiving the PLL Lock signal.
Due to improper error handling, it was not obvious that waiting for the
completion operation times out and, consequently, the shared boost is
never activated.
Further investigations revealed the signal is triggered while
snd_pcm_start() is executed, right after receiving the
SNDRV_PCM_TRIGGER_START command, which happens long after the
SND_SOC_DAPM_PRE_PMU event handler is invoked as part of
snd_pcm_prepare(). That is where cs35l41_global_enable() is called
from.
Increasing the wait duration doesn't help, as it only causes an
unnecessary delay in the invocation of snd_pcm_start(). Moving the wait
and the subsequent regmap operations to the SNDRV_PCM_TRIGGER_START
callback is not a solution either, since they would be executed in an
IRQ-off atomic context.
Solve the issue by setting the SYNC_EN bit in PWR_CTRL3 register right
after receiving the PLL Lock interrupt.
Additionally, drop the unnecessary writes to PWR_CTRL1 register, part of
the original mdsync_up_seq, which would have toggled GLOBAL_EN with
unwanted consequences on PLL locking behavior.
Fixes: f5030564938b ("ALSA: cs35l41: Add shared boost feature")
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Reviewed-by: David Rhodes <david.rhodes@cirrus.com>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20230907171010.1447274-5-cristian.ciocaltea@collabora.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/cs35l41.c')
-rw-r--r-- | sound/soc/codecs/cs35l41.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index fe5376b3e01b..12327b4c3d56 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -459,7 +459,19 @@ static irqreturn_t cs35l41_irq(int irq, void *data) if (status[2] & CS35L41_PLL_LOCK) { regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS3, CS35L41_PLL_LOCK); - complete(&cs35l41->pll_lock); + + if (cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_ACTV || + cs35l41->hw_cfg.bst_type == CS35L41_SHD_BOOST_PASS) { + ret = cs35l41_mdsync_up(cs35l41->regmap); + if (ret) + dev_err(cs35l41->dev, "MDSYNC-up failed: %d\n", ret); + else + dev_dbg(cs35l41->dev, "MDSYNC-up done\n"); + + dev_dbg(cs35l41->dev, "PUP-done status: %d\n", + !!(status[0] & CS35L41_PUP_DONE_MASK)); + } + ret = IRQ_HANDLED; } @@ -500,11 +512,11 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w, ARRAY_SIZE(cs35l41_pup_patch)); ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type, - 1, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running); + 1, cs35l41->dsp.cs_dsp.running); break; case SND_SOC_DAPM_POST_PMD: ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type, - 0, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running); + 0, cs35l41->dsp.cs_dsp.running); regmap_multi_reg_write_bypassed(cs35l41->regmap, cs35l41_pdn_patch, @@ -802,10 +814,6 @@ static const struct snd_pcm_hw_constraint_list cs35l41_constraints = { static int cs35l41_pcm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component); - - reinit_completion(&cs35l41->pll_lock); - if (substream->runtime) return snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, @@ -1273,8 +1281,6 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK3, CS35L41_INT3_PLL_LOCK_MASK, 0 << CS35L41_INT3_PLL_LOCK_SHIFT); - init_completion(&cs35l41->pll_lock); - ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq, IRQF_ONESHOT | IRQF_SHARED | irq_pol, "cs35l41", cs35l41); |