xf86-video-intel: Branch 'modesetting' - 6 commits - src/i830_crt.c src/i830_display.c src/i830_display.h src/i830_driver.c src/i830.h src/i830_randr.c src/i830_xf86Modes.c

Eric Anholt anholt at kemper.freedesktop.org
Sat Nov 4 02:46:56 EET 2006


 src/i830.h           |    5 +
 src/i830_crt.c       |   20 +++----
 src/i830_display.c   |  138 ++++++++++++++++++++++++++++++++++++++++++++++++---
 src/i830_display.h   |    5 +
 src/i830_driver.c    |    4 -
 src/i830_randr.c     |    3 -
 src/i830_xf86Modes.c |    2 
 7 files changed, 153 insertions(+), 24 deletions(-)

New commits:
diff-tree 27df2ff7908ea7ea2943a5f3445e12dbc24d97c9 (from ecbe73b940b2d642115de4b73c2f757eb46ff956)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 15:55:10 2006 -0800

    Report pipe status (and status mismatches) in i830DescribeOutputConfiguration()

diff --git a/src/i830_display.c b/src/i830_display.c
index e3db8ad..e36b5ef 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -796,12 +796,32 @@ i830DescribeOutputConfiguration(ScrnInfo
 
     for (i = 0; i < pI830->availablePipes; i++) {
 	CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
+	CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i);
+	Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
+	Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "  Pipe %c is %s\n",
+		   'A' + i, pI830->pipes[i].planeEnabled ? "on" : "off");
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "  Display plane %c is now %s and connected to pipe %c.\n",
 		   'A' + i,
 		   pI830->pipes[i].planeEnabled ? "enabled" : "disabled",
 		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
+	if (hw_pipe_enable != pI830->pipes[i].planeEnabled) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "  Hardware claims pipe %c is %s while software "
+		       "believes it is %s\n",
+		       'A' + i, hw_pipe_enable ? "on" : "off",
+		       pI830->pipes[i].planeEnabled ? "on" : "off");
+	}
+	if (hw_plane_enable != pI830->pipes[i].planeEnabled) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "  Hardware claims plane %c is %s while software "
+		       "believes it is %s\n",
+		       'A' + i, hw_plane_enable ? "on" : "off",
+		       pI830->pipes[i].planeEnabled ? "on" : "off");
+	}
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
diff-tree ecbe73b940b2d642115de4b73c2f757eb46ff956 (from parents)
Merge: 561af007974b8cdad1eea907fb73ed9d430c21ac 9681602177124e84a817a1e1d428f1779f2a45c9
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 15:59:59 2006 -0800

    Merge branch 'modesetting-origin' into modesetting
    
    Conflicts:
    
    	src/i830_display.c

diff --cc src/i830_display.c
index 6107c47,1175cf1..e3db8ad
@@@ -356,18 -357,14 +357,19 @@@
  }
  
  /**
 - * Sets the given video mode on the given pipe.  Assumes that plane A feeds
 - * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
 + * Sets the given video mode on the given pipe.
 + *
 + * Plane A is always output to pipe A, and plane B to pipe B.  The plane
 + * will not be enabled if plane_enable is FALSE, which is used for
 + * load detection, when something else will be output to the pipe other than
 + * display data.
   */
  Bool
 -i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
 +i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
 +		Bool plane_enable)
  {
      I830Ptr pI830 = I830PTR(pScrn);
+     I830PipePtr pI830Pipe = &pI830->pipes[pipe];
      int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
      CARD32 dpll = 0, fp = 0, temp;
      CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
@@@ -628,12 -635,10 +640,12 @@@
      temp = INREG(pipeconf_reg);
      OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
  
 -    /* And then turn the plane on */
 -    OUTREG(dspcntr_reg, dspcntr);
 +    if (plane_enable) {
 +	/* And then turn the plane on */
 +	OUTREG(dspcntr_reg, dspcntr);
 +    }
  
-     pI830->pipeCurMode[pipe] = *pMode;
+     pI830Pipe->curMode = *pMode;
  
      return TRUE;
  }
@@@ -729,31 -720,17 +727,18 @@@
      didLock = I830DRILock(pScrn);
  #endif
  
-     if (pI830->operatingDevices & 0xff) {
- 	pI830->planeEnabled[0] = 1;
-     } else {
- 	pI830->planeEnabled[0] = 0;
-     }
- 
-     if (pI830->operatingDevices & 0xff00) {
- 	pI830->planeEnabled[1] = 1;
-     } else {
- 	pI830->planeEnabled[1] = 0;
-     }
+     pI830->pipes[0].planeEnabled = (pI830->operatingDevices & 0xff) != 0;
+     pI830->pipes[1].planeEnabled = (pI830->operatingDevices & 0xff00) != 0;
  
-     for (i = 0; i < pI830->num_outputs; i++) {
+     for (i = 0; i < pI830->num_outputs; i++)
  	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
-     }
  
-     if (pI830->planeEnabled[0]) {
- 	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode),
- 			     0, TRUE);
- 	if (!ok)
- 	    goto done;
-     }
-     if (pI830->planeEnabled[1]) {
- 	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode),
- 			     1, TRUE);
+     for (i = 0; i < MAX_DISPLAY_PIPES; i++)
+     {
+ 	if (pI830->pipes[i].planeEnabled)
 -	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i, pMode),
 -				 i);
++	    ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, i,
++								pMode),
++				 i, TRUE);
  	if (!ok)
  	    goto done;
      }
diff --cc src/i830_randr.c
index 5b02a53,67641d6..8b6ad49
@@@ -560,10 -562,10 +562,10 @@@
  
      if (display_mode != randrp->modes[pipe])
      {
- 	pI830->planeEnabled[pipe] = mode != NULL;
+ 	pI830Pipe->planeEnabled = mode != NULL;
  	if (display_mode)
  	{
 -	    if (!i830PipeSetMode (pScrn, display_mode, pipe))
 +	    if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE))
  		return FALSE;
  	    /* XXX need I830SDVOPostSetMode here */
  	}
diff-tree 561af007974b8cdad1eea907fb73ed9d430c21ac (from e416b426d83de031441ada7a77b6bd66cec8b5c9)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 15:26:14 2006 -0800

    Add support for load-based CRT detection.

diff --git a/src/i830.h b/src/i830.h
index a07ba8e..4ce1a55 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -205,6 +205,11 @@ struct _I830OutputRec {
    int type;
    int pipe;
    Bool disabled;
+   /**
+    * Marks that the output and associated pipe is temporarily enabled for
+    * load detection.
+    */
+   Bool load_detect_temp;
 
    /**
     * Turns the output on/off, or sets intermediate power levels if available.
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 0225727..4c704b2 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -32,6 +32,7 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_xf86Modes.h"
+#include "i830_display.h"
 
 static void
 i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
@@ -166,7 +167,7 @@ i830_crt_detect_hotplug(ScrnInfoPtr pScr
  * \return FALSE if CRT is disconnected.
  */
 static Bool
-i830_crt_detect_load(ScrnInfoPtr pScrn)
+i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 adpa, pipeconf;
@@ -174,7 +175,7 @@ i830_crt_detect_load(ScrnInfoPtr pScrn)
     int pipeconf_reg, bclrpat_reg, dpll_reg;
     int pipe;
 
-    pipe = pI830->pipe;
+    pipe = output->pipe;
     if (pipe == 0) {
 	bclrpat_reg = BCLRPAT_A;
 	pipeconf_reg = PIPEACONF;
@@ -263,15 +264,12 @@ i830_crt_detect(ScrnInfoPtr pScrn, I830O
     if (i830_crt_detect_ddc(pScrn))
 	return OUTPUT_STATUS_CONNECTED;
 
-    /* Use the load-detect method if we're not currently outputting to the CRT,
-     * or we don't care.
-     *
-     * Actually, the method is unreliable currently.  We need to not share a
-     * pipe, as it seems having other outputs on that pipe will result in a
-     * false positive.
-     */
-    if (0) {
-	if (i830_crt_detect_load(pScrn))
+    /* Use the load-detect method if we have no other way of telling. */
+    if (i830GetLoadDetectPipe(pScrn, output) != -1) {
+	Bool connected = i830_crt_detect_load(pScrn, output);
+
+	i830ReleaseLoadDetectPipe(pScrn, output);
+	if (connected)
 	    return OUTPUT_STATUS_CONNECTED;
 	else
 	    return OUTPUT_STATUS_DISCONNECTED;
diff --git a/src/i830_display.c b/src/i830_display.c
index b3019f8..6107c47 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -356,11 +356,16 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
 }
 
 /**
- * Sets the given video mode on the given pipe.  Assumes that plane A feeds
- * pipe A, and plane B feeds pipe B.  Should not affect the other planes/pipes.
+ * Sets the given video mode on the given pipe.
+ *
+ * Plane A is always output to pipe A, and plane B to pipe B.  The plane
+ * will not be enabled if plane_enable is FALSE, which is used for
+ * load detection, when something else will be output to the pipe other than
+ * display data.
  */
 Bool
-i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
+i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
+		Bool plane_enable)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
@@ -623,8 +628,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     temp = INREG(pipeconf_reg);
     OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
 
-    /* And then turn the plane on */
-    OUTREG(dspcntr_reg, dspcntr);
+    if (plane_enable) {
+	/* And then turn the plane on */
+	OUTREG(dspcntr_reg, dspcntr);
+    }
 
     pI830->pipeCurMode[pipe] = *pMode;
 
@@ -740,13 +747,13 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     if (pI830->planeEnabled[0]) {
 	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 0, pMode),
-			     0);
+			     0, TRUE);
 	if (!ok)
 	    goto done;
     }
     if (pI830->planeEnabled[1]) {
 	ok = i830PipeSetMode(pScrn, i830PipeFindClosestMode(pScrn, 1, pMode),
-			     1);
+			     1, TRUE);
 	if (!ok)
 	    goto done;
     }
@@ -842,3 +849,99 @@ i830DescribeOutputConfiguration(ScrnInfo
 		   pI830->output[i].pipe == 0 ? 'A' : 'B');
     }
 }
+
+/**
+ * Get a pipe with a simple mode set on it for doing load-based monitor
+ * detection.
+ *
+ * It will be up to the load-detect code to adjust the pipe as appropriate for
+ * its requirements.  The pipe will be connected to no other outputs.
+ *
+ * Currently this code will only succeed if there is a pipe with no outputs
+ * configured for it.  In the future, it could choose to temporarily disable
+ * some outputs to free up a pipe for its use.
+ *
+ * \return monitor number, or -1 if no pipes are available.
+ */
+int
+i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    Bool pipe_available[MAX_DISPLAY_PIPES];
+    int i;
+    /* VESA 640x480x72Hz mode to set on the pipe */
+    DisplayModeRec mode = {
+	NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
+	31500,
+	640, 664, 704, 832, 0,
+	480, 489, 491, 520, 0,
+	V_NHSYNC | V_NVSYNC,
+	0, 0,
+	0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0,
+	FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
+    };
+
+    /* If the output is not marked disabled, check if it's already assigned
+     * to an active pipe, and is alone on that pipe.  If so, we're done.
+     */
+    if (!output->disabled) {
+	int pipeconf_reg = (output->pipe == 0) ? PIPEACONF : PIPEBCONF;
+
+	if (INREG(pipeconf_reg) & PIPEACONF_ENABLE) {
+	    /* Actually, maybe we don't need to be all alone on the pipe.
+	     * The worst that should happen is false positives.  Need to test,
+	     * but actually fixing this during server startup is messy.
+	     */
+#if 0
+	    for (i = 0; i < pI830->num_outputs; i++) {
+		if (&pI830->output[i] != output &&
+		    pI830->output[i].pipe == output->pipe)
+		{
+		    return -1;
+		}
+	    }
+#endif
+	    return output->pipe;
+	}
+    }
+
+    for (i = 0; i < pI830->availablePipes; i++) {
+	pipe_available[i] = TRUE;
+    }
+
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (!pI830->output[i].disabled)
+	{
+	    pipe_available[pI830->output[i].pipe] = FALSE;
+	}
+    }
+
+    for (i = 0; i < pI830->availablePipes; i++) {
+	if (pipe_available[i])
+	    break;
+    }
+
+    if (i == pI830->availablePipes) {
+	return -1;
+    }
+    output->load_detect_temp = TRUE;
+    output->pipe = i;
+    output->disabled = FALSE;
+
+    I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
+
+    i830PipeSetMode(pScrn, &mode, i, FALSE);
+
+    return i;
+}
+
+void
+i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    if (output->load_detect_temp) {
+	output->disabled = TRUE;
+	i830DisableUnusedFunctions(pScrn);
+	output->load_detect_temp = FALSE;
+    }
+}
diff --git a/src/i830_display.h b/src/i830_display.h
index 8a6e9e9..5c0f133 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -26,9 +26,12 @@
  */
 
 /* i830_display.c */
-Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe);
+Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
+		     Bool plane_enable);
 void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
 void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
+int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
+void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
diff --git a/src/i830_randr.c b/src/i830_randr.c
index e4ae9d0..5b02a53 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -563,7 +563,7 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 	pI830->planeEnabled[pipe] = mode != NULL;
 	if (display_mode)
 	{
-	    if (!i830PipeSetMode (pScrn, display_mode, pipe))
+	    if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE))
 		return FALSE;
 	    /* XXX need I830SDVOPostSetMode here */
 	}
diff-tree e416b426d83de031441ada7a77b6bd66cec8b5c9 (from 282a9e073ea985cbf0d0f3f296d593af1426bad5)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 15:25:41 2006 -0800

    Print out modelines as info, not error (which had been used for debugging).

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 166f41a..ca92e4d 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -317,7 +317,7 @@ PrintModeline(int scrnIndex,DisplayModeP
 #if 0
     if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
 #endif
-    xf86DrvMsg(scrnIndex, X_ERROR,
+    xf86DrvMsg(scrnIndex, X_INFO,
 		   "Modeline \"%s\"x%.01f  %6.2f  %i %i %i %i  %i %i %i %i%s "
 		   "(%.01f kHz)\n",
 		   mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
diff-tree 282a9e073ea985cbf0d0f3f296d593af1426bad5 (from 0510671a6c5233468ac20f0ec8096e084df03ce6)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 13:46:09 2006 -0800

    Don't memset the modes pointer on init, which was dereferencing NULL.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 59ebcc0..e4ae9d0 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -874,7 +874,6 @@ I830RandRInit12 (ScreenPtr pScreen)
     rp->rrCrtcSet = I830RandRCrtcSet;
     rp->rrCrtcSetGamma = I830RandRCrtcSetGamma;
     rp->rrSetConfig = NULL;
-    memset (rp->modes, '\0', sizeof (rp->modes));
     pScrn->PointerMoved = I830RandRPointerMoved;
     return TRUE;
 }
diff-tree 0510671a6c5233468ac20f0ec8096e084df03ce6 (from ffbd6ca09bc2300bf967d7c248a559d85b8706e0)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 10:58:23 2006 -0800

    Fix a pasteo in I965 register restore.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3612af7..d996bcd 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2404,8 +2404,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    }
 
    if (IS_I965G(pI830)) {
-      OUTREG(DSPASURF, pI830->saveDSPABASE);
-      OUTREG(DSPBSURF, pI830->saveDSPBBASE);
+      OUTREG(DSPASURF, pI830->saveDSPASURF);
+      OUTREG(DSPBSURF, pI830->saveDSPBSURF);
    }
 
    OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0);



More information about the xorg-commit mailing list