[PATCH] ALSA: hda: Always use jackpoll helper for jack update after resume
Hui Wang
hui.wang at canonical.com
Thu Apr 23 07:23:52 CEST 2020
On 2020/4/23 上午4:46, Takashi Iwai wrote:
> On Wed, 22 Apr 2020 22:37:44 +0200,
> Takashi Iwai wrote:
>> HD-audio codec driver applies a tricky procedure to forcibly perform
>> the runtime resume by mimicking the usage count even if the device has
>> been runtime-suspended beforehand. This was needed to assure to
>> trigger the jack detection update after the system resume.
>>
>> And recently we also applied the similar logic to the HD-audio
>> controller side. However this seems leading to some inconsistency,
>> and eventually PCI controller gets screwed up.
>>
>> This patch is an attempt to fix and clean up those behavior: instead
>> of the tricky runtime resume procedure, the existing jackpoll work is
>> scheduled when such a forced codec resume is required. The jackpoll
>> work will power up the codec, and this alone should suffice for the
>> jack status update in usual cases. If the extra polling is requested
>> (by checking codec->jackpoll_interval), the manual update is invoked
>> after that, and the codec is powered down again.
>>
>> Also, we filter the spurious wake up of the codec from the controller
>> runtime resume by checking codec->relaxed_resume flag. If this flag
>> is set, basically we don't need to wake up explicitly, but it's
>> supposed to be done via the audio component notifier.
>>
>> Fixes: c4c8dd6ef807 ("ALSA: hda: Skip controller resume if not needed")
>> Signed-off-by: Takashi Iwai <tiwai at suse.de>
> Note that this patch discards the previous forced resume logic
> introduced in commit b5a236c175b0
> ALSA: hda - Enforces runtime_resume after S3 and S4 for each codec
>
> So, Hui, could you check whether it still works for such a device?
> Or at least tests with a few known working devices are helpful.
I tested the patch on the machine which has the detection issue of
"ALSA: hda - Enforces runtime_resume after S3 and S4 for each codec",
the new patch worked well. The headphone could be detected after s3/s4.
And I don't have other machines at the moment since I worked at home
recently, so only tested this patch on one machine, it worked well.
Regards,
Hui.
>
> Also, Kai, it'd be appreciated if you can test whether it causes
> regression on Intel HDMI audio. Currently I have no enough test
> machines due to lockdown, unfortunately.
>
>
> Thanks!
>
> Takashi
>
>
>> ---
>> sound/pci/hda/hda_codec.c | 28 +++++++++++++++++-----------
>> sound/pci/hda/hda_intel.c | 17 ++---------------
>> 2 files changed, 19 insertions(+), 26 deletions(-)
>>
>> diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
>> index 86a632bf4d50..7e3ae4534df9 100644
>> --- a/sound/pci/hda/hda_codec.c
>> +++ b/sound/pci/hda/hda_codec.c
>> @@ -641,8 +641,18 @@ static void hda_jackpoll_work(struct work_struct *work)
>> struct hda_codec *codec =
>> container_of(work, struct hda_codec, jackpoll_work.work);
>>
>> - snd_hda_jack_set_dirty_all(codec);
>> - snd_hda_jack_poll_all(codec);
>> + /* for non-polling trigger: we need nothing if already powered on */
>> + if (!codec->jackpoll_interval && snd_hdac_is_power_on(&codec->core))
>> + return;
>> +
>> + /* the power-up/down sequence triggers the runtime resume */
>> + snd_hda_power_up_pm(codec);
>> + /* update jacks manually if polling is required, too */
>> + if (codec->jackpoll_interval) {
>> + snd_hda_jack_set_dirty_all(codec);
>> + snd_hda_jack_poll_all(codec);
>> + }
>> + snd_hda_power_down_pm(codec);
>>
>> if (!codec->jackpoll_interval)
>> return;
>> @@ -2951,18 +2961,14 @@ static int hda_codec_runtime_resume(struct device *dev)
>> static int hda_codec_force_resume(struct device *dev)
>> {
>> struct hda_codec *codec = dev_to_hda_codec(dev);
>> - bool forced_resume = hda_codec_need_resume(codec);
>> int ret;
>>
>> - /* The get/put pair below enforces the runtime resume even if the
>> - * device hasn't been used at suspend time. This trick is needed to
>> - * update the jack state change during the sleep.
>> - */
>> - if (forced_resume)
>> - pm_runtime_get_noresume(dev);
>> ret = pm_runtime_force_resume(dev);
>> - if (forced_resume)
>> - pm_runtime_put(dev);
>> + /* schedule jackpoll work for jack detection update */
>> + if (codec->jackpoll_interval ||
>> + (pm_runtime_suspended(dev) && hda_codec_need_resume(codec)))
>> + schedule_delayed_work(&codec->jackpoll_work,
>> + codec->jackpoll_interval);
>> return ret;
>> }
>>
>> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
>> index 9f995576cff1..0310193ea1bd 100644
>> --- a/sound/pci/hda/hda_intel.c
>> +++ b/sound/pci/hda/hda_intel.c
>> @@ -1004,7 +1004,8 @@ static void __azx_runtime_resume(struct azx *chip, bool from_rt)
>>
>> if (status && from_rt) {
>> list_for_each_codec(codec, &chip->bus)
>> - if (status & (1 << codec->addr))
>> + if (!codec->relaxed_resume &&
>> + (status & (1 << codec->addr)))
>> schedule_delayed_work(&codec->jackpoll_work,
>> codec->jackpoll_interval);
>> }
>> @@ -1044,9 +1045,7 @@ static int azx_suspend(struct device *dev)
>> static int azx_resume(struct device *dev)
>> {
>> struct snd_card *card = dev_get_drvdata(dev);
>> - struct hda_codec *codec;
>> struct azx *chip;
>> - bool forced_resume = false;
>>
>> if (!azx_is_pm_ready(card))
>> return 0;
>> @@ -1058,19 +1057,7 @@ static int azx_resume(struct device *dev)
>> if (azx_acquire_irq(chip, 1) < 0)
>> return -EIO;
>>
>> - /* check for the forced resume */
>> - list_for_each_codec(codec, &chip->bus) {
>> - if (hda_codec_need_resume(codec)) {
>> - forced_resume = true;
>> - break;
>> - }
>> - }
>> -
>> - if (forced_resume)
>> - pm_runtime_get_noresume(dev);
>> pm_runtime_force_resume(dev);
>> - if (forced_resume)
>> - pm_runtime_put(dev);
>> snd_power_change_state(card, SNDRV_CTL_POWER_D0);
>>
>> trace_azx_resume(chip);
>> --
>> 2.16.4
>>
More information about the Alsa-devel
mailing list