aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_runtime_pm.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-03-01 14:07:22 +1000
committerDave Airlie <airlied@redhat.com>2018-03-01 14:07:22 +1000
commitf073d78eeb8efd85718e611c15f9a78647751dea (patch)
tree7ae17810b85416c173fac5bb52f3b7575d969f14 /drivers/gpu/drm/i915/intel_runtime_pm.c
parent0feeb106c79532074b370c3cb45f742ef4302cc6 (diff)
parentfed8165851e262575585b22055ff5dba7d91b0e5 (diff)
downloadkernel_replicant_linux-f073d78eeb8efd85718e611c15f9a78647751dea.tar.gz
kernel_replicant_linux-f073d78eeb8efd85718e611c15f9a78647751dea.tar.bz2
kernel_replicant_linux-f073d78eeb8efd85718e611c15f9a78647751dea.zip
Merge tag 'drm-intel-next-2018-02-21' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
Driver Changes: - Lift alpha_support protection from Cannonlake (Rodrigo) * Meaning the driver should mostly work for the hardware we had at our disposal when testing * Used to be preliminary_hw_support - Add missing Cannonlake PCI device ID of 0x5A4C (Rodrigo) - Cannonlake port register fix (Mahesh) - Fix Dell Venue 8 Pro black screen after modeset (Hans) - Fix for always returning zero out-fence from execbuf (Daniele) - Fix HDMI audio when no no relevant video output is active (Jani) - Fix memleak of VBT data on driver_unload (Hans) - Fix for KASAN found locking issue (Maarten) - RCU barrier consolidation to improve igt/gem_sync/idle (Chris) - Optimizations to IRQ handlers (Chris) - vblank tracking improvements (64-bit resolution, PM) (Dhinakaran) - Pipe select bit corrections (Ville) - Reduce runtime computed device_info fields (Chris) - Tune down some WARN_ONs to GEM_BUG_ON now that CI has good coverage (Chris) - A bunch of kerneldoc warning fixes (Chris) * tag 'drm-intel-next-2018-02-21' of git://anongit.freedesktop.org/drm/drm-intel: (113 commits) drm/i915: Update DRIVER_DATE to 20180221 drm/i915/fbc: Use PLANE_HAS_FENCE to determine if the plane is fenced drm/i915/fbdev: Use the PLANE_HAS_FENCE flags from the time of pinning drm/i915: Move the policy for placement of the GGTT vma into the caller drm/i915: Also check view->type for a normal GGTT view drm/i915: Drop WaDoubleCursorLP3Latency:ivb drm/i915: Set the primary plane pipe select bits on gen4 drm/i915: Don't set cursor pipe select bits on g4x+ drm/i915: Assert that we don't overflow frontbuffer tracking bits drm/i915: Track number of pending freed objects drm/i915/: Initialise trans_min for skl_compute_transition_wm() drm/i915: Clear the in-use marker on execbuf failure drm/i915: Prune gen8_gt_irq_handler drm/i915: Track GT interrupt handling using the master iir drm/i915: Remove WARN_ONCE for failing to pm_runtime_if_in_use drm: intel_dpio_phy: fix kernel-doc comments at nested struct drm/i915: Release connector iterator on a digital port conflict. drm/i915/execlists: Remove too early assert drm/i915: Assert that we always complete a submission to guc/execlists drm: move read_domains and write_domain into i915 ...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_runtime_pm.c')
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c161
1 files changed, 144 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 70e659772a7a..b7924feb9f27 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -2646,6 +2646,48 @@ static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
DRM_ERROR("DBuf power disable timeout!\n");
}
+/*
+ * TODO: we shouldn't always enable DBUF_CTL_S2, we should only enable it when
+ * needed and keep it disabled as much as possible.
+ */
+static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
+{
+ I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST);
+ I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) | DBUF_POWER_REQUEST);
+ POSTING_READ(DBUF_CTL_S2);
+
+ udelay(10);
+
+ if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
+ !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
+ DRM_ERROR("DBuf power enable timeout\n");
+}
+
+static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
+{
+ I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) & ~DBUF_POWER_REQUEST);
+ I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) & ~DBUF_POWER_REQUEST);
+ POSTING_READ(DBUF_CTL_S2);
+
+ udelay(10);
+
+ if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
+ (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
+ DRM_ERROR("DBuf power disable timeout!\n");
+}
+
+static void icl_mbus_init(struct drm_i915_private *dev_priv)
+{
+ uint32_t val;
+
+ val = MBUS_ABOX_BT_CREDIT_POOL1(16) |
+ MBUS_ABOX_BT_CREDIT_POOL2(16) |
+ MBUS_ABOX_B_CREDIT(1) |
+ MBUS_ABOX_BW_CREDIT(1);
+
+ I915_WRITE(MBUS_ABOX_CTL, val);
+}
+
static void skl_display_core_init(struct drm_i915_private *dev_priv,
bool resume)
{
@@ -2794,12 +2836,19 @@ static const struct cnl_procmon {
{ .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, },
};
-static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv)
+/*
+ * CNL has just one set of registers, while ICL has two sets: one for port A and
+ * the other for port B. The CNL registers are equivalent to the ICL port A
+ * registers, that's why we call the ICL macros even though the function has CNL
+ * on its name.
+ */
+static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv,
+ enum port port)
{
const struct cnl_procmon *procmon;
u32 val;
- val = I915_READ(CNL_PORT_COMP_DW3);
+ val = I915_READ(ICL_PORT_COMP_DW3(port));
switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) {
default:
MISSING_CASE(val);
@@ -2820,13 +2869,13 @@ static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv)
break;
}
- val = I915_READ(CNL_PORT_COMP_DW1);
+ val = I915_READ(ICL_PORT_COMP_DW1(port));
val &= ~((0xff << 16) | 0xff);
val |= procmon->dw1;
- I915_WRITE(CNL_PORT_COMP_DW1, val);
+ I915_WRITE(ICL_PORT_COMP_DW1(port), val);
- I915_WRITE(CNL_PORT_COMP_DW9, procmon->dw9);
- I915_WRITE(CNL_PORT_COMP_DW10, procmon->dw10);
+ I915_WRITE(ICL_PORT_COMP_DW9(port), procmon->dw9);
+ I915_WRITE(ICL_PORT_COMP_DW10(port), procmon->dw10);
}
static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume)
@@ -2847,7 +2896,8 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume
val &= ~CNL_COMP_PWR_DOWN;
I915_WRITE(CHICKEN_MISC_2, val);
- cnl_set_procmon_ref_values(dev_priv);
+ /* Dummy PORT_A to get the correct CNL register from the ICL macro */
+ cnl_set_procmon_ref_values(dev_priv, PORT_A);
val = I915_READ(CNL_PORT_COMP_DW0);
val |= COMP_INIT;
@@ -2911,6 +2961,80 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv)
I915_WRITE(CHICKEN_MISC_2, val);
}
+static void icl_display_core_init(struct drm_i915_private *dev_priv,
+ bool resume)
+{
+ enum port port;
+ u32 val;
+
+ gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+ /* 1. Enable PCH reset handshake. */
+ val = I915_READ(HSW_NDE_RSTWRN_OPT);
+ val |= RESET_PCH_HANDSHAKE_ENABLE;
+ I915_WRITE(HSW_NDE_RSTWRN_OPT, val);
+
+ for (port = PORT_A; port <= PORT_B; port++) {
+ /* 2. Enable DDI combo PHY comp. */
+ val = I915_READ(ICL_PHY_MISC(port));
+ val &= ~ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN;
+ I915_WRITE(ICL_PHY_MISC(port), val);
+
+ cnl_set_procmon_ref_values(dev_priv, port);
+
+ val = I915_READ(ICL_PORT_COMP_DW0(port));
+ val |= COMP_INIT;
+ I915_WRITE(ICL_PORT_COMP_DW0(port), val);
+
+ /* 3. Set power down enable. */
+ val = I915_READ(ICL_PORT_CL_DW5(port));
+ val |= CL_POWER_DOWN_ENABLE;
+ I915_WRITE(ICL_PORT_CL_DW5(port), val);
+ }
+
+ /* 4. Enable power well 1 (PG1) and aux IO power. */
+ /* FIXME: ICL power wells code not here yet. */
+
+ /* 5. Enable CDCLK. */
+ icl_init_cdclk(dev_priv);
+
+ /* 6. Enable DBUF. */
+ icl_dbuf_enable(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)
+{
+ enum port port;
+ u32 val;
+
+ gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+ /* 1. Disable all display engine functions -> aready done */
+
+ /* 2. Disable DBUF */
+ icl_dbuf_disable(dev_priv);
+
+ /* 3. Disable CD clock */
+ icl_uninit_cdclk(dev_priv);
+
+ /* 4. Disable Power Well 1 (PG1) and Aux IO Power */
+ /* FIXME: ICL power wells code not here yet. */
+
+ /* 5. Disable Comp */
+ for (port = PORT_A; port <= PORT_B; port++) {
+ val = I915_READ(ICL_PHY_MISC(port));
+ val |= ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN;
+ I915_WRITE(ICL_PHY_MISC(port), val);
+ }
+}
+
static void chv_phy_control_init(struct drm_i915_private *dev_priv)
{
struct i915_power_well *cmn_bc =
@@ -3043,7 +3167,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
power_domains->initializing = true;
- if (IS_CANNONLAKE(dev_priv)) {
+ if (IS_ICELAKE(dev_priv)) {
+ icl_display_core_init(dev_priv, resume);
+ } else if (IS_CANNONLAKE(dev_priv)) {
cnl_display_core_init(dev_priv, resume);
} else if (IS_GEN9_BC(dev_priv)) {
skl_display_core_init(dev_priv, resume);
@@ -3084,7 +3210,9 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
if (!i915_modparams.disable_power_well)
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
- if (IS_CANNONLAKE(dev_priv))
+ if (IS_ICELAKE(dev_priv))
+ icl_display_core_uninit(dev_priv);
+ else if (IS_CANNONLAKE(dev_priv))
cnl_display_core_uninit(dev_priv);
else if (IS_GEN9_BC(dev_priv))
skl_display_core_uninit(dev_priv);
@@ -3200,18 +3328,19 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
* @dev_priv: i915 device instance
*
* This function grabs a device-level runtime pm reference if the device is
- * already in use and ensures that it is powered up.
+ * already in use and ensures that it is powered up. It is illegal to try
+ * and access the HW should intel_runtime_pm_get_if_in_use() report failure.
*
* Any runtime pm reference obtained by this function must have a symmetric
* call to intel_runtime_pm_put() to release the reference again.
+ *
+ * Returns: True if the wakeref was acquired, or False otherwise.
*/
bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
{
- struct pci_dev *pdev = dev_priv->drm.pdev;
- struct device *kdev = &pdev->dev;
-
if (IS_ENABLED(CONFIG_PM)) {
- int ret = pm_runtime_get_if_in_use(kdev);
+ struct pci_dev *pdev = dev_priv->drm.pdev;
+ struct device *kdev = &pdev->dev;
/*
* In cases runtime PM is disabled by the RPM core and we get
@@ -3219,9 +3348,7 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
* function, since the power state is undefined. This applies
* atm to the late/early system suspend/resume handlers.
*/
- WARN_ONCE(ret < 0,
- "pm_runtime_get_if_in_use() failed: %d\n", ret);
- if (ret <= 0)
+ if (pm_runtime_get_if_in_use(kdev) <= 0)
return false;
}