summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_runtime_pm.c
diff options
context:
space:
mode:
authorVille Syrjälä2015-07-08 22:46:00 +0200
committerDaniel Vetter2015-09-01 11:44:41 +0200
commit6669e39f95b5530ca8cb9137703ceb5e83e5d648 (patch)
treed090c4e7f784fbfb3afb3e7a2030437ac85bde82 /drivers/gpu/drm/i915/intel_runtime_pm.c
parentdrm/i915: Clean up CHV lane soft reset programming (diff)
downloadkernel-qcow2-linux-6669e39f95b5530ca8cb9137703ceb5e83e5d648.tar.gz
kernel-qcow2-linux-6669e39f95b5530ca8cb9137703ceb5e83e5d648.tar.xz
kernel-qcow2-linux-6669e39f95b5530ca8cb9137703ceb5e83e5d648.zip
drm/i915: Add some CHV DPIO lane power state asserts
Add some checks that the state of the DPIO lanes is more or less what we expect based on the overrides. The hardware only provides two bits per channel indicating whether all or some of the lanes are powered down, so we can't do an exact check. Additionally, CL2 powering down before we can check it adds another twist. To work around this we simply check for the 0 value of the CL2 register (which is what we get when it's powered down) and adjust our expectations. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Deepak S <deepak.s@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_runtime_pm.c')
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index a0df156ee92e..7991eff01662 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -1042,6 +1042,58 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
phy, dev_priv->chv_phy_control);
}
+static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+ enum dpio_channel ch, bool override, unsigned int mask)
+{
+ enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C;
+ u32 reg, val, expected, actual;
+
+ if (ch == DPIO_CH0)
+ reg = _CHV_CMN_DW0_CH0;
+ else
+ reg = _CHV_CMN_DW6_CH1;
+
+ mutex_lock(&dev_priv->sb_lock);
+ val = vlv_dpio_read(dev_priv, pipe, reg);
+ mutex_unlock(&dev_priv->sb_lock);
+
+ /*
+ * This assumes !override is only used when the port is disabled.
+ * All lanes should power down even without the override when
+ * the port is disabled.
+ */
+ if (!override || mask == 0xf) {
+ expected = DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
+ /*
+ * If CH1 common lane is not active anymore
+ * (eg. for pipe B DPLL) the entire channel will
+ * shut down, which causes the common lane registers
+ * to read as 0. That means we can't actually check
+ * the lane power down status bits, but as the entire
+ * register reads as 0 it's a good indication that the
+ * channel is indeed entirely powered down.
+ */
+ if (ch == DPIO_CH1 && val == 0)
+ expected = 0;
+ } else if (mask != 0x0) {
+ expected = DPIO_ANYDL_POWERDOWN;
+ } else {
+ expected = 0;
+ }
+
+ if (ch == DPIO_CH0)
+ actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH0;
+ else
+ actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH1;
+ actual &= DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
+
+ WARN(actual != expected,
+ "Unexpected DPIO lane power down: all %d, any %d. Expected: all %d, any %d. (0x%x = 0x%08x)\n",
+ !!(actual & DPIO_ALLDL_POWERDOWN), !!(actual & DPIO_ANYDL_POWERDOWN),
+ !!(expected & DPIO_ALLDL_POWERDOWN), !!(expected & DPIO_ANYDL_POWERDOWN),
+ reg, val);
+}
+
bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
enum dpio_channel ch, bool override)
{
@@ -1094,6 +1146,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
phy, ch, mask, dev_priv->chv_phy_control);
+ assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
+
mutex_unlock(&power_domains->lock);
}