summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-03-18 09:36:58 -0700
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-03-18 09:36:58 -0700
commit6deb26ae7bd796e88a5dd90df5f6c35fbc44e798 (patch)
treed4284d9460b7b6d0a4655717b93a81b214b0e930
parent7c94227dd4fa2164bebb36234958053bf1d26c12 (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.
-rw-r--r--src/i830_display.c226
-rw-r--r--src/i830_display.h2
-rw-r--r--src/i830_driver.c22
3 files changed, 150 insertions, 100 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;
}
diff --git a/src/i830_display.h b/src/i830_display.h
index 8d767b10..0ba196d3 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 c19fcc63..7502d301 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)