diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 735df5595b34..1b449f96d2c1 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -640,8 +640,7 @@ static int i915_drm_suspend(struct drm_device *dev) intel_display_set_init_power(dev_priv, false); - if (HAS_CSR(dev_priv)) - flush_work(&dev_priv->csr.work); + intel_csr_ucode_suspend(dev_priv); out: enable_rpm_wakeref_asserts(dev_priv); @@ -733,6 +732,8 @@ static int i915_drm_resume(struct drm_device *dev) disable_rpm_wakeref_asserts(dev_priv); + intel_csr_ucode_resume(dev_priv); + mutex_lock(&dev->struct_mutex); i915_gem_restore_gtt_mappings(dev); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index d57b00ed5e5e..a34c23eceba0 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -466,11 +466,51 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) schedule_work(&dev_priv->csr.work); } +/** + * 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) @@ -478,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); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 10dfe7251b85..beed9e81252b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1275,6 +1275,8 @@ u32 skl_plane_ctl_rotation(unsigned int rotation); void intel_csr_ucode_init(struct drm_i915_private *); void intel_csr_load_program(struct drm_i915_private *); void intel_csr_ucode_fini(struct drm_i915_private *); +void intel_csr_ucode_suspend(struct drm_i915_private *); +void intel_csr_ucode_resume(struct drm_i915_private *); /* intel_dp.c */ void intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 1242fb5d3301..0ed3ec862733 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -809,6 +809,9 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { + if (!dev_priv->csr.dmc_payload) + return; + if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6) skl_enable_dc6(dev_priv); else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5)