Disable display pipes and planes a) before setting X modes and b) before switching back to console -- some chip revisions are not very fond of having their configuration changed while active. Failing to do so may result in a black screen after VT switch in X (e.g. ThinkPad X40) diff --git a/src/i830_driver.c b/src/i830_driver.c index beb134d..2c27c82 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -956,11 +956,66 @@ I830SetupOutputs(ScrnInfoPtr pScrn) } } +/* disable all pipes and associated outputs to bring the card into a defined state */ static void -i830_init_clock_gating(ScrnInfoPtr pScrn) +i830_disable_pipes(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + + uint32_t temp; + int disabled_something=0; + + temp=INREG(DSPACNTR); + if ((temp & DISPLAY_PLANE_ENABLE)!=0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling active display plane A.\n"); + OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + OUTREG(DSPABASE, INREG(DSPABASE)); + POSTING_READ(DSPABASE); + disabled_something=1; + } + + temp=INREG(DSPBCNTR); + if ((temp & DISPLAY_PLANE_ENABLE)!=0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling active display plane B.\n"); + OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + OUTREG(DSPBBASE, INREG(DSPBBASE)); + POSTING_READ(DSPBBASE); + disabled_something=1; + } + if (!IS_I9XX(pI830) && disabled_something) { + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); + } + + disabled_something=0; + + temp=INREG(PIPEACONF); + if ((temp & PIPEACONF_ENABLE)!=0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling active pipe A.\n"); + OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); + POSTING_READ(PIPEACONF); + disabled_something=1; + } + + temp=INREG(PIPEBCONF); + if ((temp & PIPEACONF_ENABLE)!=0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling active pipe B.\n"); + OUTREG(PIPEBCONF, temp & ~PIPEACONF_ENABLE); + POSTING_READ(PIPEBCONF); + disabled_something=1; + } + + if (disabled_something) i830WaitForVblank(pScrn); +} + +static void +i830_init_clock_gating(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + /* Disable clock gating reported to work incorrectly according to the specs. */ if (IS_G4X(pI830)) { @@ -2286,6 +2341,8 @@ RestoreHWState(ScrnInfoPtr pScrn) } i830WaitForVblank(pScrn); + i830_disable_pipes(pScrn); + if (IS_MOBILE(pI830) && !IS_I830(pI830)) OUTREG(LVDS, pI830->saveLVDS); @@ -3655,6 +3712,9 @@ I830EnterVT(int scrnIndex, int flags) /* Tell the BIOS that we're in control of mode setting now. */ i830_init_bios_control(pScrn); + /* Disable any displays and pipes left active by framebuffer console */ + i830_disable_pipes(pScrn); + i830_init_clock_gating(pScrn); if (pI830->power_context)