#define DPLL_CFGCR1(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR1)
#define DPLL_CFGCR2(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR2, _DPLL2_CFGCR2)
+/*
+ * CNL Clocks
+ */
+#define DPCLKA_CFGCR0 _MMIO(0x6C200)
+#define DPCLKA_CFGCR0_DDI_CLK_OFF(port) (1 << ((port)+10))
+#define DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port) (3 << ((port)*2))
+#define DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port) ((port)*2)
+#define DPCLKA_CFGCR0_DDI_CLK_SEL(pll, port) ((pll) << ((port)*2))
+
/* BXT display engine PLL */
#define BXT_DE_PLL_CTL _MMIO(0x6d000)
#define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum port port = intel_ddi_get_encoder_port(encoder);
+ uint32_t val;
if (WARN_ON(!pll))
return;
- if (IS_GEN9_BC(dev_priv)) {
- uint32_t val;
+ if (IS_CANNONLAKE(dev_priv)) {
+ /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */
+ val = I915_READ(DPCLKA_CFGCR0);
+ val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->id, port);
+ I915_WRITE(DPCLKA_CFGCR0, val);
+ /*
+ * Configure DPCLKA_CFGCR0 to turn on the clock for the DDI.
+ * This step and the step before must be done with separate
+ * register writes.
+ */
+ val = I915_READ(DPCLKA_CFGCR0);
+ val &= ~(DPCLKA_CFGCR0_DDI_CLK_OFF(port) |
+ DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port));
+ I915_WRITE(DPCLKA_CFGCR0, val);
+ } else if (IS_GEN9_BC(dev_priv)) {
/* DDI -> PLL mapping */
val = I915_READ(DPLL_CTRL2);
if (dig_port)
intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
- if (IS_GEN9_BC(dev_priv))
+ if (IS_CANNONLAKE(dev_priv))
+ I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |
+ DPCLKA_CFGCR0_DDI_CLK_OFF(port));
+ else if (IS_GEN9_BC(dev_priv))
I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) |
DPLL_CTRL2_DDI_CLK_OFF(port)));
else if (INTEL_GEN(dev_priv) < 9)