diff --git a/src/i830_display.c b/src/i830_display.c index ca55906..21883c4 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -873,14 +873,8 @@ i830_disable_vga_plane (xf86CrtcPtr crtc) } -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void -i830_crtc_dpms(xf86CrtcPtr crtc, int mode) +void +i830_crtc_enable(xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); @@ -893,112 +887,148 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE; uint32_t temp; - /* XXX: When our outputs are all unaware of DPMS modes other than off and - * on, we should map those modes to DPMSModeOff in the CRTC. - */ - switch (mode) { - case DPMSModeOn: - case DPMSModeStandby: - case DPMSModeSuspend: - /* Enable the DPLL */ - temp = INREG(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) == 0) - { - OUTREG(dpll_reg, temp); - POSTING_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - usleep(150); - OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); - POSTING_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - usleep(150); - OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); - POSTING_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - usleep(150); - } + /* Enable the DPLL */ + temp = INREG(dpll_reg); + if ((temp & DPLL_VCO_ENABLE) == 0) + { + OUTREG(dpll_reg, temp); + POSTING_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + usleep(150); + OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); + POSTING_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + usleep(150); + OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); + POSTING_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + usleep(150); + } - /* Enable the pipe */ - temp = INREG(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) == 0) - OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); + /* Enable the pipe */ + temp = INREG(pipeconf_reg); + if ((temp & PIPEACONF_ENABLE) == 0) + OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); - /* Enable the plane */ - temp = INREG(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) == 0) - { - OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - OUTREG(dspbase_reg, INREG(dspbase_reg)); - } + /* Enable the plane */ + temp = INREG(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) == 0) + { + OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + OUTREG(dspbase_reg, INREG(dspbase_reg)); + } - i830_crtc_load_lut(crtc); + i830_crtc_load_lut(crtc); - /* Give the overlay scaler a chance to enable if it's on this pipe */ - i830_crtc_dpms_video(crtc, TRUE); + /* Give the overlay scaler a chance to enable if it's on this pipe */ + i830_crtc_dpms_video(crtc, TRUE); - /* Reenable compression if needed */ - if (i830_use_fb_compression(crtc)) - i830_enable_fb_compression(crtc); - i830_modeset_ctl(crtc, 0); - break; - case DPMSModeOff: - i830_modeset_ctl(crtc, 1); - /* Shut off compression if in use */ - if (i830_use_fb_compression(crtc)) - i830_disable_fb_compression(crtc); + /* Reenable compression if needed */ + if (i830_use_fb_compression(crtc)) + i830_enable_fb_compression(crtc); + i830_modeset_ctl(crtc, 0); +} - /* Give the overlay scaler a chance to disable if it's on this pipe */ - i830_crtc_dpms_video(crtc, FALSE); +void +i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + int plane = intel_crtc->plane; + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; + int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; + int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE; + uint32_t temp; - /* - * The documentation says : - * - Disable planes (VGA or hires) - * - Disable pipe - * - Disable VGA display - */ + i830_modeset_ctl(crtc, 1); + /* Shut off compression if in use */ + if (i830_use_fb_compression(crtc)) + i830_disable_fb_compression(crtc); - /* Disable display plane */ - temp = INREG(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) - { - OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - OUTREG(dspbase_reg, INREG(dspbase_reg)); - POSTING_READ(dspbase_reg); - } + /* Give the overlay scaler a chance to disable if it's on this pipe */ + i830_crtc_dpms_video(crtc, FALSE); - if (!IS_I9XX(pI830)) { - /* Wait for vblank for the disable to take effect */ - i830WaitForVblank(pScrn); - } + /* + * The documentation says : + * - Disable planes (VGA or hires) + * - Disable pipe + * - Disable VGA display + */ - /* May need to leave pipe A on */ - if ((pipe != 0) || !(pI830->quirk_flag & QUIRK_PIPEA_FORCE)) - { - /* Next, disable display pipes */ - temp = INREG(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) != 0) { - OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE); - POSTING_READ(pipeconf_reg); - } + /* Disable display plane */ + temp = INREG(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) != 0) + { + OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + OUTREG(dspbase_reg, INREG(dspbase_reg)); + POSTING_READ(dspbase_reg); + } - /* Wait for vblank for the disable to take effect. */ - i830WaitForVblank(pScrn); + if (!IS_I9XX(pI830)) { + /* Wait for vblank for the disable to take effect */ + i830WaitForVblank(pScrn); + } - temp = INREG(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) != 0) { - OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE); - POSTING_READ(dpll_reg); - } + /* May need to leave pipe A on */ + if (disable_pipe) + { + /* Next, disable display pipes */ + temp = INREG(pipeconf_reg); + if ((temp & PIPEACONF_ENABLE) != 0) { + OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE); + POSTING_READ(pipeconf_reg); + } - /* Wait for the clocks to turn off. */ - usleep(150); + /* Wait for vblank for the disable to take effect. */ + i830WaitForVblank(pScrn); + + temp = INREG(dpll_reg); + if ((temp & DPLL_VCO_ENABLE) != 0) { + OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE); + POSTING_READ(dpll_reg); } - /* Disable the VGA plane that we never use. */ - i830_disable_vga_plane (crtc); + /* Wait for the clocks to turn off. */ + usleep(150); + } + /* Disable the VGA plane that we never use. */ + i830_disable_vga_plane (crtc); +} + +/** + * Sets the power management mode of the pipe and plane. + * + * This code should probably grow support for turning the cursor off and back + * on appropriately at the same time as we're turning the pipe off/on. + */ +static void +i830_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + Bool disable_pipe = TRUE; + + /* XXX: When our outputs are all unaware of DPMS modes other than off and + * on, we should map those modes to DPMSModeOff in the CRTC. + */ + switch (mode) { + case DPMSModeOn: + case DPMSModeStandby: + case DPMSModeSuspend: + i830_crtc_enable(crtc); + break; + case DPMSModeOff: + if ((pipe == 0) && (pI830->quirk_flag & QUIRK_PIPEA_FORCE)) + disable_pipe = FALSE; + i830_crtc_disable(crtc, disable_pipe); break; } diff --git a/src/i830_display.h b/src/i830_display.h index 8d767b1..0ba196d 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -32,6 +32,8 @@ void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y); void i830WaitForVblank(ScrnInfoPtr pScrn); void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); void i830_set_new_crtc_bo(ScrnInfoPtr pScrn); +void i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe); +void i830_crtc_enable(xf86CrtcPtr crtc); xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode); void i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode); diff --git a/src/i830_driver.c b/src/i830_driver.c index c19fcc6..7502d30 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2275,7 +2275,7 @@ RestoreHWState(ScrnInfoPtr pScrn) /* Disable pipes */ for (i = 0; i < xf86_config->num_crtc; i++) { xf86CrtcPtr crtc = xf86_config->crtc[i]; - crtc->funcs->dpms(crtc, DPMSModeOff); + i830_crtc_disable(crtc, TRUE); } i830WaitForVblank(pScrn); @@ -3460,8 +3460,9 @@ static Bool I830EnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); - int ret; + int i, ret; DPRINTF(PFX, "Enter VT\n"); @@ -3482,6 +3483,23 @@ I830EnterVT(int scrnIndex, int flags) SaveHWState(pScrn); } + /* Get the hardware into a known state if needed */ + if (!pI830->use_drm_mode) { + /* Disable outputs */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + output->funcs->dpms(output, DPMSModeOff); + } + i830WaitForVblank(pScrn); + + /* Disable pipes */ + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + i830_crtc_disable(crtc, TRUE); + } + i830WaitForVblank(pScrn); + } + pI830->leaving = FALSE; if (!pI830->use_drm_mode)