Commit 2b73649c authored by Kai-Heng Feng's avatar Kai-Heng Feng Committed by Takashi Iwai

ALSA: hda: Balance runtime/system PM if direct-complete is disabled

After hibernation, HDA controller can't be runtime-suspended after
commit 215a22ed ("ALSA: hda: Refactor codjc PM to use
direct-complete optimization"), which enables direct-complete for HDA
codec.

The HDA codec driver didn't expect direct-complete will be disabled
after it returns a positive value from prepare() callback. However,
there are some places that PM core can disable direct-complete. For
instance, system hibernation or when codec has subordinates like LEDs.

So if the codec is prepared for direct-complete but PM core still calls
codec's suspend or freeze callback, partially revert the commit and take
the original approach, which uses pm_runtime_force_*() helpers to
ensure PM refcount are balanced. Meanwhile, still keep prepare() and
complete() callbacks to enable direct-complete and request a resume for
jack detection, respectively.
Reported-by: default avatarKenneth R. Crudup <kenny@panix.com>
Fixes: 215a22ed ("ALSA: hda: Refactor codec PM to use direct-complete optimization")
Signed-off-by: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Link: https://lore.kernel.org/r/20210119152145.346558-1-kai.heng.feng@canonical.comSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent c23010ff
...@@ -2934,7 +2934,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) ...@@ -2934,7 +2934,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
snd_hdac_leave_pm(&codec->core); snd_hdac_leave_pm(&codec->core);
} }
static int hda_codec_suspend(struct device *dev) static int hda_codec_runtime_suspend(struct device *dev)
{ {
struct hda_codec *codec = dev_to_hda_codec(dev); struct hda_codec *codec = dev_to_hda_codec(dev);
unsigned int state; unsigned int state;
...@@ -2953,7 +2953,7 @@ static int hda_codec_suspend(struct device *dev) ...@@ -2953,7 +2953,7 @@ static int hda_codec_suspend(struct device *dev)
return 0; return 0;
} }
static int hda_codec_resume(struct device *dev) static int hda_codec_runtime_resume(struct device *dev)
{ {
struct hda_codec *codec = dev_to_hda_codec(dev); struct hda_codec *codec = dev_to_hda_codec(dev);
...@@ -2968,16 +2968,6 @@ static int hda_codec_resume(struct device *dev) ...@@ -2968,16 +2968,6 @@ static int hda_codec_resume(struct device *dev)
return 0; return 0;
} }
static int hda_codec_runtime_suspend(struct device *dev)
{
return hda_codec_suspend(dev);
}
static int hda_codec_runtime_resume(struct device *dev)
{
return hda_codec_resume(dev);
}
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
...@@ -2998,31 +2988,31 @@ static void hda_codec_pm_complete(struct device *dev) ...@@ -2998,31 +2988,31 @@ static void hda_codec_pm_complete(struct device *dev)
static int hda_codec_pm_suspend(struct device *dev) static int hda_codec_pm_suspend(struct device *dev)
{ {
dev->power.power_state = PMSG_SUSPEND; dev->power.power_state = PMSG_SUSPEND;
return hda_codec_suspend(dev); return pm_runtime_force_suspend(dev);
} }
static int hda_codec_pm_resume(struct device *dev) static int hda_codec_pm_resume(struct device *dev)
{ {
dev->power.power_state = PMSG_RESUME; dev->power.power_state = PMSG_RESUME;
return hda_codec_resume(dev); return pm_runtime_force_resume(dev);
} }
static int hda_codec_pm_freeze(struct device *dev) static int hda_codec_pm_freeze(struct device *dev)
{ {
dev->power.power_state = PMSG_FREEZE; dev->power.power_state = PMSG_FREEZE;
return hda_codec_suspend(dev); return pm_runtime_force_suspend(dev);
} }
static int hda_codec_pm_thaw(struct device *dev) static int hda_codec_pm_thaw(struct device *dev)
{ {
dev->power.power_state = PMSG_THAW; dev->power.power_state = PMSG_THAW;
return hda_codec_resume(dev); return pm_runtime_force_resume(dev);
} }
static int hda_codec_pm_restore(struct device *dev) static int hda_codec_pm_restore(struct device *dev)
{ {
dev->power.power_state = PMSG_RESTORE; dev->power.power_state = PMSG_RESTORE;
return hda_codec_resume(dev); return pm_runtime_force_resume(dev);
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment