Skip to content

ASoC: SOF: Intel: optimise jack detection#1031

Merged
ranj063 merged 2 commits intothesofproject:topic/sof-devfrom
lyakh:wakeen
Jul 8, 2019
Merged

ASoC: SOF: Intel: optimise jack detection#1031
ranj063 merged 2 commits intothesofproject:topic/sof-devfrom
lyakh:wakeen

Conversation

@lyakh
Copy link
Collaborator

@lyakh lyakh commented Jun 12, 2019

  1. No need to schedule jack-checking work upon every runtime PM
    resume, it should only be checked when the status indicates a
    change.
  2. The additional HDA codec mask isn't needed, just check the codec
    table.
  3. Use u32 for the type of the "status" bitfield.

@lyakh lyakh requested review from RanderWang and plbossart June 12, 2019 13:26
@lyakh lyakh requested a review from lgirdwood as a code owner June 12, 2019 13:26
Copy link
Member

@plbossart plbossart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but there is one condition that can be clarified for the rest of us.


list_for_each_codec(codec, hbus)
if (mask & BIT(codec->core.addr))
if (status & BIT(codec->core.addr) && codec->jacktbl.used) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bit confusing to have both types of AND in the same test, I don't even know what precedence rules apply?

Copy link

@RanderWang RanderWang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@RanderWang
Copy link

RanderWang commented Jun 13, 2019

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.

@ClarexZhou
Copy link

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:
Scenario 1: Plug out headset -> do system reboot->wait several seconds->open sound setting->plug in headset. ->Error reproduced. Jack detection not work.
Scenario 2: Plug out headset->play music->wait several seconds till runtime PM status suspended.->open sound setting->plug in headset->Error reproduced. Jack detection not work.

@lyakh
Copy link
Collaborator Author

lyakh commented Jun 13, 2019

@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?

@lyakh
Copy link
Collaborator Author

lyakh commented Jun 13, 2019

Interesting, just keeping WAKEEN always set doesn't seem to help.

@lyakh
Copy link
Collaborator Author

lyakh commented Jun 13, 2019

@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.

@RanderWang
Copy link

RanderWang commented Jun 13, 2019

@RanderWang. 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

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.

snd_hdac_chip_writew(bus, WAKEEN,
snd_hdac_chip_readw(bus, WAKEEN) |
hda->hda_codec_mask);
snd_hdac_chip_readw(bus, WAKEEN) | mask);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you changed hda->hda_codec_mask to ~STATESTS_INT_MASK in hda_codec_jack_check, why not here ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we only enable the bits, that we need, but it doesn't hurt disabling all possible bits.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@lyakh
Copy link
Collaborator Author

lyakh commented Jun 13, 2019

@RanderWang. 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

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. But controller and codec in legacy hda driver are always active in default.

Interesting, do we know what exactly changes the codec "mode" from "completely suspended" to "suspended but sending UNSOLs?"

@ranj063
Copy link
Collaborator

ranj063 commented Jun 13, 2019

@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?

@lyakh
Copy link
Collaborator Author

lyakh commented Jun 14, 2019

@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.

@ranj063
Copy link
Collaborator

ranj063 commented Jun 14, 2019

@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.


list_for_each_codec(codec, hbus)
if (codec->jacktbl.used)
mask |= BIT(codec->core.addr);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lyakh can you please add a comment here to explain that we want to wake-up all jack capable codecs irrespective of status

@RanderWang
Copy link

Interesting, do we know what exactly changes the codec "mode" from "completely suspended" to "suspended but sending UNSOLs?"

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.

ranj063
ranj063 previously approved these changes Jun 17, 2019
Copy link

@RanderWang RanderWang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor fix needed but this looks fine in general. Thanks

@@ -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)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just remove IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? jack detection doesn't really make sense for HDMI, does it?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?? what are you trying to say?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the translation. I'd like this PR to be completed soonish so that we can move on.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @lyakh for your explanation. Actually, this idea was suggested by @plbossart when I implemented hda_codec_jack_check.

RanderWang
RanderWang previously approved these changes Jun 20, 2019
Copy link

@RanderWang RanderWang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@plbossart plbossart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit-pick below, but this looks quite good.

plbossart
plbossart previously approved these changes Jun 21, 2019
Copy link
Member

@plbossart plbossart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, need a 2nd reviewer. @RanderWang @ranj063 please chime in

@lyakh
Copy link
Collaborator Author

lyakh commented Jul 2, 2019

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.

@xiulipan
Copy link

xiulipan commented Jul 2, 2019

@lyakh There is a regression #1599 and already fixed. I will re-trigger this PR for test.

@lyakh
Copy link
Collaborator Author

lyakh commented Jul 2, 2019

@ranj063 @plbossart please, have a look

ranj063
ranj063 previously approved these changes Jul 2, 2019
@ranj063
Copy link
Collaborator

ranj063 commented Jul 2, 2019

@lyakh can you please resolve the conflicts?

ranj063
ranj063 previously approved these changes Jul 3, 2019
@ranj063
Copy link
Collaborator

ranj063 commented Jul 3, 2019

Need another approval. @RanderWang @kv2019i ?

Copy link
Collaborator

@kv2019i kv2019i left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost good, @lyakh please check my one comment.

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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kv2019i I'm not sure snd_sof_dsp_update_bits() is a common way to handle bitmasks, cf. set_mask_bits()

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

ranj063
ranj063 previously approved these changes Jul 5, 2019
RanderWang
RanderWang previously approved these changes Jul 8, 2019
Copy link

@RanderWang RanderWang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

kv2019i
kv2019i previously approved these changes Jul 8, 2019
lyakh added 2 commits July 8, 2019 17:59
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>
@lyakh lyakh dismissed stale reviews from kv2019i, RanderWang, and ranj063 via 863fff8 July 8, 2019 16:06
@ranj063
Copy link
Collaborator

ranj063 commented Jul 8, 2019

@kv2019i @juimonen could either of your approve this PR again? Thanks!

@kv2019i
Copy link
Collaborator

kv2019i commented Jul 8, 2019

@kv2019i @juimonen could either of your approve this PR again? Thanks!

@ranj063 done

@ranj063 ranj063 merged commit 1da8b5f into thesofproject:topic/sof-dev Jul 8, 2019
@lyakh lyakh deleted the wakeen branch July 8, 2019 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants