diff --git a/src/i830_driver.c b/src/i830_driver.c index 7818ee4..e90f091 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2025,6 +2025,24 @@ 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(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); + + /* 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); @@ -2040,6 +2058,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DPLL_A, pI830->saveDPLL_A); usleep(150); + /* Restore mode config */ OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); OUTREG(HBLANK_A, pI830->saveHBLANK_A); OUTREG(HSYNC_A, pI830->saveHSYNC_A); @@ -2058,20 +2077,17 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPASURF, pI830->saveDSPASURF); OUTREG(DSPATILEOFF, pI830->saveDSPATILEOFF); } - /* - * Make sure the DPLL is active and not in VGA mode or the - * write of PIPEnCONF may cause a crash - */ - if ((pI830->saveDPLL_A & DPLL_VCO_ENABLE) && - (pI830->saveDPLL_A & DPLL_VGA_MODE_DIS)) + + /* Make sure the DPLL is active before enabling the pipe & plane */ + if (pI830->saveDPLL_A & DPLL_VCO_ENABLE) { OUTREG(PIPEACONF, pI830->savePIPEACONF); - i830WaitForVblank(pScrn); - OUTREG(DSPACNTR, pI830->saveDSPACNTR); - OUTREG(DSPABASE, INREG(DSPABASE)); - i830WaitForVblank(pScrn); - + i830WaitForVblank(pScrn); + } + + /* See note about pipe programming above */ if(xf86_config->num_crtc == 2) { + /* If the pipe A 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); @@ -2087,6 +2103,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DPLL_B, pI830->saveDPLL_B); usleep(150); + /* Restore mode config */ OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); OUTREG(HBLANK_B, pI830->saveHBLANK_B); OUTREG(HSYNC_B, pI830->saveHSYNC_B); @@ -2108,13 +2125,38 @@ RestoreHWState(ScrnInfoPtr pScrn) /* * See PIPEnCONF note above */ - if ((pI830->saveDPLL_B & DPLL_VCO_ENABLE) && - (pI830->saveDPLL_B & DPLL_VGA_MODE_DIS)) + if (pI830->saveDPLL_B & DPLL_VCO_ENABLE) { OUTREG(PIPEBCONF, pI830->savePIPEBCONF); - i830WaitForVblank(pScrn); - OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); - OUTREG(DSPBBASE, INREG(DSPBBASE)); - i830WaitForVblank(pScrn); + i830WaitForVblank(pScrn); + } + } + + /* If we enabled pipe A, enable its corresponding plane */ + if (pI830->savePIPEACONF & PIPEACONF_ENABLE) { + 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); + } + } + + /* If we enabled pipe B, enable its corresponding plane */ + if (pI830->savePIPEBCONF & PIPEBCONF_ENABLE) { + 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); + } } /* Restore outputs */ @@ -2124,12 +2166,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);