|
@@ -52,10 +52,6 @@
|
|
|
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
|
|
|
enum i915_power_well_id power_well_id);
|
|
|
|
|
|
-static struct i915_power_well *
|
|
|
-lookup_power_well(struct drm_i915_private *dev_priv,
|
|
|
- enum i915_power_well_id power_well_id);
|
|
|
-
|
|
|
const char *
|
|
|
intel_display_power_domain_str(enum intel_display_power_domain domain)
|
|
|
{
|
|
@@ -159,17 +155,17 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
|
|
|
static void intel_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- DRM_DEBUG_KMS("enabling %s\n", power_well->name);
|
|
|
- power_well->ops->enable(dev_priv, power_well);
|
|
|
+ DRM_DEBUG_KMS("enabling %s\n", power_well->desc->name);
|
|
|
+ power_well->desc->ops->enable(dev_priv, power_well);
|
|
|
power_well->hw_enabled = true;
|
|
|
}
|
|
|
|
|
|
static void intel_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- DRM_DEBUG_KMS("disabling %s\n", power_well->name);
|
|
|
+ DRM_DEBUG_KMS("disabling %s\n", power_well->desc->name);
|
|
|
power_well->hw_enabled = false;
|
|
|
- power_well->ops->disable(dev_priv, power_well);
|
|
|
+ power_well->desc->ops->disable(dev_priv, power_well);
|
|
|
}
|
|
|
|
|
|
static void intel_power_well_get(struct drm_i915_private *dev_priv,
|
|
@@ -183,7 +179,7 @@ static void intel_power_well_put(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
WARN(!power_well->count, "Use count on power well %s is already zero",
|
|
|
- power_well->name);
|
|
|
+ power_well->desc->name);
|
|
|
|
|
|
if (!--power_well->count)
|
|
|
intel_power_well_disable(dev_priv, power_well);
|
|
@@ -213,7 +209,7 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
|
|
|
is_enabled = true;
|
|
|
|
|
|
for_each_power_domain_well_rev(dev_priv, power_well, BIT_ULL(domain)) {
|
|
|
- if (power_well->always_on)
|
|
|
+ if (power_well->desc->always_on)
|
|
|
continue;
|
|
|
|
|
|
if (!power_well->hw_enabled) {
|
|
@@ -257,30 +253,6 @@ bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * intel_display_set_init_power - set the initial power domain state
|
|
|
- * @dev_priv: i915 device instance
|
|
|
- * @enable: whether to enable or disable the initial power domain state
|
|
|
- *
|
|
|
- * For simplicity our driver load/unload and system suspend/resume code assumes
|
|
|
- * that all power domains are always enabled. This functions controls the state
|
|
|
- * of this little hack. While the initial power domain state is enabled runtime
|
|
|
- * pm is effectively disabled.
|
|
|
- */
|
|
|
-void intel_display_set_init_power(struct drm_i915_private *dev_priv,
|
|
|
- bool enable)
|
|
|
-{
|
|
|
- if (dev_priv->power_domains.init_power_on == enable)
|
|
|
- return;
|
|
|
-
|
|
|
- if (enable)
|
|
|
- intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
|
|
- else
|
|
|
- intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
|
|
-
|
|
|
- dev_priv->power_domains.init_power_on = enable;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Starting with Haswell, we have a "Power Down Well" that can be turned off
|
|
|
* when not needed anymore. We have 4 registers that can request the power well
|
|
@@ -323,26 +295,29 @@ static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv,
|
|
|
static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id id = power_well->id;
|
|
|
+ const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
|
|
|
+ int pw_idx = power_well->desc->hsw.idx;
|
|
|
|
|
|
/* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */
|
|
|
WARN_ON(intel_wait_for_register(dev_priv,
|
|
|
- HSW_PWR_WELL_CTL_DRIVER(id),
|
|
|
- HSW_PWR_WELL_CTL_STATE(id),
|
|
|
- HSW_PWR_WELL_CTL_STATE(id),
|
|
|
+ regs->driver,
|
|
|
+ HSW_PWR_WELL_CTL_STATE(pw_idx),
|
|
|
+ HSW_PWR_WELL_CTL_STATE(pw_idx),
|
|
|
1));
|
|
|
}
|
|
|
|
|
|
static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv,
|
|
|
- enum i915_power_well_id id)
|
|
|
+ const struct i915_power_well_regs *regs,
|
|
|
+ int pw_idx)
|
|
|
{
|
|
|
- u32 req_mask = HSW_PWR_WELL_CTL_REQ(id);
|
|
|
+ u32 req_mask = HSW_PWR_WELL_CTL_REQ(pw_idx);
|
|
|
u32 ret;
|
|
|
|
|
|
- ret = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)) & req_mask ? 1 : 0;
|
|
|
- ret |= I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & req_mask ? 2 : 0;
|
|
|
- ret |= I915_READ(HSW_PWR_WELL_CTL_KVMR) & req_mask ? 4 : 0;
|
|
|
- ret |= I915_READ(HSW_PWR_WELL_CTL_DEBUG(id)) & req_mask ? 8 : 0;
|
|
|
+ ret = I915_READ(regs->bios) & req_mask ? 1 : 0;
|
|
|
+ ret |= I915_READ(regs->driver) & req_mask ? 2 : 0;
|
|
|
+ if (regs->kvmr.reg)
|
|
|
+ ret |= I915_READ(regs->kvmr) & req_mask ? 4 : 0;
|
|
|
+ ret |= I915_READ(regs->debug) & req_mask ? 8 : 0;
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -350,7 +325,8 @@ static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv,
|
|
|
static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id id = power_well->id;
|
|
|
+ const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
|
|
|
+ int pw_idx = power_well->desc->hsw.idx;
|
|
|
bool disabled;
|
|
|
u32 reqs;
|
|
|
|
|
@@ -363,14 +339,14 @@ static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
* Skip the wait in case any of the request bits are set and print a
|
|
|
* diagnostic message.
|
|
|
*/
|
|
|
- wait_for((disabled = !(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) &
|
|
|
- HSW_PWR_WELL_CTL_STATE(id))) ||
|
|
|
- (reqs = hsw_power_well_requesters(dev_priv, id)), 1);
|
|
|
+ wait_for((disabled = !(I915_READ(regs->driver) &
|
|
|
+ HSW_PWR_WELL_CTL_STATE(pw_idx))) ||
|
|
|
+ (reqs = hsw_power_well_requesters(dev_priv, regs, pw_idx)), 1);
|
|
|
if (disabled)
|
|
|
return;
|
|
|
|
|
|
DRM_DEBUG_KMS("%s forced on (bios:%d driver:%d kvmr:%d debug:%d)\n",
|
|
|
- power_well->name,
|
|
|
+ power_well->desc->name,
|
|
|
!!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8));
|
|
|
}
|
|
|
|
|
@@ -386,14 +362,15 @@ static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv,
|
|
|
static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id id = power_well->id;
|
|
|
- bool wait_fuses = power_well->hsw.has_fuses;
|
|
|
+ const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
|
|
|
+ int pw_idx = power_well->desc->hsw.idx;
|
|
|
+ bool wait_fuses = power_well->desc->hsw.has_fuses;
|
|
|
enum skl_power_gate uninitialized_var(pg);
|
|
|
u32 val;
|
|
|
|
|
|
if (wait_fuses) {
|
|
|
- pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_TO_PG(id) :
|
|
|
- SKL_PW_TO_PG(id);
|
|
|
+ pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_CTL_IDX_TO_PG(pw_idx) :
|
|
|
+ SKL_PW_CTL_IDX_TO_PG(pw_idx);
|
|
|
/*
|
|
|
* For PW1 we have to wait both for the PW0/PG0 fuse state
|
|
|
* before enabling the power well and PW1/PG1's own fuse
|
|
@@ -405,52 +382,55 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
gen9_wait_for_power_well_fuses(dev_priv, SKL_PG0);
|
|
|
}
|
|
|
|
|
|
- val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
|
|
|
- I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), val | HSW_PWR_WELL_CTL_REQ(id));
|
|
|
+ val = I915_READ(regs->driver);
|
|
|
+ I915_WRITE(regs->driver, val | HSW_PWR_WELL_CTL_REQ(pw_idx));
|
|
|
hsw_wait_for_power_well_enable(dev_priv, power_well);
|
|
|
|
|
|
/* Display WA #1178: cnl */
|
|
|
if (IS_CANNONLAKE(dev_priv) &&
|
|
|
- (id == CNL_DISP_PW_AUX_B || id == CNL_DISP_PW_AUX_C ||
|
|
|
- id == CNL_DISP_PW_AUX_D || id == CNL_DISP_PW_AUX_F)) {
|
|
|
- val = I915_READ(CNL_AUX_ANAOVRD1(id));
|
|
|
+ pw_idx >= GLK_PW_CTL_IDX_AUX_B &&
|
|
|
+ pw_idx <= CNL_PW_CTL_IDX_AUX_F) {
|
|
|
+ val = I915_READ(CNL_AUX_ANAOVRD1(pw_idx));
|
|
|
val |= CNL_AUX_ANAOVRD1_ENABLE | CNL_AUX_ANAOVRD1_LDO_BYPASS;
|
|
|
- I915_WRITE(CNL_AUX_ANAOVRD1(id), val);
|
|
|
+ I915_WRITE(CNL_AUX_ANAOVRD1(pw_idx), val);
|
|
|
}
|
|
|
|
|
|
if (wait_fuses)
|
|
|
gen9_wait_for_power_well_fuses(dev_priv, pg);
|
|
|
|
|
|
- hsw_power_well_post_enable(dev_priv, power_well->hsw.irq_pipe_mask,
|
|
|
- power_well->hsw.has_vga);
|
|
|
+ hsw_power_well_post_enable(dev_priv,
|
|
|
+ power_well->desc->hsw.irq_pipe_mask,
|
|
|
+ power_well->desc->hsw.has_vga);
|
|
|
}
|
|
|
|
|
|
static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id id = power_well->id;
|
|
|
+ const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
|
|
|
+ int pw_idx = power_well->desc->hsw.idx;
|
|
|
u32 val;
|
|
|
|
|
|
- hsw_power_well_pre_disable(dev_priv, power_well->hsw.irq_pipe_mask);
|
|
|
+ hsw_power_well_pre_disable(dev_priv,
|
|
|
+ power_well->desc->hsw.irq_pipe_mask);
|
|
|
|
|
|
- val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
|
|
|
- I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id),
|
|
|
- val & ~HSW_PWR_WELL_CTL_REQ(id));
|
|
|
+ val = I915_READ(regs->driver);
|
|
|
+ I915_WRITE(regs->driver, val & ~HSW_PWR_WELL_CTL_REQ(pw_idx));
|
|
|
hsw_wait_for_power_well_disable(dev_priv, power_well);
|
|
|
}
|
|
|
|
|
|
-#define ICL_AUX_PW_TO_PORT(pw) ((pw) - ICL_DISP_PW_AUX_A)
|
|
|
+#define ICL_AUX_PW_TO_PORT(pw_idx) ((pw_idx) - ICL_PW_CTL_IDX_AUX_A)
|
|
|
|
|
|
static void
|
|
|
icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id id = power_well->id;
|
|
|
- enum port port = ICL_AUX_PW_TO_PORT(id);
|
|
|
+ const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
|
|
|
+ int pw_idx = power_well->desc->hsw.idx;
|
|
|
+ enum port port = ICL_AUX_PW_TO_PORT(pw_idx);
|
|
|
u32 val;
|
|
|
|
|
|
- val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
|
|
|
- I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), val | HSW_PWR_WELL_CTL_REQ(id));
|
|
|
+ val = I915_READ(regs->driver);
|
|
|
+ I915_WRITE(regs->driver, val | HSW_PWR_WELL_CTL_REQ(pw_idx));
|
|
|
|
|
|
val = I915_READ(ICL_PORT_CL_DW12(port));
|
|
|
I915_WRITE(ICL_PORT_CL_DW12(port), val | ICL_LANE_ENABLE_AUX);
|
|
@@ -462,16 +442,16 @@ static void
|
|
|
icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id id = power_well->id;
|
|
|
- enum port port = ICL_AUX_PW_TO_PORT(id);
|
|
|
+ const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
|
|
|
+ int pw_idx = power_well->desc->hsw.idx;
|
|
|
+ enum port port = ICL_AUX_PW_TO_PORT(pw_idx);
|
|
|
u32 val;
|
|
|
|
|
|
val = I915_READ(ICL_PORT_CL_DW12(port));
|
|
|
I915_WRITE(ICL_PORT_CL_DW12(port), val & ~ICL_LANE_ENABLE_AUX);
|
|
|
|
|
|
- val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
|
|
|
- I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id),
|
|
|
- val & ~HSW_PWR_WELL_CTL_REQ(id));
|
|
|
+ val = I915_READ(regs->driver);
|
|
|
+ I915_WRITE(regs->driver, val & ~HSW_PWR_WELL_CTL_REQ(pw_idx));
|
|
|
|
|
|
hsw_wait_for_power_well_disable(dev_priv, power_well);
|
|
|
}
|
|
@@ -484,22 +464,22 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id id = power_well->id;
|
|
|
- u32 mask = HSW_PWR_WELL_CTL_REQ(id) | HSW_PWR_WELL_CTL_STATE(id);
|
|
|
+ const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
|
|
|
+ int pw_idx = power_well->desc->hsw.idx;
|
|
|
+ u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx) |
|
|
|
+ HSW_PWR_WELL_CTL_STATE(pw_idx);
|
|
|
|
|
|
- return (I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & mask) == mask;
|
|
|
+ return (I915_READ(regs->driver) & mask) == mask;
|
|
|
}
|
|
|
|
|
|
static void assert_can_enable_dc9(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
- enum i915_power_well_id id = SKL_DISP_PW_2;
|
|
|
-
|
|
|
WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9),
|
|
|
"DC9 already programmed to be enabled.\n");
|
|
|
WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,
|
|
|
"DC5 still not disabled to enable DC9.\n");
|
|
|
- WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) &
|
|
|
- HSW_PWR_WELL_CTL_REQ(id),
|
|
|
+ WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL2) &
|
|
|
+ HSW_PWR_WELL_CTL_REQ(SKL_PW_CTL_IDX_PW_2),
|
|
|
"Power well 2 on.\n");
|
|
|
WARN_ONCE(intel_irqs_enabled(dev_priv),
|
|
|
"Interrupts not disabled yet.\n");
|
|
@@ -668,6 +648,27 @@ static void assert_csr_loaded(struct drm_i915_private *dev_priv)
|
|
|
WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
|
|
|
}
|
|
|
|
|
|
+static struct i915_power_well *
|
|
|
+lookup_power_well(struct drm_i915_private *dev_priv,
|
|
|
+ enum i915_power_well_id power_well_id)
|
|
|
+{
|
|
|
+ struct i915_power_well *power_well;
|
|
|
+
|
|
|
+ for_each_power_well(dev_priv, power_well)
|
|
|
+ if (power_well->desc->id == power_well_id)
|
|
|
+ return power_well;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * It's not feasible to add error checking code to the callers since
|
|
|
+ * this condition really shouldn't happen and it doesn't even make sense
|
|
|
+ * to abort things like display initialization sequences. Just return
|
|
|
+ * the first power well and hope the WARN gets reported so we can fix
|
|
|
+ * our driver.
|
|
|
+ */
|
|
|
+ WARN(1, "Power well %d not defined for this platform\n", power_well_id);
|
|
|
+ return &dev_priv->power_domains.power_wells[0];
|
|
|
+}
|
|
|
+
|
|
|
static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
|
|
@@ -723,54 +724,57 @@ static void skl_enable_dc6(struct drm_i915_private *dev_priv)
|
|
|
static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id id = power_well->id;
|
|
|
- u32 mask = HSW_PWR_WELL_CTL_REQ(id);
|
|
|
- u32 bios_req = I915_READ(HSW_PWR_WELL_CTL_BIOS(id));
|
|
|
+ const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
|
|
|
+ int pw_idx = power_well->desc->hsw.idx;
|
|
|
+ u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx);
|
|
|
+ u32 bios_req = I915_READ(regs->bios);
|
|
|
|
|
|
/* Take over the request bit if set by BIOS. */
|
|
|
if (bios_req & mask) {
|
|
|
- u32 drv_req = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id));
|
|
|
+ u32 drv_req = I915_READ(regs->driver);
|
|
|
|
|
|
if (!(drv_req & mask))
|
|
|
- I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), drv_req | mask);
|
|
|
- I915_WRITE(HSW_PWR_WELL_CTL_BIOS(id), bios_req & ~mask);
|
|
|
+ I915_WRITE(regs->driver, drv_req | mask);
|
|
|
+ I915_WRITE(regs->bios, bios_req & ~mask);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- bxt_ddi_phy_init(dev_priv, power_well->bxt.phy);
|
|
|
+ bxt_ddi_phy_init(dev_priv, power_well->desc->bxt.phy);
|
|
|
}
|
|
|
|
|
|
static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- bxt_ddi_phy_uninit(dev_priv, power_well->bxt.phy);
|
|
|
+ bxt_ddi_phy_uninit(dev_priv, power_well->desc->bxt.phy);
|
|
|
}
|
|
|
|
|
|
static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- return bxt_ddi_phy_is_enabled(dev_priv, power_well->bxt.phy);
|
|
|
+ return bxt_ddi_phy_is_enabled(dev_priv, power_well->desc->bxt.phy);
|
|
|
}
|
|
|
|
|
|
static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct i915_power_well *power_well;
|
|
|
|
|
|
- power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A);
|
|
|
+ power_well = lookup_power_well(dev_priv, BXT_DISP_PW_DPIO_CMN_A);
|
|
|
if (power_well->count > 0)
|
|
|
- bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);
|
|
|
+ bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy);
|
|
|
|
|
|
- power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC);
|
|
|
+ power_well = lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);
|
|
|
if (power_well->count > 0)
|
|
|
- bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);
|
|
|
+ bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy);
|
|
|
|
|
|
if (IS_GEMINILAKE(dev_priv)) {
|
|
|
- power_well = lookup_power_well(dev_priv, GLK_DPIO_CMN_C);
|
|
|
+ power_well = lookup_power_well(dev_priv,
|
|
|
+ GLK_DISP_PW_DPIO_CMN_C);
|
|
|
if (power_well->count > 0)
|
|
|
- bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy);
|
|
|
+ bxt_ddi_phy_verify_state(dev_priv,
|
|
|
+ power_well->desc->bxt.phy);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -869,14 +873,14 @@ static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv,
|
|
|
static void vlv_set_power_well(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well, bool enable)
|
|
|
{
|
|
|
- enum i915_power_well_id power_well_id = power_well->id;
|
|
|
+ int pw_idx = power_well->desc->vlv.idx;
|
|
|
u32 mask;
|
|
|
u32 state;
|
|
|
u32 ctrl;
|
|
|
|
|
|
- mask = PUNIT_PWRGT_MASK(power_well_id);
|
|
|
- state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
|
|
|
- PUNIT_PWRGT_PWR_GATE(power_well_id);
|
|
|
+ mask = PUNIT_PWRGT_MASK(pw_idx);
|
|
|
+ state = enable ? PUNIT_PWRGT_PWR_ON(pw_idx) :
|
|
|
+ PUNIT_PWRGT_PWR_GATE(pw_idx);
|
|
|
|
|
|
mutex_lock(&dev_priv->pcu_lock);
|
|
|
|
|
@@ -917,14 +921,14 @@ static void vlv_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- enum i915_power_well_id power_well_id = power_well->id;
|
|
|
+ int pw_idx = power_well->desc->vlv.idx;
|
|
|
bool enabled = false;
|
|
|
u32 mask;
|
|
|
u32 state;
|
|
|
u32 ctrl;
|
|
|
|
|
|
- mask = PUNIT_PWRGT_MASK(power_well_id);
|
|
|
- ctrl = PUNIT_PWRGT_PWR_ON(power_well_id);
|
|
|
+ mask = PUNIT_PWRGT_MASK(pw_idx);
|
|
|
+ ctrl = PUNIT_PWRGT_PWR_ON(pw_idx);
|
|
|
|
|
|
mutex_lock(&dev_priv->pcu_lock);
|
|
|
|
|
@@ -933,8 +937,8 @@ static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
|
|
|
* We only ever set the power-on and power-gate states, anything
|
|
|
* else is unexpected.
|
|
|
*/
|
|
|
- WARN_ON(state != PUNIT_PWRGT_PWR_ON(power_well_id) &&
|
|
|
- state != PUNIT_PWRGT_PWR_GATE(power_well_id));
|
|
|
+ WARN_ON(state != PUNIT_PWRGT_PWR_ON(pw_idx) &&
|
|
|
+ state != PUNIT_PWRGT_PWR_GATE(pw_idx));
|
|
|
if (state == ctrl)
|
|
|
enabled = true;
|
|
|
|
|
@@ -1045,8 +1049,6 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
|
|
|
static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D);
|
|
|
-
|
|
|
vlv_set_power_well(dev_priv, power_well, true);
|
|
|
|
|
|
vlv_display_power_well_init(dev_priv);
|
|
@@ -1055,8 +1057,6 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D);
|
|
|
-
|
|
|
vlv_display_power_well_deinit(dev_priv);
|
|
|
|
|
|
vlv_set_power_well(dev_priv, power_well, false);
|
|
@@ -1065,8 +1065,6 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC);
|
|
|
-
|
|
|
/* since ref/cri clock was enabled */
|
|
|
udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
|
|
|
|
|
@@ -1091,8 +1089,6 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
{
|
|
|
enum pipe pipe;
|
|
|
|
|
|
- WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC);
|
|
|
-
|
|
|
for_each_pipe(dev_priv, pipe)
|
|
|
assert_pll_disabled(dev_priv, pipe);
|
|
|
|
|
@@ -1104,32 +1100,14 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
#define POWER_DOMAIN_MASK (GENMASK_ULL(POWER_DOMAIN_NUM - 1, 0))
|
|
|
|
|
|
-static struct i915_power_well *
|
|
|
-lookup_power_well(struct drm_i915_private *dev_priv,
|
|
|
- enum i915_power_well_id power_well_id)
|
|
|
-{
|
|
|
- struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < power_domains->power_well_count; i++) {
|
|
|
- struct i915_power_well *power_well;
|
|
|
-
|
|
|
- power_well = &power_domains->power_wells[i];
|
|
|
- if (power_well->id == power_well_id)
|
|
|
- return power_well;
|
|
|
- }
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
#define BITS_SET(val, bits) (((val) & (bits)) == (bits))
|
|
|
|
|
|
static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct i915_power_well *cmn_bc =
|
|
|
- lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
|
|
|
+ lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);
|
|
|
struct i915_power_well *cmn_d =
|
|
|
- lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
|
|
|
+ lookup_power_well(dev_priv, CHV_DISP_PW_DPIO_CMN_D);
|
|
|
u32 phy_control = dev_priv->chv_phy_control;
|
|
|
u32 phy_status = 0;
|
|
|
u32 phy_status_mask = 0xffffffff;
|
|
@@ -1154,7 +1132,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
|
|
|
PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0) |
|
|
|
PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1));
|
|
|
|
|
|
- if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
|
|
|
+ if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) {
|
|
|
phy_status |= PHY_POWERGOOD(DPIO_PHY0);
|
|
|
|
|
|
/* this assumes override is only used to enable lanes */
|
|
@@ -1195,7 +1173,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
|
|
|
phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1);
|
|
|
}
|
|
|
|
|
|
- if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
|
|
|
+ if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) {
|
|
|
phy_status |= PHY_POWERGOOD(DPIO_PHY1);
|
|
|
|
|
|
/* this assumes override is only used to enable lanes */
|
|
@@ -1239,10 +1217,10 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
enum pipe pipe;
|
|
|
uint32_t tmp;
|
|
|
|
|
|
- WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC &&
|
|
|
- power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D);
|
|
|
+ WARN_ON_ONCE(power_well->desc->id != VLV_DISP_PW_DPIO_CMN_BC &&
|
|
|
+ power_well->desc->id != CHV_DISP_PW_DPIO_CMN_D);
|
|
|
|
|
|
- if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
|
|
|
+ if (power_well->desc->id == VLV_DISP_PW_DPIO_CMN_BC) {
|
|
|
pipe = PIPE_A;
|
|
|
phy = DPIO_PHY0;
|
|
|
} else {
|
|
@@ -1270,7 +1248,7 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
DPIO_SUS_CLK_CONFIG_GATE_CLKREQ;
|
|
|
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
|
|
|
|
|
|
- if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
|
|
|
+ if (power_well->desc->id == VLV_DISP_PW_DPIO_CMN_BC) {
|
|
|
tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
|
|
|
tmp |= DPIO_DYNPWRDOWNEN_CH1;
|
|
|
vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
|
|
@@ -1301,10 +1279,10 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
{
|
|
|
enum dpio_phy phy;
|
|
|
|
|
|
- WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC &&
|
|
|
- power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D);
|
|
|
+ WARN_ON_ONCE(power_well->desc->id != VLV_DISP_PW_DPIO_CMN_BC &&
|
|
|
+ power_well->desc->id != CHV_DISP_PW_DPIO_CMN_D);
|
|
|
|
|
|
- if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
|
|
|
+ if (power_well->desc->id == VLV_DISP_PW_DPIO_CMN_BC) {
|
|
|
phy = DPIO_PHY0;
|
|
|
assert_pll_disabled(dev_priv, PIPE_A);
|
|
|
assert_pll_disabled(dev_priv, PIPE_B);
|
|
@@ -1516,8 +1494,6 @@ out:
|
|
|
static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- WARN_ON_ONCE(power_well->id != CHV_DISP_PW_PIPE_A);
|
|
|
-
|
|
|
chv_set_pipe_power_well(dev_priv, power_well, true);
|
|
|
|
|
|
vlv_display_power_well_init(dev_priv);
|
|
@@ -1526,8 +1502,6 @@ static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
struct i915_power_well *power_well)
|
|
|
{
|
|
|
- WARN_ON_ONCE(power_well->id != CHV_DISP_PW_PIPE_A);
|
|
|
-
|
|
|
vlv_display_power_well_deinit(dev_priv);
|
|
|
|
|
|
chv_set_pipe_power_well(dev_priv, power_well, false);
|
|
@@ -2063,13 +2037,13 @@ static const struct i915_power_well_ops chv_dpio_cmn_power_well_ops = {
|
|
|
.is_enabled = vlv_power_well_enabled,
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well i9xx_always_on_power_well[] = {
|
|
|
+static const struct i915_power_well_desc i9xx_always_on_power_well[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -2080,19 +2054,19 @@ static const struct i915_power_well_ops i830_pipes_power_well_ops = {
|
|
|
.is_enabled = i830_pipes_power_well_enabled,
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well i830_power_wells[] = {
|
|
|
+static const struct i915_power_well_desc i830_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "pipes",
|
|
|
.domains = I830_PIPES_POWER_DOMAINS,
|
|
|
.ops = &i830_pipes_power_well_ops,
|
|
|
- .id = I830_DISP_PW_PIPES,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -2117,13 +2091,20 @@ static const struct i915_power_well_ops bxt_dpio_cmn_power_well_ops = {
|
|
|
.is_enabled = bxt_dpio_cmn_power_well_enabled,
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well hsw_power_wells[] = {
|
|
|
+static const struct i915_power_well_regs hsw_power_well_regs = {
|
|
|
+ .bios = HSW_PWR_WELL_CTL1,
|
|
|
+ .driver = HSW_PWR_WELL_CTL2,
|
|
|
+ .kvmr = HSW_PWR_WELL_CTL3,
|
|
|
+ .debug = HSW_PWR_WELL_CTL4,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct i915_power_well_desc hsw_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "display",
|
|
@@ -2131,18 +2112,20 @@ static struct i915_power_well hsw_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = HSW_DISP_PW_GLOBAL,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = HSW_PW_CTL_IDX_GLOBAL,
|
|
|
.hsw.has_vga = true,
|
|
|
},
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well bdw_power_wells[] = {
|
|
|
+static const struct i915_power_well_desc bdw_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "display",
|
|
@@ -2150,6 +2133,8 @@ static struct i915_power_well bdw_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = HSW_DISP_PW_GLOBAL,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = HSW_PW_CTL_IDX_GLOBAL,
|
|
|
.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
|
|
|
.hsw.has_vga = true,
|
|
|
},
|
|
@@ -2177,19 +2162,22 @@ static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
|
|
|
.is_enabled = vlv_power_well_enabled,
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well vlv_power_wells[] = {
|
|
|
+static const struct i915_power_well_desc vlv_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "display",
|
|
|
.domains = VLV_DISPLAY_POWER_DOMAINS,
|
|
|
- .id = PUNIT_POWER_WELL_DISP2D,
|
|
|
.ops = &vlv_display_power_well_ops,
|
|
|
+ .id = VLV_DISP_PW_DISP2D,
|
|
|
+ {
|
|
|
+ .vlv.idx = PUNIT_PWGT_IDX_DISP2D,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "dpio-tx-b-01",
|
|
@@ -2198,7 +2186,10 @@ static struct i915_power_well vlv_power_wells[] = {
|
|
|
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
|
|
|
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
- .id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .vlv.idx = PUNIT_PWGT_IDX_DPIO_TX_B_LANES_01,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "dpio-tx-b-23",
|
|
@@ -2207,7 +2198,10 @@ static struct i915_power_well vlv_power_wells[] = {
|
|
|
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
|
|
|
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
- .id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .vlv.idx = PUNIT_PWGT_IDX_DPIO_TX_B_LANES_23,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "dpio-tx-c-01",
|
|
@@ -2216,7 +2210,10 @@ static struct i915_power_well vlv_power_wells[] = {
|
|
|
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
|
|
|
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
- .id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .vlv.idx = PUNIT_PWGT_IDX_DPIO_TX_C_LANES_01,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "dpio-tx-c-23",
|
|
@@ -2225,23 +2222,29 @@ static struct i915_power_well vlv_power_wells[] = {
|
|
|
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
|
|
|
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
- .id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .vlv.idx = PUNIT_PWGT_IDX_DPIO_TX_C_LANES_23,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "dpio-common",
|
|
|
.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
|
|
|
- .id = PUNIT_POWER_WELL_DPIO_CMN_BC,
|
|
|
.ops = &vlv_dpio_cmn_power_well_ops,
|
|
|
+ .id = VLV_DISP_PW_DPIO_CMN_BC,
|
|
|
+ {
|
|
|
+ .vlv.idx = PUNIT_PWGT_IDX_DPIO_CMN_BC,
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well chv_power_wells[] = {
|
|
|
+static const struct i915_power_well_desc chv_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "display",
|
|
@@ -2251,20 +2254,26 @@ static struct i915_power_well chv_power_wells[] = {
|
|
|
* required for any pipe to work.
|
|
|
*/
|
|
|
.domains = CHV_DISPLAY_POWER_DOMAINS,
|
|
|
- .id = CHV_DISP_PW_PIPE_A,
|
|
|
.ops = &chv_pipe_power_well_ops,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "dpio-common-bc",
|
|
|
.domains = CHV_DPIO_CMN_BC_POWER_DOMAINS,
|
|
|
- .id = PUNIT_POWER_WELL_DPIO_CMN_BC,
|
|
|
.ops = &chv_dpio_cmn_power_well_ops,
|
|
|
+ .id = VLV_DISP_PW_DPIO_CMN_BC,
|
|
|
+ {
|
|
|
+ .vlv.idx = PUNIT_PWGT_IDX_DPIO_CMN_BC,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "dpio-common-d",
|
|
|
.domains = CHV_DPIO_CMN_D_POWER_DOMAINS,
|
|
|
- .id = PUNIT_POWER_WELL_DPIO_CMN_D,
|
|
|
.ops = &chv_dpio_cmn_power_well_ops,
|
|
|
+ .id = CHV_DISP_PW_DPIO_CMN_D,
|
|
|
+ {
|
|
|
+ .vlv.idx = PUNIT_PWGT_IDX_DPIO_CMN_D,
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -2275,18 +2284,18 @@ bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
|
|
|
bool ret;
|
|
|
|
|
|
power_well = lookup_power_well(dev_priv, power_well_id);
|
|
|
- ret = power_well->ops->is_enabled(dev_priv, power_well);
|
|
|
+ ret = power_well->desc->ops->is_enabled(dev_priv, power_well);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static struct i915_power_well skl_power_wells[] = {
|
|
|
+static const struct i915_power_well_desc skl_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 1",
|
|
@@ -2295,6 +2304,8 @@ static struct i915_power_well skl_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_1,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_PW_1,
|
|
|
.hsw.has_fuses = true,
|
|
|
},
|
|
|
},
|
|
@@ -2304,12 +2315,16 @@ static struct i915_power_well skl_power_wells[] = {
|
|
|
.domains = 0,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_MISC_IO,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_MISC_IO,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DC off",
|
|
|
.domains = SKL_DISPLAY_DC_OFF_POWER_DOMAINS,
|
|
|
.ops = &gen9_dc_off_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DC_OFF,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 2",
|
|
@@ -2317,6 +2332,8 @@ static struct i915_power_well skl_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_2,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_PW_2,
|
|
|
.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
|
|
|
.hsw.has_vga = true,
|
|
|
.hsw.has_fuses = true,
|
|
@@ -2326,35 +2343,51 @@ static struct i915_power_well skl_power_wells[] = {
|
|
|
.name = "DDI A/E IO power well",
|
|
|
.domains = SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_A_E,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_A_E,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI B IO power well",
|
|
|
.domains = SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_B,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_B,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI C IO power well",
|
|
|
.domains = SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_C,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_C,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI D IO power well",
|
|
|
.domains = SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_D,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_D,
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well bxt_power_wells[] = {
|
|
|
+static const struct i915_power_well_desc bxt_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 1",
|
|
@@ -2362,6 +2395,8 @@ static struct i915_power_well bxt_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_1,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_PW_1,
|
|
|
.hsw.has_fuses = true,
|
|
|
},
|
|
|
},
|
|
@@ -2369,7 +2404,7 @@ static struct i915_power_well bxt_power_wells[] = {
|
|
|
.name = "DC off",
|
|
|
.domains = BXT_DISPLAY_DC_OFF_POWER_DOMAINS,
|
|
|
.ops = &gen9_dc_off_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DC_OFF,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 2",
|
|
@@ -2377,6 +2412,8 @@ static struct i915_power_well bxt_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_2,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_PW_2,
|
|
|
.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
|
|
|
.hsw.has_vga = true,
|
|
|
.hsw.has_fuses = true,
|
|
@@ -2386,7 +2423,7 @@ static struct i915_power_well bxt_power_wells[] = {
|
|
|
.name = "dpio-common-a",
|
|
|
.domains = BXT_DPIO_CMN_A_POWER_DOMAINS,
|
|
|
.ops = &bxt_dpio_cmn_power_well_ops,
|
|
|
- .id = BXT_DPIO_CMN_A,
|
|
|
+ .id = BXT_DISP_PW_DPIO_CMN_A,
|
|
|
{
|
|
|
.bxt.phy = DPIO_PHY1,
|
|
|
},
|
|
@@ -2395,20 +2432,20 @@ static struct i915_power_well bxt_power_wells[] = {
|
|
|
.name = "dpio-common-bc",
|
|
|
.domains = BXT_DPIO_CMN_BC_POWER_DOMAINS,
|
|
|
.ops = &bxt_dpio_cmn_power_well_ops,
|
|
|
- .id = BXT_DPIO_CMN_BC,
|
|
|
+ .id = VLV_DISP_PW_DPIO_CMN_BC,
|
|
|
{
|
|
|
.bxt.phy = DPIO_PHY0,
|
|
|
},
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well glk_power_wells[] = {
|
|
|
+static const struct i915_power_well_desc glk_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 1",
|
|
@@ -2417,6 +2454,8 @@ static struct i915_power_well glk_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_1,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_PW_1,
|
|
|
.hsw.has_fuses = true,
|
|
|
},
|
|
|
},
|
|
@@ -2424,7 +2463,7 @@ static struct i915_power_well glk_power_wells[] = {
|
|
|
.name = "DC off",
|
|
|
.domains = GLK_DISPLAY_DC_OFF_POWER_DOMAINS,
|
|
|
.ops = &gen9_dc_off_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DC_OFF,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 2",
|
|
@@ -2432,6 +2471,8 @@ static struct i915_power_well glk_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_2,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_PW_2,
|
|
|
.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
|
|
|
.hsw.has_vga = true,
|
|
|
.hsw.has_fuses = true,
|
|
@@ -2441,7 +2482,7 @@ static struct i915_power_well glk_power_wells[] = {
|
|
|
.name = "dpio-common-a",
|
|
|
.domains = GLK_DPIO_CMN_A_POWER_DOMAINS,
|
|
|
.ops = &bxt_dpio_cmn_power_well_ops,
|
|
|
- .id = BXT_DPIO_CMN_A,
|
|
|
+ .id = BXT_DISP_PW_DPIO_CMN_A,
|
|
|
{
|
|
|
.bxt.phy = DPIO_PHY1,
|
|
|
},
|
|
@@ -2450,7 +2491,7 @@ static struct i915_power_well glk_power_wells[] = {
|
|
|
.name = "dpio-common-b",
|
|
|
.domains = GLK_DPIO_CMN_B_POWER_DOMAINS,
|
|
|
.ops = &bxt_dpio_cmn_power_well_ops,
|
|
|
- .id = BXT_DPIO_CMN_BC,
|
|
|
+ .id = VLV_DISP_PW_DPIO_CMN_BC,
|
|
|
{
|
|
|
.bxt.phy = DPIO_PHY0,
|
|
|
},
|
|
@@ -2459,7 +2500,7 @@ static struct i915_power_well glk_power_wells[] = {
|
|
|
.name = "dpio-common-c",
|
|
|
.domains = GLK_DPIO_CMN_C_POWER_DOMAINS,
|
|
|
.ops = &bxt_dpio_cmn_power_well_ops,
|
|
|
- .id = GLK_DPIO_CMN_C,
|
|
|
+ .id = GLK_DISP_PW_DPIO_CMN_C,
|
|
|
{
|
|
|
.bxt.phy = DPIO_PHY2,
|
|
|
},
|
|
@@ -2468,47 +2509,71 @@ static struct i915_power_well glk_power_wells[] = {
|
|
|
.name = "AUX A",
|
|
|
.domains = GLK_DISPLAY_AUX_A_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = GLK_DISP_PW_AUX_A,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = GLK_PW_CTL_IDX_AUX_A,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX B",
|
|
|
.domains = GLK_DISPLAY_AUX_B_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = GLK_DISP_PW_AUX_B,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = GLK_PW_CTL_IDX_AUX_B,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX C",
|
|
|
.domains = GLK_DISPLAY_AUX_C_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = GLK_DISP_PW_AUX_C,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = GLK_PW_CTL_IDX_AUX_C,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI A IO power well",
|
|
|
.domains = GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = GLK_DISP_PW_DDI_A,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = GLK_PW_CTL_IDX_DDI_A,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI B IO power well",
|
|
|
.domains = GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_B,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_B,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI C IO power well",
|
|
|
.domains = GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_C,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_C,
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well cnl_power_wells[] = {
|
|
|
+static const struct i915_power_well_desc cnl_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 1",
|
|
@@ -2517,6 +2582,8 @@ static struct i915_power_well cnl_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_1,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_PW_1,
|
|
|
.hsw.has_fuses = true,
|
|
|
},
|
|
|
},
|
|
@@ -2524,31 +2591,47 @@ static struct i915_power_well cnl_power_wells[] = {
|
|
|
.name = "AUX A",
|
|
|
.domains = CNL_DISPLAY_AUX_A_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = CNL_DISP_PW_AUX_A,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = GLK_PW_CTL_IDX_AUX_A,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX B",
|
|
|
.domains = CNL_DISPLAY_AUX_B_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = CNL_DISP_PW_AUX_B,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = GLK_PW_CTL_IDX_AUX_B,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX C",
|
|
|
.domains = CNL_DISPLAY_AUX_C_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = CNL_DISP_PW_AUX_C,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = GLK_PW_CTL_IDX_AUX_C,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX D",
|
|
|
.domains = CNL_DISPLAY_AUX_D_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = CNL_DISP_PW_AUX_D,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = CNL_PW_CTL_IDX_AUX_D,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DC off",
|
|
|
.domains = CNL_DISPLAY_DC_OFF_POWER_DOMAINS,
|
|
|
.ops = &gen9_dc_off_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DC_OFF,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 2",
|
|
@@ -2556,6 +2639,8 @@ static struct i915_power_well cnl_power_wells[] = {
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
.id = SKL_DISP_PW_2,
|
|
|
{
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_PW_2,
|
|
|
.hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
|
|
|
.hsw.has_vga = true,
|
|
|
.hsw.has_fuses = true,
|
|
@@ -2565,37 +2650,61 @@ static struct i915_power_well cnl_power_wells[] = {
|
|
|
.name = "DDI A IO power well",
|
|
|
.domains = CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = CNL_DISP_PW_DDI_A,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = GLK_PW_CTL_IDX_DDI_A,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI B IO power well",
|
|
|
.domains = CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_B,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_B,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI C IO power well",
|
|
|
.domains = CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_C,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_C,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI D IO power well",
|
|
|
.domains = CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DDI_D,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = SKL_PW_CTL_IDX_DDI_D,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI F IO power well",
|
|
|
.domains = CNL_DISPLAY_DDI_F_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = CNL_DISP_PW_DDI_F,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = CNL_PW_CTL_IDX_DDI_F,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX F",
|
|
|
.domains = CNL_DISPLAY_AUX_F_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = CNL_DISP_PW_AUX_F,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = CNL_PW_CTL_IDX_AUX_F,
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -2606,147 +2715,239 @@ static const struct i915_power_well_ops icl_combo_phy_aux_power_well_ops = {
|
|
|
.is_enabled = hsw_power_well_enabled,
|
|
|
};
|
|
|
|
|
|
-static struct i915_power_well icl_power_wells[] = {
|
|
|
+static const struct i915_power_well_regs icl_aux_power_well_regs = {
|
|
|
+ .bios = ICL_PWR_WELL_CTL_AUX1,
|
|
|
+ .driver = ICL_PWR_WELL_CTL_AUX2,
|
|
|
+ .debug = ICL_PWR_WELL_CTL_AUX4,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct i915_power_well_regs icl_ddi_power_well_regs = {
|
|
|
+ .bios = ICL_PWR_WELL_CTL_DDI1,
|
|
|
+ .driver = ICL_PWR_WELL_CTL_DDI2,
|
|
|
+ .debug = ICL_PWR_WELL_CTL_DDI4,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct i915_power_well_desc icl_power_wells[] = {
|
|
|
{
|
|
|
.name = "always-on",
|
|
|
.always_on = 1,
|
|
|
.domains = POWER_DOMAIN_MASK,
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
- .id = I915_DISP_PW_ALWAYS_ON,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 1",
|
|
|
/* Handled by the DMC firmware */
|
|
|
.domains = 0,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_1,
|
|
|
- .hsw.has_fuses = true,
|
|
|
+ .id = SKL_DISP_PW_1,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_PW_1,
|
|
|
+ .hsw.has_fuses = true,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 2",
|
|
|
.domains = ICL_PW_2_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_2,
|
|
|
- .hsw.has_fuses = true,
|
|
|
+ .id = SKL_DISP_PW_2,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_PW_2,
|
|
|
+ .hsw.has_fuses = true,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DC off",
|
|
|
.domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS,
|
|
|
.ops = &gen9_dc_off_power_well_ops,
|
|
|
- .id = SKL_DISP_PW_DC_OFF,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 3",
|
|
|
.domains = ICL_PW_3_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_3,
|
|
|
- .hsw.irq_pipe_mask = BIT(PIPE_B),
|
|
|
- .hsw.has_vga = true,
|
|
|
- .hsw.has_fuses = true,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_PW_3,
|
|
|
+ .hsw.irq_pipe_mask = BIT(PIPE_B),
|
|
|
+ .hsw.has_vga = true,
|
|
|
+ .hsw.has_fuses = true,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI A IO",
|
|
|
.domains = ICL_DDI_IO_A_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_DDI_A,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_ddi_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI B IO",
|
|
|
.domains = ICL_DDI_IO_B_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_DDI_B,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_ddi_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI C IO",
|
|
|
.domains = ICL_DDI_IO_C_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_DDI_C,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_ddi_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_C,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI D IO",
|
|
|
.domains = ICL_DDI_IO_D_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_DDI_D,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_ddi_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_D,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI E IO",
|
|
|
.domains = ICL_DDI_IO_E_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_DDI_E,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_ddi_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_E,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "DDI F IO",
|
|
|
.domains = ICL_DDI_IO_F_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_DDI_F,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_ddi_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_DDI_F,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX A",
|
|
|
.domains = ICL_AUX_A_IO_POWER_DOMAINS,
|
|
|
.ops = &icl_combo_phy_aux_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_A,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX B",
|
|
|
.domains = ICL_AUX_B_IO_POWER_DOMAINS,
|
|
|
.ops = &icl_combo_phy_aux_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_B,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX C",
|
|
|
.domains = ICL_AUX_C_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_C,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_C,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX D",
|
|
|
.domains = ICL_AUX_D_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_D,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_D,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX E",
|
|
|
.domains = ICL_AUX_E_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_E,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_E,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX F",
|
|
|
.domains = ICL_AUX_F_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_F,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_F,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX TBT1",
|
|
|
.domains = ICL_AUX_TBT1_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_TBT1,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT1,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX TBT2",
|
|
|
.domains = ICL_AUX_TBT2_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_TBT2,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT2,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX TBT3",
|
|
|
.domains = ICL_AUX_TBT3_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_TBT3,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT3,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "AUX TBT4",
|
|
|
.domains = ICL_AUX_TBT4_IO_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_AUX_TBT4,
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &icl_aux_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT4,
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
.name = "power well 4",
|
|
|
.domains = ICL_PW_4_POWER_DOMAINS,
|
|
|
.ops = &hsw_power_well_ops,
|
|
|
- .id = ICL_DISP_PW_4,
|
|
|
- .hsw.has_fuses = true,
|
|
|
- .hsw.irq_pipe_mask = BIT(PIPE_C),
|
|
|
+ .id = DISP_PW_ID_NONE,
|
|
|
+ {
|
|
|
+ .hsw.regs = &hsw_power_well_regs,
|
|
|
+ .hsw.idx = ICL_PW_CTL_IDX_PW_4,
|
|
|
+ .hsw.has_fuses = true,
|
|
|
+ .hsw.irq_pipe_mask = BIT(PIPE_C),
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -2809,26 +3010,41 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
|
|
|
return mask;
|
|
|
}
|
|
|
|
|
|
-static void assert_power_well_ids_unique(struct drm_i915_private *dev_priv)
|
|
|
+static int
|
|
|
+__set_power_wells(struct i915_power_domains *power_domains,
|
|
|
+ const struct i915_power_well_desc *power_well_descs,
|
|
|
+ int power_well_count)
|
|
|
{
|
|
|
- struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
|
|
- u64 power_well_ids;
|
|
|
+ u64 power_well_ids = 0;
|
|
|
int i;
|
|
|
|
|
|
- power_well_ids = 0;
|
|
|
- for (i = 0; i < power_domains->power_well_count; i++) {
|
|
|
- enum i915_power_well_id id = power_domains->power_wells[i].id;
|
|
|
+ power_domains->power_well_count = power_well_count;
|
|
|
+ power_domains->power_wells =
|
|
|
+ kcalloc(power_well_count,
|
|
|
+ sizeof(*power_domains->power_wells),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!power_domains->power_wells)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ for (i = 0; i < power_well_count; i++) {
|
|
|
+ enum i915_power_well_id id = power_well_descs[i].id;
|
|
|
+
|
|
|
+ power_domains->power_wells[i].desc = &power_well_descs[i];
|
|
|
+
|
|
|
+ if (id == DISP_PW_ID_NONE)
|
|
|
+ continue;
|
|
|
|
|
|
WARN_ON(id >= sizeof(power_well_ids) * 8);
|
|
|
WARN_ON(power_well_ids & BIT_ULL(id));
|
|
|
power_well_ids |= BIT_ULL(id);
|
|
|
}
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-#define set_power_wells(power_domains, __power_wells) ({ \
|
|
|
- (power_domains)->power_wells = (__power_wells); \
|
|
|
- (power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \
|
|
|
-})
|
|
|
+#define set_power_wells(power_domains, __power_well_descs) \
|
|
|
+ __set_power_wells(power_domains, __power_well_descs, \
|
|
|
+ ARRAY_SIZE(__power_well_descs))
|
|
|
|
|
|
/**
|
|
|
* intel_power_domains_init - initializes the power domain structures
|
|
@@ -2840,6 +3056,7 @@ static void assert_power_well_ids_unique(struct drm_i915_private *dev_priv)
|
|
|
int intel_power_domains_init(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
|
|
+ int err;
|
|
|
|
|
|
i915_modparams.disable_power_well =
|
|
|
sanitize_disable_power_well_option(dev_priv,
|
|
@@ -2856,15 +3073,15 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
|
|
|
* the disabling order is reversed.
|
|
|
*/
|
|
|
if (IS_ICELAKE(dev_priv)) {
|
|
|
- set_power_wells(power_domains, icl_power_wells);
|
|
|
+ err = set_power_wells(power_domains, icl_power_wells);
|
|
|
} else if (IS_HASWELL(dev_priv)) {
|
|
|
- set_power_wells(power_domains, hsw_power_wells);
|
|
|
+ err = set_power_wells(power_domains, hsw_power_wells);
|
|
|
} else if (IS_BROADWELL(dev_priv)) {
|
|
|
- set_power_wells(power_domains, bdw_power_wells);
|
|
|
+ err = set_power_wells(power_domains, bdw_power_wells);
|
|
|
} else if (IS_GEN9_BC(dev_priv)) {
|
|
|
- set_power_wells(power_domains, skl_power_wells);
|
|
|
+ err = set_power_wells(power_domains, skl_power_wells);
|
|
|
} else if (IS_CANNONLAKE(dev_priv)) {
|
|
|
- set_power_wells(power_domains, cnl_power_wells);
|
|
|
+ err = set_power_wells(power_domains, cnl_power_wells);
|
|
|
|
|
|
/*
|
|
|
* DDI and Aux IO are getting enabled for all ports
|
|
@@ -2876,57 +3093,31 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
|
|
|
power_domains->power_well_count -= 2;
|
|
|
|
|
|
} else if (IS_BROXTON(dev_priv)) {
|
|
|
- set_power_wells(power_domains, bxt_power_wells);
|
|
|
+ err = set_power_wells(power_domains, bxt_power_wells);
|
|
|
} else if (IS_GEMINILAKE(dev_priv)) {
|
|
|
- set_power_wells(power_domains, glk_power_wells);
|
|
|
+ err = set_power_wells(power_domains, glk_power_wells);
|
|
|
} else if (IS_CHERRYVIEW(dev_priv)) {
|
|
|
- set_power_wells(power_domains, chv_power_wells);
|
|
|
+ err = set_power_wells(power_domains, chv_power_wells);
|
|
|
} else if (IS_VALLEYVIEW(dev_priv)) {
|
|
|
- set_power_wells(power_domains, vlv_power_wells);
|
|
|
+ err = set_power_wells(power_domains, vlv_power_wells);
|
|
|
} else if (IS_I830(dev_priv)) {
|
|
|
- set_power_wells(power_domains, i830_power_wells);
|
|
|
+ err = set_power_wells(power_domains, i830_power_wells);
|
|
|
} else {
|
|
|
- set_power_wells(power_domains, i9xx_always_on_power_well);
|
|
|
+ err = set_power_wells(power_domains, i9xx_always_on_power_well);
|
|
|
}
|
|
|
|
|
|
- assert_power_well_ids_unique(dev_priv);
|
|
|
-
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * intel_power_domains_fini - finalizes the power domain structures
|
|
|
+ * intel_power_domains_cleanup - clean up power domains resources
|
|
|
* @dev_priv: i915 device instance
|
|
|
*
|
|
|
- * Finalizes the power domain structures for @dev_priv depending upon the
|
|
|
- * supported platform. This function also disables runtime pm and ensures that
|
|
|
- * the device stays powered up so that the driver can be reloaded.
|
|
|
+ * Release any resources acquired by intel_power_domains_init()
|
|
|
*/
|
|
|
-void intel_power_domains_fini(struct drm_i915_private *dev_priv)
|
|
|
+void intel_power_domains_cleanup(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
- struct device *kdev = &dev_priv->drm.pdev->dev;
|
|
|
-
|
|
|
- /*
|
|
|
- * The i915.ko module is still not prepared to be loaded when
|
|
|
- * the power well is not enabled, so just enable it in case
|
|
|
- * we're going to unload/reload.
|
|
|
- * The following also reacquires the RPM reference the core passed
|
|
|
- * to the driver during loading, which is dropped in
|
|
|
- * intel_runtime_pm_enable(). We have to hand back the control of the
|
|
|
- * device to the core with this reference held.
|
|
|
- */
|
|
|
- intel_display_set_init_power(dev_priv, true);
|
|
|
-
|
|
|
- /* Remove the refcount we took to keep power well support disabled. */
|
|
|
- if (!i915_modparams.disable_power_well)
|
|
|
- intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
|
|
-
|
|
|
- /*
|
|
|
- * Remove the refcount we took in intel_runtime_pm_enable() in case
|
|
|
- * the platform doesn't support runtime PM.
|
|
|
- */
|
|
|
- if (!HAS_RUNTIME_PM(dev_priv))
|
|
|
- pm_runtime_put(kdev);
|
|
|
+ kfree(dev_priv->power_domains.power_wells);
|
|
|
}
|
|
|
|
|
|
static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
|
|
@@ -2936,9 +3127,9 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
|
|
|
|
|
|
mutex_lock(&power_domains->lock);
|
|
|
for_each_power_well(dev_priv, power_well) {
|
|
|
- power_well->ops->sync_hw(dev_priv, power_well);
|
|
|
- power_well->hw_enabled = power_well->ops->is_enabled(dev_priv,
|
|
|
- power_well);
|
|
|
+ power_well->desc->ops->sync_hw(dev_priv, power_well);
|
|
|
+ power_well->hw_enabled =
|
|
|
+ power_well->desc->ops->is_enabled(dev_priv, power_well);
|
|
|
}
|
|
|
mutex_unlock(&power_domains->lock);
|
|
|
}
|
|
@@ -3360,7 +3551,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
|
|
|
* The AUX IO power wells will be enabled on demand.
|
|
|
*/
|
|
|
mutex_lock(&power_domains->lock);
|
|
|
- well = lookup_power_well(dev_priv, ICL_DISP_PW_1);
|
|
|
+ well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
|
|
|
intel_power_well_enable(dev_priv, well);
|
|
|
mutex_unlock(&power_domains->lock);
|
|
|
|
|
@@ -3372,10 +3563,6 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
/* 7. Setup MBUS. */
|
|
|
icl_mbus_init(dev_priv);
|
|
|
-
|
|
|
- /* 8. CHICKEN_DCPR_1 */
|
|
|
- I915_WRITE(GEN8_CHICKEN_DCPR_1, I915_READ(GEN8_CHICKEN_DCPR_1) |
|
|
|
- CNL_DDI_CLOCK_REG_ACCESS_ON);
|
|
|
}
|
|
|
|
|
|
static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
|
|
@@ -3401,7 +3588,7 @@ static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
|
|
|
* disabled at this point.
|
|
|
*/
|
|
|
mutex_lock(&power_domains->lock);
|
|
|
- well = lookup_power_well(dev_priv, ICL_DISP_PW_1);
|
|
|
+ well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
|
|
|
intel_power_well_disable(dev_priv, well);
|
|
|
mutex_unlock(&power_domains->lock);
|
|
|
|
|
@@ -3416,9 +3603,9 @@ static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
|
|
|
static void chv_phy_control_init(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct i915_power_well *cmn_bc =
|
|
|
- lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
|
|
|
+ lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);
|
|
|
struct i915_power_well *cmn_d =
|
|
|
- lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
|
|
|
+ lookup_power_well(dev_priv, CHV_DISP_PW_DPIO_CMN_D);
|
|
|
|
|
|
/*
|
|
|
* DISPLAY_PHY_CONTROL can get corrupted if read. As a
|
|
@@ -3441,7 +3628,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
|
|
|
* override and set the lane powerdown bits accding to the
|
|
|
* current lane status.
|
|
|
*/
|
|
|
- if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
|
|
|
+ if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) {
|
|
|
uint32_t status = I915_READ(DPLL(PIPE_A));
|
|
|
unsigned int mask;
|
|
|
|
|
@@ -3472,7 +3659,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
|
|
|
dev_priv->chv_phy_assert[DPIO_PHY0] = true;
|
|
|
}
|
|
|
|
|
|
- if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
|
|
|
+ if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) {
|
|
|
uint32_t status = I915_READ(DPIO_PHY_STATUS);
|
|
|
unsigned int mask;
|
|
|
|
|
@@ -3503,20 +3690,20 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
|
|
|
static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct i915_power_well *cmn =
|
|
|
- lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
|
|
|
+ lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);
|
|
|
struct i915_power_well *disp2d =
|
|
|
- lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D);
|
|
|
+ lookup_power_well(dev_priv, VLV_DISP_PW_DISP2D);
|
|
|
|
|
|
/* If the display might be already active skip this */
|
|
|
- if (cmn->ops->is_enabled(dev_priv, cmn) &&
|
|
|
- disp2d->ops->is_enabled(dev_priv, disp2d) &&
|
|
|
+ if (cmn->desc->ops->is_enabled(dev_priv, cmn) &&
|
|
|
+ disp2d->desc->ops->is_enabled(dev_priv, disp2d) &&
|
|
|
I915_READ(DPIO_CTL) & DPIO_CMNRST)
|
|
|
return;
|
|
|
|
|
|
DRM_DEBUG_KMS("toggling display PHY side reset\n");
|
|
|
|
|
|
/* cmnlane needs DPLL registers */
|
|
|
- disp2d->ops->enable(dev_priv, disp2d);
|
|
|
+ disp2d->desc->ops->enable(dev_priv, disp2d);
|
|
|
|
|
|
/*
|
|
|
* From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
|
|
@@ -3525,9 +3712,11 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
|
|
|
* Simply ungating isn't enough to reset the PHY enough to get
|
|
|
* ports and lanes running.
|
|
|
*/
|
|
|
- cmn->ops->disable(dev_priv, cmn);
|
|
|
+ cmn->desc->ops->disable(dev_priv, cmn);
|
|
|
}
|
|
|
|
|
|
+static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
|
|
|
+
|
|
|
/**
|
|
|
* intel_power_domains_init_hw - initialize hardware power domain state
|
|
|
* @dev_priv: i915 device instance
|
|
@@ -3535,9 +3724,14 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
|
|
|
*
|
|
|
* This function initializes the hardware power domain state and enables all
|
|
|
* power wells belonging to the INIT power domain. Power wells in other
|
|
|
- * domains (and not in the INIT domain) are referenced or disabled during the
|
|
|
- * modeset state HW readout. After that the reference count of each power well
|
|
|
- * must match its HW enabled state, see intel_power_domains_verify_state().
|
|
|
+ * domains (and not in the INIT domain) are referenced or disabled by
|
|
|
+ * intel_modeset_readout_hw_state(). After that the reference count of each
|
|
|
+ * power well must match its HW enabled state, see
|
|
|
+ * intel_power_domains_verify_state().
|
|
|
+ *
|
|
|
+ * It will return with power domains disabled (to be enabled later by
|
|
|
+ * intel_power_domains_enable()) and must be paired with
|
|
|
+ * intel_power_domains_fini_hw().
|
|
|
*/
|
|
|
void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
|
|
|
{
|
|
@@ -3563,30 +3757,117 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
|
|
|
mutex_unlock(&power_domains->lock);
|
|
|
}
|
|
|
|
|
|
- /* For now, we need the power well to be always enabled. */
|
|
|
- intel_display_set_init_power(dev_priv, true);
|
|
|
+ /*
|
|
|
+ * Keep all power wells enabled for any dependent HW access during
|
|
|
+ * initialization and to make sure we keep BIOS enabled display HW
|
|
|
+ * resources powered until display HW readout is complete. We drop
|
|
|
+ * this reference in intel_power_domains_enable().
|
|
|
+ */
|
|
|
+ intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
|
|
/* Disable power support if the user asked so. */
|
|
|
if (!i915_modparams.disable_power_well)
|
|
|
intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
|
|
intel_power_domains_sync_hw(dev_priv);
|
|
|
+
|
|
|
power_domains->initializing = false;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * intel_power_domains_fini_hw - deinitialize hw power domain state
|
|
|
+ * @dev_priv: i915 device instance
|
|
|
+ *
|
|
|
+ * De-initializes the display power domain HW state. It also ensures that the
|
|
|
+ * device stays powered up so that the driver can be reloaded.
|
|
|
+ *
|
|
|
+ * It must be called with power domains already disabled (after a call to
|
|
|
+ * intel_power_domains_disable()) and must be paired with
|
|
|
+ * intel_power_domains_init_hw().
|
|
|
+ */
|
|
|
+void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ /* Keep the power well enabled, but cancel its rpm wakeref. */
|
|
|
+ intel_runtime_pm_put(dev_priv);
|
|
|
+
|
|
|
+ /* Remove the refcount we took to keep power well support disabled. */
|
|
|
+ if (!i915_modparams.disable_power_well)
|
|
|
+ intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
|
|
+
|
|
|
+ intel_power_domains_verify_state(dev_priv);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * intel_power_domains_enable - enable toggling of display power wells
|
|
|
+ * @dev_priv: i915 device instance
|
|
|
+ *
|
|
|
+ * Enable the ondemand enabling/disabling of the display power wells. Note that
|
|
|
+ * power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled
|
|
|
+ * only at specific points of the display modeset sequence, thus they are not
|
|
|
+ * affected by the intel_power_domains_enable()/disable() calls. The purpose
|
|
|
+ * of these function is to keep the rest of power wells enabled until the end
|
|
|
+ * of display HW readout (which will acquire the power references reflecting
|
|
|
+ * the current HW state).
|
|
|
+ */
|
|
|
+void intel_power_domains_enable(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
|
|
+
|
|
|
+ intel_power_domains_verify_state(dev_priv);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * intel_power_domains_disable - disable toggling of display power wells
|
|
|
+ * @dev_priv: i915 device instance
|
|
|
+ *
|
|
|
+ * Disable the ondemand enabling/disabling of the display power wells. See
|
|
|
+ * intel_power_domains_enable() for which power wells this call controls.
|
|
|
+ */
|
|
|
+void intel_power_domains_disable(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
|
|
+
|
|
|
+ intel_power_domains_verify_state(dev_priv);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* intel_power_domains_suspend - suspend power domain state
|
|
|
* @dev_priv: i915 device instance
|
|
|
+ * @suspend_mode: specifies the target suspend state (idle, mem, hibernation)
|
|
|
*
|
|
|
* This function prepares the hardware power domain state before entering
|
|
|
- * system suspend. It must be paired with intel_power_domains_init_hw().
|
|
|
+ * system suspend.
|
|
|
+ *
|
|
|
+ * It must be called with power domains already disabled (after a call to
|
|
|
+ * intel_power_domains_disable()) and paired with intel_power_domains_resume().
|
|
|
*/
|
|
|
-void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
|
|
|
+void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
|
|
|
+ enum i915_drm_suspend_mode suspend_mode)
|
|
|
{
|
|
|
+ struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
|
|
+
|
|
|
+ intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
|
|
|
+ * support don't manually deinit the power domains. This also means the
|
|
|
+ * CSR/DMC firmware will stay active, it will power down any HW
|
|
|
+ * resources as required and also enable deeper system power states
|
|
|
+ * that would be blocked if the firmware was inactive.
|
|
|
+ */
|
|
|
+ if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
|
|
|
+ suspend_mode == I915_DRM_SUSPEND_IDLE &&
|
|
|
+ dev_priv->csr.dmc_payload != NULL) {
|
|
|
+ intel_power_domains_verify_state(dev_priv);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Even if power well support was disabled we still want to disable
|
|
|
- * power wells while we are system suspended.
|
|
|
+ * power wells if power domains must be deinitialized for suspend.
|
|
|
*/
|
|
|
- if (!i915_modparams.disable_power_well)
|
|
|
+ if (!i915_modparams.disable_power_well) {
|
|
|
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
|
|
+ intel_power_domains_verify_state(dev_priv);
|
|
|
+ }
|
|
|
|
|
|
if (IS_ICELAKE(dev_priv))
|
|
|
icl_display_core_uninit(dev_priv);
|
|
@@ -3596,8 +3877,36 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
|
|
|
skl_display_core_uninit(dev_priv);
|
|
|
else if (IS_GEN9_LP(dev_priv))
|
|
|
bxt_display_core_uninit(dev_priv);
|
|
|
+
|
|
|
+ power_domains->display_core_suspended = true;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * intel_power_domains_resume - resume power domain state
|
|
|
+ * @dev_priv: i915 device instance
|
|
|
+ *
|
|
|
+ * This function resume the hardware power domain state during system resume.
|
|
|
+ *
|
|
|
+ * It will return with power domain support disabled (to be enabled later by
|
|
|
+ * intel_power_domains_enable()) and must be paired with
|
|
|
+ * intel_power_domains_suspend().
|
|
|
+ */
|
|
|
+void intel_power_domains_resume(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
|
|
+
|
|
|
+ if (power_domains->display_core_suspended) {
|
|
|
+ intel_power_domains_init_hw(dev_priv, true);
|
|
|
+ power_domains->display_core_suspended = false;
|
|
|
+ } else {
|
|
|
+ intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
|
|
+ }
|
|
|
+
|
|
|
+ intel_power_domains_verify_state(dev_priv);
|
|
|
+}
|
|
|
+
|
|
|
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
|
|
|
+
|
|
|
static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
|
@@ -3607,9 +3916,9 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
|
|
|
enum intel_display_power_domain domain;
|
|
|
|
|
|
DRM_DEBUG_DRIVER("%-25s %d\n",
|
|
|
- power_well->name, power_well->count);
|
|
|
+ power_well->desc->name, power_well->count);
|
|
|
|
|
|
- for_each_power_domain(domain, power_well->domains)
|
|
|
+ for_each_power_domain(domain, power_well->desc->domains)
|
|
|
DRM_DEBUG_DRIVER(" %-23s %d\n",
|
|
|
intel_display_power_domain_str(domain),
|
|
|
power_domains->domain_use_count[domain]);
|
|
@@ -3626,7 +3935,7 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
|
|
|
* acquiring reference counts for any power wells in use and disabling the
|
|
|
* ones left on by BIOS but not required by any active output.
|
|
|
*/
|
|
|
-void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
|
|
|
+static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct i915_power_domains *power_domains = &dev_priv->power_domains;
|
|
|
struct i915_power_well *power_well;
|
|
@@ -3645,22 +3954,25 @@ void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
|
|
|
* and PW1 power wells) are under FW control, so ignore them,
|
|
|
* since their state can change asynchronously.
|
|
|
*/
|
|
|
- if (!power_well->domains)
|
|
|
+ if (!power_well->desc->domains)
|
|
|
continue;
|
|
|
|
|
|
- enabled = power_well->ops->is_enabled(dev_priv, power_well);
|
|
|
- if ((power_well->count || power_well->always_on) != enabled)
|
|
|
+ enabled = power_well->desc->ops->is_enabled(dev_priv,
|
|
|
+ power_well);
|
|
|
+ if ((power_well->count || power_well->desc->always_on) !=
|
|
|
+ enabled)
|
|
|
DRM_ERROR("power well %s state mismatch (refcount %d/enabled %d)",
|
|
|
- power_well->name, power_well->count, enabled);
|
|
|
+ power_well->desc->name,
|
|
|
+ power_well->count, enabled);
|
|
|
|
|
|
domains_count = 0;
|
|
|
- for_each_power_domain(domain, power_well->domains)
|
|
|
+ for_each_power_domain(domain, power_well->desc->domains)
|
|
|
domains_count += power_domains->domain_use_count[domain];
|
|
|
|
|
|
if (power_well->count != domains_count) {
|
|
|
DRM_ERROR("power well %s refcount/domain refcount mismatch "
|
|
|
"(refcount %d/domains refcount %d)\n",
|
|
|
- power_well->name, power_well->count,
|
|
|
+ power_well->desc->name, power_well->count,
|
|
|
domains_count);
|
|
|
dump_domain_info = true;
|
|
|
}
|
|
@@ -3678,6 +3990,14 @@ void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
|
|
|
mutex_unlock(&power_domains->lock);
|
|
|
}
|
|
|
|
|
|
+#else
|
|
|
+
|
|
|
+static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
/**
|
|
|
* intel_runtime_pm_get - grab a runtime pm reference
|
|
|
* @dev_priv: i915 device instance
|
|
@@ -3791,14 +4111,24 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
|
|
|
* This function enables runtime pm at the end of the driver load sequence.
|
|
|
*
|
|
|
* Note that this function does currently not enable runtime pm for the
|
|
|
- * subordinate display power domains. That is only done on the first modeset
|
|
|
- * using intel_display_set_init_power().
|
|
|
+ * subordinate display power domains. That is done by
|
|
|
+ * intel_power_domains_enable().
|
|
|
*/
|
|
|
void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
|
|
|
{
|
|
|
struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
struct device *kdev = &pdev->dev;
|
|
|
|
|
|
+ /*
|
|
|
+ * Disable the system suspend direct complete optimization, which can
|
|
|
+ * leave the device suspended skipping the driver's suspend handlers
|
|
|
+ * if the device was already runtime suspended. This is needed due to
|
|
|
+ * the difference in our runtime and system suspend sequence and
|
|
|
+ * becaue the HDA driver may require us to enable the audio power
|
|
|
+ * domain during system suspend.
|
|
|
+ */
|
|
|
+ dev_pm_set_driver_flags(kdev, DPM_FLAG_NEVER_SKIP);
|
|
|
+
|
|
|
pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */
|
|
|
pm_runtime_mark_last_busy(kdev);
|
|
|
|
|
@@ -3825,3 +4155,18 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
|
|
|
*/
|
|
|
pm_runtime_put_autosuspend(kdev);
|
|
|
}
|
|
|
+
|
|
|
+void intel_runtime_pm_disable(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
+ struct device *kdev = &pdev->dev;
|
|
|
+
|
|
|
+ /* Transfer rpm ownership back to core */
|
|
|
+ WARN(pm_runtime_get_sync(&dev_priv->drm.pdev->dev) < 0,
|
|
|
+ "Failed to pass rpm ownership back to core\n");
|
|
|
+
|
|
|
+ pm_runtime_dont_use_autosuspend(kdev);
|
|
|
+
|
|
|
+ if (!HAS_RUNTIME_PM(dev_priv))
|
|
|
+ pm_runtime_put(kdev);
|
|
|
+}
|