xf86-video-intel: src/i830_display.c src/i830_display.h src/i830_driver.c

Jesse Barnes jbarnes at kemper.freedesktop.org
Wed Mar 18 09:40:31 PDT 2009


 src/i830_display.c |  226 ++++++++++++++++++++++++++++++-----------------------
 src/i830_display.h |    2 
 src/i830_driver.c  |   22 ++++-
 3 files changed, 150 insertions(+), 100 deletions(-)

New commits:
commit 6deb26ae7bd796e88a5dd90df5f6c35fbc44e798
Author: Jesse Barnes <jbarnes at virtuousgeek.org>
Date:   Wed Mar 18 09:36:58 2009 -0700

    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.

diff --git a/src/i830_display.c b/src/i830_display.c
index e6fdff9..a44143f 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 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)


More information about the xorg-commit mailing list