diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_csr.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_csr.c | 64 |
1 files changed, 57 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 3f57cb94d9ad..a34c23eceba0 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -50,6 +50,7 @@ MODULE_FIRMWARE(I915_CSR_SKL); MODULE_FIRMWARE(I915_CSR_BXT); #define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 23) +#define BXT_CSR_VERSION_REQUIRED CSR_VERSION(1, 7) #define CSR_MAX_FW_SIZE 0x2FFF #define CSR_DEFAULT_FW_OFFSET 0xFFFFFFFF @@ -281,6 +282,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes; uint32_t i; uint32_t *dmc_payload; + uint32_t required_min_version; if (!fw) return NULL; @@ -296,15 +298,23 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, csr->version = css_header->version; - if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && - csr->version < SKL_CSR_VERSION_REQUIRED) { - DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u," + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { + required_min_version = SKL_CSR_VERSION_REQUIRED; + } else if (IS_BROXTON(dev_priv)) { + required_min_version = BXT_CSR_VERSION_REQUIRED; + } else { + MISSING_CASE(INTEL_REVID(dev_priv)); + required_min_version = 0; + } + + if (csr->version < required_min_version) { + DRM_INFO("Refusing to load old DMC firmware v%u.%u," " please upgrade to v%u.%u or later" " [" FIRMWARE_URL "].\n", CSR_VERSION_MAJOR(csr->version), CSR_VERSION_MINOR(csr->version), - CSR_VERSION_MAJOR(SKL_CSR_VERSION_REQUIRED), - CSR_VERSION_MINOR(SKL_CSR_VERSION_REQUIRED)); + CSR_VERSION_MAJOR(required_min_version), + CSR_VERSION_MINOR(required_min_version)); return NULL; } @@ -457,10 +467,50 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) } /** + * intel_csr_ucode_suspend() - prepare CSR firmware before system suspend + * @dev_priv: i915 drm device + * + * Prepare the DMC firmware before entering system suspend. This includes + * flushing pending work items and releasing any resources acquired during + * init. + */ +void intel_csr_ucode_suspend(struct drm_i915_private *dev_priv) +{ + if (!HAS_CSR(dev_priv)) + return; + + flush_work(&dev_priv->csr.work); + + /* Drop the reference held in case DMC isn't loaded. */ + if (!dev_priv->csr.dmc_payload) + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); +} + +/** + * intel_csr_ucode_resume() - init CSR firmware during system resume + * @dev_priv: i915 drm device + * + * Reinitialize the DMC firmware during system resume, reacquiring any + * resources released in intel_csr_ucode_suspend(). + */ +void intel_csr_ucode_resume(struct drm_i915_private *dev_priv) +{ + if (!HAS_CSR(dev_priv)) + return; + + /* + * Reacquire the reference to keep RPM disabled in case DMC isn't + * loaded. + */ + if (!dev_priv->csr.dmc_payload) + intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); +} + +/** * intel_csr_ucode_fini() - unload the CSR firmware. * @dev_priv: i915 drm device. * - * Firmmware unloading includes freeing the internal momory and reset the + * Firmmware unloading includes freeing the internal memory and reset the * firmware loading status. */ void intel_csr_ucode_fini(struct drm_i915_private *dev_priv) @@ -468,7 +518,7 @@ void intel_csr_ucode_fini(struct drm_i915_private *dev_priv) if (!HAS_CSR(dev_priv)) return; - flush_work(&dev_priv->csr.work); + intel_csr_ucode_suspend(dev_priv); kfree(dev_priv->csr.dmc_payload); } |