xf86-video-intel: Branch 'modesetting' - 2 commits - src/i830_display.c src/i830_driver.c src/i830_lvds.c src/i830_sdvo.c src/i830_xf86Crtc.c

Keith Packard keithp at kemper.freedesktop.org
Fri Dec 15 02:53:47 EET 2006


 src/i830_display.c  |   91 +++++++++++++++++++++++++++++++++++-----------------
 src/i830_driver.c   |   14 ++++++--
 src/i830_lvds.c     |    2 +
 src/i830_sdvo.c     |   13 +++++--
 src/i830_xf86Crtc.c |   78 +++++++++++++++++++++++++++-----------------
 5 files changed, 133 insertions(+), 65 deletions(-)

New commits:
diff-tree 082519f34b468d0c5aa08db74ff2b51cf411d743 (from 55e7a32096a58f7bb2380b04df6b3dd9dc8e5b6a)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Thu Dec 14 16:51:48 2006 -0800

    Turn pll/pipe/plane on in crtc_set_mode
    
    Instead of delaying pll/pipe/plane enables to the dpms function, turn them
    on right away in the crtc_set_mode function. To avoid rewriting these
    registers in the subsequent dpms function, check each register written there
    to see if the enable bit is already on and don't rewrite.

diff --git a/src/i830_display.c b/src/i830_display.c
index 4a429fc..897a4ee 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -506,22 +506,25 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
     case DPMSModeSuspend:
 	/* Enable the DPLL */
 	temp = INREG(dpll_reg);
-	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
-	(void)INREG(dpll_reg); /* write posting */
+	if ((temp & DPLL_VCO_ENABLE) == 0)
+	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
 
 	/* Wait for the clocks to stabilize. */
 	usleep(150);
 
 	/* Enable the pipe */
 	temp = INREG(pipeconf_reg);
-	OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
+	if ((temp & PIPEACONF_ENABLE) == 0)
+	    OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
 
 	/* Enable the plane */
 	temp = INREG(dspcntr_reg);
-	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
-
-	/* Flush the plane changes */
-	OUTREG(dspbase_reg, INREG(dspbase_reg));
+	if ((temp & DISPLAY_PLANE_ENABLE) == 0)
+	{
+	    OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+	    /* Flush the plane changes */
+	    OUTREG(dspbase_reg, INREG(dspbase_reg));
+	}
 
 	/* Give the overlay scaler a chance to enable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, TRUE);
@@ -530,16 +533,17 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, FALSE);
 
-	/* Disable display plane */
-	temp = INREG(dspcntr_reg);
-	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
-
 	/* Disable the VGA plane that we never use */
 	OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 
-	/* Flush the plane changes */
-	OUTREG(dspbase_reg, INREG(dspbase_reg));
-	(void)INREG(dspbase_reg); /* write posting */
+	/* 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));
+	}
 
 	if (!IS_I9XX(pI830)) {
 	    /* Wait for vblank for the disable to take effect */
@@ -548,15 +552,15 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 
 	/* Next, disable display pipes */
 	temp = INREG(pipeconf_reg);
-	OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-	(void)INREG(pipeconf_reg); /* write posting */
+	if ((temp & PIPEACONF_ENABLE) != 0)
+	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
 
 	/* Wait for vblank for the disable to take effect. */
 	i830WaitForVblank(pScrn);
 
 	temp = INREG(dpll_reg);
-	OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-	(void)INREG(dpll_reg); /* write posting */
+	if ((temp & DPLL_VCO_ENABLE) != 0)
+	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
 
 	/* Wait for the clocks to turn off. */
 	usleep(150);
@@ -592,6 +596,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
     int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+    int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
     int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
     int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
     int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
@@ -753,13 +758,44 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
 	else
 	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
     }
+    dspcntr |= DISPLAY_PLANE_ENABLE;
+    pipeconf |= PIPEACONF_ENABLE;
+    dpll |= DPLL_VCO_ENABLE;
+
+    if (is_lvds)
+    {
+	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
+	 * This is an exception to the general rule that mode_set doesn't turn
+	 * things on.
+	 */
+	OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
+    }
+    
+    /* Disable the panel fitter if it was on our pipe */
+    if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
+	OUTREG(PFIT_CONTROL, 0);
 
     i830PrintPll("chosen", &clock);
     ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp);
 
+    if (IS_I965G(pI830)) {
+	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+    }
+
+    if (dpll & DPLL_VCO_ENABLE)
+    {
+	OUTREG(fp_reg, fp);
+	OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
+	usleep(150);
+    }
     OUTREG(fp_reg, fp);
     OUTREG(dpll_reg, dpll);
+    /* Wait for the clocks to stabilize. */
+    usleep(150);
 
+#if 0
     /* Magic re-write of the register for the Mac Mini.  Without this, the
      * first X invocation after a cold boot will stick in 4x pixel multiply
      * mode.  Alternatives that don't work include sleeping and doing an
@@ -767,12 +803,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
      * write above.
      */
     OUTREG(dpll_reg, dpll);
-
-    if (IS_I965G(pI830)) {
-	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
-	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
-	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
-    }
+#endif
 
     OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
 	((adjusted_mode->CrtcHTotal - 1) << 16));
@@ -792,14 +823,16 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
      */
     OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
     OUTREG(dsppos_reg, 0);
-    i830PipeSetBase(crtc, crtc->x, crtc->y);
     OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
+    i830PipeSetBase(crtc, crtc->x, crtc->y);
     OUTREG(pipeconf_reg, pipeconf);
+    i830WaitForVblank(pScrn);
+    
     OUTREG(dspcntr_reg, dspcntr);
-
-    /* Disable the panel fitter if it was on our pipe */
-    if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe)
-	OUTREG(PFIT_CONTROL, 0);
+    /* Flush the plane changes */
+    OUTREG(dspbase_reg, INREG(dspbase_reg));
+    
+    i830WaitForVblank(pScrn);
 }
 
 /**
diff --git a/src/i830_driver.c b/src/i830_driver.c
index a210b63..97f5285 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2225,15 +2225,25 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    OUTREG(FPA0, pI830->saveFPA0);
    OUTREG(FPA1, pI830->saveFPA1);
-   OUTREG(DPLL_A, pI830->saveDPLL_A);
    if (IS_I965G(pI830))
       OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
+   if (pI830->saveDPLL_A & DPLL_VCO_ENABLE)
+   {
+      OUTREG(DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE);
+      usleep(150);
+   }
+   OUTREG(DPLL_A, pI830->saveDPLL_A);
    if(xf86_config->num_crtc == 2) {
       OUTREG(FPB0, pI830->saveFPB0);
       OUTREG(FPB1, pI830->saveFPB1);
-      OUTREG(DPLL_B, pI830->saveDPLL_B);
       if (IS_I965G(pI830))
 	 OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
+      if (pI830->saveDPLL_B & DPLL_VCO_ENABLE)
+      {
+	 OUTREG(DPLL_A, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE);
+	 usleep(150);
+      }
+      OUTREG(DPLL_B, pI830->saveDPLL_B);
    }
    /* Wait for clocks to stabilize */
    usleep(150);
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 4307025..b682b27 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -196,11 +196,13 @@ i830_lvds_mode_set(xf86OutputPtr output,
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 pfit_control;
 
+#if 0
     /* The LVDS pin pair needs to be on before the DPLLs are enabled.
      * This is an exception to the general rule that mode_set doesn't turn
      * things on.
      */
     OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT);
+#endif
 
     /* Enable automatic panel scaling so that non-native modes fill the
      * screen.  Should be enabled before the pipe is enabled, according to
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index fc17efd..d19b8b0 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -679,26 +679,31 @@ i830_sdvo_dpms(xf86OutputPtr output, int
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     I830Ptr pI830 = I830PTR(pScrn);
+    CARD32  temp;
 
     if (mode != DPMSModeOn) {
 	i830_sdvo_set_active_outputs(output, 0);
-	OUTREG(dev_priv->output_device,
-	       INREG(dev_priv->output_device) & ~SDVO_ENABLE);
+	temp = INREG(dev_priv->output_device);
+	if ((temp & SDVO_ENABLE) != 0)
+	    OUTREG(dev_priv->output_device, temp & ~SDVO_ENABLE);
     } else {
 	Bool input1, input2;
 	int i;
 	CARD8 status;
 
-	OUTREG(dev_priv->output_device,
-	       INREG(dev_priv->output_device) | SDVO_ENABLE);
+	temp = INREG(dev_priv->output_device);
+	if ((temp & SDVO_ENABLE) == 0)
+	    OUTREG(dev_priv->output_device, temp | SDVO_ENABLE);
 
 	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
 
+#if 0
 	/* Do it again!  If we remove this below register write, or the exact
 	 * same one 2 lines up, the mac mini SDVO output doesn't turn on.
 	 */
 	OUTREG(dev_priv->output_device,
 	       INREG(dev_priv->output_device) | SDVO_ENABLE);
+#endif
 
 	for (i = 0; i < 2; i++)
 	    i830WaitForVblank(pScrn);
diff-tree 55e7a32096a58f7bb2380b04df6b3dd9dc8e5b6a (from d4142abc68888178a8f6c54fdcece91e898bc9f5)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Thu Dec 14 16:50:26 2006 -0800

    Respect Virtual in xorg.conf
    
    Instead of growing virtual to fit our desired sizes, if it is set in the
    config file, use the value as the virtual size and make the default
    configuration fit within that size (if possible).

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 6b73264..76d6d03 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -196,7 +196,7 @@ xf86OutputDestroy (xf86OutputPtr output)
 }
 
 static DisplayModePtr
-xf86DefaultMode (xf86OutputPtr output)
+xf86DefaultMode (xf86OutputPtr output, int width, int height)
 {
     DisplayModePtr  target_mode = NULL;
     DisplayModePtr  mode;
@@ -216,6 +216,7 @@ xf86DefaultMode (xf86OutputPtr output)
 	int	    preferred = (mode->type & M_T_PREFERRED) != 0;
 	int	    diff;
 
+	if (mode->HDisplay > width || mode->VDisplay > height) continue;
 	dpi = (mode->HDisplay * 254) / (mm_height * 10);
 	diff = dpi - 96;
 	diff = diff < 0 ? -diff : diff;
@@ -231,7 +232,8 @@ xf86DefaultMode (xf86OutputPtr output)
 }
 
 static DisplayModePtr
-xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match)
+xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match,
+		 int width, int height)
 {
     DisplayModePtr  target_mode = NULL;
     DisplayModePtr  mode;
@@ -245,6 +247,8 @@ xf86ClosestMode (xf86OutputPtr output, D
 	int	    dx, dy;
 	int	    diff;
 
+	if (mode->HDisplay > width || mode->VDisplay > height) continue;
+	
 	/* exact matches are preferred */
 	if (xf86ModesEqual (mode, match))
 	    return mode;
@@ -262,13 +266,16 @@ xf86ClosestMode (xf86OutputPtr output, D
 }
 
 static Bool
-xf86OutputHasPreferredMode (xf86OutputPtr output)
+xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
 {
     DisplayModePtr  mode;
 
     for (mode = output->probed_modes; mode; mode = mode->next)
+    {
+	if (mode->HDisplay > width || mode->VDisplay > height) continue;
 	if (mode->type & M_T_PREFERRED)
 	    return TRUE;
+    }
     return FALSE;
 }
 
@@ -276,7 +283,9 @@ static int
 xf86PickCrtcs (ScrnInfoPtr	pScrn,
 	       xf86CrtcPtr	*best_crtcs,
 	       DisplayModePtr	*modes,
-	       int		n)
+	       int		n,
+	       int		width,
+	       int		height)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
     int		    c, o, l;
@@ -297,7 +306,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
      */
     best_crtcs[n] = NULL;
     best_crtc = NULL;
-    best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1);
+    best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1, width, height);
     if (modes[n] == NULL)
 	return best_score;
     
@@ -310,7 +319,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
     if (output->status == XF86OutputStatusConnected)
 	my_score++;
     /* Score outputs with preferred modes higher */
-    if (xf86OutputHasPreferredMode (output))
+    if (xf86OutputHasPreferredMode (output, width, height))
 	my_score++;
     /*
      * Select a crtc for this output and
@@ -349,7 +358,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
 	}
 	crtcs[n] = crtc;
 	memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
-	score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1);
+	score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1, width, height);
 	if (score >= best_score)
 	{
 	    best_crtc = crtc;
@@ -378,7 +387,7 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
 
     for (c = 0; c < config->num_crtc; c++)
     {
-	int	    crtc_width = 1600, crtc_height = 1200;
+	int	    crtc_width = 0, crtc_height = 0;
 
 	for (o = 0; o < config->num_output; o++) 
 	{
@@ -392,16 +401,19 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
 		    {
 			if (mode->HDisplay > crtc_width)
 			    crtc_width = mode->HDisplay;
-			if (mode->VDisplay > crtc_width)
+			if (mode->VDisplay > crtc_height)
 			    crtc_height = mode->VDisplay;
 		    }
 		}
 	}
-	if (crtc_width > width)
-	    width = crtc_width;
+	width += crtc_width;
 	if (crtc_height > height)
 	    height = crtc_height;
     }
+    if (config->maxWidth && width > config->maxWidth) width = config->maxWidth;
+    if (config->maxHeight && height > config->maxHeight) height = config->maxHeight;
+    if (config->minWidth && width < config->minWidth) width = config->minWidth;
+    if (config->minHeight && height < config->minHeight) height = config->minHeight;
     *widthp = width;
     *heightp = height;
 }
@@ -575,6 +587,26 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 
     xf86ProbeOutputModes (pScrn);
 
+    if (pScrn->display->virtualX == 0)
+    {
+	/*
+	 * Expand virtual size to cover potential mode switches
+	 */
+	xf86DefaultScreenLimits (pScrn, &width, &height);
+    
+	pScrn->display->virtualX = width;
+	pScrn->display->virtualY = height;
+    }
+    else
+    {
+	width = pScrn->display->virtualX;
+	height = pScrn->display->virtualY;
+    }
+    if (width > pScrn->virtualX)
+	pScrn->virtualX = width;
+    if (height > pScrn->virtualY)
+	pScrn->virtualY = height;
+    
     crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
     modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
     
@@ -589,9 +621,9 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	xf86OutputPtr output = config->output[o];
 
 	if (output->status != XF86OutputStatusDisconnected &&
-	    xf86OutputHasPreferredMode (output))
+	    xf86OutputHasPreferredMode (output, width, height))
 	{
-	    target_mode = xf86DefaultMode (output);
+	    target_mode = xf86DefaultMode (output, width, height);
 	    if (target_mode)
 	    {
 		modes[o] = target_mode;
@@ -607,7 +639,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	    xf86OutputPtr output = config->output[o];
 	    if (output->status != XF86OutputStatusDisconnected)
 	    {
-		target_mode = xf86DefaultMode (output);
+		target_mode = xf86DefaultMode (output, width, height);
 		if (target_mode)
 		{
 		    modes[o] = target_mode;
@@ -622,30 +654,16 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	xf86OutputPtr output = config->output[o];
 	
 	if (output->status != XF86OutputStatusDisconnected && !modes[o])
-	    modes[o] = xf86ClosestMode (output, target_mode);
+	    modes[o] = xf86ClosestMode (output, target_mode, width, height);
     }
 
-    if (!xf86PickCrtcs (pScrn, crtcs, modes, 0))
+    if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height))
     {
 	xfree (crtcs);
 	xfree (modes);
 	return FALSE;
     }
     
-    xf86DefaultScreenLimits (pScrn, &width, &height);
-    
-    /*
-     * Expand virtual size to cover potential mode switches
-     */
-    if (width > pScrn->virtualX)
-	pScrn->virtualX = width;
-    if (width > pScrn->display->virtualX)
-	pScrn->display->virtualX = width;
-    if (height > pScrn->virtualY)
-	pScrn->virtualY = height;
-    if (height > pScrn->display->virtualY)
-	pScrn->display->virtualY = height;
-    
     /* XXX override xf86 common frame computation code */
     
     pScrn->display->frameX0 = 0;



More information about the xorg-commit mailing list