Hi Takashi,
I have a question related to HDA codecs, power saving and sending verb configuration. In our tests we test avs driver with HDA codec configuration and we see problem when arecord is started before codec goes to first sleep.
In ASoC code we set power save timeout to 2 seconds [1], if we start recording before codec goes to sleep, we record only silence.
Now I've spend some time investigating the issue and as far as I can tell, when codec is being initialized channels are being set to mute and when one starts stream before first "sleep" it never sends proper configuration to codec. However if one allows codec to go to sleep proper configuration is being send on resume.
I've also managed to reproduce it with non DSP configuration (using snd_hda_intel driver). One needs to set power_save to non zero value and start recording, before it first goes into first sleep.
Here are the steps: 1. Add following to /etc/modprobe.d/test.conf options snd_intel_dspcfg dsp_driver=1 options snd_hda_intel power_save=5 blacklist snd_hda_intel 2. Reboot the machine 3. Run something like (it is time sensitive, so I just run it all in one line): echo "PRE MODPROBE" > /dev/kmsg; modprobe snd_hda_intel; echo "POST MODPROBE" > /dev/kmsg; sleep 1; echo "PRE ARECORD" > /dev/kmsg; arecord -Dhw:PCH,0 -r48 -c2 -fS16_LE -d 20 -vvv /tmp/cap.wav; echo "POST ARECORD" > /dev/kmsg; 4. Observe silence in above file 5. Run after waiting more than 5 seconds: echo "PRE SECOND ARECORD" > /dev/kmsg; arecord -Dhw:PCH,0 -r48 -c2 -fS16_LE -d 20 -vvv /tmp/cap.wav; echo "POST SECOND ARECORD" > /dev/kmsg;
I'm also attaching logs from my reproduction with debug.diff (also attached) applied. Main purpose of debug.diff is to log when snd_hdac_exec_verb() is called and to log backtraces for when record input is muted on load and set on startup.
When looking at attached dmesg, it is easy to see that when first arecord is being run almost no configuration happens.
Now my question is what would be the proper way to fix the issue?
Something like forcing the codec to suspend as soon as it is setup seems to work, but I'm pretty sure it is not the best way...:
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 2e728aad6771..251466aaef88 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1049,6 +1049,8 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, pm_runtime_get_noresume(&codec->core.dev); #endif
+ pm_runtime_force_suspend(&codec->core.dev); + return 0; } EXPORT_SYMBOL_GPL(snd_hda_codec_device_new);
Do you have any better ideas?
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/soun...