ALSA: hda: Force resume if acomp notified during system suspend

Currently if an HDMI cable is connected while the system is suspended,
the HDMI audio jack status stays off after resume.

This is due to the jack state not being synced by the HDA HDMI codec
device's runtime resume, as that never happens if the device was runtime
suspended before the system suspended, or by the acomp notification
triggered from the DRM side if that happens before the HDA HDMI codec
device has resumed.

To fix this, if snd_hda_hdmi_acomp_pin_eld_notify() gets called before
the HDA HDMI codec device has resumed, mark it to be forcefully runtime
resumed at the next PM complete time.

Do this using a separate acomp_requested_resume flag that can be
temporarily set without overwriting forced_resume for drivers that
always want to force resume.

Assisted-by: Copilot:claude-sonnet-4.6
Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Link: https://patch.msgid.link/20260626-hda-force-resume-eld-notify-v1-1-a92cb01393e0@collabora.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Nícolas F. R. A. Prado
2026-06-29 12:38:48 +02:00
committed by Takashi Iwai
parent 39edd6d5f6
commit c0933934d5
3 changed files with 8 additions and 2 deletions
+1
View File
@@ -256,6 +256,7 @@ struct hda_codec {
unsigned int link_down_at_suspend:1; /* link down at runtime suspend */
unsigned int relaxed_resume:1; /* don't resume forcibly for jack */
unsigned int forced_resume:1; /* forced resume for jack */
unsigned int acomp_requested_resume:1; /* resume requested by acomp */
unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */
unsigned int ctl_dev_id:1; /* old control element id build behaviour */
unsigned int eld_jack_detect:1; /* Machine jack-detection by ELD */
+3 -1
View File
@@ -2233,8 +2233,10 @@ void snd_hda_hdmi_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id)
/* skip notification during system suspend (but not in runtime PM);
* the state will be updated at resume
*/
if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) {
codec->acomp_requested_resume = 1;
return;
}
snd_hda_hdmi_check_presence_and_report(codec, pin_nid, dev_id);
}
+4 -1
View File
@@ -2967,8 +2967,11 @@ static void hda_codec_pm_complete(struct device *dev)
dev->power.power_state = PMSG_RESUME;
if (pm_runtime_suspended(dev) && (codec->jackpoll_interval ||
hda_codec_need_resume(codec) || codec->forced_resume))
hda_codec_need_resume(codec) || codec->forced_resume ||
codec->acomp_requested_resume)) {
codec->acomp_requested_resume = 0;
pm_request_resume(dev);
}
}
static int hda_codec_pm_suspend(struct device *dev)