forked from Minki/linux
drm/i915/skl: Add DC5 Trigger Sequence
Add triggers as per expectations mentioned in gen9_enable_dc5 and gen9_disable_dc5 patch. Also call POSTING_READ for every write to a register to ensure that its written immediately. v1: Remove POSTING_READ calls as they've already been added in previous patches. v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file. Modified as per review comments from Imre: 1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant functions. 2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into gen9_disable_DC5 which is a more appropriate place. 3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well() to warnings. However, removing them for now as they'll be included in a future patch asserting DC-state entry/exit criteria. 4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure to track 'enabled' and 'deferred' status of DC5. 5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering runtime-suspend and release it when it's loaded. 6] Protect necessary CSR-related code with locks. 7] Move CSR-loading call to runtime PM initialization, as power domains needed to be accessed during deferred DC5-enabling, are not initialized earlier. v3: Rebase to latest. Modified as per review comments from Imre: 1] Use blocking wait for CSR-loading to finish to enable DC5 for simplicity, instead of deferring enabling DC5 until CSR is loaded. 2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5- enabling is removed and release it at the end of CSR-loading functionality. 3] Revert calling CSR-loading functionality to the beginning of i915 driver-load functionality to avoid any delay in loading. 4] Define another variable to track whether CSR-loading failed and use it to avoid enabling DC5 if it's true. 5] Define CSR-load-status accessor functions for use later. v4: 1] Disable DC5 before enabling PG2 instead of after it. 2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that. 3] Enable DC5-related functionality using a macro. 4] Remove dc5_enabled tracking variable and its use as it's not needed now. v5: 1] Mark CSR failed to load where necessary in finish_csr_load function. 2] Use mutex-protected accessor function to check if CSR loaded instead of directly accessing the variable. 3] Prefix csr_load_status_get/set function names with intel_. v6: rebase to latest. v7: Rebase on top of nightly (Damien) v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre) v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v10: Added a enum for different csr states, suggested by Imre. (Animesh) v11: Based on review comments from Imre, Damien and Daniel following changes done - enum name chnaged to csr_state (singular form). - FW_UNINITIALIZED used as zeroth element in enum csr_state. - Prototype changed for helper function(set/get csr status), using enum csr_state instead of bool. v12: Based on review comment from Imre, introduced bool fw_loaded local to finish_csr_load() which helps calling once to set the csr status. The same flag used to fail RPM if find any issue during firmware loading. Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Animesh Manna <animesh.manna@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
eb805623d8
commit
dc17430054
@ -669,6 +669,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_state {
|
||||
FW_UNINITIALIZED = 0,
|
||||
FW_LOADED,
|
||||
FW_FAILED
|
||||
};
|
||||
|
||||
struct intel_csr {
|
||||
const char *fw_path;
|
||||
__be32 *dmc_payload;
|
||||
@ -676,6 +682,7 @@ struct intel_csr {
|
||||
uint32_t mmio_count;
|
||||
uint32_t mmioaddr[8];
|
||||
uint32_t mmiodata[8];
|
||||
enum csr_state state;
|
||||
};
|
||||
|
||||
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
|
||||
|
@ -183,6 +183,25 @@ static char intel_get_substepping(struct drm_device *dev)
|
||||
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;
|
||||
@ -204,6 +223,8 @@ void intel_csr_load_program(struct drm_device *dev)
|
||||
I915_WRITE(dev_priv->csr.mmioaddr[i],
|
||||
dev_priv->csr.mmiodata[i]);
|
||||
}
|
||||
|
||||
dev_priv->csr.state = FW_LOADED;
|
||||
mutex_unlock(&dev_priv->csr_lock);
|
||||
}
|
||||
|
||||
@ -220,6 +241,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
|
||||
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);
|
||||
@ -326,7 +348,14 @@ static void finish_csr_load(const struct firmware *fw, void *context)
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@ -343,17 +372,25 @@ void intel_csr_ucode_init(struct drm_device *dev)
|
||||
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)
|
||||
@ -363,5 +400,6 @@ 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);
|
||||
}
|
||||
|
@ -1155,6 +1155,9 @@ u32 skl_plane_ctl_rotation(unsigned int rotation);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -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 && \
|
||||
@ -417,9 +419,20 @@ void bxt_disable_dc9(struct drm_i915_private *dev_priv)
|
||||
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;
|
||||
@ -459,6 +472,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);
|
||||
}
|
||||
|
||||
@ -475,6 +495,19 @@ 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user