#define for_each_fw_domain(domain__, dev_priv__, i__) \
for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
+enum csr_state {
+ FW_UNINITIALIZED = 0,
+ FW_LOADED,
+ FW_FAILED
+};
+
struct intel_csr {
const char *fw_path;
__be32 *dmc_payload;
uint32_t mmio_count;
uint32_t mmioaddr[8];
uint32_t mmiodata[8];
+ enum csr_state state;
};
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
return -ENODATA;
}
+enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
+{
+ enum csr_state state;
+
+ mutex_lock(&dev_priv->csr_lock);
+ state = dev_priv->csr.state;
+ mutex_unlock(&dev_priv->csr_lock);
+
+ return state;
+}
+
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
+ enum csr_state state)
+{
+ mutex_lock(&dev_priv->csr_lock);
+ dev_priv->csr.state = state;
+ mutex_unlock(&dev_priv->csr_lock);
+}
+
void intel_csr_load_program(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
I915_WRITE(dev_priv->csr.mmioaddr[i],
dev_priv->csr.mmiodata[i]);
}
+
+ dev_priv->csr.state = FW_LOADED;
mutex_unlock(&dev_priv->csr_lock);
}
uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
uint32_t i;
__be32 *dmc_payload;
+ bool fw_loaded = false;
if (!fw) {
i915_firmware_load_error_print(csr->fw_path, 0);
/* load csr program during system boot, as needed for DC states */
intel_csr_load_program(dev);
+ fw_loaded = true;
+
out:
+ if (fw_loaded)
+ intel_runtime_pm_put(dev_priv);
+ else
+ intel_csr_load_status_set(dev_priv, FW_FAILED);
+
release_firmware(fw);
}
csr->fw_path = I915_CSR_SKL;
else {
DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
+ intel_csr_load_status_set(dev_priv, FW_FAILED);
return;
}
+ /*
+ * Obtain a runtime pm reference, until CSR is loaded,
+ * to avoid entering runtime-suspend.
+ */
+ intel_runtime_pm_get(dev_priv);
+
/* CSR supported for platform, load firmware */
ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
&dev_priv->dev->pdev->dev,
GFP_KERNEL, dev_priv,
finish_csr_load);
- if (ret)
+ if (ret) {
i915_firmware_load_error_print(csr->fw_path, ret);
-
+ intel_csr_load_status_set(dev_priv, FW_FAILED);
+ }
}
void intel_csr_ucode_fini(struct drm_device *dev)
if (!HAS_CSR(dev))
return;
+ intel_csr_load_status_set(dev_priv, FW_FAILED);
kfree(dev_priv->csr.dmc_payload);
}
/* intel_csr.c */
void intel_csr_ucode_init(struct drm_device *dev);
+enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv);
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
+ enum csr_state state);
void intel_csr_load_program(struct drm_device *dev);
void intel_csr_ucode_fini(struct drm_device *dev);
* 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 && \
POSTING_READ(DC_STATE_EN);
}
+static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+{
+ /* TODO: Implementation to be done. */
+}
+
+static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
+{
+ /* TODO: Implementation to be done. */
+}
+
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;
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);
}
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) {
+ enum csr_state state;
+
+ wait_for((state = intel_csr_load_status_get(dev_priv)) !=
+ FW_UNINITIALIZED, 1000);
+ if (state != FW_LOADED)
+ DRM_ERROR("CSR firmware not ready (%d)\n",
+ state);
+ else
+ gen9_enable_dc5(dev_priv);
+ }
}
}