|
@@ -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;
|
|
|
|
|
|
/*
|