Intel DGFX cards provides a feature Video Ram Self Refrsh(vram_sr). vram_sr can be enabled with runtime suspend D3Cold flow and with opportunistic S0ix system wide suspend flow as well. vram_sr feature requires Host BIOS support, vram_sr will be enable/disable by HOST BIOS using ACPI OpRegion. OpRegion vram_sr is only applicable on Motherboard Down cards. Adding OpRegion vram_sr support in order to enable/disable vram_sr on discrete cards. v2: - Added opregion->header NULL check. [Jani] - Bundled opregion->asle NULL check to early return. [Jani] - Use static inline for dummy declaration. [Jani] BSpec: 53440 Cc: Jani Nikula <jani.nikula@xxxxxxxxx> Cc: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> Signed-off-by: Anshuman Gupta <anshuman.gupta@xxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_opregion.c | 78 ++++++++++++++++++- drivers/gpu/drm/i915/display/intel_opregion.h | 17 ++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index 1c0c745c142d..f4a2a02c9ed3 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -55,6 +55,8 @@ #define MBOX_ASLE_EXT BIT(4) /* Mailbox #5 */ #define MBOX_BACKLIGHT BIT(5) /* Mailbox #2 (valid from v3.x) */ +#define PCON_DGFX_BIOS_SUPPORTS_VRSR BIT(11) +#define PCON_DGFX_BIOS_SUPPORTS_VRSR_FIELD_VALID BIT(12) #define PCON_HEADLESS_SKU BIT(13) struct opregion_header { @@ -132,7 +134,8 @@ struct opregion_asle { u64 rvda; /* Physical (2.0) or relative from opregion (2.1+) * address of raw VBT data. */ u32 rvds; /* Size of raw vbt data */ - u8 rsvd[58]; + u8 vrsr; /* DGFX Video Ram Self Refresh */ + u8 rsvd[57]; } __packed; /* OpRegion mailbox #5: ASLE ext */ @@ -203,6 +206,9 @@ struct opregion_asle_ext { #define ASLE_PHED_EDID_VALID_MASK 0x3 +/* VRAM SR */ +#define ASLE_VRSR_ENABLE BIT(0) + /* Software System Control Interrupt (SWSCI) */ #define SWSCI_SCIC_INDICATOR (1 << 0) #define SWSCI_SCIC_MAIN_FUNCTION_SHIFT 1 @@ -923,6 +929,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) opregion->header->over.minor, opregion->header->over.revision); + drm_dbg(&dev_priv->drm, "OpRegion PCON values 0x%x\n", opregion->header->pcon); + mboxes = opregion->header->mboxes; if (mboxes & MBOX_ACPI) { drm_dbg(&dev_priv->drm, "Public ACPI methods supported\n"); @@ -1248,3 +1256,71 @@ void intel_opregion_unregister(struct drm_i915_private *i915) opregion->vbt = NULL; opregion->lid_state = NULL; } + +/** + * intel_opregion_vram_sr_required(). + * @i915 i915 device priv data. + * + * It checks whether a DGFX card is Mother Board Down config depending + * on respective discrete platform. + * + * Returns: + * It returns a boolean whether opregion vram_sr support is required. + */ +bool +intel_opregion_vram_sr_required(struct drm_i915_private *i915) +{ + return false; +} + +/** + * intel_opregion_bios_supports_vram_sr() - get HOST BIOS vram_sr + * capability support. + * @i915: pointer to i915 device. + * + * It checks opregion pcon vram_sr fields to get HOST BIOS vram_sr + * capability support. It is only applocable to DGFX. + * + * Returns: + * true when bios supports vram_sr, or false if bios doesn't support. + */ +bool intel_opregion_bios_supports_vram_sr(struct drm_i915_private *i915) +{ + struct intel_opregion *opregion = &i915->opregion; + + if (!IS_DGFX(i915)) + return false; + + if (!opregion->header) + return false; + + if (opregion->header->pcon & PCON_DGFX_BIOS_SUPPORTS_VRSR_FIELD_VALID) + return opregion->header->pcon & PCON_DGFX_BIOS_SUPPORTS_VRSR; + else + return false; +} + +/** + * intel_opregion_vram_sr() - enable/disable vram_sr. + * @i915: pointer to i915 device. + * @enable: Argument to enable/disable vram_sr. + * + * It enables/disables vram_sr in opregion ASLE MBOX, based upon that + * HOST BIOS will enables and disbales VRAM_SR during + * ACPI _PS3/_OFF and _PS/_ON glue method. + */ +void intel_opregion_vram_sr(struct drm_i915_private *i915, bool enable) +{ + struct intel_opregion *opregion = &i915->opregion; + + if (!opregion->header || !opregion->asle) + return; + + if (!intel_opregion_vram_sr_required(i915)) + return; + + if (enable) + opregion->asle->vrsr |= ASLE_VRSR_ENABLE; + else + opregion->asle->vrsr &= ~ASLE_VRSR_ENABLE; +} diff --git a/drivers/gpu/drm/i915/display/intel_opregion.h b/drivers/gpu/drm/i915/display/intel_opregion.h index 2f261f985400..55a61e8a28dc 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.h +++ b/drivers/gpu/drm/i915/display/intel_opregion.h @@ -75,6 +75,9 @@ int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv, pci_power_t state); int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv); struct edid *intel_opregion_get_edid(struct intel_connector *connector); +bool intel_opregion_vram_sr_required(struct drm_i915_private *i915); +bool intel_opregion_bios_supports_vram_sr(struct drm_i915_private *i915); +void intel_opregion_vram_sr(struct drm_i915_private *i915, bool enable); bool intel_opregion_headless_sku(struct drm_i915_private *i915); @@ -134,6 +137,20 @@ static inline bool intel_opregion_headless_sku(struct drm_i915_private *i915) return false; } +static inline bool intel_opregion_vram_sr_required(struct drm_i915_private *i915) +{ + return false; +} + +static inline bool intel_opregion_bios_supports_vram_sr(struct drm_i915_private *i915) +{ + return false; +} + +static inline void intel_opregion_vram_sr(struct drm_i915_private *i915, bool enable) +{ +} + #endif /* CONFIG_ACPI */ #endif -- 2.26.2