Unconditionally restore pipe configuration

This is a partial fix for #13196, which covers both leaving pipes disabled at
server exit time and problems with restoring the pipe configuration on certain
chipsets.  It restores the pipe configuration unconditionally (previously we
made sure the PLL was running and we weren't in VGA mode) but also adds some
additional PLL settle time to the PLL register write paths.
This commit is contained in:
Jesse Barnes 2007-12-18 18:10:33 -08:00
parent 4757a218d7
commit f69b48fe24
1 changed files with 69 additions and 28 deletions

View File

@ -1991,6 +1991,13 @@ SaveHWState(ScrnInfoPtr pScrn)
return TRUE;
}
/* Wait for the PLL to settle down after programming */
static void
i830_dpll_settle(void)
{
usleep(10000); /* 10 ms *should* be plenty */
}
static Bool
RestoreHWState(ScrnInfoPtr pScrn)
{
@ -2025,6 +2032,23 @@ RestoreHWState(ScrnInfoPtr pScrn)
if (!IS_I830(pI830) && !IS_845G(pI830))
OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
/*
* Pipe regs
* To restore the saved state, we first need to program the PLL regs,
* followed by the pipe configuration and finally the display plane
* configuration. The VGA registers can program one, both or neither
* of the PLL regs, depending on their VGA_MOD_DIS bit value.
*/
/*
* Since either or both pipes may use the VGA clocks, make sure the
* regs are valid.
*/
OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
/* If the pipe A PLL is active, we can restore the pipe & plane config */
if (pI830->saveDPLL_A & DPLL_VCO_ENABLE)
{
OUTREG(DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE);
@ -2033,13 +2057,14 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(FPA0, pI830->saveFPA0);
OUTREG(FPA1, pI830->saveFPA1);
OUTREG(DPLL_A, pI830->saveDPLL_A);
usleep(150);
i830_dpll_settle();
if (IS_I965G(pI830))
OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
else
OUTREG(DPLL_A, pI830->saveDPLL_A);
usleep(150);
i830_dpll_settle();
/* Restore mode config */
OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
OUTREG(HBLANK_A, pI830->saveHBLANK_A);
OUTREG(HSYNC_A, pI830->saveHSYNC_A);
@ -2058,20 +2083,31 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(DSPASURF, pI830->saveDSPASURF);
OUTREG(DSPATILEOFF, pI830->saveDSPATILEOFF);
}
OUTREG(PIPEACONF, pI830->savePIPEACONF);
i830WaitForVblank(pScrn);
/*
* Make sure the DPLL is active and not in VGA mode or the
* write of PIPEnCONF may cause a crash
* Program Pipe A's plane
* The corresponding display plane may be disabled, and should only be
* enabled if pipe A is actually on (otherwise we have a bug in the initial
* state).
*/
if ((pI830->saveDPLL_A & DPLL_VCO_ENABLE) &&
(pI830->saveDPLL_A & DPLL_VGA_MODE_DIS))
OUTREG(PIPEACONF, pI830->savePIPEACONF);
i830WaitForVblank(pScrn);
OUTREG(DSPACNTR, pI830->saveDSPACNTR);
OUTREG(DSPABASE, INREG(DSPABASE));
i830WaitForVblank(pScrn);
if (pI830->saveDSPACNTR & DISPPLANE_SEL_PIPE_A) {
OUTREG(DSPACNTR, pI830->saveDSPACNTR);
OUTREG(DSPABASE, INREG(DSPABASE));
i830WaitForVblank(pScrn);
}
if (pI830->saveDSPBCNTR & DISPPLANE_SEL_PIPE_A) {
OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
OUTREG(DSPBBASE, INREG(DSPBBASE));
i830WaitForVblank(pScrn);
}
/* See note about pipe programming above */
if(xf86_config->num_crtc == 2)
{
/* If the pipe B PLL is active, we can restore the pipe & plane config */
if (pI830->saveDPLL_B & DPLL_VCO_ENABLE)
{
OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE);
@ -2080,13 +2116,14 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(FPB0, pI830->saveFPB0);
OUTREG(FPB1, pI830->saveFPB1);
OUTREG(DPLL_B, pI830->saveDPLL_B);
usleep(150);
i830_dpll_settle();
if (IS_I965G(pI830))
OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
else
OUTREG(DPLL_B, pI830->saveDPLL_B);
usleep(150);
i830_dpll_settle();
/* Restore mode config */
OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
OUTREG(HBLANK_B, pI830->saveHBLANK_B);
OUTREG(HSYNC_B, pI830->saveHSYNC_B);
@ -2105,18 +2142,28 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(DSPBTILEOFF, pI830->saveDSPBTILEOFF);
}
OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
i830WaitForVblank(pScrn);
/*
* See PIPEnCONF note above
* Program Pipe B's plane
* Note that pipe B may be disabled, and in that case, the plane
* should also be disabled or we must have had a bad initial state.
*/
if ((pI830->saveDPLL_B & DPLL_VCO_ENABLE) &&
(pI830->saveDPLL_B & DPLL_VGA_MODE_DIS))
OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
i830WaitForVblank(pScrn);
OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
OUTREG(DSPBBASE, INREG(DSPBBASE));
i830WaitForVblank(pScrn);
if (pI830->saveDSPACNTR & DISPPLANE_SEL_PIPE_B) {
OUTREG(DSPACNTR, pI830->saveDSPACNTR);
OUTREG(DSPABASE, INREG(DSPABASE));
i830WaitForVblank(pScrn);
}
if (pI830->saveDSPBCNTR & DISPPLANE_SEL_PIPE_B) {
OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
OUTREG(DSPBBASE, INREG(DSPBBASE));
i830WaitForVblank(pScrn);
}
}
OUTREG(VGACNTRL, pI830->saveVGACNTRL);
/* Restore outputs */
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
@ -2124,12 +2171,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
output->funcs->restore(output);
}
OUTREG(VGACNTRL, pI830->saveVGACNTRL);
OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);
OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1);
OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV);
i830_restore_palette(pI830, PIPE_A);
i830_restore_palette(pI830, PIPE_B);