staticvoid lpt_compute_iclkip(struct iclkip_params *p, int clock)
{
iclkip_params_init(p);
/* The iCLK virtual clock root frequency is in MHz, * but the adjusted_mode->crtc_clock in KHz. To get the * divisors, it is necessary to divide one by another, so we * convert the virtual clock precision to KHz here for higher * precision.
*/ for (p->auxdiv = 0; p->auxdiv < 2; p->auxdiv++) {
p->desired_divisor = DIV_ROUND_CLOSEST(p->iclk_virtual_root_freq,
clock << p->auxdiv);
p->divsel = (p->desired_divisor / p->iclk_pi_range) - 2;
p->phaseinc = p->desired_divisor % p->iclk_pi_range;
/* * Near 20MHz is a corner case which is * out of range for the 7-bit divisor
*/ if (p->divsel <= 0x7f) break;
}
}
int lpt_iclkip(conststruct intel_crtc_state *crtc_state)
{ struct iclkip_params p;
/* This should not happen with any sane values */
drm_WARN_ON(display->drm, SBI_SSCDIVINTPHASE_DIVSEL(p.divsel) &
~SBI_SSCDIVINTPHASE_DIVSEL_MASK);
drm_WARN_ON(display->drm, SBI_SSCDIVINTPHASE_DIR(p.phasedir) &
~SBI_SSCDIVINTPHASE_INCVAL_MASK);
drm_dbg_kms(display->drm, "iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
clock, p.auxdiv, p.divsel, p.phasedir, p.phaseinc);
/* * Bend CLKOUT_DP * steps -50 to 50 inclusive, in steps of 5 * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz) * change in clock period = -(steps / 10) * 5.787 ps
*/ staticvoid lpt_bend_clkout_dp(struct intel_display *display, int steps)
{
u32 tmp; int idx = BEND_IDX(steps);
if (drm_WARN_ON(display->drm, steps % 5 != 0)) return;
if (drm_WARN_ON(display->drm, idx >= ARRAY_SIZE(sscdivintphase))) return;
/* * The BIOS may have decided to use the PCH SSC * reference so we must not disable it until the * relevant PLLs have stopped relying on it. We'll * just leave the PCH SSC reference enabled in case * any active PLL is using it. It will get disabled * after runtime suspend if we don't have FDI. * * TODO: Move the whole reference clock handling * to the modeset sequence proper so that we can * actually enable/disable/reconfigure these things * safely. To do that we need to introduce a real * clock hierarchy. That would also allow us to do * clock bending finally.
*/
display->dpll.pch_ssc_use = 0;
if (spll_uses_pch_ssc(display)) {
drm_dbg_kms(display->drm, "SPLL using PCH SSC\n");
display->dpll.pch_ssc_use |= BIT(DPLL_ID_SPLL);
}
if (wrpll_uses_pch_ssc(display, DPLL_ID_WRPLL1)) {
drm_dbg_kms(display->drm, "WRPLL1 using PCH SSC\n");
display->dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL1);
}
if (wrpll_uses_pch_ssc(display, DPLL_ID_WRPLL2)) {
drm_dbg_kms(display->drm, "WRPLL2 using PCH SSC\n");
display->dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL2);
}
/* We need to take the global config into account */
for_each_intel_encoder(display->drm, encoder) { switch (encoder->type) { case INTEL_OUTPUT_LVDS:
has_panel = true;
has_lvds = true; break; case INTEL_OUTPUT_EDP:
has_panel = true; if (encoder->port == PORT_A)
has_cpu_edp = true; break; default: break;
}
}
/* Ironlake: try to setup display ref clock before DPLL * enabling. This is only under driver's control after * PCH B stepping, previous chipset stepping should be * ignoring this setting.
*/
val = intel_de_read(display, PCH_DREF_CONTROL);
/* As we must carefully and slowly disable/enable each source in turn, * compute the final state we want first and check if we need to * make any changes at all.
*/
final = val;
final &= ~DREF_NONSPREAD_SOURCE_MASK; if (has_ck505)
final |= DREF_NONSPREAD_CK505_ENABLE; else
final |= DREF_NONSPREAD_SOURCE_ENABLE;
final &= ~DREF_SSC_SOURCE_MASK;
final &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
final &= ~DREF_SSC1_ENABLE;
if (has_panel) {
final |= DREF_SSC_SOURCE_ENABLE;
if (intel_panel_use_ssc(display) && can_ssc)
final |= DREF_SSC1_ENABLE;
if (has_cpu_edp) { if (intel_panel_use_ssc(display) && can_ssc)
final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; else
final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
} else {
final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
}
} elseif (using_ssc_source) {
final |= DREF_SSC_SOURCE_ENABLE;
final |= DREF_SSC1_ENABLE;
}
if (final == val) return;
/* Always enable nonspread source */
val &= ~DREF_NONSPREAD_SOURCE_MASK;
if (has_ck505)
val |= DREF_NONSPREAD_CK505_ENABLE; else
val |= DREF_NONSPREAD_SOURCE_ENABLE;
if (has_panel) {
val &= ~DREF_SSC_SOURCE_MASK;
val |= DREF_SSC_SOURCE_ENABLE;
/* SSC must be turned on before enabling the CPU output */ if (intel_panel_use_ssc(display) && can_ssc) {
drm_dbg_kms(display->drm, "Using SSC on panel\n");
val |= DREF_SSC1_ENABLE;
} else {
val &= ~DREF_SSC1_ENABLE;
}
/* Get SSC going before enabling the outputs */
intel_de_write(display, PCH_DREF_CONTROL, val);
intel_de_posting_read(display, PCH_DREF_CONTROL);
udelay(200);
val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
/* Enable CPU source on CPU attached eDP */ if (has_cpu_edp) { if (intel_panel_use_ssc(display) && can_ssc) {
drm_dbg_kms(display->drm, "Using SSC on eDP\n");
val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
} else {
val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
}
} else {
val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.