On Mon, Mar 20, 2023 at 10:35:19PM +0200, Marian Postevca wrote:
In order to reduce the audible pops when speaker or headphones are activated or disabled we need to delay the switching of the GPIOs.
The usual mechanism for doing this is with the standard kernel delay functions. Why not use them in the DAPM event?
We need to also disable/enable the speaker/headphones GPIOs when the audio stream is stopped/started. To avoid race conditions between the speaker power event callback and the trigger callback we use a ring buffer to save the events that we need to process in the delayed work callback.
Why is this required? DAPM is integrated with stream start and stop, and there's a mute callback to mask any noise played back from the SoC while it stops and starts without requiring all this complexity. If there is any audible noise then why would it only affect the speaker?
+static int acp3x_es83xx_trigger(struct snd_pcm_substream *substream, int cmd) +{
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- struct snd_soc_card *card = rtd->card;
- struct acp3x_es83xx_private *priv = get_mach_priv(card);
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
if (substream->stream == 0) {
dev_dbg(priv->codec_dev, "trigger start/release/resume, activating GPIOs\n");
mutex_lock(&priv->rb_lock);
Triggers run in atomic context, you can't use mutexes in atomic context. lockdep should tell you this.