@@ -667,6 +667,12 @@ struct intel_uncore {
#define for_each_fw_domain(domain__, dev_priv__, i__) \
for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
+enum csr_states {
+ FW_LOADED = 0,
+ FW_LOADING,
+ FW_FAILED
+};
+
struct intel_csr {
const char *fw_path;
__be32 *dmc_payload;
@@ -674,6 +680,7 @@ struct intel_csr {
uint32_t mmio_count;
uint32_t mmioaddr[8];
uint32_t mmiodata[8];
+ enum csr_states states;
};
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
@@ -1058,6 +1058,8 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
/* intel_csr.c */
void intel_csr_ucode_init(struct drm_device *dev);
+bool intel_csr_load_status_get(struct drm_i915_private *dev_priv);
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val);
void intel_csr_load_program(struct drm_device *dev);
void intel_csr_ucode_fini(struct drm_device *dev);
@@ -49,6 +49,8 @@
* present for a given platform.
*/
+#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
+
#define for_each_power_well(i, power_well, domain_mask, power_domains) \
for (i = 0; \
i < (power_domains)->power_well_count && \
@@ -369,6 +371,7 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
static void skl_set_power_well(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well, bool enable)
{
+ struct drm_device *dev = dev_priv->dev;
uint32_t tmp, fuse_status;
uint32_t req_mask, state_mask;
bool is_enabled, enable_requested, check_fuse_status = false;
@@ -408,6 +411,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
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);
}
@@ -424,6 +434,25 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
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.states <= FW_LOADING) {
+ /*
+ * 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!");
+ }
+ }
}
}