From ecbc5cf34068d22cf57bac596809a346576c38a3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 30 Aug 2013 19:40:31 +0300 Subject: [PATCH] drm/i915: add opregion function to notify bios of adapter power state Notifying the bios lets it enter power saving states. Signed-off-by: Jani Nikula Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 7 +++++++ drivers/gpu/drm/i915/intel_opregion.c | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3b7368d6d72..769c1388a69 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2197,6 +2197,8 @@ extern void intel_opregion_fini(struct drm_device *dev); extern void intel_opregion_asle_intr(struct drm_device *dev); extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, bool enable); +extern int intel_opregion_notify_adapter(struct drm_device *dev, + pci_power_t state); #else static inline void intel_opregion_init(struct drm_device *dev) { return; } static inline void intel_opregion_fini(struct drm_device *dev) { return; } @@ -2206,6 +2208,11 @@ intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, bool enable) { return 0; } +static inline int +intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) +{ + return 0; +} #endif /* intel_acpi.c */ diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index ce1c79eedcb..2ff74912b65 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -342,6 +342,33 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, return swsci(dev, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL); } +static const struct { + pci_power_t pci_power_state; + u32 parm; +} power_state_map[] = { + { PCI_D0, 0x00 }, + { PCI_D1, 0x01 }, + { PCI_D2, 0x02 }, + { PCI_D3hot, 0x04 }, + { PCI_D3cold, 0x04 }, +}; + +int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) +{ + int i; + + if (!HAS_DDI(dev)) + return 0; + + for (i = 0; i < ARRAY_SIZE(power_state_map); i++) { + if (state == power_state_map[i].pci_power_state) + return swsci(dev, SWSCI_SBCB_ADAPTER_POWER_STATE, + power_state_map[i].parm, NULL); + } + + return -EINVAL; +} + static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_i915_private *dev_priv = dev->dev_private; -- 2.43.2