|
@@ -1555,6 +1555,49 @@ static void vlv_enable_pll(struct intel_crtc *crtc)
|
|
|
udelay(150); /* wait for warmup */
|
|
|
}
|
|
|
|
|
|
+static void chv_enable_pll(struct intel_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ int pipe = crtc->pipe;
|
|
|
+ enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
|
|
+ int dpll = DPLL(crtc->pipe);
|
|
|
+ u32 tmp;
|
|
|
+
|
|
|
+ assert_pipe_disabled(dev_priv, crtc->pipe);
|
|
|
+
|
|
|
+ BUG_ON(!IS_CHERRYVIEW(dev_priv->dev));
|
|
|
+
|
|
|
+ mutex_lock(&dev_priv->dpio_lock);
|
|
|
+
|
|
|
+ /* Enable back the 10bit clock to display controller */
|
|
|
+ tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
|
|
|
+ tmp |= DPIO_DCLKP_EN;
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), tmp);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Need to wait > 100ns between dclkp clock enable bit and PLL enable.
|
|
|
+ */
|
|
|
+ udelay(1);
|
|
|
+
|
|
|
+ /* Enable PLL */
|
|
|
+ tmp = I915_READ(dpll);
|
|
|
+ tmp |= DPLL_VCO_ENABLE;
|
|
|
+ I915_WRITE(dpll, tmp);
|
|
|
+
|
|
|
+ /* Check PLL is locked */
|
|
|
+ if (wait_for(((I915_READ(dpll) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
|
|
|
+ DRM_ERROR("PLL %d failed to lock\n", pipe);
|
|
|
+
|
|
|
+ /* Deassert soft data lane reset*/
|
|
|
+ tmp = vlv_dpio_read(dev_priv, pipe, VLV_PCS_DW0(port));
|
|
|
+ tmp |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
|
|
|
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), tmp);
|
|
|
+
|
|
|
+
|
|
|
+ mutex_unlock(&dev_priv->dpio_lock);
|
|
|
+}
|
|
|
+
|
|
|
static void i9xx_enable_pll(struct intel_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->base.dev;
|
|
@@ -4470,8 +4513,12 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
|
|
|
|
|
|
is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI);
|
|
|
|
|
|
- if (!is_dsi)
|
|
|
- vlv_enable_pll(intel_crtc);
|
|
|
+ if (!is_dsi) {
|
|
|
+ if (IS_CHERRYVIEW(dev))
|
|
|
+ chv_enable_pll(intel_crtc);
|
|
|
+ else
|
|
|
+ vlv_enable_pll(intel_crtc);
|
|
|
+ }
|
|
|
|
|
|
for_each_encoder_on_crtc(dev, crtc, encoder)
|
|
|
if (encoder->pre_enable)
|
|
@@ -5326,6 +5373,87 @@ static void vlv_update_pll(struct intel_crtc *crtc)
|
|
|
mutex_unlock(&dev_priv->dpio_lock);
|
|
|
}
|
|
|
|
|
|
+static void chv_update_pll(struct intel_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ int pipe = crtc->pipe;
|
|
|
+ int dpll_reg = DPLL(crtc->pipe);
|
|
|
+ enum dpio_channel port = vlv_pipe_to_channel(pipe);
|
|
|
+ u32 val, loopfilter, intcoeff;
|
|
|
+ u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
|
|
|
+ int refclk;
|
|
|
+
|
|
|
+ mutex_lock(&dev_priv->dpio_lock);
|
|
|
+
|
|
|
+ bestn = crtc->config.dpll.n;
|
|
|
+ bestm2_frac = crtc->config.dpll.m2 & 0x3fffff;
|
|
|
+ bestm1 = crtc->config.dpll.m1;
|
|
|
+ bestm2 = crtc->config.dpll.m2 >> 22;
|
|
|
+ bestp1 = crtc->config.dpll.p1;
|
|
|
+ bestp2 = crtc->config.dpll.p2;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Enable Refclk and SSC
|
|
|
+ */
|
|
|
+ val = I915_READ(dpll_reg);
|
|
|
+ val |= (DPLL_SSC_REF_CLOCK_CHV | DPLL_REFA_CLK_ENABLE_VLV);
|
|
|
+ I915_WRITE(dpll_reg, val);
|
|
|
+
|
|
|
+ /* Propagate soft reset to data lane reset */
|
|
|
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS_DW0(port));
|
|
|
+ val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
|
|
|
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), val);
|
|
|
+
|
|
|
+ /* Disable 10bit clock to display controller */
|
|
|
+ val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
|
|
|
+ val &= ~DPIO_DCLKP_EN;
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
|
|
|
+
|
|
|
+ /* p1 and p2 divider */
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW13(port),
|
|
|
+ 5 << DPIO_CHV_S1_DIV_SHIFT |
|
|
|
+ bestp1 << DPIO_CHV_P1_DIV_SHIFT |
|
|
|
+ bestp2 << DPIO_CHV_P2_DIV_SHIFT |
|
|
|
+ 1 << DPIO_CHV_K_DIV_SHIFT);
|
|
|
+
|
|
|
+ /* Feedback post-divider - m2 */
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW0(port), bestm2);
|
|
|
+
|
|
|
+ /* Feedback refclk divider - n and m1 */
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW1(port),
|
|
|
+ DPIO_CHV_M1_DIV_BY_2 |
|
|
|
+ 1 << DPIO_CHV_N_DIV_SHIFT);
|
|
|
+
|
|
|
+ /* M2 fraction division */
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
|
|
|
+
|
|
|
+ /* M2 fraction division enable */
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port),
|
|
|
+ DPIO_CHV_FRAC_DIV_EN |
|
|
|
+ (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT));
|
|
|
+
|
|
|
+ /* Loop filter */
|
|
|
+ refclk = i9xx_get_refclk(&crtc->base, 0);
|
|
|
+ loopfilter = 5 << DPIO_CHV_PROP_COEFF_SHIFT |
|
|
|
+ 2 << DPIO_CHV_GAIN_CTRL_SHIFT;
|
|
|
+ if (refclk == 100000)
|
|
|
+ intcoeff = 11;
|
|
|
+ else if (refclk == 38400)
|
|
|
+ intcoeff = 10;
|
|
|
+ else
|
|
|
+ intcoeff = 9;
|
|
|
+ loopfilter |= intcoeff << DPIO_CHV_INT_COEFF_SHIFT;
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW6(port), loopfilter);
|
|
|
+
|
|
|
+ /* AFC Recal */
|
|
|
+ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port),
|
|
|
+ vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)) |
|
|
|
+ DPIO_AFC_RECAL);
|
|
|
+
|
|
|
+ mutex_unlock(&dev_priv->dpio_lock);
|
|
|
+}
|
|
|
+
|
|
|
static void i9xx_update_pll(struct intel_crtc *crtc,
|
|
|
intel_clock_t *reduced_clock,
|
|
|
int num_connectors)
|
|
@@ -5709,6 +5837,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
i8xx_update_pll(intel_crtc,
|
|
|
has_reduced_clock ? &reduced_clock : NULL,
|
|
|
num_connectors);
|
|
|
+ } else if (IS_CHERRYVIEW(dev)) {
|
|
|
+ chv_update_pll(intel_crtc);
|
|
|
} else if (IS_VALLEYVIEW(dev)) {
|
|
|
vlv_update_pll(intel_crtc);
|
|
|
} else {
|