drm/i915: add intel_display_driver_pm_runtime*() functions

Add new functions intel_display_driver_pm_runtime_suspend(),
intel_display_driver_pm_runtime_suspend_late(),
intel_display_driver_pm_runtime_resume_early(), and
intel_display_driver_pm_runtime_resume(). The IRQ suspend/resume is
meant to happen between the corresponding calls. For now,
intel_display_driver_pm_runtime_suspend() is empty, but is included for
completeness as a placeholder.

Initially, only migrate i915, as there are some differences with xe that
will be addressed later.

There's a functional change, which should be benign:
i915_pm_runtime_resume() moves intel_opregion_notify_adapter() call
slightly later.

In the interest of not introducing more severe functional changes, the
calls become slightly asymmetric. We might want to address this later.

v2:
- Rebase, move placement of suspend calls

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patch.msgid.link/81e29bd9bee6c023d079ab076af7dc4b7e8985ca.1782913901.git.jani.nikula@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
This commit is contained in:
Jani Nikula 2026-07-01 16:53:02 +03:00
parent 8d880fe6f6
commit 93094e9099
3 changed files with 74 additions and 44 deletions

View File

@ -887,3 +887,64 @@ void intel_display_driver_pm_resume(struct intel_display *display)
intel_display_power_enable(display);
}
/* before irq suspend */
void intel_display_driver_pm_runtime_suspend(struct intel_display *display)
{
}
/* after irq suspend */
void intel_display_driver_pm_runtime_suspend_late(struct intel_display *display)
{
intel_display_power_runtime_suspend(display);
/*
* FIXME: We really should find a document that references the arguments
* used below!
*/
if (display->platform.broadwell) {
/*
* On Broadwell, if we use PCI_D1 the PCH DDI ports will stop
* being detected, and the call we do at i915_pm_runtime_resume()
* won't be able to restore them. Since PCI_D3hot matches the
* actual specification and appears to be working, use it.
*/
intel_opregion_notify_adapter(display, PCI_D3hot);
} else {
/*
* current versions of firmware which depend on this opregion
* notification have repurposed the D1 definition to mean
* "runtime suspended" vs. what you would normally expect (D3)
* to distinguish it from notifications that might be sent via
* the suspend path.
*/
intel_opregion_notify_adapter(display, PCI_D1);
}
if (!display->platform.valleyview && !display->platform.cherryview)
intel_hpd_poll_enable(display);
}
/* before irq resume */
void intel_display_driver_pm_runtime_resume_early(struct intel_display *display)
{
intel_opregion_notify_adapter(display, PCI_D0);
intel_display_power_runtime_resume(display);
}
/* after irq resume */
void intel_display_driver_pm_runtime_resume(struct intel_display *display)
{
/*
* On VLV/CHV display interrupts are part of the display
* power well, so hpd is reinitialized from there. For
* everyone else do it here.
*/
if (!display->platform.valleyview && !display->platform.cherryview) {
intel_hpd_init(display);
intel_hpd_poll_disable(display);
}
skl_watermark_ipc_update(display);
}

View File

@ -43,5 +43,10 @@ void intel_display_driver_suspend_access(struct intel_display *display);
void intel_display_driver_resume_access(struct intel_display *display);
bool intel_display_driver_check_access(struct intel_display *display);
void intel_display_driver_pm_runtime_suspend(struct intel_display *display);
void intel_display_driver_pm_runtime_suspend_late(struct intel_display *display);
void intel_display_driver_pm_runtime_resume_early(struct intel_display *display);
void intel_display_driver_pm_runtime_resume(struct intel_display *display);
#endif /* __INTEL_DISPLAY_DRIVER_H__ */

View File

@ -1511,47 +1511,21 @@ static int i915_pm_runtime_suspend(struct device *kdev)
for_each_gt(gt, dev_priv, i)
intel_gt_runtime_suspend(gt);
intel_display_driver_pm_runtime_suspend(display);
intel_irq_suspend(dev_priv);
for_each_gt(gt, dev_priv, i)
intel_uncore_suspend(gt->uncore);
intel_display_power_runtime_suspend(display);
/*
* FIXME: We really should find a document that references the arguments
* used below!
*/
if (IS_BROADWELL(dev_priv)) {
/*
* On Broadwell, if we use PCI_D1 the PCH DDI ports will stop
* being detected, and the call we do at i915_pm_runtime_resume()
* won't be able to restore them. Since PCI_D3hot matches the
* actual specification and appears to be working, use it.
*/
intel_opregion_notify_adapter(display, PCI_D3hot);
} else {
/*
* current versions of firmware which depend on this opregion
* notification have repurposed the D1 definition to mean
* "runtime suspended" vs. what you would normally expect (D3)
* to distinguish it from notifications that might be sent via
* the suspend path.
*/
intel_opregion_notify_adapter(display, PCI_D1);
}
if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
intel_hpd_poll_enable(display);
intel_display_driver_pm_runtime_suspend_late(display);
ret = vlv_suspend_complete(dev_priv);
if (ret) {
drm_err(&dev_priv->drm,
"Runtime suspend failed, disabling it (%d)\n", ret);
intel_opregion_notify_adapter(display, PCI_D0);
intel_display_power_runtime_resume(display);
intel_display_driver_pm_runtime_resume_early(display);
for_each_gt(gt, dev_priv, i)
intel_uncore_runtime_resume(gt->uncore);
@ -1561,6 +1535,8 @@ static int i915_pm_runtime_suspend(struct device *kdev)
for_each_gt(gt, dev_priv, i)
intel_gt_runtime_resume(gt);
intel_display_driver_pm_runtime_resume(display);
enable_rpm_wakeref_asserts(rpm);
return ret;
@ -1606,8 +1582,6 @@ static int i915_pm_runtime_resume(struct device *kdev)
drm_WARN_ON_ONCE(&dev_priv->drm, atomic_read(&rpm->wakeref_count));
disable_rpm_wakeref_asserts(rpm);
intel_opregion_notify_adapter(display, PCI_D0);
root_pdev = pcie_find_root_port(pdev);
if (root_pdev)
pci_d3cold_enable(root_pdev);
@ -1616,7 +1590,7 @@ static int i915_pm_runtime_resume(struct device *kdev)
drm_dbg(&dev_priv->drm,
"Unclaimed access during suspend, bios?\n");
intel_display_power_runtime_resume(display);
intel_display_driver_pm_runtime_resume_early(display);
ret = vlv_resume_prepare(dev_priv, true);
@ -1634,17 +1608,7 @@ static int i915_pm_runtime_resume(struct device *kdev)
intel_pxp_runtime_resume(dev_priv->pxp);
/*
* On VLV/CHV display interrupts are part of the display
* power well, so hpd is reinitialized from there. For
* everyone else do it here.
*/
if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
intel_hpd_init(display);
intel_hpd_poll_disable(display);
}
skl_watermark_ipc_update(display);
intel_display_driver_pm_runtime_resume(display);
enable_rpm_wakeref_asserts(rpm);