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 commite19c1eb885
) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
parent
2ba7d7e043
commit
7130013297
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue