[PATCH] ALSA: hda: Always use jackpoll helper for jack update after resume

Takashi Iwai tiwai at suse.de
Wed Apr 22 22:46:57 CEST 2020


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.

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