ASoC: SOF: Intel: optimise jack detection#1031
ASoC: SOF: Intel: optimise jack detection#1031ranj063 merged 2 commits intothesofproject:topic/sof-devfrom
Conversation
plbossart
left a comment
There was a problem hiding this comment.
LGTM but there is one condition that can be clarified for the rest of us.
sound/soc/sof/intel/hda-codec.c
Outdated
|
|
||
| list_for_each_codec(codec, hbus) | ||
| if (mask & BIT(codec->core.addr)) | ||
| if (status & BIT(codec->core.addr) && codec->jacktbl.used) { |
There was a problem hiding this comment.
this is a bit confusing to have both types of AND in the same test, I don't even know what precedence rules apply?
RanderWang
left a comment
There was a problem hiding this comment.
I don't agree this change. Jack detection doesn't work when checking sound setting.
@ClarexZhou can you test this patch to check sound setting case.
|
As discussed in my patch for jack detection, for some cases like playback with HDMI or capture with DMIC connected to dsp. In these cases, only controller is active and codecs are suspended. At this time if a headphone or headset is plugged in, WAKEEN feature will not trigger interrupt to resume sof (it is already resumed). How to do ? I checked the legacy hda (please check the WSR sent by me) and found one way to fix it. Just check the jack status of non-hdmi codec, which is activated by this poll operation, when controller is resuming, and then unsolicited event can be sent to controller to do jack detection. Even then non-hdmi codec goes to sleep, the unsolicited event still works. This is what I learned from legacy hda driver. This costs little time . We already reload FW and power up the dsp. More info: for sound setting case, pulse audio will setup a capture stream with DMIC. At this time, hda codec is still suspended and the status of WAKEEN interrupt will be zero because the resume is triggered by capture not by WAKEEN interrupt. |
|
Check jack detection function with https://github.com/lyakh/linux/commits/ipc-no_disable, which include #1031. Jack detection still not work in below 2 scenarios: |
|
@RanderWang thanks for reviewing. I have been able to reproduce the problem by waiting for runtime-suspend and then starting HDMI-audio playback. Which HDMI-playback was active no jack detection was possible. Is this the problem, that you're describing? Same with DMIC or, I guess, any other connection, not using the respective codec. As far as I understand your patch, you force wake up to the HDA codec by scheduling the jack-detection work, is my understanding correct? That means, that one of the ways to fix this problem would be to always force any HDA codecs with jacks to wake up when the controller wakes up. Would the other option work too - if we only enable WAKEEN when the codec runtime-suspends, and disable WAKEEN when the codec wakes up? I.e. would WAKEEN work when the controller is active but the codec is suspended? |
|
Interesting, just keeping WAKEEN always set doesn't seem to help. |
|
@RanderWang ok, I updated the patch. I kept your approach to schedule a jack check for all jack-capable codecs, although I don't quite understand why it works. In principle what we want is when the controller wakes up to also wake up those codecs, right? But I briefly checked the jack-detection path and I didn't find anything like that there. I didn't check codec methods though. But I also don't understand how the codec then stays awake for the whole duration of the controller being awake and then suspends again... Anyway, I think this now should be quite close to your version, just with less added code. |
Actually , codec will suspends if it is not used, not staying awake. But with these operations, codec could send unsolicited event to controller, even codec is suspended. I checked legacy hda driver and did a few experiments, then found this behavior. |
sound/soc/sof/intel/hda-dsp.c
Outdated
| snd_hdac_chip_writew(bus, WAKEEN, | ||
| snd_hdac_chip_readw(bus, WAKEEN) | | ||
| hda->hda_codec_mask); | ||
| snd_hdac_chip_readw(bus, WAKEEN) | mask); |
There was a problem hiding this comment.
you changed hda->hda_codec_mask to ~STATESTS_INT_MASK in hda_codec_jack_check, why not here ?
There was a problem hiding this comment.
we only enable the bits, that we need, but it doesn't hurt disabling all possible bits.
There was a problem hiding this comment.
can you implement a function in hda-codec.c to do this ? Just like hda_codec_jack_check. Here only
if (runtime)
xxx_xxxx_xxx
also move if (IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) && runtime_suspend) to the function to make codec beautiful.
| * even codecs become suspended later. | ||
| */ | ||
| mask = status ? status : hda->hda_codec_mask; | ||
|
|
There was a problem hiding this comment.
don't check status ? If there is one codec, there is no different for this change. But if there are two codecs, the checking will save one jack polling operation.
There was a problem hiding this comment.
but do we want that? I thought that actually would be bad? If there are 2 codecs and one of them has a bit set in the status, we will only check it, so the other codec will stay suspended? And if headphones are plugged into it, they won't be detected?
There was a problem hiding this comment.
Good question: one popular design: two codecs, one for headphone, anther one with amplifier for speaker. Some vendors may add a special codec for DMIC.
I don't insist on checking status. It is a just optional optimization.
There was a problem hiding this comment.
On my PC I have 8 3.5 mm jack ports - 2 on the front panel and 6 on the back. They aren't all handled by the same codec, are they? How common are designs with multiple codecs providing multiple jack connectors?
There was a problem hiding this comment.
for HDaudio designs, it's typically to have an all-in-one integrated codec which can deal with amplification and jack detection. I don't think we have a need to handle jack detection across multiple HDaudio codecs, it's difficult enough for a single codec to get things right.
There was a problem hiding this comment.
yes, but there are still two codecs cases. I also talked to @bardliao and conformed this case. Takashi also had a UCM patch for two codecs. But I think this case it is not a common case and we haven't test SOF on two codecs device.
There was a problem hiding this comment.
yes, but there are still two codecs cases. I also talked to @bardliao and conformed this case.
@RanderWang Sorry I thought we were talking about I2S codec. I know that there are some designs with more than one codec. E.g. one for headset and the other for speaker.
we haven't test SOF on two codecs device.
Yes, we have.
Interesting, do we know what exactly changes the codec "mode" from "completely suspended" to "suspended but sending UNSOLs?" |
|
@lyakh the previous version was a bit more intuitive ie check the status for which codec generated the unsol event and check the jack status for that one. But with this version, you wake up all codecs that are jack capable. Why is this better than that? |
@ranj063 you can see an explanation in my discussion with Rander above. If you look at the present code that's also what it does - almost. But IMHO in a less obvious way. It checks if the status != 0, then it uses it. If status == 0, then it checks all the codecs... So if the system has more than one codec with jack connectors, with the current code it seems like some of those connectors can stay suspended and will miss any plugin events. |
@lyakh hmm yes I missed that part, thanks. I think it makes sense now. |
sound/soc/sof/intel/hda-dsp.c
Outdated
|
|
||
| list_for_each_codec(codec, hbus) | ||
| if (codec->jacktbl.used) | ||
| mask |= BIT(codec->core.addr); |
There was a problem hiding this comment.
@lyakh can you please add a comment here to explain that we want to wake-up all jack capable codecs irrespective of status
In my opinion, after codec resumes, controller setup a link for this codec. And this link is still available even codec sleeps. If the controller is suspended, the link is invalid. |
RanderWang
left a comment
There was a problem hiding this comment.
Minor fix needed but this looks fine in general. Thanks
sound/soc/sof/intel/hda-dsp.c
Outdated
| @@ -297,10 +297,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, int state, | |||
|
|
|||
| #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | |||
| if (IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) && runtime_suspend) | |||
There was a problem hiding this comment.
just remove IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
There was a problem hiding this comment.
why? jack detection doesn't really make sense for HDMI, does it?
There was a problem hiding this comment.
please check hda_codec_jack_wake_enable, the CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC is there.
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
hda_codec_jack_wake_enable(){
....
}
#else
hda_codec_jack_wake_enable() {}
#endif
There was a problem hiding this comment.
?? what are you trying to say?
There was a problem hiding this comment.
@plbossart: @RanderWang is saying, that you don't need to check for CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC before calling hda_codec_jack_wake_enable() because if the CONFIG_... isn't selected, the function is defined as a dummy, so, it's still safe to call it. @RanderWang you're right, I'll update that, thanks
There was a problem hiding this comment.
thanks for the translation. I'd like this PR to be completed soonish so that we can move on.
There was a problem hiding this comment.
thanks @lyakh for your explanation. Actually, this idea was suggested by @plbossart when I implemented hda_codec_jack_check.
plbossart
left a comment
There was a problem hiding this comment.
nit-pick below, but this looks quite good.
plbossart
left a comment
There was a problem hiding this comment.
LGTM, need a 2nd reviewer. @RanderWang @ranj063 please chime in
|
As for the failing CI, this patch only touches HDA so I cannot see how it can break aplay on BYT. Interestingly, just because #1020 has also been updated yesterday, the same tests are failing there. So I'm pretty certain it's a regression elsewhere. |
|
@ranj063 @plbossart please, have a look |
|
@lyakh can you please resolve the conflicts? |
|
Need another approval. @RanderWang @kv2019i ? |
sound/soc/sof/intel/hda-dsp.c
Outdated
| snd_hdac_chip_writew(bus, WAKEEN, | ||
| snd_hdac_chip_readw(bus, WAKEEN) | | ||
| hda->hda_codec_mask); | ||
| snd_hdac_chip_updatew(bus, WAKEEN, 0, hda->hda_codec_mask); |
There was a problem hiding this comment.
Hmm, the macros in hdaudio.h are a bit odd in that the mask is not applied to the value, so this still works, but it looks odd. Can you fix this to
snd_hdac_chip_updatew(bus, WAKEEN, hda->hda_codec_mask, hda->hda_codec_mask);
... just in case someone refactors the hdaudio.h macros (to behave like e.g. snd_sof_dsp_update_bits() family works).
There was a problem hiding this comment.
@kv2019i I'm not sure snd_sof_dsp_update_bits() is a common way to handle bitmasks, cf. set_mask_bits()
There was a problem hiding this comment.
@lyakh True, but in ALSA we seem to be using the sof_dsp_update_bits style (see e.g. use of snd_hdac_chip_updateb in hda_controller.c). Also regmap_update_bits applies the mask to value.
Use snd_hdac_chip_updatew() to update WAKEEN instead of open-coding. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1. The additional HDA codec mask isn't needed, just check the codec jack table. 2. Remove the "status" parameter. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
resume, it should only be checked when the status indicates a
change.
table.