Skip to content

Commit 89cdb22

Browse files
Zhu Ningbroonie
authored andcommitted
ASoC: sof_es8336: reduce pop noise on speaker
The Speaker GPIO needs to be turned on slightly behind the codec turned on. It also need to be turned off slightly before the codec turned down. Current code uses delay in DAPM_EVENT to do it but the mdelay delays the DAPM itself and thus has no effect. A delayed_work is added to turn on the speaker. The Speaker is turned off in .trigger since trigger is called slightly before the DAPM events. Signed-off-by: Zhu Ning <[email protected]> ------------ v1: cancel delayed work while disabling speaker. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 3d59eae commit 89cdb22

File tree

1 file changed

+46
-14
lines changed

1 file changed

+46
-14
lines changed

sound/soc/intel/boards/sof_es8336.c

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct sof_es8336_private {
6363
struct snd_soc_jack jack;
6464
struct list_head hdmi_pcm_list;
6565
bool speaker_en;
66+
struct delayed_work pcm_pop_work;
6667
};
6768

6869
struct sof_hdmi_pcm {
@@ -111,6 +112,46 @@ static void log_quirks(struct device *dev)
111112
dev_info(dev, "quirk headset at mic1 port enabled\n");
112113
}
113114

115+
static void pcm_pop_work_events(struct work_struct *work)
116+
{
117+
struct sof_es8336_private *priv =
118+
container_of(work, struct sof_es8336_private, pcm_pop_work.work);
119+
120+
gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_en);
121+
122+
if (quirk & SOF_ES8336_HEADPHONE_GPIO)
123+
gpiod_set_value_cansleep(priv->gpio_headphone, priv->speaker_en);
124+
125+
}
126+
127+
static int sof_8336_trigger(struct snd_pcm_substream *substream, int cmd)
128+
{
129+
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
130+
struct snd_soc_card *card = rtd->card;
131+
struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
132+
133+
switch (cmd) {
134+
case SNDRV_PCM_TRIGGER_START:
135+
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
136+
case SNDRV_PCM_TRIGGER_RESUME:
137+
break;
138+
139+
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
140+
case SNDRV_PCM_TRIGGER_SUSPEND:
141+
case SNDRV_PCM_TRIGGER_STOP:
142+
if (priv->speaker_en == false)
143+
if (substream->stream == 0) {
144+
cancel_delayed_work(&priv->pcm_pop_work);
145+
gpiod_set_value_cansleep(priv->gpio_speakers, true);
146+
}
147+
break;
148+
default:
149+
return -EINVAL;
150+
}
151+
152+
return 0;
153+
}
154+
114155
static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
115156
struct snd_kcontrol *kcontrol, int event)
116157
{
@@ -122,19 +163,7 @@ static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
122163

123164
priv->speaker_en = !SND_SOC_DAPM_EVENT_ON(event);
124165

125-
if (SND_SOC_DAPM_EVENT_ON(event))
126-
msleep(70);
127-
128-
gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_en);
129-
130-
if (!(quirk & SOF_ES8336_HEADPHONE_GPIO))
131-
return 0;
132-
133-
if (SND_SOC_DAPM_EVENT_ON(event))
134-
msleep(70);
135-
136-
gpiod_set_value_cansleep(priv->gpio_headphone, priv->speaker_en);
137-
166+
queue_delayed_work(system_wq, &priv->pcm_pop_work, msecs_to_jiffies(70));
138167
return 0;
139168
}
140169

@@ -344,6 +373,7 @@ static int sof_es8336_hw_params(struct snd_pcm_substream *substream,
344373
/* machine stream operations */
345374
static struct snd_soc_ops sof_es8336_ops = {
346375
.hw_params = sof_es8336_hw_params,
376+
.trigger = sof_8336_trigger,
347377
};
348378

349379
static struct snd_soc_dai_link_component platform_component[] = {
@@ -723,7 +753,8 @@ static int sof_es8336_probe(struct platform_device *pdev)
723753
}
724754

725755
INIT_LIST_HEAD(&priv->hdmi_pcm_list);
726-
756+
INIT_DELAYED_WORK(&priv->pcm_pop_work,
757+
pcm_pop_work_events);
727758
snd_soc_card_set_drvdata(card, priv);
728759

729760
if (mach->mach_params.dmic_num > 0) {
@@ -752,6 +783,7 @@ static int sof_es8336_remove(struct platform_device *pdev)
752783
struct snd_soc_card *card = platform_get_drvdata(pdev);
753784
struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
754785

786+
cancel_delayed_work(&priv->pcm_pop_work);
755787
gpiod_put(priv->gpio_speakers);
756788
device_remove_software_node(priv->codec_dev);
757789
put_device(priv->codec_dev);

0 commit comments

Comments
 (0)