diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 604 |
1 files changed, 583 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 68703cecdefc..e6b45cd150d3 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -670,6 +670,111 @@ static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, return (refclk * n * 100) / (p * r); } +static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv, + uint32_t dpll) +{ + uint32_t cfgcr1_reg, cfgcr2_reg; + uint32_t cfgcr1_val, cfgcr2_val; + uint32_t p0, p1, p2, dco_freq; + + cfgcr1_reg = GET_CFG_CR1_REG(dpll); + cfgcr2_reg = GET_CFG_CR2_REG(dpll); + + cfgcr1_val = I915_READ(cfgcr1_reg); + cfgcr2_val = I915_READ(cfgcr2_reg); + + p0 = cfgcr2_val & DPLL_CFGCR2_PDIV_MASK; + p2 = cfgcr2_val & DPLL_CFGCR2_KDIV_MASK; + + if (cfgcr2_val & DPLL_CFGCR2_QDIV_MODE(1)) + p1 = (cfgcr2_val & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8; + else + p1 = 1; + + + switch (p0) { + case DPLL_CFGCR2_PDIV_1: + p0 = 1; + break; + case DPLL_CFGCR2_PDIV_2: + p0 = 2; + break; + case DPLL_CFGCR2_PDIV_3: + p0 = 3; + break; + case DPLL_CFGCR2_PDIV_7: + p0 = 7; + break; + } + + switch (p2) { + case DPLL_CFGCR2_KDIV_5: + p2 = 5; + break; + case DPLL_CFGCR2_KDIV_2: + p2 = 2; + break; + case DPLL_CFGCR2_KDIV_3: + p2 = 3; + break; + case DPLL_CFGCR2_KDIV_1: + p2 = 1; + break; + } + + dco_freq = (cfgcr1_val & DPLL_CFGCR1_DCO_INTEGER_MASK) * 24 * 1000; + + dco_freq += (((cfgcr1_val & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * 24 * + 1000) / 0x8000; + + return dco_freq / (p0 * p1 * p2 * 5); +} + + +static void skl_ddi_clock_get(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + int link_clock = 0; + uint32_t dpll_ctl1, dpll; + + dpll = pipe_config->ddi_pll_sel; + + dpll_ctl1 = I915_READ(DPLL_CTRL1); + + if (dpll_ctl1 & DPLL_CTRL1_HDMI_MODE(dpll)) { + link_clock = skl_calc_wrpll_link(dev_priv, dpll); + } else { + link_clock = dpll_ctl1 & DPLL_CRTL1_LINK_RATE_MASK(dpll); + link_clock >>= DPLL_CRTL1_LINK_RATE_SHIFT(dpll); + + switch (link_clock) { + case DPLL_CRTL1_LINK_RATE_810: + link_clock = 81000; + break; + case DPLL_CRTL1_LINK_RATE_1350: + link_clock = 135000; + break; + case DPLL_CRTL1_LINK_RATE_2700: + link_clock = 270000; + break; + default: + WARN(1, "Unsupported link rate\n"); + break; + } + link_clock *= 2; + } + + pipe_config->port_clock = link_clock; + + if (pipe_config->has_dp_encoder) + pipe_config->adjusted_mode.crtc_clock = + intel_dotclock_calculate(pipe_config->port_clock, + &pipe_config->dp_m_n); + else + pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; +} + static void hsw_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) { @@ -828,6 +933,228 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, return true; } +struct skl_wrpll_params { + uint32_t dco_fraction; + uint32_t dco_integer; + uint32_t qdiv_ratio; + uint32_t qdiv_mode; + uint32_t kdiv; + uint32_t pdiv; + uint32_t central_freq; +}; + +static void +skl_ddi_calculate_wrpll(int clock /* in Hz */, + struct skl_wrpll_params *wrpll_params) +{ + uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */ + uint64_t dco_central_freq[3] = {8400000000ULL, + 9000000000ULL, + 9600000000ULL}; + uint32_t min_dco_deviation = 400; + uint32_t min_dco_index = 3; + uint32_t P0[4] = {1, 2, 3, 7}; + uint32_t P2[4] = {1, 2, 3, 5}; + bool found = false; + uint32_t candidate_p = 0; + uint32_t candidate_p0[3] = {0}, candidate_p1[3] = {0}; + uint32_t candidate_p2[3] = {0}; + uint32_t dco_central_freq_deviation[3]; + uint32_t i, P1, k, dco_count; + bool retry_with_odd = false; + uint64_t dco_freq; + + /* Determine P0, P1 or P2 */ + for (dco_count = 0; dco_count < 3; dco_count++) { + found = false; + candidate_p = + div64_u64(dco_central_freq[dco_count], afe_clock); + if (retry_with_odd == false) + candidate_p = (candidate_p % 2 == 0 ? + candidate_p : candidate_p + 1); + + for (P1 = 1; P1 < candidate_p; P1++) { + for (i = 0; i < 4; i++) { + if (!(P0[i] != 1 || P1 == 1)) + continue; + + for (k = 0; k < 4; k++) { + if (P1 != 1 && P2[k] != 2) + continue; + + if (candidate_p == P0[i] * P1 * P2[k]) { + /* Found possible P0, P1, P2 */ + found = true; + candidate_p0[dco_count] = P0[i]; + candidate_p1[dco_count] = P1; + candidate_p2[dco_count] = P2[k]; + goto found; + } + + } + } + } + +found: + if (found) { + dco_central_freq_deviation[dco_count] = + div64_u64(10000 * + abs_diff((candidate_p * afe_clock), + dco_central_freq[dco_count]), + dco_central_freq[dco_count]); + + if (dco_central_freq_deviation[dco_count] < + min_dco_deviation) { + min_dco_deviation = + dco_central_freq_deviation[dco_count]; + min_dco_index = dco_count; + } + } + + if (min_dco_index > 2 && dco_count == 2) { + retry_with_odd = true; + dco_count = 0; + } + } + + if (min_dco_index > 2) { + WARN(1, "No valid values found for the given pixel clock\n"); + } else { + wrpll_params->central_freq = dco_central_freq[min_dco_index]; + + switch (dco_central_freq[min_dco_index]) { + case 9600000000ULL: + wrpll_params->central_freq = 0; + break; + case 9000000000ULL: + wrpll_params->central_freq = 1; + break; + case 8400000000ULL: + wrpll_params->central_freq = 3; + } + + switch (candidate_p0[min_dco_index]) { + case 1: + wrpll_params->pdiv = 0; + break; + case 2: + wrpll_params->pdiv = 1; + break; + case 3: + wrpll_params->pdiv = 2; + break; + case 7: + wrpll_params->pdiv = 4; + break; + default: + WARN(1, "Incorrect PDiv\n"); + } + + switch (candidate_p2[min_dco_index]) { + case 5: + wrpll_params->kdiv = 0; + break; + case 2: + wrpll_params->kdiv = 1; + break; + case 3: + wrpll_params->kdiv = 2; + break; + case 1: + wrpll_params->kdiv = 3; + break; + default: + WARN(1, "Incorrect KDiv\n"); + } + + wrpll_params->qdiv_ratio = candidate_p1[min_dco_index]; + wrpll_params->qdiv_mode = + (wrpll_params->qdiv_ratio == 1) ? 0 : 1; + + dco_freq = candidate_p0[min_dco_index] * + candidate_p1[min_dco_index] * + candidate_p2[min_dco_index] * afe_clock; + + /* + * Intermediate values are in Hz. + * Divide by MHz to match bsepc + */ + wrpll_params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); + wrpll_params->dco_fraction = + div_u64(((div_u64(dco_freq, 24) - + wrpll_params->dco_integer * MHz(1)) * 0x8000), MHz(1)); + + } +} + + +static bool +skl_ddi_pll_select(struct intel_crtc *intel_crtc, + struct intel_encoder *intel_encoder, + int clock) +{ + struct intel_shared_dpll *pll; + uint32_t ctrl1, cfgcr1, cfgcr2; + + /* + * See comment in intel_dpll_hw_state to understand why we always use 0 + * as the DPLL id in this function. + */ + + ctrl1 = DPLL_CTRL1_OVERRIDE(0); + + if (intel_encoder->type == INTEL_OUTPUT_HDMI) { + struct skl_wrpll_params wrpll_params = { 0, }; + + ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); + + skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params); + + cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | + DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | + wrpll_params.dco_integer; + + cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | + DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) | + DPLL_CFGCR2_KDIV(wrpll_params.kdiv) | + DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | + wrpll_params.central_freq; + } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { + struct drm_encoder *encoder = &intel_encoder->base; + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + switch (intel_dp->link_bw) { + case DP_LINK_BW_1_62: + ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_810, 0); + break; + case DP_LINK_BW_2_7: + ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_1350, 0); + break; + case DP_LINK_BW_5_4: + ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_2700, 0); + break; + } + + cfgcr1 = cfgcr2 = 0; + } else /* eDP */ + return true; + + intel_crtc->new_config->dpll_hw_state.ctrl1 = ctrl1; + intel_crtc->new_config->dpll_hw_state.cfgcr1 = cfgcr1; + intel_crtc->new_config->dpll_hw_state.cfgcr2 = cfgcr2; + + pll = intel_get_shared_dpll(intel_crtc); + if (pll == NULL) { + DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", + pipe_name(intel_crtc->pipe)); + return false; + } + + /* shared DPLL id 0 is DPLL 1 */ + intel_crtc->new_config->ddi_pll_sel = pll->id + 1; + + return true; +} /* * Tries to find a *shared* PLL for the CRTC and store it in @@ -838,11 +1165,15 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, */ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) { + struct drm_device *dev = intel_crtc->base.dev; struct intel_encoder *intel_encoder = intel_ddi_get_crtc_new_encoder(intel_crtc); int clock = intel_crtc->new_config->port_clock; - return hsw_ddi_pll_select(intel_crtc, intel_encoder, clock); + if (IS_SKYLAKE(dev)) + return skl_ddi_pll_select(intel_crtc, intel_encoder, clock); + else + return hsw_ddi_pll_select(intel_crtc, intel_encoder, clock); } void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) @@ -1134,7 +1465,8 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; - struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); enum port port = intel_ddi_get_encoder_port(intel_encoder); int type = intel_encoder->type; @@ -1144,8 +1476,42 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) intel_edp_panel_on(intel_dp); } - WARN_ON(crtc->config.ddi_pll_sel == PORT_CLK_SEL_NONE); - I915_WRITE(PORT_CLK_SEL(port), crtc->config.ddi_pll_sel); + if (IS_SKYLAKE(dev)) { + uint32_t dpll = crtc->config.ddi_pll_sel; + uint32_t val; + + /* + * DPLL0 is used for eDP and is the only "private" DPLL (as + * opposed to shared) on SKL + */ + if (type == INTEL_OUTPUT_EDP) { + WARN_ON(dpll != SKL_DPLL0); + + val = I915_READ(DPLL_CTRL1); + + val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | + DPLL_CTRL1_SSC(dpll) | + DPLL_CRTL1_LINK_RATE_MASK(dpll)); + val |= crtc->config.dpll_hw_state.ctrl1 << (dpll * 6); + + I915_WRITE(DPLL_CTRL1, val); + POSTING_READ(DPLL_CTRL1); + } + + /* DDI -> PLL mapping */ + val = I915_READ(DPLL_CTRL2); + + val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | + DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); + val |= (DPLL_CTRL2_DDI_CLK_SEL(dpll, port) | + DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); + + I915_WRITE(DPLL_CTRL2, val); + + } else { + WARN_ON(crtc->config.ddi_pll_sel == PORT_CLK_SEL_NONE); + I915_WRITE(PORT_CLK_SEL(port), crtc->config.ddi_pll_sel); + } if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -1155,7 +1521,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); - if (port != PORT_A) + if (port != PORT_A || INTEL_INFO(dev)->gen >= 9) intel_dp_stop_link_train(intel_dp); } else if (type == INTEL_OUTPUT_HDMI) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); @@ -1169,7 +1535,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; - struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; enum port port = intel_ddi_get_encoder_port(intel_encoder); int type = intel_encoder->type; uint32_t val; @@ -1197,7 +1564,11 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) intel_edp_panel_off(intel_dp); } - I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); + if (IS_SKYLAKE(dev)) + I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) | + DPLL_CTRL2_DDI_CLK_OFF(port))); + else + I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); } static void intel_enable_ddi(struct intel_encoder *intel_encoder) @@ -1224,11 +1595,11 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder) } else if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - if (port == PORT_A) + if (port == PORT_A && INTEL_INFO(dev)->gen < 9) intel_dp_stop_link_train(intel_dp); intel_edp_backlight_on(intel_dp); - intel_edp_psr_enable(intel_dp); + intel_psr_enable(intel_dp); } if (intel_crtc->config.has_audio) { @@ -1254,11 +1625,59 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - intel_edp_psr_disable(intel_dp); + intel_psr_disable(intel_dp); intel_edp_backlight_off(intel_dp); } } +static int skl_get_cdclk_freq(struct drm_i915_private *dev_priv) +{ + uint32_t lcpll1 = I915_READ(LCPLL1_CTL); + uint32_t cdctl = I915_READ(CDCLK_CTL); + uint32_t linkrate; + + if (!(lcpll1 & LCPLL_PLL_ENABLE)) { + WARN(1, "LCPLL1 not enabled\n"); + return 24000; /* 24MHz is the cd freq with NSSC ref */ + } + + if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) + return 540000; + + linkrate = (I915_READ(DPLL_CTRL1) & + DPLL_CRTL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; + + if (linkrate == DPLL_CRTL1_LINK_RATE_2160 || + linkrate == DPLL_CRTL1_LINK_RATE_1080) { + /* vco 8640 */ + switch (cdctl & CDCLK_FREQ_SEL_MASK) { + case CDCLK_FREQ_450_432: + return 432000; + case CDCLK_FREQ_337_308: + return 308570; + case CDCLK_FREQ_675_617: + return 617140; + default: + WARN(1, "Unknown cd freq selection\n"); + } + } else { + /* vco 8100 */ + switch (cdctl & CDCLK_FREQ_SEL_MASK) { + case CDCLK_FREQ_450_432: + return 450000; + case CDCLK_FREQ_337_308: + return 337500; + case CDCLK_FREQ_675_617: + return 675000; + default: + WARN(1, "Unknown cd freq selection\n"); + } + } + + /* error case, do as if DPLL0 isn't enabled */ + return 24000; +} + static int bdw_get_cdclk_freq(struct drm_i915_private *dev_priv) { uint32_t lcpll = I915_READ(LCPLL_CTL); @@ -1300,6 +1719,9 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; + if (IS_SKYLAKE(dev)) + return skl_get_cdclk_freq(dev_priv); + if (IS_BROADWELL(dev)) return bdw_get_cdclk_freq(dev_priv); @@ -1361,26 +1783,156 @@ static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv) } } +static const char * const skl_ddi_pll_names[] = { + "DPLL 1", + "DPLL 2", + "DPLL 3", +}; + +struct skl_dpll_regs { + u32 ctl, cfgcr1, cfgcr2; +}; + +/* this array is indexed by the *shared* pll id */ +static const struct skl_dpll_regs skl_dpll_regs[3] = { + { + /* DPLL 1 */ + .ctl = LCPLL2_CTL, + .cfgcr1 = DPLL1_CFGCR1, + .cfgcr2 = DPLL1_CFGCR2, + }, + { + /* DPLL 2 */ + .ctl = WRPLL_CTL1, + .cfgcr1 = DPLL2_CFGCR1, + .cfgcr2 = DPLL2_CFGCR2, + }, + { + /* DPLL 3 */ + .ctl = WRPLL_CTL2, + .cfgcr1 = DPLL3_CFGCR1, + .cfgcr2 = DPLL3_CFGCR2, + }, +}; + +static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + uint32_t val; + unsigned int dpll; + const struct skl_dpll_regs *regs = skl_dpll_regs; + + /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ + dpll = pll->id + 1; + + val = I915_READ(DPLL_CTRL1); + + val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) | + DPLL_CRTL1_LINK_RATE_MASK(dpll)); + val |= pll->config.hw_state.ctrl1 << (dpll * 6); + + I915_WRITE(DPLL_CTRL1, val); + POSTING_READ(DPLL_CTRL1); + + I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1); + I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2); + POSTING_READ(regs[pll->id].cfgcr1); + POSTING_READ(regs[pll->id].cfgcr2); + + /* the enable bit is always bit 31 */ + I915_WRITE(regs[pll->id].ctl, + I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE); + + if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5)) + DRM_ERROR("DPLL %d not locked\n", dpll); +} + +static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + const struct skl_dpll_regs *regs = skl_dpll_regs; + + /* the enable bit is always bit 31 */ + I915_WRITE(regs[pll->id].ctl, + I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE); + POSTING_READ(regs[pll->id].ctl); +} + +static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + uint32_t val; + unsigned int dpll; + const struct skl_dpll_regs *regs = skl_dpll_regs; + + if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ + dpll = pll->id + 1; + + val = I915_READ(regs[pll->id].ctl); + if (!(val & LCPLL_PLL_ENABLE)) + return false; + + val = I915_READ(DPLL_CTRL1); + hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f; + + /* avoid reading back stale values if HDMI mode is not enabled */ + if (val & DPLL_CTRL1_HDMI_MODE(dpll)) { + hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); + hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); + } + + return true; +} + +static void skl_shared_dplls_init(struct drm_i915_private *dev_priv) +{ + int i; + + dev_priv->num_shared_dpll = 3; + + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + dev_priv->shared_dplls[i].id = i; + dev_priv->shared_dplls[i].name = skl_ddi_pll_names[i]; + dev_priv->shared_dplls[i].disable = skl_ddi_pll_disable; + dev_priv->shared_dplls[i].enable = skl_ddi_pll_enable; + dev_priv->shared_dplls[i].get_hw_state = + skl_ddi_pll_get_hw_state; + } +} + void intel_ddi_pll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t val = I915_READ(LCPLL_CTL); - hsw_shared_dplls_init(dev_priv); - - /* The LCPLL register should be turned on by the BIOS. For now let's - * just check its state and print errors in case something is wrong. - * Don't even try to turn it on. - */ + if (IS_SKYLAKE(dev)) + skl_shared_dplls_init(dev_priv); + else + hsw_shared_dplls_init(dev_priv); DRM_DEBUG_KMS("CDCLK running at %dKHz\n", intel_ddi_get_cdclk_freq(dev_priv)); - if (val & LCPLL_CD_SOURCE_FCLK) - DRM_ERROR("CDCLK source is not LCPLL\n"); + if (IS_SKYLAKE(dev)) { + if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) + DRM_ERROR("LCPLL1 is disabled\n"); + } else { + /* + * The LCPLL register should be turned on by the BIOS. For now + * let's just check its state and print errors in case + * something is wrong. Don't even try to turn it on. + */ + + if (val & LCPLL_CD_SOURCE_FCLK) + DRM_ERROR("CDCLK source is not LCPLL\n"); - if (val & LCPLL_PLL_DISABLE) - DRM_ERROR("LCPLL is disabled\n"); + if (val & LCPLL_PLL_DISABLE) + DRM_ERROR("LCPLL is disabled\n"); + } } void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) @@ -1475,7 +2027,9 @@ void intel_ddi_get_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; + struct intel_hdmi *intel_hdmi; u32 temp, flags = 0; + struct drm_device *dev = dev_priv->dev; temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) @@ -1509,6 +2063,11 @@ void intel_ddi_get_config(struct intel_encoder *encoder, switch (temp & TRANS_DDI_MODE_SELECT_MASK) { case TRANS_DDI_MODE_SELECT_HDMI: pipe_config->has_hdmi_sink = true; + intel_hdmi = enc_to_intel_hdmi(&encoder->base); + + if (intel_hdmi->infoframe_enabled(&encoder->base)) + pipe_config->has_infoframe = true; + break; case TRANS_DDI_MODE_SELECT_DVI: case TRANS_DDI_MODE_SELECT_FDI: break; @@ -1547,7 +2106,10 @@ void intel_ddi_get_config(struct intel_encoder *encoder, dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; } - hsw_ddi_clock_get(encoder, pipe_config); + if (INTEL_INFO(dev)->gen <= 8) + hsw_ddi_clock_get(encoder, pipe_config); + else + skl_ddi_clock_get(encoder, pipe_config); } static void intel_ddi_destroy(struct drm_encoder *encoder) |