drm/i915: Fix DDI PHY init if it was already on

The common lane power down flag of a DPIO PHY has a funky semantic:
after the initial enabling of the PHY (so from a disabled state) this
flag will be clear. It will be set only after the PHY will be used for
the first time (for instance due to enabling the corresponding pipe) and
then become unused (due to disabling the pipe). During the initial PHY
enablement we don't know which of the above phases we are in, so move
the check for the flag where this is known, the HW readout code. This is
where the rest of lane power down status checks are done anyway.

This fixes at least a problem on GLK where after module reloading, the
common lane power down flag of PHY1 is set, but the PHY is actually
powered-on and properly set up. The GRC readout code for other PHYs will
hence think that PHY1 is not powered initially and disable it after the
GRC readout. This will cause the AUX power well related to PHY1 to get
disabled in a stuck state, timing out when we try to enable it later.

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Fixes: e93da0a013 ("drm/i915/bxt: Sanitiy check the PHY lane power down status")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102777
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171002135307.26117-1-imre.deak@intel.com
(cherry picked from commit e19c1eb885)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
Imre Deak 2017-10-02 16:53:07 +03:00 committed by Rodrigo Vivi
parent 2ba7d7e043
commit 7130013297
2 changed files with 2 additions and 21 deletions

View File

@ -1655,7 +1655,8 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
out: out:
if (ret && IS_GEN9_LP(dev_priv)) { if (ret && IS_GEN9_LP(dev_priv)) {
tmp = I915_READ(BXT_PHY_CTL(port)); tmp = I915_READ(BXT_PHY_CTL(port));
if ((tmp & (BXT_PHY_LANE_POWERDOWN_ACK | if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK |
BXT_PHY_LANE_POWERDOWN_ACK |
BXT_PHY_LANE_ENABLED)) != BXT_PHY_LANE_ENABLED) BXT_PHY_LANE_ENABLED)) != BXT_PHY_LANE_ENABLED)
DRM_ERROR("Port %c enabled but PHY powered down? " DRM_ERROR("Port %c enabled but PHY powered down? "
"(PHY_CTL %08x)\n", port_name(port), tmp); "(PHY_CTL %08x)\n", port_name(port), tmp);

View File

@ -208,12 +208,6 @@ static const struct bxt_ddi_phy_info glk_ddi_phy_info[] = {
}, },
}; };
static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info)
{
return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) |
BIT(phy_info->channel[DPIO_CH0].port);
}
static const struct bxt_ddi_phy_info * static const struct bxt_ddi_phy_info *
bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count) bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count)
{ {
@ -313,7 +307,6 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
enum dpio_phy phy) enum dpio_phy phy)
{ {
const struct bxt_ddi_phy_info *phy_info; const struct bxt_ddi_phy_info *phy_info;
enum port port;
phy_info = bxt_get_phy_info(dev_priv, phy); phy_info = bxt_get_phy_info(dev_priv, phy);
@ -335,19 +328,6 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
return false; return false;
} }
for_each_port_masked(port, bxt_phy_port_mask(phy_info)) {
u32 tmp = I915_READ(BXT_PHY_CTL(port));
if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) {
DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane "
"for port %c powered down "
"(PHY_CTL %08x)\n",
phy, port_name(port), tmp);
return false;
}
}
return true; return true;
} }