drm/i915/bxt: Sanitize CDCLK to fix breakage during S4 resume
I noticed that during S4 resume BIOS incorrectly sets bits 18, 19 which are reserved/MBZ and sets the decimal frequency fields to all 0xff in the CDCLK register. The result is a hard lockup as display register accesses are attempted later. Work around this by sanitizing the CDCLK PLL/dividers the same way it's done on SKL. While this is clearly a BIOS bug which should be fixed separately, it doesn't hurt to check/sanitize this regardless. v2: - Use the same condition for VCO and CDCLK in broxton_init_cdclk as is used in skl_init_cdclk for the same purpose. CC: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1464093513-16258-2-git-send-email-imre.deak@intel.com
This commit is contained in:
parent
1c3f7700b2
commit
d66a21947e
|
@ -5491,11 +5491,58 @@ static void broxton_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
|
|||
intel_update_cdclk(dev_priv->dev);
|
||||
}
|
||||
|
||||
void broxton_init_cdclk(struct drm_i915_private *dev_priv)
|
||||
static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 cdctl, expected;
|
||||
|
||||
intel_update_cdclk(dev_priv->dev);
|
||||
|
||||
if (dev_priv->cdclk_pll.vco != 0)
|
||||
if (dev_priv->cdclk_pll.vco == 0 ||
|
||||
dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
|
||||
goto sanitize;
|
||||
|
||||
/* DPLL okay; verify the cdclock
|
||||
*
|
||||
* Some BIOS versions leave an incorrect decimal frequency value and
|
||||
* set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
|
||||
* so sanitize this register.
|
||||
*/
|
||||
cdctl = I915_READ(CDCLK_CTL);
|
||||
/*
|
||||
* Let's ignore the pipe field, since BIOS could have configured the
|
||||
* dividers both synching to an active pipe, or asynchronously
|
||||
* (PIPE_NONE).
|
||||
*/
|
||||
cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
|
||||
|
||||
expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
|
||||
skl_cdclk_decimal(dev_priv->cdclk_freq);
|
||||
/*
|
||||
* Disable SSA Precharge when CD clock frequency < 500 MHz,
|
||||
* enable otherwise.
|
||||
*/
|
||||
if (dev_priv->cdclk_freq >= 500000)
|
||||
expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
|
||||
|
||||
if (cdctl == expected)
|
||||
/* All well; nothing to sanitize */
|
||||
return;
|
||||
|
||||
sanitize:
|
||||
DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
|
||||
|
||||
/* force cdclk programming */
|
||||
dev_priv->cdclk_freq = 0;
|
||||
|
||||
/* force full PLL disable + enable */
|
||||
dev_priv->cdclk_pll.vco = -1;
|
||||
}
|
||||
|
||||
void broxton_init_cdclk(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
bxt_sanitize_cdclk(dev_priv);
|
||||
|
||||
if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue