diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-03-18 09:36:58 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-03-18 09:36:58 -0700 |
commit | 6deb26ae7bd796e88a5dd90df5f6c35fbc44e798 (patch) | |
tree | d4284d9460b7b6d0a4655717b93a81b214b0e930 /src/i830_display.c | |
parent | 7c94227dd4fa2164bebb36234958053bf1d26c12 (diff) |
Create known output configuration at EnterVT time
Since we added the pipe A force quirk (leaving pipe A on all the time),
DPMS calls to disable it have silently returned, leaving the pipe on.
If another driver (like vesafb) has enabled it, we may end up with a bad
configuration, leading to hangs or blank screens at VT switch time.
Fixes bug #19603.
Diffstat (limited to 'src/i830_display.c')
-rw-r--r-- | src/i830_display.c | 226 |
1 files changed, 128 insertions, 98 deletions
diff --git a/src/i830_display.c b/src/i830_display.c index e6fdff97..a44143fd 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1121,14 +1121,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); @@ -1141,112 +1135,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; } |