@@ -795,6 +795,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
hsw_disable_pc8(dev_priv);
+ else if (IS_SKYLAKE(dev_priv))
+ ret = skl_resume_prepare(dev_priv);
intel_uncore_sanitize(dev);
intel_power_domains_init_hw(dev_priv);
@@ -1009,6 +1011,19 @@ static int i915_pm_resume(struct device *dev)
return i915_drm_resume(drm_dev);
}
+static int skl_suspend_complete(struct drm_i915_private *dev_priv)
+{
+ /* Enabling DC6 is not a hard requirement to enter runtime D3 */
+
+ /*
+ * This is to ensure that CSR isn't identified as loaded before
+ * CSR-loading program is called during runtime-resume.
+ */
+ intel_csr_load_status_set(dev_priv, false);
+
+ return 0;
+}
+
static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
{
hsw_enable_pc8(dev_priv);
@@ -1016,6 +1031,16 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
return 0;
}
+int skl_resume_prepare(struct drm_i915_private *dev_priv)
+{
+ struct drm_device *dev = dev_priv->dev;
+
+ if (!intel_csr_load_status_get(dev_priv))
+ intel_csr_load_program(dev);
+
+ return 0;
+}
+
/*
* Save all Gunit registers that may be lost after a D3 and a subsequent
* S0i[R123] transition. The list of registers needing a save/restore is
@@ -1484,6 +1509,8 @@ static int intel_runtime_resume(struct device *device)
if (IS_GEN6(dev_priv))
intel_init_pch_refclk(dev);
+ else if (IS_SKYLAKE(dev))
+ ret = skl_resume_prepare(dev_priv);
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
hsw_disable_pc8(dev_priv);
else if (IS_VALLEYVIEW(dev_priv))
@@ -1516,6 +1543,8 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
struct drm_device *dev = dev_priv->dev;
int ret;
+ if (IS_SKYLAKE(dev))
+ ret = skl_suspend_complete(dev_priv);
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
ret = hsw_suspend_complete(dev_priv);
else if (IS_VALLEYVIEW(dev))
@@ -2642,6 +2642,7 @@ extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
void i915_firmware_load_error_print(const char *fw_path, int err);
+int skl_resume_prepare(struct drm_i915_private *dev_priv);
/* i915_irq.c */
void i915_queue_hangcheck(struct drm_device *dev);
@@ -49,7 +49,8 @@
* present for a given platform.
*/
-#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
+#define GEN9_ENABLE_DC5(dev) 0
+#define SKL_ENABLE_DC6(dev) IS_SKYLAKE(dev)
#define for_each_power_well(i, power_well, domain_mask, power_domains) \
for (i = 0; \
@@ -373,7 +374,7 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
WARN(!pg2_enabled, "PG2 not enabled to disable DC5.\n");
WARN(dev_priv->pm.suspended,
- "Disabling of DC5 while platform is runtime-suspended should never happen.\n");
+ "Platform is runtime-suspended, should not disable DC5.\n");
}
static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
@@ -438,8 +439,6 @@ static void skl_disable_dc6(struct drm_i915_private *dev_priv)
val &= ~DC_STATE_EN_UPTO_DC6;
I915_WRITE(DC_STATE_EN, val);
POSTING_READ(DC_STATE_EN);
-
- intel_prepare_ddi(dev);
}
static void skl_set_power_well(struct drm_i915_private *dev_priv,
@@ -483,55 +482,60 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
state_mask = SKL_POWER_WELL_STATE(power_well->data);
is_enabled = tmp & state_mask;
- if (enable) {
- if (!enable_requested) {
- WARN((tmp & state_mask) &&
- !I915_READ(HSW_PWR_WELL_BIOS), "Invalid for \
- power well status to be enabled, unless done \
- by the BIOS, when request is to disable!\n");
- if (GEN9_ENABLE_DC5(dev) &&
- power_well->data == SKL_DISP_PW_2)
- gen9_disable_dc5(dev_priv);
- I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
+ if (enable && (!enable_requested)) {
+ WARN(is_enabled && !I915_READ(HSW_PWR_WELL_BIOS),
+ "Invalid for power well status to be enabled, unless done by \
+ the BIOS, when request is to disable!\n");
+ if (SKL_ENABLE_DC6(dev) && power_well->data == SKL_DISP_PW_2) {
+ skl_disable_dc6(dev_priv);
+ /*
+ * DDI buffer programming unnecessary during driver
+ * load/resumeas it's already done during modeset
+ * initialization then. It's also invalid here as
+ * encoder list is still uninitialized.
+ */
+ if (!dev_priv->power_domains.initializing)
+ intel_prepare_ddi(dev);
}
-
- if (!is_enabled) {
- DRM_DEBUG_KMS("Enabling %s\n", power_well->name);
- if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
- state_mask), 1))
- DRM_ERROR("%s enable timeout\n",
- power_well->name);
+ if (GEN9_ENABLE_DC5(dev) && power_well->data == SKL_DISP_PW_2)
+ gen9_disable_dc5(dev_priv);
+ I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
+ }
+ if (enable && (!is_enabled)) {
+ DRM_DEBUG_KMS("Enabling %s\n", power_well->name);
+ if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) & state_mask), 1))
+ DRM_ERROR("%s enable timeout\n", power_well->name);
check_fuse_status = true;
- }
- } else {
- if (enable_requested) {
- I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask);
- POSTING_READ(HSW_PWR_WELL_DRIVER);
- DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
-
- if (GEN9_ENABLE_DC5(dev) &&
- power_well->data == SKL_DISP_PW_2) {
- if (!dev_priv->csr.failed) {
- /*
- * TODO: wait for a completion event or
- * similar here instead of busy
- * waiting using wait_for function.
- */
- if (wait_for(
- intel_csr_load_status_get(
- dev_priv), 1000))
- DRM_ERROR("Timed out waiting \
- for CSR to be loaded!");
- else
- gen9_enable_dc5(dev_priv);
- } else {
- DRM_ERROR("Cannot enable DC5 as CSR \
- failed to load!");
- }
+ }
+ if ((!enable) && enable_requested) {
+ I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask);
+ POSTING_READ(HSW_PWR_WELL_DRIVER);
+ DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
+
+ if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
+ power_well->data == SKL_DISP_PW_2) {
+ if (dev_priv->csr.failed) {
+ DRM_ERROR("CSR loading failed, not entering %s",
+ SKL_ENABLE_DC6(dev) ? "DC6" : "DC5");
+ goto exit;
+ }
+ /*
+ * TODO: wait for a completion event or similar here
+ * instead of busy waiting using wait_for function.
+ */
+ if (wait_for(intel_csr_load_status_get(dev_priv),
+ 1000)) {
+ DRM_ERROR("Timed out for CSR loading!");
+ goto exit;
}
+ if (SKL_ENABLE_DC6(dev))
+ skl_enable_dc6(dev_priv);
+ else
+ gen9_enable_dc5(dev_priv);
}
}
+exit:
if (check_fuse_status) {
if (power_well->data == SKL_DISP_PW_1) {
if (wait_for((I915_READ(SKL_FUSE_STATUS) &