ALSA: hda: Balance runtime/system PM if direct-complete is disabled
After hibernation, HDA controller can't be runtime-suspended after commit215a22ed31
("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: Kenneth R. Crudup <kenny@panix.com> Fixes:215a22ed31
("ALSA: hda: Refactor codec PM to use direct-complete optimization") Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Link: https://lore.kernel.org/r/20210119152145.346558-1-kai.heng.feng@canonical.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Родитель
c23010ffb2
Коммит
2b73649cee
|
@ -2934,7 +2934,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
|
|||
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);
|
||||
unsigned int state;
|
||||
|
@ -2953,7 +2953,7 @@ static int hda_codec_suspend(struct device *dev)
|
|||
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);
|
||||
|
||||
|
@ -2968,16 +2968,6 @@ static int hda_codec_resume(struct device *dev)
|
|||
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 */
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
@ -2998,31 +2988,31 @@ static void hda_codec_pm_complete(struct device *dev)
|
|||
static int hda_codec_pm_suspend(struct device *dev)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
dev->power.power_state = PMSG_RESTORE;
|
||||
return hda_codec_resume(dev);
|
||||
return pm_runtime_force_resume(dev);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче