Commit 3be60de9 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter

drm/i915: Skip CHV PHY asserts until PHY has been fully reset

The BIOS can leave the CHV display PHY in some odd state where
some of the LDOs/lanes won't power down fully when unused. This
will trigger a host of asserts that were added in:
30142273 drm/i915: Add CHV PHY LDO power sanity checks
6669e39f drm/i915: Add some CHV DPIO lane power state asserts

To avoid that, skip the asserts until the PHY power well has been
disabled at least once. That will fully reset the PHY, and once
brought back up, the dynamic power down features will work correctly.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Deepak S<deepak.s@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 9571b190
...@@ -1953,6 +1953,9 @@ struct drm_i915_private { ...@@ -1953,6 +1953,9 @@ struct drm_i915_private {
bool edp_low_vswing; bool edp_low_vswing;
/* perform PHY state sanity checks? */
bool chv_phy_assert[2];
/* /*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place. * will be rejected. Instead look for a better place.
......
...@@ -993,8 +993,29 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv) ...@@ -993,8 +993,29 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D); lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
u32 phy_control = dev_priv->chv_phy_control; u32 phy_control = dev_priv->chv_phy_control;
u32 phy_status = 0; u32 phy_status = 0;
u32 phy_status_mask = 0xffffffff;
u32 tmp; u32 tmp;
/*
* The BIOS can leave the PHY is some weird state
* where it doesn't fully power down some parts.
* Disable the asserts until the PHY has been fully
* reset (ie. the power well has been disabled at
* least once).
*/
if (!dev_priv->chv_phy_assert[DPIO_PHY0])
phy_status_mask &= ~(PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1) |
PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0) |
PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1));
if (!dev_priv->chv_phy_assert[DPIO_PHY1])
phy_status_mask &= ~(PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0) |
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->ops->is_enabled(dev_priv, cmn_bc)) {
phy_status |= PHY_POWERGOOD(DPIO_PHY0); phy_status |= PHY_POWERGOOD(DPIO_PHY0);
...@@ -1055,11 +1076,13 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv) ...@@ -1055,11 +1076,13 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1); phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1);
} }
phy_status &= phy_status_mask;
/* /*
* The PHY may be busy with some initial calibration and whatnot, * The PHY may be busy with some initial calibration and whatnot,
* so the power state can take a while to actually change. * so the power state can take a while to actually change.
*/ */
if (wait_for((tmp = I915_READ(DISPLAY_PHY_STATUS)) == phy_status, 10)) if (wait_for((tmp = I915_READ(DISPLAY_PHY_STATUS) & phy_status_mask) == phy_status, 10))
WARN(phy_status != tmp, WARN(phy_status != tmp,
"Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n", "Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n",
tmp, phy_status, dev_priv->chv_phy_control); tmp, phy_status, dev_priv->chv_phy_control);
...@@ -1152,6 +1175,9 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, ...@@ -1152,6 +1175,9 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n", DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
phy, dev_priv->chv_phy_control); phy, dev_priv->chv_phy_control);
/* PHY is fully reset now, so we can enable the PHY state asserts */
dev_priv->chv_phy_assert[phy] = true;
assert_chv_phy_status(dev_priv); assert_chv_phy_status(dev_priv);
} }
...@@ -1161,6 +1187,16 @@ static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpi ...@@ -1161,6 +1187,16 @@ static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpi
enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C; enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C;
u32 reg, val, expected, actual; u32 reg, val, expected, actual;
/*
* The BIOS can leave the PHY is some weird state
* where it doesn't fully power down some parts.
* Disable the asserts until the PHY has been fully
* reset (ie. the power well has been disabled at
* least once).
*/
if (!dev_priv->chv_phy_assert[phy])
return;
if (ch == DPIO_CH0) if (ch == DPIO_CH0)
reg = _CHV_CMN_DW0_CH0; reg = _CHV_CMN_DW0_CH0;
else else
...@@ -1916,6 +1952,10 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv) ...@@ -1916,6 +1952,10 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1); PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1);
dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0); dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0);
dev_priv->chv_phy_assert[DPIO_PHY0] = false;
} else {
dev_priv->chv_phy_assert[DPIO_PHY0] = true;
} }
if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) { if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
...@@ -1934,6 +1974,10 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv) ...@@ -1934,6 +1974,10 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0); PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0);
dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1); dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1);
dev_priv->chv_phy_assert[DPIO_PHY1] = false;
} else {
dev_priv->chv_phy_assert[DPIO_PHY1] = true;
} }
I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control); I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment